Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/DerivedMesh.c')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c3964
1 files changed, 2024 insertions, 1940 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 02afdfe035b..2c22f744125 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -21,7 +21,6 @@
* \ingroup bke
*/
-
#include <string.h>
#include <limits.h>
@@ -81,7 +80,8 @@
#ifdef USE_MODIFIER_VALIDATE
# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true)))
-# define ASSERT_IS_VALID_MESH(mesh) (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true)))
+# define ASSERT_IS_VALID_MESH(mesh) \
+ (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true)))
#else
# define ASSERT_IS_VALID_DM(dm)
# define ASSERT_IS_VALID_MESH(mesh)
@@ -90,197 +90,191 @@
static CLG_LogRef LOG = {"bke.derivedmesh"};
static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
-
static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
static void mesh_init_origspace(Mesh *mesh);
-
/* -------------------------------------------------------------------- */
static MVert *dm_getVertArray(DerivedMesh *dm)
{
- MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
+ MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
- if (!mvert) {
- mvert = CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL,
- dm->getNumVerts(dm));
- CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY);
- dm->copyVertArray(dm, mvert);
- }
+ if (!mvert) {
+ mvert = CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, dm->getNumVerts(dm));
+ CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY);
+ dm->copyVertArray(dm, mvert);
+ }
- return mvert;
+ return mvert;
}
static MEdge *dm_getEdgeArray(DerivedMesh *dm)
{
- MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
+ MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
- if (!medge) {
- medge = CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL,
- dm->getNumEdges(dm));
- CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
- dm->copyEdgeArray(dm, medge);
- }
+ if (!medge) {
+ medge = CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, dm->getNumEdges(dm));
+ CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
+ dm->copyEdgeArray(dm, medge);
+ }
- return medge;
+ return medge;
}
static MFace *dm_getTessFaceArray(DerivedMesh *dm)
{
- MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
- if (!mface) {
- int numTessFaces = dm->getNumTessFaces(dm);
+ if (!mface) {
+ int numTessFaces = dm->getNumTessFaces(dm);
- if (!numTessFaces) {
- /* Do not add layer if there's no elements in it, this leads to issues later when
- * this layer is needed with non-zero size, but currently CD stuff does not check
- * for requested layer size on creation and just returns layer which was previously
- * added (sergey) */
- return NULL;
- }
+ if (!numTessFaces) {
+ /* Do not add layer if there's no elements in it, this leads to issues later when
+ * this layer is needed with non-zero size, but currently CD stuff does not check
+ * for requested layer size on creation and just returns layer which was previously
+ * added (sergey) */
+ return NULL;
+ }
- mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces);
- CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
- dm->copyTessFaceArray(dm, mface);
- }
+ mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces);
+ CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
+ dm->copyTessFaceArray(dm, mface);
+ }
- return mface;
+ return mface;
}
static MLoop *dm_getLoopArray(DerivedMesh *dm)
{
- MLoop *mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ MLoop *mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
- if (!mloop) {
- mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL,
- dm->getNumLoops(dm));
- CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
- dm->copyLoopArray(dm, mloop);
- }
+ if (!mloop) {
+ mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, dm->getNumLoops(dm));
+ CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
+ dm->copyLoopArray(dm, mloop);
+ }
- return mloop;
+ return mloop;
}
static MPoly *dm_getPolyArray(DerivedMesh *dm)
{
- MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+ MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
- if (!mpoly) {
- mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL,
- dm->getNumPolys(dm));
- CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
- dm->copyPolyArray(dm, mpoly);
- }
+ if (!mpoly) {
+ mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, dm->getNumPolys(dm));
+ CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
+ dm->copyPolyArray(dm, mpoly);
+ }
- return mpoly;
+ return mpoly;
}
static MVert *dm_dupVertArray(DerivedMesh *dm)
{
- MVert *tmp = MEM_malloc_arrayN(dm->getNumVerts(dm), sizeof(*tmp),
- "dm_dupVertArray tmp");
+ MVert *tmp = MEM_malloc_arrayN(dm->getNumVerts(dm), sizeof(*tmp), "dm_dupVertArray tmp");
- if (tmp) dm->copyVertArray(dm, tmp);
+ if (tmp)
+ dm->copyVertArray(dm, tmp);
- return tmp;
+ return tmp;
}
static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
{
- MEdge *tmp = MEM_malloc_arrayN(dm->getNumEdges(dm), sizeof(*tmp),
- "dm_dupEdgeArray tmp");
+ MEdge *tmp = MEM_malloc_arrayN(dm->getNumEdges(dm), sizeof(*tmp), "dm_dupEdgeArray tmp");
- if (tmp) dm->copyEdgeArray(dm, tmp);
+ if (tmp)
+ dm->copyEdgeArray(dm, tmp);
- return tmp;
+ return tmp;
}
static MFace *dm_dupFaceArray(DerivedMesh *dm)
{
- MFace *tmp = MEM_malloc_arrayN(dm->getNumTessFaces(dm), sizeof(*tmp),
- "dm_dupFaceArray tmp");
+ MFace *tmp = MEM_malloc_arrayN(dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp");
- if (tmp) dm->copyTessFaceArray(dm, tmp);
+ if (tmp)
+ dm->copyTessFaceArray(dm, tmp);
- return tmp;
+ return tmp;
}
static MLoop *dm_dupLoopArray(DerivedMesh *dm)
{
- MLoop *tmp = MEM_malloc_arrayN(dm->getNumLoops(dm), sizeof(*tmp),
- "dm_dupLoopArray tmp");
+ MLoop *tmp = MEM_malloc_arrayN(dm->getNumLoops(dm), sizeof(*tmp), "dm_dupLoopArray tmp");
- if (tmp) dm->copyLoopArray(dm, tmp);
+ if (tmp)
+ dm->copyLoopArray(dm, tmp);
- return tmp;
+ return tmp;
}
static MPoly *dm_dupPolyArray(DerivedMesh *dm)
{
- MPoly *tmp = MEM_malloc_arrayN(dm->getNumPolys(dm), sizeof(*tmp),
- "dm_dupPolyArray tmp");
+ MPoly *tmp = MEM_malloc_arrayN(dm->getNumPolys(dm), sizeof(*tmp), "dm_dupPolyArray tmp");
- if (tmp) dm->copyPolyArray(dm, tmp);
+ if (tmp)
+ dm->copyPolyArray(dm, tmp);
- return tmp;
+ return tmp;
}
static int dm_getNumLoopTri(DerivedMesh *dm)
{
- const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm));
- BLI_assert(ELEM(dm->looptris.num, 0, numlooptris));
- return numlooptris;
+ const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm));
+ BLI_assert(ELEM(dm->looptris.num, 0, numlooptris));
+ return numlooptris;
}
static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
{
- MLoopTri *looptri;
+ MLoopTri *looptri;
- BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ);
- looptri = dm->looptris.array;
- BLI_rw_mutex_unlock(&loops_cache_lock);
+ BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ);
+ looptri = dm->looptris.array;
+ BLI_rw_mutex_unlock(&loops_cache_lock);
- if (looptri != NULL) {
- BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num);
- }
- else {
- BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE);
- /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already
- * recomputed those looptris. */
- if (dm->looptris.array == NULL) {
- dm->recalcLoopTri(dm);
- }
- looptri = dm->looptris.array;
- BLI_rw_mutex_unlock(&loops_cache_lock);
- }
- return looptri;
+ if (looptri != NULL) {
+ BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num);
+ }
+ else {
+ BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE);
+ /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already
+ * recomputed those looptris. */
+ if (dm->looptris.array == NULL) {
+ dm->recalcLoopTri(dm);
+ }
+ looptri = dm->looptris.array;
+ BLI_rw_mutex_unlock(&loops_cache_lock);
+ }
+ return looptri;
}
static CustomData *dm_getVertCData(DerivedMesh *dm)
{
- return &dm->vertData;
+ return &dm->vertData;
}
static CustomData *dm_getEdgeCData(DerivedMesh *dm)
{
- return &dm->edgeData;
+ return &dm->edgeData;
}
static CustomData *dm_getTessFaceCData(DerivedMesh *dm)
{
- return &dm->faceData;
+ return &dm->faceData;
}
static CustomData *dm_getLoopCData(DerivedMesh *dm)
{
- return &dm->loopData;
+ return &dm->loopData;
}
static CustomData *dm_getPolyCData(DerivedMesh *dm)
{
- return &dm->polyData;
+ return &dm->polyData;
}
/**
@@ -289,40 +283,40 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
*/
void DM_init_funcs(DerivedMesh *dm)
{
- /* default function implementations */
- dm->getVertArray = dm_getVertArray;
- dm->getEdgeArray = dm_getEdgeArray;
- dm->getTessFaceArray = dm_getTessFaceArray;
- dm->getLoopArray = dm_getLoopArray;
- dm->getPolyArray = dm_getPolyArray;
- dm->dupVertArray = dm_dupVertArray;
- dm->dupEdgeArray = dm_dupEdgeArray;
- dm->dupTessFaceArray = dm_dupFaceArray;
- dm->dupLoopArray = dm_dupLoopArray;
- dm->dupPolyArray = dm_dupPolyArray;
-
- dm->getLoopTriArray = dm_getLoopTriArray;
-
- /* subtypes handle getting actual data */
- dm->getNumLoopTri = dm_getNumLoopTri;
-
- dm->getVertDataLayout = dm_getVertCData;
- dm->getEdgeDataLayout = dm_getEdgeCData;
- dm->getTessFaceDataLayout = dm_getTessFaceCData;
- dm->getLoopDataLayout = dm_getLoopCData;
- dm->getPolyDataLayout = dm_getPolyCData;
-
- dm->getVertData = DM_get_vert_data;
- dm->getEdgeData = DM_get_edge_data;
- dm->getTessFaceData = DM_get_tessface_data;
- dm->getPolyData = DM_get_poly_data;
- dm->getVertDataArray = DM_get_vert_data_layer;
- dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getTessFaceDataArray = DM_get_tessface_data_layer;
- dm->getPolyDataArray = DM_get_poly_data_layer;
- dm->getLoopDataArray = DM_get_loop_data_layer;
-
- dm->bvhCache = NULL;
+ /* default function implementations */
+ dm->getVertArray = dm_getVertArray;
+ dm->getEdgeArray = dm_getEdgeArray;
+ dm->getTessFaceArray = dm_getTessFaceArray;
+ dm->getLoopArray = dm_getLoopArray;
+ dm->getPolyArray = dm_getPolyArray;
+ dm->dupVertArray = dm_dupVertArray;
+ dm->dupEdgeArray = dm_dupEdgeArray;
+ dm->dupTessFaceArray = dm_dupFaceArray;
+ dm->dupLoopArray = dm_dupLoopArray;
+ dm->dupPolyArray = dm_dupPolyArray;
+
+ dm->getLoopTriArray = dm_getLoopTriArray;
+
+ /* subtypes handle getting actual data */
+ dm->getNumLoopTri = dm_getNumLoopTri;
+
+ dm->getVertDataLayout = dm_getVertCData;
+ dm->getEdgeDataLayout = dm_getEdgeCData;
+ dm->getTessFaceDataLayout = dm_getTessFaceCData;
+ dm->getLoopDataLayout = dm_getLoopCData;
+ dm->getPolyDataLayout = dm_getPolyCData;
+
+ dm->getVertData = DM_get_vert_data;
+ dm->getEdgeData = DM_get_edge_data;
+ dm->getTessFaceData = DM_get_tessface_data;
+ dm->getPolyData = DM_get_poly_data;
+ dm->getVertDataArray = DM_get_vert_data_layer;
+ dm->getEdgeDataArray = DM_get_edge_data_layer;
+ dm->getTessFaceDataArray = DM_get_tessface_data_layer;
+ dm->getPolyDataArray = DM_get_poly_data_layer;
+ dm->getLoopDataArray = DM_get_loop_data_layer;
+
+ dm->bvhCache = NULL;
}
/**
@@ -330,133 +324,157 @@ void DM_init_funcs(DerivedMesh *dm)
* of vertices, edges and faces (doesn't allocate memory for them, just
* sets up the custom data layers)
*/
-void DM_init(
- DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
- int numTessFaces, int numLoops, int numPolys)
-{
- dm->type = type;
- dm->numVertData = numVerts;
- dm->numEdgeData = numEdges;
- dm->numTessFaceData = numTessFaces;
- dm->numLoopData = numLoops;
- dm->numPolyData = numPolys;
-
- DM_init_funcs(dm);
-
- dm->needsFree = 1;
- dm->dirty = 0;
-
- /* don't use CustomData_reset(...); because we dont want to touch customdata */
- copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
- copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
- copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
- copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1);
- copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
+void DM_init(DerivedMesh *dm,
+ DerivedMeshType type,
+ int numVerts,
+ int numEdges,
+ int numTessFaces,
+ int numLoops,
+ int numPolys)
+{
+ dm->type = type;
+ dm->numVertData = numVerts;
+ dm->numEdgeData = numEdges;
+ dm->numTessFaceData = numTessFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPolys;
+
+ DM_init_funcs(dm);
+
+ dm->needsFree = 1;
+ dm->dirty = 0;
+
+ /* don't use CustomData_reset(...); because we dont want to touch customdata */
+ copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1);
+ copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
}
/**
* Utility function to initialize a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
-void DM_from_template_ex(
- DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
- int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys,
- const CustomData_MeshMasks *mask)
-{
- CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts);
- CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges);
- CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces);
- CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_CALLOC, numLoops);
- CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_CALLOC, numPolys);
-
- dm->cd_flag = source->cd_flag;
-
- dm->type = type;
- dm->numVertData = numVerts;
- dm->numEdgeData = numEdges;
- dm->numTessFaceData = numTessFaces;
- dm->numLoopData = numLoops;
- dm->numPolyData = numPolys;
-
- DM_init_funcs(dm);
-
- dm->needsFree = 1;
- dm->dirty = 0;
-}
-void DM_from_template(
- DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
- int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys)
-{
- DM_from_template_ex(
- dm, source, type,
- numVerts, numEdges, numTessFaces,
- numLoops, numPolys,
- &CD_MASK_DERIVEDMESH);
+void DM_from_template_ex(DerivedMesh *dm,
+ DerivedMesh *source,
+ DerivedMeshType type,
+ int numVerts,
+ int numEdges,
+ int numTessFaces,
+ int numLoops,
+ int numPolys,
+ const CustomData_MeshMasks *mask)
+{
+ CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts);
+ CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges);
+ CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces);
+ CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_CALLOC, numLoops);
+ CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_CALLOC, numPolys);
+
+ dm->cd_flag = source->cd_flag;
+
+ dm->type = type;
+ dm->numVertData = numVerts;
+ dm->numEdgeData = numEdges;
+ dm->numTessFaceData = numTessFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPolys;
+
+ DM_init_funcs(dm);
+
+ dm->needsFree = 1;
+ dm->dirty = 0;
+}
+void DM_from_template(DerivedMesh *dm,
+ DerivedMesh *source,
+ DerivedMeshType type,
+ int numVerts,
+ int numEdges,
+ int numTessFaces,
+ int numLoops,
+ int numPolys)
+{
+ DM_from_template_ex(dm,
+ source,
+ type,
+ numVerts,
+ numEdges,
+ numTessFaces,
+ numLoops,
+ numPolys,
+ &CD_MASK_DERIVEDMESH);
}
int DM_release(DerivedMesh *dm)
{
- if (dm->needsFree) {
- bvhcache_free(&dm->bvhCache);
- CustomData_free(&dm->vertData, dm->numVertData);
- CustomData_free(&dm->edgeData, dm->numEdgeData);
- CustomData_free(&dm->faceData, dm->numTessFaceData);
- CustomData_free(&dm->loopData, dm->numLoopData);
- CustomData_free(&dm->polyData, dm->numPolyData);
-
- if (dm->mat) {
- MEM_freeN(dm->mat);
- dm->mat = NULL;
- dm->totmat = 0;
- }
-
- MEM_SAFE_FREE(dm->looptris.array);
- dm->looptris.num = 0;
- dm->looptris.num_alloc = 0;
-
- return 1;
- }
- else {
- CustomData_free_temporary(&dm->vertData, dm->numVertData);
- CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
- CustomData_free_temporary(&dm->faceData, dm->numTessFaceData);
- CustomData_free_temporary(&dm->loopData, dm->numLoopData);
- CustomData_free_temporary(&dm->polyData, dm->numPolyData);
-
- return 0;
- }
+ if (dm->needsFree) {
+ bvhcache_free(&dm->bvhCache);
+ CustomData_free(&dm->vertData, dm->numVertData);
+ CustomData_free(&dm->edgeData, dm->numEdgeData);
+ CustomData_free(&dm->faceData, dm->numTessFaceData);
+ CustomData_free(&dm->loopData, dm->numLoopData);
+ CustomData_free(&dm->polyData, dm->numPolyData);
+
+ if (dm->mat) {
+ MEM_freeN(dm->mat);
+ dm->mat = NULL;
+ dm->totmat = 0;
+ }
+
+ MEM_SAFE_FREE(dm->looptris.array);
+ dm->looptris.num = 0;
+ dm->looptris.num_alloc = 0;
+
+ return 1;
+ }
+ else {
+ CustomData_free_temporary(&dm->vertData, dm->numVertData);
+ CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
+ CustomData_free_temporary(&dm->faceData, dm->numTessFaceData);
+ CustomData_free_temporary(&dm->loopData, dm->numLoopData);
+ CustomData_free_temporary(&dm->polyData, dm->numPolyData);
+
+ return 0;
+ }
}
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
{
- CustomData_free(&target->loopData, source->numLoopData);
- CustomData_free(&target->polyData, source->numPolyData);
+ CustomData_free(&target->loopData, source->numLoopData);
+ CustomData_free(&target->polyData, source->numPolyData);
- CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH.lmask, CD_DUPLICATE, source->numLoopData);
- CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH.pmask, CD_DUPLICATE, source->numPolyData);
+ CustomData_copy(&source->loopData,
+ &target->loopData,
+ CD_MASK_DERIVEDMESH.lmask,
+ CD_DUPLICATE,
+ source->numLoopData);
+ CustomData_copy(&source->polyData,
+ &target->polyData,
+ CD_MASK_DERIVEDMESH.pmask,
+ CD_DUPLICATE,
+ source->numPolyData);
- target->numLoopData = source->numLoopData;
- target->numPolyData = source->numPolyData;
+ target->numLoopData = source->numLoopData;
+ target->numPolyData = source->numPolyData;
- if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) {
- MPoly *mpoly;
- MLoop *mloop;
+ if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) {
+ MPoly *mpoly;
+ MLoop *mloop;
- mloop = source->dupLoopArray(source);
- mpoly = source->dupPolyArray(source);
- CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData);
- CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData);
- }
+ mloop = source->dupLoopArray(source);
+ mpoly = source->dupPolyArray(source);
+ CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData);
+ CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData);
+ }
}
void DM_ensure_normals(DerivedMesh *dm)
{
- if (dm->dirty & DM_DIRTY_NORMALS) {
- dm->calcNormals(dm);
- }
- BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
+ if (dm->dirty & DM_DIRTY_NORMALS) {
+ dm->calcNormals(dm);
+ }
+ BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
}
/**
@@ -466,175 +484,178 @@ void DM_ensure_normals(DerivedMesh *dm)
*/
void DM_ensure_looptri_data(DerivedMesh *dm)
{
- const unsigned int totpoly = dm->numPolyData;
- const unsigned int totloop = dm->numLoopData;
- const int looptris_num = poly_to_tri_count(totpoly, totloop);
-
- BLI_assert(dm->looptris.array_wip == NULL);
-
- SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip);
-
- if ((looptris_num > dm->looptris.num_alloc) ||
- (looptris_num < dm->looptris.num_alloc * 2) ||
- (totpoly == 0))
- {
- MEM_SAFE_FREE(dm->looptris.array_wip);
- dm->looptris.num_alloc = 0;
- dm->looptris.num = 0;
- }
-
- if (totpoly) {
- if (dm->looptris.array_wip == NULL) {
- dm->looptris.array_wip = MEM_malloc_arrayN(looptris_num, sizeof(*dm->looptris.array_wip), __func__);
- dm->looptris.num_alloc = looptris_num;
- }
-
- dm->looptris.num = looptris_num;
- }
-}
-
-void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership)
-{
- /* dm might depend on me, so we need to do everything with a local copy */
- Mesh tmp = *me;
- int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
- int did_shapekeys = 0;
- eCDAllocType alloctype = CD_DUPLICATE;
-
- if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) {
- bool has_any_referenced_layers =
- CustomData_has_referenced(&dm->vertData) ||
- CustomData_has_referenced(&dm->edgeData) ||
- CustomData_has_referenced(&dm->loopData) ||
- CustomData_has_referenced(&dm->faceData) ||
- CustomData_has_referenced(&dm->polyData);
- if (!has_any_referenced_layers) {
- alloctype = CD_ASSIGN;
- }
- }
-
- CustomData_reset(&tmp.vdata);
- CustomData_reset(&tmp.edata);
- CustomData_reset(&tmp.fdata);
- CustomData_reset(&tmp.ldata);
- CustomData_reset(&tmp.pdata);
-
- DM_ensure_normals(dm);
-
- totvert = tmp.totvert = dm->getNumVerts(dm);
- totedge = tmp.totedge = dm->getNumEdges(dm);
- totloop = tmp.totloop = dm->getNumLoops(dm);
- totpoly = tmp.totpoly = dm->getNumPolys(dm);
- tmp.totface = 0;
-
- CustomData_copy(&dm->vertData, &tmp.vdata, mask->vmask, alloctype, totvert);
- CustomData_copy(&dm->edgeData, &tmp.edata, mask->emask, alloctype, totedge);
- CustomData_copy(&dm->loopData, &tmp.ldata, mask->lmask, alloctype, totloop);
- CustomData_copy(&dm->polyData, &tmp.pdata, mask->pmask, alloctype, totpoly);
- tmp.cd_flag = dm->cd_flag;
- tmp.runtime.deformed_only = dm->deformedOnly;
-
- if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
- KeyBlock *kb;
- int uid;
-
- if (ob) {
- kb = BLI_findlink(&me->key->block, ob->shapenr - 1);
- if (kb) {
- uid = kb->uid;
- }
- else {
- CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);
- uid = INT_MAX;
- }
- }
- else {
- /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
- uid = INT_MAX;
- }
-
- shapekey_layers_to_keyblocks(dm, me, uid);
- did_shapekeys = 1;
- }
-
- /* copy texture space */
- if (ob) {
- BKE_mesh_texspace_copy_from_object(&tmp, ob);
- }
-
- /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
- * we set them here in case they are missing */
- if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
- CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN,
- (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm),
- totvert);
- }
- if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
- CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN,
- (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm),
- totedge);
- }
- if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
- tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm);
- tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm);
-
- CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
- CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
- }
-
- /* object had got displacement layer, should copy this layer to save sculpted data */
- /* NOTE: maybe some other layers should be copied? nazgul */
- if (CustomData_has_layer(&me->ldata, CD_MDISPS)) {
- if (totloop == me->totloop) {
- MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
- CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
- }
- }
-
- /* yes, must be before _and_ after tessellate */
- BKE_mesh_update_customdata_pointers(&tmp, false);
-
- /* since 2.65 caller must do! */
- // BKE_mesh_tessface_calc(&tmp);
-
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
-
- /* ok, this should now use new CD shapekey data,
- * which should be fed through the modifier
- * stack */
- if (tmp.totvert != me->totvert && !did_shapekeys && me->key) {
- CLOG_WARN(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
- if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
- id_us_min(&tmp.key->id);
- }
- tmp.key = NULL;
- }
-
- /* Clear selection history */
- MEM_SAFE_FREE(tmp.mselect);
- tmp.totselect = 0;
- BLI_assert(ELEM(tmp.bb, NULL, me->bb));
- if (me->bb) {
- MEM_freeN(me->bb);
- tmp.bb = NULL;
- }
-
- /* skip the listbase */
- MEMCPY_STRUCT_AFTER(me, &tmp, id.prev);
-
- if (take_ownership) {
- if (alloctype == CD_ASSIGN) {
- CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask->vmask);
- CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask->emask);
- CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask->lmask);
- CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask->pmask);
- }
- dm->release(dm);
- }
+ const unsigned int totpoly = dm->numPolyData;
+ const unsigned int totloop = dm->numLoopData;
+ const int looptris_num = poly_to_tri_count(totpoly, totloop);
+
+ BLI_assert(dm->looptris.array_wip == NULL);
+
+ SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip);
+
+ if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) ||
+ (totpoly == 0)) {
+ MEM_SAFE_FREE(dm->looptris.array_wip);
+ dm->looptris.num_alloc = 0;
+ dm->looptris.num = 0;
+ }
+
+ if (totpoly) {
+ if (dm->looptris.array_wip == NULL) {
+ dm->looptris.array_wip = MEM_malloc_arrayN(
+ looptris_num, sizeof(*dm->looptris.array_wip), __func__);
+ dm->looptris.num_alloc = looptris_num;
+ }
+
+ dm->looptris.num = looptris_num;
+ }
+}
+
+void DM_to_mesh(
+ DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership)
+{
+ /* dm might depend on me, so we need to do everything with a local copy */
+ Mesh tmp = *me;
+ int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
+ int did_shapekeys = 0;
+ eCDAllocType alloctype = CD_DUPLICATE;
+
+ if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) {
+ bool has_any_referenced_layers = CustomData_has_referenced(&dm->vertData) ||
+ CustomData_has_referenced(&dm->edgeData) ||
+ CustomData_has_referenced(&dm->loopData) ||
+ CustomData_has_referenced(&dm->faceData) ||
+ CustomData_has_referenced(&dm->polyData);
+ if (!has_any_referenced_layers) {
+ alloctype = CD_ASSIGN;
+ }
+ }
+
+ CustomData_reset(&tmp.vdata);
+ CustomData_reset(&tmp.edata);
+ CustomData_reset(&tmp.fdata);
+ CustomData_reset(&tmp.ldata);
+ CustomData_reset(&tmp.pdata);
+
+ DM_ensure_normals(dm);
+
+ totvert = tmp.totvert = dm->getNumVerts(dm);
+ totedge = tmp.totedge = dm->getNumEdges(dm);
+ totloop = tmp.totloop = dm->getNumLoops(dm);
+ totpoly = tmp.totpoly = dm->getNumPolys(dm);
+ tmp.totface = 0;
+
+ CustomData_copy(&dm->vertData, &tmp.vdata, mask->vmask, alloctype, totvert);
+ CustomData_copy(&dm->edgeData, &tmp.edata, mask->emask, alloctype, totedge);
+ CustomData_copy(&dm->loopData, &tmp.ldata, mask->lmask, alloctype, totloop);
+ CustomData_copy(&dm->polyData, &tmp.pdata, mask->pmask, alloctype, totpoly);
+ tmp.cd_flag = dm->cd_flag;
+ tmp.runtime.deformed_only = dm->deformedOnly;
+
+ if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
+ KeyBlock *kb;
+ int uid;
+
+ if (ob) {
+ kb = BLI_findlink(&me->key->block, ob->shapenr - 1);
+ if (kb) {
+ uid = kb->uid;
+ }
+ else {
+ CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);
+ uid = INT_MAX;
+ }
+ }
+ else {
+ /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
+ uid = INT_MAX;
+ }
+
+ shapekey_layers_to_keyblocks(dm, me, uid);
+ did_shapekeys = 1;
+ }
+
+ /* copy texture space */
+ if (ob) {
+ BKE_mesh_texspace_copy_from_object(&tmp, ob);
+ }
+
+ /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
+ * we set them here in case they are missing */
+ if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
+ CustomData_add_layer(&tmp.vdata,
+ CD_MVERT,
+ CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm),
+ totvert);
+ }
+ if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
+ CustomData_add_layer(&tmp.edata,
+ CD_MEDGE,
+ CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm),
+ totedge);
+ }
+ if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
+ tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm);
+ tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm);
+
+ CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
+ CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
+ }
+
+ /* object had got displacement layer, should copy this layer to save sculpted data */
+ /* NOTE: maybe some other layers should be copied? nazgul */
+ if (CustomData_has_layer(&me->ldata, CD_MDISPS)) {
+ if (totloop == me->totloop) {
+ MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
+ }
+ }
+
+ /* yes, must be before _and_ after tessellate */
+ BKE_mesh_update_customdata_pointers(&tmp, false);
+
+ /* since 2.65 caller must do! */
+ // BKE_mesh_tessface_calc(&tmp);
+
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* ok, this should now use new CD shapekey data,
+ * which should be fed through the modifier
+ * stack */
+ if (tmp.totvert != me->totvert && !did_shapekeys && me->key) {
+ CLOG_WARN(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
+ if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
+ id_us_min(&tmp.key->id);
+ }
+ tmp.key = NULL;
+ }
+
+ /* Clear selection history */
+ MEM_SAFE_FREE(tmp.mselect);
+ tmp.totselect = 0;
+ BLI_assert(ELEM(tmp.bb, NULL, me->bb));
+ if (me->bb) {
+ MEM_freeN(me->bb);
+ tmp.bb = NULL;
+ }
+
+ /* skip the listbase */
+ MEMCPY_STRUCT_AFTER(me, &tmp, id.prev);
+
+ if (take_ownership) {
+ if (alloctype == CD_ASSIGN) {
+ CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask->vmask);
+ CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask->emask);
+ CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask->lmask);
+ CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask->pmask);
+ }
+ dm->release(dm);
+ }
}
/** Utility function to convert an (evaluated) Mesh to a shape key block. */
@@ -642,13 +663,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMask
* that ensures both evaluated mesh and original one has same number of vertices. */
void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb)
{
- const int totvert = me_deformed->totvert;
+ const int totvert = me_deformed->totvert;
- if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) {
- return;
- }
+ if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) {
+ return;
+ }
- BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb);
+ BKE_keyblock_convert_from_mesh(me_deformed, me->key, kb);
}
/**
@@ -658,121 +679,119 @@ void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb)
*/
void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
{
- CustomData_set_only_copy(&dm->vertData, mask->vmask);
- CustomData_set_only_copy(&dm->edgeData, mask->emask);
- CustomData_set_only_copy(&dm->faceData, mask->fmask);
- /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
- * weight paint mode when there are modifiers applied, needs further investigation,
- * see replies to r50969, Campbell */
+ CustomData_set_only_copy(&dm->vertData, mask->vmask);
+ CustomData_set_only_copy(&dm->edgeData, mask->emask);
+ CustomData_set_only_copy(&dm->faceData, mask->fmask);
+ /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
+ * weight paint mode when there are modifiers applied, needs further investigation,
+ * see replies to r50969, Campbell */
#if 0
- CustomData_set_only_copy(&dm->loopData, mask->lmask);
- CustomData_set_only_copy(&dm->polyData, mask->pmask);
+ CustomData_set_only_copy(&dm->loopData, mask->lmask);
+ CustomData_set_only_copy(&dm->polyData, mask->pmask);
#endif
}
static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask)
{
- CustomData_set_only_copy(&mesh->vdata, mask->vmask);
- CustomData_set_only_copy(&mesh->edata, mask->emask);
- CustomData_set_only_copy(&mesh->fdata, mask->fmask);
- /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
- * weight paint mode when there are modifiers applied, needs further investigation,
- * see replies to r50969, Campbell */
+ CustomData_set_only_copy(&mesh->vdata, mask->vmask);
+ CustomData_set_only_copy(&mesh->edata, mask->emask);
+ CustomData_set_only_copy(&mesh->fdata, mask->fmask);
+ /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
+ * weight paint mode when there are modifiers applied, needs further investigation,
+ * see replies to r50969, Campbell */
#if 0
- CustomData_set_only_copy(&mesh->ldata, mask->lmask);
- CustomData_set_only_copy(&mesh->pdata, mask->pmask);
+ CustomData_set_only_copy(&mesh->ldata, mask->lmask);
+ CustomData_set_only_copy(&mesh->pdata, mask->pmask);
#endif
}
void DM_add_vert_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
- CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData);
+ CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData);
}
void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
- CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
+ CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
}
void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
- CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
+ CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
}
void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
- CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
+ CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
}
void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
- CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
+ CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
}
void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
{
- BLI_assert(index >= 0 && index < dm->getNumVerts(dm));
- return CustomData_get(&dm->vertData, index, type);
+ BLI_assert(index >= 0 && index < dm->getNumVerts(dm));
+ return CustomData_get(&dm->vertData, index, type);
}
void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
{
- BLI_assert(index >= 0 && index < dm->getNumEdges(dm));
- return CustomData_get(&dm->edgeData, index, type);
+ BLI_assert(index >= 0 && index < dm->getNumEdges(dm));
+ return CustomData_get(&dm->edgeData, index, type);
}
void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
{
- BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm));
- return CustomData_get(&dm->faceData, index, type);
+ BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm));
+ return CustomData_get(&dm->faceData, index, type);
}
void *DM_get_poly_data(DerivedMesh *dm, int index, int type)
{
- BLI_assert(index >= 0 && index < dm->getNumPolys(dm));
- return CustomData_get(&dm->polyData, index, type);
+ BLI_assert(index >= 0 && index < dm->getNumPolys(dm));
+ return CustomData_get(&dm->polyData, index, type);
}
-
void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
{
- if (type == CD_MVERT)
- return dm->getVertArray(dm);
+ if (type == CD_MVERT)
+ return dm->getVertArray(dm);
- return CustomData_get_layer(&dm->vertData, type);
+ return CustomData_get_layer(&dm->vertData, type);
}
void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
{
- if (type == CD_MEDGE)
- return dm->getEdgeArray(dm);
+ if (type == CD_MEDGE)
+ return dm->getEdgeArray(dm);
- return CustomData_get_layer(&dm->edgeData, type);
+ return CustomData_get_layer(&dm->edgeData, type);
}
void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
{
- if (type == CD_MFACE)
- return dm->getTessFaceArray(dm);
+ if (type == CD_MFACE)
+ return dm->getTessFaceArray(dm);
- return CustomData_get_layer(&dm->faceData, type);
+ return CustomData_get_layer(&dm->faceData, type);
}
void *DM_get_poly_data_layer(DerivedMesh *dm, int type)
{
- return CustomData_get_layer(&dm->polyData, type);
+ return CustomData_get_layer(&dm->polyData, type);
}
void *DM_get_loop_data_layer(DerivedMesh *dm, int type)
{
- return CustomData_get_layer(&dm->loopData, type);
+ return CustomData_get_layer(&dm->loopData, type);
}
-void DM_copy_vert_data(DerivedMesh *source, DerivedMesh *dest,
- int source_index, int dest_index, int count)
+void DM_copy_vert_data(
+ DerivedMesh *source, DerivedMesh *dest, int source_index, int dest_index, int count)
{
- CustomData_copy_data(&source->vertData, &dest->vertData,
- source_index, dest_index, count);
+ CustomData_copy_data(&source->vertData, &dest->vertData, source_index, dest_index, count);
}
/**
@@ -780,1717 +799,1782 @@ void DM_copy_vert_data(DerivedMesh *source, DerivedMesh *dest,
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
*/
-void DM_interp_vert_data(
- DerivedMesh *source, DerivedMesh *dest,
- int *src_indices, float *weights,
- int count, int dest_index)
+void DM_interp_vert_data(DerivedMesh *source,
+ DerivedMesh *dest,
+ int *src_indices,
+ float *weights,
+ int count,
+ int dest_index)
{
- CustomData_interp(&source->vertData, &dest->vertData, src_indices,
- weights, NULL, count, dest_index);
+ CustomData_interp(
+ &source->vertData, &dest->vertData, src_indices, weights, NULL, count, dest_index);
}
DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
{
- DerivedMesh *dm = CDDM_from_mesh(me);
+ DerivedMesh *dm = CDDM_from_mesh(me);
- if (!dm)
- return NULL;
+ if (!dm)
+ return NULL;
- if (vertCos) {
- CDDM_apply_vert_coords(dm, vertCos);
- }
+ if (vertCos) {
+ CDDM_apply_vert_coords(dm, vertCos);
+ }
- return dm;
+ return dm;
}
static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
{
- BMIter iter;
- BMVert *eve;
- float (*orco)[3];
- int i;
+ BMIter iter;
+ BMVert *eve;
+ float(*orco)[3];
+ int i;
- /* these may not really be the orco's, but it's only for preview.
- * could be solver better once, but isn't simple */
+ /* these may not really be the orco's, but it's only for preview.
+ * could be solver better once, but isn't simple */
- orco = MEM_malloc_arrayN(em->bm->totvert, sizeof(float) * 3, "BMEditMesh Orco");
+ orco = MEM_malloc_arrayN(em->bm->totvert, sizeof(float) * 3, "BMEditMesh Orco");
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- copy_v3_v3(orco[i], eve->co);
- }
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ copy_v3_v3(orco[i], eve->co);
+ }
- return orco;
+ return orco;
}
/* orco custom data layer */
static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free))[3]
{
- *free = 0;
+ *free = 0;
- if (layer == CD_ORCO) {
- /* get original coordinates */
- *free = 1;
+ if (layer == CD_ORCO) {
+ /* get original coordinates */
+ *free = 1;
- if (em)
- return get_editbmesh_orco_verts(em);
- else
- return BKE_mesh_orco_verts_get(ob);
- }
- else if (layer == CD_CLOTH_ORCO) {
- /* apply shape key for cloth, this should really be solved
- * by a more flexible customdata system, but not simple */
- if (!em) {
- ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
- KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest);
+ if (em)
+ return get_editbmesh_orco_verts(em);
+ else
+ return BKE_mesh_orco_verts_get(ob);
+ }
+ else if (layer == CD_CLOTH_ORCO) {
+ /* apply shape key for cloth, this should really be solved
+ * by a more flexible customdata system, but not simple */
+ if (!em) {
+ ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+ KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob),
+ clmd->sim_parms->shapekey_rest);
- if (kb && kb->data) {
- return kb->data;
- }
- }
+ if (kb && kb->data) {
+ return kb->data;
+ }
+ }
- return NULL;
- }
+ return NULL;
+ }
- return NULL;
+ return NULL;
}
static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
{
- Mesh *mesh;
- float (*orco)[3];
- int free;
+ Mesh *mesh;
+ float(*orco)[3];
+ int free;
- if (em) {
- mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL);
- }
- else {
- mesh = BKE_mesh_copy_for_eval(me, true);
- }
+ if (em) {
+ mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL);
+ }
+ else {
+ mesh = BKE_mesh_copy_for_eval(me, true);
+ }
- orco = get_orco_coords(ob, em, layer, &free);
+ orco = get_orco_coords(ob, em, layer, &free);
- if (orco) {
- BKE_mesh_apply_vert_coords(mesh, orco);
- if (free) MEM_freeN(orco);
- }
+ if (orco) {
+ BKE_mesh_apply_vert_coords(mesh, orco);
+ if (free)
+ MEM_freeN(orco);
+ }
- return mesh;
+ return mesh;
}
-static void add_orco_mesh(
- Object *ob, BMEditMesh *em, Mesh *mesh,
- Mesh *mesh_orco, int layer)
+static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, int layer)
{
- float (*orco)[3], (*layerorco)[3];
- int totvert, free;
+ float(*orco)[3], (*layerorco)[3];
+ int totvert, free;
- totvert = mesh->totvert;
+ totvert = mesh->totvert;
- if (mesh_orco) {
- free = 1;
+ if (mesh_orco) {
+ free = 1;
- if (mesh_orco->totvert == totvert) {
- orco = BKE_mesh_vertexCos_get(mesh_orco, NULL);
- }
- else {
- orco = BKE_mesh_vertexCos_get(mesh, NULL);
- }
- }
- else {
- /* TODO(sybren): totvert should potentially change here, as ob->data
- * or em may have a different number of vertices than dm. */
- orco = get_orco_coords(ob, em, layer, &free);
- }
+ if (mesh_orco->totvert == totvert) {
+ orco = BKE_mesh_vertexCos_get(mesh_orco, NULL);
+ }
+ else {
+ orco = BKE_mesh_vertexCos_get(mesh, NULL);
+ }
+ }
+ else {
+ /* TODO(sybren): totvert should potentially change here, as ob->data
+ * or em may have a different number of vertices than dm. */
+ orco = get_orco_coords(ob, em, layer, &free);
+ }
- if (orco) {
- if (layer == CD_ORCO) {
- BKE_mesh_orco_verts_transform(ob->data, orco, totvert, 0);
- }
+ if (orco) {
+ if (layer == CD_ORCO) {
+ BKE_mesh_orco_verts_transform(ob->data, orco, totvert, 0);
+ }
- if (!(layerorco = CustomData_get_layer(&mesh->vdata, layer))) {
- CustomData_add_layer(&mesh->vdata, layer, CD_CALLOC, NULL, mesh->totvert);
- BKE_mesh_update_customdata_pointers(mesh, false);
+ if (!(layerorco = CustomData_get_layer(&mesh->vdata, layer))) {
+ CustomData_add_layer(&mesh->vdata, layer, CD_CALLOC, NULL, mesh->totvert);
+ BKE_mesh_update_customdata_pointers(mesh, false);
- layerorco = CustomData_get_layer(&mesh->vdata, layer);
- }
+ layerorco = CustomData_get_layer(&mesh->vdata, layer);
+ }
- memcpy(layerorco, orco, sizeof(float) * 3 * totvert);
- if (free) MEM_freeN(orco);
- }
+ memcpy(layerorco, orco, sizeof(float) * 3 * totvert);
+ if (free)
+ MEM_freeN(orco);
+ }
}
static void editmesh_update_statvis_color(const Scene *scene, Object *ob)
{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- Mesh *me = ob->data;
- BKE_mesh_runtime_ensure_edit_data(me);
- BKE_editmesh_statvis_calc(em, me->runtime.edit_data, &scene->toolsettings->statvis);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ Mesh *me = ob->data;
+ BKE_mesh_runtime_ensure_edit_data(me);
+ BKE_editmesh_statvis_calc(em, me->runtime.edit_data, &scene->toolsettings->statvis);
}
static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid)
{
- KeyBlock *kb;
- int i, j, tot;
-
- if (!me->key)
- return;
-
- tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
- for (i = 0; i < tot; i++) {
- CustomDataLayer *layer = &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)];
- float (*cos)[3], (*kbcos)[3];
-
- for (kb = me->key->block.first; kb; kb = kb->next) {
- if (kb->uid == layer->uid)
- break;
- }
-
- if (!kb) {
- kb = BKE_keyblock_add(me->key, layer->name);
- kb->uid = layer->uid;
- }
-
- if (kb->data)
- MEM_freeN(kb->data);
-
- cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
- kb->totelem = dm->numVertData;
-
- kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
- if (kb->uid == actshape_uid) {
- MVert *mvert = dm->getVertArray(dm);
-
- for (j = 0; j < dm->numVertData; j++, kbcos++, mvert++) {
- copy_v3_v3(*kbcos, mvert->co);
- }
- }
- else {
- for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
- copy_v3_v3(*kbcos, *cos);
- }
- }
- }
-
- for (kb = me->key->block.first; kb; kb = kb->next) {
- if (kb->totelem != dm->numVertData) {
- if (kb->data)
- MEM_freeN(kb->data);
-
- kb->totelem = dm->numVertData;
- kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), "kb->data derivedmesh.c");
- CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name);
- }
- }
+ KeyBlock *kb;
+ int i, j, tot;
+
+ if (!me->key)
+ return;
+
+ tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
+ for (i = 0; i < tot; i++) {
+ CustomDataLayer *layer =
+ &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)];
+ float(*cos)[3], (*kbcos)[3];
+
+ for (kb = me->key->block.first; kb; kb = kb->next) {
+ if (kb->uid == layer->uid)
+ break;
+ }
+
+ if (!kb) {
+ kb = BKE_keyblock_add(me->key, layer->name);
+ kb->uid = layer->uid;
+ }
+
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
+ kb->totelem = dm->numVertData;
+
+ kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
+ if (kb->uid == actshape_uid) {
+ MVert *mvert = dm->getVertArray(dm);
+
+ for (j = 0; j < dm->numVertData; j++, kbcos++, mvert++) {
+ copy_v3_v3(*kbcos, mvert->co);
+ }
+ }
+ else {
+ for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
+ copy_v3_v3(*kbcos, *cos);
+ }
+ }
+ }
+
+ for (kb = me->key->block.first; kb; kb = kb->next) {
+ if (kb->totelem != dm->numVertData) {
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ kb->totelem = dm->numVertData;
+ kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), "kb->data derivedmesh.c");
+ CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name);
+ }
+ }
}
static void mesh_copy_autosmooth(Mesh *me, Mesh *me_orig)
{
- if (me_orig->flag & ME_AUTOSMOOTH) {
- me->flag |= ME_AUTOSMOOTH;
- me->smoothresh = me_orig->smoothresh;
- }
-}
-
-static void mesh_calc_modifier_final_normals(
- const Mesh *mesh_input,
- const CustomData_MeshMasks *dataMask,
- const bool sculpt_dyntopo,
- Mesh *mesh_final)
-{
- /* Compute normals. */
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
- (dataMask->lmask & CD_MASK_NORMAL) != 0);
- /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well.
- * Note that they will always be generated when no loop normals are comptuted,
- * since they are needed by drawing code. */
- const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
-
- if (do_loop_normals) {
- /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
- if (do_poly_normals) {
- if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
- CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
- }
- }
- /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
- BKE_mesh_calc_normals_split(mesh_final);
- BKE_mesh_tessface_clear(mesh_final);
- }
-
- if (sculpt_dyntopo == false) {
- /* watch this! after 2.75a we move to from tessface to looptri (by default) */
- if (dataMask->fmask & CD_MASK_MFACE) {
- BKE_mesh_tessface_ensure(mesh_final);
- }
-
- /* without this, drawing ngon tri's faces will show ugly tessellated face
- * normals and will also have to calculate normals on the fly, try avoid
- * this where possible since calculating polygon normals isn't fast,
- * note that this isn't a problem for subsurf (only quads) or editmode
- * which deals with drawing differently.
- *
- * Only calc vertex normals if they are flagged as dirty.
- * If using loop normals, poly nors have already been computed.
- */
- if (!do_loop_normals) {
- BKE_mesh_ensure_normals_for_display(mesh_final);
- }
- }
-
- /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
- * as they are used by display code when available (i.e. even if autosmooth is disabled). */
- if (!do_loop_normals && CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
- CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
- }
-}
-
-static void mesh_calc_modifiers(
- struct Depsgraph *depsgraph,
- Scene *scene, Object *ob,
- int useDeform,
- const bool need_mapping,
- const CustomData_MeshMasks *dataMask,
- const int index,
- const bool use_cache,
- /* return args */
- Mesh **r_deform,
- Mesh **r_final)
-{
- /* Input and final mesh. Final mesh is only created the moment the first
- * constructive modifier is executed, or a deform modifier needs normals
- * or certain data layers. */
- Mesh *mesh_input = ob->data;
- Mesh *mesh_final = NULL;
- Mesh *mesh_deform = NULL;
- BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
-
- /* Deformed vertex locations array. Deform only modifier need this type of
- * float array rather than MVert*. Tracked along with mesh_final as an
- * optimization to avoid copying coordinates back and forth if there are
- * multiple sequential deform only modifiers. */
- float (*deformed_verts)[3] = NULL;
- int num_deformed_verts = mesh_input->totvert;
- bool isPrevDeform = false;
-
- /* Mesh with constructive modifiers but no deformation applied. Tracked
- * along with final mesh if undeformed / orco coordinates are requested
- * for texturing. */
- Mesh *mesh_orco = NULL;
- Mesh *mesh_orco_cloth = NULL;
-
- /* Modifier evaluation modes. */
- const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
-
- /* Sculpt can skip certain modifiers. */
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
- const bool has_multires = (mmd && mmd->sculptlvl != 0);
- bool multires_applied = false;
- const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render;
- const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render;
-
- /* Modifier evaluation contexts for different types of modifiers. */
- ModifierApplyFlag app_render = use_render ? MOD_APPLY_RENDER : 0;
- ModifierApplyFlag app_cache = use_cache ? MOD_APPLY_USECACHE : 0;
- const ModifierEvalContext mectx = {depsgraph, ob, app_render | app_cache};
- const ModifierEvalContext mectx_orco = {depsgraph, ob, app_render | MOD_APPLY_ORCO};
-
- /* Get effective list of modifiers to execute. Some effects like shape keys
- * are added as virtual modifiers before the user created modifiers. */
- VirtualModifierData virtualModifierData;
- ModifierData *firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
- ModifierData *md = firstmd;
-
- /* Preview colors by modifiers such as dynamic paint, to show the results
- * even if the resulting data is not used in a material. Only in object mode.
- * TODO: this is broken, not drawn by the drawn manager. */
- const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
- ModifierData *previewmd = NULL;
- CustomData_MeshMasks previewmask = {0};
- if (do_mod_mcol) {
- /* Find the last active modifier generating a preview, or NULL if none. */
- /* XXX Currently, DPaint modifier just ignores this.
- * Needs a stupid hack...
- * The whole "modifier preview" thing has to be (re?)designed, anyway! */
- previewmd = modifiers_getLastPreview(scene, md, required_mode);
- }
-
- /* Compute accumulated datamasks needed by each modifier. It helps to do
- * this fine grained so that for example vertex groups are preserved up to
- * an armature modifier, but not through a following subsurf modifier where
- * subdividing them is expensive. */
- CDMaskLink *datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, &previewmask);
- CDMaskLink *md_datamask = datamasks;
- /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
- CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX;
-
- /* Clear errors before evaluation. */
- modifiers_clearErrors(ob);
-
- /* Apply all leading deform modifiers. */
- if (useDeform) {
- for (; md; md = md->next, md_datamask = md_datamask->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (!modifier_isEnabled(scene, md, required_mode)) {
- continue;
- }
-
- if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
- continue;
- }
-
- if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
- if (!deformed_verts) {
- deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
- }
- else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- if (mesh_final == NULL) {
- mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
- ASSERT_IS_VALID_MESH(mesh_final);
- }
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
-
- modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
-
- isPrevDeform = true;
- }
- else {
- break;
- }
-
- /* grab modifiers until index i */
- if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
- break;
- }
-
- /* Result of all leading deforming modifiers is cached for
- * places that wish to use the original mesh but with deformed
- * coordinates (like vertex paint). */
- if (r_deform) {
- mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
-
- if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_deform, deformed_verts);
- }
- }
- }
-
- /* Apply all remaining constructive and deforming modifiers. */
- for (; md; md = md->next, md_datamask = md_datamask->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (!modifier_isEnabled(scene, md, required_mode)) {
- continue;
- }
-
- if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) {
- continue;
- }
-
- if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && mesh_final) {
- modifier_setError(md, "Modifier requires original data, bad stack position");
- continue;
- }
-
- if (sculpt_mode &&
- (!has_multires || multires_applied || sculpt_dyntopo))
- {
- bool unsupported = false;
-
- if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) {
- /* If multires is on level 0 skip it silently without warning message. */
- if (!sculpt_dyntopo) {
- continue;
- }
- }
-
- if (sculpt_dyntopo)
- unsupported = true;
-
- if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
- unsupported |= (mti->type != eModifierTypeType_OnlyDeform);
-
- unsupported |= multires_applied;
-
- if (unsupported) {
- if (sculpt_dyntopo)
- modifier_setError(md, "Not supported in dyntopo");
- else
- modifier_setError(md, "Not supported in sculpt mode");
- continue;
- }
- else {
- modifier_setError(md, "Hide, Mask and optimized display disabled");
- }
- }
-
- if (need_mapping && !modifier_supportsMapping(md)) {
- continue;
- }
-
- if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
- continue;
- }
-
- /* Add an orco layer if needed by this modifier. */
- if (mesh_final && mti->requiredDataMask) {
- CustomData_MeshMasks mask = {0};
- mti->requiredDataMask(ob, md, &mask);
- if (mask.vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
- }
- }
-
- /* How to apply modifier depends on (a) what we already have as
- * a result of previous modifiers (could be a Mesh or just
- * deformed vertices) and (b) what type the modifier is. */
- if (mti->type == eModifierTypeType_OnlyDeform) {
- /* No existing verts to deform, need to build them. */
- if (!deformed_verts) {
- if (mesh_final) {
- /* Deforming a mesh, read the vertex locations
- * out of the mesh and deform them. Once done with this
- * run of deformers verts will be written back. */
- deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
- }
- else {
- deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
- }
- }
- /* if this is not the last modifier in the stack then recalculate the normals
- * to avoid giving bogus normals to the next modifier see: [#23673] */
- else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- /* XXX, this covers bug #23673, but we may need normal calc for other types */
- if (mesh_final) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
- }
-
- modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
- }
- else {
- /* determine which data layers are needed by following modifiers */
- CustomData_MeshMasks nextmask;
- if (md_datamask->next)
- nextmask = md_datamask->next->mask;
- else
- nextmask = *dataMask;
-
- /* apply vertex coordinates or build a Mesh as necessary */
- if (mesh_final) {
- if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
- }
- else {
- mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
- ASSERT_IS_VALID_MESH(mesh_final);
-
- if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
-
- /* Initialize original indices the first time we evaluate a
- * constructive modifier. Modifiers will then do mapping mostly
- * automatic by copying them through CustomData_copy_data along
- * with other data.
- *
- * These are created when either requested by evaluation, or if
- * following modifiers requested them. */
- if (need_mapping || ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) {
- /* calc */
- CustomData_add_layer(&mesh_final->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totvert);
- CustomData_add_layer(&mesh_final->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totedge);
- CustomData_add_layer(&mesh_final->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totpoly);
-
- /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */
- range_vn_i(CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX), mesh_final->totvert, 0);
- range_vn_i(CustomData_get_layer(&mesh_final->edata, CD_ORIGINDEX), mesh_final->totedge, 0);
- range_vn_i(CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX), mesh_final->totpoly, 0);
- }
- }
-
-
- /* set the Mesh to only copy needed data */
- CustomData_MeshMasks mask = md_datamask->mask;
- /* needMapping check here fixes bug [#28112], otherwise it's
- * possible that it won't be copied */
- CustomData_MeshMasks_update(&mask, &append_mask);
- if (need_mapping) {
- mask.vmask |= CD_MASK_ORIGINDEX;
- mask.emask |= CD_MASK_ORIGINDEX;
- mask.pmask |= CD_MASK_ORIGINDEX;
- }
- mesh_set_only_copy(mesh_final, &mask);
-
- /* add cloth rest shape key if needed */
- if (mask.vmask & CD_MASK_CLOTH_ORCO) {
- add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_CLOTH_ORCO);
- }
-
- /* add an origspace layer if needed */
- if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
- if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
- CustomData_add_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
- mesh_init_origspace(mesh_final);
- }
- }
-
- Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
- ASSERT_IS_VALID_MESH(mesh_next);
-
- if (mesh_next) {
- /* if the modifier returned a new mesh, release the old one */
- if (mesh_final != mesh_next) {
- BLI_assert(mesh_final != mesh_input);
- BKE_id_free(NULL, mesh_final);
- }
- mesh_final = mesh_next;
-
- if (deformed_verts) {
- MEM_freeN(deformed_verts);
- deformed_verts = NULL;
- }
-
- mesh_copy_autosmooth(mesh_final, mesh_input);
- }
-
- /* create an orco mesh in parallel */
- if (nextmask.vmask & CD_MASK_ORCO) {
- if (!mesh_orco) {
- mesh_orco = create_orco_mesh(ob, mesh_input, NULL, CD_ORCO);
- }
-
- nextmask.vmask &= ~CD_MASK_ORCO;
- CustomData_MeshMasks temp_cddata_masks = {
- .vmask = CD_MASK_ORIGINDEX,
- .emask = CD_MASK_ORIGINDEX,
- .fmask = CD_MASK_ORIGINDEX,
- .pmask = CD_MASK_ORIGINDEX,
- };
- if (mti->requiredDataMask != NULL) {
- mti->requiredDataMask(ob, md, &temp_cddata_masks);
- }
- CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask);
- mesh_set_only_copy(mesh_orco, &temp_cddata_masks);
-
- mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
- ASSERT_IS_VALID_MESH(mesh_next);
-
- if (mesh_next) {
- /* if the modifier returned a new mesh, release the old one */
- if (mesh_orco != mesh_next) {
- BLI_assert(mesh_orco != mesh_input);
- BKE_id_free(NULL, mesh_orco);
- }
-
- mesh_orco = mesh_next;
- }
- }
-
- /* create cloth orco mesh in parallel */
- if (nextmask.vmask & CD_MASK_CLOTH_ORCO) {
- if (!mesh_orco_cloth) {
- mesh_orco_cloth = create_orco_mesh(ob, mesh_input, NULL, CD_CLOTH_ORCO);
- }
-
- nextmask.vmask &= ~CD_MASK_CLOTH_ORCO;
- nextmask.vmask |= CD_MASK_ORIGINDEX;
- nextmask.emask |= CD_MASK_ORIGINDEX;
- nextmask.pmask |= CD_MASK_ORIGINDEX;
- mesh_set_only_copy(mesh_orco_cloth, &nextmask);
-
- mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco_cloth);
- ASSERT_IS_VALID_MESH(mesh_next);
-
- if (mesh_next) {
- /* if the modifier returned a new mesh, release the old one */
- if (mesh_orco_cloth != mesh_next) {
- BLI_assert(mesh_orco != mesh_input);
- BKE_id_free(NULL, mesh_orco_cloth);
- }
-
- mesh_orco_cloth = mesh_next;
- }
- }
-
- /* in case of dynamic paint, make sure preview mask remains for following modifiers */
- /* XXX Temp and hackish solution! */
- if (md->type == eModifierType_DynamicPaint) {
- append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL;
- }
-
- mesh_final->runtime.deformed_only = false;
- }
-
- isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
-
- /* grab modifiers until index i */
- if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
- break;
-
- if (sculpt_mode && md->type == eModifierType_Multires) {
- multires_applied = true;
- }
- }
-
- BLI_linklist_free((LinkNode *)datamasks, NULL);
-
- for (md = firstmd; md; md = md->next)
- modifier_freeTemporaryData(md);
-
- /* Yay, we are done. If we have a Mesh and deformed vertices
- * need to apply these back onto the Mesh. If we have no
- * Mesh then we need to build one. */
- if (mesh_final == NULL) {
- mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
- }
- if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- MEM_freeN(deformed_verts);
- deformed_verts = NULL;
- }
-
- /* Add orco coordinates to final and deformed mesh if requested. */
- if (dataMask->vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
-
- if (mesh_deform)
- add_orco_mesh(ob, NULL, mesh_deform, NULL, CD_ORCO);
- }
-
- if (mesh_orco) {
- BKE_id_free(NULL, mesh_orco);
- }
- if (mesh_orco_cloth) {
- BKE_id_free(NULL, mesh_orco_cloth);
- }
-
- /* Compute normals. */
- mesh_calc_modifier_final_normals(mesh_input, dataMask, sculpt_dyntopo, mesh_final);
-
- /* Return final mesh */
- *r_final = mesh_final;
- if (r_deform) {
- *r_deform = mesh_deform;
- }
+ if (me_orig->flag & ME_AUTOSMOOTH) {
+ me->flag |= ME_AUTOSMOOTH;
+ me->smoothresh = me_orig->smoothresh;
+ }
+}
+
+static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
+ const CustomData_MeshMasks *dataMask,
+ const bool sculpt_dyntopo,
+ Mesh *mesh_final)
+{
+ /* Compute normals. */
+ const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (dataMask->lmask & CD_MASK_NORMAL) != 0);
+ /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well.
+ * Note that they will always be generated when no loop normals are comptuted,
+ * since they are needed by drawing code. */
+ const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+
+ if (do_loop_normals) {
+ /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
+ if (do_poly_normals) {
+ if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
+ CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
+ }
+ }
+ /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
+ BKE_mesh_calc_normals_split(mesh_final);
+ BKE_mesh_tessface_clear(mesh_final);
+ }
+
+ if (sculpt_dyntopo == false) {
+ /* watch this! after 2.75a we move to from tessface to looptri (by default) */
+ if (dataMask->fmask & CD_MASK_MFACE) {
+ BKE_mesh_tessface_ensure(mesh_final);
+ }
+
+ /* without this, drawing ngon tri's faces will show ugly tessellated face
+ * normals and will also have to calculate normals on the fly, try avoid
+ * this where possible since calculating polygon normals isn't fast,
+ * note that this isn't a problem for subsurf (only quads) or editmode
+ * which deals with drawing differently.
+ *
+ * Only calc vertex normals if they are flagged as dirty.
+ * If using loop normals, poly nors have already been computed.
+ */
+ if (!do_loop_normals) {
+ BKE_mesh_ensure_normals_for_display(mesh_final);
+ }
+ }
+
+ /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (!do_loop_normals && CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
+ CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
+ }
+}
+
+static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ int useDeform,
+ const bool need_mapping,
+ const CustomData_MeshMasks *dataMask,
+ const int index,
+ const bool use_cache,
+ /* return args */
+ Mesh **r_deform,
+ Mesh **r_final)
+{
+ /* Input and final mesh. Final mesh is only created the moment the first
+ * constructive modifier is executed, or a deform modifier needs normals
+ * or certain data layers. */
+ Mesh *mesh_input = ob->data;
+ Mesh *mesh_final = NULL;
+ Mesh *mesh_deform = NULL;
+ BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
+
+ /* Deformed vertex locations array. Deform only modifier need this type of
+ * float array rather than MVert*. Tracked along with mesh_final as an
+ * optimization to avoid copying coordinates back and forth if there are
+ * multiple sequential deform only modifiers. */
+ float(*deformed_verts)[3] = NULL;
+ int num_deformed_verts = mesh_input->totvert;
+ bool isPrevDeform = false;
+
+ /* Mesh with constructive modifiers but no deformation applied. Tracked
+ * along with final mesh if undeformed / orco coordinates are requested
+ * for texturing. */
+ Mesh *mesh_orco = NULL;
+ Mesh *mesh_orco_cloth = NULL;
+
+ /* Modifier evaluation modes. */
+ const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+
+ /* Sculpt can skip certain modifiers. */
+ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
+ const bool has_multires = (mmd && mmd->sculptlvl != 0);
+ bool multires_applied = false;
+ const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render;
+ const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render;
+
+ /* Modifier evaluation contexts for different types of modifiers. */
+ ModifierApplyFlag app_render = use_render ? MOD_APPLY_RENDER : 0;
+ ModifierApplyFlag app_cache = use_cache ? MOD_APPLY_USECACHE : 0;
+ const ModifierEvalContext mectx = {depsgraph, ob, app_render | app_cache};
+ const ModifierEvalContext mectx_orco = {depsgraph, ob, app_render | MOD_APPLY_ORCO};
+
+ /* Get effective list of modifiers to execute. Some effects like shape keys
+ * are added as virtual modifiers before the user created modifiers. */
+ VirtualModifierData virtualModifierData;
+ ModifierData *firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ ModifierData *md = firstmd;
+
+ /* Preview colors by modifiers such as dynamic paint, to show the results
+ * even if the resulting data is not used in a material. Only in object mode.
+ * TODO: this is broken, not drawn by the drawn manager. */
+ const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
+ ModifierData *previewmd = NULL;
+ CustomData_MeshMasks previewmask = {0};
+ if (do_mod_mcol) {
+ /* Find the last active modifier generating a preview, or NULL if none. */
+ /* XXX Currently, DPaint modifier just ignores this.
+ * Needs a stupid hack...
+ * The whole "modifier preview" thing has to be (re?)designed, anyway! */
+ previewmd = modifiers_getLastPreview(scene, md, required_mode);
+ }
+
+ /* Compute accumulated datamasks needed by each modifier. It helps to do
+ * this fine grained so that for example vertex groups are preserved up to
+ * an armature modifier, but not through a following subsurf modifier where
+ * subdividing them is expensive. */
+ CDMaskLink *datamasks = modifiers_calcDataMasks(
+ scene, ob, md, dataMask, required_mode, previewmd, &previewmask);
+ CDMaskLink *md_datamask = datamasks;
+ /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
+ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX;
+
+ /* Clear errors before evaluation. */
+ modifiers_clearErrors(ob);
+
+ /* Apply all leading deform modifiers. */
+ if (useDeform) {
+ for (; md; md = md->next, md_datamask = md_datamask->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ continue;
+ }
+
+ if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
+ continue;
+ }
+
+ if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
+ if (!deformed_verts) {
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
+ }
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+ ASSERT_IS_VALID_MESH(mesh_final);
+ }
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
+
+ isPrevDeform = true;
+ }
+ else {
+ break;
+ }
+
+ /* grab modifiers until index i */
+ if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
+ break;
+ }
+
+ /* Result of all leading deforming modifiers is cached for
+ * places that wish to use the original mesh but with deformed
+ * coordinates (like vertex paint). */
+ if (r_deform) {
+ mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
+
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_deform, deformed_verts);
+ }
+ }
+ }
+
+ /* Apply all remaining constructive and deforming modifiers. */
+ for (; md; md = md->next, md_datamask = md_datamask->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ continue;
+ }
+
+ if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) {
+ continue;
+ }
+
+ if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && mesh_final) {
+ modifier_setError(md, "Modifier requires original data, bad stack position");
+ continue;
+ }
+
+ if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) {
+ bool unsupported = false;
+
+ if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) {
+ /* If multires is on level 0 skip it silently without warning message. */
+ if (!sculpt_dyntopo) {
+ continue;
+ }
+ }
+
+ if (sculpt_dyntopo)
+ unsupported = true;
+
+ if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
+ unsupported |= (mti->type != eModifierTypeType_OnlyDeform);
+
+ unsupported |= multires_applied;
+
+ if (unsupported) {
+ if (sculpt_dyntopo)
+ modifier_setError(md, "Not supported in dyntopo");
+ else
+ modifier_setError(md, "Not supported in sculpt mode");
+ continue;
+ }
+ else {
+ modifier_setError(md, "Hide, Mask and optimized display disabled");
+ }
+ }
+
+ if (need_mapping && !modifier_supportsMapping(md)) {
+ continue;
+ }
+
+ if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) {
+ continue;
+ }
+
+ /* Add an orco layer if needed by this modifier. */
+ if (mesh_final && mti->requiredDataMask) {
+ CustomData_MeshMasks mask = {0};
+ mti->requiredDataMask(ob, md, &mask);
+ if (mask.vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
+ }
+ }
+
+ /* How to apply modifier depends on (a) what we already have as
+ * a result of previous modifiers (could be a Mesh or just
+ * deformed vertices) and (b) what type the modifier is. */
+ if (mti->type == eModifierTypeType_OnlyDeform) {
+ /* No existing verts to deform, need to build them. */
+ if (!deformed_verts) {
+ if (mesh_final) {
+ /* Deforming a mesh, read the vertex locations
+ * out of the mesh and deform them. Once done with this
+ * run of deformers verts will be written back. */
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
+ }
+ else {
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
+ }
+ }
+ /* if this is not the last modifier in the stack then recalculate the normals
+ * to avoid giving bogus normals to the next modifier see: [#23673] */
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ /* XXX, this covers bug #23673, but we may need normal calc for other types */
+ if (mesh_final) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+ }
+
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
+ }
+ else {
+ /* determine which data layers are needed by following modifiers */
+ CustomData_MeshMasks nextmask;
+ if (md_datamask->next)
+ nextmask = md_datamask->next->mask;
+ else
+ nextmask = *dataMask;
+
+ /* apply vertex coordinates or build a Mesh as necessary */
+ if (mesh_final) {
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+ }
+ else {
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+ ASSERT_IS_VALID_MESH(mesh_final);
+
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+
+ /* Initialize original indices the first time we evaluate a
+ * constructive modifier. Modifiers will then do mapping mostly
+ * automatic by copying them through CustomData_copy_data along
+ * with other data.
+ *
+ * These are created when either requested by evaluation, or if
+ * following modifiers requested them. */
+ if (need_mapping ||
+ ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) {
+ /* calc */
+ CustomData_add_layer(
+ &mesh_final->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totvert);
+ CustomData_add_layer(
+ &mesh_final->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totedge);
+ CustomData_add_layer(
+ &mesh_final->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totpoly);
+
+ /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */
+ range_vn_i(
+ CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX), mesh_final->totvert, 0);
+ range_vn_i(
+ CustomData_get_layer(&mesh_final->edata, CD_ORIGINDEX), mesh_final->totedge, 0);
+ range_vn_i(
+ CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX), mesh_final->totpoly, 0);
+ }
+ }
+
+ /* set the Mesh to only copy needed data */
+ CustomData_MeshMasks mask = md_datamask->mask;
+ /* needMapping check here fixes bug [#28112], otherwise it's
+ * possible that it won't be copied */
+ CustomData_MeshMasks_update(&mask, &append_mask);
+ if (need_mapping) {
+ mask.vmask |= CD_MASK_ORIGINDEX;
+ mask.emask |= CD_MASK_ORIGINDEX;
+ mask.pmask |= CD_MASK_ORIGINDEX;
+ }
+ mesh_set_only_copy(mesh_final, &mask);
+
+ /* add cloth rest shape key if needed */
+ if (mask.vmask & CD_MASK_CLOTH_ORCO) {
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_CLOTH_ORCO);
+ }
+
+ /* add an origspace layer if needed */
+ if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
+ if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
+ CustomData_add_layer(
+ &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
+ mesh_init_origspace(mesh_final);
+ }
+ }
+
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
+ ASSERT_IS_VALID_MESH(mesh_next);
+
+ if (mesh_next) {
+ /* if the modifier returned a new mesh, release the old one */
+ if (mesh_final != mesh_next) {
+ BLI_assert(mesh_final != mesh_input);
+ BKE_id_free(NULL, mesh_final);
+ }
+ mesh_final = mesh_next;
+
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
+ }
+
+ mesh_copy_autosmooth(mesh_final, mesh_input);
+ }
+
+ /* create an orco mesh in parallel */
+ if (nextmask.vmask & CD_MASK_ORCO) {
+ if (!mesh_orco) {
+ mesh_orco = create_orco_mesh(ob, mesh_input, NULL, CD_ORCO);
+ }
+
+ nextmask.vmask &= ~CD_MASK_ORCO;
+ CustomData_MeshMasks temp_cddata_masks = {
+ .vmask = CD_MASK_ORIGINDEX,
+ .emask = CD_MASK_ORIGINDEX,
+ .fmask = CD_MASK_ORIGINDEX,
+ .pmask = CD_MASK_ORIGINDEX,
+ };
+ if (mti->requiredDataMask != NULL) {
+ mti->requiredDataMask(ob, md, &temp_cddata_masks);
+ }
+ CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask);
+ mesh_set_only_copy(mesh_orco, &temp_cddata_masks);
+
+ mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
+ ASSERT_IS_VALID_MESH(mesh_next);
+
+ if (mesh_next) {
+ /* if the modifier returned a new mesh, release the old one */
+ if (mesh_orco != mesh_next) {
+ BLI_assert(mesh_orco != mesh_input);
+ BKE_id_free(NULL, mesh_orco);
+ }
+
+ mesh_orco = mesh_next;
+ }
+ }
+
+ /* create cloth orco mesh in parallel */
+ if (nextmask.vmask & CD_MASK_CLOTH_ORCO) {
+ if (!mesh_orco_cloth) {
+ mesh_orco_cloth = create_orco_mesh(ob, mesh_input, NULL, CD_CLOTH_ORCO);
+ }
+
+ nextmask.vmask &= ~CD_MASK_CLOTH_ORCO;
+ nextmask.vmask |= CD_MASK_ORIGINDEX;
+ nextmask.emask |= CD_MASK_ORIGINDEX;
+ nextmask.pmask |= CD_MASK_ORIGINDEX;
+ mesh_set_only_copy(mesh_orco_cloth, &nextmask);
+
+ mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco_cloth);
+ ASSERT_IS_VALID_MESH(mesh_next);
+
+ if (mesh_next) {
+ /* if the modifier returned a new mesh, release the old one */
+ if (mesh_orco_cloth != mesh_next) {
+ BLI_assert(mesh_orco != mesh_input);
+ BKE_id_free(NULL, mesh_orco_cloth);
+ }
+
+ mesh_orco_cloth = mesh_next;
+ }
+ }
+
+ /* in case of dynamic paint, make sure preview mask remains for following modifiers */
+ /* XXX Temp and hackish solution! */
+ if (md->type == eModifierType_DynamicPaint) {
+ append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL;
+ }
+
+ mesh_final->runtime.deformed_only = false;
+ }
+
+ isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
+
+ /* grab modifiers until index i */
+ if ((index != -1) && (BLI_findindex(&ob->modifiers, md) >= index))
+ break;
+
+ if (sculpt_mode && md->type == eModifierType_Multires) {
+ multires_applied = true;
+ }
+ }
+
+ BLI_linklist_free((LinkNode *)datamasks, NULL);
+
+ for (md = firstmd; md; md = md->next)
+ modifier_freeTemporaryData(md);
+
+ /* Yay, we are done. If we have a Mesh and deformed vertices
+ * need to apply these back onto the Mesh. If we have no
+ * Mesh then we need to build one. */
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+ }
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
+ }
+
+ /* Add orco coordinates to final and deformed mesh if requested. */
+ if (dataMask->vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
+
+ if (mesh_deform)
+ add_orco_mesh(ob, NULL, mesh_deform, NULL, CD_ORCO);
+ }
+
+ if (mesh_orco) {
+ BKE_id_free(NULL, mesh_orco);
+ }
+ if (mesh_orco_cloth) {
+ BKE_id_free(NULL, mesh_orco_cloth);
+ }
+
+ /* Compute normals. */
+ mesh_calc_modifier_final_normals(mesh_input, dataMask, sculpt_dyntopo, mesh_final);
+
+ /* Return final mesh */
+ *r_final = mesh_final;
+ if (r_deform) {
+ *r_deform = mesh_deform;
+ }
}
-
float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3]
{
- BMIter iter;
- BMVert *eve;
- float (*cos)[3];
- int i;
+ BMIter iter;
+ BMVert *eve;
+ float(*cos)[3];
+ int i;
- *r_numVerts = em->bm->totvert;
+ *r_numVerts = em->bm->totvert;
- cos = MEM_malloc_arrayN(em->bm->totvert, 3 * sizeof(float), "vertexcos");
+ cos = MEM_malloc_arrayN(em->bm->totvert, 3 * sizeof(float), "vertexcos");
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- copy_v3_v3(cos[i], eve->co);
- }
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ copy_v3_v3(cos[i], eve->co);
+ }
- return cos;
+ return cos;
}
bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev_mesh)
{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
-
- if (!modifier_isEnabled(scene, md, required_mode)) {
- return false;
- }
-
- if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) {
- modifier_setError(md, "Modifier requires original data, bad stack position");
- return false;
- }
-
- return true;
-}
-
-static void editbmesh_calc_modifier_final_normals(
- const Mesh *mesh_input,
- const CustomData_MeshMasks *dataMask,
- Mesh *mesh_final)
-{
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
- (dataMask->lmask & CD_MASK_NORMAL) != 0);
- /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well. */
- const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
-
- if (do_loop_normals) {
- /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
- if (do_poly_normals) {
- if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
- CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
- }
- }
- /* Compute loop normals */
- BKE_mesh_calc_normals_split(mesh_final);
- BKE_mesh_tessface_clear(mesh_final);
- }
-
- /* BMESH_ONLY, ensure tessface's used for drawing,
- * but don't recalculate if the last modifier in the stack gives us tessfaces
- * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential
- * but quiets annoying error messages since tessfaces wont be created. */
- if (dataMask->fmask & CD_MASK_MFACE) {
- if (mesh_final->edit_mesh == NULL) {
- BKE_mesh_tessface_ensure(mesh_final);
- }
- }
-
- /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
- if (!do_loop_normals) {
- BKE_mesh_ensure_normals_for_display(mesh_final);
-
- /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
- * as they are used by display code when available (i.e. even if autosmooth is disabled). */
- if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
- CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
- }
- }
-}
-
-static void editbmesh_calc_modifiers(
- struct Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- BMEditMesh *em_input,
- const CustomData_MeshMasks *dataMask,
- /* return args */
- Mesh **r_cage,
- Mesh **r_final)
-{
- /* Input and final mesh. Final mesh is only created the moment the first
- * constructive modifier is executed, or a deform modifier needs normals
- * or certain data layers. */
- Mesh *mesh_input = ob->data;
- Mesh *mesh_final = NULL;
- Mesh *mesh_cage = NULL;
-
- /* Deformed vertex locations array. Deform only modifier need this type of
- * float array rather than MVert*. Tracked along with mesh_final as an
- * optimization to avoid copying coordinates back and forth if there are
- * multiple sequential deform only modifiers. */
- float (*deformed_verts)[3] = NULL;
- int num_deformed_verts = 0;
- bool isPrevDeform = false;
-
- /* Mesh with constructive modifiers but no deformation applied. Tracked
- * along with final mesh if undeformed / orco coordinates are requested
- * for texturing. */
- Mesh *mesh_orco = NULL;
-
- /* Modifier evaluation modes. */
- const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
- const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */
-
- /* Modifier evaluation contexts for different types of modifiers. */
- const ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE};
- const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO};
-
- /* Evaluate modifiers up to certain index to get the mesh cage. */
- int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
- if (r_cage && cageIndex == -1) {
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, NULL);
- mesh_copy_autosmooth(mesh_cage, mesh_input);
- }
-
- /* Get effective list of modifiers to execute. Some effects like shape keys
- * are added as virtual modifiers before the user created modifiers. */
- VirtualModifierData virtualModifierData;
- ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- /* Compute accumulated datamasks needed by each modifier. It helps to do
- * this fine grained so that for example vertex groups are preserved up to
- * an armature modifier, but not through a following subsurf modifier where
- * subdividing them is expensive. */
- CDMaskLink *datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, NULL, NULL);
- CDMaskLink *md_datamask = datamasks;
- CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
-
- /* Clear errors before evaluation. */
- modifiers_clearErrors(ob);
-
- for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) {
- continue;
- }
-
- /* Add an orco layer if needed by this modifier. */
- if (mesh_final && mti->requiredDataMask) {
- CustomData_MeshMasks mask = {0};
- mti->requiredDataMask(ob, md, &mask);
- if (mask.vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
- }
- }
-
- /* How to apply modifier depends on (a) what we already have as
- * a result of previous modifiers (could be a mesh or just
- * deformed vertices) and (b) what type the modifier is. */
- if (mti->type == eModifierTypeType_OnlyDeform) {
- /* No existing verts to deform, need to build them. */
- if (!deformed_verts) {
- if (mesh_final) {
- /* Deforming a derived mesh, read the vertex locations
- * out of the mesh and deform them. Once done with this
- * run of deformers verts will be written back. */
- deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
- }
- else {
- deformed_verts = editbmesh_get_vertex_cos(em_input, &num_deformed_verts);
- }
- }
- else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- if (mesh_final == NULL) {
- mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
- ASSERT_IS_VALID_MESH(mesh_final);
- mesh_copy_autosmooth(mesh_final, mesh_input);
- }
- BLI_assert(deformed_verts != NULL);
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
-
- if (mti->deformVertsEM)
- modwrap_deformVertsEM(md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts);
- else
- modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
- }
- else {
- /* apply vertex coordinates or build a DerivedMesh as necessary */
- if (mesh_final) {
- if (deformed_verts) {
- Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
- if (mesh_final != mesh_cage) {
- BKE_id_free(NULL, mesh_final);
- }
- mesh_final = mesh_tmp;
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
- else if (mesh_final == mesh_cage) {
- /* 'me' may be changed by this modifier, so we need to copy it. */
- mesh_final = BKE_mesh_copy_for_eval(mesh_final, false);
- }
-
- }
- else {
- mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
- ASSERT_IS_VALID_MESH(mesh_final);
-
- mesh_copy_autosmooth(mesh_final, mesh_input);
-
- if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
- }
-
- /* create an orco derivedmesh in parallel */
- CustomData_MeshMasks mask = md_datamask->mask;
- if (mask.vmask & CD_MASK_ORCO) {
- if (!mesh_orco) {
- mesh_orco = create_orco_mesh(ob, mesh_input, em_input, CD_ORCO);
- }
-
- mask.vmask &= ~CD_MASK_ORCO;
- mask.vmask |= CD_MASK_ORIGINDEX;
- mask.emask |= CD_MASK_ORIGINDEX;
- mask.pmask |= CD_MASK_ORIGINDEX;
- mesh_set_only_copy(mesh_orco, &mask);
-
- Mesh *mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
- ASSERT_IS_VALID_MESH(mesh_next);
-
- if (mesh_next) {
- /* if the modifier returned a new dm, release the old one */
- if (mesh_orco && mesh_orco != mesh_next) {
- BKE_id_free(NULL, mesh_orco);
- }
- mesh_orco = mesh_next;
- }
- }
-
- /* set the DerivedMesh to only copy needed data */
- CustomData_MeshMasks_update(&mask, &append_mask);
- /* XXX WHAT? ovewrites mask ??? */
- /* CD_MASK_ORCO may have been cleared above */
- mask = md_datamask->mask;
- mask.vmask |= CD_MASK_ORIGINDEX;
- mask.emask |= CD_MASK_ORIGINDEX;
- mask.pmask |= CD_MASK_ORIGINDEX;
-
- mesh_set_only_copy(mesh_final, &mask);
-
- if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
- if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
- CustomData_add_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
- mesh_init_origspace(mesh_final);
- }
- }
-
- Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
- ASSERT_IS_VALID_MESH(mesh_next);
-
- if (mesh_next) {
- if (mesh_final && mesh_final != mesh_next) {
- BKE_id_free(NULL, mesh_final);
- }
- mesh_final = mesh_next;
-
- if (deformed_verts) {
- MEM_freeN(deformed_verts);
- deformed_verts = NULL;
- }
-
- mesh_copy_autosmooth(mesh_final, mesh_input);
- }
- mesh_final->runtime.deformed_only = false;
- }
-
- if (r_cage && i == cageIndex) {
- if (mesh_final && deformed_verts) {
- mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false);
- BKE_mesh_apply_vert_coords(mesh_cage, deformed_verts);
- }
- else if (mesh_final) {
- mesh_cage = mesh_final;
- }
- else {
- Mesh *me_orig = mesh_input;
- if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) {
- BKE_mesh_runtime_ensure_edit_data(me_orig);
- me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts);
- }
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
- em_input, dataMask,
- deformed_verts ? MEM_dupallocN(deformed_verts) : NULL);
- mesh_copy_autosmooth(mesh_cage, mesh_input);
- }
- }
-
- isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
- }
-
- BLI_linklist_free((LinkNode *)datamasks, NULL);
-
- /* Yay, we are done. If we have a DerivedMesh and deformed vertices need
- * to apply these back onto the DerivedMesh. If we have no DerivedMesh
- * then we need to build one. */
- if (mesh_final) {
- if (deformed_verts) {
- Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
- if (mesh_final != mesh_cage) {
- BKE_id_free(NULL, mesh_final);
- }
- mesh_final = mesh_tmp;
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
- }
- }
- else if (!deformed_verts && mesh_cage) {
- /* cage should already have up to date normals */
- mesh_final = mesh_cage;
-
- /* In this case, we should never have weight-modifying modifiers in stack... */
- if (do_init_statvis) {
- editmesh_update_statvis_color(scene, ob);
- }
- }
- else {
- /* this is just a copy of the editmesh, no need to calc normals */
- mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, deformed_verts);
- deformed_verts = NULL;
-
- mesh_copy_autosmooth(mesh_final, mesh_input);
-
- /* In this case, we should never have weight-modifying modifiers in stack... */
- if (do_init_statvis) {
- editmesh_update_statvis_color(scene, ob);
- }
- }
-
- if (deformed_verts) {
- MEM_freeN(deformed_verts);
- }
-
- /* Add orco coordinates to final and deformed mesh if requested. */
- if (dataMask->vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
- }
-
- if (mesh_orco) {
- BKE_id_free(NULL, mesh_orco);
- }
-
- /* Compute normals. */
- editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_final);
- if (mesh_cage && (mesh_cage != mesh_final)) {
- editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_cage);
- }
-
- /* Return final mesh. */
- *r_final = mesh_final;
- if (r_cage) {
- *r_cage = mesh_cage;
- }
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+
+ if (!modifier_isEnabled(scene, md, required_mode)) {
+ return false;
+ }
+
+ if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) {
+ modifier_setError(md, "Modifier requires original data, bad stack position");
+ return false;
+ }
+
+ return true;
+}
+
+static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input,
+ const CustomData_MeshMasks *dataMask,
+ Mesh *mesh_final)
+{
+ const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (dataMask->lmask & CD_MASK_NORMAL) != 0);
+ /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well. */
+ const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+
+ if (do_loop_normals) {
+ /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
+ if (do_poly_normals) {
+ if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
+ CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
+ }
+ }
+ /* Compute loop normals */
+ BKE_mesh_calc_normals_split(mesh_final);
+ BKE_mesh_tessface_clear(mesh_final);
+ }
+
+ /* BMESH_ONLY, ensure tessface's used for drawing,
+ * but don't recalculate if the last modifier in the stack gives us tessfaces
+ * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential
+ * but quiets annoying error messages since tessfaces wont be created. */
+ if (dataMask->fmask & CD_MASK_MFACE) {
+ if (mesh_final->edit_mesh == NULL) {
+ BKE_mesh_tessface_ensure(mesh_final);
+ }
+ }
+
+ /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
+ if (!do_loop_normals) {
+ BKE_mesh_ensure_normals_for_display(mesh_final);
+
+ /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
+ CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
+ }
+ }
+}
+
+static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ BMEditMesh *em_input,
+ const CustomData_MeshMasks *dataMask,
+ /* return args */
+ Mesh **r_cage,
+ Mesh **r_final)
+{
+ /* Input and final mesh. Final mesh is only created the moment the first
+ * constructive modifier is executed, or a deform modifier needs normals
+ * or certain data layers. */
+ Mesh *mesh_input = ob->data;
+ Mesh *mesh_final = NULL;
+ Mesh *mesh_cage = NULL;
+
+ /* Deformed vertex locations array. Deform only modifier need this type of
+ * float array rather than MVert*. Tracked along with mesh_final as an
+ * optimization to avoid copying coordinates back and forth if there are
+ * multiple sequential deform only modifiers. */
+ float(*deformed_verts)[3] = NULL;
+ int num_deformed_verts = 0;
+ bool isPrevDeform = false;
+
+ /* Mesh with constructive modifiers but no deformation applied. Tracked
+ * along with final mesh if undeformed / orco coordinates are requested
+ * for texturing. */
+ Mesh *mesh_orco = NULL;
+
+ /* Modifier evaluation modes. */
+ const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+ const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */
+
+ /* Modifier evaluation contexts for different types of modifiers. */
+ const ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE};
+ const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO};
+
+ /* Evaluate modifiers up to certain index to get the mesh cage. */
+ int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
+ if (r_cage && cageIndex == -1) {
+ mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, NULL);
+ mesh_copy_autosmooth(mesh_cage, mesh_input);
+ }
+
+ /* Get effective list of modifiers to execute. Some effects like shape keys
+ * are added as virtual modifiers before the user created modifiers. */
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+
+ /* Compute accumulated datamasks needed by each modifier. It helps to do
+ * this fine grained so that for example vertex groups are preserved up to
+ * an armature modifier, but not through a following subsurf modifier where
+ * subdividing them is expensive. */
+ CDMaskLink *datamasks = modifiers_calcDataMasks(
+ scene, ob, md, dataMask, required_mode, NULL, NULL);
+ CDMaskLink *md_datamask = datamasks;
+ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
+
+ /* Clear errors before evaluation. */
+ modifiers_clearErrors(ob);
+
+ for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) {
+ continue;
+ }
+
+ /* Add an orco layer if needed by this modifier. */
+ if (mesh_final && mti->requiredDataMask) {
+ CustomData_MeshMasks mask = {0};
+ mti->requiredDataMask(ob, md, &mask);
+ if (mask.vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
+ }
+ }
+
+ /* How to apply modifier depends on (a) what we already have as
+ * a result of previous modifiers (could be a mesh or just
+ * deformed vertices) and (b) what type the modifier is. */
+ if (mti->type == eModifierTypeType_OnlyDeform) {
+ /* No existing verts to deform, need to build them. */
+ if (!deformed_verts) {
+ if (mesh_final) {
+ /* Deforming a derived mesh, read the vertex locations
+ * out of the mesh and deform them. Once done with this
+ * run of deformers verts will be written back. */
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
+ }
+ else {
+ deformed_verts = editbmesh_get_vertex_cos(em_input, &num_deformed_verts);
+ }
+ }
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
+ ASSERT_IS_VALID_MESH(mesh_final);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
+ }
+ BLI_assert(deformed_verts != NULL);
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+
+ if (mti->deformVertsEM)
+ modwrap_deformVertsEM(
+ md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts);
+ else
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
+ }
+ else {
+ /* apply vertex coordinates or build a DerivedMesh as necessary */
+ if (mesh_final) {
+ if (deformed_verts) {
+ Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
+ if (mesh_final != mesh_cage) {
+ BKE_id_free(NULL, mesh_final);
+ }
+ mesh_final = mesh_tmp;
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+ else if (mesh_final == mesh_cage) {
+ /* 'me' may be changed by this modifier, so we need to copy it. */
+ mesh_final = BKE_mesh_copy_for_eval(mesh_final, false);
+ }
+ }
+ else {
+ mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
+ ASSERT_IS_VALID_MESH(mesh_final);
+
+ mesh_copy_autosmooth(mesh_final, mesh_input);
+
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+ }
+
+ /* create an orco derivedmesh in parallel */
+ CustomData_MeshMasks mask = md_datamask->mask;
+ if (mask.vmask & CD_MASK_ORCO) {
+ if (!mesh_orco) {
+ mesh_orco = create_orco_mesh(ob, mesh_input, em_input, CD_ORCO);
+ }
+
+ mask.vmask &= ~CD_MASK_ORCO;
+ mask.vmask |= CD_MASK_ORIGINDEX;
+ mask.emask |= CD_MASK_ORIGINDEX;
+ mask.pmask |= CD_MASK_ORIGINDEX;
+ mesh_set_only_copy(mesh_orco, &mask);
+
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
+ ASSERT_IS_VALID_MESH(mesh_next);
+
+ if (mesh_next) {
+ /* if the modifier returned a new dm, release the old one */
+ if (mesh_orco && mesh_orco != mesh_next) {
+ BKE_id_free(NULL, mesh_orco);
+ }
+ mesh_orco = mesh_next;
+ }
+ }
+
+ /* set the DerivedMesh to only copy needed data */
+ CustomData_MeshMasks_update(&mask, &append_mask);
+ /* XXX WHAT? ovewrites mask ??? */
+ /* CD_MASK_ORCO may have been cleared above */
+ mask = md_datamask->mask;
+ mask.vmask |= CD_MASK_ORIGINDEX;
+ mask.emask |= CD_MASK_ORIGINDEX;
+ mask.pmask |= CD_MASK_ORIGINDEX;
+
+ mesh_set_only_copy(mesh_final, &mask);
+
+ if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
+ if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
+ CustomData_add_layer(
+ &mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
+ mesh_init_origspace(mesh_final);
+ }
+ }
+
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
+ ASSERT_IS_VALID_MESH(mesh_next);
+
+ if (mesh_next) {
+ if (mesh_final && mesh_final != mesh_next) {
+ BKE_id_free(NULL, mesh_final);
+ }
+ mesh_final = mesh_next;
+
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
+ }
+
+ mesh_copy_autosmooth(mesh_final, mesh_input);
+ }
+ mesh_final->runtime.deformed_only = false;
+ }
+
+ if (r_cage && i == cageIndex) {
+ if (mesh_final && deformed_verts) {
+ mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false);
+ BKE_mesh_apply_vert_coords(mesh_cage, deformed_verts);
+ }
+ else if (mesh_final) {
+ mesh_cage = mesh_final;
+ }
+ else {
+ Mesh *me_orig = mesh_input;
+ if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) {
+ BKE_mesh_runtime_ensure_edit_data(me_orig);
+ me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts);
+ }
+ mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ em_input, dataMask, deformed_verts ? MEM_dupallocN(deformed_verts) : NULL);
+ mesh_copy_autosmooth(mesh_cage, mesh_input);
+ }
+ }
+
+ isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
+ }
+
+ BLI_linklist_free((LinkNode *)datamasks, NULL);
+
+ /* Yay, we are done. If we have a DerivedMesh and deformed vertices need
+ * to apply these back onto the DerivedMesh. If we have no DerivedMesh
+ * then we need to build one. */
+ if (mesh_final) {
+ if (deformed_verts) {
+ Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
+ if (mesh_final != mesh_cage) {
+ BKE_id_free(NULL, mesh_final);
+ }
+ mesh_final = mesh_tmp;
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ }
+ }
+ else if (!deformed_verts && mesh_cage) {
+ /* cage should already have up to date normals */
+ mesh_final = mesh_cage;
+
+ /* In this case, we should never have weight-modifying modifiers in stack... */
+ if (do_init_statvis) {
+ editmesh_update_statvis_color(scene, ob);
+ }
+ }
+ else {
+ /* this is just a copy of the editmesh, no need to calc normals */
+ mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, deformed_verts);
+ deformed_verts = NULL;
+
+ mesh_copy_autosmooth(mesh_final, mesh_input);
+
+ /* In this case, we should never have weight-modifying modifiers in stack... */
+ if (do_init_statvis) {
+ editmesh_update_statvis_color(scene, ob);
+ }
+ }
+
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
+ }
+
+ /* Add orco coordinates to final and deformed mesh if requested. */
+ if (dataMask->vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
+ }
+
+ if (mesh_orco) {
+ BKE_id_free(NULL, mesh_orco);
+ }
+
+ /* Compute normals. */
+ editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_final);
+ if (mesh_cage && (mesh_cage != mesh_final)) {
+ editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_cage);
+ }
+
+ /* Return final mesh. */
+ *r_final = mesh_final;
+ if (r_cage) {
+ *r_cage = mesh_cage;
+ }
}
static void mesh_finalize_eval(Object *object)
{
- Mesh *mesh = (Mesh *)object->data;
- Mesh *mesh_eval = object->runtime.mesh_eval;
- /* Special Tweaks for cases when evaluated mesh came from
- * BKE_mesh_new_nomain_from_template().
- */
- BLI_strncpy(mesh_eval->id.name, mesh->id.name, sizeof(mesh_eval->id.name));
- if (mesh_eval->mat != NULL) {
- MEM_freeN(mesh_eval->mat);
- }
- /* Set flag which makes it easier to see what's going on in a debugger. */
- mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
- mesh_eval->mat = MEM_dupallocN(mesh->mat);
- mesh_eval->totcol = mesh->totcol;
- /* Make evaluated mesh to share same edit mesh pointer as original
- * and copied meshes.
- */
- mesh_eval->edit_mesh = mesh->edit_mesh;
- /* Copy autosmooth settings from original mesh.
- * This is not done by BKE_mesh_new_nomain_from_template(), so need to take
- * extra care here.
- */
- mesh_eval->flag |= (mesh->flag & ME_AUTOSMOOTH);
- mesh_eval->smoothresh = mesh->smoothresh;
- /* Replace evaluated object's data with fully evaluated mesh. */
- /* TODO(sergey): There was statement done by Sybren and Mai that this
- * caused modifiers to be applied twice. which is weirtd and shouldn't
- * really happen. But since there is no reference to the report, can not
- * do much about this.
- */
-
- /* Object is sometimes not evaluated!
- * TODO(sergey): BAD TEMPORARY HACK FOR UNTIL WE ARE SMARTER */
- if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) {
- object->data = mesh_eval;
- }
- else {
- /* evaluated will be available via: 'object->runtime.mesh_eval' */
- }
+ Mesh *mesh = (Mesh *)object->data;
+ Mesh *mesh_eval = object->runtime.mesh_eval;
+ /* Special Tweaks for cases when evaluated mesh came from
+ * BKE_mesh_new_nomain_from_template().
+ */
+ BLI_strncpy(mesh_eval->id.name, mesh->id.name, sizeof(mesh_eval->id.name));
+ if (mesh_eval->mat != NULL) {
+ MEM_freeN(mesh_eval->mat);
+ }
+ /* Set flag which makes it easier to see what's going on in a debugger. */
+ mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
+ mesh_eval->mat = MEM_dupallocN(mesh->mat);
+ mesh_eval->totcol = mesh->totcol;
+ /* Make evaluated mesh to share same edit mesh pointer as original
+ * and copied meshes.
+ */
+ mesh_eval->edit_mesh = mesh->edit_mesh;
+ /* Copy autosmooth settings from original mesh.
+ * This is not done by BKE_mesh_new_nomain_from_template(), so need to take
+ * extra care here.
+ */
+ mesh_eval->flag |= (mesh->flag & ME_AUTOSMOOTH);
+ mesh_eval->smoothresh = mesh->smoothresh;
+ /* Replace evaluated object's data with fully evaluated mesh. */
+ /* TODO(sergey): There was statement done by Sybren and Mai that this
+ * caused modifiers to be applied twice. which is weirtd and shouldn't
+ * really happen. But since there is no reference to the report, can not
+ * do much about this.
+ */
+
+ /* Object is sometimes not evaluated!
+ * TODO(sergey): BAD TEMPORARY HACK FOR UNTIL WE ARE SMARTER */
+ if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) {
+ object->data = mesh_eval;
+ }
+ else {
+ /* evaluated will be available via: 'object->runtime.mesh_eval' */
+ }
}
static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob)
{
- uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id);
+ uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id);
- if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) {
- BKE_shrinkwrap_compute_boundary_data(ob->runtime.mesh_eval);
- }
+ if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) {
+ BKE_shrinkwrap_compute_boundary_data(ob->runtime.mesh_eval);
+ }
}
static void mesh_runtime_check_normals_valid(const Mesh *mesh)
{
- UNUSED_VARS_NDEBUG(mesh);
- BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL));
- BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL));
- BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL));
+ UNUSED_VARS_NDEBUG(mesh);
+ BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL));
+ BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL));
+ BLI_assert(!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL));
}
-static void mesh_build_data(
- struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask,
- const bool need_mapping)
+static void mesh_build_data(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask,
+ const bool need_mapping)
{
- BLI_assert(ob->type == OB_MESH);
+ BLI_assert(ob->type == OB_MESH);
- /* Evaluated meshes aren't supposed to be created on original instances. If you do,
- * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
- BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ /* Evaluated meshes aren't supposed to be created on original instances. If you do,
+ * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
+ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
- BKE_object_free_derived_caches(ob);
- BKE_object_sculpt_modifiers_changed(ob);
+ BKE_object_free_derived_caches(ob);
+ BKE_object_sculpt_modifiers_changed(ob);
#if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */
- if (need_mapping) {
- /* Also add the flag so that it is recorded in lastDataMask. */
- dataMask->vmask |= CD_MASK_ORIGINDEX;
- dataMask->emask |= CD_MASK_ORIGINDEX;
- dataMask->pmask |= CD_MASK_ORIGINDEX;
- }
+ if (need_mapping) {
+ /* Also add the flag so that it is recorded in lastDataMask. */
+ dataMask->vmask |= CD_MASK_ORIGINDEX;
+ dataMask->emask |= CD_MASK_ORIGINDEX;
+ dataMask->pmask |= CD_MASK_ORIGINDEX;
+ }
#endif
- mesh_calc_modifiers(
- depsgraph, scene, ob, 1, need_mapping, dataMask, -1, true,
- &ob->runtime.mesh_deform_eval, &ob->runtime.mesh_eval);
+ mesh_calc_modifiers(depsgraph,
+ scene,
+ ob,
+ 1,
+ need_mapping,
+ dataMask,
+ -1,
+ true,
+ &ob->runtime.mesh_deform_eval,
+ &ob->runtime.mesh_eval);
- BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval);
- /* Only copy texspace from orig mesh if some modifier (hint: smoke sim, see T58492)
- * did not re-enable that flag (which always get disabled for eval mesh as a start). */
- if (!(ob->runtime.mesh_eval->texflag & ME_AUTOSPACE)) {
- BKE_mesh_texspace_copy_from_object(ob->runtime.mesh_eval, ob);
- }
+ BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval);
+ /* Only copy texspace from orig mesh if some modifier (hint: smoke sim, see T58492)
+ * did not re-enable that flag (which always get disabled for eval mesh as a start). */
+ if (!(ob->runtime.mesh_eval->texflag & ME_AUTOSPACE)) {
+ BKE_mesh_texspace_copy_from_object(ob->runtime.mesh_eval, ob);
+ }
- mesh_finalize_eval(ob);
+ mesh_finalize_eval(ob);
- ob->runtime.last_data_mask = *dataMask;
- ob->runtime.last_need_mapping = need_mapping;
+ ob->runtime.last_data_mask = *dataMask;
+ ob->runtime.last_need_mapping = need_mapping;
- if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
- /* create PBVH immediately (would be created on the fly too,
- * but this avoids waiting on first stroke) */
- /* XXX Disabled for now.
- * This can create horrible nasty bugs by generating re-entrant call of mesh_get_eval_final! */
-// BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
- }
+ if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
+ /* create PBVH immediately (would be created on the fly too,
+ * but this avoids waiting on first stroke) */
+ /* XXX Disabled for now.
+ * This can create horrible nasty bugs by generating re-entrant call of mesh_get_eval_final! */
+ // BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
+ }
- mesh_runtime_check_normals_valid(ob->runtime.mesh_eval);
- mesh_build_extra_data(depsgraph, ob);
+ mesh_runtime_check_normals_valid(ob->runtime.mesh_eval);
+ mesh_build_extra_data(depsgraph, ob);
}
-static void editbmesh_build_data(
- struct Depsgraph *depsgraph, Scene *scene,
- Object *obedit, BMEditMesh *em, CustomData_MeshMasks *dataMask)
+static void editbmesh_build_data(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *obedit,
+ BMEditMesh *em,
+ CustomData_MeshMasks *dataMask)
{
- BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
- BKE_object_free_derived_caches(obedit);
- BKE_object_sculpt_modifiers_changed(obedit);
+ BKE_object_free_derived_caches(obedit);
+ BKE_object_sculpt_modifiers_changed(obedit);
- BKE_editmesh_free_derivedmesh(em);
+ BKE_editmesh_free_derivedmesh(em);
- Mesh *me_cage;
- Mesh *me_final;
+ Mesh *me_cage;
+ Mesh *me_final;
- editbmesh_calc_modifiers(
- depsgraph, scene, obedit, em, dataMask,
- &me_cage, &me_final);
+ editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final);
- em->mesh_eval_final = me_final;
- em->mesh_eval_cage = me_cage;
+ em->mesh_eval_final = me_final;
+ em->mesh_eval_cage = me_cage;
- BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final);
+ BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final);
- em->lastDataMask = *dataMask;
+ em->lastDataMask = *dataMask;
- mesh_runtime_check_normals_valid(em->mesh_eval_final);
+ mesh_runtime_check_normals_valid(em->mesh_eval_final);
}
-static void object_get_datamask(const Depsgraph *depsgraph, Object *ob, CustomData_MeshMasks *r_mask, bool *r_need_mapping)
+static void object_get_datamask(const Depsgraph *depsgraph,
+ Object *ob,
+ CustomData_MeshMasks *r_mask,
+ bool *r_need_mapping)
{
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
- Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL;
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL;
- DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask);
+ DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask);
- if (r_need_mapping) {
- *r_need_mapping = false;
- }
+ if (r_need_mapping) {
+ *r_need_mapping = false;
+ }
- if (DEG_get_original_object(ob) == actob) {
- bool editing = BKE_paint_select_face_test(actob);
+ if (DEG_get_original_object(ob) == actob) {
+ bool editing = BKE_paint_select_face_test(actob);
- /* weight paint and face select need original indices because of selection buffer drawing */
- if (r_need_mapping) {
- *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)));
- }
+ /* weight paint and face select need original indices because of selection buffer drawing */
+ if (r_need_mapping) {
+ *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)));
+ }
- /* check if we need tfaces & mcols due to face select or texture paint */
- if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) {
- r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
- r_mask->fmask |= CD_MASK_MTFACE;
- }
+ /* check if we need tfaces & mcols due to face select or texture paint */
+ if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) {
+ r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+ r_mask->fmask |= CD_MASK_MTFACE;
+ }
- /* check if we need mcols due to vertex paint or weightpaint */
- if (ob->mode & OB_MODE_VERTEX_PAINT) {
- r_mask->lmask |= CD_MASK_MLOOPCOL;
- }
+ /* check if we need mcols due to vertex paint or weightpaint */
+ if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ r_mask->lmask |= CD_MASK_MLOOPCOL;
+ }
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- r_mask->vmask |= CD_MASK_MDEFORMVERT;
- }
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ r_mask->vmask |= CD_MASK_MDEFORMVERT;
+ }
- if (ob->mode & OB_MODE_EDIT)
- r_mask->vmask |= CD_MASK_MVERT_SKIN;
- }
+ if (ob->mode & OB_MODE_EDIT)
+ r_mask->vmask |= CD_MASK_MVERT_SKIN;
+ }
}
-void makeDerivedMesh(
- struct Depsgraph *depsgraph, Scene *scene, Object *ob, BMEditMesh *em,
- const CustomData_MeshMasks *dataMask)
+void makeDerivedMesh(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ BMEditMesh *em,
+ const CustomData_MeshMasks *dataMask)
{
- bool need_mapping;
- CustomData_MeshMasks cddata_masks = *dataMask;
- object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
+ bool need_mapping;
+ CustomData_MeshMasks cddata_masks = *dataMask;
+ object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
- if (em) {
- editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks);
- }
- else {
- mesh_build_data(depsgraph, scene, ob, &cddata_masks, need_mapping);
- }
+ if (em) {
+ editbmesh_build_data(depsgraph, scene, ob, em, &cddata_masks);
+ }
+ else {
+ mesh_build_data(depsgraph, scene, ob, &cddata_masks, need_mapping);
+ }
}
/***/
-Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
+Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- /* This function isn't thread-safe and can't be used during evaluation. */
- BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
+ /* This function isn't thread-safe and can't be used during evaluation. */
+ BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
- /* Evaluated meshes aren't supposed to be created on original instances. If you do,
- * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
- BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ /* Evaluated meshes aren't supposed to be created on original instances. If you do,
+ * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
+ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
- /* if there's no evaluated mesh or the last data mask used doesn't include
- * the data we need, rebuild the derived mesh
- */
- bool need_mapping;
- CustomData_MeshMasks cddata_masks = *dataMask;
- object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
+ /* if there's no evaluated mesh or the last data mask used doesn't include
+ * the data we need, rebuild the derived mesh
+ */
+ bool need_mapping;
+ CustomData_MeshMasks cddata_masks = *dataMask;
+ object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
- if (!ob->runtime.mesh_eval ||
- !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) ||
- (need_mapping && !ob->runtime.last_need_mapping))
- {
- CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask);
- mesh_build_data(depsgraph, scene, ob, &cddata_masks,
- need_mapping || ob->runtime.last_need_mapping);
- }
+ if (!ob->runtime.mesh_eval ||
+ !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) ||
+ (need_mapping && !ob->runtime.last_need_mapping)) {
+ CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask);
+ mesh_build_data(
+ depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping);
+ }
- if (ob->runtime.mesh_eval) { BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); }
- return ob->runtime.mesh_eval;
+ if (ob->runtime.mesh_eval) {
+ BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL));
+ }
+ return ob->runtime.mesh_eval;
}
-Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
+Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- /* This function isn't thread-safe and can't be used during evaluation. */
- BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
+ /* This function isn't thread-safe and can't be used during evaluation. */
+ BLI_assert(DEG_debug_is_evaluating(depsgraph) == false);
- /* Evaluated meshes aren't supposed to be created on original instances. If you do,
- * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
- BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ /* Evaluated meshes aren't supposed to be created on original instances. If you do,
+ * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */
+ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
- /* if there's no derived mesh or the last data mask used doesn't include
- * the data we need, rebuild the derived mesh
- */
- bool need_mapping;
+ /* if there's no derived mesh or the last data mask used doesn't include
+ * the data we need, rebuild the derived mesh
+ */
+ bool need_mapping;
- CustomData_MeshMasks cddata_masks = *dataMask;
- object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
+ CustomData_MeshMasks cddata_masks = *dataMask;
+ object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping);
- if (!ob->runtime.mesh_deform_eval ||
- !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) ||
- (need_mapping && !ob->runtime.last_need_mapping))
- {
- CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask);
- mesh_build_data(depsgraph, scene, ob, &cddata_masks,
- need_mapping || ob->runtime.last_need_mapping);
- }
+ if (!ob->runtime.mesh_deform_eval ||
+ !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) ||
+ (need_mapping && !ob->runtime.last_need_mapping)) {
+ CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask);
+ mesh_build_data(
+ depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping);
+ }
- return ob->runtime.mesh_deform_eval;
+ return ob->runtime.mesh_deform_eval;
}
-
-Mesh *mesh_create_eval_final_render(Depsgraph *depsgraph, Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
+Mesh *mesh_create_eval_final_render(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
+ Mesh *final;
- mesh_calc_modifiers(
- depsgraph, scene, ob, 1, false, dataMask, -1, false,
- NULL, &final);
+ mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, NULL, &final);
- return final;
+ return final;
}
-Mesh *mesh_create_eval_final_index_render(
- Depsgraph *depsgraph, Scene *scene,
- Object *ob, const CustomData_MeshMasks *dataMask, int index)
+Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask,
+ int index)
{
- Mesh *final;
+ Mesh *final;
- mesh_calc_modifiers(
- depsgraph, scene, ob, 1, false, dataMask, index, false,
- NULL, &final);
+ mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, index, false, NULL, &final);
- return final;
+ return final;
}
-Mesh *mesh_create_eval_final_view(
- Depsgraph *depsgraph, Scene *scene,
- Object *ob, const CustomData_MeshMasks *dataMask)
+Mesh *mesh_create_eval_final_view(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
+ Mesh *final;
- /* XXX hack
- * psys modifier updates particle state when called during dupli-list generation,
- * which can lead to wrong transforms. This disables particle system modifier execution.
- */
- ob->transflag |= OB_NO_PSYS_UPDATE;
+ /* XXX hack
+ * psys modifier updates particle state when called during dupli-list generation,
+ * which can lead to wrong transforms. This disables particle system modifier execution.
+ */
+ ob->transflag |= OB_NO_PSYS_UPDATE;
- mesh_calc_modifiers(
- depsgraph, scene, ob, 1, false, dataMask, -1, false,
- NULL, &final);
+ mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, NULL, &final);
- ob->transflag &= ~OB_NO_PSYS_UPDATE;
+ ob->transflag &= ~OB_NO_PSYS_UPDATE;
- return final;
+ return final;
}
-Mesh *mesh_create_eval_no_deform(
- Depsgraph *depsgraph, Scene *scene, Object *ob,
- const CustomData_MeshMasks *dataMask)
+Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
+ Mesh *final;
- mesh_calc_modifiers(
- depsgraph, scene, ob, 0, false, dataMask, -1, false,
- NULL, &final);
+ mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, NULL, &final);
- return final;
+ return final;
}
-Mesh *mesh_create_eval_no_deform_render(
- Depsgraph *depsgraph, Scene *scene, Object *ob,
- const CustomData_MeshMasks *dataMask)
+Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ const CustomData_MeshMasks *dataMask)
{
- Mesh *final;
+ Mesh *final;
- mesh_calc_modifiers(
- depsgraph, scene, ob, 0, false, dataMask, -1, false,
- NULL, &final);
+ mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, NULL, &final);
- return final;
+ return final;
}
/***/
-Mesh *editbmesh_get_eval_cage_and_final(
- Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em,
- const CustomData_MeshMasks *dataMask,
- /* return args */
- Mesh **r_final)
+Mesh *editbmesh_get_eval_cage_and_final(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *obedit,
+ BMEditMesh *em,
+ const CustomData_MeshMasks *dataMask,
+ /* return args */
+ Mesh **r_final)
{
- CustomData_MeshMasks cddata_masks = *dataMask;
+ CustomData_MeshMasks cddata_masks = *dataMask;
- /* if there's no derived mesh or the last data mask used doesn't include
- * the data we need, rebuild the derived mesh
- */
- object_get_datamask(depsgraph, obedit, &cddata_masks, NULL);
+ /* if there's no derived mesh or the last data mask used doesn't include
+ * the data we need, rebuild the derived mesh
+ */
+ object_get_datamask(depsgraph, obedit, &cddata_masks, NULL);
- if (!em->mesh_eval_cage ||
- !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks))
- {
- editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks);
- }
+ if (!em->mesh_eval_cage ||
+ !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) {
+ editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks);
+ }
- *r_final = em->mesh_eval_final;
- if (em->mesh_eval_final) { BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS)); }
- return em->mesh_eval_cage;
+ *r_final = em->mesh_eval_final;
+ if (em->mesh_eval_final) {
+ BLI_assert(!(em->mesh_eval_final->runtime.cd_dirty_vert & DM_DIRTY_NORMALS));
+ }
+ return em->mesh_eval_cage;
}
-Mesh *editbmesh_get_eval_cage(
- struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em,
- const CustomData_MeshMasks *dataMask)
+Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *obedit,
+ BMEditMesh *em,
+ const CustomData_MeshMasks *dataMask)
{
- CustomData_MeshMasks cddata_masks = *dataMask;
+ CustomData_MeshMasks cddata_masks = *dataMask;
- /* if there's no derived mesh or the last data mask used doesn't include
- * the data we need, rebuild the derived mesh
- */
- object_get_datamask(depsgraph, obedit, &cddata_masks, NULL);
+ /* if there's no derived mesh or the last data mask used doesn't include
+ * the data we need, rebuild the derived mesh
+ */
+ object_get_datamask(depsgraph, obedit, &cddata_masks, NULL);
- if (!em->mesh_eval_cage ||
- !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks))
- {
- editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks);
- }
+ if (!em->mesh_eval_cage ||
+ !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) {
+ editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks);
+ }
- return em->mesh_eval_cage;
+ return em->mesh_eval_cage;
}
-Mesh *editbmesh_get_eval_cage_from_orig(
- struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *UNUSED(em),
- const CustomData_MeshMasks *dataMask)
+Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *obedit,
+ BMEditMesh *UNUSED(em),
+ const CustomData_MeshMasks *dataMask)
{
- BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0);
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
- Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id);
- BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
- return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask);
+ BLI_assert((obedit->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0);
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+ Object *obedit_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obedit->id);
+ BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
+ return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask);
}
/***/
/* same as above but for vert coords */
typedef struct {
- float (*vertexcos)[3];
- BLI_bitmap *vertex_visit;
+ float (*vertexcos)[3];
+ BLI_bitmap *vertex_visit;
} MappedUserData;
-static void make_vertexcos__mapFunc(
- void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void make_vertexcos__mapFunc(void *userData,
+ int index,
+ const float co[3],
+ const float UNUSED(no_f[3]),
+ const short UNUSED(no_s[3]))
{
- MappedUserData *mappedData = (MappedUserData *)userData;
+ MappedUserData *mappedData = (MappedUserData *)userData;
- if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
- /* we need coord from prototype vertex, not from copies,
- * assume they stored in the beginning of vertex array stored in DM
- * (mirror modifier for eg does this) */
- copy_v3_v3(mappedData->vertexcos[index], co);
- BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
- }
+ if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
+ /* we need coord from prototype vertex, not from copies,
+ * assume they stored in the beginning of vertex array stored in DM
+ * (mirror modifier for eg does this) */
+ copy_v3_v3(mappedData->vertexcos[index], co);
+ BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
+ }
}
void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int totcos)
{
- if (me_eval->runtime.deformed_only == false) {
- MappedUserData userData;
- memset(r_cos, 0, sizeof(*r_cos) * totcos);
- userData.vertexcos = r_cos;
- userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags");
- BKE_mesh_foreach_mapped_vert(me_eval, make_vertexcos__mapFunc, &userData, MESH_FOREACH_NOP);
- MEM_freeN(userData.vertex_visit);
- }
- else {
- MVert *mv = me_eval->mvert;
- for (int i = 0; i < totcos; i++, mv++) {
- copy_v3_v3(r_cos[i], mv->co);
- }
- }
-}
-
-void DM_calc_loop_tangents(
- DerivedMesh *dm, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_len)
-{
- BKE_mesh_calc_loop_tangent_ex(
- dm->getVertArray(dm),
- dm->getPolyArray(dm), dm->getNumPolys(dm),
- dm->getLoopArray(dm),
- dm->getLoopTriArray(dm), dm->getNumLoopTri(dm),
- &dm->loopData,
- calc_active_tangent,
- tangent_names, tangent_names_len,
- CustomData_get_layer(&dm->polyData, CD_NORMAL),
- dm->getLoopDataArray(dm, CD_NORMAL),
- dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */
- /* result */
- &dm->loopData, dm->getNumLoops(dm),
- &dm->tangent_mask);
+ if (me_eval->runtime.deformed_only == false) {
+ MappedUserData userData;
+ memset(r_cos, 0, sizeof(*r_cos) * totcos);
+ userData.vertexcos = r_cos;
+ userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags");
+ BKE_mesh_foreach_mapped_vert(me_eval, make_vertexcos__mapFunc, &userData, MESH_FOREACH_NOP);
+ MEM_freeN(userData.vertex_visit);
+ }
+ else {
+ MVert *mv = me_eval->mvert;
+ for (int i = 0; i < totcos; i++, mv++) {
+ copy_v3_v3(r_cos[i], mv->co);
+ }
+ }
+}
+
+void DM_calc_loop_tangents(DerivedMesh *dm,
+ bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME],
+ int tangent_names_len)
+{
+ BKE_mesh_calc_loop_tangent_ex(dm->getVertArray(dm),
+ dm->getPolyArray(dm),
+ dm->getNumPolys(dm),
+ dm->getLoopArray(dm),
+ dm->getLoopTriArray(dm),
+ dm->getNumLoopTri(dm),
+ &dm->loopData,
+ calc_active_tangent,
+ tangent_names,
+ tangent_names_len,
+ CustomData_get_layer(&dm->polyData, CD_NORMAL),
+ dm->getLoopDataArray(dm, CD_NORMAL),
+ dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */
+ /* result */
+ &dm->loopData,
+ dm->getNumLoops(dm),
+ &dm->tangent_mask);
}
static void mesh_init_origspace(Mesh *mesh)
{
- const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
-
- OrigSpaceLoop *lof_array = CustomData_get_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP);
- const int numpoly = mesh->totpoly;
- // const int numloop = mesh->totloop;
- MVert *mv = mesh->mvert;
- MLoop *ml = mesh->mloop;
- MPoly *mp = mesh->mpoly;
- int i, j, k;
-
- float (*vcos_2d)[2] = NULL;
- BLI_array_staticdeclare(vcos_2d, 64);
-
- for (i = 0; i < numpoly; i++, mp++) {
- OrigSpaceLoop *lof = lof_array + mp->loopstart;
-
- if (mp->totloop == 3 || mp->totloop == 4) {
- for (j = 0; j < mp->totloop; j++, lof++) {
- copy_v2_v2(lof->uv, default_osf[j]);
- }
- }
- else {
- MLoop *l = &ml[mp->loopstart];
- float p_nor[3], co[3];
- float mat[3][3];
-
- float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
- float translate[2], scale[2];
-
- BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
- axis_dominant_v3_to_m3(mat, p_nor);
-
- BLI_array_clear(vcos_2d);
- BLI_array_reserve(vcos_2d, mp->totloop);
- for (j = 0; j < mp->totloop; j++, l++) {
- mul_v3_m3v3(co, mat, mv[l->v].co);
- copy_v2_v2(vcos_2d[j], co);
-
- for (k = 0; k < 2; k++) {
- if (co[k] > max[k])
- max[k] = co[k];
- else if (co[k] < min[k])
- min[k] = co[k];
- }
- }
-
- /* Brings min to (0, 0). */
- negate_v2_v2(translate, min);
-
- /* Scale will bring max to (1, 1). */
- sub_v2_v2v2(scale, max, min);
- if (scale[0] == 0.0f)
- scale[0] = 1e-9f;
- if (scale[1] == 0.0f)
- scale[1] = 1e-9f;
- invert_v2(scale);
-
- /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assign them as origspace. */
- for (j = 0; j < mp->totloop; j++, lof++) {
- add_v2_v2v2(lof->uv, vcos_2d[j], translate);
- mul_v2_v2(lof->uv, scale);
- }
- }
- }
-
- BKE_mesh_tessface_clear(mesh);
- BLI_array_free(vcos_2d);
+ const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+
+ OrigSpaceLoop *lof_array = CustomData_get_layer(&mesh->ldata, CD_ORIGSPACE_MLOOP);
+ const int numpoly = mesh->totpoly;
+ // const int numloop = mesh->totloop;
+ MVert *mv = mesh->mvert;
+ MLoop *ml = mesh->mloop;
+ MPoly *mp = mesh->mpoly;
+ int i, j, k;
+
+ float(*vcos_2d)[2] = NULL;
+ BLI_array_staticdeclare(vcos_2d, 64);
+
+ for (i = 0; i < numpoly; i++, mp++) {
+ OrigSpaceLoop *lof = lof_array + mp->loopstart;
+
+ if (mp->totloop == 3 || mp->totloop == 4) {
+ for (j = 0; j < mp->totloop; j++, lof++) {
+ copy_v2_v2(lof->uv, default_osf[j]);
+ }
+ }
+ else {
+ MLoop *l = &ml[mp->loopstart];
+ float p_nor[3], co[3];
+ float mat[3][3];
+
+ float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
+ float translate[2], scale[2];
+
+ BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
+ axis_dominant_v3_to_m3(mat, p_nor);
+
+ BLI_array_clear(vcos_2d);
+ BLI_array_reserve(vcos_2d, mp->totloop);
+ for (j = 0; j < mp->totloop; j++, l++) {
+ mul_v3_m3v3(co, mat, mv[l->v].co);
+ copy_v2_v2(vcos_2d[j], co);
+
+ for (k = 0; k < 2; k++) {
+ if (co[k] > max[k])
+ max[k] = co[k];
+ else if (co[k] < min[k])
+ min[k] = co[k];
+ }
+ }
+
+ /* Brings min to (0, 0). */
+ negate_v2_v2(translate, min);
+
+ /* Scale will bring max to (1, 1). */
+ sub_v2_v2v2(scale, max, min);
+ if (scale[0] == 0.0f)
+ scale[0] = 1e-9f;
+ if (scale[1] == 0.0f)
+ scale[1] = 1e-9f;
+ invert_v2(scale);
+
+ /* Finally, transform all vcos_2d into ((0, 0), (1, 1)) square and assign them as origspace. */
+ for (j = 0; j < mp->totloop; j++, lof++) {
+ add_v2_v2v2(lof->uv, vcos_2d[j], translate);
+ mul_v2_v2(lof->uv, scale);
+ }
+ }
+ }
+
+ BKE_mesh_tessface_clear(mesh);
+ BLI_array_free(vcos_2d);
}
-
/* derivedmesh info printing function,
* to help track down differences DM output */
#ifndef NDEBUG
-#include "BLI_dynstr.h"
-
-static void dm_debug_info_layers(
- DynStr *dynstr, DerivedMesh *dm, CustomData *cd,
- void *(*getElemDataArray)(DerivedMesh *, int))
-{
- int type;
-
- for (type = 0; type < CD_NUMTYPES; type++) {
- if (CustomData_has_layer(cd, type)) {
- /* note: doesn't account for multiple layers */
- const char *name = CustomData_layertype_name(type);
- const int size = CustomData_sizeof(type);
- const void *pt = getElemDataArray(dm, type);
- const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
- const char *structname;
- int structnum;
- CustomData_file_write_info(type, &structname, &structnum);
- BLI_dynstr_appendf(dynstr,
- " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, type, (const void *)pt, size, pt_size);
- }
- }
+# include "BLI_dynstr.h"
+
+static void dm_debug_info_layers(DynStr *dynstr,
+ DerivedMesh *dm,
+ CustomData *cd,
+ void *(*getElemDataArray)(DerivedMesh *, int))
+{
+ int type;
+
+ for (type = 0; type < CD_NUMTYPES; type++) {
+ if (CustomData_has_layer(cd, type)) {
+ /* note: doesn't account for multiple layers */
+ const char *name = CustomData_layertype_name(type);
+ const int size = CustomData_sizeof(type);
+ const void *pt = getElemDataArray(dm, type);
+ const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
+ const char *structname;
+ int structnum;
+ CustomData_file_write_info(type, &structname, &structnum);
+ BLI_dynstr_appendf(
+ dynstr,
+ " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
+ name,
+ structname,
+ type,
+ (const void *)pt,
+ size,
+ pt_size);
+ }
+ }
}
char *DM_debug_info(DerivedMesh *dm)
{
- DynStr *dynstr = BLI_dynstr_new();
- char *ret;
- const char *tstr;
-
- BLI_dynstr_append(dynstr, "{\n");
- BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm);
- switch (dm->type) {
- case DM_TYPE_CDDM: tstr = "DM_TYPE_CDDM"; break;
- case DM_TYPE_CCGDM: tstr = "DM_TYPE_CCGDM"; break;
- default: tstr = "UNKNOWN"; break;
- }
- BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr);
- BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData);
- BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData);
- BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData);
- BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData);
- BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly);
-
- BLI_dynstr_append(dynstr, " 'vertexLayers': (\n");
- dm_debug_info_layers(dynstr, dm, &dm->vertData, dm->getVertDataArray);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'edgeLayers': (\n");
- dm_debug_info_layers(dynstr, dm, &dm->edgeData, dm->getEdgeDataArray);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'loopLayers': (\n");
- dm_debug_info_layers(dynstr, dm, &dm->loopData, dm->getLoopDataArray);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'polyLayers': (\n");
- dm_debug_info_layers(dynstr, dm, &dm->polyData, dm->getPolyDataArray);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n");
- dm_debug_info_layers(dynstr, dm, &dm->faceData, dm->getTessFaceDataArray);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, "}\n");
-
- ret = BLI_dynstr_get_cstring(dynstr);
- BLI_dynstr_free(dynstr);
- return ret;
+ DynStr *dynstr = BLI_dynstr_new();
+ char *ret;
+ const char *tstr;
+
+ BLI_dynstr_append(dynstr, "{\n");
+ BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm);
+ switch (dm->type) {
+ case DM_TYPE_CDDM:
+ tstr = "DM_TYPE_CDDM";
+ break;
+ case DM_TYPE_CCGDM:
+ tstr = "DM_TYPE_CCGDM";
+ break;
+ default:
+ tstr = "UNKNOWN";
+ break;
+ }
+ BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr);
+ BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData);
+ BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData);
+ BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData);
+ BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData);
+ BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly);
+
+ BLI_dynstr_append(dynstr, " 'vertexLayers': (\n");
+ dm_debug_info_layers(dynstr, dm, &dm->vertData, dm->getVertDataArray);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'edgeLayers': (\n");
+ dm_debug_info_layers(dynstr, dm, &dm->edgeData, dm->getEdgeDataArray);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'loopLayers': (\n");
+ dm_debug_info_layers(dynstr, dm, &dm->loopData, dm->getLoopDataArray);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'polyLayers': (\n");
+ dm_debug_info_layers(dynstr, dm, &dm->polyData, dm->getPolyDataArray);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n");
+ dm_debug_info_layers(dynstr, dm, &dm->faceData, dm->getTessFaceDataArray);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, "}\n");
+
+ ret = BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+ return ret;
}
void DM_debug_print(DerivedMesh *dm)
{
- char *str = DM_debug_info(dm);
- puts(str);
- fflush(stdout);
- MEM_freeN(str);
+ char *str = DM_debug_info(dm);
+ puts(str);
+ fflush(stdout);
+ MEM_freeN(str);
}
void DM_debug_print_cdlayers(CustomData *data)
{
- int i;
- const CustomDataLayer *layer;
+ int i;
+ const CustomDataLayer *layer;
- printf("{\n");
+ printf("{\n");
- for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
+ for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
- const char *name = CustomData_layertype_name(layer->type);
- const int size = CustomData_sizeof(layer->type);
- const char *structname;
- int structnum;
- CustomData_file_write_info(layer->type, &structname, &structnum);
- printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name, structname, layer->type, (const void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size));
- }
+ const char *name = CustomData_layertype_name(layer->type);
+ const int size = CustomData_sizeof(layer->type);
+ const char *structname;
+ int structnum;
+ CustomData_file_write_info(layer->type, &structname, &structnum);
+ printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
+ name,
+ structname,
+ layer->type,
+ (const void *)layer->data,
+ size,
+ (int)(MEM_allocN_len(layer->data) / size));
+ }
- printf("}\n");
+ printf("}\n");
}
bool DM_is_valid(DerivedMesh *dm)
{
- const bool do_verbose = true;
- const bool do_fixes = false;
-
- bool is_valid = true;
- bool changed = true;
-
- is_valid &= BKE_mesh_validate_all_customdata(
- dm->getVertDataLayout(dm), dm->getNumVerts(dm),
- dm->getEdgeDataLayout(dm), dm->getNumEdges(dm),
- dm->getLoopDataLayout(dm), dm->getNumLoops(dm),
- dm->getPolyDataLayout(dm), dm->getNumPolys(dm),
- false, /* setting mask here isn't useful, gives false positives */
- do_verbose, do_fixes, &changed);
-
- is_valid &= BKE_mesh_validate_arrays(
- NULL,
- dm->getVertArray(dm), dm->getNumVerts(dm),
- dm->getEdgeArray(dm), dm->getNumEdges(dm),
- dm->getTessFaceArray(dm), dm->getNumTessFaces(dm),
- dm->getLoopArray(dm), dm->getNumLoops(dm),
- dm->getPolyArray(dm), dm->getNumPolys(dm),
- dm->getVertDataArray(dm, CD_MDEFORMVERT),
- do_verbose, do_fixes, &changed);
-
- BLI_assert(changed == false);
-
- return is_valid;
+ const bool do_verbose = true;
+ const bool do_fixes = false;
+
+ bool is_valid = true;
+ bool changed = true;
+
+ is_valid &= BKE_mesh_validate_all_customdata(
+ dm->getVertDataLayout(dm),
+ dm->getNumVerts(dm),
+ dm->getEdgeDataLayout(dm),
+ dm->getNumEdges(dm),
+ dm->getLoopDataLayout(dm),
+ dm->getNumLoops(dm),
+ dm->getPolyDataLayout(dm),
+ dm->getNumPolys(dm),
+ false, /* setting mask here isn't useful, gives false positives */
+ do_verbose,
+ do_fixes,
+ &changed);
+
+ is_valid &= BKE_mesh_validate_arrays(NULL,
+ dm->getVertArray(dm),
+ dm->getNumVerts(dm),
+ dm->getEdgeArray(dm),
+ dm->getNumEdges(dm),
+ dm->getTessFaceArray(dm),
+ dm->getNumTessFaces(dm),
+ dm->getLoopArray(dm),
+ dm->getNumLoops(dm),
+ dm->getPolyArray(dm),
+ dm->getNumPolys(dm),
+ dm->getVertDataArray(dm, CD_MDEFORMVERT),
+ do_verbose,
+ do_fixes,
+ &changed);
+
+ BLI_assert(changed == false);
+
+ return is_valid;
}
#endif /* NDEBUG */