diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-07-16 20:36:03 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-07-16 20:55:14 +0300 |
commit | 595a491e63d6f3f3462675d38cfa71b4e784fe9c (patch) | |
tree | df32ec17691b9280d7b2fa675cd5e5a0f87ea849 /source/blender/blenkernel/intern | |
parent | c8f6313487dfbbee030c6796220cc0d91228d658 (diff) |
Add tessellation data to DerivedMesh (LoopTri)
This stores loop indices into the loop array giving easier acess
to data such as vertex-colors and UV's,
removing the need to store an MFace duplicate of custom-data.
This doesn't yet move all internal code from MFace to LoopTri just yet.
Only applies to:
- opengl drawing
- sculpting (pbvh)
- vertex/weight paint
Thanks to @psy-fi for review, fixes and improvements to drawing!
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 123 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 773 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/editderivedmesh.c | 44 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_evaluate.c | 176 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 132 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_intern.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 199 |
8 files changed, 857 insertions, 603 deletions
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; |