diff options
Diffstat (limited to 'source/blender/blenkernel/intern/DerivedMesh.c')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 177 |
1 files changed, 98 insertions, 79 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ae18f5289d4..9dae4c5eae7 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -93,6 +93,10 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); # define ASSERT_IS_VALID_DM(dm) #endif + +static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; + + static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob); static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid); @@ -230,7 +234,33 @@ static MPoly *dm_dupPolyArray(DerivedMesh *dm) static int dm_getNumLoopTri(DerivedMesh *dm) { - return dm->looptris.num; + const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm)); + BLI_assert(ELEM(dm->looptris.num, 0, numlooptris)); + return numlooptris; +} + +static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm) +{ + MLoopTri *looptri; + + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ); + looptri = dm->looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + + if (looptri != NULL) { + BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num); + } + else { + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE); + /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already + * recomputed those looptris. */ + if (dm->looptris.array == NULL) { + dm->recalcLoopTri(dm); + } + looptri = dm->looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + } + return looptri; } static CustomData *dm_getVertCData(DerivedMesh *dm) @@ -276,6 +306,8 @@ void DM_init_funcs(DerivedMesh *dm) dm->dupLoopArray = dm_dupLoopArray; dm->dupPolyArray = dm_dupPolyArray; + dm->getLoopTriArray = dm_getLoopTriArray; + /* subtypes handle getting actual data */ dm->getNumLoopTri = dm_getNumLoopTri; @@ -469,6 +501,8 @@ void DM_ensure_tessface(DerivedMesh *dm) /** * Ensure the array is large enough + * + * /note This function must always be thread-protected by caller. It should only be used by internal code. */ void DM_ensure_looptri_data(DerivedMesh *dm) { @@ -476,18 +510,22 @@ void DM_ensure_looptri_data(DerivedMesh *dm) const unsigned int totloop = dm->numLoopData; const int looptris_num = poly_to_tri_count(totpoly, totloop); + BLI_assert(dm->looptris.array_wip == NULL); + + SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip); + if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) || (totpoly == 0)) { - MEM_SAFE_FREE(dm->looptris.array); + MEM_SAFE_FREE(dm->looptris.array_wip); 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__); + if (dm->looptris.array_wip == NULL) { + dm->looptris.array_wip = MEM_mallocN(sizeof(*dm->looptris.array_wip) * looptris_num, __func__); dm->looptris.num_alloc = looptris_num; } @@ -495,19 +533,6 @@ void DM_ensure_looptri_data(DerivedMesh *dm) } } -/** - * 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); - } -} - void DM_verttri_from_looptri(MVertTri *verttri, const MLoop *mloop, const MLoopTri *looptri, int looptri_num) { int i; @@ -2121,6 +2146,8 @@ static void mesh_calc_modifiers( DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); append_mask |= CD_MASK_PREVIEW_MLOOPCOL; } + + dm->deformedOnly = false; } isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); @@ -2197,7 +2224,6 @@ static void mesh_calc_modifiers( if (dataMask & CD_MASK_MFACE) { DM_ensure_tessface(finaldm); } - DM_ensure_looptri(finaldm); /* 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 @@ -2213,6 +2239,12 @@ static void mesh_calc_modifiers( } } + /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them, + * as they are used by display code when available (i.e. even if autosmooth is disabled). */ + if (!do_loop_normals && CustomData_has_layer(&finaldm->loopData, CD_NORMAL)) { + CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData); + } + #ifdef WITH_GAMEENGINE /* NavMesh - this is a hack but saves having a NavMesh modifier */ if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) { @@ -2455,6 +2487,8 @@ static void editbmesh_calc_modifiers( deformedVerts = NULL; } } + + dm->deformedOnly = false; } /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ @@ -2548,6 +2582,15 @@ static void editbmesh_calc_modifiers( /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */ if (!do_loop_normals) { dm_ensure_display_normals(*r_final); + + /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them, + * as they are used by display code when available (i.e. even if autosmooth is disabled). */ + if (CustomData_has_layer(&(*r_final)->loopData, CD_NORMAL)) { + CustomData_free_layers(&(*r_final)->loopData, CD_NORMAL, (*r_final)->numLoopData); + } + if (r_cage && CustomData_has_layer(&(*r_cage)->loopData, CD_NORMAL)) { + CustomData_free_layers(&(*r_cage)->loopData, CD_NORMAL, (*r_cage)->numLoopData); + } } /* add an orco layer if needed */ @@ -2620,7 +2663,7 @@ static void mesh_build_data( ob->lastDataMask = dataMask; ob->lastNeedMapping = need_mapping; - if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) { + if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { /* create PBVH immediately (would be created on the fly too, * but this avoids waiting on first stroke) */ @@ -2895,9 +2938,6 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em, CustomDa /* get derived mesh from an object, using editbmesh if available. */ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; - if (for_render) { /* TODO(sergey): use proper derived render here in the future. */ return ob->derivedFinal; @@ -2905,9 +2945,13 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) /* only return the editmesh if its from this object because * we don't a mesh from another object's modifier stack: T43122 */ - if (em && (em->ob == ob)) { - DerivedMesh *dm = em->derivedFinal; - return dm; + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + if (em && (em->ob == ob)) { + DerivedMesh *dm = em->derivedFinal; + return dm; + } } return ob->derivedFinal; @@ -3300,7 +3344,8 @@ void DM_calc_loop_tangents_step_0( const CustomData *loopData, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count, bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, - char *ract_uv_name, char *rren_uv_name, char *rtangent_mask) { + char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) +{ /* Active uv in viewport */ int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV); *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV); @@ -3354,21 +3399,22 @@ void DM_calc_loop_tangents_step_0( if (add) *rtangent_mask |= 1 << n; } + + if (uv_layer_num == 0) + *rtangent_mask |= DM_TANGENT_MASK_ORCO; } void DM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count) { - if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV) == 0) - return; int act_uv_n = -1; int ren_uv_n = -1; bool calc_act = false; bool calc_ren = false; char act_uv_name[MAX_NAME]; char ren_uv_name[MAX_NAME]; - char tangent_mask = 0; + short tangent_mask = 0; DM_calc_loop_tangents_step_0( &dm->loopData, calc_active_tangent, tangent_names, tangent_names_count, &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); @@ -3381,6 +3427,8 @@ void DM_calc_loop_tangents( for (int i = 0; i < tangent_names_count; i++) if (tangent_names[i][0]) DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]); + if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) + CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); if (calc_act && act_uv_name[0]) DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name); if (calc_ren && ren_uv_name[0]) @@ -3438,23 +3486,28 @@ void DM_calc_loop_tangents( * have to check this is valid... */ mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL); - mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->faceData, CD_NORMAL); + mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL); mesh2tangent->orco = NULL; mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); + + /* Fill the resulting tangent_mask */ if (!mesh2tangent->mloopuv) { mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO); if (!mesh2tangent->orco) continue; + + dm->tangent_mask |= DM_TANGENT_MASK_ORCO; + } + else { + int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); + int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV); + BLI_assert(uv_ind != -1 && uv_start != -1); + BLI_assert(uv_ind - uv_start < MAX_MTFACE); + dm->tangent_mask |= 1 << (uv_ind - uv_start); } - mesh2tangent->tangent = dm->loopData.layers[index].data; - /* Fill the resulting tangent_mask */ - int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); + mesh2tangent->tangent = dm->loopData.layers[index].data; BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); } @@ -3470,21 +3523,19 @@ void DM_calc_loop_tangents( #endif - int uv_index, tan_index; - /* Update active layer index */ - uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n); - if (uv_index != -1) { - tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name); + int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n); + if (act_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name); CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); - } + } /* else tangent has been built from orco */ /* Update render layer index */ - uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n); - if (uv_index != -1) { - tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name); + int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n); + if (ren_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name); CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); - } + } /* else tangent has been built from orco */ } } @@ -4357,35 +4408,3 @@ MFace *DM_get_tessface_array(DerivedMesh *dm, bool *r_allocated) return mface; } - -const MLoopTri *DM_get_looptri_array( - DerivedMesh *dm, - const MVert *mvert, - const MPoly *mpoly, int mpoly_len, - const MLoop *mloop, int mloop_len, - bool *r_allocated) -{ - const MLoopTri *looptri = dm->getLoopTriArray(dm); - *r_allocated = false; - - if (looptri == NULL) { - if (mpoly_len > 0) { - const int looptris_num = poly_to_tri_count(mpoly_len, mloop_len); - MLoopTri *looptri_data; - - looptri_data = MEM_mallocN(sizeof(MLoopTri) * looptris_num, __func__); - - BKE_mesh_recalc_looptri( - mloop, mpoly, - mvert, - mloop_len, mpoly_len, - looptri_data); - - looptri = looptri_data; - - *r_allocated = true; - } - } - - return looptri; -} |