From 595a491e63d6f3f3462675d38cfa71b4e784fe9c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Jul 2015 03:36:03 +1000 Subject: 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! --- source/blender/blenkernel/BKE_DerivedMesh.h | 25 +- source/blender/blenkernel/BKE_cdderivedmesh.h | 2 + source/blender/blenkernel/BKE_mesh.h | 11 + source/blender/blenkernel/BKE_paint.h | 4 +- source/blender/blenkernel/BKE_pbvh.h | 10 +- source/blender/blenkernel/intern/DerivedMesh.c | 123 +++- source/blender/blenkernel/intern/cdderivedmesh.c | 773 +++++++++------------ source/blender/blenkernel/intern/editderivedmesh.c | 44 ++ source/blender/blenkernel/intern/mesh_evaluate.c | 176 +++++ source/blender/blenkernel/intern/paint.c | 9 +- source/blender/blenkernel/intern/pbvh.c | 132 ++-- source/blender/blenkernel/intern/pbvh_intern.h | 4 +- source/blender/blenkernel/intern/subsurf_ccg.c | 199 ++++-- source/blender/blenlib/BLI_math_geom.h | 5 + source/blender/blenlib/intern/math_geom.c | 34 + source/blender/editors/mesh/editface.c | 39 +- source/blender/editors/sculpt_paint/paint_vertex.c | 204 +----- source/blender/editors/space_view3d/drawmesh.c | 137 ++-- source/blender/gpu/GPU_buffers.h | 9 +- source/blender/gpu/intern/gpu_buffers.c | 174 +++-- source/blender/makesdna/DNA_customdata_types.h | 2 +- source/blender/makesdna/DNA_meshdata_types.h | 11 + 22 files changed, 1109 insertions(+), 1018 deletions(-) (limited to 'source/blender') 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; diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 359e2a97d9f..5734d0125c7 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -300,6 +300,11 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f /********************************** Normals **********************************/ +void accumulate_vertex_normals_tri( + float n1[3], float n2[3], float n3[3], + const float f_no[3], + const float co1[3], const float co2[3], const float co3[3]); + void accumulate_vertex_normals( float n1[3], float n2[3], float n3[3], float n4[3], const float f_no[3], diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index f40f1cc3f97..4662762ad21 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -3549,6 +3549,40 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f /********************************* Normals **********************************/ +void accumulate_vertex_normals_tri( + float n1[3], float n2[3], float n3[3], + const float f_no[3], + const float co1[3], const float co2[3], const float co3[3]) +{ + float vdiffs[3][3]; + const int nverts = 3; + + /* compute normalized edge vectors */ + sub_v3_v3v3(vdiffs[0], co2, co1); + sub_v3_v3v3(vdiffs[1], co3, co2); + sub_v3_v3v3(vdiffs[2], co1, co3); + + normalize_v3(vdiffs[0]); + normalize_v3(vdiffs[1]); + normalize_v3(vdiffs[2]); + + /* accumulate angle weighted face normal */ + { + float *vn[] = {n1, n2, n3}; + const float *prev_edge = vdiffs[nverts - 1]; + int i; + + for (i = 0; i < nverts; i++) { + const float *cur_edge = vdiffs[i]; + const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + + /* accumulate */ + madd_v3_v3fl(vn[i], f_no, fac); + prev_edge = cur_edge; + } + } +} + void accumulate_vertex_normals( float n1[3], float n2[3], float n3[3], float n4[3], const float f_no[3], diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index ca3c8a97d40..0017cd3c2ae 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -62,9 +62,8 @@ void paintface_flush_flags(Object *ob) Mesh *me = BKE_mesh_from_object(ob); DerivedMesh *dm = ob->derivedFinal; MPoly *polys, *mp_orig; - MFace *faces; const int *index_array = NULL; - int totface, totpoly; + int totpoly; int i; if (me == NULL) @@ -79,26 +78,7 @@ void paintface_flush_flags(Object *ob) if (dm == NULL) return; - /* - * Try to push updated mesh poly flags to three other data sets: - * - Mesh polys => Mesh tess faces - * - Mesh polys => Final derived polys - * - Final derived polys => Final derived tessfaces - */ - - if ((index_array = CustomData_get_layer(&me->fdata, CD_ORIGINDEX))) { - faces = me->mface; - totface = me->totface; - - /* loop over tessfaces */ - for (i = 0; i < totface; i++) { - if (index_array[i] != ORIGINDEX_NONE) { - /* Copy flags onto the original tessface from its original poly */ - mp_orig = me->mpoly + index_array[i]; - faces[i].flag = mp_orig->flag; - } - } - } + /* Mesh polys => Final derived polys */ if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) { polys = dm->getPolyArray(dm); @@ -113,21 +93,6 @@ void paintface_flush_flags(Object *ob) } } } - - if ((index_array = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))) { - polys = dm->getPolyArray(dm); - faces = dm->getTessFaceArray(dm); - totface = dm->getNumTessFaces(dm); - - /* loop over tessfaces */ - for (i = 0; i < totface; i++) { - if (index_array[i] != ORIGINDEX_NONE) { - /* Copy flags onto the final tessface from its final poly */ - mp_orig = polys + index_array[i]; - faces[i].flag = mp_orig->flag; - } - } - } } void paintface_hide(Object *ob, const bool unselected) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index e34bcf7c97b..cafc773c48c 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -91,45 +91,6 @@ static bool vertex_paint_use_fast_update_check(Object *ob) return false; } -/* if the polygons from the mesh and the 'derivedFinal' match - * we can assume that no modifiers are applied and that its worth adding tessellated faces - * so 'vertex_paint_use_fast_update_check()' returns true */ -static bool vertex_paint_use_tessface_check(Object *ob, Mesh *me) -{ - DerivedMesh *dm = ob->derivedFinal; - - if (me && dm) { - return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY)); - } - - return false; -} - -static void update_tessface_data(Object *ob, Mesh *me) -{ - if (vertex_paint_use_tessface_check(ob, me)) { - /* assume if these exist, that they are up to date & valid */ - if (!me->mcol || !me->mface) { - /* should always be true */ - /* XXX Why this clearing? tessface_calc will reset it anyway! */ -#if 0 - if (me->mcol) { - memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); - } -#endif - - /* create tessfaces because they will be used for drawing & fast updates */ - BKE_mesh_tessface_calc(me); /* does own call to update pointers */ - } - } - else { - if (me->totface) { - /* this wont be used, theres no need to keep it */ - BKE_mesh_tessface_clear(me); - } - } - -} /* polling - retrieve whether cursor should be set or operator should be done */ /* Returns true if vertex paint mode is active */ @@ -205,80 +166,7 @@ unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp) return *(unsigned int *)col; } -static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) -{ - /* if no mcol: do not do */ - /* if tface: only the involved faces, otherwise all */ - const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - MFace *mface; - int a; - short *scolmain, *scol; - char *mcol; - const bool *mftag; - - if (me->mcol == NULL || me->totvert == 0 || me->totface == 0) return; - - scolmain = MEM_callocN(4 * sizeof(short) * me->totvert, "colmain"); - - mface = me->mface; - mcol = (char *)me->mcol; - for (a = me->totface; a > 0; a--, mface++, mcol += 16) { - if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) { - scol = scolmain + 4 * mface->v1; - scol[0]++; scol[1] += mcol[1]; scol[2] += mcol[2]; scol[3] += mcol[3]; - scol = scolmain + 4 * mface->v2; - scol[0]++; scol[1] += mcol[5]; scol[2] += mcol[6]; scol[3] += mcol[7]; - scol = scolmain + 4 * mface->v3; - scol[0]++; scol[1] += mcol[9]; scol[2] += mcol[10]; scol[3] += mcol[11]; - if (mface->v4) { - scol = scolmain + 4 * mface->v4; - scol[0]++; scol[1] += mcol[13]; scol[2] += mcol[14]; scol[3] += mcol[15]; - } - } - } - - a = me->totvert; - scol = scolmain; - while (a--) { - if (scol[0] > 1) { - scol[1] = divide_round_i(scol[1], scol[0]); - scol[2] = divide_round_i(scol[2], scol[0]); - scol[3] = divide_round_i(scol[3], scol[0]); - } - scol += 4; - } - - mface = me->mface; - mcol = (char *)me->mcol; - mftag = mfacetag; - for (a = me->totface; a > 0; a--, mface++, mcol += 16, mftag += 4) { - if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) { - if (mftag[0]) { - scol = scolmain + 4 * mface->v1; - mcol[1] = scol[1]; mcol[2] = scol[2]; mcol[3] = scol[3]; - } - - if (mftag[1]) { - scol = scolmain + 4 * mface->v2; - mcol[5] = scol[1]; mcol[6] = scol[2]; mcol[7] = scol[3]; - } - - if (mftag[2]) { - scol = scolmain + 4 * mface->v3; - mcol[9] = scol[1]; mcol[10] = scol[2]; mcol[11] = scol[3]; - } - - if (mface->v4 && mftag[3]) { - scol = scolmain + 4 * mface->v4; - mcol[13] = scol[1]; mcol[14] = scol[2]; mcol[15] = scol[3]; - } - } - } - - MEM_freeN(scolmain); -} - -static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface) +static void do_shared_vertexcol(Mesh *me, bool *mlooptag) { const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; MPoly *mp; @@ -332,10 +220,6 @@ static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const } MEM_freeN(scol); - - if (has_shared && do_tessface) { - do_shared_vertex_tesscol(me, mfacetag); - } } static bool make_vertexcol(Object *ob) /* single ob */ @@ -352,17 +236,12 @@ static bool make_vertexcol(Object *ob) /* single ob */ /* copies from shadedisplist to mcol */ if (!me->mloopcol && me->totloop) { - if (!me->mcol) { - CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); - } if (!me->mloopcol) { CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); } BKE_mesh_update_customdata_pointers(me, true); } - update_tessface_data(ob, me); - DAG_id_tag_update(&me->id, 0); return (me->mloopcol != NULL); @@ -593,7 +472,7 @@ bool ED_vpaint_smooth(Object *ob) /* remove stale me->mcol, will be added later */ BKE_mesh_tessface_clear(me); - do_shared_vertexcol(me, mlooptag, NULL, false); + do_shared_vertexcol(me, mlooptag); MEM_freeN(mlooptag); @@ -2753,35 +2632,13 @@ typedef struct VPaintData { * array, otherwise we need to refresh the modifier stack */ bool use_fast_update; - /* mpoly -> mface mapping */ - MeshElemMap *polyfacemap; - void *polyfacemap_mem; - /* loops tagged as having been painted, to apply shared vertex color * blending only to modified loops */ bool *mlooptag; - bool *mfacetag; bool is_texbrush; } VPaintData; -static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) -{ - const int *tessface_origindex; - - vd->polyfacemap = NULL; - vd->polyfacemap_mem = NULL; - - tessface_origindex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); - - if (!tessface_origindex) - return; - - BKE_mesh_origindex_map_create(&vd->polyfacemap, (int **)&vd->polyfacemap_mem, - me->totpoly, - tessface_origindex, me->totface); -} - static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2])) { Scene *scene = CTX_data_scene(C); @@ -2804,11 +2661,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f if (me->mloopcol == NULL) return false; - /* Update tessface data if needed - * Added here too because e.g. switching to/from edit mode would remove tessface data, - * yet "fast_update" could still be used! */ - update_tessface_data(ob, me); - /* make mode data storage */ vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData"); paint_stroke_set_mode_data(stroke, vpd); @@ -2825,7 +2677,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f /* are we painting onto a modified mesh?, * if not we can skip face map trickyness */ if (vertex_paint_use_fast_update_check(ob)) { - vpaint_build_poly_facemap(vpd, me); vpd->use_fast_update = true; /* printf("Fast update!\n");*/ } @@ -2837,8 +2688,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f /* to keep tracked of modified loops for shared vertex color blending */ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag"); - if (vpd->use_fast_update) - vpd->mfacetag = MEM_mallocN(sizeof(bool) * me->totface * 4, "VPaintData mfacetag"); } /* for filtering */ @@ -2859,14 +2708,10 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, ViewContext *vc = &vpd->vc; Brush *brush = BKE_paint_brush(&vp->paint); MPoly *mpoly = &me->mpoly[index]; - MFace *mf; - MCol *mc; MLoop *ml; - MLoopCol *mlc; unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart; unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart; bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL; - bool *mftag; float alpha; int i, j; int totloop = mpoly->totloop; @@ -2923,35 +2768,6 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, if (mlooptag) mlooptag[i] = 1; } } - - if (vpd->use_fast_update) { - const MeshElemMap *map = &vpd->polyfacemap[index]; - - /* update vertex colors for tessellations incrementally, - * rather then regenerating the tessellation altogether */ - for (i = 0; i < map->count; i++) { - const int index_tessface = map->indices[i]; - - mf = &me->mface[index_tessface]; - mc = &me->mcol[index_tessface * 4]; - mftag = &vpd->mfacetag[index_tessface * 4]; - - ml = me->mloop + mpoly->loopstart; - mlc = me->mloopcol + mpoly->loopstart; - - for (j = 0; j < totloop; j++, ml++, mlc++) { - /* search for the loop vertex within the tessface */ - const int fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml->v); - if (fidx != -1) { - MESH_MLOOPCOL_TO_MCOL(mlc, mc + fidx); - if (mlooptag) { - mftag[fidx] = mlooptag[j]; - } - } - } - } - } - } static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) @@ -3003,8 +2819,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* clear modified tag for blur tool */ if (vpd->mlooptag) memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop); - if (vpd->mfacetag) - memset(vpd->mfacetag, 0, sizeof(bool) * me->totface * 4); for (index = 0; index < totindex; index++) { if (indexar[index] && indexar[index] <= me->totpoly) { @@ -3016,8 +2830,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* was disabled because it is slow, but necessary for blur */ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { - int do_tessface = vpd->use_fast_update; - do_shared_vertexcol(me, vpd->mlooptag, vpd->mfacetag, do_tessface); + do_shared_vertexcol(me, vpd->mlooptag); } ED_region_tag_redraw(vc->ar); @@ -3046,20 +2859,9 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) /* frees prev buffer */ copy_vpaint_prev(ts->vpaint, NULL, 0); - if (vpd->polyfacemap) { - MEM_freeN(vpd->polyfacemap); - } - - if (vpd->polyfacemap_mem) { - MEM_freeN(vpd->polyfacemap_mem); - } - if (vpd->mlooptag) MEM_freeN(vpd->mlooptag); - if (vpd->mfacetag) - MEM_freeN(vpd->mfacetag); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); MEM_freeN(vpd); diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index b0250dfdec0..9ccacbad4a2 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -80,14 +80,14 @@ typedef struct drawEMTFMapped_userData { BMEditMesh *em; bool has_mcol; int cd_poly_tex_offset; - MFace *mf; - MTFace *tf; + const MPoly *mpoly; + const MTexPoly *mtexpoly; } drawEMTFMapped_userData; typedef struct drawTFace_userData { - Mesh *me; - MFace *mf; - MTFace *tf; + const Mesh *me; + const MPoly *mpoly; + const MTexPoly *mtexpoly; } drawTFace_userData; /**************************** Face Select Mode *******************************/ @@ -590,11 +590,12 @@ static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(h static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) { + const MPoly *mp = dm->getPolyArray(dm); + const int mpoly_num = dm->getNumPolys(dm); MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - MFace *mface = dm->getTessFaceArray(dm); - MCol *finalCol; + MLoopCol *finalCol; int i, j; - MCol *mcol = NULL; + MLoopCol *mloopcol = NULL; /* cache material values to avoid a lot of lookups */ Material *ma = NULL; @@ -606,108 +607,94 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) } copy_mode = COPY_CALC; if (use_mcol) { - 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); } - if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) { - finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL); + if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) { + finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL); } else { - finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer"); - - CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData); + finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer"); + CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData); } - for (i = 0; i < dm->getNumTessFaces(dm); i++) { - const short mat_nr = mface[i].mat_nr; + for (i = mpoly_num; i--; mp++) { + const short mat_nr = mp->mat_nr; if (UNLIKELY(mat_nr_prev != mat_nr)) { - ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1); + ma = give_current_material(Gtexdraw.ob, mat_nr + 1); copy_mode = COPY_CALC; mat_nr_prev = mat_nr; } /* avoid lookups */ if (copy_mode == COPY_ORIG) { - memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4); + memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); } else if (copy_mode == COPY_PREV) { - memcpy(&finalCol[i * 4], &finalCol[(i - 1) * 4], sizeof(MCol) * 4); + int loop_index = mp->loopstart; + const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart]; + for (j = 0; j < mp->totloop; j++, loop_index++) { + finalCol[loop_index] = *lcol_prev; + } } /* (copy_mode == COPY_CALC) */ else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) { - if (mcol) { - memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4); + if (mloopcol) { + memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); copy_mode = COPY_ORIG; } else { - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j].b = 255; - finalCol[i * 4 + j].g = 255; - finalCol[i * 4 + j].r = 255; - } + memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); copy_mode = COPY_PREV; } } else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) { - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j].b = 255; - finalCol[i * 4 + j].g = 0; - finalCol[i * 4 + j].r = 255; + int loop_index = mp->loopstart; + for (j = 0; j < mp->totloop; j++, loop_index++) { + finalCol[loop_index].r = 255; + finalCol[loop_index].g = 0; + finalCol[loop_index].b = 255; } copy_mode = COPY_PREV; } else if (ma && (ma->shade_flag & MA_OBCOLOR)) { - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j].b = Gtexdraw.obcol[0]; - finalCol[i * 4 + j].g = Gtexdraw.obcol[1]; - finalCol[i * 4 + j].r = Gtexdraw.obcol[2]; + int loop_index = mp->loopstart;; + for (j = 0; j < mp->totloop; j++, loop_index++) { + copy_v3_v3_char(&finalCol[loop_index].r, (char *)Gtexdraw.obcol); } copy_mode = COPY_PREV; } else { - if (mcol) { - memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4); + if (mloopcol) { + memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); copy_mode = COPY_ORIG; } else if (mtexpoly) { - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j].b = 255; - finalCol[i * 4 + j].g = 255; - finalCol[i * 4 + j].r = 255; - } + memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); copy_mode = COPY_PREV; } else { - if (ma) { - float col[3]; - MCol tcol; - - if (Gtexdraw.color_profile) { - linearrgb_to_srgb_v3_v3(col, &ma->r); - } - else { - copy_v3_v3(col, &ma->r); - } + float col[3]; - tcol.b = FTOCHAR(col[0]); - tcol.g = FTOCHAR(col[1]); - tcol.r = FTOCHAR(col[2]); - tcol.a = 255; + if (ma) { + int loop_index = mp->loopstart; + MLoopCol lcol; - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j] = tcol; + if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); + else copy_v3_v3(col, &ma->r); + rgb_float_to_uchar((unsigned char *)&lcol.r, col); + lcol.a = 255; + + for (j = 0; j < mp->totloop; j++, loop_index++) { + finalCol[loop_index] = lcol; } } else { - for (j = 0; j < 4; j++) { - finalCol[i * 4 + j].b = 255; - finalCol[i * 4 + j].g = 255; - finalCol[i * 4 + j].r = 255; - } + memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); } copy_mode = COPY_PREV; } @@ -717,7 +704,7 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr)) { - Mesh *me = ((drawTFace_userData *)userData)->me; + const Mesh *me = ((drawTFace_userData *)userData)->me; /* array checked for NULL before calling */ MPoly *mpoly = &me->mpoly[origindex]; @@ -915,10 +902,10 @@ static int compareDrawOptions(void *userData, int cur_index, int next_index) { drawTFace_userData *data = userData; - if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr) + if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) return 0; - if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage) + if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) return 0; return 1; @@ -929,10 +916,10 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index) { drawEMTFMapped_userData *data = userData; - if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr) + if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr) return 0; - if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage) + if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage) return 0; return 1; @@ -964,8 +951,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL); data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY); - data.mf = DM_get_tessface_data_layer(dm, CD_MFACE); - data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); + data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0); } @@ -976,8 +963,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d else { drawTFace_userData userData; - userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE); - userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); + userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); userData.me = me; dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag); } @@ -987,8 +974,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT)); - userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE); - userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY); + userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); userData.me = NULL; dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag); diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 9c2ca6c5305..12e66264661 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -212,9 +212,12 @@ void GPU_interleaved_attrib_unbind(void); typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers; /* build */ -GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4], - const struct MFace *mface, const struct MVert *mvert, - const int *face_indices, int totface); +GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( + const int (*face_vert_indices)[4], + const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri, + const struct MVert *verts, + const int *face_indices, + const int face_indices_len); GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, unsigned int **grid_hidden, int gridsize, const struct CCGKey *key); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index d30ca9f27df..cd3a5d6d725 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -644,11 +644,11 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) /* special handling for MCol and UV buffers */ if (type == GPU_BUFFER_COLOR) { - if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType))) + if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType))) return NULL; } else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) { - if (!DM_get_tessface_data_layer(dm, CD_MTFACE)) + if (!DM_get_loop_data_layer(dm, CD_MLOOPUV)) return NULL; } @@ -1090,10 +1090,13 @@ struct GPU_PBVH_Buffers { GLenum index_type; /* mesh pointers in case buffer allocation fails */ - const MFace *mface; + const MPoly *mpoly; + const MLoop *mloop; + const MLoopTri *looptri; const MVert *mvert; + const int *face_indices; - int totface; + int face_indices_len; const float *vmask; /* grid pointers */ @@ -1177,7 +1180,7 @@ void GPU_update_mesh_pbvh_buffers( const int (*face_vert_indices)[4], bool show_diffuse_color) { VertexBufferFormat *vert_data; - int i, j, k; + int i, j; buffers->vmask = vmask; buffers->show_diffuse_color = show_diffuse_color; @@ -1190,9 +1193,10 @@ void GPU_update_mesh_pbvh_buffers( if (buffers->use_matcaps) diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; else if (show_diffuse_color) { - const MFace *f = buffers->mface + buffers->face_indices[0]; + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; + const MPoly *mp = &buffers->mpoly[lt->poly]; - GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); } copy_v4_v4(buffers->diffuse_color, diffuse_color); @@ -1225,72 +1229,61 @@ void GPU_update_mesh_pbvh_buffers( rgb_float_to_uchar(out->color, diffuse_color); \ } (void)0 - for (i = 0; i < buffers->totface; i++) { - const MFace *f = buffers->mface + buffers->face_indices[i]; - - UPDATE_VERTEX(i, f->v1, 0, diffuse_color); - UPDATE_VERTEX(i, f->v2, 1, diffuse_color); - UPDATE_VERTEX(i, f->v3, 2, diffuse_color); - if (f->v4) - UPDATE_VERTEX(i, f->v4, 3, diffuse_color); + for (i = 0; i < buffers->face_indices_len; i++) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; + const unsigned int vtri[3] = { + buffers->mloop[lt->tri[0]].v, + buffers->mloop[lt->tri[1]].v, + buffers->mloop[lt->tri[2]].v, + }; + + UPDATE_VERTEX(i, vtri[0], 0, diffuse_color); + UPDATE_VERTEX(i, vtri[1], 1, diffuse_color); + UPDATE_VERTEX(i, vtri[2], 2, diffuse_color); } #undef UPDATE_VERTEX } else { - for (i = 0; i < buffers->totface; ++i) { - const MFace *f = &buffers->mface[buffers->face_indices[i]]; - const unsigned int *fv = &f->v1; - const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}}; + for (i = 0; i < buffers->face_indices_len; ++i) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; + const unsigned int vtri[3] = { + buffers->mloop[lt->tri[0]].v, + buffers->mloop[lt->tri[1]].v, + buffers->mloop[lt->tri[2]].v, + }; float fno[3]; short no[3]; float fmask; - if (paint_is_face_hidden(f, mvert)) + if (paint_is_face_hidden(lt, mvert, buffers->mloop)) continue; /* Face normal and mask */ - if (f->v4) { - normal_quad_v3(fno, - mvert[fv[0]].co, - mvert[fv[1]].co, - mvert[fv[2]].co, - mvert[fv[3]].co); - if (vmask) { - fmask = (vmask[fv[0]] + - vmask[fv[1]] + - vmask[fv[2]] + - vmask[fv[3]]) * 0.25f; - } - } - else { - normal_tri_v3(fno, - mvert[fv[0]].co, - mvert[fv[1]].co, - mvert[fv[2]].co); - if (vmask) { - fmask = (vmask[fv[0]] + - vmask[fv[1]] + - vmask[fv[2]]) / 3.0f; - } + normal_tri_v3(fno, + mvert[vtri[0]].co, + mvert[vtri[1]].co, + mvert[vtri[2]].co); + if (vmask) { + fmask = (vmask[vtri[0]] + + vmask[vtri[1]] + + vmask[vtri[2]]) / 3.0f; } normal_float_to_short_v3(no, fno); - for (j = 0; j < (f->v4 ? 2 : 1); j++) { - for (k = 0; k < 3; k++) { - const MVert *v = &mvert[fv[vi[j][k]]]; - VertexBufferFormat *out = vert_data; + for (j = 0; j < 3; j++) { + const MVert *v = &mvert[vtri[j]]; + VertexBufferFormat *out = vert_data; - copy_v3_v3(out->co, v->co); - memcpy(out->no, no, sizeof(short) * 3); + copy_v3_v3(out->co, v->co); + copy_v3_v3_short(out->no, no); - if (vmask) - gpu_color_from_mask_copy(fmask, diffuse_color, out->color); - else - rgb_float_to_uchar(out->color, diffuse_color); + if (vmask) + gpu_color_from_mask_copy(fmask, diffuse_color, out->color); + else + rgb_float_to_uchar(out->color, diffuse_color); - vert_data++; - } + vert_data++; } } } @@ -1308,35 +1301,39 @@ void GPU_update_mesh_pbvh_buffers( buffers->mvert = mvert; } -GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4], - const MFace *mface, const MVert *mvert, +GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( + const int (*face_vert_indices)[4], + const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri, + const MVert *mvert, const int *face_indices, - int totface) + const int face_indices_len) { GPU_PBVH_Buffers *buffers; unsigned short *tri_data; - int i, j, k, tottri; + int i, j, tottri; buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); buffers->index_type = GL_UNSIGNED_SHORT; - buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; + buffers->smooth = mpoly[face_indices[0]].flag & ME_SMOOTH; buffers->show_diffuse_color = false; buffers->use_matcaps = false; /* Count the number of visible triangles */ - for (i = 0, tottri = 0; i < totface; ++i) { - const MFace *f = &mface[face_indices[i]]; - if (!paint_is_face_hidden(f, mvert)) - tottri += f->v4 ? 2 : 1; + for (i = 0, tottri = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; + if (!paint_is_face_hidden(lt, mvert, mloop)) + tottri++; } if (tottri == 0) { buffers->tot_tri = 0; - buffers->mface = mface; + buffers->mpoly = mpoly; + buffers->mloop = mloop; + buffers->looptri = looptri; buffers->face_indices = face_indices; - buffers->totface = 0; + buffers->face_indices_len = 0; return buffers; } @@ -1351,26 +1348,16 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4], /* Fill the triangle buffer */ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX); if (tri_data) { - for (i = 0; i < totface; ++i) { - const MFace *f = mface + face_indices[i]; - int v[3]; + for (i = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; /* Skip hidden faces */ - if (paint_is_face_hidden(f, mvert)) + if (paint_is_face_hidden(lt, mvert, mloop)) continue; - v[0] = 0; - v[1] = 1; - v[2] = 2; - - for (j = 0; j < (f->v4 ? 2 : 1); ++j) { - for (k = 0; k < 3; ++k) { - *tri_data = face_vert_indices[i][v[k]]; - tri_data++; - } - v[0] = 3; - v[1] = 0; - v[2] = 2; + for (j = 0; j < 3; ++j) { + *tri_data = face_vert_indices[i][j]; + tri_data++; } } GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX); @@ -1385,9 +1372,12 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4], buffers->tot_tri = tottri; - buffers->mface = mface; + buffers->mpoly = mpoly; + buffers->mloop = mloop; + buffers->looptri = looptri; + buffers->face_indices = face_indices; - buffers->totface = totface; + buffers->face_indices_len = face_indices_len; return buffers; } @@ -1946,9 +1936,10 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, /* sets material from the first face, to solve properly face would need to * be sorted in buckets by materials */ if (setMaterial) { - if (buffers->totface) { - const MFace *f = &buffers->mface[buffers->face_indices[0]]; - if (!setMaterial(f->mat_nr + 1, NULL)) + if (buffers->face_indices_len) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; + const MPoly *mp = &buffers->mpoly[lt->poly]; + if (!setMaterial(mp->mat_nr + 1, NULL)) return; } else if (buffers->totgrid) { @@ -1962,7 +1953,7 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, } } - glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT); + glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT); if (buffers->vert_buf) { char *base = NULL; @@ -2056,10 +2047,11 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, if ((buffers->show_diffuse_color == false) || use_matcaps) return false; - if (buffers->mface) { - const MFace *f = &buffers->mface[buffers->face_indices[0]]; + if (buffers->looptri) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; + const MPoly *mp = &buffers->mpoly[lt->poly]; - GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); } else if (buffers->use_bmesh) { /* due to dynamic nature of dyntopo, only get first material */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index a92c8b3307c..79be28bb1aa 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -99,7 +99,7 @@ typedef enum CustomDataType { CD_MDISPS = 19, CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */ /* CD_ID_MCOL = 21, */ - CD_TEXTURE_MCOL = 22, + CD_TEXTURE_MLOOPCOL = 22, CD_CLOTH_ORCO = 23, CD_RECAST = 24, diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index b76f40c884d..12c6e0ec0a5 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -89,6 +89,14 @@ typedef struct MLoop { unsigned int e; /* edge index */ } MLoop; +/* runtime only */ +# +# +typedef struct MLoopTri { + unsigned int tri[3]; + unsigned int poly; +} MLoopTri; + typedef struct MTexPoly { struct Image *tpage; char flag, transp; @@ -345,6 +353,9 @@ enum { #define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)]) #define ME_POLY_LOOP_NEXT(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + 1) % (mp)->totloop)]) +/* number of tri's that make up this polygon once tessellated */ +#define ME_POLY_TRI_TOT(mp) ((mp)->totloop - 2) + /* mselect->type */ enum { ME_VSEL = 0, -- cgit v1.2.3