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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user