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:
authorCampbell Barton <ideasman42@gmail.com>2015-07-16 20:36:03 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-07-16 20:55:14 +0300
commit595a491e63d6f3f3462675d38cfa71b4e784fe9c (patch)
treedf32ec17691b9280d7b2fa675cd5e5a0f87ea849 /source/blender/blenkernel
parentc8f6313487dfbbee030c6796220cc0d91228d658 (diff)
Add tessellation data to DerivedMesh (LoopTri)
This stores loop indices into the loop array giving easier acess to data such as vertex-colors and UV's, removing the need to store an MFace duplicate of custom-data. This doesn't yet move all internal code from MFace to LoopTri just yet. Only applies to: - opengl drawing - sculpting (pbvh) - vertex/weight paint Thanks to @psy-fi for review, fixes and improvements to drawing!
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h25
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h11
-rw-r--r--source/blender/blenkernel/BKE_paint.h4
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h10
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c123
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c773
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c44
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c176
-rw-r--r--source/blender/blenkernel/intern/paint.c9
-rw-r--r--source/blender/blenkernel/intern/pbvh.c132
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h4
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c199
13 files changed, 902 insertions, 610 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 62c68380289..0a4cc7f543f 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -185,6 +185,15 @@ struct DerivedMesh {
int totmat; /* total materials. Will be valid only before object drawing. */
struct Material **mat; /* material array. Will be valid only before object drawing */
+ /**
+ * \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
+ */
+ struct {
+ struct MLoopTri *array;
+ int num;
+ int num_alloc;
+ } looptris;
+
/* use for converting to BMesh which doesn't store bevel weight and edge crease by default */
char cd_flag;
@@ -201,6 +210,12 @@ struct DerivedMesh {
/** Recalculates mesh tessellation */
void (*recalcTessellation)(DerivedMesh *dm);
+ /** Loop tessellation cache */
+ void (*recalcLoopTri)(DerivedMesh *dm);
+ /** accessor functions */
+ const struct MLoopTri *(*getLoopTriArray)(DerivedMesh * dm);
+ int (*getNumLoopTri)(DerivedMesh *dm);
+
/* Misc. Queries */
/* Also called in Editmode */
@@ -594,10 +609,14 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
void DM_ensure_normals(DerivedMesh *dm);
void DM_ensure_tessface(DerivedMesh *dm);
+void DM_ensure_looptri_data(DerivedMesh *dm);
+void DM_ensure_looptri(DerivedMesh *dm);
+
void DM_update_tessface_data(DerivedMesh *dm);
void DM_update_materials(DerivedMesh *dm, struct Object *ob);
struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+struct MLoopUV *DM_paint_uvlayer_active_get_mloopuv(DerivedMesh *dm, int mat_nr);
void DM_interp_vert_data(
struct DerivedMesh *source, struct DerivedMesh *dest,
@@ -721,12 +740,12 @@ void DM_update_weight_mcol(
* the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
typedef struct DMVertexAttribs {
struct {
- struct MTFace *array;
+ struct MLoopUV *array;
int em_offset, gl_index, gl_texco;
} tface[MAX_MTFACE];
struct {
- struct MCol *array;
+ struct MLoopCol *array;
int em_offset, gl_index;
} mcol[MAX_MCOL];
@@ -747,7 +766,7 @@ void DM_vertex_attributes_from_gpu(
DerivedMesh *dm,
struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
-void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert);
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop);
void DM_add_tangent_layer(DerivedMesh *dm);
void DM_calc_auto_bump_scale(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 59ec316a403..c7ad6419560 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -125,6 +125,8 @@ void CDDM_calc_edges(struct DerivedMesh *dm);
void CDDM_recalc_tessellation(struct DerivedMesh *dm);
void CDDM_recalc_tessellation_ex(struct DerivedMesh *dm, const bool do_face_nor_cpy);
+void CDDM_recalc_looptri(struct DerivedMesh *dm);
+
/* lowers the number of vertices/edges/faces in a CDDerivedMesh
* the layer data stays the same size
*/
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 1ff2c6bc862..afe6fda48ed 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -39,6 +39,7 @@ struct LinkNode;
struct BLI_Stack;
struct MemArena;
struct BMesh;
+struct MLoopTri;
struct Main;
struct Mesh;
struct MPoly;
@@ -178,6 +179,11 @@ void BKE_mesh_calc_normals_tessface(
struct MVert *mverts, int numVerts,
const struct MFace *mfaces, int numFaces,
float (*r_faceNors)[3]);
+void BKE_mesh_calc_normals_looptri(
+ struct MVert *mverts, int numVerts,
+ const struct MLoop *mloop,
+ const struct MLoopTri *looptri, int looptri_num,
+ float (*r_tri_nors)[3]);
void BKE_mesh_loop_tangents_ex(
const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
@@ -285,6 +291,11 @@ int BKE_mesh_recalc_tessellation(
struct MVert *mvert,
int totface, int totloop, int totpoly,
const bool do_face_nor_copy);
+void BKE_mesh_recalc_looptri(
+ const struct MLoop *mloop, const struct MPoly *mpoly,
+ const struct MVert *mvert,
+ int totloop, int totpoly,
+ struct MLoopTri *mlooptri);
int BKE_mesh_mpoly_to_mface(
struct CustomData *fdata, struct CustomData *ldata,
struct CustomData *pdata, int totface, int totloop, int totpoly);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 09ccc3dced7..c9192fddec6 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -40,6 +40,8 @@ struct CurveMapping;
struct MeshElemMap;
struct GridPaintMask;
struct Main;
+struct MLoop;
+struct MLoopTri;
struct MFace;
struct MVert;
struct Object;
@@ -133,7 +135,7 @@ bool BKE_paint_select_vert_test(struct Object *ob);
bool BKE_paint_select_elem_test(struct Object *ob);
/* partial visibility */
-bool paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert);
+bool paint_is_face_hidden(const struct MLoopTri *lt, const struct MVert *mvert, const struct MLoop *mloop);
bool paint_is_grid_face_hidden(const unsigned int *grid_hidden,
int gridsize, int x, int y);
bool paint_is_bmesh_face_hidden(struct BMFace *f);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index fbaf91d60bd..79b285faaf5 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -34,7 +34,9 @@ struct CCGElem;
struct CCGKey;
struct CustomData;
struct DMFlagMat;
-struct MFace;
+struct MPoly;
+struct MLoop;
+struct MLoopTri;
struct MVert;
struct PBVH;
struct PBVHNode;
@@ -60,8 +62,10 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
PBVH *BKE_pbvh_new(void);
void BKE_pbvh_build_mesh(
- PBVH *bvh, const struct MFace *faces, struct MVert *verts,
- int totface, int totvert, struct CustomData *vdata);
+ PBVH *bvh,
+ const struct MPoly *mpoly, const struct MLoop *mloop,
+ struct MVert *verts, int totvert, struct CustomData *vdata,
+ const struct MLoopTri *looptri, int looptri_num);
void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
int totgrid,
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 7ced227f5b7..1bf49ad8fb0 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -220,6 +220,11 @@ static MPoly *dm_dupPolyArray(DerivedMesh *dm)
return tmp;
}
+static int dm_getNumLoopTri(DerivedMesh *dm)
+{
+ return dm->looptris.num;
+}
+
static CustomData *dm_getVertCData(DerivedMesh *dm)
{
return &dm->vertData;
@@ -263,6 +268,9 @@ void DM_init_funcs(DerivedMesh *dm)
dm->dupLoopArray = dm_dupLoopArray;
dm->dupPolyArray = dm_dupPolyArray;
+ /* subtypes handle getting actual data */
+ dm->getNumLoopTri = dm_getNumLoopTri;
+
dm->getVertDataLayout = dm_getVertCData;
dm->getEdgeDataLayout = dm_getEdgeCData;
dm->getTessFaceDataLayout = dm_getTessFaceCData;
@@ -364,6 +372,10 @@ int DM_release(DerivedMesh *dm)
dm->totmat = 0;
}
+ MEM_SAFE_FREE(dm->looptris.array);
+ dm->looptris.num = 0;
+ dm->looptris.num_alloc = 0;
+
return 1;
}
else {
@@ -440,6 +452,47 @@ void DM_ensure_tessface(DerivedMesh *dm)
dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS;
}
+/**
+ * Ensure the array is large enough
+ */
+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);
+
+ if ((looptris_num > dm->looptris.num_alloc) ||
+ (looptris_num < dm->looptris.num_alloc * 2) ||
+ (totpoly == 0))
+ {
+ MEM_SAFE_FREE(dm->looptris.array);
+ dm->looptris.num_alloc = 0;
+ dm->looptris.num = 0;
+ }
+
+ if (totpoly) {
+ if (dm->looptris.array == NULL) {
+ dm->looptris.array = MEM_mallocN(sizeof(*dm->looptris.array) * looptris_num, __func__);
+ dm->looptris.num_alloc = looptris_num;
+ }
+
+ dm->looptris.num = looptris_num;
+ }
+}
+
+/**
+ * The purpose of this function is that we can call:
+ * `dm->getLoopTriArray(dm)` and get the array returned.
+ */
+void DM_ensure_looptri(DerivedMesh *dm)
+{
+ const int numPolys = dm->getNumPolys(dm);
+
+ if ((dm->looptris.num == 0) && (numPolys != 0)) {
+ dm->recalcLoopTri(dm);
+ }
+}
+
/* Update tessface CD data from loop/poly ones. Needed when not retessellating after modstack evaluation. */
/* NOTE: Assumes dm has valid tessellated data! */
void DM_update_tessface_data(DerivedMesh *dm)
@@ -546,6 +599,29 @@ MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
return tf_base;
}
+MLoopUV *DM_paint_uvlayer_active_get_mloopuv(DerivedMesh *dm, int mat_nr)
+{
+ MLoopUV *uv_base;
+
+ BLI_assert(mat_nr < dm->totmat);
+
+ if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
+ {
+ uv_base = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV,
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
+ /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
+ * texture slot.*/
+ if (!uv_base)
+ uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ }
+ else {
+ uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ }
+
+ return uv_base;
+}
+
void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool take_ownership)
{
/* dm might depend on me, so we need to do everything with a local copy */
@@ -2031,7 +2107,12 @@ static void mesh_calc_modifiers(
}
if (sculpt_dyntopo == false) {
+ /* watch this! after 2.75a we move to from tessface to looptri (by default) */
+#if 0
DM_ensure_tessface(finaldm);
+#else
+ DM_ensure_looptri(finaldm);
+#endif
/* 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
@@ -3160,17 +3241,20 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
}
else {
+ /* exception .. */
+ CustomData *ldata = dm->getLoopDataLayout(dm);
+
if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+ layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV,
gattribs->layer[b].name);
else
- layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
+ layer = CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
a = attribs->tottface++;
if (layer != -1) {
- attribs->tface[a].array = tfdata->layers[layer].data;
- attribs->tface[a].em_offset = tfdata->layers[layer].offset;
+ attribs->tface[a].array = ldata->layers[layer].data;
+ attribs->tface[a].em_offset = ldata->layers[layer].offset;
}
else {
attribs->tface[a].array = NULL;
@@ -3207,19 +3291,22 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
}
else {
+ /* exception .. */
+ CustomData *ldata = dm->getLoopDataLayout(dm);
+
/* vertex colors */
if (gattribs->layer[b].name[0])
- layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+ layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL,
gattribs->layer[b].name);
else
- layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
+ layer = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
a = attribs->totmcol++;
if (layer != -1) {
- attribs->mcol[a].array = tfdata->layers[layer].data;
+ attribs->mcol[a].array = ldata->layers[layer].data;
/* odd, store the offset for a different layer type here, but editmode draw code expects it */
- attribs->mcol[a].em_offset = tfdata->layers[layer].offset;
+ attribs->mcol[a].em_offset = ldata->layers[layer].offset;
}
else {
attribs->mcol[a].array = NULL;
@@ -3266,13 +3353,15 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
}
}
-/* Set vertex shader attribute inputs for a particular tessface vert
+/**
+ * Set vertex shader attribute inputs for a particular tessface vert
*
- * a: tessface index
- * index: vertex index
- * vert: corner index (0, 1, 2, 3)
+ * \param a: tessface index
+ * \param index: vertex index
+ * \param vert: corner index (0, 1, 2, 3)
+ * \param loop: absolute loop corner index
*/
-void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop)
{
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
int b;
@@ -3293,8 +3382,8 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
const float *uv;
if (attribs->tface[b].array) {
- MTFace *tf = &attribs->tface[b].array[a];
- uv = tf->uv[vert];
+ const MLoopUV *mloopuv = &attribs->tface[b].array[loop];
+ uv = mloopuv->uv;
}
else {
uv = zero;
@@ -3311,8 +3400,8 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
GLubyte col[4];
if (attribs->mcol[b].array) {
- MCol *cp = &attribs->mcol[b].array[a * 4 + vert];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ const MLoopCol *cp = &attribs->mcol[b].array[loop];
+ copy_v4_v4_char((char *)col, &cp->r);
}
else {
col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index c16af7c2412..6f2579442c3 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -296,15 +296,26 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
* that this is actually for, to support a pbvh on a modified mesh */
if (!cddm->pbvh && ob->type == OB_MESH) {
Mesh *me = ob->data;
+ const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
bool deformed;
cddm->pbvh = BKE_pbvh_new();
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
- BKE_mesh_tessface_ensure(me);
+ looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
- BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
- me->totface, me->totvert, &me->vdata);
+ BKE_pbvh_build_mesh(
+ cddm->pbvh,
+ me->mpoly, me->mloop,
+ me->mvert, me->totvert, &me->vdata,
+ looptri, looptris_num);
pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
@@ -333,10 +344,10 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
float (*face_nors)[3];
- if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numTessFaceData)
+ if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numPolyData)
return;
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
}
@@ -354,37 +365,31 @@ static void cdDM_drawVerts(DerivedMesh *dm)
static void cdDM_drawUVEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MFace *mf = cddm->mface;
+ const MPoly *mpoly = cddm->mpoly;
+ int totpoly = dm->getNumPolys(dm);
+ int prevstart = 0;
+ bool prevdraw = true;
+ int curpos = 0;
int i;
- if (mf) {
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
- const bool draw = (mf->flag & ME_HIDE) == 0;
+ GPU_uvedge_setup(dm);
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ const bool draw = (mpoly->flag & ME_HIDE) == 0;
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
- if (mf->v4) {
- curpos += 8;
- }
- else {
- curpos += 6;
+ if (prevdraw != draw) {
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
- prevdraw = draw;
+ prevstart = curpos;
}
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffer_unbind();
+
+ curpos += 2 * mpoly->totloop;
+ prevdraw = draw;
+ }
+ if (prevdraw && (curpos != prevstart)) {
+ glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
}
+ GPU_buffer_unbind();
}
static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
@@ -477,10 +482,10 @@ static void cdDM_drawFacesTex_common(
void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
+ const MPoly *mpoly = cddm->mpoly;
MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- MCol *mcol;
- int i, orig;
+ const MLoopCol *mloopcol;
+ int i;
int colType, start_element, tot_drawn;
bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
int totpoly;
@@ -489,11 +494,7 @@ static void cdDM_drawFacesTex_common(
int tot_element;
/* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: not entirely correct, but currently dynamic topology will
* destroy UVs anyway, so textured display wouldn't work anyway
@@ -511,15 +512,15 @@ static void cdDM_drawFacesTex_common(
return;
}
- colType = CD_TEXTURE_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
- if (!mcol) {
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ if (!mloopcol) {
colType = CD_PREVIEW_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
- if (!mcol) {
- colType = CD_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
cdDM_update_normals_from_pbvh(dm);
@@ -531,7 +532,7 @@ static void cdDM_drawFacesTex_common(
GPU_texpaint_uv_setup(dm);
else
GPU_uv_setup(dm);
- if (mcol) {
+ if (mloopcol) {
GPU_color_setup(dm, colType);
}
@@ -550,24 +551,18 @@ static void cdDM_drawFacesTex_common(
int actualFace = bufmat->polys[i];
DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
int flush = 0;
+ int tot_tri_verts;
if (i != totpoly - 1)
next_actualFace = bufmat->polys[i + 1];
if (drawParams) {
- MTexPoly *tp = NULL;
- if (use_tface && mtexpoly && index_mf_to_mpoly) {
- int actualFace_poly = index_mf_to_mpoly[actualFace];
- if (actualFace_poly != ORIGINDEX_NONE) {
- tp = &mtexpoly[actualFace_poly];
- }
- }
-
- draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
+ MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL;
+ draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr);
}
else {
- if (index_mf_to_mpoly) {
- orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+ if (index_mp_to_orig) {
+ const int orig = index_mp_to_orig[actualFace];
if (orig == ORIGINDEX_NONE) {
/* XXX, this is not really correct
* it will draw the previous faces context for this one when we don't know its settings.
@@ -575,11 +570,11 @@ static void cdDM_drawFacesTex_common(
draw_option = DM_DRAW_OPTION_NORMAL;
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+ draw_option = drawParamsMapped(userData, orig, mpoly[actualFace].mat_nr);
}
}
else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
+ draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr);
}
}
@@ -592,14 +587,15 @@ static void cdDM_drawFacesTex_common(
flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
- tot_element += mf[actualFace].v4 ? 6 : 3;
+ tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+ tot_element += tot_tri_verts;
if (flush) {
if (draw_option != DM_DRAW_OPTION_SKIP)
- tot_drawn += mf[actualFace].v4 ? 6 : 3;
+ tot_drawn += tot_tri_verts;
if (tot_drawn) {
- if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
GPU_color_switch(1);
else
GPU_color_switch(0);
@@ -610,7 +606,7 @@ static void cdDM_drawFacesTex_common(
start_element = tot_element;
}
else {
- tot_drawn += mf[actualFace].v4 ? 6 : 3;
+ tot_drawn += tot_tri_verts;
}
}
}
@@ -637,29 +633,24 @@ static void cdDM_drawMappedFaces(
void *userData, DMDrawFlag flag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- MFace *mf = cddm->mface;
- MCol *mcol;
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoopCol *mloopcol = NULL;
int colType, useColors = flag & DM_DRAW_USE_COLORS, useHide = flag & DM_DRAW_SKIP_HIDDEN;
- int i, orig;
+ int i, j, orig;
int start_element = 0, tot_element, tot_drawn;
int totpoly;
int tottri;
int mat_index;
GPUBuffer *findex_buffer = NULL;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- cdDM_update_normals_from_pbvh(dm);
/* fist, setup common buffers */
GPU_vertex_setup(dm);
GPU_triangle_setup(dm);
+ totpoly = dm->getNumPolys(dm);
+
/* if we do selection, fill the selection buffer color */
if (G.f & G_BACKBUFSEL) {
Mesh *me = userData;
@@ -669,46 +660,43 @@ static void cdDM_drawMappedFaces(
fi_map = GPU_buffer_lock(findex_buffer, GPU_BINDING_ARRAY);
if (fi_map) {
- for (i = 0; i < dm->numTessFaceData; i++, mf++) {
+ for (i = 0; i < totpoly; i++, mpoly++) {
int selcol = 0xFFFFFFFF;
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i;
if ((orig != ORIGINDEX_NONE) && (!useHide || !(me->mpoly[orig].flag & ME_HIDE))) {
WM_framebuffer_index_get(orig + 1, &selcol);
}
- fi_map[start_element++] = selcol;
- fi_map[start_element++] = selcol;
- fi_map[start_element++] = selcol;
-
- if (mf->v4) {
+ for (j = 0; j < mpoly->totloop; j++)
fi_map[start_element++] = selcol;
- }
}
start_element = 0;
- mf = cddm->mface;
+ mpoly = cddm->mpoly;
GPU_buffer_unlock(findex_buffer, GPU_BINDING_ARRAY);
GPU_buffer_bind_as_color(findex_buffer);
}
}
else {
+ cdDM_update_normals_from_pbvh(dm);
+
GPU_normal_setup(dm);
if (useColors) {
- colType = CD_TEXTURE_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
- if (!mcol) {
- colType = CD_PREVIEW_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
+ if (!mloopcol) {
+ colType = CD_PREVIEW_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
}
- if (!mcol) {
- colType = CD_MCOL;
- mcol = DM_get_tessface_data_layer(dm, colType);
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = DM_get_loop_data_layer(dm, colType);
}
- if (useColors && mcol) {
+ if (useColors && mloopcol) {
GPU_color_setup(dm, colType);
}
}
@@ -744,12 +732,14 @@ static void cdDM_drawMappedFaces(
for (i = 0; i < totpoly; i++) {
int actualFace = next_actualFace;
int flush = 0;
+ int tot_tri_verts;
+
draw_option = DM_DRAW_OPTION_NORMAL;
if (i != totpoly - 1)
next_actualFace = bufmat->polys[i + 1];
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i;
if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE))
draw_option = setDrawOptions(userData, orig);
@@ -770,11 +760,12 @@ static void cdDM_drawMappedFaces(
flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
- tot_element += mf[actualFace].v4 ? 6 : 3;
+ tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+ tot_element += tot_tri_verts;
if (flush) {
if (!ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE))
- tot_drawn += mf[actualFace].v4 ? 6 : 3;
+ tot_drawn += tot_tri_verts;
if (tot_drawn) {
GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
@@ -787,7 +778,7 @@ static void cdDM_drawMappedFaces(
glDisable(GL_POLYGON_STIPPLE);
}
else {
- tot_drawn += mf[actualFace].v4 ? 6 : 3;
+ tot_drawn += tot_tri_verts;
}
}
}
@@ -812,14 +803,15 @@ static void cdDM_drawMappedFacesTex(
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
-static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int vert,
- const short (*lnor)[3], const bool smoothnormal)
+static void cddm_draw_attrib_vertex(
+ DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert,
+ const float *lnor, const bool smoothnormal)
{
- DM_draw_attrib_vertex(attribs, a, index, vert);
+ DM_draw_attrib_vertex(attribs, a, index, vert, loop);
/* vertex normal */
if (lnor) {
- glNormal3sv((const GLshort *)lnor);
+ glNormal3fv(lnor);
}
else if (smoothnormal) {
glNormal3sv(mvert[index].no);
@@ -845,20 +837,19 @@ static void cdDM_drawMappedFacesGLSL(
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
GPUVertexAttribs gattribs;
const MVert *mvert = cddm->mvert;
- const MFace *mface = cddm->mface;
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoop *mloop = cddm->mloop;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
/* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
- const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+ const int totpoly = dm->getNumPolys(dm);
int a, b, matnr, new_matnr;
bool do_draw;
int orig;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: same as for solid draw, not entirely correct, but works fine for now,
* will skip using textures (dyntopo currently destroys UV anyway) and
@@ -888,12 +879,15 @@ static void cdDM_drawMappedFacesGLSL(
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
memset(&attribs, 0, sizeof(attribs));
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH);
- const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
- new_matnr = mface->mat_nr;
+ for (a = 0; a < tottri; a++, lt++) {
+ const MPoly *mp = &mpoly[lt->poly];
+ const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+ const unsigned int *ltri = lt->tri;
+ const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
+ const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+ new_matnr = mp->mat_nr;
if (new_matnr != matnr) {
glEnd();
@@ -909,7 +903,7 @@ static void cdDM_drawMappedFacesGLSL(
continue;
}
else if (setDrawOptions) {
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly;
if (orig == ORIGINDEX_NONE) {
/* since the material is set by setMaterial(), faces with no
@@ -928,46 +922,32 @@ static void cdDM_drawMappedFacesGLSL(
else {
/* TODO ideally a normal layer should always be available */
float nor[3];
- if (mface->v4) {
- normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
- }
- else {
- normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
- }
+ normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
glNormal3fv(nor);
}
}
else if (lnors) {
- ln1 = &lnors[a][0];
- ln2 = &lnors[a][1];
- ln3 = &lnors[a][2];
- ln4 = &lnors[a][3];
+ ln1 = lnors[ltri[0]];
+ ln2 = lnors[ltri[1]];
+ ln3 = lnors[ltri[2]];
}
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, ln2, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
-
- if (mface->v4)
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, ln4, smoothnormal);
- else
- cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
}
glEnd();
}
else {
GPUMaterialConv *matconv;
int offset;
- int totface = dm->getNumTessFaces(dm);
int *mat_orig_to_new;
int tot_active_mat;
GPUBuffer *buffer = NULL;
char *varray;
int max_element_size = 0;
int tot_loops = 0;
-
- const MFace *mf = mface;
-
+
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
GPU_triangle_setup(dm);
@@ -1044,75 +1024,47 @@ static void cdDM_drawMappedFacesGLSL(
return;
}
- mface = mf;
-
- for (a = 0; a < totface; a++, mface++) {
- int i = mat_orig_to_new[mface->mat_nr];
+ for (a = 0; a < totpoly; a++, mpoly++) {
+ int j;
+ int i = mat_orig_to_new[mpoly->mat_nr];
offset = tot_loops * max_element_size;
if (matconv[i].numdata != 0) {
if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
- copy_v3_v3((float *)&varray[offset], (float *)matconv[i].attribs.orco.array[mface->v1]);
- copy_v3_v3((float *)&varray[offset + max_element_size], (float *)matconv[i].attribs.orco.array[mface->v2]);
- copy_v3_v3((float *)&varray[offset + max_element_size * 2], (float *)matconv[i].attribs.orco.array[mface->v3]);
- if (mface->v4) {
- copy_v3_v3((float *)&varray[offset + max_element_size * 3], (float *)matconv[i].attribs.orco.array[mface->v4]);
- }
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v3_v3((float *)&varray[offset + j * max_element_size],
+ (float *)matconv[i].attribs.orco.array[mloop[mpoly->loopstart + j].v]);
offset += sizeof(float) * 3;
}
for (b = 0; b < matconv[i].attribs.tottface; b++) {
if (matconv[i].attribs.tface[b].array) {
- MTFace *tf = &matconv[i].attribs.tface[b].array[a];
- copy_v2_v2((float *)&varray[offset], tf->uv[0]);
- copy_v2_v2((float *)&varray[offset + max_element_size], tf->uv[1]);
- copy_v2_v2((float *)&varray[offset + max_element_size * 2], tf->uv[2]);
- if (mface->v4) {
- copy_v2_v2((float *)&varray[offset + max_element_size * 3], tf->uv[3]);
- }
+ const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v2_v2((float *)&varray[offset + j * max_element_size], mloopuv[mpoly->loopstart + j].uv);
offset += sizeof(float) * 2;
}
}
for (b = 0; b < matconv[i].attribs.totmcol; b++) {
if (matconv[i].attribs.mcol[b].array) {
- MCol *cp = &matconv[i].attribs.mcol[b].array[a * 4 + 0];
- GLubyte col[4];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[offset], (char *)col);
- cp = &matconv[i].attribs.mcol[b].array[a * 4 + 1];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[offset + max_element_size], (char *)col);
- cp = &matconv[i].attribs.mcol[b].array[a * 4 + 2];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[offset + max_element_size * 2], (char *)col);
- if (mface->v4) {
- cp = &matconv[i].attribs.mcol[b].array[a * 4 + 3];
- col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
- copy_v4_v4_char((char *)&varray[offset + max_element_size * 3], (char *)col);
- }
+ const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v4_v4_char((char *)&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r);
offset += sizeof(unsigned char) * 4;
}
}
+ /* TODO, handle tangents */
if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
- const float *tang = matconv[i].attribs.tang.array[a * 4 + 0];
+ const float *tang = matconv[i].attribs.tang.array[i * 4 + 0];
copy_v4_v4((float *)&varray[offset], tang);
- tang = matconv[i].attribs.tang.array[a * 4 + 1];
+ tang = matconv[i].attribs.tang.array[i * 4 + 1];
copy_v4_v4((float *)&varray[offset + max_element_size], tang);
- tang = matconv[i].attribs.tang.array[a * 4 + 2];
+ tang = matconv[i].attribs.tang.array[i * 4 + 2];
copy_v4_v4((float *)&varray[offset + max_element_size * 2], tang);
- if (mface->v4) {
- tang = matconv[i].attribs.tang.array[a * 4 + 3];
- copy_v4_v4((float *)&varray[offset + max_element_size * 3], tang);
- }
offset += sizeof(float) * 4;
}
}
- if (mface->v4) {
- tot_loops += 4;
- }
- else {
- tot_loops += 3;
- }
+ tot_loops += mpoly->totloop;
}
GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
}
@@ -1159,18 +1111,16 @@ static void cdDM_drawMappedFacesMat(
GPUVertexAttribs gattribs;
DMVertexAttribs attribs;
MVert *mvert = cddm->mvert;
- MFace *mf = cddm->mface;
- const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const MPoly *mpoly = cddm->mpoly;
+ const MLoop *mloop = cddm->mloop;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int a, matnr, new_matnr;
int orig;
- /* double lookup */
- const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
/* TODO: same as for solid draw, not entirely correct, but works fine for now,
* will skip using textures (dyntopo currently destroys UV anyway) and
@@ -1193,14 +1143,17 @@ static void cdDM_drawMappedFacesMat(
memset(&attribs, 0, sizeof(attribs));
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
- for (a = 0; a < dm->numTessFaceData; a++, mf++) {
- const bool smoothnormal = lnors || (mf->flag & ME_SMOOTH);
- const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
+ for (a = 0; a < tottri; a++, lt++) {
+ const MPoly *mp = &mpoly[lt->poly];
+ const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+ const unsigned int *ltri = lt->tri;
+ const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+ const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
/* material */
- new_matnr = mf->mat_nr + 1;
+ new_matnr = mp->mat_nr + 1;
if (new_matnr != matnr) {
glEnd();
@@ -1208,12 +1161,12 @@ static void cdDM_drawMappedFacesMat(
setMaterial(userData, matnr = new_matnr, &gattribs);
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLES);
}
/* skipping faces */
if (setFace) {
- orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+ orig = (index_mp_to_orig) ? index_mp_to_orig[a] : lt->poly;
if (orig != ORIGINDEX_NONE && !setFace(userData, orig))
continue;
@@ -1227,31 +1180,20 @@ static void cdDM_drawMappedFacesMat(
else {
/* TODO ideally a normal layer should always be available */
float nor[3];
-
- if (mf->v4)
- normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- else
- normal_tri_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
-
+ normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
glNormal3fv(nor);
}
}
else if (lnors) {
- ln1 = &lnors[a][0];
- ln2 = &lnors[a][1];
- ln3 = &lnors[a][2];
- ln4 = &lnors[a][3];
+ ln1 = lnors[ltri[0]];
+ ln2 = lnors[ltri[1]];
+ ln3 = lnors[ltri[2]];
}
/* vertices */
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, ln1, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, ln2, smoothnormal);
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
-
- if (mf->v4)
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, ln4, smoothnormal);
- else
- cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+ cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
}
glEnd();
@@ -1287,59 +1229,48 @@ static void cdDM_buffer_copy_triangles(
const int *mat_orig_to_new)
{
GPUBufferMaterial *gpumat;
- MFace *f;
- int i, start, totface, findex = 0;
+ int i, findex = 0;
+
+ const MPoly *mpoly;
+ const MLoopTri *lt = dm->getLoopTriArray(dm);
+ const int tottri = dm->getNumLoopTri(dm);
- f = dm->getTessFaceArray(dm);
+ mpoly = dm->getPolyArray(dm);
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- gpumat = dm->drawObject->materials + mat_orig_to_new[f->mat_nr];
+ for (i = 0; i < tottri; i++, lt++) {
+ int start;
+ gpumat = dm->drawObject->materials + mat_orig_to_new[mpoly[lt->poly].mat_nr];
start = gpumat->counter;
/* v1 v2 v3 */
- varray[start++] = findex;
- varray[start++] = findex + 1;
- varray[start++] = findex + 2;
+ varray[start++] = lt->tri[0];
+ varray[start++] = lt->tri[1];
+ varray[start++] = lt->tri[2];
- if (f->v4) {
- /* v3 v4 v1 */
- varray[start++] = findex + 2;
- varray[start++] = findex + 3;
- varray[start++] = findex;
-
- gpumat->counter += 6;
- findex += 4;
- }
- else {
- gpumat->counter += 3;
- findex += 3;
- }
+ gpumat->counter += 3;
+ findex += 3;
}
}
static void cdDM_buffer_copy_vertex(
DerivedMesh *dm, float *varray)
{
- MVert *mvert;
- MFace *f;
- int i, j, start, totface;
+ const MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+
+ int i, j, start, totpoly;
mvert = dm->getVertArray(dm);
- f = dm->getTessFaceArray(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ totpoly = dm->getNumPolys(dm);
start = 0;
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- /* v1 v2 v3 */
- copy_v3_v3(&varray[start], mvert[f->v1].co);
- copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
- copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
- start += 9;
-
- if (f->v4) {
- /* v4 */
- copy_v3_v3(&varray[start], mvert[f->v4].co);
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v3_v3(&varray[start], mvert[mloop[mpoly->loopstart + j].v].co);
start += 3;
}
}
@@ -1357,80 +1288,52 @@ static void cdDM_buffer_copy_vertex(
static void cdDM_buffer_copy_normal(
DerivedMesh *dm, short *varray)
{
- int i, totface;
+ int i, j, totpoly;
int start;
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- const short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- MVert *mvert = dm->getVertArray(dm);
- MFace *f = dm->getTessFaceArray(dm);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+
+ const MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+
+ mvert = dm->getVertArray(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ totpoly = dm->getNumPolys(dm);
- totface = dm->getNumTessFaces(dm);
start = 0;
- for (i = 0; i < totface; i++, f++) {
- const int smoothnormal = (f->flag & ME_SMOOTH);
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ const bool smoothnormal = (mpoly->flag & ME_SMOOTH) != 0;
- if (tlnors) {
- const short (*ln)[3] = tlnors[i];
+ if (lnors) {
/* Copy loop normals */
- copy_v3_v3_short(&varray[start], ln[0]);
- copy_v3_v3_short(&varray[start + 4], ln[1]);
- copy_v3_v3_short(&varray[start + 8], ln[2]);
- start += 12;
-
- if (f->v4) {
- copy_v3_v3_short(&varray[start], ln[3]);
- start += 4;
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
+ normal_float_to_short_v3(&varray[start], lnors[mpoly->loopstart + j]);
}
}
else if (smoothnormal) {
- /* copy vertex normal */
- copy_v3_v3_short(&varray[start], mvert[f->v1].no);
- copy_v3_v3_short(&varray[start + 4], mvert[f->v2].no);
- copy_v3_v3_short(&varray[start + 8], mvert[f->v3].no);
- start += 12;
-
- if (f->v4) {
- copy_v3_v3_short(&varray[start], mvert[f->v4].no);
- start += 4;
- }
- }
- else if (nors) {
- /* copy cached face normal */
- short f_no_s[3];
-
- normal_float_to_short_v3(f_no_s, &nors[i * 3]);
-
- copy_v3_v3_short(&varray[start], f_no_s);
- copy_v3_v3_short(&varray[start + 4], f_no_s);
- copy_v3_v3_short(&varray[start + 8], f_no_s);
- start += 12;
-
- if (f->v4) {
- copy_v3_v3_short(&varray[start], f_no_s);
- start += 4;
+ /* Copy vertex normal */
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
+ copy_v3_v3_short(&varray[start], mvert[mloop[mpoly->loopstart + j].v].no);
}
}
else {
- /* calculate face normal */
- float f_no[3];
+ /* Copy cached OR calculated face normal */
short f_no_s[3];
- if (f->v4)
- normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
- else
- normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
-
- normal_float_to_short_v3(f_no_s, f_no);
-
- copy_v3_v3_short(&varray[start], f_no_s);
- copy_v3_v3_short(&varray[start + 4], f_no_s);
- copy_v3_v3_short(&varray[start + 8], f_no_s);
- start += 12;
+ if (nors) {
+ normal_float_to_short_v3(f_no_s, nors[i]);
+ }
+ else {
+ float f_no[3];
+ BKE_mesh_calc_poly_normal(mpoly, &mloop[mpoly->loopstart], mvert, f_no);
+ normal_float_to_short_v3(f_no_s, f_no);
+ }
- if (f->v4) {
+ for (j = 0; j < mpoly->totloop; j++, start += 4) {
copy_v3_v3_short(&varray[start], f_no_s);
- start += 4;
}
}
}
@@ -1439,90 +1342,68 @@ static void cdDM_buffer_copy_normal(
static void cdDM_buffer_copy_uv(
DerivedMesh *dm, float *varray)
{
+ int i, j, totpoly;
int start;
- int i, totface;
- MTFace *mtface;
- MFace *f;
+ const MPoly *mpoly;
+ const MLoopUV *mloopuv;
- if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
+ if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
return;
- f = dm->getTessFaceArray(dm);
+ }
+
+ mpoly = dm->getPolyArray(dm);
+ totpoly = dm->getNumPolys(dm);
start = 0;
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface[i].uv[0]);
- copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
- copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
- start += 6;
-
- if (f->v4) {
- /* v4 */
- copy_v2_v2(&varray[start], mtface[i].uv[3]);
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
start += 2;
}
}
}
-
static void cdDM_buffer_copy_uv_texpaint(
DerivedMesh *dm, float *varray)
{
+ int i, j, totpoly;
int start;
- int i, totface;
+
+ const MPoly *mpoly;
int totmaterial = dm->totmat;
- MTFace **mtface_base;
- MTFace *stencil_base;
+ const MLoopUV **uv_base;
+ const MLoopUV *uv_stencil_base;
int stencil;
- MFace *mf;
+
+ totpoly = dm->getNumPolys(dm);
/* should have been checked for before, reassert */
- BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
- mf = dm->getTessFaceArray(dm);
- mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+ BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+ uv_base = MEM_mallocN(totmaterial * sizeof(*uv_base), "texslots");
for (i = 0; i < totmaterial; i++) {
- mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ uv_base[i] = DM_paint_uvlayer_active_get_mloopuv(dm, i);
}
- stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+ uv_stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
- totface = dm->getNumTessFaces(dm);
+ mpoly = dm->getPolyArray(dm);
start = 0;
- for (i = 0; i < totface; i++, mf++) {
- int mat_i = mf->mat_nr;
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
- copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
- copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
- copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
- start += 12;
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ int mat_i = mpoly->mat_nr;
- if (mf->v4) {
- /* v4 */
- copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[3]);
- copy_v2_v2(&varray[start + 2], stencil_base[i].uv[3]);
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], uv_base[mat_i][mpoly->loopstart + j].uv);
+ copy_v2_v2(&varray[start + 2], uv_stencil_base[mpoly->loopstart + j].uv);
start += 4;
}
}
- MEM_freeN(mtface_base);
-}
-
-
-static void copy_mcol_uc3(unsigned char *v, const unsigned char *col)
-{
- v[0] = col[3];
- v[1] = col[2];
- v[2] = col[1];
+ MEM_freeN(uv_base);
}
/* treat varray_ as an array of MCol, four MCol's per face */
@@ -1530,22 +1411,19 @@ static void cdDM_buffer_copy_mcol(
DerivedMesh *dm, unsigned char *varray,
const void *user_data)
{
- int i, totface, start;
- const unsigned char *mcol = user_data;
- MFace *f = dm->getTessFaceArray(dm);
+ int i, j, totpoly;
+ int start;
+
+ const MLoopCol *mloopcol = user_data;
+ const MPoly *mpoly = dm->getPolyArray(dm);
+
+ totpoly = dm->getNumPolys(dm);
- totface = dm->getNumTessFaces(dm);
start = 0;
- for (i = 0; i < totface; i++, f++) {
- /* v1 v2 v3 */
- copy_mcol_uc3(&varray[start], &mcol[i * 16]);
- copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
- copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
- start += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_mcol_uc3(&varray[start], &mcol[i * 16 + 12]);
+
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v3_v3_char((char *)&varray[start], &mloopcol[mpoly->loopstart + j].r);
start += 3;
}
}
@@ -1614,34 +1492,23 @@ static void cdDM_buffer_copy_edge(
static void cdDM_buffer_copy_uvedge(
DerivedMesh *dm, float *varray)
{
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- int i, j = 0;
+ int i, j, totpoly;
+ int start;
+ const MLoopUV *mloopuv;
+ const MPoly *mpoly = dm->getPolyArray(dm);
- if (!tf)
+ if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
return;
+ }
- for (i = 0; i < dm->numTessFaceData; i++, tf++) {
- MFace mf;
- dm->getTessFace(dm, i, &mf);
-
- copy_v2_v2(&varray[j], tf->uv[0]);
- copy_v2_v2(&varray[j + 2], tf->uv[1]);
-
- copy_v2_v2(&varray[j + 4], tf->uv[1]);
- copy_v2_v2(&varray[j + 6], tf->uv[2]);
-
- if (!mf.v4) {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[0]);
- j += 12;
- }
- else {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[3]);
+ totpoly = dm->getNumPolys(dm);
+ start = 0;
- copy_v2_v2(&varray[j + 12], tf->uv[3]);
- copy_v2_v2(&varray[j + 14], tf->uv[0]);
- j += 16;
+ for (i = 0; i < totpoly; i++, mpoly++) {
+ for (j = 0; j < mpoly->totloop; j++) {
+ copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
+ start += 4;
}
}
}
@@ -1717,22 +1584,13 @@ static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, i
#endif /* USE_GPU_POINT_LINK */
-static int tri_indices[2][3] = {{0, 1, 2}, {2, 3, 0}};
-
-/* update the vert_points and triangle_to_mface fields with a new
- * triangle */
-static void cdDM_drawobject_add_triangle(GPUDrawObject *gdo,
- int v1, int v2, int v3, bool quad, int loopindex)
-{
- int i, v[3] = {v1, v2, v3};
- int *tri_i = quad ? tri_indices[1] : tri_indices[0];
- for (i = 0; i < 3; i++)
- cdDM_drawobject_add_vert_point(gdo, v[i], loopindex + tri_i[i]);
-}
-
/* for each vertex, build a list of points related to it; these lists
* are stored in an array sized to the number of vertices */
-static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
+static void cdDM_drawobject_init_vert_points(
+ GPUDrawObject *gdo,
+ const MPoly *mpoly, const MLoop *mloop,
+ int tot_poly,
+ int totmat)
{
GPUBufferMaterial *mat;
int i, *mat_orig_to_new;
@@ -1764,24 +1622,18 @@ static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int t
gdo->vert_points[i].point_index = -1;
}
- for (i = 0; i < totface; i++, f++) {
- mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
+ for (i = 0; i < tot_poly; i++) {
+ int j;
+ const MPoly *mp = &mpoly[i];
+ mat = &gdo->materials[mat_orig_to_new[mp->mat_nr]];
mat->polys[mat->counter++] = i;
- /* add triangle */
- cdDM_drawobject_add_triangle(gdo, f->v1, f->v2, f->v3, false, tot_loops);
- mat->totelements += 3;
-
- /* add second triangle for quads */
- if (f->v4) {
- cdDM_drawobject_add_triangle(gdo, f->v3, f->v4, f->v1, true, tot_loops);
- mat->totelements += 3;
- tot_loops += 4;
- }
- else {
- tot_loops += 3;
+ /* assign unique indices to vertices of the mesh */
+ for (j = 0; j < mp->totloop; j++) {
+ cdDM_drawobject_add_vert_point(gdo, mloop[mp->loopstart + j].v, tot_loops + j);
}
+ tot_loops += mp->totloop;
}
/* map any unused vertices to loose points */
@@ -1806,30 +1658,29 @@ typedef struct {
static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
{
GPUDrawObject *gdo;
- MFace *mface;
+ const MPoly *mpoly;
+ const MLoop *mloop;
int totmat = dm->totmat;
GPUMaterialInfo *mat_info;
- int i, curmat, totelements, totface, totloops;
+ int i, curmat, totelements, totloops, totpolys;
/* object contains at least one material (default included) so zero means uninitialized dm */
BLI_assert(totmat != 0);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+
+ totpolys = dm->getNumPolys(dm);
/* get the number of points used by each material, treating
* each quad as two triangles */
mat_info = MEM_callocN(sizeof(*mat_info) * totmat, "GPU_drawobject_new.mat_orig_to_new");
- for (i = 0; i < totface; i++) {
- mat_info[mface[i].mat_nr].polys++;
- if (mface[i].v4) {
- mat_info[mface[i].mat_nr].elements += 6;
- mat_info[mface[i].mat_nr].loops += 4;
- }
- else {
- mat_info[mface[i].mat_nr].elements += 3;
- mat_info[mface[i].mat_nr].loops += 3;
- }
+
+ for (i = 0; i < totpolys; i++) {
+ const int mat_nr = mpoly[i].mat_nr;
+ mat_info[mat_nr].polys++;
+ mat_info[mat_nr].elements += 3 * ME_POLY_TRI_TOT(&mpoly[i]);
+ mat_info[mat_nr].loops += mpoly[i].totloop;
}
/* create the GPUDrawObject */
gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
@@ -1851,7 +1702,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
if (mat_info[i].elements > 0) {
gdo->materials[curmat].start = totelements;
/* can set it to points now but used in cdDM_drawobject_init_vert_points as counter */
- gdo->materials[curmat].totelements = 0;
+ gdo->materials[curmat].totelements = mat_info[i].elements;
gdo->materials[curmat].totloops = mat_info[i].loops;
gdo->materials[curmat].mat_nr = i;
gdo->materials[curmat].totpolys = mat_info[i].polys;
@@ -1868,7 +1719,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
/* store total number of points used for triangles */
gdo->tot_triangle_point = totelements;
- cdDM_drawobject_init_vert_points(gdo, mface, totface, totmat);
+ cdDM_drawobject_init_vert_points(gdo, mpoly, mloop, totpolys, totmat);
MEM_freeN(mat_info);
return gdo;
@@ -2013,6 +1864,34 @@ void CDDM_recalc_tessellation(DerivedMesh *dm)
CDDM_recalc_tessellation_ex(dm, true);
}
+void CDDM_recalc_looptri(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
+ const unsigned int totpoly = dm->numPolyData;
+ const unsigned int totloop = dm->numLoopData;
+
+ DM_ensure_looptri_data(dm);
+
+ BKE_mesh_recalc_looptri(
+ cddm->mloop, cddm->mpoly,
+ cddm->mvert,
+ totloop, totpoly,
+ cddm->dm.looptris.array);
+}
+
+static const MLoopTri *cdDM_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ dm->recalcLoopTri(dm);
+
+ /* ccdm is an exception here, that recalcLoopTri will fill in the array too */
+ }
+ return dm->looptris.array;
+}
+
static void cdDM_free_internal(CDDerivedMesh *cddm)
{
if (cddm->pmap) MEM_freeN(cddm->pmap);
@@ -2063,10 +1942,13 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
+ dm->getLoopTriArray = cdDM_getLoopTriArray;
+
dm->calcNormals = CDDM_calc_normals;
dm->calcLoopNormals = CDDM_calc_loop_normals;
dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
dm->recalcTessellation = CDDM_recalc_tessellation;
+ dm->recalcLoopTri = CDDM_recalc_looptri;
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
@@ -2628,16 +2510,15 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
}
- face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numTessFaceData, "face_nors");
+ face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numPolyData, "face_nors");
/* calculate face normals */
- BKE_mesh_calc_normals_mapping_ex(
+ BKE_mesh_calc_normals_poly(
cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
- dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numTessFaceData,
- CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors,
+ dm->numLoopData, dm->numPolyData, face_nors,
only_face_normals);
- CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData);
+ CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numPolyData);
cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
}
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 58f25179c5c..b8fade6e4cd 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -242,6 +242,47 @@ static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* do nothing */
}
+static void emDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
+{
+ /* Nothing to do: emDM tessellation is known,
+ * allocate and fill in with emDM_getLoopTriArray */
+}
+
+static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMLoop *(*looptris)[3] = bmdm->em->looptris;
+ MLoopTri *mlooptri;
+ const int tottri = bmdm->em->tottri;
+ int i;
+
+ DM_ensure_looptri_data(dm);
+ mlooptri = dm->looptris.array;
+
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ BLI_assert(tottri == dm->looptris.num);
+
+ BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
+
+ for (i = 0; i < tottri; i++) {
+ BMLoop **ltri = looptris[i];
+ MLoopTri *lt = &mlooptri[i];
+
+ ARRAY_SET_ITEMS(
+ lt->tri,
+ BM_elem_index_get(ltri[0]),
+ BM_elem_index_get(ltri[1]),
+ BM_elem_index_get(ltri[2]));
+ lt->poly = BM_elem_index_get(ltri[0]->f);
+ }
+ }
+ return dm->looptris.array;
+}
+
static void emDM_foreachMappedVert(
DerivedMesh *dm,
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -1794,6 +1835,8 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
bmdm->dm.getNumLoops = emDM_getNumLoops;
bmdm->dm.getNumPolys = emDM_getNumPolys;
+ bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
+
bmdm->dm.getVert = emDM_getVert;
bmdm->dm.getVertCo = emDM_getVertCo;
bmdm->dm.getVertNo = emDM_getVertNo;
@@ -1812,6 +1855,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
bmdm->dm.calcLoopNormalsSpaceArray = emDM_calcLoopNormalsSpaceArray;
bmdm->dm.recalcTessellation = emDM_recalcTessellation;
+ bmdm->dm.recalcLoopTri = emDM_recalcLoopTri;
bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 40a299ef343..8ac0c7f7a6e 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -328,6 +328,52 @@ void BKE_mesh_calc_normals_tessface(
MEM_freeN(fnors);
}
+void BKE_mesh_calc_normals_looptri(
+ MVert *mverts, int numVerts,
+ const MLoop *mloop,
+ const MLoopTri *looptri, int looptri_num,
+ float (*r_tri_nors)[3])
+{
+ float (*tnorms)[3] = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, "tnorms");
+ float (*fnors)[3] = (r_tri_nors) ? r_tri_nors : MEM_callocN(sizeof(*fnors) * (size_t)looptri_num, "meshnormals");
+ int i;
+
+ for (i = 0; i < looptri_num; i++) {
+ const MLoopTri *lt = &looptri[i];
+ float *f_no = fnors[i];
+ const unsigned int vtri[3] = {
+ mloop[lt->tri[0]].v,
+ mloop[lt->tri[1]].v,
+ mloop[lt->tri[2]].v,
+ };
+
+ normal_tri_v3(
+ f_no,
+ mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+
+ accumulate_vertex_normals_tri(
+ tnorms[vtri[0]], tnorms[vtri[1]], tnorms[vtri[2]],
+ f_no, mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for (i = 0; i < numVerts; i++) {
+ MVert *mv = &mverts[i];
+ float *no = tnorms[i];
+
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+ normalize_v3_v3(no, mv->co);
+ }
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ MEM_freeN(tnorms);
+
+ if (fnors != r_tri_nors)
+ MEM_freeN(fnors);
+}
+
void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
{
if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
@@ -2541,6 +2587,136 @@ int BKE_mesh_recalc_tessellation(
}
+/**
+ * Calculate tessellation into #MLoopTri which exist only for this purpose.
+ */
+void BKE_mesh_recalc_looptri(
+ const MLoop *mloop, const MPoly *mpoly,
+ const MVert *mvert,
+ int totloop, int totpoly,
+ MLoopTri *mlooptri)
+{
+ /* use this to avoid locking pthread for _every_ polygon
+ * and calling the fill function */
+
+#define USE_TESSFACE_SPEEDUP
+
+ const MPoly *mp;
+ const MLoop *ml;
+ MLoopTri *mlt;
+ MemArena *arena = NULL;
+ int poly_index, mlooptri_index;
+ unsigned int j;
+
+ mlooptri_index = 0;
+ mp = mpoly;
+ for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
+ const unsigned int mp_loopstart = (unsigned int)mp->loopstart;
+ const unsigned int mp_totloop = (unsigned int)mp->totloop;
+ unsigned int l1, l2, l3;
+ if (mp_totloop < 3) {
+ /* do nothing */
+ }
+
+#ifdef USE_TESSFACE_SPEEDUP
+
+#define ML_TO_MLT(i1, i2, i3) { \
+ mlt = &mlooptri[mlooptri_index]; \
+ l1 = mp_loopstart + i1; \
+ l2 = mp_loopstart + i2; \
+ l3 = mp_loopstart + i3; \
+ ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3); \
+ mlt->poly = (unsigned int)poly_index; \
+ } ((void)0)
+
+ else if (mp_totloop == 3) {
+ ML_TO_MLT(0, 1, 2);
+ mlooptri_index++;
+ }
+ else if (mp_totloop == 4) {
+ ML_TO_MLT(0, 1, 2);
+ mlooptri_index++;
+ ML_TO_MLT(0, 2, 3);
+ mlooptri_index++;
+ }
+#endif /* USE_TESSFACE_SPEEDUP */
+ else {
+ const float *co_curr, *co_prev;
+
+ float normal[3];
+
+ float axis_mat[3][3];
+ float (*projverts)[2];
+ unsigned int (*tris)[3];
+
+ const unsigned int totfilltri = mp_totloop - 2;
+
+ if (UNLIKELY(arena == NULL)) {
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
+
+ tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
+ projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop);
+
+ zero_v3(normal);
+
+ /* calc normal, flipped: to get a positive 2d cross product */
+ ml = mloop + mp_loopstart;
+ co_prev = mvert[ml[mp_totloop - 1].v].co;
+ for (j = 0; j < mp_totloop; j++, ml++) {
+ co_curr = mvert[ml->v].co;
+ add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
+ co_prev = co_curr;
+ }
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
+
+ /* project verts to 2d */
+ axis_dominant_v3_to_m3_negate(axis_mat, normal);
+
+ ml = mloop + mp_loopstart;
+ for (j = 0; j < mp_totloop; j++, ml++) {
+ mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
+ }
+
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, mp_totloop, 1, tris, arena);
+
+ /* apply fill */
+ for (j = 0; j < totfilltri; j++) {
+ unsigned int *tri = tris[j];
+
+ mlt = &mlooptri[mlooptri_index];
+
+ /* set loop indices, transformed to vert indices later */
+ l1 = mp_loopstart + tri[0];
+ l2 = mp_loopstart + tri[1];
+ l3 = mp_loopstart + tri[2];
+
+ ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3);
+ mlt->poly = (unsigned int)poly_index;
+
+ mlooptri_index++;
+ }
+
+ BLI_memarena_clear(arena);
+ }
+ }
+
+ if (arena) {
+ BLI_memarena_free(arena);
+ arena = NULL;
+ }
+
+ BLI_assert(mlooptri_index == poly_to_tri_count(totpoly, totloop));
+
+#undef USE_TESSFACE_SPEEDUP
+#undef ML_TO_MLT
+}
+
+/* -------------------------------------------------------------------- */
+
+
#ifdef USE_BMESH_SAVE_AS_COMPAT
/**
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 0bda740af53..76e56f0bc30 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -470,12 +470,11 @@ void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
/* returns non-zero if any of the face's vertices
* are hidden, zero otherwise */
-bool paint_is_face_hidden(const MFace *f, const MVert *mvert)
+bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop)
{
- return ((mvert[f->v1].flag & ME_HIDE) ||
- (mvert[f->v2].flag & ME_HIDE) ||
- (mvert[f->v3].flag & ME_HIDE) ||
- (f->v4 && (mvert[f->v4].flag & ME_HIDE)));
+ return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) ||
+ (mvert[mloop[lt->tri[1]].v].flag & ME_HIDE) ||
+ (mvert[mloop[lt->tri[2]].v].flag & ME_HIDE));
}
/* returns non-zero if any of the corners of the grid
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index edeba9fd7e6..6e379f293d7 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -168,7 +168,7 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
-static int face_materials_match(const MFace *f1, const MFace *f2)
+static int face_materials_match(const MPoly *f1, const MPoly *f2)
{
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
(f1->mat_nr == f2->mat_nr));
@@ -201,21 +201,22 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis,
/* Returns the index of the first element on the right of the partition */
static int partition_indices_material(PBVH *bvh, int lo, int hi)
{
- const MFace *faces = bvh->faces;
+ const MPoly *mpoly = bvh->mpoly;
+ const MLoopTri *looptri = bvh->looptri;
const DMFlagMat *flagmats = bvh->grid_flag_mats;
const int *indices = bvh->prim_indices;
const void *first;
int i = lo, j = hi;
- if (bvh->faces)
- first = &faces[bvh->prim_indices[lo]];
+ if (bvh->looptri)
+ first = &looptri[bvh->prim_indices[lo]];
else
first = &flagmats[bvh->prim_indices[lo]];
for (;; ) {
- if (bvh->faces) {
- for (; face_materials_match(first, &faces[indices[i]]); i++) ;
- for (; !face_materials_match(first, &faces[indices[j]]); j--) ;
+ if (bvh->looptri) {
+ for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) ;
+ for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) ;
}
else {
for (; grid_materials_match(first, &flagmats[indices[i]]); i++) ;
@@ -295,17 +296,18 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
node->face_vert_indices = (const int (*)[4])face_vert_indices;
for (i = 0; i < totface; ++i) {
- const MFace *f = &bvh->faces[node->prim_indices[i]];
- int sides = f->v4 ? 4 : 3;
+ const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
+ const int sides = 3;
for (j = 0; j < sides; ++j) {
face_vert_indices[i][j] =
map_insert_vert(bvh, map, &node->face_verts,
- &node->uniq_verts, (&f->v1)[j]);
+ &node->uniq_verts, bvh->mloop[lt->tri[j]].v);
}
- if (!paint_is_face_hidden(f, bvh->verts))
+ if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
has_visible = true;
+ }
}
vert_indices = MEM_callocN(sizeof(int) *
@@ -326,9 +328,8 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
}
for (i = 0; i < totface; ++i) {
- const MFace *f = &bvh->faces[node->prim_indices[i]];
- int sides = f->v4 ? 4 : 3;
-
+ const int sides = 3;
+
for (j = 0; j < sides; ++j) {
if (face_vert_indices[i][j] < 0)
face_vert_indices[i][j] =
@@ -406,7 +407,7 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
/* Still need vb for searches */
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
- if (bvh->faces)
+ if (bvh->looptri)
build_mesh_leaf_node(bvh, bvh->nodes + node_index);
else {
build_grid_leaf_node(bvh, bvh->nodes + node_index);
@@ -417,25 +418,28 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
* same material (including flat/smooth shading), non-zero otherwise */
static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
{
- int i, prim;
+ int i;
if (count <= 1)
return 0;
- if (bvh->faces) {
- const MFace *first = &bvh->faces[bvh->prim_indices[offset]];
+ if (bvh->looptri) {
+ const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
+ const MPoly *mp = &bvh->mpoly[first->poly];
for (i = offset + count - 1; i > offset; --i) {
- prim = bvh->prim_indices[i];
- if (!face_materials_match(first, &bvh->faces[prim]))
+ int prim = bvh->prim_indices[i];
+ const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
+ if (!face_materials_match(mp, mp_other)) {
return 1;
+ }
}
}
else {
const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
for (i = offset + count - 1; i > offset; --i) {
- prim = bvh->prim_indices[i];
+ int prim = bvh->prim_indices[i];
if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
return 1;
}
@@ -534,15 +538,18 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
/* Do a full rebuild with on Mesh data structure */
void BKE_pbvh_build_mesh(
- PBVH *bvh, const MFace *faces, MVert *verts,
- int totface, int totvert, struct CustomData *vdata)
+ PBVH *bvh, const MPoly *mpoly, const MLoop *mloop, MVert *verts,
+ int totvert, struct CustomData *vdata,
+ const MLoopTri *looptri, int looptri_num)
{
BBC *prim_bbc = NULL;
BB cb;
int i, j;
bvh->type = PBVH_FACES;
- bvh->faces = faces;
+ bvh->mpoly = mpoly;
+ bvh->mloop = mloop;
+ bvh->looptri = looptri;
bvh->verts = verts;
bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
bvh->totvert = totvert;
@@ -552,25 +559,25 @@ void BKE_pbvh_build_mesh(
BB_reset(&cb);
/* For each face, store the AABB and the AABB centroid */
- prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
+ prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
- for (i = 0; i < totface; ++i) {
- const MFace *f = &faces[i];
- const int sides = f->v4 ? 4 : 3;
+ for (i = 0; i < looptri_num; ++i) {
+ const MLoopTri *lt = &looptri[i];
+ const int sides = 3;
BBC *bbc = prim_bbc + i;
BB_reset((BB *)bbc);
for (j = 0; j < sides; ++j)
- BB_expand((BB *)bbc, verts[(&f->v1)[j]].co);
+ BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
BBC_update_centroid(bbc);
BB_expand(&cb, bbc->bcentroid);
}
- if (totface)
- pbvh_build(bvh, &cb, prim_bbc, totface);
+ if (looptri_num)
+ pbvh_build(bvh, &cb, prim_bbc, looptri_num);
MEM_freeN(prim_bbc);
MEM_freeN(bvh->vert_bitmap);
@@ -657,12 +664,13 @@ void BKE_pbvh_free(PBVH *bvh)
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
MEM_freeN((void *)bvh->verts);
- if (bvh->faces) {
- MEM_freeN((void *)bvh->faces);
- }
}
}
+ if (bvh->looptri) {
+ MEM_freeN((void *)bvh->looptri);
+ }
+
if (bvh->nodes)
MEM_freeN(bvh->nodes);
@@ -983,20 +991,23 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
totface = node->totprim;
for (i = 0; i < totface; ++i) {
- const MFace *f = &bvh->faces[faces[i]];
+ const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const unsigned int vtri[3] = {
+ bvh->mloop[lt->tri[0]].v,
+ bvh->mloop[lt->tri[1]].v,
+ bvh->mloop[lt->tri[2]].v,
+ };
float fn[3];
- const unsigned int *fv = &f->v1;
- int sides = (f->v4) ? 4 : 3;
+ const int sides = 3;
- if (f->v4)
- normal_quad_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
- bvh->verts[f->v3].co, bvh->verts[f->v4].co);
- else
- normal_tri_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
- bvh->verts[f->v3].co);
+ normal_tri_v3(
+ fn,
+ bvh->verts[vtri[0]].co,
+ bvh->verts[vtri[1]].co,
+ bvh->verts[vtri[2]].co);
for (j = 0; j < sides; ++j) {
- int v = fv[j];
+ int v = vtri[j];
if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
/* this seems like it could be very slow but profile
@@ -1010,8 +1021,9 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
}
}
- if (face_nors)
- copy_v3_v3(face_nors[faces[i]], fn);
+ if (face_nors) {
+ copy_v3_v3(face_nors[lt->poly], fn);
+ }
}
}
}
@@ -1093,7 +1105,8 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
case PBVH_FACES:
node->draw_buffers =
GPU_build_mesh_pbvh_buffers(node->face_vert_indices,
- bvh->faces, bvh->verts,
+ bvh->mpoly, bvh->mloop, bvh->looptri,
+ bvh->verts,
node->prim_indices,
node->totprim);
break;
@@ -1515,15 +1528,16 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
const float ray_normal[3], float *dist)
{
const MVert *vert = bvh->verts;
+ const MLoop *mloop = bvh->mloop;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
for (i = 0; i < totface; ++i) {
- const MFace *f = bvh->faces + faces[i];
+ const MLoopTri *lt = &bvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (paint_is_face_hidden(f, vert))
+ if (paint_is_face_hidden(lt, vert, mloop))
continue;
if (origco) {
@@ -1532,16 +1546,16 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
origco[face_verts[0]],
origco[face_verts[1]],
origco[face_verts[2]],
- f->v4 ? origco[face_verts[3]] : NULL,
+ NULL,
dist);
}
else {
/* intersect with current coordinates */
hit |= ray_face_intersection(ray_start, ray_normal,
- vert[f->v1].co,
- vert[f->v2].co,
- vert[f->v3].co,
- f->v4 ? vert[f->v4].co : NULL,
+ vert[mloop[lt->tri[0]].v].co,
+ vert[mloop[lt->tri[1]].v].co,
+ vert[mloop[lt->tri[2]].v].co,
+ NULL,
dist);
}
}
@@ -1874,8 +1888,8 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
/* original data and applying new coords to this arrays would lead to */
/* unneeded deformation -- duplicate verts/faces to avoid this */
- pbvh->verts = MEM_dupallocN(pbvh->verts);
- pbvh->faces = MEM_dupallocN(pbvh->faces);
+ pbvh->verts = MEM_dupallocN(pbvh->verts);
+ pbvh->looptri = MEM_dupallocN(pbvh->looptri);
pbvh->deformed = 1;
}
@@ -1890,7 +1904,11 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
}
/* coordinates are new -- normals should also be updated */
- BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
+ BKE_mesh_calc_normals_looptri(
+ pbvh->verts, pbvh->totvert,
+ pbvh->mloop,
+ pbvh->looptri, pbvh->totprim,
+ NULL);
for (a = 0; a < pbvh->totnode; ++a)
BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 74897d6f4cd..5967704141f 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -133,7 +133,9 @@ struct PBVH {
/* Mesh data */
MVert *verts;
- const MFace *faces;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
CustomData *vdata;
/* Grid Data */
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index aaf631abbf0..1ab6a354605 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1769,7 +1769,7 @@ static void ccgDM_buffer_copy_normal(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
DMFlagMat *faceFlags = ccgdm->faceFlags;
@@ -1784,7 +1784,7 @@ static void ccgDM_buffer_copy_normal(
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- const short (*ln)[3] = NULL;
+ const float (*ln)[3] = NULL;
if (faceFlags) {
shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
@@ -1794,8 +1794,8 @@ static void ccgDM_buffer_copy_normal(
}
if (lnors) {
- ln = *lnors;
- lnors += gridFaces * gridFaces * numVerts;
+ ln = lnors;
+ lnors += gridFaces * gridFaces * numVerts * 4;
}
for (S = 0; S < numVerts; S++) {
@@ -1805,10 +1805,10 @@ static void ccgDM_buffer_copy_normal(
/* Can't use quad strips here... */
for (y = 0; y < gridFaces; y ++) {
for (x = 0; x < gridFaces; x ++) {
- copy_v3_v3_short(&varray[start], ln[0]);
- copy_v3_v3_short(&varray[start + 4], ln[3]);
- copy_v3_v3_short(&varray[start + 8], ln[2]);
- copy_v3_v3_short(&varray[start + 12], ln[1]);
+ normal_float_to_short_v3(&varray[start + 0], ln[0]);
+ normal_float_to_short_v3(&varray[start + 4], ln[3]);
+ normal_float_to_short_v3(&varray[start + 8], ln[2]);
+ normal_float_to_short_v3(&varray[start + 12], ln[1]);
start += 16;
ln += 4;
@@ -1953,13 +1953,6 @@ static void ccgDM_buffer_copy_vertex(
}
}
-static void copy_mcol_uc3(unsigned char *v, const unsigned char *col)
-{
- v[0] = col[3];
- v[1] = col[2];
- v[2] = col[1];
-}
-
/* Only used by non-editmesh types */
static void ccgDM_buffer_copy_color(
DerivedMesh *dm, unsigned char *varray,
@@ -1968,7 +1961,7 @@ static void ccgDM_buffer_copy_color(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- const unsigned char *mcol = user_data;
+ const char *mloopcol = user_data;
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int i, totface = ccgSubSurf_getNumFaces(ss);
@@ -1985,10 +1978,10 @@ static void ccgDM_buffer_copy_color(
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridFaces; y++) {
for (x = 0; x < gridFaces; x++) {
- copy_mcol_uc3(&varray[start], &mcol[iface * 16]);
- copy_mcol_uc3(&varray[start + 3], &mcol[iface * 16 + 12]);
- copy_mcol_uc3(&varray[start + 6], &mcol[iface * 16 + 8]);
- copy_mcol_uc3(&varray[start + 9], &mcol[iface * 16 + 4]);
+ copy_v3_v3_char((char *)&varray[start + 0], &mloopcol[iface * 16 + 0]);
+ copy_v3_v3_char((char *)&varray[start + 3], &mloopcol[iface * 16 + 12]);
+ copy_v3_v3_char((char *)&varray[start + 6], &mloopcol[iface * 16 + 8]);
+ copy_v3_v3_char((char *)&varray[start + 9], &mloopcol[iface * 16 + 4]);
start += 12;
iface++;
@@ -2005,7 +1998,7 @@ static void ccgDM_buffer_copy_uv(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int i, totface = ccgSubSurf_getNumFaces(ss);
@@ -2020,12 +2013,12 @@ static void ccgDM_buffer_copy_uv(
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridFaces; y++) {
for (x = 0; x < gridFaces; x++) {
- copy_v2_v2(&varray[start], tf->uv[0]);
- copy_v2_v2(&varray[start + 2], tf->uv[3]);
- copy_v2_v2(&varray[start + 4], tf->uv[2]);
- copy_v2_v2(&varray[start + 6], tf->uv[1]);
+ copy_v2_v2(&varray[start + 0], mloopuv[0].uv);
+ copy_v2_v2(&varray[start + 2], mloopuv[3].uv);
+ copy_v2_v2(&varray[start + 4], mloopuv[2].uv);
+ copy_v2_v2(&varray[start + 6], mloopuv[1].uv);
- tf++;
+ mloopuv += 4;
start += 8;
}
}
@@ -2045,22 +2038,22 @@ static void ccgDM_buffer_copy_uv_texpaint(
int start = 0;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int totmaterial = dm->totmat;
- MTFace **mtface_base;
- MTFace *stencil_base;
+ MLoopUV **mloopuv_base;
+ MLoopUV *stencil_base;
int stencil;
CCG_key_top_level(&key, ss);
/* should have been checked for before, reassert */
- BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
- mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+ BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+ mloopuv_base = MEM_mallocN(totmaterial * sizeof(*mloopuv_base), "texslots");
for (i = 0; i < totmaterial; i++) {
- mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ mloopuv_base[i] = DM_paint_uvlayer_active_get_mloopuv(dm, i);
}
- stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+ stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
start = 0;
@@ -2080,23 +2073,23 @@ static void ccgDM_buffer_copy_uv_texpaint(
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridFaces; y++) {
for (x = 0; x < gridFaces; x++) {
- /* divide by 16, gives us current tface */
- unsigned int i_tf = start / 16;
- copy_v2_v2(&varray[start], mtface_base[matnr][i_tf].uv[0]);
- copy_v2_v2(&varray[start + 2], stencil_base[i_tf].uv[0]);
- copy_v2_v2(&varray[start + 4], mtface_base[matnr][i_tf].uv[3]);
- copy_v2_v2(&varray[start + 6], stencil_base[i_tf].uv[3]);
- copy_v2_v2(&varray[start + 8], mtface_base[matnr][i_tf].uv[2]);
- copy_v2_v2(&varray[start + 10], stencil_base[i_tf].uv[2]);
- copy_v2_v2(&varray[start + 12], mtface_base[matnr][i_tf].uv[1]);
- copy_v2_v2(&varray[start + 14], stencil_base[i_tf].uv[1]);
+ /* divide by 4, gives us current loop-index */
+ unsigned int i_ml = start / 4;
+ copy_v2_v2(&varray[start + 0], mloopuv_base[matnr][i_ml + 0].uv);
+ copy_v2_v2(&varray[start + 2], stencil_base[i_ml + 0].uv);
+ copy_v2_v2(&varray[start + 4], mloopuv_base[matnr][i_ml + 3].uv);
+ copy_v2_v2(&varray[start + 6], stencil_base[i_ml + 3].uv);
+ copy_v2_v2(&varray[start + 8], mloopuv_base[matnr][i_ml + 2].uv);
+ copy_v2_v2(&varray[start + 10], stencil_base[i_ml + 2].uv);
+ copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv);
+ copy_v2_v2(&varray[start + 14], stencil_base[i_ml + 1].uv);
start += 16;
}
}
}
}
- MEM_freeN(mtface_base);
+ MEM_freeN(mloopuv_base);
}
static void ccgDM_copy_gpu_data(
@@ -2301,7 +2294,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
else \
index = 0; \
- DM_draw_attrib_vertex(&attribs, a, index, vert); \
+ DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
} (void)0
totface = ccgSubSurf_getNumFaces(ss);
@@ -2472,7 +2465,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
else \
index = 0; \
- DM_draw_attrib_vertex(&attribs, a, index, vert); \
+ DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
} (void)0
totface = ccgSubSurf_getNumFaces(ss);
@@ -2621,8 +2614,8 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- int colType = CD_TEXTURE_MCOL;
- MCol *mcol = dm->getTessFaceDataArray(dm, colType);
+ int colType;
+ const MLoopCol *mloopcol;
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
@@ -2637,13 +2630,15 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
- if (!mcol) {
+ colType = CD_TEXTURE_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
+ if (!mloopcol) {
colType = CD_PREVIEW_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
- if (!mcol) {
- colType = CD_MCOL;
- mcol = dm->getTessFaceDataArray(dm, colType);
+ if (!mloopcol) {
+ colType = CD_MLOOPCOL;
+ mloopcol = dm->getLoopDataArray(dm, colType);
}
GPU_vertex_setup(dm);
@@ -2653,7 +2648,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
GPU_texpaint_uv_setup(dm);
else
GPU_uv_setup(dm);
- if (mcol) {
+ if (mloopcol) {
GPU_color_setup(dm, colType);
}
@@ -2695,10 +2690,11 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
if (drawParams) {
MTexPoly tpoly;
if (tf) {
+ memset(&tpoly, 0, sizeof(tpoly));
ME_MTEXFACE_CPY(&tpoly, tf + actualFace);
}
- draw_option = drawParams((use_tface && tf) ? &tpoly : NULL, (mcol != NULL), mat_nr);
+ draw_option = drawParams((use_tface && tf) ? &tpoly : NULL, (mloopcol != NULL), mat_nr);
}
else if (index != ORIGINDEX_NONE)
draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
@@ -2721,7 +2717,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
tot_drawn += facequads * 6;
if (tot_drawn) {
- if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+ if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
GPU_color_switch(1);
else
GPU_color_switch(0);
@@ -2801,7 +2797,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- MCol *mcol = NULL;
+ MLoopCol *mloopcol = NULL;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
int i, gridSize = ccgSubSurf_getGridSize(ss);
DMFlagMat *faceFlags = ccgdm->faceFlags;
@@ -2815,9 +2811,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
(void)compareDrawOptions;
if (useColors) {
- mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
- if (!mcol)
- mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+ mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
+ if (!mloopcol)
+ mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
}
totface = ccgSubSurf_getNumFaces(ss);
@@ -2835,9 +2831,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
else drawSmooth = 1;
- if (mcol) {
- cp = (unsigned char *)mcol;
- mcol += gridFaces * gridFaces * numVerts * 4;
+ if (mloopcol) {
+ cp = (unsigned char *)mloopcol;
+ mloopcol += gridFaces * gridFaces * numVerts * 4;
}
if (lnors) {
@@ -2881,16 +2877,16 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (cp) glColor3ubv(&cp[4]);
glNormal3sv(ln[0][1]);
glVertex3fv(d);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (cp) glColor3ubv(&cp[8]);
glNormal3sv(ln[0][2]);
glVertex3fv(c);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (cp) glColor3ubv(&cp[12]);
glNormal3sv(ln[0][3]);
glVertex3fv(b);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (cp) glColor3ubv(&cp[0]);
glNormal3sv(ln[0][0]);
glVertex3fv(a);
@@ -2908,10 +2904,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (cp) glColor3ubv(&cp[0]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (cp) glColor3ubv(&cp[4]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
@@ -2923,10 +2919,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
a = CCG_grid_elem(&key, faceGridData, x, y + 0);
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (cp) glColor3ubv(&cp[12]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (cp) glColor3ubv(&cp[8]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
@@ -2946,13 +2942,13 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
ccgDM_glNormalFast(a, b, c, d);
- if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+ if (cp) glColor3ubv(&cp[4]);
glVertex3fv(d);
- if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+ if (cp) glColor3ubv(&cp[8]);
glVertex3fv(c);
- if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+ if (cp) glColor3ubv(&cp[12]);
glVertex3fv(b);
- if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+ if (cp) glColor3ubv(&cp[0]);
glVertex3fv(a);
if (cp) cp += 16;
@@ -3568,10 +3564,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
}
else if (ob->type == OB_MESH) {
Mesh *me = ob->data;
+ const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+
+ looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */
- BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
- me->totface, me->totvert, &me->vdata);
+ BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
+ looptri, looptris_num);
}
if (ccgdm->pbvh)
@@ -3585,6 +3586,47 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* Nothing to do: CCG handles creating its own tessfaces */
}
+static void ccgDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
+{
+ /* Nothing to do: CCG tessellation is known,
+ * allocate and fill in with ccgDM_getLoopTriArray */
+}
+
+static const MLoopTri *ccgDM_getLoopTriArray(DerivedMesh *dm)
+{
+ if (dm->looptris.array) {
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ }
+ else {
+ MLoopTri *mlooptri;
+ const int tottri = dm->numTessFaceData * 2;
+ int i, poly_index;
+
+ DM_ensure_looptri_data(dm);
+ mlooptri = dm->looptris.array;
+
+ BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+ BLI_assert(tottri == dm->looptris.num);
+
+ for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
+ MLoopTri *lt;
+ lt = &mlooptri[i];
+ /* quad is (0, 3, 2, 1) */
+ lt->tri[0] = (poly_index * 4) + 0;
+ lt->tri[1] = (poly_index * 4) + 3;
+ lt->tri[2] = (poly_index * 4) + 2;
+ lt->poly = poly_index;
+
+ lt = &mlooptri[i + 1];
+ lt->tri[0] = (poly_index * 4) + 0;
+ lt->tri[1] = (poly_index * 4) + 2;
+ lt->tri[2] = (poly_index * 4) + 1;
+ lt->poly = poly_index;
+ }
+ }
+ return dm->looptris.array;
+}
+
static void ccgDM_calcNormals(DerivedMesh *dm)
{
/* Nothing to do: CCG calculates normals during drawing */
@@ -3667,6 +3709,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/* reuse of ccgDM_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */
ccgdm->dm.getNumPolys = ccgDM_getNumTessFaces;
+ ccgdm->dm.getLoopTriArray = ccgDM_getLoopTriArray;
+
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
ccgdm->dm.getTessFace = ccgDM_getFinalFace;
@@ -3702,6 +3746,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
+ ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
ccgdm->dm.getVertCos = ccgdm_getVertCos;
ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;