Mesh: Split MLoopTri poly indices into a separate array

For derived mesh triangulation information, currently the three face
corner indices are stored in the same struct as index of the mesh
polygon the triangle is part of. While those pieces of information are
often used together, they often aren't, and combining them prevents
the indices from being used with generic utilities. It also means that
1/3 more memory has to be written when recalculating the triangulation
after deforming the mesh, and that the entire triangle data has to be
read when only the polygon indices are needed.

This commit splits the polygon index into a separate cache on `Mesh`.
The triangulation data isn't saved to files, so this doesn't affect
.blend files at all.

In a simple test deforming a mesh with geometry nodes, the time used
to recalculate the triangulation reduced from 2.0 ms to 1.6 ms,
increasing overall FPS from 14.6 to 15.

Pull Request: blender/blender#106774
This commit is contained in:
2023-05-04 15:39:10 +02:00
committed by Hans Goudey
parent bf77d3436d
commit d0705bd697
51 changed files with 416 additions and 225 deletions

View File

@@ -319,10 +319,10 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
}
else {
const int tris_num = b_mesh.loop_triangles.length();
const MLoopTri *looptris = static_cast<const MLoopTri *>(
b_mesh.loop_triangles[0].ptr.data);
const int *looptri_polys = static_cast<const int *>(
b_mesh.loop_triangle_polygons[0].ptr.data);
for (int i = 0; i < tris_num; i++) {
data[i] = get_value_at_index(looptris[i].poly);
data[i] = get_value_at_index(looptri_polys[i]);
}
}
break;
@@ -1095,9 +1095,10 @@ static void create_mesh(Scene *scene,
}
if (material_indices) {
const int *looptri_polys = static_cast<const int *>(
b_mesh.loop_triangle_polygons[0].ptr.data);
for (int i = 0; i < numtris; i++) {
const int poly_index = looptris[i].poly;
shader[i] = clamp_material_index(material_indices[poly_index]);
shader[i] = clamp_material_index(material_indices[looptri_polys[i]]);
}
}
else {
@@ -1105,9 +1106,10 @@ static void create_mesh(Scene *scene,
}
if (sharp_faces && !(use_loop_normals && corner_normals)) {
const int *looptri_polys = static_cast<const int *>(
b_mesh.loop_triangle_polygons[0].ptr.data);
for (int i = 0; i < numtris; i++) {
const int poly_index = looptris[i].poly;
smooth[i] = !sharp_faces[poly_index];
smooth[i] = !sharp_faces[looptri_polys[i]];
}
}
else {

View File

@@ -37,6 +37,8 @@ void looptris_calc_with_normals(Span<float3> vert_positions,
Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris);
void looptris_calc_poly_indices(OffsetIndices<int> polys, MutableSpan<int> looptri_polys);
/** Calculate the average position of the vertices in the polygon. */
float3 poly_center_calc(Span<float3> vert_positions, Span<int> poly_verts);

View File

@@ -211,7 +211,7 @@ void BKE_mesh_origindex_map_create(
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
int **r_mem,
blender::OffsetIndices<int> polys,
const struct MLoopTri *looptri,
const int *looptri_polys,
int looptri_num);
/* islands */

View File

@@ -33,6 +33,7 @@ int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
* \note Prefer #Mesh::looptris() in C++ code.
*/
const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh);
const int *BKE_mesh_runtime_looptri_polys_ensure(const struct Mesh *mesh);
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh);
void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);

View File

@@ -49,7 +49,7 @@ void sample_corner_normals(Span<MLoopTri> looptris,
IndexMask mask,
MutableSpan<float3> dst);
void sample_face_attribute(Span<MLoopTri> looptris,
void sample_face_attribute(Span<int> looptri_polys,
Span<int> looptri_indices,
const GVArray &src,
IndexMask mask,

View File

@@ -60,6 +60,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
blender::OffsetIndices<int> polys,
const int *corner_verts,
const struct MLoopTri *looptri,
const int *looptri_polys,
uint looptri_len,
const bool *sharp_faces,

View File

@@ -119,6 +119,7 @@ struct MeshRuntime {
/** Cache for derived triangulation of the mesh, accessed with #Mesh::looptris(). */
SharedCache<Array<MLoopTri>> looptris_cache;
SharedCache<Array<int>> looptri_polys_cache;
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
BVHCache *bvh_cache = nullptr;

View File

@@ -218,7 +218,7 @@ bool BKE_paint_always_hide_test(struct Object *ob);
/**
* Returns non-zero if any of the face's vertices are hidden, zero otherwise.
*/
bool paint_is_face_hidden(const struct MLoopTri *lt, const bool *hide_poly);
bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, int tri_index);
/**
* Returns non-zero if any of the corners of the grid
* face whose inner corner is at (x, y) are hidden, zero otherwise.

View File

@@ -713,7 +713,7 @@ typedef struct PBVHFaceIter {
bool *hide_poly_;
int *face_sets_;
const int *poly_offsets_;
const struct MLoopTri *looptri_;
const int *looptri_polys_;
const int *corner_verts_;
int prim_index_;
const struct SubdivCCG *subdiv_ccg_;

View File

@@ -134,6 +134,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->runtime->verts_no_face_cache = mesh_src->runtime->verts_no_face_cache;
mesh_dst->runtime->loose_edges_cache = mesh_src->runtime->loose_edges_cache;
mesh_dst->runtime->looptris_cache = mesh_src->runtime->looptris_cache;
mesh_dst->runtime->looptri_polys_cache = mesh_src->runtime->looptri_polys_cache;
/* Only do tessface if we have no polys. */
const bool do_tessface = ((mesh_src->totface != 0) && (mesh_src->totpoly == 0));

View File

@@ -498,7 +498,7 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
int **r_mem,
const blender::OffsetIndices<int> polys,
const MLoopTri *looptri,
const int *looptri_polys,
const int looptri_num)
{
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(polys.size()), __func__);
@@ -514,7 +514,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
/* assign poly-tessface users */
for (int i = 0; i < looptri_num; i++) {
MeshElemMap *map_ele = &map[looptri[i].poly];
MeshElemMap *map_ele = &map[looptri_polys[i]];
map_ele->indices[map_ele->count++] = i;
}

View File

@@ -567,6 +567,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
const blender::Span<int> corner_verts_src = me_src->corner_verts();
const blender::Span<blender::float3> positions_src = me_src->vert_positions();
const blender::Span<blender::float3> vert_normals_dst = me_dst->vert_normals();
const blender::Span<int> looptri_polys = me_src->looptri_polys();
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
float(*vcos)[3] = static_cast<float(*)[3]>(
@@ -591,8 +592,8 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_raycast(
&treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
{
const MLoopTri *lt = &treedata.looptri[rayhit.index];
const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly],
const int poly_index = looptri_polys[rayhit.index];
const int sources_num = mesh_remap_interp_poly_data_get(polys_src[poly_index],
corner_verts_src,
positions_src,
rayhit.co,
@@ -625,11 +626,11 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(
&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
const MLoopTri *lt = &treedata.looptri[nearest.index];
const int poly_index = looptri_polys[rayhit.index];
if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
int index;
mesh_remap_interp_poly_data_get(polys_src[lt->poly],
mesh_remap_interp_poly_data_get(polys_src[poly_index],
corner_verts_src,
positions_src,
nearest.co,
@@ -644,7 +645,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
}
else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) {
const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly],
const int sources_num = mesh_remap_interp_poly_data_get(polys_src[poly_index],
corner_verts_src,
positions_src,
nearest.co,
@@ -870,6 +871,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
const blender::OffsetIndices polys_src = me_src->polys();
const blender::Span<int> corner_edges_src = me_src->corner_edges();
const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src);
const blender::Span<int> looptri_polys = me_src->looptri_polys();
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2);
@@ -886,8 +888,8 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
{
const MLoopTri *lt = &treedata.looptri[nearest.index];
const blender::IndexRange poly_src = polys_src[lt->poly];
const int poly_index = looptri_polys[rayhit.index];
const blender::IndexRange poly_src = polys_src[poly_index];
const int *corner_edge_src = &corner_edges_src[poly_src.start()];
int nloops = int(poly_src.size());
float best_dist_sq = FLT_MAX;
@@ -1302,6 +1304,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const blender::Span<int> corner_verts_src = me_src->corner_verts();
const blender::Span<int> corner_edges_src = me_src->corner_edges();
blender::Span<MLoopTri> looptris_src;
blender::Span<int> looptri_polys_src;
size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
float(*vcos_interp)[3] = nullptr;
@@ -1510,13 +1513,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
else { /* We use polygons. */
if (use_islands) {
looptris_src = me_src->looptris();
looptri_polys_src = me_src->looptri_polys();
blender::BitVector<> looptri_active(looptris_src.size());
for (tindex = 0; tindex < num_trees; tindex++) {
int num_looptri_active = 0;
looptri_active.fill(false);
for (const int64_t i : looptris_src.index_range()) {
const blender::IndexRange poly = polys_src[looptris_src[i].poly];
const blender::IndexRange poly = polys_src[looptri_polys_src[i]];
if (island_store.items_to_islands[poly.start()] == tindex) {
looptri_active[i].set();
num_looptri_active++;
@@ -1547,6 +1551,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
islands_res[tindex] = static_cast<IslandResult *>(
MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__));
}
const blender::Span<int> looptri_polys = me_src->looptri_polys();
for (pidx_dst = 0; pidx_dst < polys_dst.size(); pidx_dst++) {
const blender::IndexRange poly_dst = polys_dst[pidx_dst];
@@ -1703,7 +1708,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
{
islands_res[tindex][plidx_dst].factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) * w;
islands_res[tindex][plidx_dst].hit_dist = hit_dist;
islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[rayhit.index].poly);
islands_res[tindex][plidx_dst].index_src = looptri_polys[rayhit.index];
copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.co);
break;
}
@@ -1732,7 +1737,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(
tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
islands_res[tindex][plidx_dst].hit_dist = hit_dist;
islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[nearest.index].poly);
islands_res[tindex][plidx_dst].index_src = looptri_polys[nearest.index];
copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
}
else {
@@ -1755,7 +1760,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
{
islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
islands_res[tindex][plidx_dst].hit_dist = hit_dist;
islands_res[tindex][plidx_dst].index_src = int(tdata->looptri[nearest.index].poly);
islands_res[tindex][plidx_dst].index_src = looptri_polys[nearest.index];
copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
}
else {
@@ -1980,8 +1985,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
BKE_mesh_origindex_map_create_looptri(&poly_to_looptri_map_src,
&poly_to_looptri_map_src_buff,
polys_src,
looptris_src.data(),
int(looptris_src.size()));
looptri_polys_src.data(),
int(looptri_polys_src.size()));
}
for (j = poly_to_looptri_map_src[pidx_src].count; j--;) {
@@ -2152,6 +2157,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
BVHTreeNearest nearest = {0};
BVHTreeRayHit rayhit = {0};
float hit_dist;
const blender::Span<int> looptri_polys = me_src->looptri_polys();
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2);
@@ -2171,8 +2177,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
{
const MLoopTri *lt = &treedata.looptri[nearest.index];
const int poly_index = int(lt->poly);
const int poly_index = looptri_polys[nearest.index];
mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight);
}
else {
@@ -2199,9 +2204,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_raycast(
&treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
{
const MLoopTri *lt = &treedata.looptri[rayhit.index];
const int poly_index = int(lt->poly);
const int poly_index = looptri_polys[rayhit.index];
mesh_remap_item_define(r_map, int(i), hit_dist, 0, 1, &poly_index, &full_weight);
}
else {
@@ -2355,9 +2358,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
if (mesh_remap_bvhtree_query_raycast(
&treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
{
const MLoopTri *lt = &treedata.looptri[rayhit.index];
weights[lt->poly] += w;
const int poly_index = looptri_polys[rayhit.index];
weights[poly_index] += w;
totweights += w;
hit_dist_accum += hit_dist;
break;

View File

@@ -330,7 +330,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
const VArraySpan<int> src(src_face_sets);
MutableSpan<int> dst = dst_face_sets.span;
const blender::Span<MLoopTri> looptris = source->looptris();
const blender::Span<int> looptri_polys = source->looptri_polys();
BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
@@ -344,7 +344,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
dst[i] = src[looptris[nearest.index].poly];
dst[i] = src[looptri_polys[nearest.index]];
}
else {
dst[i] = 1;

View File

@@ -221,6 +221,17 @@ blender::Span<MLoopTri> Mesh::looptris() const
return this->runtime->looptris_cache.data();
}
blender::Span<int> Mesh::looptri_polys() const
{
using namespace blender;
this->runtime->looptri_polys_cache.ensure([&](blender::Array<int> &r_data) {
const OffsetIndices polys = this->polys();
r_data.reinitialize(poly_to_tri_count(polys.size(), this->totloop));
bke::mesh::looptris_calc_poly_indices(polys, r_data);
});
return this->runtime->looptri_polys_cache.data();
}
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
{
/* Allow returning the size without calculating the cache. */
@@ -232,6 +243,11 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
return mesh->looptris().data();
}
const int *BKE_mesh_runtime_looptri_polys_ensure(const Mesh *mesh)
{
return mesh->looptri_polys().data();
}
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
const int *corner_verts,
const MLoopTri *looptri,
@@ -281,6 +297,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->loose_verts_cache.tag_dirty();
mesh->runtime->verts_no_face_cache.tag_dirty();
mesh->runtime->looptris_cache.tag_dirty();
mesh->runtime->looptri_polys_cache.tag_dirty();
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) {

View File

@@ -107,7 +107,7 @@ void sample_corner_attribute(const Span<MLoopTri> looptris,
}
template<typename T>
void sample_face_attribute(const Span<MLoopTri> looptris,
void sample_face_attribute(const Span<int> looptri_polys,
const Span<int> looptri_indices,
const VArray<T> &src,
const IndexMask mask,
@@ -115,13 +115,12 @@ void sample_face_attribute(const Span<MLoopTri> looptris,
{
for (const int i : mask) {
const int looptri_index = looptri_indices[i];
const MLoopTri &looptri = looptris[looptri_index];
const int poly_index = looptri.poly;
const int poly_index = looptri_polys[looptri_index];
dst[i] = src[poly_index];
}
}
void sample_face_attribute(const Span<MLoopTri> looptris,
void sample_face_attribute(const Span<int> looptri_polys,
const Span<int> looptri_indices,
const GVArray &src,
const IndexMask mask,
@@ -132,7 +131,7 @@ void sample_face_attribute(const Span<MLoopTri> looptris,
const CPPType &type = src.type();
attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);
sample_face_attribute<T>(looptris, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
sample_face_attribute<T>(looptri_polys, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
});
}

View File

@@ -177,8 +177,8 @@ struct SGLSLMeshToTangent {
{
#ifdef USE_LOOPTRI_DETECT_QUADS
if (face_as_quad_map) {
const MLoopTri *lt = &looptri[face_as_quad_map[face_num]];
if (polys[lt->poly].size() == 4) {
const int poly_index = looptri_polys[face_as_quad_map[face_num]];
if (polys[poly_index].size() == 4) {
return 4;
}
}
@@ -189,36 +189,40 @@ struct SGLSLMeshToTangent {
#endif
}
uint GetLoop(const uint face_num, const uint vert_num, const MLoopTri *&lt)
uint GetLoop(const uint face_num, const uint vert_num, MLoopTri &lt, int &poly_index)
{
#ifdef USE_LOOPTRI_DETECT_QUADS
if (face_as_quad_map) {
lt = &looptri[face_as_quad_map[face_num]];
if (polys[lt->poly].size() == 4) {
return uint(polys[lt->poly][vert_num]);
lt = looptri[face_as_quad_map[face_num]];
poly_index = looptri_polys[face_as_quad_map[face_num]];
if (polys[poly_index].size() == 4) {
return uint(polys[poly_index][vert_num]);
}
/* fall through to regular triangle */
}
else {
lt = &looptri[face_num];
lt = looptri[face_num];
poly_index = looptri_polys[face_num];
}
#else
lt = &looptri[face_num];
#endif
return lt->tri[vert_num];
return lt.tri[vert_num];
}
mikk::float3 GetPosition(const uint face_num, const uint vert_num)
{
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
MLoopTri lt;
int poly_index;
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
return mikk::float3(positions[corner_verts[loop_index]]);
}
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
{
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
MLoopTri lt;
int poly_index;
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
if (mloopuv != nullptr) {
const float2 &uv = mloopuv[loop_index];
return mikk::float3(uv[0], uv[1], 1.0f);
@@ -231,17 +235,18 @@ struct SGLSLMeshToTangent {
mikk::float3 GetNormal(const uint face_num, const uint vert_num)
{
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
MLoopTri lt;
int poly_index;
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
if (precomputedLoopNormals) {
return mikk::float3(precomputedLoopNormals[loop_index]);
}
if (sharp_faces && sharp_faces[lt->poly]) { /* flat */
if (sharp_faces && sharp_faces[poly_index]) { /* flat */
if (precomputedFaceNormals) {
return mikk::float3(precomputedFaceNormals[lt->poly]);
return mikk::float3(precomputedFaceNormals[poly_index]);
}
#ifdef USE_LOOPTRI_DETECT_QUADS
const blender::IndexRange poly = polys[lt->poly];
const blender::IndexRange poly = polys[poly_index];
float normal[3];
if (poly.size() == 4) {
normal_quad_v3(normal,
@@ -254,9 +259,9 @@ struct SGLSLMeshToTangent {
#endif
{
normal_tri_v3(normal,
positions[corner_verts[lt->tri[0]]],
positions[corner_verts[lt->tri[1]]],
positions[corner_verts[lt->tri[2]]]);
positions[corner_verts[lt.tri[0]]],
positions[corner_verts[lt.tri[1]]],
positions[corner_verts[lt.tri[2]]]);
}
return mikk::float3(normal);
}
@@ -265,8 +270,9 @@ struct SGLSLMeshToTangent {
void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation)
{
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
MLoopTri lt;
int poly_index;
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
}
@@ -274,6 +280,7 @@ struct SGLSLMeshToTangent {
const float (*precomputedFaceNormals)[3];
const float (*precomputedLoopNormals)[3];
const MLoopTri *looptri;
const int *looptri_polys;
const float2 *mloopuv; /* texture coordinates */
blender::OffsetIndices<int> polys;
const int *corner_verts; /* indices */
@@ -390,6 +397,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
const blender::OffsetIndices<int> polys,
const int *corner_verts,
const MLoopTri *looptri,
const int *looptri_polys,
const uint looptri_len,
const bool *sharp_faces,
@@ -464,7 +472,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
for (k = 0, j = 0; j < int(looptri_len); k++, j++) {
face_as_quad_map[k] = j;
/* step over all quads */
if (polys[looptri[j].poly].size() == 4) {
if (polys[looptri_polys[j]].size() == 4) {
j++; /* skips the nest looptri */
}
}
@@ -497,6 +505,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
mesh2tangent->polys = polys;
mesh2tangent->corner_verts = corner_verts;
mesh2tangent->looptri = looptri;
mesh2tangent->looptri_polys = looptri_polys;
mesh2tangent->sharp_faces = sharp_faces;
/* NOTE: we assume we do have tessellated loop normals at this point
* (in case it is object-enabled), have to check this is valid. */
@@ -581,6 +590,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
me_eval->polys(),
me_eval->corner_verts().data(),
looptris.data(),
me_eval->looptri_polys().data(),
uint(looptris.size()),
static_cast<const bool *>(
CustomData_get_layer_named(&me_eval->pdata, CD_PROP_BOOL, "sharp_face")),

View File

@@ -15,6 +15,7 @@
#include "BLI_memarena.h"
#include "BLI_polyfill_2d.h"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BKE_mesh.hh"
@@ -50,7 +51,6 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<int> corner_vert
mlt->tri[0] = mp_loopstart + i1;
mlt->tri[1] = mp_loopstart + i2;
mlt->tri[2] = mp_loopstart + i3;
mlt->poly = poly_index;
};
switch (mp_totloop) {
@@ -298,6 +298,18 @@ void looptris_calc(const Span<float3> vert_positions,
looptris_calc_all(vert_positions, polys, corner_verts, {}, looptris);
}
void looptris_calc_poly_indices(const OffsetIndices<int> polys, MutableSpan<int> looptri_polys)
{
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int64_t i : range) {
const IndexRange poly = polys[i];
const int start = poly_to_tri_count(int(i), int(poly.start()));
const int num = ME_POLY_TRI_TOT(int(poly.size()));
looptri_polys.slice(start, num).fill(int(i));
}
});
}
void looptris_calc_with_normals(const Span<float3> vert_positions,
const OffsetIndices<int> polys,
const Span<int> corner_verts,

View File

@@ -1259,12 +1259,12 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p)
}
}
bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_poly)
bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, const int tri_index)
{
if (!hide_poly) {
return false;
}
return hide_poly[lt->poly];
return hide_poly[looptri_polys[tri_index]];
}
bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y)

View File

@@ -189,7 +189,7 @@ static int partition_indices_faces(int *prim_indices,
int axis,
float mid,
BBC *prim_bbc,
const MLoopTri *looptri)
const int *looptri_polys)
{
for (int i = lo; i < hi; i++) {
prim_scratch[i - lo] = prim_indices[i];
@@ -199,10 +199,10 @@ static int partition_indices_faces(int *prim_indices,
int i1 = lo, i2 = 0;
while (i1 < hi) {
int poly = looptri[prim_scratch[i2]].poly;
int poly = looptri_polys[prim_scratch[i2]];
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
while (i1 < hi && looptri[prim_scratch[i2]].poly == poly) {
while (i1 < hi && looptri_polys[prim_scratch[i2]] == poly) {
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
i1++;
i2++;
@@ -246,19 +246,20 @@ static int partition_indices_grids(int *prim_indices,
static int partition_indices_material(
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi)
{
const MLoopTri *looptri = pbvh->looptri;
const int *looptri_polys = pbvh->looptri_polys;
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
const int *indices = pbvh->prim_indices;
int i = lo, j = hi;
for (;;) {
if (pbvh->looptri) {
const int first = looptri[pbvh->prim_indices[lo]].poly;
for (; face_materials_match(material_indices, sharp_faces, first, looptri[indices[i]].poly);
if (pbvh->looptri_polys) {
const int first = looptri_polys[pbvh->prim_indices[lo]];
for (; face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[i]]);
i++) {
/* pass */
}
for (; !face_materials_match(material_indices, sharp_faces, first, looptri[indices[j]].poly);
for (;
!face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[j]]);
j--) {
/* pass */
}
@@ -345,7 +346,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
}
if (has_visible == false) {
if (!paint_is_face_hidden(lt, pbvh->hide_poly)) {
if (!paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, node->prim_indices[i])) {
has_visible = true;
}
}
@@ -471,11 +472,10 @@ static bool leaf_needs_material_split(
}
if (pbvh->looptri) {
const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
const int first = pbvh->looptri_polys[pbvh->prim_indices[offset]];
for (int i = offset + count - 1; i > offset; i--) {
int prim = pbvh->prim_indices[i];
if (!face_materials_match(
material_indices, sharp_faces, first->poly, pbvh->looptri[prim].poly)) {
if (!face_materials_match(material_indices, sharp_faces, first, pbvh->looptri_polys[prim])) {
return true;
}
}
@@ -513,7 +513,7 @@ static void test_face_boundaries(PBVH *pbvh)
switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES: {
for (int j = 0; j < node->totprim; j++) {
int poly = pbvh->looptri[node->prim_indices[j]].poly;
int poly = pbvh->looptri_polys[node->prim_indices[j]];
if (node_map[poly] >= 0 && node_map[poly] != i) {
int old_i = node_map[poly];
@@ -612,7 +612,7 @@ static void build_sub(PBVH *pbvh,
axis,
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
prim_bbc,
pbvh->looptri);
pbvh->looptri_polys);
}
else {
end = partition_indices_grids(pbvh->prim_indices,
@@ -792,7 +792,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
int poly;
if (pbvh->header.type == PBVH_FACES) {
poly = pbvh->looptri[node->prim_indices[j]].poly;
poly = pbvh->looptri_polys[node->prim_indices[j]];
}
else {
poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
@@ -819,7 +819,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
int poly;
if (pbvh->header.type == PBVH_FACES) {
poly = pbvh->looptri[node->prim_indices[j]].poly;
poly = pbvh->looptri_polys[node->prim_indices[j]];
}
else {
poly = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
@@ -845,6 +845,7 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
pbvh->polys = mesh->polys();
pbvh->corner_verts = mesh->corner_verts().data();
pbvh->looptri_polys = mesh->looptri_polys().data();
if (!pbvh->deformed) {
/* Deformed positions not matching the original mesh are owned directly by the PBVH, and are
* set separately by #BKE_pbvh_vert_coords_apply. */
@@ -888,7 +889,6 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
/* Those are not set in #BKE_pbvh_update_mesh_pointers because they are owned by the #PBVH. */
pbvh->looptri = looptri;
pbvh->vert_bitmap = static_cast<bool *>(
MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap"));
pbvh->totvert = totvert;
@@ -1412,6 +1412,8 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const int totface = node->totprim;
for (int i = 0; i < totface; i++) {
const int tri_index = faces[i];
const int poly_index = pbvh->looptri_polys[tri_index];
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int vtri[3] = {
pbvh->corner_verts[lt->tri[0]],
@@ -1421,12 +1423,12 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const int sides = 3;
/* Face normal and mask */
if (lt->poly != mpoly_prev) {
const blender::IndexRange poly = pbvh->polys[lt->poly];
if (poly_index != mpoly_prev) {
const blender::IndexRange poly = pbvh->polys[poly_index];
fn = blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const blender::float3 *>(pbvh->vert_positions), pbvh->totvert},
{&pbvh->corner_verts[poly.start()], poly.size()});
mpoly_prev = lt->poly;
mpoly_prev = poly_index;
}
for (int j = sides; j--;) {
@@ -2533,10 +2535,11 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
float nearest_vertex_co[3] = {0.0f};
for (int i = 0; i < totface; i++) {
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int tri_index = faces[i];
const MLoopTri *lt = &pbvh->looptri[tri_index];
const int *face_verts = node->face_vert_indices[i];
if (paint_is_face_hidden(lt, pbvh->hide_poly)) {
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) {
continue;
}
@@ -2572,7 +2575,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
r_active_vertex->i = corner_verts[lt->tri[j]];
*r_active_face_index = lt->poly;
*r_active_face_index = pbvh->looptri_polys[tri_index];
}
}
}
@@ -2842,10 +2845,11 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
bool hit = false;
for (i = 0; i < totface; i++) {
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int tri_index = faces[i];
const MLoopTri *lt = &pbvh->looptri[tri_index];
const int *face_verts = node->face_vert_indices[i];
if (paint_is_face_hidden(lt, pbvh->hide_poly)) {
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, tri_index)) {
continue;
}
@@ -3586,7 +3590,7 @@ BLI_INLINE int face_iter_prim_to_face(PBVHFaceIter *fd, int prim_index)
return BKE_subdiv_ccg_grid_to_face_index(fd->subdiv_ccg_, prim_index);
}
return fd->looptri_[prim_index].poly;
return fd->looptri_polys_[prim_index];
}
static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
@@ -3705,7 +3709,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd)
case PBVH_FACES:
fd->poly_offsets_ = pbvh->polys.data();
fd->corner_verts_ = pbvh->corner_verts;
fd->looptri_ = pbvh->looptri;
fd->looptri_polys_ = pbvh->looptri_polys;
fd->hide_poly_ = pbvh->hide_poly;
fd->face_sets_ = pbvh->face_sets;
fd->last_face_index_ = -1;

View File

@@ -163,6 +163,7 @@ struct PBVH {
const int *corner_verts;
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
const MLoopTri *looptri;
const int *looptri_polys;
CustomData *vdata;
CustomData *ldata;
CustomData *pdata;

View File

@@ -542,7 +542,6 @@ struct FanSegment {
void print_debug(const MeshData &mesh_data) const
{
std::stringstream ss;
ss << "# p:" << primitive->poly;
ss << " v1:" << mesh_data.corner_verts[primitive->tri[vert_order[0]]];
ss << " v2:" << mesh_data.corner_verts[primitive->tri[vert_order[1]]];
ss << " v3:" << mesh_data.corner_verts[primitive->tri[vert_order[2]]];

View File

@@ -1188,9 +1188,10 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
const BVHTreeFromMesh *treeData = &tree->treeData;
const MLoopTri *tri = &treeData->looptri[looptri_idx];
const float(*vert_normals)[3] = tree->vert_normals;
const int poly_i = tree->mesh->looptri_polys()[looptri_idx];
/* Interpolate smooth normals if enabled. */
if (!(tree->sharp_faces && tree->sharp_faces[tri->poly])) {
if (!(tree->sharp_faces && tree->sharp_faces[poly_i])) {
const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]],
treeData->corner_verts[tri->tri[1]],
treeData->corner_verts[tri->tri[2]]};
@@ -1234,7 +1235,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
}
/* Use the polygon normal if flat. */
else if (tree->poly_normals != nullptr) {
copy_v3_v3(r_no, tree->poly_normals[tri->poly]);
copy_v3_v3(r_no, tree->poly_normals[poly_i]);
}
/* Finally fallback to the looptri normal. */
else {

View File

@@ -63,6 +63,7 @@ struct PBVH_GPU_Args {
int node_verts_num;
const MLoopTri *mlooptri;
const int *looptri_polys;
PBVHNode *node;
/* BMesh. */

View File

@@ -310,6 +310,7 @@ void mesh_render_data_update_looptris(MeshRenderData *mr,
/* Mesh */
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
mr->looptris = mr->me->looptris();
mr->looptri_polys = mr->me->looptri_polys();
}
}
else {

View File

@@ -191,7 +191,7 @@ struct PBVHBatches {
switch (args->pbvh_type) {
case PBVH_FACES: {
for (int i = 0; i < args->totprim; i++) {
int face_index = args->mlooptri[args->prim_indices[i]].poly;
int face_index = args->looptri_polys[args->prim_indices[i]];
if (args->hide_poly && args->hide_poly[face_index]) {
continue;
@@ -337,14 +337,15 @@ struct PBVHBatches {
int last_poly = -1;
bool flat = false;
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const MLoopTri *tri) {
if (tri->poly != last_poly) {
last_poly = tri->poly;
flat = sharp_faces && sharp_faces[tri->poly];
foreach_faces([&](int /*buffer_i*/, int tri_i, int vertex_i, const MLoopTri * /*tri*/) {
const int poly_i = args->looptri_polys[tri_i];
if (args->looptri_polys[tri_i] != last_poly) {
last_poly = poly_i;
flat = sharp_faces && sharp_faces[poly_i];
if (flat) {
const float3 fno = blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const float3 *>(args->vert_positions), args->mesh_verts_num},
args->corner_verts.slice(args->polys[tri->poly]));
args->corner_verts.slice(args->polys[poly_i]));
normal_float_to_short_v3(no, fno);
}
}
@@ -549,7 +550,7 @@ struct PBVHBatches {
int buffer_i = 0;
for (int i : IndexRange(args->totprim)) {
int face_index = args->mlooptri[args->prim_indices[i]].poly;
int face_index = args->looptri_polys[args->prim_indices[i]];
if (args->hide_poly && args->hide_poly[face_index]) {
continue;
@@ -617,11 +618,12 @@ struct PBVHBatches {
uchar fset_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
foreach_faces(
[&](int /*buffer_i*/, int /*tri_i*/, int /*vertex_i*/, const MLoopTri *tri) {
if (last_poly != tri->poly) {
last_poly = tri->poly;
[&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const MLoopTri * /*tri*/) {
const int poly_i = args->looptri_polys[tri_i];
if (last_poly != poly_i) {
last_poly = poly_i;
const int fset = face_sets[tri->poly];
const int fset = face_sets[poly_i];
if (fset != args->face_sets_color_default) {
BKE_paint_face_set_overlay_color_get(
@@ -973,7 +975,7 @@ struct PBVHBatches {
CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
if (mat_index && args->totprim) {
int poly_index = args->mlooptri[args->prim_indices[0]].poly;
int poly_index = args->looptri_polys[args->prim_indices[0]];
material_index = mat_index[poly_index];
}
@@ -982,12 +984,13 @@ struct PBVHBatches {
/* Calculate number of edges. */
int edge_count = 0;
for (int i = 0; i < args->totprim; i++) {
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
if (args->hide_poly && args->hide_poly[lt->poly]) {
const int tri_i = args->prim_indices[i];
const int poly_i = args->looptri_polys[tri_i];
if (args->hide_poly && args->hide_poly[poly_i]) {
continue;
}
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
int r_edges[3];
BKE_mesh_looptri_get_real_edges(
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);
@@ -1008,12 +1011,13 @@ struct PBVHBatches {
int vertex_i = 0;
for (int i = 0; i < args->totprim; i++) {
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
if (args->hide_poly && args->hide_poly[lt->poly]) {
const int tri_i = args->prim_indices[i];
const int poly_i = args->looptri_polys[tri_i];
if (args->hide_poly && args->hide_poly[poly_i]) {
continue;
}
const MLoopTri *lt = args->mlooptri + args->prim_indices[i];
int r_edges[3];
BKE_mesh_looptri_get_real_edges(
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);

View File

@@ -86,6 +86,7 @@ struct MeshRenderData {
BMFace *efa_act_uv;
/* The triangulation of #Mesh polygons, owned by the mesh. */
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
const int *material_indices;
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> poly_normals;

View File

@@ -55,11 +55,12 @@ static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData * /*mr*/,
static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr,
const MLoopTri *mlt,
const int /*elt_index*/,
const int elt_index,
void *_data)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const BMFace *efa = bm_original_face_get(mr, mlt->poly);
const int poly_i = mr->looptri_polys[elt_index];
const BMFace *efa = bm_original_face_get(mr, poly_i);
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;

View File

@@ -115,11 +115,12 @@ static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData * /*mr*
static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr,
const MLoopTri *mlt,
const int /*elt_index*/,
const int elt_index,
void *_data)
{
MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(_data);
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly];
const int poly_i = mr->looptri_polys[elt_index];
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[poly_i];
if (hidden) {
return;
}

View File

@@ -190,7 +190,8 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr,
void *_data)
{
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[mlt->poly];
const int poly_i = mr->looptri_polys[mlt_index];
const bool hidden = mr->use_hide && mr->hide_poly && mr->hide_poly[poly_i];
if (hidden) {
GPU_indexbuf_set_tri_restart(elb, mlt_index);
}

View File

@@ -214,8 +214,9 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
const Span<MLoopTri> looptris = mr->looptris;
const Span<int> looptri_polys = mr->looptri_polys;
for (const int i : looptris.index_range()) {
const int index = looptris[i].poly;
const int index = looptri_polys[i];
const float *cos[3] = {mr->vert_positions[mr->corner_verts[looptris[i].tri[0]]],
mr->vert_positions[mr->corner_verts[looptris[i].tri[1]]],
mr->vert_positions[mr->corner_verts[looptris[i].tri[2]]]};
@@ -261,6 +262,7 @@ struct BVHTree_OverlapData {
Span<float3> positions;
Span<int> corner_verts;
Span<MLoopTri> looptris;
Span<int> looptri_polys;
float epsilon;
};
@@ -268,13 +270,13 @@ static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*threa
{
struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata);
const MLoopTri *tri_a = &data->looptris[index_a];
const MLoopTri *tri_b = &data->looptris[index_b];
if (UNLIKELY(tri_a->poly == tri_b->poly)) {
if (UNLIKELY(data->looptri_polys[index_a] == data->looptri_polys[index_b])) {
return false;
}
const MLoopTri *tri_a = &data->looptris[index_a];
const MLoopTri *tri_b = &data->looptris[index_b];
const float *tri_a_co[3] = {data->positions[data->corner_verts[tri_a->tri[0]]],
data->positions[data->corner_verts[tri_a->tri[1]]],
data->positions[data->corner_verts[tri_a->tri[2]]]};
@@ -344,14 +346,15 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
data.positions = mr->vert_positions;
data.corner_verts = mr->corner_verts;
data.looptris = mr->looptris;
data.looptri_polys = mr->looptri_polys;
data.epsilon = BLI_bvhtree_get_epsilon(tree);
BVHTreeOverlap *overlap = BLI_bvhtree_overlap_self(tree, &overlap_len, bvh_overlap_cb, &data);
if (overlap) {
for (int i = 0; i < overlap_len; i++) {
for (const IndexRange f_hit : {mr->polys[mr->looptris[overlap[i].indexA].poly],
mr->polys[mr->looptris[overlap[i].indexB].poly]})
for (const IndexRange f_hit : {mr->polys[mr->looptri_polys[overlap[i].indexA]],
mr->polys[mr->looptri_polys[overlap[i].indexB]]})
{
int l_index = f_hit.start();
for (int k = 0; k < f_hit.size(); k++, l_index++) {

View File

@@ -118,6 +118,7 @@ static void extract_tan_init_common(const MeshRenderData *mr,
mr->polys,
mr->corner_verts.data(),
mr->looptris.data(),
mr->looptri_polys.data(),
mr->tri_len,
mr->sharp_faces,
cd_ldata,

View File

@@ -921,6 +921,7 @@ typedef struct MeshDeformBind {
blender::OffsetIndices<int> polys;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
blender::Span<blender::float3> poly_normals;
} cagemesh_cache;
} MeshDeformBind;
@@ -951,6 +952,7 @@ static void harmonic_ray_callback(void *userdata,
MeshRayCallbackData *data = static_cast<MeshRayCallbackData *>(userdata);
MeshDeformBind *mdb = data->mdb;
const blender::Span<int> corner_verts = mdb->cagemesh_cache.corner_verts;
const blender::Span<int> looptri_polys = mdb->cagemesh_cache.looptri_polys;
const blender::Span<blender::float3> poly_normals = mdb->cagemesh_cache.poly_normals;
MeshDeformIsect *isec = data->isec;
float no[3], co[3], dist;
@@ -970,7 +972,7 @@ static void harmonic_ray_callback(void *userdata,
}
if (!poly_normals.is_empty()) {
copy_v3_v3(no, poly_normals[lt->poly]);
copy_v3_v3(no, poly_normals[looptri_polys[index]]);
}
else {
normal_tri_v3(no, UNPACK3(face));
@@ -1026,8 +1028,8 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
BVH_RAYCAST_WATERTIGHT) != -1)
{
const blender::Span<int> corner_verts = mdb->cagemesh_cache.corner_verts;
const MLoopTri *lt = &mdb->cagemesh_cache.looptris[hit.index];
const blender::IndexRange poly = mdb->cagemesh_cache.polys[lt->poly];
const int poly_i = mdb->cagemesh_cache.looptri_polys[hit.index];
const blender::IndexRange poly = mdb->cagemesh_cache.polys[poly_i];
const float(*cagecos)[3] = mdb->cagecos;
const float len = isect_mdef.lambda;
MDefBoundIsect *isect;
@@ -1043,7 +1045,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
isect->facing = isect_mdef.isect;
isect->poly_index = lt->poly;
isect->poly_index = poly_i;
isect->len = max_ff(len_v3v3(co1, isect->co), MESHDEFORM_LEN_THRESHOLD);
@@ -1626,6 +1628,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
mdb->cagemesh_cache.polys = me->polys();
mdb->cagemesh_cache.corner_verts = me->corner_verts();
mdb->cagemesh_cache.looptris = me->looptris();
mdb->cagemesh_cache.looptri_polys = me->looptri_polys();
mdb->cagemesh_cache.poly_normals = me->poly_normals();
}

View File

@@ -268,9 +268,9 @@ static void try_convert_single_object(Object &curves_ob,
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); });
const Span<float3> positions_cu = curves.positions();
const Span<MLoopTri> looptris = surface_me.looptris();
const Span<int> looptri_polys = surface_me.looptri_polys();
if (looptris.is_empty()) {
if (looptri_polys.is_empty()) {
*r_could_not_convert_some_curves = true;
}
@@ -338,8 +338,7 @@ static void try_convert_single_object(Object &curves_ob,
BLI_assert(nearest.index >= 0);
const int looptri_i = nearest.index;
const MLoopTri &looptri = looptris[looptri_i];
const int poly_i = looptri.poly;
const int poly_i = looptri_polys[looptri_i];
const int mface_i = find_mface_for_root_position(
positions, mfaces, poly_to_mface_map[poly_i], root_pos_su);

View File

@@ -1039,6 +1039,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets,
const blender::Span<int> corner_verts = me_eval->corner_verts();
blender::bke::mesh::looptris_calc(
me_eval->vert_positions(), me_eval->polys(), corner_verts, {looptri, tottri});
const blender::Span<int> looptri_polys = me_eval->looptri_polys();
/* For mapping back to original mesh in case there are modifiers. */
const int *vert_origindex = static_cast<const int *>(
@@ -1050,6 +1051,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets,
for (int i = 0; i < tottri; i++) {
const MLoopTri *lt = &looptri[i];
const int poly_i = looptri_polys[i];
for (int j = 0; j < 3; j++) {
uint l = lt->tri[j];
@@ -1058,7 +1060,7 @@ static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets,
/* Map back to original loop if there are modifiers. */
if (vert_origindex != nullptr && poly_origindex != nullptr) {
l = find_original_loop(
orig_polys, orig_corner_verts, vert_origindex, poly_origindex, lt->poly, v);
orig_polys, orig_corner_verts, vert_origindex, poly_origindex, poly_i, v);
if (l == ORIGINDEX_NONE || l >= me->totloop) {
continue;
}

View File

@@ -420,6 +420,7 @@ struct ProjPaintState {
const int *material_indices;
const bool *sharp_faces_eval;
blender::Span<MLoopTri> looptris_eval;
blender::Span<int> looptri_polys_eval;
const float (*mloopuv_stencil_eval)[2];
@@ -512,14 +513,14 @@ struct VertSeam {
ps->corner_verts_eval[lt->tri[0]], ps->corner_verts_eval[lt->tri[1]], \
ps->corner_verts_eval[lt->tri[2]],
#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
uvlayer[lt->poly][lt->tri[0]], uvlayer[lt->poly][lt->tri[1]], uvlayer[lt->poly][lt->tri[2]],
#define PS_LOOPTRI_AS_UV_3(uvlayer, poly_i, lt) \
uvlayer[poly_i][lt->tri[0]], uvlayer[poly_i][lt->tri[1]], uvlayer[poly_i][lt->tri[2]],
#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) \
#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, poly_i, lt) \
{ \
(uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]]; \
(uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]]; \
(uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]]; \
(uv_tri)[0] = uvlayer[poly_i][lt->tri[0]]; \
(uv_tri)[1] = uvlayer[poly_i][lt->tri[1]]; \
(uv_tri)[2] = uvlayer[poly_i][lt->tri[2]]; \
} \
((void)0)
@@ -551,7 +552,7 @@ static Material *tex_get_material(const ProjPaintState *ps, int poly_i)
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->looptris_eval[tri_index].poly;
const int poly_i = ps->looptri_polys_eval[tri_index];
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
}
@@ -562,7 +563,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
return ps->stencil_ima;
}
const int poly_i = ps->looptris_eval[tri_index].poly;
const int poly_i = ps->looptri_polys_eval[tri_index];
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
return slot ? slot->ima : ps->canvas_ima;
@@ -570,14 +571,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->looptris_eval[tri_index].poly;
const int poly_i = ps->looptri_polys_eval[tri_index];
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->looptris_eval[tri_index].poly;
const int poly_i = ps->looptri_polys_eval[tri_index];
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
return slot ? slot->ima : ps->clone_ima;
@@ -738,7 +739,7 @@ static bool project_paint_PickColor(
}
lt = &ps->looptris_eval[tri_index];
PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, ps->looptri_polys_eval[tri_index], lt);
interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
@@ -1122,7 +1123,8 @@ static void project_face_winding_init(const ProjPaintState *ps, const int tri_in
{
/* detect the winding of faces in uv space */
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int poly_i = ps->looptri_polys_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
if (winding > 0) {
@@ -1142,7 +1144,8 @@ static bool check_seam(const ProjPaintState *ps,
int *orig_fidx)
{
const MLoopTri *orig_lt = &ps->looptris_eval[orig_face];
const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)};
const int orig_poly_i = ps->looptri_polys_eval[orig_face];
const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_poly_i, orig_lt)};
/* vert indices from face vert order indices */
const uint i1 = ps->corner_verts_eval[orig_lt->tri[orig_i1_fidx]];
const uint i2 = ps->corner_verts_eval[orig_lt->tri[orig_i2_fidx]];
@@ -1155,6 +1158,7 @@ static bool check_seam(const ProjPaintState *ps,
if (tri_index != orig_face) {
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int poly_i = ps->looptri_polys_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
/* could check if the 2 faces images match here,
* but then there wouldn't be a way to return the opposite face's info */
@@ -1167,7 +1171,7 @@ static bool check_seam(const ProjPaintState *ps,
/* Only need to check if 'i2_fidx' is valid because
* we know i1_fidx is the same vert on both faces. */
if (i2_fidx != -1) {
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
Image *tpage = project_paint_face_paint_image(ps, tri_index);
Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
@@ -1389,7 +1393,8 @@ static void insert_seam_vert_array(const ProjPaintState *ps,
const int ibuf_y)
{
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int poly_i = ps->looptri_polys_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
float vec[2];
@@ -1724,10 +1729,11 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
/* calculate mask */
if (ps->do_mask_normal) {
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int poly_i = ps->looptri_polys_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
float no[3], angle_cos;
if (!(ps->sharp_faces_eval && ps->sharp_faces_eval[lt->poly])) {
if (!(ps->sharp_faces_eval && ps->sharp_faces_eval[poly_i])) {
const float *no1, *no2, *no3;
no1 = ps->vert_normals[lt_vtri[0]];
no2 = ps->vert_normals[lt_vtri[1]];
@@ -1963,8 +1969,9 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->looptris_eval[tri_index];
const int poly_other_i = ps->looptri_polys_eval[tri_index];
const float *lt_other_tri_uv[3] = {
PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, poly_other_i, lt_other)};
/* #BKE_image_acquire_ibuf - TODO: this may be slow. */
@@ -3007,8 +3014,9 @@ static void project_paint_face_init(const ProjPaintState *ps,
};
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int poly_i = ps->looptri_polys_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
/* UV/pixel seeking data */
/* Image X/Y-Pixel */
@@ -3544,7 +3552,8 @@ static void project_bucket_init(const ProjPaintState *ps,
tri_index = POINTER_AS_INT(node->link);
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int poly_i = ps->looptri_polys_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
/* Image context switching */
tpage = project_paint_face_paint_image(ps, tri_index);
@@ -4027,7 +4036,8 @@ static void project_paint_bleed_add_face_user(const ProjPaintState *ps,
/* add face user if we have bleed enabled, set the UV seam flags later */
/* annoying but we need to add all faces even ones we never use elsewhere */
if (ps->seam_bleed_px > 0.0f) {
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int poly_i = ps->looptri_polys_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, poly_i, lt)};
/* Check for degenerate triangles. Degenerate faces cause trouble with bleed computations.
* Ideally this would be checked later, not to add to the cost of computing non-degenerate
@@ -4112,6 +4122,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->totloop_eval = ps->me_eval->totloop;
ps->looptris_eval = ps->me_eval->looptris();
ps->looptri_polys_eval = ps->me_eval->looptri_polys();
ps->poly_to_loop_uv = static_cast<const float(**)[2]>(
MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces"));
@@ -4185,7 +4196,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps,
}
/* will set multiple times for 4+ sided poly */
ps->poly_to_loop_uv_clone[ps->looptris_eval[tri_index].poly] = lc->mloopuv_clone_base;
ps->poly_to_loop_uv_clone[ps->looptri_polys_eval[tri_index]] = lc->mloopuv_clone_base;
}
return false;
}
@@ -4213,27 +4224,27 @@ static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceL
/* Return true if face should be considered paintable, false otherwise */
static bool project_paint_check_face_paintable(const ProjPaintState *ps,
const ProjPaintFaceLookup *face_lookup,
const MLoopTri *lt)
const int tri_i)
{
if (ps->do_face_sel) {
int orig_index;
const int poly_i = ps->looptri_polys_eval[tri_i];
if ((face_lookup->index_mp_to_orig != nullptr) &&
((orig_index = (face_lookup->index_mp_to_orig[lt->poly])) != ORIGINDEX_NONE))
((orig_index = (face_lookup->index_mp_to_orig[poly_i])) != ORIGINDEX_NONE))
{
return face_lookup->select_poly_orig && face_lookup->select_poly_orig[orig_index];
}
return ps->select_poly_eval && ps->select_poly_eval[lt->poly];
return ps->select_poly_eval && ps->select_poly_eval[poly_i];
}
else {
int orig_index;
const int poly_i = ps->looptri_polys_eval[tri_i];
if ((face_lookup->index_mp_to_orig != nullptr) &&
((orig_index = (face_lookup->index_mp_to_orig[lt->poly])) != ORIGINDEX_NONE))
((orig_index = (face_lookup->index_mp_to_orig[poly_i])) != ORIGINDEX_NONE))
{
return !(face_lookup->hide_poly_orig && face_lookup->hide_poly_orig[orig_index]);
}
return !(ps->hide_poly_eval && ps->hide_poly_eval[lt->poly]);
return !(ps->hide_poly_eval && ps->hide_poly_eval[poly_i]);
}
}
@@ -4346,6 +4357,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
int image_index = -1, tri_index;
int prev_poly = -1;
const blender::Span<MLoopTri> looptris = ps->looptris_eval;
const blender::Span<int> looptri_polys = ps->looptri_polys_eval;
BLI_assert(ps->image_tot == 0);
@@ -4353,7 +4365,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
bool is_face_paintable;
bool skip_tri = false;
is_face_paintable = project_paint_check_face_paintable(ps, face_lookup, &looptris[tri_index]);
is_face_paintable = project_paint_check_face_paintable(ps, face_lookup, tri_index);
if (!ps->do_stencil_brush) {
slot = project_paint_face_paint_slot(ps, tri_index);
@@ -4393,7 +4405,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
tpage = ps->stencil_ima;
}
ps->poly_to_loop_uv[looptris[tri_index].poly] = mloopuv_base;
ps->poly_to_loop_uv[looptri_polys[tri_index]] = mloopuv_base;
tile = project_paint_face_paint_tile(tpage, mloopuv_base[looptris[tri_index].tri[0]]);
@@ -4426,10 +4438,10 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
/* Back-face culls individual triangles but mask normal will use polygon. */
if (ps->do_backfacecull) {
if (ps->do_mask_normal) {
if (prev_poly != looptris[tri_index].poly) {
if (prev_poly != looptri_polys[tri_index]) {
bool culled = true;
const blender::IndexRange poly = ps->polys_eval[looptris[tri_index].poly];
prev_poly = looptris[tri_index].poly;
const blender::IndexRange poly = ps->polys_eval[looptri_polys[tri_index]];
prev_poly = looptri_polys[tri_index];
for (const int corner : poly) {
if (!(ps->vertFlags[ps->corner_verts_eval[corner]] & PROJ_VERT_CULL)) {
culled = false;

View File

@@ -272,6 +272,7 @@ static void imapaint_pick_uv(
const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
const int tottri = BKE_mesh_runtime_looptri_len(me_eval);
const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(me_eval);
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
const int *corner_verts = BKE_mesh_corner_verts(me_eval);
@@ -294,7 +295,8 @@ static void imapaint_pick_uv(
/* test all faces in the derivedmesh with the original index of the picked face */
/* face means poly here, not triangle, indeed */
for (i = 0; i < tottri; i++, lt++) {
findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
const int poly_i = looptri_polys[i];
findex = index_mp_to_orig ? index_mp_to_orig[poly_i] : poly_i;
if (findex == faceindex) {
const float(*mloopuv)[2];
@@ -309,8 +311,8 @@ static void imapaint_pick_uv(
const Material *ma;
const TexPaintSlot *slot;
ma = BKE_object_material_get(
ob_eval, material_indices == NULL ? 1 : material_indices[lt->poly] + 1);
ma = BKE_object_material_get(ob_eval,
material_indices == NULL ? 1 : material_indices[poly_i] + 1);
slot = &ma->texpaintslot[ma->paint_active_slot];
if (!(slot && slot->uvname &&

View File

@@ -749,6 +749,8 @@ static bool raycastMesh(SnapObjectContext *sctx,
BVHTreeFromMesh treedata;
snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide, &treedata);
const blender::Span<int> looptri_polys = me_eval->looptri_polys();
if (treedata.tree == nullptr) {
return retval;
}
@@ -809,7 +811,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
retval = true;
if (r_index) {
*r_index = treedata.looptri[hit.index].poly;
*r_index = looptri_polys[hit.index];
}
}
}

View File

@@ -414,6 +414,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
int tottri = poly_to_tri_count(me->totpoly, me->totloop);
MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__);
blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, corner_verts, {mlooptri, tottri});
const blender::Span<int> looptri_polys = me->looptri_polys();
// Compute loop normals
BKE_mesh_calc_normals_split(me);
@@ -523,7 +524,8 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
// by the near and far view planes.
for (int a = 0; a < tottri; a++) {
const MLoopTri *lt = &mlooptri[a];
Material *mat = BKE_object_material_get(ob, material_indices[lt->poly] + 1);
const int poly_i = looptri_polys[a];
Material *mat = BKE_object_material_get(ob, material_indices[poly_i] + 1);
copy_v3_v3(v1, vert_positions[corner_verts[lt->tri[0]]]);
copy_v3_v3(v2, vert_positions[corner_verts[lt->tri[1]]]);
@@ -537,7 +539,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
v2[2] += _z_offset;
v3[2] += _z_offset;
if (_smooth && (!sharp_faces[lt->poly]) && lnors) {
if (_smooth && (!sharp_faces[poly_i]) && lnors) {
copy_v3_v3(n1, lnors[lt->tri[0]]);
copy_v3_v3(n2, lnors[lt->tri[1]]);
copy_v3_v3(n3, lnors[lt->tri[2]]);
@@ -563,7 +565,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
continue;
}
bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false;
bool fm = (ffa) ? (ffa[poly_i].flag & FREESTYLE_FACE_MARK) != 0 : false;
bool em1 = false, em2 = false, em3 = false;
if (fed) {

View File

@@ -1466,6 +1466,7 @@ struct EdgeFeatData {
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
LineartTriangle *tri_array;
blender::VArray<bool> sharp_edges;
blender::VArray<bool> sharp_faces;
@@ -1503,6 +1504,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
Object *ob_eval = e_feat_data->ob_eval;
LineartEdgeNeighbor *edge_nabr = e_feat_data->edge_nabr;
const blender::Span<MLoopTri> looptris = e_feat_data->looptris;
const blender::Span<int> looptri_polys = e_feat_data->looptri_polys;
uint16_t edge_flag_result = 0;
@@ -1520,10 +1522,10 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
FreestyleFace *ff1, *ff2;
int index = e_feat_data->freestyle_face_index;
if (index > -1) {
ff1 = &((FreestyleFace *)me->pdata.layers[index].data)[looptris[i / 3].poly];
ff1 = &((FreestyleFace *)me->pdata.layers[index].data)[looptri_polys[i / 3]];
}
if (edge_nabr[i].e > -1) {
ff2 = &((FreestyleFace *)me->pdata.layers[index].data)[looptris[edge_nabr[i].e / 3].poly];
ff2 = &((FreestyleFace *)me->pdata.layers[index].data)[looptri_polys[edge_nabr[i].e / 3]];
}
else {
/* Handle mesh boundary cases: We want mesh boundaries to respect
@@ -1637,8 +1639,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
if (ld->conf.use_crease) {
bool do_crease = true;
if (!ld->conf.force_crease && !e_feat_data->use_auto_smooth &&
(!e_feat_data->sharp_faces[looptris[f1].poly]) &&
(!e_feat_data->sharp_faces[looptris[f2].poly]))
(!e_feat_data->sharp_faces[looptri_polys[f1]]) &&
(!e_feat_data->sharp_faces[looptri_polys[f2]]))
{
do_crease = false;
}
@@ -1647,8 +1649,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
}
}
int mat1 = material_indices ? material_indices[looptris[f1].poly] : 0;
int mat2 = material_indices ? material_indices[looptris[f2].poly] : 0;
int mat1 = material_indices ? material_indices[looptri_polys[f1]] : 0;
int mat2 = material_indices ? material_indices[looptri_polys[f2]] : 0;
if (mat1 != mat2) {
Material *m1 = BKE_object_material_get_eval(ob_eval, mat1 + 1);
@@ -1785,6 +1787,7 @@ struct TriData {
blender::Span<blender::float3> positions;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
const int *material_indices;
LineartVert *vert_arr;
LineartTriangle *tri_arr;
@@ -1801,6 +1804,7 @@ static void lineart_load_tri_task(void *__restrict userdata,
const blender::Span<blender::float3> positions = tri_task_data->positions;
const blender::Span<int> corner_verts = tri_task_data->corner_verts;
const MLoopTri *looptri = &tri_task_data->looptris[i];
const int poly_i = tri_task_data->looptri_polys[i];
const int *material_indices = tri_task_data->material_indices;
LineartVert *vert_arr = tri_task_data->vert_arr;
LineartTriangle *tri = tri_task_data->tri_arr;
@@ -1816,8 +1820,8 @@ static void lineart_load_tri_task(void *__restrict userdata,
tri->v[2] = &vert_arr[v3];
/* Material mask bits and occlusion effectiveness assignment. */
Material *mat = BKE_object_material_get(
ob_info->original_ob_eval, material_indices ? material_indices[looptri->poly] + 1 : 1);
Material *mat = BKE_object_material_get(ob_info->original_ob_eval,
material_indices ? material_indices[poly_i] + 1 : 1);
tri->material_mask_bits |= ((mat && (mat->lineart.flags & LRT_MATERIAL_MASK_ENABLED)) ?
mat->lineart.material_mask_bits :
0);
@@ -1859,6 +1863,7 @@ struct EdgeNeighborData {
LineartAdjacentEdge *adj_e;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
};
static void lineart_edge_neighbor_init_task(void *__restrict userdata,
@@ -1921,6 +1926,7 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge
en_data.edge_nabr = edge_nabr;
en_data.corner_verts = me->corner_verts();
en_data.looptris = me->looptris();
en_data.looptri_polys = me->looptri_polys();
BLI_task_parallel_range(0, total_edges, &en_data, lineart_edge_neighbor_init_task, &en_settings);

View File

@@ -119,7 +119,9 @@ eAttrDomain BKE_id_attribute_domain(const struct ID * /*id*/,
/* -------------------------------------------------------------------- */
/** \name Stubs of BKE_paint.h
* \{ */
bool paint_is_face_hidden(const struct MLoopTri * /*lt*/, const bool * /*hide_poly*/)
bool paint_is_face_hidden(const int * /*looptri_polys*/,
const bool * /*hide_poly*/,
int /*tri_index*/)
{
BLI_assert_unreachable();
return false;

View File

@@ -292,10 +292,15 @@ typedef struct Mesh {
blender::MutableSpan<MDeformVert> deform_verts_for_write();
/**
* Cached triangulation of the mesh.
* Cached triangulation of mesh faces, depending on the face topology and the vertex positions.
*/
blender::Span<MLoopTri> looptris() const;
/**
* A map containing the face index that each cached triangle from #Mesh::looptris() came from.
*/
blender::Span<int> looptri_polys() const;
/** Set cached mesh bounds to a known-correct value to avoid their lazy calculation later on. */
void bounds_set_eager(const blender::Bounds<blender::float3> &bounds);

View File

@@ -69,9 +69,6 @@ enum {
*
* Usage examples:
* \code{.c}
* // access polygon attribute value.
* T value = polygon_attribute[lt->poly];
*
* // access vertex locations.
* float *vtri_co[3] = {
* positions[corner_verts[lt->tri[0]]],
@@ -137,7 +134,6 @@ enum {
*/
typedef struct MLoopTri {
unsigned int tri[3];
unsigned int poly;
} MLoopTri;
#
#

View File

@@ -413,6 +413,14 @@ static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr)
return index;
}
static int rna_MeshLoopTriangle_polygon_index_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const int index = rna_MeshLoopTriangle_index_get(ptr);
const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh);
return looptri_polys[index];
}
static void rna_Mesh_loop_triangles_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
@@ -440,6 +448,30 @@ int rna_Mesh_loop_triangles_lookup_int(PointerRNA *ptr, int index, PointerRNA *r
return true;
}
static void rna_Mesh_loop_triangle_faces_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
rna_iterator_array_begin(iter,
(void *)BKE_mesh_runtime_looptri_polys_ensure(mesh),
sizeof(int),
BKE_mesh_runtime_looptri_len(mesh),
false,
NULL);
}
int rna_Mesh_loop_triangle_faces_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
const Mesh *mesh = rna_mesh(ptr);
if (index < 0 || index >= BKE_mesh_runtime_looptri_len(mesh)) {
return false;
}
/* Casting away const is okay because this RNA type doesn't allow changing the value. */
r_ptr->owner_id = (ID *)&mesh->id;
r_ptr->type = &RNA_ReadOnlyInteger;
r_ptr->data = (void *)&BKE_mesh_runtime_looptri_polys_ensure(mesh)[index];
return true;
}
static void rna_MeshVertex_co_get(PointerRNA *ptr, float *value)
{
copy_v3_v3(value, (const float *)ptr->data);
@@ -1832,18 +1864,18 @@ static bool rna_MeshEdge_is_loose_get(PointerRNA *ptr)
static int rna_MeshLoopTriangle_material_index_get(PointerRNA *ptr)
{
const Mesh *me = rna_mesh(ptr);
const int poly_i = rna_MeshLoopTriangle_polygon_index_get(ptr);
const int *material_indices = BKE_mesh_material_indices(me);
const MLoopTri *ltri = (MLoopTri *)ptr->data;
return material_indices == NULL ? 0 : material_indices[ltri->poly];
return material_indices == NULL ? 0 : material_indices[poly_i];
}
static bool rna_MeshLoopTriangle_use_smooth_get(PointerRNA *ptr)
{
const Mesh *me = rna_mesh(ptr);
const MLoopTri *ltri = (MLoopTri *)ptr->data;
const int poly_i = rna_MeshLoopTriangle_polygon_index_get(ptr);
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&me->pdata, CD_PROP_BOOL, "sharp_face");
return !(sharp_faces && sharp_faces[ltri->poly]);
return !(sharp_faces && sharp_faces[poly_i]);
}
/* path construction */
@@ -2883,7 +2915,7 @@ static void rna_def_mlooptri(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "polygon_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "poly");
RNA_def_property_int_funcs(prop, "rna_MeshLoopTriangle_polygon_index_get", NULL, NULL);
RNA_def_property_ui_text(
prop, "Polygon", "Index of mesh polygon that the triangle is a part of");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -4190,6 +4222,18 @@ static void rna_def_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
}
static void rna_def_looptri_poly_value(BlenderRNA *brna)
{
StructRNA *srna = RNA_def_struct(brna, "ReadOnlyInteger", NULL);
RNA_def_struct_sdna(srna, "MIntProperty");
RNA_def_struct_ui_text(srna, "Read-only Integer", "");
PropertyRNA *prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Value", "");
RNA_def_property_int_sdna(prop, NULL, "i");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_mesh(BlenderRNA *brna)
{
StructRNA *srna;
@@ -4328,6 +4372,23 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles");
rna_def_mesh_looptris(brna, prop);
rna_def_looptri_poly_value(brna);
prop = RNA_def_property(srna, "loop_triangle_polygons", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop,
"rna_Mesh_loop_triangle_faces_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_Mesh_loop_triangles_length",
"rna_Mesh_loop_triangle_faces_lookup_int",
NULL,
NULL);
RNA_def_property_struct_type(prop, "ReadOnlyInteger");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Triangle Faces", "The polygon index for each loop triangle");
/* TODO: should this be allowed to be itself? */
prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");

View File

@@ -59,6 +59,7 @@ static const EnumPropertyItem space_items[] = {
# include "BKE_main.h"
# include "BKE_mball.h"
# include "BKE_mesh.h"
# include "BKE_mesh_runtime.h"
# include "BKE_modifier.h"
# include "BKE_object.h"
# include "BKE_report.h"
@@ -546,10 +547,12 @@ static void rna_Mesh_assign_verts_to_group(
# endif
/* don't call inside a loop */
static int mesh_looptri_to_poly_index(Mesh *me_eval, const MLoopTri *lt)
static int mesh_looptri_to_poly_index(Mesh *me_eval, const int tri_index)
{
const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(me_eval);
const int poly_i = looptri_polys[tri_index];
const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
return index_mp_to_orig ? index_mp_to_orig[poly_i] : poly_i;
}
/* TODO(sergey): Make the Python API more clear that evaluation might happen, or require
@@ -635,7 +638,7 @@ static void rna_Object_ray_cast(Object *ob,
copy_v3_v3(r_location, hit.co);
copy_v3_v3(r_normal, hit.no);
*r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[hit.index]);
*r_index = mesh_looptri_to_poly_index(mesh_eval, hit.index);
}
}
@@ -693,7 +696,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob,
copy_v3_v3(r_location, nearest.co);
copy_v3_v3(r_normal, nearest.no);
*r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[nearest.index]);
*r_index = mesh_looptri_to_poly_index(mesh_eval, nearest.index);
goto finally;
}

View File

@@ -73,6 +73,7 @@ struct SDefBindCalcData {
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
/** Coordinates to bind to, transformed into local space (compatible with `vertexCos`). */
float (*targetCos)[3];
@@ -390,7 +391,7 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3
BLI_bvhtree_find_nearest(
data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
const blender::IndexRange poly = data->polys[data->looptris[nearest.index].poly];
const blender::IndexRange poly = data->polys[data->looptri_polys[nearest.index]];
for (int i = 0; i < poly.size(); i++) {
const int edge_i = data->corner_edges[poly.start() + i];
@@ -1258,6 +1259,7 @@ static bool surfacedeformBind(Object *ob,
data.corner_verts = corner_verts;
data.corner_edges = corner_edges;
data.looptris = target->looptris();
data.looptri_polys = target->looptri_polys();
data.targetCos = static_cast<float(*)[3]>(
MEM_malloc_arrayN(target_verts_num, sizeof(float[3]), "SDefTargetBindVertArray"));
data.bind_verts = smd_orig->verts;

View File

@@ -274,7 +274,7 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
break;
}
case ATTR_DOMAIN_FACE: {
bke::mesh_surface_sample::sample_face_attribute(mesh.looptris(),
bke::mesh_surface_sample::sample_face_attribute(mesh.looptri_polys(),
looptri_indices,
source_data,
IndexMask(output_data.size()),

View File

@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "DNA_pointcloud_types.h"
#include "BKE_bvhutils.h"
@@ -147,11 +149,10 @@ static void get_closest_mesh_polys(const Mesh &mesh,
Array<int> looptri_indices(positions.size());
get_closest_mesh_looptris(mesh, positions, mask, looptri_indices, r_distances_sq, r_positions);
const Span<MLoopTri> looptris = mesh.looptris();
const Span<int> looptri_polys = mesh.looptri_polys();
for (const int i : mask) {
const MLoopTri &looptri = looptris[looptri_indices[i]];
r_poly_indices[i] = looptri.poly;
r_poly_indices[i] = looptri_polys[looptri_indices[i]];
}
}

View File

@@ -1142,6 +1142,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<MLoopTri> looptris = mesh->looptris();
const blender::Span<int> looptri_polys = mesh->looptri_polys();
/* Get data for tessellation */
@@ -1182,7 +1183,7 @@ static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObje
copy_v3_v3(co[2], coords[tris[i][2]]);
BLI_bvhtree_insert(tree, int(i), co[0], 3);
orig_index[i] = int(looptris[i].poly);
orig_index[i] = int(looptri_polys[i]);
}
BLI_bvhtree_balance(tree);

View File

@@ -501,8 +501,10 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
}
const blender::Span<blender::float3> vert_normals = me->vert_normals();
const blender::Span<int> looptri_polys = me->looptri_polys();
for (i = 0; i < tottri; i++) {
const MLoopTri *lt = &looptri[i];
const int poly_i = looptri_polys[i];
triangles[i].positions[0] = positions[corner_verts[lt->tri[0]]];
triangles[i].positions[1] = positions[corner_verts[lt->tri[1]]];
@@ -510,7 +512,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
triangles[i].vert_normals[0] = vert_normals[corner_verts[lt->tri[0]]];
triangles[i].vert_normals[1] = vert_normals[corner_verts[lt->tri[1]]];
triangles[i].vert_normals[2] = vert_normals[corner_verts[lt->tri[2]]];
triangles[i].is_smooth = !sharp_faces[lt->poly];
triangles[i].is_smooth = !sharp_faces[poly_i];
if (tangent) {
triangles[i].tspace[0] = &tspace[lt->tri[0]];
@@ -525,14 +527,14 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
}
if (calculate_normal) {
if (lt->poly != mpoly_prev) {
no = blender::bke::mesh::poly_normal_calc(positions, corner_verts.slice(polys[lt->poly]));
mpoly_prev = lt->poly;
if (poly_i != mpoly_prev) {
no = blender::bke::mesh::poly_normal_calc(positions, corner_verts.slice(polys[poly_i]));
mpoly_prev = poly_i;
}
copy_v3_v3(triangles[i].normal, no);
}
else {
copy_v3_v3(triangles[i].normal, precomputed_normals[lt->poly]);
copy_v3_v3(triangles[i].normal, precomputed_normals[poly_i]);
}
}
@@ -753,17 +755,20 @@ void RE_bake_pixels_populate(Mesh *me,
blender::bke::mesh::looptris_calc(
me->vert_positions(), me->polys(), me->corner_verts(), {looptri, tottri});
const blender::Span<int> looptri_polys = me->looptri_polys();
const int *material_indices = BKE_mesh_material_indices(me);
const int materials_num = targets->materials_num;
for (int i = 0; i < tottri; i++) {
const MLoopTri *lt = &looptri[i];
const int poly_i = looptri_polys[i];
bd.primitive_id = i;
/* Find images matching this material. */
const int material_index = (material_indices && materials_num) ?
clamp_i(material_indices[lt->poly], 0, materials_num - 1) :
clamp_i(material_indices[poly_i], 0, materials_num - 1) :
0;
Image *image = targets->material_to_image[material_index];
for (int image_id = 0; image_id < targets->images_num; image_id++) {

View File

@@ -45,6 +45,7 @@ using MPassKnownData = void (*)(blender::Span<blender::float3> vert_positions,
blender::OffsetIndices<int> polys,
blender::Span<int> corner_verts,
blender::Span<MLoopTri> looptris,
blender::Span<int> looptri_polys,
blender::Span<blender::float2> uv_map,
DerivedMesh *hires_dm,
void *thread_data,
@@ -70,6 +71,7 @@ struct MResolvePixelData {
blender::OffsetIndices<int> polys;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
blender::Span<int> looptri_polys;
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> poly_normals;
@@ -125,7 +127,7 @@ static void multiresbake_get_normal(const MResolvePixelData *data,
const int vert_index,
float r_normal[3])
{
const int poly_index = data->looptris[tri_num].poly;
const int poly_index = data->looptri_polys[tri_num];
const bool smoothnormal = !(data->sharp_faces && data->sharp_faces[poly_index]);
if (smoothnormal) {
@@ -209,6 +211,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
data->polys,
data->corner_verts,
data->looptris,
data->looptri_polys,
data->uv_map,
data->hires_dm,
data->thread_data,
@@ -395,7 +398,8 @@ static void *do_multires_bake_thread(void *data_v)
while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
const MLoopTri *lt = &data->looptris[tri_index];
const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[lt->poly];
const int poly_i = data->looptri_polys[tri_index];
const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[poly_i];
if (multiresbake_test_break(bkr)) {
break;
@@ -507,6 +511,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
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();
const blender::Span<int> looptri_polys = temp_mesh->looptri_polys();
if (require_tangent) {
if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
@@ -515,6 +520,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
polys,
dm->getCornerVertArray(dm),
looptris.data(),
looptri_polys.data(),
looptris.size(),
static_cast<const bool *>(
CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")),
@@ -565,6 +571,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
handle->data.polys = polys;
handle->data.corner_verts = corner_verts;
handle->data.looptris = looptris;
handle->data.looptri_polys = looptri_polys;
handle->data.vert_normals = vert_normals;
handle->data.poly_normals = poly_normals;
handle->data.material_indices = static_cast<const int *>(
@@ -658,7 +665,7 @@ static void get_ccgdm_data(const blender::OffsetIndices<int> lores_polys,
DerivedMesh *hidm,
const int *index_mp_to_orig,
const int lvl,
const MLoopTri *lt,
const int poly_index,
const float u,
const float v,
float co[3],
@@ -669,7 +676,6 @@ static void get_ccgdm_data(const blender::OffsetIndices<int> lores_polys,
float crn_x, crn_y;
int grid_size, S, face_side;
int *grid_offset, g_index;
int poly_index = lt->poly;
grid_size = hidm->getGridSize(hidm);
grid_data = hidm->getGridData(hidm);
@@ -840,6 +846,7 @@ static void apply_heights_callback(const blender::Span<blender::float3> vert_pos
const blender::OffsetIndices<int> polys,
const blender::Span<int> corner_verts,
const blender::Span<MLoopTri> looptris,
const blender::Span<int> looptri_polys,
const blender::Span<blender::float2> uv_map,
DerivedMesh *hires_dm,
void *thread_data_v,
@@ -853,7 +860,8 @@ static void apply_heights_callback(const blender::Span<blender::float3> vert_pos
const int y)
{
const MLoopTri *lt = &looptris[tri_index];
const blender::IndexRange poly = polys[lt->poly];
const int poly_i = looptri_polys[tri_index];
const blender::IndexRange poly = polys[poly_i];
MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v;
float uv[2];
@@ -880,11 +888,18 @@ static void apply_heights_callback(const blender::Span<blender::float3> vert_pos
clamp_v2(uv, 0.0f, 1.0f);
get_ccgdm_data(
polys, 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, poly_i, uv[0], uv[1], p1, nullptr);
if (height_data->ssdm) {
get_ccgdm_data(
polys, 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,
poly_i,
uv[0],
uv[1],
p0,
n);
}
else {
if (poly.size() == 4) {
@@ -954,6 +969,7 @@ static void apply_tangmat_callback(const blender::Span<blender::float3> /*vert_p
const blender::OffsetIndices<int> polys,
const blender::Span<int> /*corner_verts*/,
const blender::Span<MLoopTri> looptris,
const blender::Span<int> looptri_polys,
const blender::Span<blender::float2> uv_map,
DerivedMesh *hires_dm,
void * /*thread_data*/,
@@ -967,7 +983,8 @@ static void apply_tangmat_callback(const blender::Span<blender::float3> /*vert_p
const int y)
{
const MLoopTri *lt = &looptris[tri_index];
const blender::IndexRange poly = polys[lt->poly];
const int poly_i = looptri_polys[tri_index];
const blender::IndexRange poly = polys[poly_i];
MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
float uv[2];
const float *st0, *st1, *st2, *st3;
@@ -993,7 +1010,7 @@ static void apply_tangmat_callback(const blender::Span<blender::float3> /*vert_p
clamp_v2(uv, 0.0f, 1.0f);
get_ccgdm_data(
polys, 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, poly_i, uv[0], uv[1], nullptr, n);
mul_v3_m3v3(vec, tangmat, n);
normalize_v3_length(vec, 0.5);

View File

@@ -483,6 +483,9 @@ static void generate_margin(ImBuf *ibuf,
Array<MLoopTri> looptris(poly_to_tri_count(polys.size(), corner_edges.size()));
bke::mesh::looptris_calc(vert_positions, polys, corner_verts, looptris);
Array<int> looptri_polys(looptris.size());
bke::mesh::looptris_calc_poly_indices(polys, looptri_polys);
TextureMarginMap map(ibuf->x, ibuf->y, uv_offset, edges_num, polys, corner_edges, mloopuv);
bool draw_new_mask = false;
@@ -512,9 +515,9 @@ static void generate_margin(ImBuf *ibuf,
}
/* NOTE: we need the top bit for the dijkstra distance map. */
BLI_assert(lt->poly < 0x80000000);
BLI_assert(looptri_polys[i] < 0x80000000);
map.rasterize_tri(vec[0], vec[1], vec[2], lt->poly, draw_new_mask ? mask : nullptr);
map.rasterize_tri(vec[0], vec[1], vec[2], looptri_polys[i], draw_new_mask ? mask : nullptr);
}
char *tmpmask = (char *)MEM_dupallocN(mask);