diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 5f2436e14bc..3297226f9e8 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -91,26 +91,8 @@ struct DerivedMesh { int deformedOnly; /* set by modifier stack if only deformed from original */ DerivedMeshType type; - /** - * \warning Typical access is done via #getLoopTriArray, #getNumLoopTri. - */ - struct { - /* WARNING! swapping between array (ready-to-be-used data) and array_wip - * (where data is actually computed) shall always be protected by same - * lock as one used for looptris computing. */ - struct MLoopTri *array, *array_wip; - int num; - int num_alloc; - } looptris; - short tangent_mask; /* which tangent layers are calculated */ - /** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */ - void (*recalcLoopTri)(DerivedMesh *dm); - /** accessor functions */ - const struct MLoopTri *(*getLoopTriArray)(DerivedMesh *dm); - int (*getNumLoopTri)(DerivedMesh *dm); - /* Misc. Queries */ /* Also called in Editmode */ @@ -246,14 +228,6 @@ void DM_copy_vert_data(const struct DerivedMesh *source, int dest_index, int count); -/** - * 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); - /** * Interpolates vertex data from the vertices indexed by `src_indices` in the * source mesh using the given weights and stores the result in the vertex diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 84f6b1a5b9e..381bd66dcf1 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -82,8 +82,6 @@ using blender::VArray; # define ASSERT_IS_VALID_MESH(mesh) #endif -static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; - static void mesh_init_origspace(Mesh *mesh); static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, const CustomData_MeshMasks *final_datamask); @@ -165,37 +163,6 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm) return mpoly; } -static int dm_getNumLoopTri(DerivedMesh *dm) -{ - const int numlooptris = poly_to_tri_count(dm->getNumPolys(dm), dm->getNumLoops(dm)); - BLI_assert(ELEM(dm->looptris.num, 0, numlooptris)); - return numlooptris; -} - -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 != nullptr) { - 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 nullptr inside mutex-protected code, - * some other thread might have already recomputed those looptris. */ - if (dm->looptris.array == nullptr) { - dm->recalcLoopTri(dm); - } - looptri = dm->looptris.array; - BLI_rw_mutex_unlock(&loops_cache_lock); - } - return looptri; -} - void DM_init_funcs(DerivedMesh *dm) { /* default function implementations */ @@ -205,11 +172,6 @@ void DM_init_funcs(DerivedMesh *dm) dm->getCornerEdgeArray = dm_getCornerEdgeArray; dm->getPolyArray = dm_getPolyArray; - dm->getLoopTriArray = dm_getLoopTriArray; - - /* Sub-types handle getting actual data. */ - dm->getNumLoopTri = dm_getNumLoopTri; - dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; dm->getPolyDataArray = DM_get_poly_data_layer; @@ -280,10 +242,6 @@ bool DM_release(DerivedMesh *dm) CustomData_free(&dm->loopData, dm->numLoopData); CustomData_free(&dm->polyData, dm->numPolyData); - MEM_SAFE_FREE(dm->looptris.array); - dm->looptris.num = 0; - dm->looptris.num_alloc = 0; - return true; } @@ -296,34 +254,6 @@ bool DM_release(DerivedMesh *dm) return false; } -void DM_ensure_looptri_data(DerivedMesh *dm) -{ - const uint totpoly = dm->numPolyData; - const uint totloop = dm->numLoopData; - const int looptris_num = poly_to_tri_count(totpoly, totloop); - - BLI_assert(dm->looptris.array_wip == nullptr); - - std::swap(dm->looptris.array, dm->looptris.array_wip); - - if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) || - (totpoly == 0)) { - MEM_SAFE_FREE(dm->looptris.array_wip); - dm->looptris.num_alloc = 0; - dm->looptris.num = 0; - } - - if (totpoly) { - if (dm->looptris.array_wip == nullptr) { - dm->looptris.array_wip = (MLoopTri *)MEM_malloc_arrayN( - looptris_num, sizeof(*dm->looptris.array_wip), __func__); - dm->looptris.num_alloc = looptris_num; - } - - dm->looptris.num = looptris_num; - } -} - void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb) { /* Just a shallow wrapper around #BKE_keyblock_convert_from_mesh, diff --git a/source/blender/blenkernel/intern/cdderivedmesh.cc b/source/blender/blenkernel/intern/cdderivedmesh.cc index 032c21643c1..a6638439c13 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.cc +++ b/source/blender/blenkernel/intern/cdderivedmesh.cc @@ -119,27 +119,6 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3]) copy_v3_v3(r_no, cddm->vert_normals[index]); } -static void cdDM_recalc_looptri(DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - const uint totpoly = dm->numPolyData; - const uint totloop = dm->numLoopData; - - DM_ensure_looptri_data(dm); - BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL); - - blender::bke::mesh::looptris_calc( - {reinterpret_cast(cddm->vert_positions), dm->numVertData}, - {cddm->mpoly, totpoly}, - {cddm->corner_verts, totloop}, - {dm->looptris.array_wip, dm->looptris.num}); - - BLI_assert(cddm->dm.looptris.array == NULL); - atomic_cas_ptr( - (void **)&cddm->dm.looptris.array, cddm->dm.looptris.array, cddm->dm.looptris.array_wip); - cddm->dm.looptris.array_wip = nullptr; -} - static void cdDM_free_internal(CDDerivedMesh *cddm) { if (cddm->pmap) { @@ -180,8 +159,6 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; - dm->recalcLoopTri = cdDM_recalc_looptri; - dm->getVertCo = cdDM_getVertCo; dm->getVertNo = cdDM_getVertNo; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 9d569c470b3..779c247c234 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -1449,40 +1449,6 @@ static BLI_bitmap **ccgDM_getGridHidden(DerivedMesh *dm) return ccgdm->gridHidden; } -/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */ -static void ccgDM_recalcLoopTri(DerivedMesh *dm) -{ - const int tottri = dm->numPolyData * 2; - int i, poly_index; - - DM_ensure_looptri_data(dm); - MLoopTri *mlooptri = dm->looptris.array_wip; - - BLI_assert(tottri == 0 || mlooptri != nullptr); - 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) + 2; - lt->tri[2] = (poly_index * 4) + 3; - lt->poly = poly_index; - - lt = &mlooptri[i + 1]; - lt->tri[0] = (poly_index * 4) + 0; - lt->tri[1] = (poly_index * 4) + 1; - lt->tri[2] = (poly_index * 4) + 2; - lt->poly = poly_index; - } - - BLI_assert(dm->looptris.array == nullptr); - atomic_cas_ptr((void **)&dm->looptris.array, dm->looptris.array, dm->looptris.array_wip); - dm->looptris.array_wip = nullptr; -} - static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) { ccgdm->dm.getNumVerts = ccgDM_getNumVerts; @@ -1510,8 +1476,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats; ccgdm->dm.getGridHidden = ccgDM_getGridHidden; - ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri; - ccgdm->dm.release = ccgDM_release; } diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 96d09dbf721..8976c1f26de 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -40,7 +40,12 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -using MPassKnownData = void (*)(DerivedMesh *lores_dm, +using MPassKnownData = void (*)(blender::Span vert_positions, + blender::Span vert_normals, + blender::Span polys, + blender::Span corner_verts, + blender::Span looptris, + blender::Span uv_map, DerivedMesh *hires_dm, void *thread_data, void *bake_data, @@ -60,21 +65,27 @@ struct MultiresBakeResult { }; struct MResolvePixelData { - const float (*vert_positions)[3]; - const blender::float3 *vert_normals; - int verts_num; - const MPoly *polys; + /* Data from low-resolution mesh. */ + blender::Span vert_positions; + blender::Span polys; + blender::Span corner_verts; + blender::Span looptris; + blender::Span vert_normals; + blender::Span poly_normals; + + blender::Span uv_map; + + /* May be null. */ const int *material_indices; - const int *corner_verts; const bool *sharp_faces; - float (*mloopuv)[2]; + float uv_offset[2]; - const MLoopTri *mlooptri; float *pvtangent; - const blender::float3 *poly_normals; int w, h; int tri_index; - DerivedMesh *lores_dm, *hires_dm; + + DerivedMesh *hires_dm; + int lvl; void *thread_data; void *bake_data; @@ -114,25 +125,15 @@ static void multiresbake_get_normal(const MResolvePixelData *data, const int vert_index, float r_normal[3]) { - const int poly_index = data->mlooptri[tri_num].poly; - const MPoly &poly = data->polys[poly_index]; + const int poly_index = data->looptris[tri_num].poly; const bool smoothnormal = !(data->sharp_faces && data->sharp_faces[poly_index]); if (smoothnormal) { - const int vi = data->corner_verts[data->mlooptri[tri_num].tri[vert_index]]; + const int vi = data->corner_verts[data->looptris[tri_num].tri[vert_index]]; copy_v3_v3(r_normal, data->vert_normals[vi]); } else { - if (data->poly_normals) { - copy_v3_v3(r_normal, data->poly_normals[poly_index]); - } - else { - copy_v3_v3( - r_normal, - blender::bke::mesh::poly_normal_calc( - {reinterpret_cast(data->vert_positions), data->verts_num}, - {&data->corner_verts[poly.loopstart], poly.totloop})); - } + copy_v3_v3(r_normal, data->poly_normals[poly_index]); } } @@ -165,9 +166,9 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) float u, v, w, sign; int r; - st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]]; - st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]]; - st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]]; + st0 = data->uv_map[data->looptris[data->tri_index].tri[0]]; + st1 = data->uv_map[data->looptris[data->tri_index].tri[1]]; + st2 = data->uv_map[data->looptris[data->tri_index].tri[2]]; multiresbake_get_normal(data, data->tri_index, 0, no0); /* can optimize these 3 into one call */ multiresbake_get_normal(data, data->tri_index, 1, no1); @@ -180,9 +181,9 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) w = 1 - u - v; if (data->pvtangent) { - tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4; - tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4; - tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4; + tang0 = data->pvtangent + data->looptris[data->tri_index].tri[0] * 4; + tang1 = data->pvtangent + data->looptris[data->tri_index].tri[1] * 4; + tang2 = data->pvtangent + data->looptris[data->tri_index].tri[2] * 4; /* the sign is the same at all face vertices for any non degenerate face. * Just in case we clamp the interpolated value though. */ @@ -203,7 +204,12 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) zero_m3(to_tang); } - data->pass_data(data->lores_dm, + data->pass_data(data->vert_positions, + data->vert_normals, + data->polys, + data->corner_verts, + data->looptris, + data->uv_map, data->hires_dm, data->thread_data, data->bake_data, @@ -388,9 +394,8 @@ static void *do_multires_bake_thread(void *data_v) int tri_index; while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) { - const MLoopTri *lt = &data->mlooptri[tri_index]; + const MLoopTri *lt = &data->looptris[tri_index]; const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[lt->poly]; - const float(*mloopuv)[2] = data->mloopuv; if (multiresbake_test_break(bkr)) { break; @@ -404,9 +409,9 @@ static void *do_multires_bake_thread(void *data_v) data->tri_index = tri_index; float uv[3][2]; - sub_v2_v2v2(uv[0], mloopuv[lt->tri[0]], data->uv_offset); - sub_v2_v2v2(uv[1], mloopuv[lt->tri[1]], data->uv_offset); - sub_v2_v2v2(uv[2], mloopuv[lt->tri[2]], data->uv_offset); + sub_v2_v2v2(uv[0], data->uv_map[lt->tri[0]], data->uv_offset); + sub_v2_v2v2(uv[1], data->uv_map[lt->tri[1]], data->uv_offset); + sub_v2_v2v2(uv[2], data->uv_map[lt->tri[2]], data->uv_offset); bake_rasterize(bake_rast, uv[0], uv[1], uv[2]); @@ -468,19 +473,17 @@ static void do_multires_bake(MultiresBakeRender *bkr, MultiresBakeResult *result) { DerivedMesh *dm = bkr->lores_dm; - const MLoopTri *mlooptri = dm->getLoopTriArray(dm); const int lvl = bkr->lvl; - int tot_tri = dm->getNumLoopTri(dm); - if (tot_tri < 1) { + if (dm->getNumPolys(dm) == 0) { return; } - MultiresBakeThread *handles; MultiresBakeQueue queue; - const float(*positions)[3] = (float(*)[3])dm->getVertArray(dm); - const MPoly *polys = dm->getPolyArray(dm); - float(*mloopuv)[2] = static_cast(dm->getLoopDataArray(dm, CD_PROP_FLOAT2)); + const blender::Span uv_map( + reinterpret_cast(dm->getLoopDataArray(dm, CD_PROP_FLOAT2)), + dm->getNumLoops(dm)); + float *pvtangent = nullptr; ListBase threads; @@ -490,25 +493,29 @@ static void do_multires_bake(MultiresBakeRender *bkr, Mesh *temp_mesh = BKE_mesh_new_nomain( dm->getNumVerts(dm), dm->getNumEdges(dm), dm->getNumLoops(dm), dm->getNumPolys(dm)); - memcpy(temp_mesh->vert_positions_for_write().data(), - positions, - temp_mesh->totvert * sizeof(float[3])); + temp_mesh->vert_positions_for_write().copy_from( + {reinterpret_cast(dm->getVertArray(dm)), temp_mesh->totvert}); temp_mesh->edges_for_write().copy_from({dm->getEdgeArray(dm), temp_mesh->totedge}); temp_mesh->polys_for_write().copy_from({dm->getPolyArray(dm), temp_mesh->totpoly}); temp_mesh->corner_verts_for_write().copy_from({dm->getCornerVertArray(dm), temp_mesh->totloop}); temp_mesh->corner_edges_for_write().copy_from({dm->getCornerEdgeArray(dm), temp_mesh->totloop}); + + const blender::Span positions = temp_mesh->vert_positions(); + const blender::Span polys = temp_mesh->polys(); + const blender::Span corner_verts = temp_mesh->corner_verts(); const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); + const blender::Span looptris = temp_mesh->looptris(); if (require_tangent) { if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { BKE_mesh_calc_loop_tangent_ex( - positions, + reinterpret_cast(positions.data()), dm->getPolyArray(dm), dm->getNumPolys(dm), dm->getCornerVertArray(dm), - dm->getLoopTriArray(dm), - dm->getNumLoopTri(dm), + looptris.data(), + looptris.size(), static_cast( CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")), &dm->loopData, @@ -537,13 +544,13 @@ static void do_multires_bake(MultiresBakeRender *bkr, BLI_threadpool_init(&threads, do_multires_bake_thread, tot_thread); } - handles = MEM_cnew_array(tot_thread, "do_multires_bake handles"); + blender::Array handles(tot_thread); init_ccgdm_arrays(bkr->hires_dm); /* faces queue */ queue.cur_tri = 0; - queue.tot_tri = tot_tri; + queue.tot_tri = looptris.size(); BLI_spin_init(&queue.spin); /* fill in threads handles */ @@ -554,23 +561,21 @@ static void do_multires_bake(MultiresBakeRender *bkr, handle->image = ima; handle->queue = &queue; + handle->data.vert_positions = positions; handle->data.polys = polys; + handle->data.corner_verts = corner_verts; + handle->data.looptris = looptris; + handle->data.vert_normals = vert_normals; + handle->data.poly_normals = poly_normals; handle->data.material_indices = static_cast( CustomData_get_layer_named(&dm->polyData, CD_PROP_INT32, "material_index")); handle->data.sharp_faces = static_cast( CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")); - handle->data.vert_positions = positions; - handle->data.vert_normals = vert_normals.data(); - handle->data.verts_num = dm->getNumVerts(dm); - handle->data.mloopuv = mloopuv; + handle->data.uv_map = uv_map; BKE_image_get_tile_uv(ima, tile->tile_number, handle->data.uv_offset); - handle->data.mlooptri = mlooptri; - handle->data.corner_verts = dm->getCornerVertArray(dm); handle->data.pvtangent = pvtangent; - handle->data.poly_normals = poly_normals.data(); /* don't strictly need this */ handle->data.w = ibuf->x; handle->data.h = ibuf->y; - handle->data.lores_dm = dm; handle->data.hires_dm = bkr->hires_dm; handle->data.lvl = lvl; handle->data.pass_data = passKnownData; @@ -612,8 +617,6 @@ static void do_multires_bake(MultiresBakeRender *bkr, freeBakeData(bake_data); } - MEM_freeN(handles); - BKE_id_free(nullptr, temp_mesh); } @@ -651,7 +654,7 @@ static void interp_bilinear_grid( interp_bilinear_quad_v3(data, u, v, res); } -static void get_ccgdm_data(DerivedMesh *lodm, +static void get_ccgdm_data(const blender::Span lores_polys, DerivedMesh *hidm, const int *index_mp_to_orig, const int lvl, @@ -676,7 +679,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, if (lvl == 0) { face_side = (grid_size << 1) - 1; - const MPoly &poly = lodm->getPolyArray(lodm)[poly_index]; + const MPoly &poly = lores_polys[poly_index]; g_index = grid_offset[poly_index]; S = mdisp_rot_face_to_crn( &poly, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); @@ -720,8 +723,9 @@ static void get_ccgdm_data(DerivedMesh *lodm, /* mode = 0: interpolate normals, * mode = 1: interpolate coord */ -static void interp_bilinear_mpoly(DerivedMesh *dm, - const int *corner_verts, +static void interp_bilinear_mpoly(const blender::Span vert_positions, + const blender::Span vert_normals, + const blender::Span corner_verts, const MPoly &poly, const float u, const float v, @@ -731,23 +735,24 @@ static void interp_bilinear_mpoly(DerivedMesh *dm, float data[4][3]; if (mode == 0) { - dm->getVertNo(dm, corner_verts[poly.loopstart], data[0]); - dm->getVertNo(dm, corner_verts[poly.loopstart + 1], data[1]); - dm->getVertNo(dm, corner_verts[poly.loopstart + 2], data[2]); - dm->getVertNo(dm, corner_verts[poly.loopstart + 3], data[3]); + copy_v3_v3(data[0], vert_normals[corner_verts[poly.loopstart]]); + copy_v3_v3(data[1], vert_normals[corner_verts[poly.loopstart + 1]]); + copy_v3_v3(data[2], vert_normals[corner_verts[poly.loopstart + 2]]); + copy_v3_v3(data[3], vert_normals[corner_verts[poly.loopstart + 3]]); } else { - dm->getVertCo(dm, corner_verts[poly.loopstart], data[0]); - dm->getVertCo(dm, corner_verts[poly.loopstart + 1], data[1]); - dm->getVertCo(dm, corner_verts[poly.loopstart + 2], data[2]); - dm->getVertCo(dm, corner_verts[poly.loopstart + 3], data[3]); + copy_v3_v3(data[0], vert_positions[corner_verts[poly.loopstart]]); + copy_v3_v3(data[1], vert_positions[corner_verts[poly.loopstart + 1]]); + copy_v3_v3(data[2], vert_positions[corner_verts[poly.loopstart + 2]]); + copy_v3_v3(data[3], vert_positions[corner_verts[poly.loopstart + 3]]); } interp_bilinear_quad_v3(data, u, v, res); } -static void interp_barycentric_mlooptri(DerivedMesh *dm, - const int *corner_verts, +static void interp_barycentric_mlooptri(const blender::Span vert_positions, + const blender::Span vert_normals, + const blender::Span corner_verts, const MLoopTri *lt, const float u, const float v, @@ -757,14 +762,14 @@ static void interp_barycentric_mlooptri(DerivedMesh *dm, float data[3][3]; if (mode == 0) { - dm->getVertNo(dm, corner_verts[lt->tri[0]], data[0]); - dm->getVertNo(dm, corner_verts[lt->tri[1]], data[1]); - dm->getVertNo(dm, corner_verts[lt->tri[2]], data[2]); + copy_v3_v3(data[0], vert_normals[corner_verts[lt->tri[0]]]); + copy_v3_v3(data[1], vert_normals[corner_verts[lt->tri[1]]]); + copy_v3_v3(data[2], vert_normals[corner_verts[lt->tri[2]]]); } else { - dm->getVertCo(dm, corner_verts[lt->tri[0]], data[0]); - dm->getVertCo(dm, corner_verts[lt->tri[1]], data[1]); - dm->getVertCo(dm, corner_verts[lt->tri[2]], data[2]); + copy_v3_v3(data[0], vert_positions[corner_verts[lt->tri[0]]]); + copy_v3_v3(data[1], vert_positions[corner_verts[lt->tri[1]]]); + copy_v3_v3(data[2], vert_positions[corner_verts[lt->tri[2]]]); } interp_barycentric_tri_v3(data, u, v, res); @@ -827,7 +832,12 @@ static void free_heights_data(void *bake_data) * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ -static void apply_heights_callback(DerivedMesh *lores_dm, +static void apply_heights_callback(const blender::Span vert_positions, + const blender::Span vert_normals, + const blender::Span polys, + const blender::Span corner_verts, + const blender::Span looptris, + const blender::Span uv_map, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data, @@ -839,57 +849,50 @@ static void apply_heights_callback(DerivedMesh *lores_dm, const int x, const int y) { - const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; - const int *corner_verts = lores_dm->getCornerVertArray(lores_dm); - const MPoly &poly = lores_dm->getPolyArray(lores_dm)[lt->poly]; - float(*mloopuv)[2] = static_cast( - lores_dm->getLoopDataArray(lores_dm, CD_PROP_FLOAT2)); + const MLoopTri *lt = &looptris[tri_index]; + const MPoly &poly = polys[lt->poly]; MHeightBakeData *height_data = (MHeightBakeData *)bake_data; MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v; - float uv[2], *st0, *st1, *st2, *st3; + float uv[2]; + const float *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float vec[3], p0[3], p1[3], n[3], len; /* ideally we would work on triangles only, however, we rely on quads to get orthogonal * coordinates for use in grid space (triangle barycentric is not orthogonal) */ if (poly.totloop == 4) { - st0 = mloopuv[poly.loopstart]; - st1 = mloopuv[poly.loopstart + 1]; - st2 = mloopuv[poly.loopstart + 2]; - st3 = mloopuv[poly.loopstart + 3]; + st0 = uv_map[poly.loopstart]; + st1 = uv_map[poly.loopstart + 1]; + st2 = uv_map[poly.loopstart + 2]; + st3 = uv_map[poly.loopstart + 3]; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } else { - st0 = mloopuv[lt->tri[0]]; - st1 = mloopuv[lt->tri[1]]; - st2 = mloopuv[lt->tri[2]]; + st0 = uv_map[lt->tri[0]]; + st1 = uv_map[lt->tri[1]]; + st2 = uv_map[lt->tri[2]]; resolve_tri_uv_v2(uv, st, st0, st1, st2); } clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - lores_dm, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, nullptr); + polys, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, nullptr); if (height_data->ssdm) { - get_ccgdm_data(lores_dm, - height_data->ssdm, - height_data->orig_index_mp_to_orig, - 0, - lt, - uv[0], - uv[1], - p0, - n); + get_ccgdm_data( + polys, height_data->ssdm, height_data->orig_index_mp_to_orig, 0, lt, uv[0], uv[1], p0, n); } else { if (poly.totloop == 4) { - interp_bilinear_mpoly(lores_dm, corner_verts, poly, uv[0], uv[1], 1, p0); - interp_bilinear_mpoly(lores_dm, corner_verts, poly, uv[0], uv[1], 0, n); + interp_bilinear_mpoly(vert_positions, vert_normals, corner_verts, poly, uv[0], uv[1], 1, p0); + interp_bilinear_mpoly(vert_positions, vert_normals, corner_verts, poly, uv[0], uv[1], 0, n); } else { - interp_barycentric_mlooptri(lores_dm, corner_verts, lt, uv[0], uv[1], 1, p0); - interp_barycentric_mlooptri(lores_dm, corner_verts, lt, uv[0], uv[1], 0, n); + interp_barycentric_mlooptri( + vert_positions, vert_normals, corner_verts, lt, uv[0], uv[1], 1, p0); + interp_barycentric_mlooptri( + vert_positions, vert_normals, corner_verts, lt, uv[0], uv[1], 0, n); } } @@ -943,7 +946,12 @@ static void free_normal_data(void *bake_data) * - Multiply it by tangmat. * - Vector in color space would be `norm(vec) / 2 + (0.5, 0.5, 0.5)`. */ -static void apply_tangmat_callback(DerivedMesh *lores_dm, +static void apply_tangmat_callback(const blender::Span /*vert_positions*/, + const blender::Span /*vert_normals*/, + const blender::Span polys, + const blender::Span /*corner_verts*/, + const blender::Span looptris, + const blender::Span uv_map, DerivedMesh *hires_dm, void * /*thread_data*/, void *bake_data, @@ -955,35 +963,34 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, const int x, const int y) { - const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; - const MPoly &poly = lores_dm->getPolyArray(lores_dm)[lt->poly]; - float(*mloopuv)[2] = static_cast( - lores_dm->getLoopDataArray(lores_dm, CD_PROP_FLOAT2)); + const MLoopTri *lt = &looptris[tri_index]; + const MPoly &poly = polys[lt->poly]; MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; - float uv[2], *st0, *st1, *st2, *st3; + float uv[2]; + const float *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5}; /* ideally we would work on triangles only, however, we rely on quads to get orthogonal * coordinates for use in grid space (triangle barycentric is not orthogonal) */ if (poly.totloop == 4) { - st0 = mloopuv[poly.loopstart]; - st1 = mloopuv[poly.loopstart + 1]; - st2 = mloopuv[poly.loopstart + 2]; - st3 = mloopuv[poly.loopstart + 3]; + st0 = uv_map[poly.loopstart]; + st1 = uv_map[poly.loopstart + 1]; + st2 = uv_map[poly.loopstart + 2]; + st3 = uv_map[poly.loopstart + 3]; resolve_quad_uv_v2(uv, st, st0, st1, st2, st3); } else { - st0 = mloopuv[lt->tri[0]]; - st1 = mloopuv[lt->tri[1]]; - st2 = mloopuv[lt->tri[2]]; + st0 = uv_map[lt->tri[0]]; + st1 = uv_map[lt->tri[1]]; + st2 = uv_map[lt->tri[2]]; resolve_tri_uv_v2(uv, st, st0, st1, st2); } clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - lores_dm, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], nullptr, n); + polys, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], nullptr, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3_length(vec, 0.5);