Cleanup: Removed DerivedMesh triangle cache

This was only used in a single place, multires baking, where it's simple
to just retrieve the looptris from the temporary `Mesh` that we already
create to simplify accessing normals. This allows removing a bunch of
complexity from `DerivedMesh`, to help progress towards its complete
removal at some point in the future.

Also use `Span` more instead of raw pointers in multires baking,
and pass around the spans instead of the low-resolution DerivedMesh.
This commit is contained in:
Hans Goudey
2023-04-04 11:26:14 -04:00
parent 85bd64ece4
commit 7adea7ee15
5 changed files with 129 additions and 277 deletions

View File

@@ -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

View File

@@ -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,

View File

@@ -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<const blender::float3 *>(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;

View File

@@ -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;
}

View File

@@ -40,7 +40,12 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
using MPassKnownData = void (*)(DerivedMesh *lores_dm,
using MPassKnownData = void (*)(blender::Span<blender::float3> vert_positions,
blender::Span<blender::float3> vert_normals,
blender::Span<MPoly> polys,
blender::Span<int> corner_verts,
blender::Span<MLoopTri> looptris,
blender::Span<blender::float2> 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<blender::float3> vert_positions;
blender::Span<MPoly> polys;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> poly_normals;
blender::Span<blender::float2> 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<const blender::float3 *>(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<float(*)[2]>(dm->getLoopDataArray(dm, CD_PROP_FLOAT2));
const blender::Span<blender::float2> uv_map(
reinterpret_cast<const blender::float2 *>(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<const blender::float3 *>(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<blender::float3> positions = temp_mesh->vert_positions();
const blender::Span<MPoly> polys = temp_mesh->polys();
const blender::Span<int> corner_verts = temp_mesh->corner_verts();
const blender::Span<blender::float3> vert_normals = temp_mesh->vert_normals();
const blender::Span<blender::float3> poly_normals = temp_mesh->poly_normals();
const blender::Span<MLoopTri> 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<const float(*)[3]>(positions.data()),
dm->getPolyArray(dm),
dm->getNumPolys(dm),
dm->getCornerVertArray(dm),
dm->getLoopTriArray(dm),
dm->getNumLoopTri(dm),
looptris.data(),
looptris.size(),
static_cast<const bool *>(
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<MultiresBakeThread>(tot_thread, "do_multires_bake handles");
blender::Array<MultiresBakeThread> 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<const int *>(
CustomData_get_layer_named(&dm->polyData, CD_PROP_INT32, "material_index"));
handle->data.sharp_faces = static_cast<const bool *>(
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<MPoly> 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<blender::float3> vert_positions,
const blender::Span<blender::float3> vert_normals,
const blender::Span<int> 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<blender::float3> vert_positions,
const blender::Span<blender::float3> vert_normals,
const blender::Span<int> 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<blender::float3> vert_positions,
const blender::Span<blender::float3> vert_normals,
const blender::Span<MPoly> polys,
const blender::Span<int> corner_verts,
const blender::Span<MLoopTri> looptris,
const blender::Span<blender::float2> 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<float(*)[2]>(
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<blender::float3> /*vert_positions*/,
const blender::Span<blender::float3> /*vert_normals*/,
const blender::Span<MPoly> polys,
const blender::Span<int> /*corner_verts*/,
const blender::Span<MLoopTri> looptris,
const blender::Span<blender::float2> 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<float(*)[2]>(
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);