Mesh: Replace MLoop struct with generic attributes

Implements #102359.

Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".

The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.

The commit also starts a renaming from "loop" to "corner" in mesh code.

Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.

Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.

For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):

**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
  for (const int64_t i : range) {
    dst[i] = src[loops[i].v];
  }
});
```

**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```

That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.

Pull Request: https://projects.blender.org/blender/blender/pulls/104424
This commit is contained in:
Hans Goudey
2023-03-20 15:55:13 +01:00
committed by Hans Goudey
parent a2600e0a76
commit 16fbadde36
224 changed files with 3934 additions and 3422 deletions
+22 -6
View File
@@ -818,6 +818,23 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
}
}
static std::optional<BL::IntAttribute> find_corner_vert_attribute(BL::Mesh b_mesh)
{
for (BL::Attribute &b_attribute : b_mesh.attributes) {
if (b_attribute.domain() != BL::Attribute::domain_CORNER) {
continue;
}
if (b_attribute.data_type() != BL::Attribute::data_type_INT) {
continue;
}
if (b_attribute.name() != ".corner_vert") {
continue;
}
return BL::IntAttribute{b_attribute};
}
return std::nullopt;
}
/* The Random Per Island attribute is a random float associated with each
* connected component (island) of the mesh. The attribute is computed by
* first classifying the vertices into different sets using a Disjoint Set
@@ -864,11 +881,11 @@ static void attr_create_random_per_island(Scene *scene,
else {
if (polys_num != 0) {
const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
const MLoop *loops = static_cast<const MLoop *>(b_mesh.loops[0].ptr.data);
BL::IntAttribute corner_verts = *find_corner_vert_attribute(b_mesh);
for (int i = 0; i < polys_num; i++) {
const MPoly &b_poly = polys[i];
const MLoop &b_loop = loops[b_poly.loopstart];
data[i] = hash_uint_to_float(vertices_sets.find(b_loop.v));
const int vert = corner_verts.data[b_poly.loopstart].value();
data[i] = hash_uint_to_float(vertices_sets.find(vert));
}
}
}
@@ -1036,7 +1053,7 @@ static void create_mesh(Scene *scene,
vector<int> vi;
const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
const MLoop *loops = static_cast<const MLoop *>(b_mesh.loops[0].ptr.data);
std::optional<BL::IntAttribute> corner_verts = find_corner_vert_attribute(b_mesh);
for (int i = 0; i < numfaces; i++) {
const MPoly &b_poly = polys[i];
@@ -1047,8 +1064,7 @@ static void create_mesh(Scene *scene,
vi.resize(n);
for (int i = 0; i < n; i++) {
/* NOTE: Autosmooth is already taken care about. */
vi[i] = loops[b_poly.loopstart + i].v;
vi[i] = corner_verts->data[b_poly.loopstart + i].value();
}
/* create subd faces */
+4 -2
View File
@@ -129,7 +129,8 @@ struct DerivedMesh {
*/
float *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
struct MLoop *(*getLoopArray)(DerivedMesh *dm);
int *(*getCornerVertArray)(DerivedMesh *dm);
int *(*getCornerEdgeArray)(DerivedMesh *dm);
struct MPoly *(*getPolyArray)(DerivedMesh *dm);
/** Copy all verts/edges/faces from the derived mesh into
@@ -137,7 +138,8 @@ struct DerivedMesh {
*/
void (*copyVertArray)(DerivedMesh *dm, float (*r_positions)[3]);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge);
void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop);
void (*copyCornerVertArray)(DerivedMesh *dm, int *r_corner_verts);
void (*copyCornerEdgeArray)(DerivedMesh *dm, int *r_corner_edges);
void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly);
/** Return a pointer to the entire array of vert/edge/face custom data
+2 -2
View File
@@ -61,7 +61,7 @@ typedef struct BVHTreeFromMesh {
const float (*vert_positions)[3];
const struct MEdge *edge;
const struct MFace *face;
const struct MLoop *loop;
const int *corner_verts;
const struct MLoopTri *looptri;
/* Private data */
@@ -181,7 +181,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
*/
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const struct MLoop *mloop,
const int *corner_verts,
const struct MLoopTri *looptri,
int looptri_num,
blender::BitSpan mask,
+2 -3
View File
@@ -18,7 +18,6 @@ struct ID;
struct ListBase;
struct MDeformVert;
struct MEdge;
struct MLoop;
struct MPoly;
struct Object;
struct bDeformGroup;
@@ -270,14 +269,14 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const struct MDeformVert *dvert,
void BKE_defvert_extract_vgroup_to_loopweights(const struct MDeformVert *dvert,
int defgroup,
int verts_num,
const struct MLoop *loops,
const int *corner_verts,
int loops_num,
bool invert_vgroup,
float *r_weights);
void BKE_defvert_extract_vgroup_to_polyweights(const struct MDeformVert *dvert,
int defgroup,
int verts_num,
const struct MLoop *loops,
const int *corner_verts,
int loops_num,
const struct MPoly *polys,
int polys_num,
+37 -22
View File
@@ -33,7 +33,6 @@ struct MDeformVert;
struct MDisps;
struct MEdge;
struct MFace;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct Main;
@@ -109,14 +108,14 @@ void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh);
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
*/
int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, int vert);
int poly_find_loop_from_vert(const struct MPoly *poly, const int *poly_verts, int vert);
/**
* Fill \a r_adj with the loop indices in \a poly adjacent to the
* vertex. Returns the index of the loop matching vertex, or -1 if the
* vertex is not in \a poly
*/
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
const int *corner_verts,
int vert,
int r_adj[2]);
@@ -129,8 +128,9 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
* Sets each output array element to the edge index if it is a real edge, or -1.
*/
void BKE_mesh_looptri_get_real_edges(const struct MEdge *edges,
const struct MLoop *loops,
const struct MLoopTri *looptri,
const int *corner_verts,
const int *corner_edges,
const struct MLoopTri *tri,
int r_edges[3]);
/**
@@ -312,7 +312,7 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]
/**
* Calculate tessellation into #MLoopTri which exist only for this purpose.
*/
void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
void BKE_mesh_recalc_looptri(const int *corner_verts,
const struct MPoly *polys,
const float (*vert_positions)[3],
int totvert,
@@ -384,7 +384,7 @@ bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
*/
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MLoop *poly_loops,
void BKE_mesh_calc_poly_normal(const int *poly_verts,
int poly_size,
const float (*vert_positions)[3],
int verts_num,
@@ -430,7 +430,7 @@ enum {
* Collection of #MLoopNorSpace basic storage & pre-allocation.
*/
typedef struct MLoopNorSpaceArray {
MLoopNorSpace **lspacearr; /* MLoop aligned array */
MLoopNorSpace **lspacearr; /* Face corner aligned array */
struct LinkNode
*loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
@@ -505,7 +505,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
* \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
*/
void BKE_mesh_normals_loop_to_vertex(int numVerts,
const struct MLoop *mloops,
const int *corner_verts,
int numLoops,
const float (*clnors)[3],
float (*r_vert_clnors)[3]);
@@ -546,12 +546,12 @@ void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_
/* *** mesh_evaluate.cc *** */
void BKE_mesh_calc_poly_center(const struct MLoop *poly_loops,
void BKE_mesh_calc_poly_center(const int *poly_verts,
int poly_size,
const float (*vert_positions)[3],
int verts_num,
float r_cent[3]);
float BKE_mesh_calc_poly_area(const struct MLoop *poly_loops,
float BKE_mesh_calc_poly_area(const int *poly_verts,
int poly_size,
const float (*vert_positions)[3],
int verts_num);
@@ -581,12 +581,12 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
int mverts_num,
const struct MLoopTri *mlooptri,
int looptri_num,
const struct MLoop *mloop,
const int *corner_verts,
float *r_volume,
float r_center[3]);
/**
* Flip a single MLoop's #MDisps structure,
* Flip a single corner's #MDisps structure,
* low level function to be called from face-flipping code which re-arranged the mdisps themselves.
*/
void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
@@ -600,13 +600,15 @@ void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
* \param ldata: the loops custom data.
*/
void BKE_mesh_polygon_flip_ex(const struct MPoly *poly,
struct MLoop *mloop,
int *corner_verts,
int *corner_edges,
struct CustomData *ldata,
float (*lnors)[3],
struct MDisps *mdisp,
bool use_loop_mdisp_flip);
void BKE_mesh_polygon_flip(const struct MPoly *poly,
struct MLoop *mloop,
int *corner_verts,
int *corner_edges,
struct CustomData *ldata,
int totloop);
/**
@@ -615,7 +617,8 @@ void BKE_mesh_polygon_flip(const struct MPoly *poly,
* \note Invalidates tessellation, caller must handle that.
*/
void BKE_mesh_polys_flip(const struct MPoly *polys,
struct MLoop *mloop,
int *corner_verts,
int *corner_edges,
struct CustomData *ldata,
int totpoly);
@@ -652,7 +655,7 @@ void BKE_mesh_flush_select_from_verts(struct Mesh *me);
*/
void BKE_mesh_calc_relative_deform(const struct MPoly *polys,
int totpoly,
const struct MLoop *mloop,
const int *corner_verts,
int totvert,
const float (*vert_cos_src)[3],
@@ -702,7 +705,8 @@ bool BKE_mesh_validate_arrays(struct Mesh *me,
unsigned int totedge,
struct MFace *mfaces,
unsigned int totface,
struct MLoop *mloops,
int *corner_verts,
int *corner_edges,
unsigned int totloop,
struct MPoly *polys,
unsigned int totpoly,
@@ -819,13 +823,24 @@ BLI_INLINE MPoly *BKE_mesh_polys_for_write(Mesh *mesh)
return (MPoly *)CustomData_get_layer_for_write(&mesh->pdata, CD_MPOLY, mesh->totpoly);
}
BLI_INLINE const MLoop *BKE_mesh_loops(const Mesh *mesh)
BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh)
{
return (const MLoop *)CustomData_get_layer(&mesh->ldata, CD_MLOOP);
return (const int *)CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert");
}
BLI_INLINE MLoop *BKE_mesh_loops_for_write(Mesh *mesh)
BLI_INLINE int *BKE_mesh_corner_verts_for_write(Mesh *mesh)
{
return (MLoop *)CustomData_get_layer_for_write(&mesh->ldata, CD_MLOOP, mesh->totloop);
return (int *)CustomData_get_layer_named_for_write(
&mesh->ldata, CD_PROP_INT32, ".corner_vert", mesh->totloop);
}
BLI_INLINE const int *BKE_mesh_corner_edges(const Mesh *mesh)
{
return (const int *)CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge");
}
BLI_INLINE int *BKE_mesh_corner_edges_for_write(Mesh *mesh)
{
return (int *)CustomData_get_layer_named_for_write(
&mesh->ldata, CD_PROP_INT32, ".corner_edge", mesh->totloop);
}
BLI_INLINE const MDeformVert *BKE_mesh_deform_verts(const Mesh *mesh)
+30 -17
View File
@@ -15,14 +15,14 @@ namespace blender::bke::mesh {
* \{ */
/** Calculate the up direction for the polygon, depending on its winding direction. */
float3 poly_normal_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
float3 poly_normal_calc(Span<float3> vert_positions, Span<int> poly_verts);
/**
* Calculate tessellation into #MLoopTri which exist only for this purpose.
*/
void looptris_calc(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
MutableSpan<MLoopTri> looptris);
/**
* A version of #looptris_calc which takes pre-calculated polygon normals
@@ -33,19 +33,19 @@ void looptris_calc(Span<float3> vert_positions,
*/
void looptris_calc_with_normals(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris);
/** Calculate the average position of the vertices in the polygon. */
float3 poly_center_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
float3 poly_center_calc(Span<float3> vert_positions, Span<int> poly_verts);
/** Calculate the surface area of the polygon described by the indexed vertices. */
float poly_area_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
float poly_area_calc(Span<float3> vert_positions, Span<int> poly_verts);
/** Calculate the angles at each of the polygons corners. */
void poly_angles_calc(Span<float3> vert_positions,
Span<MLoop> poly_loops,
Span<int> poly_verts,
MutableSpan<float> angles);
/** \} */
@@ -62,7 +62,7 @@ void poly_angles_calc(Span<float3> vert_positions,
*/
void normals_calc_polys(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
MutableSpan<float3> poly_normals);
/**
@@ -73,7 +73,7 @@ void normals_calc_polys(Span<float3> vert_positions,
*/
void normals_calc_poly_vert(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
MutableSpan<float3> poly_normals,
MutableSpan<float3> vert_normals);
@@ -82,14 +82,15 @@ void normals_calc_poly_vert(Span<float3> vert_positions,
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
* (splitting edges).
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
* \param loop_to_poly_map: Optional pre-created map from corners to their polygon.
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
* each side of the edge.
*/
void normals_calc_loop(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<int> corner_edges,
Span<int> loop_to_poly_map,
Span<float3> vert_normals,
Span<float3> poly_normals,
@@ -104,7 +105,8 @@ void normals_calc_loop(Span<float3> vert_positions,
void normals_loop_custom_set(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<int> corner_edges,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_faces,
@@ -115,7 +117,8 @@ void normals_loop_custom_set(Span<float3> vert_positions,
void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<int> corner_edges,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_faces,
@@ -132,7 +135,8 @@ void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
*/
void edges_sharp_from_angle_set(Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<int> corner_edges,
Span<float3> poly_normals,
const bool *sharp_faces,
const float split_angle,
@@ -174,13 +178,22 @@ inline blender::MutableSpan<MPoly> Mesh::polys_for_write()
return {BKE_mesh_polys_for_write(this), this->totpoly};
}
inline blender::Span<MLoop> Mesh::loops() const
inline blender::Span<int> Mesh::corner_verts() const
{
return {BKE_mesh_loops(this), this->totloop};
return {BKE_mesh_corner_verts(this), this->totloop};
}
inline blender::MutableSpan<MLoop> Mesh::loops_for_write()
inline blender::MutableSpan<int> Mesh::corner_verts_for_write()
{
return {BKE_mesh_loops_for_write(this), this->totloop};
return {BKE_mesh_corner_verts_for_write(this), this->totloop};
}
inline blender::Span<int> Mesh::corner_edges() const
{
return {BKE_mesh_corner_edges(this), this->totloop};
}
inline blender::MutableSpan<int> Mesh::corner_edges_for_write()
{
return {BKE_mesh_corner_edges_for_write(this), this->totloop};
}
inline blender::Span<MDeformVert> Mesh::deform_verts() const
@@ -112,8 +112,15 @@ struct MVert *BKE_mesh_legacy_convert_positions_to_verts(
void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh);
struct MLoop *BKE_mesh_legacy_convert_corners_to_loops(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,
blender::Vector<CustomDataLayer, 16> &loop_layers_to_write);
#endif
void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh);
/**
* Recreate #MFace Tessellation.
*
+22 -16
View File
@@ -15,7 +15,6 @@ extern "C" {
#endif
struct MEdge;
struct MLoop;
struct MLoopTri;
struct MPoly;
@@ -104,7 +103,7 @@ typedef struct MeshElemMap {
UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *polys,
const bool *hide_poly,
const bool *select_poly,
const struct MLoop *mloop,
const int *corner_verts,
const float (*mloopuv)[2],
unsigned int totpoly,
unsigned int totvert,
@@ -122,7 +121,7 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *polys,
const struct MLoop *mloop,
const int *corner_verts,
int totvert,
int totpoly,
int totloop);
@@ -134,7 +133,7 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MPoly *polys,
const struct MLoop *mloop,
const int *corner_verts,
int totvert,
int totpoly,
int totloop);
@@ -148,7 +147,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
int totvert,
const struct MLoopTri *mlooptri,
int totlooptri,
const struct MLoop *mloop,
const int *corner_verts,
int totloop);
/**
* Generates a map where the key is the vertex and the value
@@ -173,7 +172,7 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
int totedge,
const struct MPoly *polys,
int totpoly,
const struct MLoop *mloop,
const int *corner_edges,
int totloop);
/**
* Generates a map where the key is the edge and the value
@@ -185,7 +184,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
int totedge,
const struct MPoly *polys,
int totpoly,
const struct MLoop *mloop,
const int *corner_edges,
int totloop);
/**
* This function creates a map so the source-data (vert/edge/loop/poly)
@@ -263,7 +262,8 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3],
const bool *uv_seams,
const struct MPoly *polys,
int totpoly,
const struct MLoop *loops,
const int *corner_verts,
const int *corner_edges,
int totloop,
struct MeshIslandStore *r_island_store);
@@ -281,7 +281,8 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
const bool *uv_seams,
const struct MPoly *polys,
int totpoly,
const struct MLoop *loops,
const int *corner_verts,
const int *corner_edges,
int totloop,
MeshIslandStore *r_island_store);
@@ -305,7 +306,8 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
const bool *uv_seams,
struct MPoly *polys,
int totpoly,
struct MLoop *loops,
const int *corner_verts,
const int *corner_edges,
int totloop,
const float (*luvs)[2],
MeshIslandStore *r_island_store);
@@ -321,7 +323,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
int *BKE_mesh_calc_smoothgroups(int totedge,
const struct MPoly *polys,
int totpoly,
const struct MLoop *mloop,
const int *corner_edges,
int totloop,
const bool *sharp_edges,
const bool *sharp_faces,
@@ -351,11 +353,15 @@ namespace blender::bke::mesh_topology {
Array<int> build_loop_to_poly_map(Span<MPoly> polys, int loops_num);
Array<Vector<int>> build_vert_to_edge_map(Span<MEdge> edges, int verts_num);
Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_edge_to_loop_map(Span<MLoop> loops, int edges_num);
Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<MLoop> loops, int edges_num);
Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys,
Span<int> corner_verts,
int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<int> corner_verts, int verts_num);
Array<Vector<int>> build_edge_to_loop_map(Span<int> corner_edges, int edges_num);
Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys,
Span<int> corner_edges,
int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<int> corner_edges, int edges_num);
inline int poly_loop_prev(const MPoly &poly, int loop_i)
{
+3 -2
View File
@@ -202,7 +202,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
int numverts_dst,
const struct MEdge *edges_dst,
int numedges_dst,
const struct MLoop *loops_dst,
const int *corner_verts_dst,
const int *corner_edges_dst,
int numloops_dst,
const struct MPoly *polys_dst,
int numpolys_dst,
@@ -222,7 +223,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode,
const struct Mesh *mesh_dst,
const float (*vert_positions_dst)[3],
int numverts_dst,
const struct MLoop *loops_dst,
const int *corner_verts,
const struct MPoly *polys_dst,
int numpolys_dst,
struct Mesh *me_src,
+1 -2
View File
@@ -17,7 +17,6 @@ extern "C" {
struct CustomData_MeshMasks;
struct Depsgraph;
struct KeyBlock;
struct MLoop;
struct MLoopTri;
struct MVertTri;
struct Mesh;
@@ -63,7 +62,7 @@ void BKE_mesh_runtime_clear_cache(struct Mesh *mesh);
* Convert triangles encoded as face corner indices to triangles encoded as vertex indices.
*/
void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
const struct MLoop *mloop,
const int *corner_verts,
const struct MLoopTri *looptri,
int looptri_num);
+1 -1
View File
@@ -128,7 +128,7 @@ int sample_surface_points_projected(
Vector<float3> &r_positions);
float3 compute_bary_coord_in_triangle(Span<float3> vert_positions,
Span<MLoop> loops,
Span<int> corner_verts,
const MLoopTri &looptri,
const float3 &position);
+2 -2
View File
@@ -20,7 +20,7 @@ struct ReportList;
*/
void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
int numVerts,
const struct MLoop *mloops,
const int *corner_verts,
float (*r_looptangent)[4],
const float (*loop_normals)[3],
const float (*loopuv)[2],
@@ -45,7 +45,7 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh,
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
const struct MPoly *polys,
uint polys_len,
const struct MLoop *mloop,
const int *corner_verts,
const struct MLoopTri *looptri,
uint looptri_len,
const bool *sharp_faces,
+1 -1
View File
@@ -49,7 +49,7 @@ typedef enum eMeshBatchDirtyMode {
/** #MeshRuntime.wrapper_type */
typedef enum eMeshWrapperType {
/** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
/** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.corner_verts(), #Mesh.mpoly). */
ME_WRAPPER_TYPE_MDATA = 0,
/** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */
ME_WRAPPER_TYPE_BMESH = 1,
+1
View File
@@ -24,6 +24,7 @@ struct Object;
struct Scene;
struct SubdivCCG;
struct MLoopTri;
struct MPoly;
/**
+1 -2
View File
@@ -37,7 +37,6 @@ struct Image;
struct ImagePool;
struct ImageUser;
struct ListBase;
struct MLoop;
struct MLoopTri;
struct Main;
struct Mesh;
@@ -578,7 +577,7 @@ typedef struct SculptSession {
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
float (*vert_positions)[3];
const struct MPoly *polys;
const struct MLoop *mloop;
const int *corner_verts;
/* These contain the vertex and poly counts of the final mesh. */
int totvert, totpoly;
+4 -5
View File
@@ -29,7 +29,6 @@ struct CCGKey;
struct CustomData;
struct DMFlagMat;
struct IsectRayPrecalc;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct Mesh;
@@ -283,13 +282,13 @@ PBVH *BKE_pbvh_new(PBVHType type);
/**
* Do a full rebuild with on Mesh data structure.
*
* \note Unlike mpoly/mloop/verts, looptri is *totally owned* by PBVH
* \note Unlike mpoly/corner_verts/verts, looptri is *totally owned* by PBVH
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
*/
void BKE_pbvh_build_mesh(PBVH *pbvh,
struct Mesh *mesh,
const struct MPoly *polys,
const struct MLoop *mloop,
const int *corner_verts,
float (*vert_positions)[3],
int totvert,
struct CustomData *vdata,
@@ -510,7 +509,7 @@ const int *BKE_pbvh_node_get_vert_indices(PBVHNode *node);
void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
const struct MLoop **r_loops);
const int **r_corner_verts);
/* Get number of faces in the mesh; for PBVH_GRIDS the
* number of base mesh faces is returned.
@@ -737,7 +736,7 @@ typedef struct PBVHFaceIter {
int *face_sets_;
const struct MPoly *polys_;
const struct MLoopTri *looptri_;
const struct MLoop *mloop_;
const int *corner_verts_;
int prim_index_;
const struct SubdivCCG *subdiv_ccg_;
const struct BMesh *bm;
@@ -75,6 +75,7 @@ typedef struct ShrinkwrapTreeData {
const struct MPoly *polys;
const float (*vert_normals)[3];
const int *corner_edges;
const float (*poly_normals)[3];
const bool *sharp_faces;
const float (*clnors)[3];
+2 -3
View File
@@ -21,7 +21,6 @@ struct CCGKey;
struct DMFlagMat;
struct Mesh;
struct MPoly;
struct MLoop;
struct Subdiv;
/* --------------------------------------------------------------------
@@ -310,8 +309,8 @@ typedef enum SubdivCCGAdjacencyType {
* adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const struct MLoop *mloop,
const struct MPoly *polys,
const int *corner_verts,
const struct MPoly *mpoly,
int *r_v1,
int *r_v2);
@@ -64,7 +64,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
int loop_offset,
MutableSpan<float3> vert_positions,
MutableSpan<MPoly> polys,
MutableSpan<MLoop> loops);
MutableSpan<int> corner_verts);
#endif
+28 -15
View File
@@ -122,19 +122,32 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
return edge;
}
static MLoop *dm_getLoopArray(DerivedMesh *dm)
static int *dm_getCornerVertArray(DerivedMesh *dm)
{
MLoop *mloop = (MLoop *)CustomData_get_layer_for_write(
&dm->loopData, CD_MLOOP, dm->getNumLoops(dm));
int *corner_verts = (int *)CustomData_get_layer_named_for_write(
&dm->loopData, CD_PROP_INT32, ".corner_vert", dm->getNumLoops(dm));
if (!mloop) {
mloop = (MLoop *)CustomData_add_layer(
&dm->loopData, CD_MLOOP, CD_SET_DEFAULT, dm->getNumLoops(dm));
CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
dm->copyLoopArray(dm, mloop);
if (!corner_verts) {
corner_verts = (int *)CustomData_add_layer_named(
&dm->loopData, CD_PROP_INT32, CD_SET_DEFAULT, dm->getNumLoops(dm), ".corner_vert");
dm->copyCornerVertArray(dm, corner_verts);
}
return mloop;
return corner_verts;
}
static int *dm_getCornerEdgeArray(DerivedMesh *dm)
{
int *corner_edges = (int *)CustomData_get_layer_named(
&dm->loopData, CD_PROP_INT32, ".corner_edge");
if (!corner_edges) {
corner_edges = (int *)CustomData_add_layer_named(
&dm->loopData, CD_PROP_INT32, CD_SET_DEFAULT, dm->getNumLoops(dm), ".corner_edge");
dm->copyCornerEdgeArray(dm, corner_edges);
}
return corner_edges;
}
static MPoly *dm_getPolyArray(DerivedMesh *dm)
@@ -188,7 +201,8 @@ void DM_init_funcs(DerivedMesh *dm)
/* default function implementations */
dm->getVertArray = dm_getVertArray;
dm->getEdgeArray = dm_getEdgeArray;
dm->getLoopArray = dm_getLoopArray;
dm->getCornerVertArray = dm_getCornerVertArray;
dm->getCornerEdgeArray = dm_getCornerEdgeArray;
dm->getPolyArray = dm_getPolyArray;
dm->getLoopTriArray = dm_getLoopTriArray;
@@ -1891,7 +1905,7 @@ static void mesh_init_origspace(Mesh *mesh)
&mesh->ldata, CD_ORIGSPACE_MLOOP, mesh->totloop);
const Span<float3> positions = mesh->vert_positions();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
int j, k;
@@ -1907,7 +1921,6 @@ static void mesh_init_origspace(Mesh *mesh)
}
}
else {
const MLoop *l = &loops[poly.loopstart];
float co[3];
float mat[3][3];
@@ -1915,13 +1928,13 @@ static void mesh_init_origspace(Mesh *mesh)
float translate[2], scale[2];
const float3 p_nor = blender::bke::mesh::poly_normal_calc(
positions, loops.slice(poly.loopstart, poly.totloop));
positions, corner_verts.slice(poly.loopstart, poly.totloop));
axis_dominant_v3_to_m3(mat, p_nor);
vcos_2d.resize(poly.totloop);
for (j = 0; j < poly.totloop; j++, l++) {
mul_v3_m3v3(co, mat, positions[l->v]);
for (j = 0; j < poly.totloop; j++) {
mul_v3_m3v3(co, mat, positions[corner_verts[poly.loopstart + j]]);
copy_v2_v2(vcos_2d[j], co);
for (k = 0; k < 2; k++) {
+18 -18
View File
@@ -276,9 +276,9 @@ static void mesh_looptri_nearest_point(void *userdata,
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
positions[data->loop[lt->tri[0]].v],
positions[data->loop[lt->tri[1]].v],
positions[data->loop[lt->tri[2]].v],
positions[data->corner_verts[lt->tri[0]]],
positions[data->corner_verts[lt->tri[1]]],
positions[data->corner_verts[lt->tri[2]]],
};
float nearest_tmp[3], dist_sq;
@@ -376,9 +376,9 @@ static void mesh_looptri_spherecast(void *userdata,
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
positions[data->loop[lt->tri[0]].v],
positions[data->loop[lt->tri[1]].v],
positions[data->loop[lt->tri[2]].v],
positions[data->corner_verts[lt->tri[0]]],
positions[data->corner_verts[lt->tri[1]]],
positions[data->corner_verts[lt->tri[2]]],
};
float dist;
@@ -579,7 +579,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const float (*positions)[3],
const MEdge *edge,
const MFace *face,
const MLoop *loop,
const int *corner_verts,
const Span<MLoopTri> looptris,
BVHTreeFromMesh *r_data)
{
@@ -590,7 +590,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->vert_positions = positions;
r_data->edge = edge;
r_data->face = face;
r_data->loop = loop;
r_data->corner_verts = corner_verts;
r_data->looptri = looptris.data();
switch (bvh_cache_type) {
@@ -1036,7 +1036,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
int tree_type,
int axis,
const float (*positions)[3],
const MLoop *mloop,
const int *corner_verts,
const Span<MLoopTri> looptris,
const BitSpan looptri_mask,
int looptri_num_active)
@@ -1065,9 +1065,9 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
continue;
}
copy_v3_v3(co[0], positions[mloop[looptris[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptris[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptris[i].tri[2]].v]);
copy_v3_v3(co[0], positions[corner_verts[looptris[i].tri[0]]]);
copy_v3_v3(co[1], positions[corner_verts[looptris[i].tri[1]]]);
copy_v3_v3(co[2], positions[corner_verts[looptris[i].tri[2]]]);
BLI_bvhtree_insert(tree, i, co[0], 3);
}
@@ -1106,7 +1106,7 @@ BVHTree *bvhtree_from_editmesh_looptri(
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const float (*vert_positions)[3],
const struct MLoop *mloop,
const int *corner_verts,
const struct MLoopTri *looptri,
const int looptri_num,
const BitSpan looptri_mask,
@@ -1119,7 +1119,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
tree_type,
axis,
vert_positions,
mloop,
corner_verts,
{looptri, looptri_num},
looptri_mask,
looptri_num_active);
@@ -1133,7 +1133,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
vert_positions,
nullptr,
nullptr,
mloop,
corner_verts,
{looptri, looptri_num},
data);
}
@@ -1218,7 +1218,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
}
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
const Span<MEdge> edges = mesh->edges();
const Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(nullptr,
@@ -1226,7 +1226,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
positions,
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
corner_verts.data(),
looptris,
data);
@@ -1286,7 +1286,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
}
case BVHTREE_FROM_LOOPTRI:
data->tree = bvhtree_from_mesh_looptri_create_tree(
0.0f, tree_type, 6, positions, loops.data(), looptris, mask, mask_bits_act_len);
0.0f, tree_type, 6, positions, corner_verts.data(), looptris, mask, mask_bits_act_len);
break;
case BVHTREE_FROM_EM_VERTS:
case BVHTREE_FROM_EM_EDGES:
@@ -42,7 +42,8 @@ struct CDDerivedMesh {
const blender::float3 *vert_normals;
MEdge *medge;
MFace *mface;
MLoop *mloop;
int *corner_verts;
int *corner_edges;
MPoly *mpoly;
/* Cached */
@@ -87,10 +88,16 @@ static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData);
}
static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
static void cdDM_copyCornerVertArray(DerivedMesh *dm, int *r_corner_verts)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
memcpy(r_loop, cddm->mloop, sizeof(*r_loop) * dm->numLoopData);
memcpy(r_corner_verts, cddm->corner_verts, sizeof(*r_corner_verts) * dm->numLoopData);
}
static void cdDM_copyCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
memcpy(r_corner_edges, cddm->corner_edges, sizeof(*r_corner_edges) * dm->numLoopData);
}
static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
@@ -124,7 +131,7 @@ static void cdDM_recalc_looptri(DerivedMesh *dm)
blender::bke::mesh::looptris_calc(
{reinterpret_cast<const blender::float3 *>(cddm->vert_positions), dm->numVertData},
{cddm->mpoly, totpoly},
{cddm->mloop, totloop},
{cddm->corner_verts, totloop},
{dm->looptris.array_wip, dm->looptris.num});
BLI_assert(cddm->dm.looptris.array == NULL);
@@ -166,7 +173,8 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->copyVertArray = cdDM_copyVertArray;
dm->copyEdgeArray = cdDM_copyEdgeArray;
dm->copyLoopArray = cdDM_copyLoopArray;
dm->copyCornerVertArray = cdDM_copyCornerVertArray;
dm->copyCornerEdgeArray = cdDM_copyCornerEdgeArray;
dm->copyPolyArray = cdDM_copyPolyArray;
dm->getVertDataArray = DM_get_vert_data_layer;
@@ -224,8 +232,10 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
cddm->vert_normals = mesh->vert_normals().data();
cddm->medge = static_cast<MEdge *>(
CustomData_get_layer_for_write(&dm->edgeData, CD_MEDGE, mesh->totedge));
cddm->mloop = static_cast<MLoop *>(
CustomData_get_layer_for_write(&dm->loopData, CD_MLOOP, mesh->totloop));
cddm->corner_verts = static_cast<int *>(CustomData_get_layer_named_for_write(
&dm->loopData, CD_PROP_INT32, ".corner_vert", mesh->totloop));
cddm->corner_edges = static_cast<int *>(CustomData_get_layer_named_for_write(
&dm->loopData, CD_PROP_INT32, ".corner_edge", mesh->totloop));
cddm->mpoly = static_cast<MPoly *>(
CustomData_get_layer_for_write(&dm->polyData, CD_MPOLY, mesh->totpoly));
#if 0
+29 -26
View File
@@ -835,7 +835,7 @@ static bool cloth_from_object(
static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh)
{
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<MLoopTri> looptris = mesh->looptris();
const uint mvert_num = mesh->totvert;
@@ -868,7 +868,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
return;
}
BKE_mesh_runtime_verttri_from_looptri(
clmd->clothObject->tri, loops.data(), looptris.data(), looptris.size());
clmd->clothObject->tri, corner_verts.data(), looptris.data(), looptris.size());
clmd->clothObject->edges = mesh->edges().data();
@@ -1288,7 +1288,7 @@ void cloth_parallel_transport_hair_frame(float mat[3][3],
/* Add a shear and a bend spring between two verts within a poly. */
static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
LinkNodePair *edgelist,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_verts,
const blender::Span<MPoly> polys,
int i,
int j,
@@ -1296,7 +1296,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
{
Cloth *cloth = clmd->clothObject;
ClothSpring *spring;
const MLoop *tmp_loop;
const int *tmp_corner;
float shrink_factor;
int x, y;
@@ -1308,7 +1308,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
}
spring_verts_ordered_set(
spring, loops[polys[i].loopstart + j].v, loops[polys[i].loopstart + k].v);
spring, corner_verts[polys[i].loopstart + j], corner_verts[polys[i].loopstart + k]);
shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) *
@@ -1340,18 +1340,18 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
return false;
}
tmp_loop = &loops[polys[i].loopstart];
tmp_corner = &corner_verts[polys[i].loopstart];
for (x = 0; x < spring->la; x++) {
spring->pa[x] = tmp_loop[j + x].v;
spring->pa[x] = tmp_corner[j + x];
}
for (x = 0; x <= j; x++) {
spring->pb[x] = tmp_loop[x].v;
spring->pb[x] = tmp_corner[x];
}
for (y = k; y < polys[i].totloop; x++, y++) {
spring->pb[x] = tmp_loop[y].v;
spring->pb[x] = tmp_corner[y];
}
spring->mn = -1;
@@ -1369,7 +1369,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
return true;
}
BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop *mloop)
BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const int *corner_verts)
{
int *p = static_cast<int *>(MEM_mallocN(sizeof(int) * len, "spring poly"));
@@ -1377,8 +1377,8 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop
return false;
}
for (int i = 0; i < len; i++, mloop++) {
p[i] = mloop->v;
for (int i = 0; i < len; i++) {
p[i] = corner_verts[i];
}
*poly = p;
@@ -1431,7 +1431,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
uint vert_idx = -1;
const MLoop *mloop = treedata->loop;
const int *corner_verts = treedata->corner_verts;
const MLoopTri *lt = nullptr;
if (rayhit.index != -1 && rayhit.dist <= max_length) {
@@ -1444,7 +1444,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
lt = &treedata->looptri[rayhit.index];
for (int i = 0; i < 3; i++) {
uint tmp_vert_idx = mloop[lt->tri[i]].v;
uint tmp_vert_idx = corner_verts[lt->tri[i]];
if (tmp_vert_idx == v_idx) {
/* We managed to hit ourselves. */
return false;
@@ -1466,6 +1466,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
Cloth *cloth = clmd->clothObject;
ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr;
@@ -1476,7 +1477,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
float shrink_factor;
const blender::Span<MEdge> edges = mesh->edges();
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
const Span<int> corner_edges = mesh->corner_edges();
int index2 = 0; /* our second vertex index */
LinkNodePair *edgelist = nullptr;
EdgeSet *edgeset = nullptr;
@@ -1672,7 +1674,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
if (polys[i].totloop > 3) {
for (int j = 1; j < polys[i].totloop - 1; j++) {
if (j > 1) {
if (cloth_add_shear_bend_spring(clmd, edgelist, loops, polys, i, 0, j)) {
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, 0, j)) {
shear_springs++;
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
@@ -1686,7 +1688,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
}
for (int k = j + 2; k < polys[i].totloop; k++) {
if (cloth_add_shear_bend_spring(clmd, edgelist, loops, polys, i, j, k)) {
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, j, k)) {
shear_springs++;
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
@@ -1703,10 +1705,9 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
/* Angular bending springs along struct springs. */
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
const MLoop *ml = &loops[polys[i].loopstart];
for (int j = 0; j < polys[i].totloop; j++, ml++) {
BendSpringRef *curr_ref = &spring_ref[ml->e];
for (int j = 0; j < polys[i].totloop; j++) {
const int edge_i = corner_edges[polys[i].loopstart + j];
BendSpringRef *curr_ref = &spring_ref[edge_i];
curr_ref->polys++;
/* First poly found for this edge, store poly index. */
@@ -1723,14 +1724,14 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
spring->lb = polys[i].totloop;
if (!cloth_bend_set_poly_vert_array(
&spring->pa, spring->la, &loops[polys[curr_ref->index].loopstart]) ||
&spring->pa, spring->la, &corner_verts[polys[curr_ref->index].loopstart]) ||
!cloth_bend_set_poly_vert_array(
&spring->pb, spring->lb, &loops[polys[i].loopstart])) {
&spring->pb, spring->lb, &corner_verts[polys[i].loopstart])) {
cloth_free_errorsprings(cloth, edgelist, spring_ref);
return false;
}
spring->mn = ml->e;
spring->mn = edge_i;
spring->restang = cloth_spring_angle(cloth->verts,
spring->ij,
@@ -1897,8 +1898,10 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
for (int i = 0; i < numpolys; i++) { /* edge springs */
if (polys[i].totloop == 4) {
BLI_edgeset_add(edgeset, loops[polys[i].loopstart + 0].v, loops[polys[i].loopstart + 2].v);
BLI_edgeset_add(edgeset, loops[polys[i].loopstart + 1].v, loops[polys[i].loopstart + 3].v);
BLI_edgeset_add(
edgeset, corner_verts[polys[i].loopstart + 0], corner_verts[polys[i].loopstart + 2]);
BLI_edgeset_add(
edgeset, corner_verts[polys[i].loopstart + 1], corner_verts[polys[i].loopstart + 3]);
}
}
+19 -19
View File
@@ -190,44 +190,44 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
const Span<float3> positions = me->vert_positions();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
for (int i = 0; i < me->totpoly; i++) {
const MPoly &poly = polys[i];
const MLoop *ml_next = &loops[poly.loopstart];
const MLoop *ml_curr = &ml_next[poly.totloop - 1];
const MLoop *ml_prev = &ml_next[poly.totloop - 2];
const int *corner_vert_next = &corner_verts[poly.loopstart];
const int *corner_vert_curr = &corner_vert_next[poly.totloop - 1];
const int *corner_vert_prev = &corner_vert_next[poly.totloop - 2];
for (int j = 0; j < poly.totloop; j++) {
if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) {
if (!BLI_BITMAP_TEST(vert_tag, *corner_vert_curr)) {
const float *co_prev, *co_curr, *co_next; /* orig */
const float *vd_prev, *vd_curr, *vd_next; /* deform */
/* retrieve mapped coordinates */
vd_prev = mappedcos[ml_prev->v];
vd_curr = mappedcos[ml_curr->v];
vd_next = mappedcos[ml_next->v];
vd_prev = mappedcos[*corner_vert_prev];
vd_curr = mappedcos[*corner_vert_curr];
vd_next = mappedcos[*corner_vert_next];
if (origcos) {
co_prev = origcos[ml_prev->v];
co_curr = origcos[ml_curr->v];
co_next = origcos[ml_next->v];
co_prev = origcos[*corner_vert_prev];
co_curr = origcos[*corner_vert_curr];
co_next = origcos[*corner_vert_next];
}
else {
co_prev = positions[ml_prev->v];
co_curr = positions[ml_curr->v];
co_next = positions[ml_next->v];
co_prev = positions[*corner_vert_prev];
co_curr = positions[*corner_vert_curr];
co_next = positions[*corner_vert_next];
}
set_crazy_vertex_quat(
quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev);
quats[*corner_vert_curr], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev);
BLI_BITMAP_ENABLE(vert_tag, ml_curr->v);
BLI_BITMAP_ENABLE(vert_tag, *corner_vert_curr);
}
ml_prev = ml_curr;
ml_curr = ml_next;
ml_next++;
corner_vert_prev = corner_vert_curr;
corner_vert_curr = corner_vert_next;
corner_vert_next++;
}
}
@@ -28,7 +28,8 @@ static void fill_mesh_topology(const int vert_offset,
const bool profile_cyclic,
const bool fill_caps,
MutableSpan<MEdge> edges,
MutableSpan<MLoop> loops,
MutableSpan<int> corner_verts,
MutableSpan<int> corner_edges,
MutableSpan<MPoly> polys)
{
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
@@ -104,18 +105,17 @@ static void fill_mesh_topology(const int vert_offset,
poly.loopstart = ring_segment_loop_offset;
poly.totloop = 4;
MLoop &loop_a = loops[ring_segment_loop_offset];
loop_a.v = ring_vert_offset + i_profile;
loop_a.e = ring_edge_start + i_profile;
MLoop &loop_b = loops[ring_segment_loop_offset + 1];
loop_b.v = ring_vert_offset + i_next_profile;
loop_b.e = next_main_edge_start + i_ring;
MLoop &loop_c = loops[ring_segment_loop_offset + 2];
loop_c.v = next_ring_vert_offset + i_next_profile;
loop_c.e = next_ring_edge_offset + i_profile;
MLoop &loop_d = loops[ring_segment_loop_offset + 3];
loop_d.v = next_ring_vert_offset + i_profile;
loop_d.e = main_edge_start + i_ring;
corner_verts[ring_segment_loop_offset] = ring_vert_offset + i_profile;
corner_edges[ring_segment_loop_offset] = ring_edge_start + i_profile;
corner_verts[ring_segment_loop_offset + 1] = ring_vert_offset + i_next_profile;
corner_edges[ring_segment_loop_offset + 1] = next_main_edge_start + i_ring;
corner_verts[ring_segment_loop_offset + 2] = next_ring_vert_offset + i_next_profile;
corner_edges[ring_segment_loop_offset + 2] = next_ring_edge_offset + i_profile;
corner_verts[ring_segment_loop_offset + 3] = next_ring_vert_offset + i_profile;
corner_edges[ring_segment_loop_offset + 3] = main_edge_start + i_ring;
}
}
@@ -138,13 +138,12 @@ static void fill_mesh_topology(const int vert_offset,
for (const int i : IndexRange(profile_segment_num)) {
const int i_inv = profile_segment_num - i - 1;
MLoop &loop_start = loops[cap_loop_offset + i];
loop_start.v = vert_offset + i_inv;
loop_start.e = profile_edges_start +
((i == (profile_segment_num - 1)) ? (profile_segment_num - 1) : (i_inv - 1));
MLoop &loop_end = loops[cap_loop_offset + profile_segment_num + i];
loop_end.v = last_ring_vert_offset + i;
loop_end.e = last_ring_edge_offset + i;
corner_verts[cap_loop_offset + i] = vert_offset + i_inv;
corner_edges[cap_loop_offset + i] = profile_edges_start + ((i == (profile_segment_num - 1)) ?
(profile_segment_num - 1) :
(i_inv - 1));
corner_verts[cap_loop_offset + profile_segment_num + i] = last_ring_vert_offset + i;
corner_edges[cap_loop_offset + profile_segment_num + i] = last_ring_edge_offset + i;
}
}
}
@@ -672,7 +671,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
MutableSpan<float3> positions = mesh->vert_positions_for_write();
MutableSpan<MEdge> edges = mesh->edges_for_write();
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
MutableSpan<int> corner_edges = mesh->corner_edges_for_write();
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
@@ -686,7 +686,8 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
info.profile_cyclic,
fill_caps,
edges,
loops,
corner_verts,
corner_edges,
polys);
});
@@ -1770,7 +1770,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr},
/* 25: CD_MPOLY */
{sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 26: CD_MLOOP */
/* 26: CD_MLOOP */ /* DEPRECATED*/
{sizeof(MLoop),
"MLoop",
1,
@@ -2030,14 +2030,14 @@ const CustomData_MeshMasks CD_MASK_BAREMESH = {
/*emask*/ CD_MASK_MEDGE,
/*fmask*/ 0,
/*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP,
/*lmask*/ CD_MASK_MLOOP,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
/*vmask*/ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
/*emask*/ CD_MASK_MEDGE | CD_MASK_ORIGINDEX,
/*fmask*/ 0,
/*pmask*/ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
/*lmask*/ CD_MASK_MLOOP,
/*lmask*/ CD_MASK_PROP_INT32,
};
const CustomData_MeshMasks CD_MASK_MESH = {
/*vmask*/ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN |
@@ -2048,8 +2048,7 @@ const CustomData_MeshMasks CD_MASK_MESH = {
/*pmask*/
(CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK |
CD_MASK_PROP_ALL),
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/*vmask*/ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
@@ -2090,9 +2089,9 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP |
CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/*lmask*/
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
static const LayerTypeInfo *layerType_getInfo(int type)
@@ -380,7 +380,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
blender::bke::mesh::normals_calc_loop(me_dst->vert_positions(),
me_dst->edges(),
me_dst->polys(),
me_dst->loops(),
me_dst->corner_verts(),
me_dst->corner_edges(),
{},
me_dst->vert_normals(),
me_dst->poly_normals(),
@@ -429,7 +430,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(),
me_dst->edges(),
me_dst->polys(),
me_dst->loops(),
me_dst->corner_verts(),
me_dst->corner_edges(),
me_dst->vert_normals(),
me_dst->poly_normals(),
sharp_faces,
@@ -1563,7 +1565,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
const int num_verts_dst = me_dst->totvert;
const blender::Span<MEdge> edges_dst = me_dst->edges();
const blender::Span<MPoly> polys_dst = me_dst->polys();
const blender::Span<MLoop> loops_dst = me_dst->loops();
const blender::Span<int> corner_verts_dst = me_dst->corner_verts();
const blender::Span<int> corner_edges_dst = me_dst->corner_edges();
CustomData *ldata_dst = &me_dst->ldata;
MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type);
@@ -1571,7 +1574,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (!geom_map_init[LDATA]) {
const int num_loops_src = me_src->totloop;
if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (loops_dst.size() != num_loops_src)) {
if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) &&
(corner_verts_dst.size() != num_loops_src)) {
BKE_report(reports,
RPT_ERROR,
"Source and destination meshes do not have the same amount of face corners, "
@@ -1585,7 +1589,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
"None of the 'Edge' mappings can be used in this case");
continue;
}
if (ELEM(0, loops_dst.size(), num_loops_src)) {
if (ELEM(0, corner_verts_dst.size(), num_loops_src)) {
BKE_report(
reports,
RPT_ERROR,
@@ -1602,8 +1606,9 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
num_verts_dst,
edges_dst.data(),
edges_dst.size(),
loops_dst.data(),
loops_dst.size(),
corner_verts_dst.data(),
corner_edges_dst.data(),
corner_verts_dst.size(),
polys_dst.data(),
polys_dst.size(),
ldata_dst,
@@ -1619,12 +1624,12 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (mdef && vg_idx != -1 && !weights[LDATA]) {
weights[LDATA] = static_cast<float *>(
MEM_mallocN(sizeof(*weights[LDATA]) * size_t(loops_dst.size()), __func__));
MEM_mallocN(sizeof(*weights[LDATA]) * size_t(corner_verts_dst.size()), __func__));
BKE_defvert_extract_vgroup_to_loopweights(mdef,
vg_idx,
num_verts_dst,
loops_dst.data(),
loops_dst.size(),
corner_verts_dst.data(),
corner_verts_dst.size(),
invert_vgroup,
weights[LDATA]);
}
@@ -1639,7 +1644,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
mix_mode,
mix_factor,
weights[LDATA],
loops_dst.size(),
corner_verts_dst.size(),
use_create,
use_delete,
fromlayers,
@@ -1661,7 +1666,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst);
const int num_verts_dst = me_dst->totvert;
const blender::Span<MPoly> polys_dst = me_dst->polys();
const blender::Span<MLoop> loops_dst = me_dst->loops();
const blender::Span<int> corner_verts_dst = me_dst->corner_verts();
if (!geom_map_init[PDATA]) {
const int num_polys_src = me_src->totpoly;
@@ -1695,7 +1700,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
me_dst,
positions_dst,
num_verts_dst,
loops_dst.data(),
corner_verts_dst.data(),
polys_dst.data(),
polys_dst.size(),
me_src,
@@ -1709,8 +1714,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
BKE_defvert_extract_vgroup_to_polyweights(mdef,
vg_idx,
num_verts_dst,
loops_dst.data(),
loops_dst.size(),
corner_verts_dst.data(),
corner_verts_dst.size(),
polys_dst.data(),
polys_dst.size(),
invert_vgroup,
+6 -8
View File
@@ -1074,7 +1074,7 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert,
void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
const int defgroup,
const int verts_num,
const MLoop *loops,
const int *corner_verts,
const int loops_num,
const bool invert_vgroup,
float *r_weights)
@@ -1088,9 +1088,7 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
while (i--) {
const MLoop *ml = &loops[i];
r_weights[i] = tmp_weights[ml->v];
r_weights[i] = tmp_weights[corner_verts[i]];
}
MEM_freeN(tmp_weights);
@@ -1103,7 +1101,7 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert,
const int defgroup,
const int verts_num,
const MLoop *loops,
const int *corner_verts,
const int /*loops_num*/,
const MPoly *polys,
const int polys_num,
@@ -1120,12 +1118,12 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert,
while (i--) {
const MPoly &poly = polys[i];
const MLoop *ml = &loops[poly.loopstart];
const int *corner_vert = &corner_verts[poly.loopstart];
int j = poly.totloop;
float w = 0.0f;
for (; j--; ml++) {
w += tmp_weights[ml->v];
for (; j--; corner_vert++) {
w += tmp_weights[*corner_vert];
}
r_weights[i] = w / float(poly.totloop);
}
@@ -1416,7 +1416,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
int numOfPolys = mesh->totpoly;
const blender::Span<MEdge> edges = mesh->edges();
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
/* count number of edges per vertex */
for (int i = 0; i < numOfEdges; i++) {
@@ -1431,7 +1431,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
* to locate points on "mesh edge" */
for (int i = 0; i < numOfPolys; i++) {
for (int j = 0; j < polys[i].totloop; j++) {
temp_data[loops[polys[i].loopstart + j].v]++;
temp_data[corner_verts[polys[i].loopstart + j]]++;
}
}
@@ -1479,7 +1479,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
struct DynamicPaintSetInitColorData {
const DynamicPaintSurface *surface;
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
const float (*mloopuv)[2];
blender::Span<MLoopTri> looptris;
const MLoopCol *mloopcol;
@@ -1497,7 +1497,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
const PaintSurfaceData *sData = data->surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
ImagePool *pool = data->pool;
@@ -1509,7 +1509,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
for (int j = 3; j--;) {
TexResult texres = {0};
const uint vert = loops[looptris[i].tri[j]].v;
const int vert = corner_verts[looptris[i].tri[j]];
/* remap to [-1.0, 1.0] */
uv[0] = mloopuv[looptris[i].tri[j]][0] * 2.0f - 1.0f;
@@ -1618,7 +1618,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
Tex *tex = surface->init_texture;
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<MLoopTri> looptris = mesh->looptris();
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@@ -1643,7 +1643,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.loops = loops;
data.corner_verts = corner_verts;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.pool = pool;
@@ -1675,15 +1675,15 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
/* For vertex surface, just copy colors from #MLoopCol. */
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const MLoopCol *col = static_cast<const MLoopCol *>(
CustomData_get_layer_named(&mesh->ldata, CD_PROP_BYTE_COLOR, surface->init_layername));
if (!col) {
return;
}
for (const int i : loops.index_range()) {
rgba_uchar_to_float(pPoint[loops[i].v].color, (const uchar *)&col[i].r);
for (const int i : corner_verts.index_range()) {
rgba_uchar_to_float(pPoint[corner_verts[i]].color, (const uchar *)&col[i].r);
}
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
@@ -1791,7 +1791,7 @@ struct DynamicPaintModifierApplyData {
float (*vert_positions)[3];
blender::Span<blender::float3> vert_normals;
blender::Span<MPoly> polys;
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
float (*fcolor)[4];
MLoopCol *mloopcol;
@@ -1860,7 +1860,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata,
userdata);
const blender::Span<MPoly> polys = data->polys;
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
const DynamicPaintSurface *surface = data->surface;
PaintPoint *pPoint = (PaintPoint *)surface->data->type_data;
@@ -1871,7 +1871,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata,
for (int j = 0; j < polys[p_index].totloop; j++) {
const int l_index = polys[p_index].loopstart + j;
const int v_index = loops[l_index].v;
const int v_index = corner_verts[l_index];
/* save layer data to output layer */
/* apply color */
@@ -1929,7 +1929,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
/* vertex color paint */
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
const blender::Span<MPoly> polys = result->polys();
const blender::Span<MLoop> loops = result->loops();
const blender::Span<int> corner_verts = result->corner_verts();
/* paint is stored on dry and wet layers, so mix final color first */
float(*fcolor)[4] = static_cast<float(*)[4]>(
@@ -1958,7 +1958,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
mloopcol = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
loops.size(),
corner_verts.size(),
surface->output_name));
}
@@ -1971,12 +1971,12 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
loops.size(),
corner_verts.size(),
surface->output_name2));
}
data.ob = ob;
data.loops = loops;
data.corner_verts = corner_verts;
data.polys = polys;
data.mloopcol = mloopcol;
data.mloopcol_wet = mloopcol_wet;
@@ -2191,7 +2191,7 @@ struct DynamicPaintCreateUVSurfaceData {
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
const Bounds2D *faceBB;
uint32_t *active_points;
@@ -2210,7 +2210,7 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
const Bounds2D *faceBB = data->faceBB;
@@ -2281,9 +2281,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
tPoint->tri_index = i;
/* save vertex indexes */
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
tPoint->v1 = corner_verts[looptris[i].tri[0]];
tPoint->v2 = corner_verts[looptris[i].tri[1]];
tPoint->v3 = corner_verts[looptris[i].tri[2]];
sample = 5; /* make sure we exit sample loop as well */
break;
@@ -2306,7 +2306,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
uint32_t *active_points = data->active_points;
@@ -2371,9 +2371,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
}
/* save vertex indexes */
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
tPoint->v1 = corner_verts[looptris[i].tri[0]];
tPoint->v2 = corner_verts[looptris[i].tri[1]];
tPoint->v3 = corner_verts[looptris[i].tri[2]];
break;
}
@@ -2514,7 +2514,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
int in_edge,
int depth)
{
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
@@ -2552,8 +2552,8 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
}
/* Now find another face that is linked to that edge. */
const int vert0 = loops[loop_idx[(edge_idx + 0)]].v;
const int vert1 = loops[loop_idx[(edge_idx + 1) % 3]].v;
const int vert0 = corner_verts[loop_idx[(edge_idx + 0)]];
const int vert1 = corner_verts[loop_idx[(edge_idx + 1) % 3]];
/* Use a pre-computed vert-to-looptri mapping,
* speeds up things a lot compared to looping over all looptri. */
@@ -2576,8 +2576,8 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
/* Check edges for match, looping in the same order as the outer loop. */
for (int j = 0; j < 3; j++) {
const int overt0 = loops[other_loop_idx[(j + 0)]].v;
const int overt1 = loops[other_loop_idx[(j + 1) % 3]].v;
const int overt0 = corner_verts[other_loop_idx[(j + 0)]];
const int overt1 = corner_verts[other_loop_idx[(j + 1) % 3]];
/* Allow for swapped vertex order */
if (overt0 == vert0 && overt1 == vert1) {
@@ -2828,7 +2828,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
return setError(canvas, N_("Cannot bake non-'image sequence' formats"));
}
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<MLoopTri> looptris = mesh->looptris();
/* get uv map */
@@ -2917,7 +2917,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
data.tempWeights = tempWeights;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.loops = loops;
data.corner_verts = corner_verts;
data.faceBB = faceBB;
{
@@ -2975,7 +2975,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
mesh->totvert,
looptris.data(),
looptris.size(),
loops.data(),
corner_verts.data(),
mesh->totloop);
int total_border = 0;
@@ -3434,14 +3434,14 @@ static void mesh_tris_spherecast_dp(void *userdata,
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
const int *corner_verts = data->corner_verts;
const float *t0, *t1, *t2;
float dist;
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
t0 = positions[corner_verts[looptris[index].tri[0]]];
t1 = positions[corner_verts[looptris[index].tri[1]]];
t2 = positions[corner_verts[looptris[index].tri[2]]];
dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
@@ -3466,13 +3466,13 @@ static void mesh_tris_nearest_point_dp(void *userdata,
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
const int *corner_verts = data->corner_verts;
float nearest_tmp[3], dist_sq;
const float *t0, *t1, *t2;
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
t0 = positions[corner_verts[looptris[index].tri[0]]];
t1 = positions[corner_verts[looptris[index].tri[1]]];
t2 = positions[corner_verts[looptris[index].tri[2]]];
closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
dist_sq = len_squared_v3v3(co, nearest_tmp);
@@ -3905,7 +3905,7 @@ struct DynamicPaintPaintData {
Mesh *mesh;
const float (*positions)[3];
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
float brush_radius;
const float *avg_brushNor;
@@ -3939,7 +3939,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
const int c_index = data->c_index;
const float(*positions)[3] = data->positions;
const blender::Span<MLoop> loops = data->loops;
const blender::Span<int> corner_verts = data->corner_verts;
const blender::Span<MLoopTri> looptris = data->looptris;
const float brush_radius = data->brush_radius;
const float *avg_brushNor = data->avg_brushNor;
@@ -4013,9 +4013,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
/* For optimization sake, hit point normal isn't calculated in ray cast loop */
const int vtri[3] = {
int(loops[looptris[hit.index].tri[0]].v),
int(loops[looptris[hit.index].tri[1]].v),
int(loops[looptris[hit.index].tri[2]].v),
corner_verts[looptris[hit.index].tri[0]],
corner_verts[looptris[hit.index].tri[1]],
corner_verts[looptris[hit.index].tri[2]],
};
float dot;
@@ -4163,9 +4163,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
float brushPointVelocity[3];
float velocity[3];
const int v1 = loops[looptris[hitTri].tri[0]].v;
const int v2 = loops[looptris[hitTri].tri[1]].v;
const int v3 = loops[looptris[hitTri].tri[2]].v;
const int v1 = corner_verts[looptris[hitTri].tri[0]];
const int v2 = corner_verts[looptris[hitTri].tri[1]];
const int v3 = corner_verts[looptris[hitTri].tri[2]];
/* calculate barycentric weights for hit point */
interp_weights_tri_v3(weights, positions[v1], positions[v2], positions[v3], hitCoord);
@@ -4287,8 +4287,8 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh);
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<MLoopTri> looptris = mesh->looptris();
const blender::Span<MLoop> loops = mesh->loops();
numOfVerts = mesh->totvert;
/* Transform collider vertices to global space
@@ -4342,7 +4342,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
data.c_index = c_index;
data.mesh = mesh;
data.positions = positions;
data.loops = loops;
data.corner_verts = corner_verts;
data.looptris = looptris;
data.brush_radius = brush_radius;
data.avg_brushNor = avg_brushNor;
+4 -4
View File
@@ -660,12 +660,12 @@ bool closest_point_on_surface(SurfaceModifierData *surmd,
}
if (surface_vel) {
const MLoop *mloop = bvhtree->loop;
const int *corner_verts = bvhtree->corner_verts;
const MLoopTri *lt = &bvhtree->looptri[nearest.index];
copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[0]].v]);
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[1]].v]);
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[mloop[lt->tri[2]].v]);
copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[0]]]);
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[1]]]);
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[2]]]);
mul_v3_fl(surface_vel, (1.0f / 3.0f));
}
+52 -52
View File
@@ -840,7 +840,7 @@ BLI_INLINE void apply_effector_fields(FluidEffectorSettings * /*fes*/,
static void update_velocities(FluidEffectorSettings *fes,
const float (*vert_positions)[3],
const MLoop *mloop,
const int *corner_verts,
const MLoopTri *mlooptri,
float *velocity_map,
int index,
@@ -866,9 +866,9 @@ static void update_velocities(FluidEffectorSettings *fes,
int v1, v2, v3, f_index = nearest.index;
/* Calculate barycentric weights for nearest point. */
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
v1 = corner_verts[mlooptri[f_index].tri[0]];
v2 = corner_verts[mlooptri[f_index].tri[1]];
v3 = corner_verts[mlooptri[f_index].tri[2]];
interp_weights_tri_v3(
weights, vert_positions[v1], vert_positions[v2], vert_positions[v3], nearest.co);
@@ -938,7 +938,7 @@ struct ObstaclesFromDMData {
FluidEffectorSettings *fes;
const float (*vert_positions)[3];
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
BVHTreeFromMesh *tree;
@@ -973,7 +973,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
/* Calculate object velocities. Result in bb->velocity. */
update_velocities(data->fes,
data->vert_positions,
data->loops.data(),
data->corner_verts.data(),
data->looptris.data(),
bb->velocity,
index,
@@ -1008,7 +1008,7 @@ static void obstacles_from_mesh(Object *coll_ob,
int min[3], max[3], res[3];
const blender::Span<MLoop> loops = me->loops();
const blender::Span<int> corner_verts = me->corner_verts();
const blender::Span<MLoopTri> looptris = me->looptris();
numverts = me->totvert;
@@ -1072,7 +1072,7 @@ static void obstacles_from_mesh(Object *coll_ob,
ObstaclesFromDMData data{};
data.fes = fes;
data.vert_positions = positions;
data.loops = loops;
data.corner_verts = corner_verts;
data.looptris = looptris;
data.tree = &tree_data;
data.bb = bb;
@@ -1786,7 +1786,7 @@ static void update_distances(int index,
static void sample_mesh(FluidFlowSettings *ffs,
const float (*vert_positions)[3],
const blender::Span<blender::float3> vert_normals,
const MLoop *mloop,
const int *corner_verts,
const MLoopTri *mlooptri,
const float (*mloopuv)[2],
float *influence_map,
@@ -1869,9 +1869,9 @@ static void sample_mesh(FluidFlowSettings *ffs,
float hit_normal[3];
/* Calculate barycentric weights for nearest point. */
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
v1 = corner_verts[mlooptri[f_index].tri[0]];
v2 = corner_verts[mlooptri[f_index].tri[1]];
v3 = corner_verts[mlooptri[f_index].tri[2]];
interp_weights_tri_v3(
weights, vert_positions[v1], vert_positions[v2], vert_positions[v3], nearest.co);
@@ -1981,7 +1981,7 @@ struct EmitFromDMData {
const float (*vert_positions)[3];
blender::Span<blender::float3> vert_normals;
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
const MDeformVert *dvert;
@@ -2015,7 +2015,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
sample_mesh(data->ffs,
data->vert_positions,
data->vert_normals,
data->loops.data(),
data->corner_verts.data(),
data->looptris.data(),
data->mloopuv,
bb->influence,
@@ -2065,7 +2065,7 @@ static void emit_from_mesh(
Mesh *me = BKE_mesh_copy_for_eval(ffs->mesh, false);
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
const blender::Span<MLoop> loops = me->loops();
const blender::Span<int> corner_verts = me->corner_verts();
const blender::Span<MLoopTri> looptris = me->looptris();
const int numverts = me->totvert;
const MDeformVert *dvert = BKE_mesh_deform_verts(me);
@@ -2136,7 +2136,7 @@ static void emit_from_mesh(
data.ffs = ffs;
data.vert_positions = positions;
data.vert_normals = me->vert_normals();
data.loops = loops;
data.corner_verts = corner_verts;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.dvert = dvert;
@@ -3235,7 +3235,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
}
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
blender::MutableSpan<MPoly> polys = me->polys_for_write();
blender::MutableSpan<MLoop> loops = me->loops_for_write();
blender::MutableSpan<int> corner_verts = me->corner_verts_for_write();
const bool is_sharp = orgmesh->attributes().lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false)[0];
@@ -3332,9 +3332,9 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
polys[i].loopstart = i * 3;
polys[i].totloop = 3;
loops[i * 3 + 0].v = manta_liquid_get_triangle_x_at(fds->fluid, i);
loops[i * 3 + 1].v = manta_liquid_get_triangle_y_at(fds->fluid, i);
loops[i * 3 + 2].v = manta_liquid_get_triangle_z_at(fds->fluid, i);
corner_verts[i * 3 + 0] = manta_liquid_get_triangle_x_at(fds->fluid, i);
corner_verts[i * 3 + 1] = manta_liquid_get_triangle_y_at(fds->fluid, i);
corner_verts[i * 3 + 2] = manta_liquid_get_triangle_z_at(fds->fluid, i);
# ifdef DEBUG_PRINT
/* Debugging: Print mesh faces. */
printf("mloops[0].v: %d, mloops[1].v: %d, mloops[2].v: %d\n",
@@ -3356,7 +3356,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
float max[3];
float *co;
MPoly *poly;
MLoop *ml;
int *corner_vert;
int num_verts = 8;
int num_faces = 6;
@@ -3371,7 +3371,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
result = BKE_mesh_new_nomain(num_verts, 0, num_faces * 4, num_faces);
float(*positions)[3] = BKE_mesh_vert_positions_for_write(result);
blender::MutableSpan<MPoly> polys = result->polys_for_write();
blender::MutableSpan<MLoop> loops = result->loops_for_write();
blender::MutableSpan<int> corner_verts = result->corner_verts_for_write();
if (num_verts) {
/* Volume bounds. */
@@ -3417,58 +3417,58 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
/* Create faces. */
/* Top side. */
poly = &polys[0];
ml = &loops[0 * 4];
corner_vert = &corner_verts[0 * 4];
poly->loopstart = 0 * 4;
poly->totloop = 4;
ml[0].v = 0;
ml[1].v = 1;
ml[2].v = 2;
ml[3].v = 3;
corner_vert[0] = 0;
corner_vert[1] = 1;
corner_vert[2] = 2;
corner_vert[3] = 3;
/* Right side. */
poly = &polys[1];
ml = &loops[1 * 4];
corner_vert = &corner_verts[1 * 4];
poly->loopstart = 1 * 4;
poly->totloop = 4;
ml[0].v = 2;
ml[1].v = 1;
ml[2].v = 5;
ml[3].v = 6;
corner_vert[0] = 2;
corner_vert[1] = 1;
corner_vert[2] = 5;
corner_vert[3] = 6;
/* Bottom side. */
poly = &polys[2];
ml = &loops[2 * 4];
corner_vert = &corner_verts[2 * 4];
poly->loopstart = 2 * 4;
poly->totloop = 4;
ml[0].v = 7;
ml[1].v = 6;
ml[2].v = 5;
ml[3].v = 4;
corner_vert[0] = 7;
corner_vert[1] = 6;
corner_vert[2] = 5;
corner_vert[3] = 4;
/* Left side. */
poly = &polys[3];
ml = &loops[3 * 4];
corner_vert = &corner_verts[3 * 4];
poly->loopstart = 3 * 4;
poly->totloop = 4;
ml[0].v = 0;
ml[1].v = 3;
ml[2].v = 7;
ml[3].v = 4;
corner_vert[0] = 0;
corner_vert[1] = 3;
corner_vert[2] = 7;
corner_vert[3] = 4;
/* Front side. */
poly = &polys[4];
ml = &loops[4 * 4];
corner_vert = &corner_verts[4 * 4];
poly->loopstart = 4 * 4;
poly->totloop = 4;
ml[0].v = 3;
ml[1].v = 2;
ml[2].v = 6;
ml[3].v = 7;
corner_vert[0] = 3;
corner_vert[1] = 2;
corner_vert[2] = 6;
corner_vert[3] = 7;
/* Back side. */
poly = &polys[5];
ml = &loops[5 * 4];
corner_vert = &corner_verts[5 * 4];
poly->loopstart = 5 * 4;
poly->totloop = 4;
ml[0].v = 1;
ml[1].v = 0;
ml[2].v = 4;
ml[3].v = 5;
corner_vert[0] = 1;
corner_vert[1] = 0;
corner_vert[2] = 4;
corner_vert[3] = 5;
/* Calculate required shift to match domain's global position
* it was originally simulated at (if object moves without manta step). */
@@ -174,15 +174,11 @@ static void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
MutableSpan<T> r_values)
{
BLI_assert(r_values.size() == mesh.totvert);
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
attribute_math::DefaultMixer<T> mixer(r_values);
for (const int loop_index : IndexRange(mesh.totloop)) {
const T value = old_values[loop_index];
const MLoop &loop = loops[loop_index];
const int point_index = loop.v;
mixer.mix_in(point_index, value);
for (const int corner : IndexRange(mesh.totloop)) {
mixer.mix_in(corner_verts[corner], old_values[corner]);
}
mixer.finalize();
}
@@ -194,17 +190,16 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
MutableSpan<bool> r_values)
{
BLI_assert(r_values.size() == mesh.totvert);
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
Array<bool> loose_verts(mesh.totvert, true);
r_values.fill(true);
for (const int loop_index : IndexRange(mesh.totloop)) {
const MLoop &loop = loops[loop_index];
const int point_index = loop.v;
for (const int corner : IndexRange(mesh.totloop)) {
const int point_index = corner_verts[corner];
loose_verts[point_index] = false;
if (!old_values[loop_index]) {
if (!old_values[corner]) {
r_values[point_index] = false;
}
}
@@ -242,16 +237,15 @@ static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray
*/
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
{
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
new_varray = VArray<T>::ForFunc(mesh.totloop,
[loops, varray = varray.typed<T>()](const int64_t loop_index) {
const int vertex_index = loops[loop_index].v;
return varray[vertex_index];
});
new_varray = VArray<T>::ForFunc(
mesh.totloop, [corner_verts, varray = varray.typed<T>()](const int64_t corner) {
return varray[corner_verts[corner]];
});
});
return new_varray;
}
@@ -303,7 +297,7 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totedge);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -315,8 +309,7 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
const int next_i = (i + 1) % poly.totloop;
const int loop_i = poly.loopstart + i;
const int next_loop_i = poly.loopstart + next_i;
const MLoop &loop = loops[loop_i];
const int edge_index = loop.e;
const int edge_index = corner_edges[loop_i];
mixer.mix_in(edge_index, old_values[loop_i]);
mixer.mix_in(edge_index, old_values[next_loop_i]);
}
@@ -333,7 +326,7 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totedge);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
r_values.fill(true);
for (const int poly_index : polys.index_range()) {
@@ -343,8 +336,7 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
const int next_i = (i + 1) % poly.totloop;
const int loop_i = poly.loopstart + i;
const int next_loop_i = poly.loopstart + next_i;
const MLoop &loop = loops[loop_i];
const int edge_index = loop.e;
const int edge_index = corner_edges[loop_i];
if (!old_values[loop_i] || !old_values[next_loop_i]) {
r_values[edge_index] = false;
@@ -385,17 +377,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totvert);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
attribute_math::DefaultMixer<T> mixer(r_values);
for (const int poly_index : polys.index_range()) {
const MPoly &poly = polys[poly_index];
const T value = old_values[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
const int point_index = loop.v;
mixer.mix_in(point_index, value);
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
mixer.mix_in(vert, value);
}
}
@@ -410,15 +400,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totvert);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
r_values.fill(false);
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
for (const int poly_index : range) {
if (old_values[poly_index]) {
const MPoly &poly = polys[poly_index];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
r_values[loop.v] = true;
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
r_values[vert] = true;
}
}
}
@@ -476,16 +466,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totedge);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
attribute_math::DefaultMixer<T> mixer(r_values);
for (const int poly_index : polys.index_range()) {
const MPoly &poly = polys[poly_index];
const T value = old_values[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
mixer.mix_in(loop.e, value);
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
mixer.mix_in(edge, value);
}
}
mixer.finalize();
@@ -499,15 +488,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totedge);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
r_values.fill(false);
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
for (const int poly_index : range) {
if (old_values[poly_index]) {
const MPoly &poly = polys[poly_index];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
r_values[loop.e] = true;
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
r_values[edge] = true;
}
}
}
@@ -530,7 +519,7 @@ static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &v
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
{
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
@@ -538,12 +527,12 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
if constexpr (std::is_same_v<T, bool>) {
new_varray = VArray<T>::ForFunc(
mesh.totpoly, [loops, polys, varray = varray.typed<bool>()](const int face_index) {
mesh.totpoly,
[corner_verts, polys, varray = varray.typed<bool>()](const int face_index) {
/* A face is selected if all of its vertices were selected. */
const MPoly &poly = polys[face_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
if (!varray[loop.v]) {
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
if (!varray[vert]) {
return false;
}
}
@@ -552,14 +541,12 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &
}
else {
new_varray = VArray<T>::ForFunc(
mesh.totpoly, [loops, polys, varray = varray.typed<T>()](const int face_index) {
mesh.totpoly, [corner_verts, polys, varray = varray.typed<T>()](const int face_index) {
T return_value;
attribute_math::DefaultMixer<T> mixer({&return_value, 1});
const MPoly &poly = polys[face_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
const T value = varray[loop.v];
mixer.mix_in(0, value);
for (const int vert : corner_verts.slice(poly.loopstart, poly.totloop)) {
mixer.mix_in(0, varray[vert]);
}
mixer.finalize();
return return_value;
@@ -610,7 +597,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totloop);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
attribute_math::DefaultMixer<T> mixer(r_values);
@@ -620,10 +607,10 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
/* For every corner, mix the values from the adjacent edges on the face. */
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index);
const MLoop &loop = loops[loop_index];
const MLoop &loop_prev = loops[loop_index_prev];
mixer.mix_in(loop_index, old_values[loop.e]);
mixer.mix_in(loop_index, old_values[loop_prev.e]);
const int edge = corner_edges[loop_index];
const int edge_prev = corner_edges[loop_index_prev];
mixer.mix_in(loop_index, old_values[edge]);
mixer.mix_in(loop_index, old_values[edge_prev]);
}
}
@@ -638,7 +625,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
{
BLI_assert(r_values.size() == mesh.totloop);
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
r_values.fill(false);
@@ -647,9 +634,9 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
const MPoly &poly = polys[poly_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int loop_index_prev = mesh_topology::poly_loop_prev(poly, loop_index);
const MLoop &loop = loops[loop_index];
const MLoop &loop_prev = loops[loop_index_prev];
if (old_values[loop.e] && old_values[loop_prev.e]) {
const int edge = corner_edges[loop_index];
const int edge_prev = corner_edges[loop_index_prev];
if (old_values[edge] && old_values[edge_prev]) {
r_values[loop_index] = true;
}
}
@@ -729,7 +716,7 @@ static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &
static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
{
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_edges = mesh.corner_edges();
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
@@ -738,11 +725,10 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v
if constexpr (std::is_same_v<T, bool>) {
/* A face is selected if all of its edges are selected. */
new_varray = VArray<bool>::ForFunc(
polys.size(), [loops, polys, varray = varray.typed<T>()](const int face_index) {
polys.size(), [corner_edges, polys, varray = varray.typed<T>()](const int face_index) {
const MPoly &poly = polys[face_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
if (!varray[loop.e]) {
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
if (!varray[edge]) {
return false;
}
}
@@ -751,14 +737,12 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v
}
else {
new_varray = VArray<T>::ForFunc(
polys.size(), [loops, polys, varray = varray.typed<T>()](const int face_index) {
polys.size(), [corner_edges, polys, varray = varray.typed<T>()](const int face_index) {
T return_value;
attribute_math::DefaultMixer<T> mixer({&return_value, 1});
const MPoly &poly = polys[face_index];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const MLoop &loop = loops[loop_index];
const T value = varray[loop.e];
mixer.mix_in(0, value);
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
mixer.mix_in(0, varray[edge]);
}
mixer.finalize();
return return_value;
@@ -1207,6 +1191,35 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
nullptr,
AttributeValidator{&material_index_clamp});
/* Note: This clamping is more of a last resort, since it's quite easy to make an
* invalid mesh that will crash Blender by arbitrarily editing this attribute. */
static const auto int_index_clamp = mf::build::SI1_SO<int, int>(
"Index Validate",
[](int value) { return std::max(value, 0); },
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider corner_vert(".corner_vert",
ATTR_DOMAIN_CORNER,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::NonCreatable,
BuiltinAttributeProvider::NonDeletable,
corner_access,
make_array_read_attribute<int>,
make_array_write_attribute<int>,
nullptr,
AttributeValidator{&int_index_clamp});
static BuiltinCustomDataLayerProvider corner_edge(".corner_edge",
ATTR_DOMAIN_CORNER,
CD_PROP_INT32,
CD_PROP_INT32,
BuiltinAttributeProvider::NonCreatable,
BuiltinAttributeProvider::NonDeletable,
corner_access,
make_array_read_attribute<int>,
make_array_write_attribute<int>,
nullptr,
AttributeValidator{&int_index_clamp});
static BuiltinCustomDataLayerProvider sharp_face("sharp_face",
ATTR_DOMAIN_FACE,
CD_PROP_BOOL,
@@ -1247,13 +1260,19 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access);
static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access);
return ComponentAttributeProviders(
{&position, &id, &material_index, &sharp_face, &sharp_edge, &crease},
{&corner_custom_data,
&vertex_groups,
&point_custom_data,
&edge_custom_data,
&face_custom_data});
return ComponentAttributeProviders({&position,
&corner_vert,
&corner_edge,
&id,
&material_index,
&sharp_face,
&sharp_edge,
&crease},
{&corner_custom_data,
&vertex_groups,
&point_custom_data,
&edge_custom_data,
&face_custom_data});
}
static AttributeAccessorFunctions get_mesh_accessor_functions()
@@ -2715,7 +2715,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
const Span<float3> positions = me_eval->vert_positions();
const Span<MPoly> polys = me_eval->polys();
const Span<MLoop> loops = me_eval->loops();
const Span<int> corner_verts = me_eval->corner_verts();
int polys_len = me_eval->totpoly;
char element_name[200];
@@ -2787,10 +2787,10 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
/* Add points to strokes. */
for (int j = 0; j < poly.totloop; j++) {
const MLoop *ml = &loops[poly.loopstart + j];
const int vert = corner_verts[poly.loopstart + j];
bGPDspoint *pt = &gps_fill->points[j];
copy_v3_v3(&pt->x, positions[ml->v]);
copy_v3_v3(&pt->x, positions[vert]);
mul_m4_v3(matrix, &pt->x);
pt->pressure = 1.0f;
pt->strength = 1.0f;
@@ -2798,7 +2798,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
/* Copy vertex groups from mesh. Assuming they already exist in the same order. */
if (use_vgroups && !dverts.is_empty()) {
MDeformVert *dv = &gps_fill->dvert[j];
const MDeformVert *src_dv = &dverts[ml->v];
const MDeformVert *src_dv = &dverts[vert];
dv->totweight = src_dv->totweight;
dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
"gp_fill_dverts_dw");
+8 -6
View File
@@ -2235,7 +2235,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
BKE_keyblock_convert_to_mesh(kb, positions, mesh->totvert);
const blender::Span<MEdge> edges = mesh->edges();
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const blender::Span<int> corner_edges = mesh->corner_edges();
const bool loop_normals_needed = r_loop_normals != nullptr;
const bool vert_normals_needed = r_vert_normals != nullptr || loop_normals_needed;
@@ -2261,20 +2262,20 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
blender::bke::mesh::normals_calc_polys(
{reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
polys,
loops,
corner_verts,
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()});
}
if (vert_normals_needed) {
blender::bke::mesh::normals_calc_poly_vert(
{reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
polys,
loops,
corner_verts,
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert});
}
if (loop_normals_needed) {
short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer_for_write(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, loops.size())); /* May be nullptr. */
&mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); /* May be nullptr. */
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>(
@@ -2283,7 +2284,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
{reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
edges,
polys,
loops,
corner_verts,
corner_edges,
{},
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert},
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
@@ -2293,7 +2295,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
mesh->smoothresh,
clnors,
nullptr,
{reinterpret_cast<blender::float3 *>(r_loop_normals), loops.size()});
{reinterpret_cast<blender::float3 *>(r_loop_normals), corner_verts.size()});
}
if (free_vert_normals) {
@@ -1470,8 +1470,8 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
mesh->totpoly = int(process.curindex);
MPoly *polys = static_cast<MPoly *>(
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, mesh->totpoly));
MLoop *mloop = static_cast<MLoop *>(
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, mesh->totpoly * 4));
int *corner_verts = static_cast<int *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totpoly * 4, ".corner_vert"));
int loop_offset = 0;
for (int i = 0; i < mesh->totpoly; i++) {
@@ -1481,11 +1481,11 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
polys[i].loopstart = loop_offset;
polys[i].totloop = count;
mloop[loop_offset].v = uint32_t(indices[0]);
mloop[loop_offset + 1].v = uint32_t(indices[1]);
mloop[loop_offset + 2].v = uint32_t(indices[2]);
corner_verts[loop_offset] = indices[0];
corner_verts[loop_offset + 1] = indices[1];
corner_verts[loop_offset + 2] = indices[2];
if (count == 4) {
mloop[loop_offset + 3].v = uint32_t(indices[3]);
corner_verts[loop_offset + 3] = indices[3];
}
loop_offset += count;
+46 -48
View File
@@ -256,6 +256,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
if (!BLO_write_is_undo(writer)) {
/* When converting to the old mesh format, don't save redundant attributes. */
names_to_skip.add_multiple_new({"position",
".corner_vert",
".corner_edge",
".hide_vert",
".hide_edge",
".hide_poly",
@@ -269,6 +271,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
mesh->mvert = BKE_mesh_legacy_convert_positions_to_verts(
mesh, temp_arrays_for_legacy_format, vert_layers);
mesh->mloop = BKE_mesh_legacy_convert_corners_to_loops(
mesh, temp_arrays_for_legacy_format, loop_layers);
BKE_mesh_legacy_convert_hide_layers_to_flags(mesh);
BKE_mesh_legacy_convert_selection_layers_to_flags(mesh);
BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh);
@@ -285,7 +289,6 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
/* Set deprecated mesh data pointers for forward compatibility. */
mesh->medge = const_cast<MEdge *>(mesh->edges().data());
mesh->mpoly = const_cast<MPoly *>(mesh->polys().data());
mesh->mloop = const_cast<MLoop *>(mesh->loops().data());
mesh->dvert = const_cast<MDeformVert *>(mesh->deform_verts().data());
}
@@ -518,14 +521,12 @@ static bool is_uv_bool_sublayer(CustomDataLayer const *l)
/** Thresh is threshold for comparing vertices, UVs, vertex colors, weights, etc. */
static int customdata_compare(
CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh)
CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, const float thresh)
{
CustomDataLayer *l1, *l2;
int layer_count1 = 0, layer_count2 = 0, j;
const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MDEFORMVERT;
const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic;
const Span<MLoop> loops_1 = m1->loops();
const Span<MLoop> loops_2 = m2->loops();
/* The uv selection / pin layers are ignored in the comparisons because
* the original flags they replace were ignored as well. Because of the
@@ -574,6 +575,12 @@ static int customdata_compare(
found_corresponding_layer = true;
if (StringRef(l1->name) == ".corner_edge") {
/* TODO(Hans): This attribute wasn't tested before loops were refactored into separate
* corner edges and corner verts attributes. Remove after updating tests. */
continue;
}
switch (l1->type) {
/* We're order-agnostic for edges here. */
case CD_MEDGE: {
@@ -600,32 +607,9 @@ static int customdata_compare(
int ptot = m1->totpoly;
for (j = 0; j < ptot; j++, p1++, p2++) {
int k;
if (p1->totloop != p2->totloop) {
return MESHCMP_POLYMISMATCH;
}
const MLoop *lp1 = &loops_1[p1->loopstart];
const MLoop *lp2 = &loops_2[p2->loopstart];
for (k = 0; k < p1->totloop; k++, lp1++, lp2++) {
if (lp1->v != lp2->v) {
return MESHCMP_POLYVERTMISMATCH;
}
}
}
break;
}
case CD_MLOOP: {
MLoop *lp1 = (MLoop *)l1->data;
MLoop *lp2 = (MLoop *)l2->data;
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
if (lp1->v != lp2->v) {
return MESHCMP_LOOPMISMATCH;
}
}
break;
}
@@ -791,19 +775,19 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
return "Number of loops don't match";
}
if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) {
if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, thresh))) {
return cmpcode_to_str(c);
}
if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) {
if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, thresh))) {
return cmpcode_to_str(c);
}
if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) {
if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, thresh))) {
return cmpcode_to_str(c);
}
if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) {
if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, thresh))) {
return cmpcode_to_str(c);
}
@@ -812,7 +796,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
bool BKE_mesh_attribute_required(const char *name)
{
return StringRef(name) == "position";
return ELEM(StringRef(name), "position", ".corner_vert", ".corner_edge");
}
void BKE_mesh_ensure_skin_customdata(Mesh *me)
@@ -970,8 +954,13 @@ static void mesh_ensure_cdlayers_primary(Mesh *mesh)
if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) {
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge);
}
if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) {
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop);
if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_vert");
}
if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, ".corner_edge");
}
if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) {
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly);
@@ -1516,10 +1505,10 @@ void BKE_mesh_auto_smooth_flag_set(Mesh *me,
}
}
int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, int vert)
int poly_find_loop_from_vert(const MPoly *poly, const int *poly_corner_verts, int vert)
{
for (int j = 0; j < poly->totloop; j++, loopstart++) {
if (loopstart->v == vert) {
for (int j = 0; j < poly->totloop; j++) {
if (poly_corner_verts[j] == vert) {
return j;
}
}
@@ -1527,14 +1516,17 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, int vert
return -1;
}
int poly_get_adj_loops_from_vert(const MPoly *poly, const MLoop *mloop, int vert, int r_adj[2])
int poly_get_adj_loops_from_vert(const MPoly *poly,
const int *corner_verts,
int vert,
int r_adj[2])
{
int corner = poly_find_loop_from_vert(poly, &mloop[poly->loopstart], vert);
int corner = poly_find_loop_from_vert(poly, &corner_verts[poly->loopstart], vert);
if (corner != -1) {
/* vertex was found */
r_adj[0] = ME_POLY_LOOP_PREV(mloop, poly, corner)->v;
r_adj[1] = ME_POLY_LOOP_NEXT(mloop, poly, corner)->v;
r_adj[0] = corner_verts[ME_POLY_LOOP_PREV(poly, corner)];
r_adj[1] = corner_verts[ME_POLY_LOOP_NEXT(poly, corner)];
}
return corner;
@@ -1553,18 +1545,23 @@ int BKE_mesh_edge_other_vert(const MEdge *edge, int v)
}
void BKE_mesh_looptri_get_real_edges(const MEdge *edges,
const MLoop *loops,
const int *corner_verts,
const int *corner_edges,
const MLoopTri *tri,
int r_edges[3])
{
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
const MLoop *l1 = &loops[tri->tri[i]], *l2 = &loops[tri->tri[i_next]];
const MEdge *edge = &edges[l1->e];
const int corner_1 = tri->tri[i];
const int corner_2 = tri->tri[i_next];
const int vert_1 = corner_verts[corner_1];
const int vert_2 = corner_verts[corner_2];
const int edge_i = corner_edges[corner_1];
const MEdge *edge = &edges[edge_i];
bool is_real = (l1->v == edge->v1 && l2->v == edge->v2) ||
(l1->v == edge->v2 && l2->v == edge->v1);
bool is_real = (vert_1 == edge->v1 && vert_2 == edge->v2) ||
(vert_1 == edge->v2 && vert_2 == edge->v1);
r_edges[i] = is_real ? l1->e : -1;
r_edges[i] = is_real ? edge_i : -1;
}
}
@@ -1859,7 +1856,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
mesh->vert_positions(),
mesh->edges(),
mesh->polys(),
mesh->loops(),
mesh->corner_verts(),
mesh->corner_edges(),
{},
mesh->vert_normals(),
mesh->poly_normals(),
@@ -304,7 +304,8 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
Vector<Vert *> verts(me->totvert);
const Span<float3> vert_positions = me->vert_positions();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
const Span<int> corner_edges = me->corner_edges();
/* Allocate verts
* Skip the matrix multiplication for each point when there is no transform for a mesh,
@@ -339,20 +340,19 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
int flen = poly.totloop;
face_vert.resize(flen);
face_edge_orig.resize(flen);
const MLoop *l = &loops[poly.loopstart];
for (int i = 0; i < flen; ++i) {
int mverti = r_info->mesh_vert_offset[mi] + l->v;
const int corner_i = poly.loopstart + i;
int mverti = r_info->mesh_vert_offset[mi] + corner_verts[corner_i];
const Vert *fv = r_info->mesh_to_imesh_vert[mverti];
if (need_face_flip) {
face_vert[flen - i - 1] = fv;
int iedge = i < flen - 1 ? flen - i - 2 : flen - 1;
face_edge_orig[iedge] = e + l->e;
face_edge_orig[iedge] = e + corner_edges[corner_i];
}
else {
face_vert[i] = fv;
face_edge_orig[i] = e + l->e;
face_edge_orig[i] = e + corner_edges[corner_i];
}
++l;
}
r_info->mesh_to_imesh_face[f] = arena.add_face(face_vert, f, face_edge_orig);
++f;
@@ -466,7 +466,7 @@ static int fill_orig_loops(const Face *f,
MutableSpan<int> r_orig_loops)
{
r_orig_loops.fill(-1);
const Span<MLoop> orig_loops = orig_me->loops();
const Span<int> orig_corner_verts = orig_me->corner_verts();
int orig_mplen = orig_poly->totloop;
if (f->size() != orig_mplen) {
@@ -494,7 +494,7 @@ static int fill_orig_loops(const Face *f,
int offset = -1;
for (int i = 0; i < orig_mplen; ++i) {
int loop_i = i + orig_poly->loopstart;
if (orig_loops[loop_i].v == first_orig_v_in_orig_me) {
if (orig_corner_verts[loop_i] == first_orig_v_in_orig_me) {
offset = i;
break;
}
@@ -505,7 +505,7 @@ static int fill_orig_loops(const Face *f,
int num_orig_loops_found = 0;
for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) {
int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen;
const MLoop *l = &orig_loops[orig_poly->loopstart + orig_mp_loop_index];
const int vert_i = orig_corner_verts[orig_poly->loopstart + orig_mp_loop_index];
int fv_orig = f->vert[mp_loop_index]->orig;
if (fv_orig != NO_INDEX) {
fv_orig -= orig_me_vert_offset;
@@ -513,9 +513,9 @@ static int fill_orig_loops(const Face *f,
fv_orig = NO_INDEX;
}
}
if (l->v == fv_orig) {
const MLoop *lnext =
&orig_loops[orig_poly->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)];
if (vert_i == fv_orig) {
const int vert_next =
orig_corner_verts[orig_poly->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)];
int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig;
if (fvnext_orig != NO_INDEX) {
fvnext_orig -= orig_me_vert_offset;
@@ -523,7 +523,7 @@ static int fill_orig_loops(const Face *f,
fvnext_orig = NO_INDEX;
}
}
if (lnext->v == fvnext_orig) {
if (vert_next == fvnext_orig) {
r_orig_loops[mp_loop_index] = orig_poly->loopstart + orig_mp_loop_index;
++num_orig_loops_found;
}
@@ -543,14 +543,14 @@ static void get_poly2d_cos(const Mesh *me,
float r_axis_mat[3][3])
{
const Span<float3> positions = me->vert_positions();
const Span<MLoop> loops = me->loops();
const Span<MLoop> poly_loops = loops.slice(poly->loopstart, poly->totloop);
const Span<int> corner_verts = me->corner_verts();
const Span<int> poly_verts = corner_verts.slice(poly->loopstart, poly->totloop);
/* Project coordinates to 2d in cos_2d, using normal as projection axis. */
const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_loops);
const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_verts);
axis_dominant_v3_to_m3(r_axis_mat, axis_dominant);
for (const int i : poly_loops.index_range()) {
float3 co = positions[poly_loops[i].v];
for (const int i : poly_verts.index_range()) {
float3 co = positions[poly_verts[i]];
co = math::transform_point(trans_mat, co);
*reinterpret_cast<float2 *>(&cos_2d[i]) = (float3x3(r_axis_mat) * co).xy();
}
@@ -588,7 +588,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
}
CustomData *target_cd = &dest_mesh->ldata;
const Span<float3> dst_positions = dest_mesh->vert_positions();
const Span<MLoop> dst_loops = dest_mesh->loops();
const Span<int> dst_corner_verts = dest_mesh->corner_verts();
for (int i = 0; i < poly->totloop; ++i) {
int loop_index = poly->loopstart + i;
int orig_loop_index = norig > 0 ? orig_loops[i] : -1;
@@ -598,12 +598,13 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
* The coordinate needs to be projected into 2d, just like the interpolating polygon's
* coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */
float co[2];
mul_v2_m3v3(co, axis_mat, dst_positions[dst_loops[loop_index].v]);
mul_v2_m3v3(co, axis_mat, dst_positions[dst_corner_verts[loop_index]]);
interp_weights_poly_v2(weights.data(), cos_2d, orig_poly->totloop, co);
}
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
int ty = source_cd->layers[source_layer_i].type;
if (ty == CD_MLOOP) {
if (STREQ(source_cd->layers[source_layer_i].name, ".corner_vert") ||
STREQ(source_cd->layers[source_layer_i].name, ".corner_edge")) {
continue;
}
const char *name = source_cd->layers[source_layer_i].name;
@@ -722,9 +723,8 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
result->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index",
ATTR_DOMAIN_FACE);
int cur_loop_index = 0;
MutableSpan<MLoop> dst_loops = result->loops_for_write();
MutableSpan<int> dst_corner_verts = result->corner_verts_for_write();
MutableSpan<MPoly> dst_polys = result->polys_for_write();
MLoop *l = dst_loops.data();
for (int fi : im->face_index_range()) {
const Face *f = im->face(fi);
const Mesh *orig_me;
@@ -738,8 +738,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
for (int j : f->index_range()) {
const Vert *vf = f->vert[j];
const int vfi = im->lookup_vert(vf);
l->v = vfi;
++l;
dst_corner_verts[cur_loop_index] = vfi;
++cur_loop_index;
}
@@ -762,6 +761,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
/* Now that the MEdges are populated, we can copy over the required attributes and custom layers.
*/
const Span<int> dst_corner_edges = result->corner_edges();
for (int fi : im->face_index_range()) {
const Face *f = im->face(fi);
const MPoly &poly = dst_polys[fi];
@@ -770,7 +770,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
const Mesh *orig_me;
int index_in_orig_me;
mim.input_medge_for_orig_index(f->edge_orig[j], &orig_me, &index_in_orig_me);
int e_index = dst_loops[poly.loopstart + j].e;
int e_index = dst_corner_edges[poly.loopstart + j];
copy_edge_attributes(result, orig_me, e_index, index_in_orig_me);
}
}
@@ -833,13 +833,13 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
/* Store intersecting edge indices. */
if (r_intersecting_edges != nullptr) {
const Span<MPoly> polys = result->polys();
const Span<MLoop> loops = result->loops();
const Span<int> corner_edges = result->corner_edges();
for (int fi : m_out.face_index_range()) {
const Face &face = *m_out.face(fi);
const MPoly &poly = polys[fi];
for (int corner_i : face.index_range()) {
if (face.is_intersect[corner_i]) {
int e_index = loops[poly.loopstart + corner_i].e;
int e_index = corner_edges[poly.loopstart + corner_i];
r_intersecting_edges->append(e_index);
}
}
@@ -98,22 +98,22 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh,
uint32_t parallel_mask)
{
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
const int task_index = &edge_map - edge_maps.data();
for (const MPoly &poly : polys) {
Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
const MLoop *prev_loop = &poly_loops.last();
for (const MLoop &next_loop : poly_loops) {
const Span<int> poly_verts = corner_verts.slice(poly.loopstart, poly.totloop);
int vert_prev = poly_verts.last();
for (const int vert : poly_verts) {
/* Can only be the same when the mesh data is invalid. */
if (prev_loop->v != next_loop.v) {
OrderedEdge ordered_edge{prev_loop->v, next_loop.v};
if (vert_prev != vert) {
OrderedEdge ordered_edge{vert_prev, vert};
/* Only add the edge when it belongs into this map. */
if (task_index == (parallel_mask & ordered_edge.hash2())) {
edge_map.lookup_or_add(ordered_edge, {nullptr});
}
}
prev_loop = &next_loop;
vert_prev = vert;
}
}
});
@@ -158,17 +158,21 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh,
uint32_t parallel_mask)
{
const Span<MPoly> polys = mesh->polys();
MutableSpan<MLoop> loops = mesh->loops_for_write();
const Span<int> corner_verts = mesh->corner_verts();
MutableSpan<int> corner_edges = mesh->corner_edges_for_write();
threading::parallel_for(IndexRange(mesh->totpoly), 100, [&](IndexRange range) {
for (const int poly_index : range) {
const MPoly &poly = polys[poly_index];
MutableSpan<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
const IndexRange corners(poly.loopstart, poly.totloop);
int prev_corner = corners.last();
for (const int next_corner : corners) {
const int vert = corner_verts[next_corner];
const int vert_prev = corner_verts[prev_corner];
MLoop *prev_loop = &poly_loops.last();
for (MLoop &next_loop : poly_loops) {
int edge_index;
if (prev_loop->v != next_loop.v) {
OrderedEdge ordered_edge{prev_loop->v, next_loop.v};
if (vert_prev != vert) {
OrderedEdge ordered_edge{vert_prev, vert};
/* Double lookup: First find the map that contains the edge, then lookup the edge. */
const EdgeMap &edge_map = edge_maps[parallel_mask & ordered_edge.hash2()];
edge_index = edge_map.lookup(ordered_edge).index;
@@ -179,8 +183,8 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh,
* #76514. */
edge_index = 0;
}
prev_loop->e = edge_index;
prev_loop = &next_loop;
corner_edges[prev_corner] = edge_index;
prev_corner = next_corner;
}
}
});
@@ -232,6 +236,10 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
}
/* Create new edges. */
if (!CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_edge");
}
MutableSpan<MEdge> new_edges{
static_cast<MEdge *>(MEM_calloc_arrayN(new_totedge, sizeof(MEdge), __func__)), new_totedge};
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges);
@@ -76,19 +76,18 @@ using blender::StringRefNull;
static CLG_LogRef LOG = {"bke.mesh_convert"};
static void poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const MLoop *mloop)
static void poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const Span<int> corner_verts)
{
const MLoop *ml, *ml_next;
int i = poly->totloop;
ml_next = mloop; /* first loop */
ml = &ml_next[i - 1]; /* last loop */
int corner_next = poly->loopstart; /* first loop */
int corner = corner_next + (i - 1); /* last loop */
while (i-- != 0) {
BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, nullptr);
BLI_edgehash_reinsert(ehash, corner_verts[corner], corner_verts[corner_next], nullptr);
ml = ml_next;
ml_next++;
corner = corner_next;
corner_next++;
}
}
@@ -100,13 +99,14 @@ static void make_edges_mdata_extend(Mesh &mesh)
int totedge = mesh.totedge;
const Span<MPoly> polys = mesh.polys();
MutableSpan<MLoop> loops = mesh.loops_for_write();
const Span<int> corner_verts = mesh.corner_verts();
MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
const int eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(mesh.totpoly));
EdgeHash *eh = BLI_edgehash_new_ex(__func__, eh_reserve);
for (const MPoly &poly : polys) {
poly_edgehash_insert(eh, &poly, &loops[poly.loopstart]);
poly_edgehash_insert(eh, &poly, corner_verts);
}
const int totedge_new = BLI_edgehash_len(eh);
@@ -139,13 +139,14 @@ static void make_edges_mdata_extend(Mesh &mesh)
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
MLoop *l = &loops[poly.loopstart];
MLoop *l_prev = (l + (poly.totloop - 1));
int corner = poly.loopstart;
int corner_prev = poly.loopstart + (poly.totloop - 1);
int j;
for (j = 0; j < poly.totloop; j++, l++) {
for (j = 0; j < poly.totloop; j++, corner++) {
/* lookup hashed edge index */
l_prev->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, l_prev->v, l->v));
l_prev = l;
corner_edges[corner_prev] = POINTER_AS_UINT(
BLI_edgehash_lookup(eh, corner_verts[corner_prev], corner_verts[corner]));
corner_prev = corner;
}
}
}
@@ -206,7 +207,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
MutableSpan<float3> positions = mesh->vert_positions_for_write();
MutableSpan<MEdge> edges = mesh->edges_for_write();
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
@@ -283,16 +284,16 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
a = dl->parts;
const int *index = dl->index;
while (a--) {
loops[dst_loop + 0].v = startvert + index[0];
loops[dst_loop + 1].v = startvert + index[2];
loops[dst_loop + 2].v = startvert + index[1];
corner_verts[dst_loop + 0] = startvert + index[0];
corner_verts[dst_loop + 1] = startvert + index[2];
corner_verts[dst_loop + 2] = startvert + index[1];
polys[dst_poly].loopstart = dst_loop;
polys[dst_poly].totloop = 3;
material_indices.span[dst_poly] = dl->col;
if (mloopuv) {
for (int i = 0; i < 3; i++, mloopuv++) {
(*mloopuv)[0] = (loops[dst_loop + i].v - startvert) / float(dl->nr - 1);
(*mloopuv)[0] = (corner_verts[dst_loop + i] - startvert) / float(dl->nr - 1);
(*mloopuv)[1] = 0.0f;
}
}
@@ -340,10 +341,10 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
}
for (; b < dl->nr; b++) {
loops[dst_loop + 0].v = p1;
loops[dst_loop + 1].v = p3;
loops[dst_loop + 2].v = p4;
loops[dst_loop + 3].v = p2;
corner_verts[dst_loop + 0] = p1;
corner_verts[dst_loop + 1] = p3;
corner_verts[dst_loop + 2] = p4;
corner_verts[dst_loop + 3] = p2;
polys[dst_poly].loopstart = dst_loop;
polys[dst_poly].totloop = 4;
material_indices.span[dst_poly] = dl->col;
@@ -365,7 +366,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
for (int i = 0; i < 4; i++, mloopuv++) {
/* find uv based on vertex index into grid array */
int v = loops[dst_loop + i].v - startvert;
int v = corner_verts[dst_loop + i] - startvert;
(*mloopuv)[0] = (v / dl->nr) / float(orco_sizev);
(*mloopuv)[1] = (v % dl->nr) / float(orco_sizeu);
@@ -470,7 +471,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
const Span<float3> positions = me->vert_positions();
const Span<MEdge> mesh_edges = me->edges();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_edges = me->corner_edges();
/* only to detect edge polylines */
int *edge_users;
@@ -481,10 +482,9 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
edge_users = (int *)MEM_calloc_arrayN(mesh_edges.size(), sizeof(int), __func__);
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
const MLoop *ml = &loops[poly.loopstart];
int j;
for (j = 0; j < poly.totloop; j++, ml++) {
edge_users[ml->e]++;
for (j = 0; j < poly.totloop; j++) {
edge_users[corner_edges[poly.loopstart + j]]++;
}
}
+110 -103
View File
@@ -40,43 +40,42 @@ using blender::VArray;
namespace blender::bke::mesh {
static float3 poly_center_calc_ngon(const Span<float3> vert_positions,
const Span<MLoop> poly_loops)
static float3 poly_center_calc_ngon(const Span<float3> vert_positions, const Span<int> poly_verts)
{
const float w = 1.0f / float(poly_loops.size());
const float w = 1.0f / float(poly_verts.size());
float3 center(0);
for (const int i : poly_loops.index_range()) {
center += vert_positions[poly_loops[i].v] * w;
for (const int i : poly_verts.index_range()) {
center += vert_positions[poly_verts[i]] * w;
}
return center;
}
float3 poly_center_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
float3 poly_center_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
{
if (poly_loops.size() == 3) {
if (poly_verts.size() == 3) {
float3 center;
mid_v3_v3v3v3(center,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v]);
vert_positions[poly_verts[0]],
vert_positions[poly_verts[1]],
vert_positions[poly_verts[2]]);
return center;
}
if (poly_loops.size() == 4) {
if (poly_verts.size() == 4) {
float3 center;
mid_v3_v3v3v3v3(center,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v],
vert_positions[poly_loops[3].v]);
vert_positions[poly_verts[0]],
vert_positions[poly_verts[1]],
vert_positions[poly_verts[2]],
vert_positions[poly_verts[3]]);
return center;
}
return poly_center_calc_ngon(vert_positions, poly_loops);
return poly_center_calc_ngon(vert_positions, poly_verts);
}
} // namespace blender::bke::mesh
void BKE_mesh_calc_poly_center(const MLoop *poly_loops,
void BKE_mesh_calc_poly_center(const int *poly_verts,
const int poly_size,
const float (*vert_positions)[3],
const int verts_num,
@@ -85,51 +84,51 @@ void BKE_mesh_calc_poly_center(const MLoop *poly_loops,
copy_v3_v3(r_cent,
blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions), verts_num},
{poly_loops, poly_size}));
{poly_verts, poly_size}));
}
namespace blender::bke::mesh {
float poly_area_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
float poly_area_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
{
if (poly_loops.size() == 3) {
return area_tri_v3(vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v]);
if (poly_verts.size() == 3) {
return area_tri_v3(vert_positions[poly_verts[0]],
vert_positions[poly_verts[1]],
vert_positions[poly_verts[2]]);
}
Array<float3, 32> poly_coords(poly_loops.size());
for (const int i : poly_loops.index_range()) {
poly_coords[i] = vert_positions[poly_loops[i].v];
Array<float3, 32> poly_coords(poly_verts.size());
for (const int i : poly_verts.index_range()) {
poly_coords[i] = vert_positions[poly_verts[i]];
}
return area_poly_v3((const float(*)[3])poly_coords.data(), poly_loops.size());
return area_poly_v3((const float(*)[3])poly_coords.data(), poly_verts.size());
}
} // namespace blender::bke::mesh
float BKE_mesh_calc_poly_area(const MLoop *poly_loops,
float BKE_mesh_calc_poly_area(const int *poly_verts,
const int poly_size,
const float (*vert_positions)[3],
const int verts_num)
{
return blender::bke::mesh::poly_area_calc(
{reinterpret_cast<const float3 *>(vert_positions), verts_num}, {poly_loops, poly_size});
{reinterpret_cast<const float3 *>(vert_positions), verts_num}, {poly_verts, poly_size});
}
float BKE_mesh_calc_area(const Mesh *me)
{
const Span<float3> positions = me->vert_positions();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
float total_area = 0.0f;
for (const MPoly &poly : polys) {
total_area += blender::bke::mesh::poly_area_calc(positions,
loops.slice(poly.loopstart, poly.totloop));
total_area += blender::bke::mesh::poly_area_calc(
positions, corner_verts.slice(poly.loopstart, poly.totloop));
}
return total_area;
}
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MLoop *poly_loops,
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const int *poly_verts,
const int poly_size,
const float (*positions)[3],
float r_cent[3])
@@ -139,11 +138,11 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MLoop *poly_l
zero_v3(r_cent);
v_pivot = positions[poly_loops[0].v];
v_step1 = positions[poly_loops[1].v];
v_pivot = positions[poly_verts[0]];
v_step1 = positions[poly_verts[1]];
for (int i = 2; i < poly_size; i++) {
const float *v_step2 = positions[poly_loops[i].v];
const float *v_step2 = positions[poly_verts[i]];
/* Calculate the 6x volume of the tetrahedron formed by the 3 vertices
* of the triangle and the origin as the fourth vertex */
@@ -174,7 +173,7 @@ namespace blender::bke::mesh {
* very low quality as the value moves away from 0.0, see: #65986.
*/
static float mesh_calc_poly_volume_centroid_with_reference_center(const Span<float3> positions,
const Span<MLoop> poly_loops,
const Span<int> poly_verts,
const float3 &reference_center,
float r_cent[3])
{
@@ -182,11 +181,11 @@ static float mesh_calc_poly_volume_centroid_with_reference_center(const Span<flo
float v_pivot[3], v_step1[3];
float total_volume = 0.0f;
zero_v3(r_cent);
sub_v3_v3v3(v_pivot, positions[poly_loops[0].v], reference_center);
sub_v3_v3v3(v_step1, positions[poly_loops[1].v], reference_center);
for (int i = 2; i < poly_loops.size(); i++) {
sub_v3_v3v3(v_pivot, positions[poly_verts[0]], reference_center);
sub_v3_v3v3(v_step1, positions[poly_verts[1]], reference_center);
for (int i = 2; i < poly_verts.size(); i++) {
float v_step2[3];
sub_v3_v3v3(v_step2, positions[poly_loops[i].v], reference_center);
sub_v3_v3v3(v_step2, positions[poly_verts[i]], reference_center);
const float tetra_volume = volume_tri_tetrahedron_signed_v3_6x(v_pivot, v_step1, v_step2);
total_volume += tetra_volume;
for (uint j = 0; j < 3; j++) {
@@ -204,21 +203,21 @@ static float mesh_calc_poly_volume_centroid_with_reference_center(const Span<flo
* that it doesn't depend on solid geometry, instead it weights the surface by volume.
*/
static float poly_area_centroid_calc(const Span<float3> positions,
const Span<MLoop> poly_loops,
const Span<int> poly_verts,
float r_cent[3])
{
float total_area = 0.0f;
float v1[3], v2[3], v3[3], tri_cent[3];
const float3 normal = blender::bke::mesh::poly_normal_calc(positions, poly_loops);
const float3 normal = blender::bke::mesh::poly_normal_calc(positions, poly_verts);
copy_v3_v3(v1, positions[poly_loops[0].v]);
copy_v3_v3(v2, positions[poly_loops[1].v]);
copy_v3_v3(v1, positions[poly_verts[0]]);
copy_v3_v3(v2, positions[poly_verts[1]]);
zero_v3(r_cent);
for (int i = 2; i < poly_loops.size(); i++) {
copy_v3_v3(v3, positions[poly_loops[i].v]);
for (int i = 2; i < poly_verts.size(); i++) {
copy_v3_v3(v3, positions[poly_verts[i]]);
float tri_area = area_tri_signed_v3(v1, v2, v3, normal);
total_area += tri_area;
@@ -235,22 +234,21 @@ static float poly_area_centroid_calc(const Span<float3> positions,
}
void poly_angles_calc(const Span<float3> vert_positions,
const Span<MLoop> poly_loops,
const Span<int> poly_verts,
MutableSpan<float> angles)
{
float nor_prev[3];
float nor_next[3];
int i_this = poly_loops.size() - 1;
int i_this = poly_verts.size() - 1;
int i_next = 0;
sub_v3_v3v3(
nor_prev, vert_positions[poly_loops[i_this - 1].v], vert_positions[poly_loops[i_this].v]);
nor_prev, vert_positions[poly_verts[i_this - 1]], vert_positions[poly_verts[i_this]]);
normalize_v3(nor_prev);
while (i_next < poly_loops.size()) {
sub_v3_v3v3(
nor_next, vert_positions[poly_loops[i_this].v], vert_positions[poly_loops[i_next].v]);
while (i_next < poly_verts.size()) {
sub_v3_v3v3(nor_next, vert_positions[poly_verts[i_this]], vert_positions[poly_verts[i_next]]);
normalize_v3(nor_next);
angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next);
@@ -288,12 +286,12 @@ bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3])
int tot = 0;
const Span<float3> positions = me->vert_positions();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
zero_v3(r_cent);
for (const MPoly &poly : polys) {
int loopend = poly.loopstart + poly.totloop;
for (int j = poly.loopstart; j < loopend; j++) {
add_v3_v3(r_cent, positions[loops[j].v]);
add_v3_v3(r_cent, positions[corner_verts[j]]);
}
tot += poly.totloop;
}
@@ -323,14 +321,14 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
float poly_cent[3];
const Span<float3> positions = me->vert_positions();
const blender::Span<MPoly> polys = me->polys();
const blender::Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
zero_v3(r_cent);
/* calculate a weighted average of polygon centroids */
for (const int i : polys.index_range()) {
poly_area = blender::bke::mesh::poly_area_centroid_calc(
positions, loops.slice(polys[i].loopstart, polys[i].totloop), poly_cent);
positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), poly_cent);
madd_v3_v3fl(r_cent, poly_cent, poly_area);
total_area += poly_area;
@@ -355,7 +353,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
float poly_cent[3];
const Span<float3> positions = me->vert_positions();
const blender::Span<MPoly> polys = me->polys();
const blender::Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
/* Use an initial center to avoid numeric instability of geometry far away from the center. */
float init_cent[3];
@@ -366,7 +364,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
/* calculate a weighted average of polyhedron centroids */
for (const int i : polys.index_range()) {
poly_volume = blender::bke::mesh::mesh_calc_poly_volume_centroid_with_reference_center(
positions, loops.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent);
positions, corner_verts.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent);
/* poly_cent is already volume-weighted, so no need to multiply by the volume */
add_v3_v3(r_cent, poly_cent);
@@ -399,7 +397,7 @@ static bool mesh_calc_center_centroid_ex(const float (*positions)[3],
int /*mverts_num*/,
const MLoopTri *looptri,
int looptri_num,
const MLoop *mloop,
const int *corner_verts,
float r_center[3])
{
@@ -413,9 +411,9 @@ static bool mesh_calc_center_centroid_ex(const float (*positions)[3],
const MLoopTri *lt;
int i;
for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
const float *v1 = positions[mloop[lt->tri[0]].v];
const float *v2 = positions[mloop[lt->tri[1]].v];
const float *v3 = positions[mloop[lt->tri[2]].v];
const float *v1 = positions[corner_verts[lt->tri[0]]];
const float *v2 = positions[corner_verts[lt->tri[1]]];
const float *v3 = positions[corner_verts[lt->tri[2]]];
float area;
area = area_tri_v3(v1, v2, v3);
@@ -437,7 +435,7 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
const int mverts_num,
const MLoopTri *looptri,
const int looptri_num,
const MLoop *mloop,
const int *corner_verts,
float *r_volume,
float r_center[3])
{
@@ -458,16 +456,16 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
}
if (!mesh_calc_center_centroid_ex(
vert_positions, mverts_num, looptri, looptri_num, mloop, center)) {
vert_positions, mverts_num, looptri, looptri_num, corner_verts, center)) {
return;
}
totvol = 0.0f;
for (i = 0, lt = looptri; i < looptri_num; i++, lt++) {
const float *v1 = vert_positions[mloop[lt->tri[0]].v];
const float *v2 = vert_positions[mloop[lt->tri[1]].v];
const float *v3 = vert_positions[mloop[lt->tri[2]].v];
const float *v1 = vert_positions[corner_verts[lt->tri[0]]];
const float *v2 = vert_positions[corner_verts[lt->tri[1]]];
const float *v3 = vert_positions[corner_verts[lt->tri[2]]];
float vol;
vol = volume_tetrahedron_signed_v3(center, v1, v2, v3);
@@ -538,7 +536,8 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
}
void BKE_mesh_polygon_flip_ex(const MPoly *poly,
MLoop *mloop,
int *corner_verts,
int *corner_edges,
CustomData *ldata,
float (*lnors)[3],
MDisps *mdisp,
@@ -546,7 +545,10 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly,
{
int loopstart = poly->loopstart;
int loopend = loopstart + poly->totloop - 1;
const bool loops_in_ldata = (CustomData_get_layer(ldata, CD_MLOOP) == mloop);
const bool corner_verts_in_data = (CustomData_get_layer_named(
ldata, CD_PROP_INT32, ".corner_vert") == corner_verts);
const bool corner_edges_in_data = (CustomData_get_layer_named(
ldata, CD_PROP_INT32, ".corner_edge") == corner_edges);
if (mdisp) {
for (int i = loopstart; i <= loopend; i++) {
@@ -559,15 +561,18 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly,
/* We also have to update loops edge
* (they will get their original 'other edge', that is,
* the original edge of their original previous loop)... */
uint prev_edge_index = mloop[loopstart].e;
mloop[loopstart].e = mloop[loopend].e;
int prev_edge_index = corner_edges[loopstart];
corner_edges[loopstart] = corner_edges[loopend];
for (loopstart++; loopend > loopstart; loopstart++, loopend--) {
mloop[loopend].e = mloop[loopend - 1].e;
std::swap(mloop[loopstart].e, prev_edge_index);
corner_edges[loopend] = corner_edges[loopend - 1];
std::swap(corner_edges[loopstart], prev_edge_index);
if (!loops_in_ldata) {
std::swap(mloop[loopstart], mloop[loopend]);
if (!corner_verts_in_data) {
std::swap(corner_verts[loopstart], corner_verts[loopend]);
}
if (!corner_edges_in_data) {
std::swap(corner_edges[loopstart], corner_edges[loopend]);
}
if (lnors) {
swap_v3_v3(lnors[loopstart], lnors[loopend]);
@@ -576,21 +581,23 @@ void BKE_mesh_polygon_flip_ex(const MPoly *poly,
}
/* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */
if (loopstart == loopend) {
mloop[loopstart].e = prev_edge_index;
corner_edges[loopstart] = prev_edge_index;
}
}
void BKE_mesh_polygon_flip(const MPoly *poly, MLoop *mloop, CustomData *ldata, const int totloop)
void BKE_mesh_polygon_flip(
const MPoly *poly, int *corner_verts, int *corner_edges, CustomData *ldata, const int totloop)
{
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totloop);
BKE_mesh_polygon_flip_ex(poly, mloop, ldata, nullptr, mdisp, true);
BKE_mesh_polygon_flip_ex(poly, corner_verts, corner_edges, ldata, nullptr, mdisp, true);
}
void BKE_mesh_polys_flip(const MPoly *polys, MLoop *mloop, CustomData *ldata, int totpoly)
void BKE_mesh_polys_flip(
const MPoly *polys, int *corner_verts, int *corner_edges, CustomData *ldata, int totpoly)
{
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totpoly);
for (const int i : blender::IndexRange(totpoly)) {
BKE_mesh_polygon_flip_ex(&polys[i], mloop, ldata, nullptr, mdisp, true);
BKE_mesh_polygon_flip_ex(&polys[i], corner_verts, corner_edges, ldata, nullptr, mdisp, true);
}
}
@@ -614,7 +621,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
const VArraySpan<bool> hide_vert_span{hide_vert};
const Span<MEdge> edges = me->edges();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
/* Hide edges when either of their vertices are hidden. */
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
@@ -630,9 +637,9 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
".hide_poly", ATTR_DOMAIN_FACE);
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
hide_poly.span[i] = std::any_of(poly_loops.begin(), poly_loops.end(), [&](const MLoop &loop) {
return hide_vert_span[loop.v];
const Span<int> poly_verts = corner_verts.slice(poly.loopstart, poly.totloop);
hide_poly.span[i] = std::any_of(poly_verts.begin(), poly_verts.end(), [&](const int vert) {
return hide_vert_span[vert];
});
}
hide_poly.finish();
@@ -653,7 +660,8 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
}
const VArraySpan<bool> hide_poly_span{hide_poly};
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
const Span<int> corner_edges = me->corner_edges();
SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
@@ -663,9 +671,9 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
for (const int i : polys.index_range()) {
if (hide_poly_span[i]) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
hide_vert.span[loop.v] = true;
hide_edge.span[loop.e] = true;
for (const int corner : IndexRange(poly.loopstart, poly.totloop)) {
hide_vert.span[corner_verts[corner]] = true;
hide_edge.span[corner_edges[corner]] = true;
}
}
}
@@ -673,9 +681,9 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
for (const int i : polys.index_range()) {
if (!hide_poly_span[i]) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
hide_vert.span[loop.v] = false;
hide_edge.span[loop.e] = false;
for (const int corner : IndexRange(poly.loopstart, poly.totloop)) {
hide_vert.span[corner_verts[corner]] = false;
hide_edge.span[corner_edges[corner]] = false;
}
}
}
@@ -713,7 +721,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
static void mesh_flush_select_from_verts(const Span<MEdge> edges,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const VArray<bool> &hide_edge,
const VArray<bool> &hide_poly,
const VArray<bool> &select_vert,
@@ -732,10 +740,9 @@ static void mesh_flush_select_from_verts(const Span<MEdge> edges,
for (const int i : polys.index_range()) {
if (!hide_poly[i]) {
const MPoly &poly = polys[i];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
select_poly[i] = std::all_of(poly_loops.begin(), poly_loops.end(), [&](const MLoop &loop) {
return select_vert[loop.v];
});
const Span<int> poly_verts = corner_verts.slice(poly.loopstart, poly.totloop);
select_poly[i] = std::all_of(
poly_verts.begin(), poly_verts.end(), [&](const int vert) { return select_vert[vert]; });
}
}
}
@@ -758,7 +765,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
mesh_flush_select_from_verts(
me->edges(),
me->polys(),
me->loops(),
me->corner_verts(),
attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
select_vert,
@@ -776,7 +783,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
void BKE_mesh_calc_relative_deform(const MPoly *polys,
const int totpoly,
const MLoop *mloop,
const int *corner_verts,
const int totvert,
const float (*vert_cos_src)[3],
@@ -791,12 +798,12 @@ void BKE_mesh_calc_relative_deform(const MPoly *polys,
for (const int i : blender::IndexRange(totpoly)) {
const MPoly &poly = polys[i];
const MLoop *loopstart = mloop + poly.loopstart;
const int *poly_verts = &corner_verts[poly.loopstart];
for (int j = 0; j < poly.totloop; j++) {
uint v_prev = loopstart[(poly.totloop + (j - 1)) % poly.totloop].v;
uint v_curr = loopstart[j].v;
uint v_next = loopstart[(j + 1) % poly.totloop].v;
const int v_prev = poly_verts[(poly.totloop + (j - 1)) % poly.totloop];
const int v_curr = poly_verts[j];
const int v_next = poly_verts[(j + 1) % poly.totloop];
float tvec[3];
+12 -9
View File
@@ -200,11 +200,12 @@ class MeshFairingContext : public FairingContext {
MutableSpan<float3> positions = mesh->vert_positions_for_write();
edges_ = mesh->edges();
polys = mesh->polys();
mloop_ = mesh->loops();
corner_verts_ = mesh->corner_verts();
corner_edges_ = mesh->corner_edges();
BKE_mesh_vert_loop_map_create(&vlmap_,
&vlmap_mem_,
polys.data(),
mloop_.data(),
corner_verts_.data(),
mesh->totvert,
mesh->totpoly,
mesh->totloop);
@@ -222,7 +223,8 @@ class MeshFairingContext : public FairingContext {
}
}
loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys, mloop_.size());
loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys,
corner_verts_.size());
}
~MeshFairingContext() override
@@ -235,16 +237,16 @@ class MeshFairingContext : public FairingContext {
float r_adj_next[3],
float r_adj_prev[3]) override
{
const int vert = mloop_[loop].v;
const int vert = corner_verts_[loop];
const MPoly &poly = polys[loop_to_poly_map_[loop]];
const int corner = poly_find_loop_from_vert(&poly, &mloop_[poly.loopstart], vert);
copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, &poly, corner)->v]);
copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, &poly, corner)->v]);
const int corner = poly_find_loop_from_vert(&poly, &corner_verts_[poly.loopstart], vert);
copy_v3_v3(r_adj_next, co_[corner_verts_[ME_POLY_LOOP_NEXT(&poly, corner)]]);
copy_v3_v3(r_adj_prev, co_[corner_verts_[ME_POLY_LOOP_PREV(&poly, corner)]]);
}
int other_vertex_index_from_loop(const int loop, const uint v) override
{
const MEdge *edge = &edges_[mloop_[loop].e];
const MEdge *edge = &edges_[corner_edges_[loop]];
if (edge->v1 == v) {
return edge->v2;
}
@@ -253,7 +255,8 @@ class MeshFairingContext : public FairingContext {
protected:
Mesh *mesh_;
Span<MLoop> mloop_;
Span<int> corner_verts_;
Span<int> corner_edges_;
Span<MPoly> polys;
Span<MEdge> edges_;
Array<int> loop_to_poly_map_;
@@ -194,7 +194,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const int *v_index = static_cast<const int *>(
CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX));
const int *f_index = static_cast<const int *>(
@@ -202,26 +202,24 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
if (v_index || f_index) {
for (const int poly_i : polys.index_range()) {
for (const int loop_i :
blender::IndexRange(polys[poly_i].loopstart, polys[poly_i].totloop)) {
const int v_idx = v_index ? v_index[loops[loop_i].v] : loops[loop_i].v;
for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) {
const int v_idx = v_index ? v_index[vert] : vert;
const int f_idx = f_index ? f_index[poly_i] : poly_i;
const float *no = loop_normals ? *loop_normals++ : nullptr;
if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
continue;
}
func(userData, v_idx, f_idx, positions[loops[loop_i].v], no);
func(userData, v_idx, f_idx, positions[vert], no);
}
}
}
else {
for (const int poly_i : polys.index_range()) {
for (const int loop_i :
blender::IndexRange(polys[poly_i].loopstart, polys[poly_i].totloop)) {
const int v_idx = loops[loop_i].v;
for (const int vert : corner_verts.slice(polys[poly_i].loopstart, polys[poly_i].totloop)) {
const int v_idx = vert;
const int f_idx = poly_i;
const float *no = loop_normals ? *loop_normals++ : nullptr;
func(userData, v_idx, f_idx, positions[loops[loop_i].v], no);
func(userData, v_idx, f_idx, positions[vert], no);
}
}
}
@@ -271,7 +269,7 @@ void BKE_mesh_foreach_mapped_face_center(
else {
const blender::Span<float3> positions = mesh->vert_positions();
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
if (index) {
@@ -280,10 +278,10 @@ void BKE_mesh_foreach_mapped_face_center(
if (orig == ORIGINDEX_NONE) {
continue;
}
const Span<MLoop> poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop);
const float3 center = bke::mesh::poly_center_calc(positions, poly_loops);
const Span<int> poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop);
const float3 center = bke::mesh::poly_center_calc(positions, poly_verts);
if (flag & MESH_FOREACH_USE_NORMAL) {
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops);
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts);
func(userData, orig, center, normal);
}
else {
@@ -293,10 +291,10 @@ void BKE_mesh_foreach_mapped_face_center(
}
else {
for (const int i : polys.index_range()) {
const Span<MLoop> poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop);
const float3 center = bke::mesh::poly_center_calc(positions, poly_loops);
const Span<int> poly_verts = corner_verts.slice(polys[i].loopstart, polys[i].totloop);
const float3 center = bke::mesh::poly_center_calc(positions, poly_verts);
if (flag & MESH_FOREACH_USE_NORMAL) {
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops);
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts);
func(userData, i, center, normal);
}
else {
@@ -315,7 +313,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
{
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
blender::Span<blender::float3> vert_normals;
if (flag & MESH_FOREACH_USE_NORMAL) {
vert_normals = mesh->vert_normals();
@@ -329,24 +327,24 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
if (orig == ORIGINDEX_NONE) {
continue;
}
for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) {
if (facedot_tags[loop.v]) {
for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) {
if (facedot_tags[vert]) {
func(userData,
orig,
positions[loop.v],
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr);
positions[vert],
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[vert].x : nullptr);
}
}
}
}
else {
for (const int i : polys.index_range()) {
for (const MLoop &loop : loops.slice(polys[i].loopstart, polys[i].totloop)) {
if (facedot_tags[loop.v]) {
for (const int vert : corner_verts.slice(polys[i].loopstart, polys[i].totloop)) {
if (facedot_tags[vert]) {
func(userData,
i,
positions[loop.v],
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[loop.v].x : nullptr);
positions[vert],
(flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[vert].x : nullptr);
}
}
}
@@ -209,18 +209,18 @@ void BKE_mesh_calc_edges_legacy(Mesh *me)
const Span<MVert> verts(static_cast<const MVert *>(CustomData_get_layer(&me->vdata, CD_MVERT)),
me->totvert);
const Span<MPoly> polys = me->polys();
MutableSpan<MLoop> loops = me->loops_for_write();
mesh_calc_edges_mdata(verts.data(),
(MFace *)CustomData_get_layer(&me->fdata, CD_MFACE),
loops.data(),
polys.data(),
verts.size(),
me->totface,
loops.size(),
polys.size(),
&edges,
&totedge);
mesh_calc_edges_mdata(
verts.data(),
(MFace *)CustomData_get_layer(&me->fdata, CD_MFACE),
static_cast<MLoop *>(CustomData_get_layer_for_write(&me->ldata, CD_MLOOP, me->totloop)),
polys.data(),
verts.size(),
me->totface,
me->totloop,
polys.size(),
&edges,
&totedge);
if (totedge == 0) {
/* flag that mesh has edges */
@@ -705,6 +705,7 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
&mesh->totpoly);
mesh_ensure_tessellation_customdata(mesh);
BKE_mesh_legacy_convert_loops_to_corners(mesh);
}
/**
@@ -964,7 +965,6 @@ static int mesh_tessface_calc(Mesh &mesh,
const int looptri_num = poly_to_tri_count(totpoly, totloop);
const MPoly *poly, *mpoly;
const MLoop *ml, *mloop;
MFace *mface, *mf;
MemArena *arena = nullptr;
int *mface_to_poly_map;
@@ -973,7 +973,7 @@ static int mesh_tessface_calc(Mesh &mesh,
uint j;
mpoly = (const MPoly *)CustomData_get_layer(pdata, CD_MPOLY);
mloop = (const MLoop *)CustomData_get_layer(ldata, CD_MLOOP);
const Span<int> corner_verts = mesh.corner_verts();
const int *material_indices = static_cast<const int *>(
CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index"));
const bool *sharp_faces = static_cast<const bool *>(
@@ -1008,9 +1008,9 @@ static int mesh_tessface_calc(Mesh &mesh,
l1 = mp_loopstart + i1; \
l2 = mp_loopstart + i2; \
l3 = mp_loopstart + i3; \
mf->v1 = mloop[l1].v; \
mf->v2 = mloop[l2].v; \
mf->v3 = mloop[l3].v; \
mf->v1 = corner_verts[l1]; \
mf->v2 = corner_verts[l2]; \
mf->v3 = corner_verts[l3]; \
mf->v4 = 0; \
lidx[0] = l1; \
lidx[1] = l2; \
@@ -1031,10 +1031,10 @@ static int mesh_tessface_calc(Mesh &mesh,
l2 = mp_loopstart + 1; /* EXCEPTION */ \
l3 = mp_loopstart + 2; /* EXCEPTION */ \
l4 = mp_loopstart + 3; /* EXCEPTION */ \
mf->v1 = mloop[l1].v; \
mf->v2 = mloop[l2].v; \
mf->v3 = mloop[l3].v; \
mf->v4 = mloop[l4].v; \
mf->v1 = corner_verts[l1]; \
mf->v2 = corner_verts[l2]; \
mf->v3 = corner_verts[l3]; \
mf->v4 = corner_verts[l4]; \
lidx[0] = l1; \
lidx[1] = l2; \
lidx[2] = l3; \
@@ -1081,10 +1081,10 @@ static int mesh_tessface_calc(Mesh &mesh,
zero_v3(normal);
/* Calculate the normal, flipped: to get a positive 2D cross product. */
ml = mloop + mp_loopstart;
co_prev = positions[ml[mp_totloop - 1].v];
for (j = 0; j < mp_totloop; j++, ml++) {
co_curr = positions[ml->v];
co_prev = positions[corner_verts[mp_loopstart + mp_totloop - 1]];
for (j = 0; j < mp_totloop; j++) {
const int vert = corner_verts[mp_loopstart + j];
co_curr = positions[vert];
add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
co_prev = co_curr;
}
@@ -1095,9 +1095,9 @@ static int mesh_tessface_calc(Mesh &mesh,
/* Project verts to 2D. */
axis_dominant_v3_to_m3_negate(axis_mat, normal);
ml = mloop + mp_loopstart;
for (j = 0; j < mp_totloop; j++, ml++) {
mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]);
for (j = 0; j < mp_totloop; j++) {
const int vert = corner_verts[mp_loopstart + j];
mul_v2_m3v3(projverts[j], axis_mat, positions[vert]);
}
BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena);
@@ -1115,9 +1115,9 @@ static int mesh_tessface_calc(Mesh &mesh,
l2 = mp_loopstart + tri[1];
l3 = mp_loopstart + tri[2];
mf->v1 = mloop[l1].v;
mf->v2 = mloop[l2].v;
mf->v3 = mloop[l3].v;
mf->v1 = corner_verts[l1];
mf->v2 = corner_verts[l2];
mf->v3 = corner_verts[l3];
mf->v4 = 0;
lidx[0] = l1;
@@ -2138,3 +2138,61 @@ void BKE_mesh_legacy_attribute_strings_to_flags(Mesh *mesh)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Face Corner Conversion
* \{ */
MLoop *BKE_mesh_legacy_convert_corners_to_loops(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,
blender::Vector<CustomDataLayer, 16> &loop_layers_to_write)
{
using namespace blender;
const Span<int> corner_verts = mesh->corner_verts();
const Span<int> corner_edges = mesh->corner_edges();
CustomDataLayer mloop_layer{};
mloop_layer.type = CD_MLOOP;
MutableSpan<MLoop> loops = temp_arrays_for_convert.construct<Array<MLoop>>(mesh->totloop);
mloop_layer.data = loops.data();
threading::parallel_for(loops.index_range(), 2048, [&](IndexRange range) {
for (const int i : range) {
loops[i].v = corner_verts[i];
loops[i].e = corner_edges[i];
}
});
loop_layers_to_write.append(mloop_layer);
return loops.data();
}
void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh)
{
using namespace blender;
if (CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_vert") &&
CustomData_get_layer_named(&mesh->ldata, CD_PROP_INT32, ".corner_edge")) {
return;
}
const Span<MLoop> loops(static_cast<const MLoop *>(CustomData_get_layer(&mesh->ldata, CD_MLOOP)),
mesh->totloop);
MutableSpan<int> corner_verts(
static_cast<int *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_vert")),
mesh->totloop);
MutableSpan<int> corner_edges(
static_cast<int *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh->totloop, ".corner_edge")),
mesh->totloop);
threading::parallel_for(loops.index_range(), 2048, [&](IndexRange range) {
for (const int i : range) {
corner_verts[i] = loops[i].v;
corner_edges[i] = loops[i].e;
}
});
CustomData_free_layers(&mesh->ldata, CD_MLOOP, mesh->totloop);
}
/** \} */
@@ -33,7 +33,7 @@
UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys,
const bool *hide_poly,
const bool *select_poly,
const MLoop *mloop,
const int *corner_verts,
const float (*mloopuv)[2],
uint totpoly,
uint totvert,
@@ -92,8 +92,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *polys,
buf->loop_of_poly_index = ushort(i);
buf->poly_index = uint(a);
buf->separate = false;
buf->next = vmap->vert[mloop[poly.loopstart + i].v];
vmap->vert[mloop[poly.loopstart + i].v] = buf;
buf->next = vmap->vert[corner_verts[poly.loopstart + i]];
vmap->vert[corner_verts[poly.loopstart + i]] = buf;
if (use_winding) {
copy_v2_v2(tf_uv[i], mloopuv[poly.loopstart + i]);
@@ -192,7 +192,7 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MPoly *polys,
const MLoop *mloop,
const int *corner_verts,
int totvert,
int totpoly,
int totloop,
@@ -210,7 +210,7 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
const MPoly &poly = polys[i];
for (j = 0; j < poly.totloop; j++) {
map[mloop[poly.loopstart + j].v].count++;
map[corner_verts[poly.loopstart + j]].count++;
}
}
@@ -228,7 +228,7 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
const MPoly &poly = polys[i];
for (j = 0; j < poly.totloop; j++) {
uint v = mloop[poly.loopstart + j].v;
const int v = corner_verts[poly.loopstart + j];
map[v].indices[map[v].count] = do_loops ? poly.loopstart + j : i;
map[v].count++;
@@ -242,23 +242,25 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
int **r_mem,
const MPoly *polys,
const MLoop *mloop,
const int *corner_verts,
int totvert,
int totpoly,
int totloop)
{
mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, mloop, totvert, totpoly, totloop, false);
mesh_vert_poly_or_loop_map_create(
r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, false);
}
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
int **r_mem,
const MPoly *polys,
const MLoop *mloop,
const int *corner_verts,
int totvert,
int totpoly,
int totloop)
{
mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, mloop, totvert, totpoly, totloop, true);
mesh_vert_poly_or_loop_map_create(
r_map, r_mem, polys, corner_verts, totvert, totpoly, totloop, true);
}
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
@@ -266,7 +268,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
const int totvert,
const MLoopTri *mlooptri,
const int totlooptri,
const MLoop *mloop,
const int *corner_verts,
const int /*totloop*/)
{
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totvert), __func__);
@@ -278,7 +280,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
/* count face users */
for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
for (int j = 3; j--;) {
map[mloop[mlt->tri[j]].v].count++;
map[corner_verts[mlt->tri[j]]].count++;
}
}
@@ -295,7 +297,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
/* assign looptri-edge users */
for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
for (int j = 3; j--;) {
MeshElemMap *map_ele = &map[mloop[mlt->tri[j]].v];
MeshElemMap *map_ele = &map[corner_verts[mlt->tri[j]]];
map_ele->indices[map_ele->count++] = i;
}
}
@@ -387,21 +389,17 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
const int totedge,
const MPoly *polys,
const int totpoly,
const MLoop *mloop,
const int *corner_edges,
const int totloop)
{
using namespace blender;
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__);
int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop) * 2, __func__));
int *index_step;
/* count face users */
for (const int64_t i : blender::IndexRange(totpoly)) {
const MPoly &poly = polys[i];
const MLoop *ml;
int j = poly.totloop;
for (ml = &mloop[poly.loopstart]; j--; ml++) {
map[ml->e].count += 2;
}
for (const int64_t i : IndexRange(totloop)) {
map[corner_edges[i]].count += 2;
}
/* create offsets */
@@ -417,12 +415,10 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
/* assign loop-edge users */
for (const int64_t i : blender::IndexRange(totpoly)) {
const MPoly &poly = polys[i];
const MLoop *ml;
MeshElemMap *map_ele;
const int max_loop = poly.loopstart + poly.totloop;
int j = poly.loopstart;
for (ml = &mloop[j]; j < max_loop; j++, ml++) {
map_ele = &map[ml->e];
for (int j = poly.loopstart; j < max_loop; j++) {
map_ele = &map[corner_edges[j]];
map_ele->indices[map_ele->count++] = j;
map_ele->indices[map_ele->count++] = j + 1;
}
@@ -439,7 +435,7 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
const int totedge,
const MPoly *polys,
const int totpoly,
const MLoop *mloop,
const int *corner_edges,
const int totloop)
{
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__);
@@ -447,13 +443,8 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
int *index_step;
/* count face users */
for (const int64_t i : blender::IndexRange(totpoly)) {
const MPoly &poly = polys[i];
const MLoop *ml;
int j = poly.totloop;
for (ml = &mloop[poly.loopstart]; j--; ml++) {
map[ml->e].count++;
}
for (const int64_t i : blender::IndexRange(totloop)) {
map[corner_edges[i]].count++;
}
/* create offsets */
@@ -469,10 +460,9 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
/* assign poly-edge users */
for (const int64_t i : blender::IndexRange(totpoly)) {
const MPoly &poly = polys[i];
const MLoop *ml;
int j = poly.totloop;
for (ml = &mloop[poly.loopstart]; j--; ml++) {
MeshElemMap *map_ele = &map[ml->e];
for (int j = 0; j < poly.totloop; j++) {
const int edge_i = corner_edges[poly.loopstart + j];
MeshElemMap *map_ele = &map[edge_i];
map_ele->indices[map_ele->count++] = int(i);
}
}
@@ -576,56 +566,58 @@ Array<Vector<int>> build_vert_to_edge_map(const Span<MEdge> edges, const int ver
}
Array<Vector<int>> build_vert_to_poly_map(const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
int verts_num)
{
Array<Vector<int>> map(verts_num);
for (const int64_t i : polys.index_range()) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
map[loop.v].append(int(i));
for (const int64_t vert_i : corner_verts.slice(poly.loopstart, poly.totloop)) {
map[int(vert_i)].append(int(i));
}
}
return map;
}
Array<Vector<int>> build_vert_to_loop_map(const Span<MLoop> loops, const int verts_num)
Array<Vector<int>> build_vert_to_loop_map(const Span<int> corner_verts, const int verts_num)
{
Array<Vector<int>> map(verts_num);
for (const int64_t i : loops.index_range()) {
map[loops[i].v].append(int(i));
for (const int64_t i : corner_verts.index_range()) {
map[corner_verts[i]].append(int(i));
}
return map;
}
Array<Vector<int>> build_edge_to_loop_map(const Span<MLoop> loops, const int edges_num)
Array<Vector<int>> build_edge_to_loop_map(const Span<int> corner_edges, const int edges_num)
{
Array<Vector<int>> map(edges_num);
for (const int64_t i : loops.index_range()) {
map[loops[i].e].append(int(i));
for (const int64_t i : corner_edges.index_range()) {
map[corner_edges[i]].append(int(i));
}
return map;
}
Array<Vector<int, 2>> build_edge_to_poly_map(const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_edges,
const int edges_num)
{
Array<Vector<int, 2>> map(edges_num);
for (const int64_t i : polys.index_range()) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
map[loop.e].append(int(i));
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
map[edge].append(int(i));
}
}
return map;
}
Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, const int edges_num)
Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<int> corner_edges,
const int edges_num)
{
Vector<Vector<int>> map(edges_num);
for (const int64_t i : loops.index_range()) {
map[loops[i].e].append(int(i));
for (const int64_t i : corner_edges.index_range()) {
map[corner_edges[i]].append(int(i));
}
return map;
}
@@ -651,7 +643,7 @@ using MeshRemap_CheckIslandBoundary =
static void poly_edge_loop_islands_calc(const int totedge,
const blender::Span<MPoly> polys,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_edges,
MeshElemMap *edge_poly_map,
const bool use_bitflags,
MeshRemap_CheckIslandBoundary edge_boundary_check,
@@ -699,8 +691,8 @@ static void poly_edge_loop_islands_calc(const int totedge,
totedge,
polys.data(),
int(polys.size()),
loops.data(),
int(loops.size()));
corner_edges.data(),
int(corner_edges.size()));
}
poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__));
@@ -736,7 +728,7 @@ static void poly_edge_loop_islands_calc(const int totedge,
BLI_assert(poly_groups[poly] == poly_group_id);
for (const int64_t loop : blender::IndexRange(polys[poly].loopstart, polys[poly].totloop)) {
const int edge = int(loops[loop].e);
const int edge = corner_edges[loop];
/* loop over poly users */
const MeshElemMap &map_ele = edge_poly_map[edge];
const int *p = map_ele.indices;
@@ -842,7 +834,7 @@ static void poly_edge_loop_islands_calc(const int totedge,
int *BKE_mesh_calc_smoothgroups(const int totedge,
const MPoly *polys,
const int totpoly,
const MLoop *mloop,
const int *corner_edges,
const int totloop,
const bool *sharp_edges,
const bool *sharp_faces,
@@ -873,7 +865,7 @@ int *BKE_mesh_calc_smoothgroups(const int totedge,
poly_edge_loop_islands_calc(totedge,
{polys, totpoly},
{mloop, totloop},
{corner_edges, totloop},
nullptr,
use_bitflags,
poly_is_island_boundary_smooth,
@@ -1004,7 +996,8 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
const bool *uv_seams,
const MPoly *polys,
const int totpoly,
const MLoop *loops,
const int *corner_verts,
const int *corner_edges,
const int totloop,
const float (*luvs)[2],
MeshIslandStore *r_island_store)
@@ -1039,11 +1032,11 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
BKE_mesh_edge_poly_map_create(
&edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, loops, totloop);
&edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, corner_edges, totloop);
if (luvs) {
BKE_mesh_edge_loop_map_create(
&edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, loops, totloop);
&edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, corner_edges, totloop);
}
/* TODO: I'm not sure edge seam flag is enough to define UV islands?
@@ -1058,23 +1051,23 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
const int /*edge_user_count*/,
const MeshElemMap & /*edge_poly_map_elem*/) -> bool {
if (luvs) {
const MeshElemMap &edge_to_loops = edge_loop_map[loops[loop_index].e];
const MeshElemMap &edge_to_loops = edge_loop_map[corner_edges[loop_index]];
BLI_assert(edge_to_loops.count >= 2 && (edge_to_loops.count % 2) == 0);
const uint v1 = loops[edge_to_loops.indices[0]].v;
const uint v2 = loops[edge_to_loops.indices[1]].v;
const int v1 = corner_verts[edge_to_loops.indices[0]];
const int v2 = corner_verts[edge_to_loops.indices[1]];
const float *uvco_v1 = luvs[edge_to_loops.indices[0]];
const float *uvco_v2 = luvs[edge_to_loops.indices[1]];
for (int i = 2; i < edge_to_loops.count; i += 2) {
if (loops[edge_to_loops.indices[i]].v == v1) {
if (corner_verts[edge_to_loops.indices[i]] == v1) {
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i]]) ||
!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i + 1]])) {
return true;
}
}
else {
BLI_assert(loops[edge_to_loops.indices[i]].v == v2);
BLI_assert(corner_verts[edge_to_loops.indices[i]] == v2);
UNUSED_VARS_NDEBUG(v2);
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i]]) ||
!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i + 1]])) {
@@ -1091,7 +1084,7 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
poly_edge_loop_islands_calc(totedge,
{polys, totpoly},
{loops, totloop},
{corner_edges, totloop},
edge_poly_map,
false,
mesh_check_island_boundary_uv,
@@ -1138,13 +1131,13 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
const MPoly &poly = polys[p_idx];
poly_indices[num_pidx++] = p_idx;
for (l_idx = poly.loopstart, pl_idx = 0; pl_idx < poly.totloop; l_idx++, pl_idx++) {
const MLoop *ml = &loops[l_idx];
const int edge_i = corner_edges[l_idx];
loop_indices[num_lidx++] = l_idx;
if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) &&
(edge_border_count[ml->e] < 2)) {
edge_border_count[ml->e]++;
if (edge_border_count[ml->e] == 2) {
edge_innercut_indices[num_einnercuts++] = int(ml->e);
if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, edge_i) &&
(edge_border_count[edge_i] < 2)) {
edge_border_count[edge_i]++;
if (edge_border_count[edge_i] == 2) {
edge_innercut_indices[num_einnercuts++] = edge_i;
}
}
}
@@ -1189,13 +1182,21 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
const bool *uv_seams,
const MPoly *polys,
const int totpoly,
const MLoop *loops,
const int *corner_verts,
const int *corner_edges,
const int totloop,
MeshIslandStore *r_island_store)
{
UNUSED_VARS(vert_positions, totvert, edges);
return mesh_calc_islands_loop_poly_uv(
totedge, uv_seams, polys, totpoly, loops, totloop, nullptr, r_island_store);
return mesh_calc_islands_loop_poly_uv(totedge,
uv_seams,
polys,
totpoly,
corner_verts,
corner_edges,
totloop,
nullptr,
r_island_store);
}
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
@@ -1205,15 +1206,23 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
const bool *uv_seams,
MPoly *polys,
const int totpoly,
MLoop *loops,
const int *corner_verts,
const int *corner_edges,
const int totloop,
const float (*luvs)[2],
MeshIslandStore *r_island_store)
{
UNUSED_VARS(vert_positions, totvert, edges);
BLI_assert(luvs != nullptr);
return mesh_calc_islands_loop_poly_uv(
totedge, uv_seams, polys, totpoly, loops, totloop, luvs, r_island_store);
return mesh_calc_islands_loop_poly_uv(totedge,
uv_seams,
polys,
totpoly,
corner_verts,
corner_edges,
totloop,
luvs,
r_island_store);
}
/** \} */
@@ -117,7 +117,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me)
BKE_mesh_vert_loop_map_create(&vert_to_loop,
&vert_map_mem,
me->polys().data(),
me->loops().data(),
me->corner_verts().data(),
me->totvert,
me->totpoly,
me->totloop);
+14 -11
View File
@@ -288,7 +288,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
blender::MutableSpan<MEdge> result_edges = result->edges_for_write();
blender::MutableSpan<MPoly> result_polys = result->polys_for_write();
blender::MutableSpan<MLoop> result_loops = result->loops_for_write();
blender::MutableSpan<int> result_corner_verts = result->corner_verts_for_write();
blender::MutableSpan<int> result_corner_edges = result->corner_edges_for_write();
/* adjust mirrored edge vertex indices */
for (const int i : result_edges.index_range().drop_front(src_edges_num)) {
@@ -315,18 +316,20 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly[j], mirror_poly.last(j - 1), 1);
}
blender::MutableSpan<MLoop> mirror_loops = result_loops.slice(mirror_poly);
const int e = mirror_loops.first().e;
blender::MutableSpan<int> mirror_poly_edges = result_corner_edges.slice(mirror_poly);
const int e = mirror_poly_edges.first();
for (int j = 0; j < mirror_poly.size() - 1; j++) {
mirror_loops[j].e = mirror_loops[j + 1].e;
mirror_poly_edges[j] = mirror_poly_edges[j + 1];
}
mirror_loops.last().e = e;
mirror_poly_edges.last() = e;
}
/* adjust mirrored loop vertex and edge indices */
for (const int i : result_loops.index_range().drop_front(src_loops_num)) {
result_loops[i].v += src_verts_num;
result_loops[i].e += src_edges_num;
for (const int i : result_corner_verts.index_range().drop_front(src_loops_num)) {
result_corner_verts[i] += src_verts_num;
}
for (const int i : result_corner_edges.index_range().drop_front(src_loops_num)) {
result_corner_edges[i] += src_edges_num;
}
/* handle uvs,
@@ -373,7 +376,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* handle custom split normals */
if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) {
blender::Array<blender::float3> loop_normals(result_loops.size());
blender::Array<blender::float3> loop_normals(result_corner_verts.size());
CustomData *ldata = &result->ldata;
short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop));
@@ -394,7 +397,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
blender::bke::mesh::normals_calc_loop(result->vert_positions(),
result_edges,
result_polys,
result_loops,
result_corner_verts,
result_corner_edges,
{},
result->vert_normals(),
result->poly_normals(),
@@ -456,6 +460,5 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
if (mesh_bisect != nullptr) {
BKE_id_free(nullptr, mesh_bisect);
}
return result;
}
+147 -124
View File
@@ -149,14 +149,14 @@ namespace blender::bke::mesh {
* polygon See Graphics Gems for
* computing newell normal.
*/
static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<int> poly_verts)
{
float3 normal(0);
/* Newell's Method */
const float *v_prev = vert_positions[poly_loops.last().v];
for (const int i : poly_loops.index_range()) {
const float *v_curr = vert_positions[poly_loops[i].v];
const float *v_prev = vert_positions[poly_verts.last()];
for (const int i : poly_verts.index_range()) {
const float *v_curr = vert_positions[poly_verts[i]];
add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
v_prev = v_curr;
}
@@ -168,23 +168,23 @@ static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<MLo
return normal;
}
float3 poly_normal_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
float3 poly_normal_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
{
if (poly_loops.size() > 4) {
return normal_calc_ngon(vert_positions, poly_loops);
if (poly_verts.size() > 4) {
return normal_calc_ngon(vert_positions, poly_verts);
}
if (poly_loops.size() == 3) {
return math::normal_tri(vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v]);
if (poly_verts.size() == 3) {
return math::normal_tri(vert_positions[poly_verts[0]],
vert_positions[poly_verts[1]],
vert_positions[poly_verts[2]]);
}
if (poly_loops.size() == 4) {
if (poly_verts.size() == 4) {
float3 normal;
normal_quad_v3(normal,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v],
vert_positions[poly_loops[3].v]);
vert_positions[poly_verts[0]],
vert_positions[poly_verts[1]],
vert_positions[poly_verts[2]],
vert_positions[poly_verts[3]]);
return normal;
}
/* horrible, two sided face! */
@@ -193,7 +193,7 @@ float3 poly_normal_calc(const Span<float3> vert_positions, const Span<MLoop> pol
} // namespace blender::bke::mesh
void BKE_mesh_calc_poly_normal(const MLoop *poly_loops,
void BKE_mesh_calc_poly_normal(const int *poly_verts,
const int poly_size,
const float (*vert_positions)[3],
const int verts_num,
@@ -202,21 +202,22 @@ void BKE_mesh_calc_poly_normal(const MLoop *poly_loops,
copy_v3_v3(r_no,
blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions), verts_num},
{poly_loops, poly_size}));
{poly_verts, poly_size}));
}
namespace blender::bke::mesh {
void normals_calc_polys(const Span<float3> positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
MutableSpan<float3> poly_normals)
{
BLI_assert(polys.size() == poly_normals.size());
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
const MPoly &poly = polys[i];
poly_normals[i] = poly_normal_calc(positions, loops.slice(poly.loopstart, poly.totloop));
poly_normals[i] = poly_normal_calc(positions,
corner_verts.slice(poly.loopstart, poly.totloop));
}
});
}
@@ -232,7 +233,7 @@ void normals_calc_polys(const Span<float3> positions,
void normals_calc_poly_vert(const Span<float3> positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
MutableSpan<float3> poly_normals,
MutableSpan<float3> vert_normals)
{
@@ -247,7 +248,7 @@ void normals_calc_poly_vert(const Span<float3> positions,
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
const Span<int> poly_verts = corner_verts.slice(poly.loopstart, poly.totloop);
float3 &pnor = poly_normals[poly_i];
@@ -258,9 +259,9 @@ void normals_calc_poly_vert(const Span<float3> positions,
{
zero_v3(pnor);
/* Newell's Method */
const float *v_curr = positions[poly_loops[i_end].v];
const float *v_curr = positions[poly_verts[i_end]];
for (int i_next = 0; i_next <= i_end; i_next++) {
const float *v_next = positions[poly_loops[i_next].v];
const float *v_next = positions[poly_verts[i_next]];
add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
v_curr = v_next;
}
@@ -273,13 +274,13 @@ void normals_calc_poly_vert(const Span<float3> positions,
/* Inline version of #accumulate_vertex_normals_poly_v3. */
{
float edvec_prev[3], edvec_next[3], edvec_end[3];
const float *v_curr = positions[poly_loops[i_end].v];
sub_v3_v3v3(edvec_prev, positions[poly_loops[i_end - 1].v], v_curr);
const float *v_curr = positions[poly_verts[i_end]];
sub_v3_v3v3(edvec_prev, positions[poly_verts[i_end - 1]], v_curr);
normalize_v3(edvec_prev);
copy_v3_v3(edvec_end, edvec_prev);
for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) {
const float *v_next = positions[poly_loops[i_next].v];
const float *v_next = positions[poly_verts[i_next]];
/* Skip an extra normalization by reusing the first calculated edge. */
if (i_next != i_end) {
@@ -294,7 +295,7 @@ void normals_calc_poly_vert(const Span<float3> positions,
const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next));
const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac};
float *vnor = vert_normals[poly_loops[i_curr].v];
float *vnor = vert_normals[poly_verts[i_curr]];
add_v3_v3_atomic(vnor, vnor_add);
v_curr = v_next;
copy_v3_v3(edvec_prev, edvec_next);
@@ -344,12 +345,12 @@ blender::Span<blender::float3> Mesh::vert_normals() const
blender::threading::isolate_task([&]() {
const Span<float3> positions = this->vert_positions();
const Span<MPoly> polys = this->polys();
const Span<MLoop> loops = this->loops();
const Span<int> corner_verts = this->corner_verts();
this->runtime->vert_normals.reinitialize(positions.size());
this->runtime->poly_normals.reinitialize(polys.size());
blender::bke::mesh::normals_calc_poly_vert(
positions, polys, loops, this->runtime->poly_normals, this->runtime->vert_normals);
positions, polys, corner_verts, this->runtime->poly_normals, this->runtime->vert_normals);
this->runtime->vert_normals_dirty = false;
this->runtime->poly_normals_dirty = false;
@@ -375,10 +376,11 @@ blender::Span<blender::float3> Mesh::poly_normals() const
blender::threading::isolate_task([&]() {
const Span<float3> positions = this->vert_positions();
const Span<MPoly> polys = this->polys();
const Span<MLoop> loops = this->loops();
const Span<int> corner_verts = this->corner_verts();
this->runtime->poly_normals.reinitialize(polys.size());
blender::bke::mesh::normals_calc_polys(positions, polys, loops, this->runtime->poly_normals);
blender::bke::mesh::normals_calc_polys(
positions, polys, corner_verts, this->runtime->poly_normals);
this->runtime->poly_normals_dirty = false;
});
@@ -715,7 +717,8 @@ struct LoopSplitTaskDataCommon {
/* Read-only. */
Span<float3> positions;
Span<MEdge> edges;
Span<MLoop> loops;
Span<int> corner_verts;
Span<int> corner_edges;
Span<MPoly> polys;
Span<int2> edge_to_loops;
Span<int> loop_to_poly;
@@ -731,7 +734,8 @@ struct LoopSplitTaskDataCommon {
namespace blender::bke::mesh {
static void mesh_edges_sharp_tag(const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<int> loop_to_poly_map,
const Span<float3> poly_normals,
const Span<bool> sharp_faces,
@@ -749,8 +753,8 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
for (const int poly_i : polys.index_range()) {
const MPoly &poly = polys[poly_i];
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
const int vert_i = loops[loop_index].v;
const int edge_i = loops[loop_index].e;
const int vert_i = corner_verts[loop_index];
const int edge_i = corner_edges[loop_index];
int2 &e2l = edge_to_loops[edge_i];
@@ -772,7 +776,7 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
* same vertex, or angle between both its polys' normals is above split_angle value.
*/
if (!poly_is_smooth(poly_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) ||
vert_i == loops[e2l[0]].v || is_angle_sharp) {
vert_i == corner_verts[e2l[0]] || is_angle_sharp) {
/* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
@@ -802,7 +806,8 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
}
void edges_sharp_from_angle_set(const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<float3> poly_normals,
const bool *sharp_faces,
const float split_angle,
@@ -817,10 +822,12 @@ void edges_sharp_from_angle_set(const Span<MPoly> polys,
Array<int2> edge_to_loops(sharp_edges.size(), int2(0));
/* Simple mapping from a loop to its polygon index. */
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size());
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys,
corner_verts.size());
mesh_edges_sharp_tag(polys,
loops,
corner_verts,
corner_edges,
loop_to_poly,
poly_normals,
Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
@@ -831,7 +838,7 @@ void edges_sharp_from_angle_set(const Span<MPoly> polys,
sharp_edges);
}
static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
static void loop_manifold_fan_around_vert_next(const Span<int> corner_verts,
const Span<MPoly> polys,
const Span<int> loop_to_poly,
const int *e2lfan_curr,
@@ -841,7 +848,7 @@ static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
int *r_mpfan_curr_index)
{
const int mlfan_curr_orig = *r_mlfan_curr_index;
const uint vert_fan_orig = loops[mlfan_curr_orig].v;
const uint vert_fan_orig = corner_verts[mlfan_curr_orig];
/* WARNING: This is rather complex!
* We have to find our next edge around the vertex (fan mode).
@@ -856,7 +863,7 @@ static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
BLI_assert(*r_mlfan_curr_index >= 0);
BLI_assert(*r_mpfan_curr_index >= 0);
const uint vert_fan_next = loops[*r_mlfan_curr_index].v;
const uint vert_fan_next = corner_verts[*r_mlfan_curr_index];
const MPoly &mpfan_next = polys[*r_mpfan_curr_index];
if ((vert_fan_orig == vert_fan_next && vert_fan_orig == mv_pivot_index) ||
!ELEM(vert_fan_orig, vert_fan_next, mv_pivot_index)) {
@@ -882,7 +889,8 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
const Span<float3> positions = common_data->positions;
const Span<MEdge> edges = common_data->edges;
const Span<MLoop> loops = common_data->loops;
const Span<int> corner_verts = common_data->corner_verts;
const Span<int> corner_edges = common_data->corner_edges;
const Span<float3> poly_normals = common_data->poly_normals;
MutableSpan<float3> loop_normals = common_data->loop_normals;
@@ -908,10 +916,11 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
if (lnors_spacearr) {
float vec_curr[3], vec_prev[3];
const uint mv_pivot_index = loops[ml_curr_index].v; /* The vertex we are "fanning" around! */
const MEdge *me_curr = &edges[loops[ml_curr_index].e];
const uint mv_pivot_index =
corner_verts[ml_curr_index]; /* The vertex we are "fanning" around! */
const MEdge *me_curr = &edges[corner_edges[ml_curr_index]];
const int vert_2 = me_curr->v1 == mv_pivot_index ? me_curr->v2 : me_curr->v1;
const MEdge *me_prev = &edges[loops[ml_prev_index].e];
const MEdge *me_prev = &edges[corner_edges[ml_prev_index]];
const int vert_3 = me_prev->v1 == mv_pivot_index ? me_prev->v2 : me_prev->v1;
sub_v3_v3v3(vec_curr, positions[vert_2], positions[mv_pivot_index]);
@@ -941,7 +950,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
const Span<float3> positions = common_data->positions;
const Span<MEdge> edges = common_data->edges;
const Span<MPoly> polys = common_data->polys;
const Span<MLoop> loops = common_data->loops;
const Span<int> corner_verts = common_data->corner_verts;
const Span<int> corner_edges = common_data->corner_edges;
const Span<int2> edge_to_loops = common_data->edge_to_loops;
const Span<int> loop_to_poly = common_data->loop_to_poly;
const Span<float3> poly_normals = common_data->poly_normals;
@@ -960,10 +970,10 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
* same as the vertex normal, but I do not see any easy way to detect that (would need to count
* number of sharp edges per vertex, I doubt the additional memory usage would be worth it,
* especially as it should not be a common case in real-life meshes anyway). */
const uint mv_pivot_index = loops[ml_curr_index].v; /* The vertex we are "fanning" around! */
const int mv_pivot_index = corner_verts[ml_curr_index]; /* The vertex we are "fanning" around! */
/* `ml_curr_index` would be mlfan_prev if we needed that one. */
const MEdge *me_org = &edges[loops[ml_curr_index].e];
const MEdge *me_org = &edges[corner_edges[ml_curr_index]];
float vec_curr[3], vec_prev[3], vec_org[3];
float lnor[3] = {0.0f, 0.0f, 0.0f};
@@ -1006,7 +1016,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
// printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
while (true) {
const MEdge *me_curr = &edges[loops[mlfan_curr_index].e];
const MEdge *me_curr = &edges[corner_edges[mlfan_curr_index]];
/* Compute edge vectors.
* NOTE: We could pre-compute those into an array, in the first iteration, instead of computing
* them twice (or more) here. However, time gained is not worth memory and time lost,
@@ -1020,7 +1030,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
normalize_v3(vec_curr);
}
// printf("\thandling edge %d / loop %d\n", loops[mlfan_curr_index].e, mlfan_curr_index);
// printf("\thandling edge %d / loop %d\n", corner_edges[mlfan_curr_index], mlfan_curr_index);
{
/* Code similar to accumulate_vertex_normals_poly_v3. */
@@ -1058,7 +1068,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
}
}
if (IS_EDGE_SHARP(edge_to_loops[loops[mlfan_curr_index].e]) || (me_curr == me_org)) {
if (IS_EDGE_SHARP(edge_to_loops[corner_edges[mlfan_curr_index]]) || (me_curr == me_org)) {
/* Current edge is sharp and we have finished with this fan of faces around this vert,
* or this vert is smooth, and we have completed a full turn around it. */
// printf("FAN: Finished!\n");
@@ -1068,10 +1078,10 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
copy_v3_v3(vec_prev, vec_curr);
/* Find next loop of the smooth fan. */
loop_manifold_fan_around_vert_next(loops,
loop_manifold_fan_around_vert_next(corner_verts,
polys,
loop_to_poly,
edge_to_loops[loops[mlfan_curr_index].e],
edge_to_loops[corner_edges[mlfan_curr_index]],
mv_pivot_index,
&mlfan_curr_index,
&mlfan_vert_index,
@@ -1159,7 +1169,6 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
if (data->flag == LoopSplitTaskData::Type::BlockEnd) {
break;
}
loop_split_worker_do(common_data, data, edge_vectors);
}
@@ -1173,7 +1182,8 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
* Needed because cyclic smooth fans have no obvious 'entry point',
* and yet we need to walk them once, and only once.
*/
static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloops,
static bool loop_split_generator_check_cyclic_smooth_fan(const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<MPoly> polys,
const Span<int2> edge_to_loops,
const Span<int> loop_to_poly,
@@ -1183,7 +1193,8 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloop
const int ml_prev_index,
const int mp_curr_index)
{
const uint mv_pivot_index = mloops[ml_curr_index].v; /* The vertex we are "fanning" around! */
/* The vertex we are "fanning" around! */
const uint mv_pivot_index = corner_verts[ml_curr_index];
const int *e2lfan_curr = e2l_prev;
if (IS_EDGE_SHARP(e2lfan_curr)) {
@@ -1206,7 +1217,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloop
while (true) {
/* Find next loop of the smooth fan. */
loop_manifold_fan_around_vert_next(mloops,
loop_manifold_fan_around_vert_next(corner_verts,
polys,
loop_to_poly,
e2lfan_curr,
@@ -1215,7 +1226,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloop
&mlfan_vert_index,
&mpfan_curr_index);
e2lfan_curr = edge_to_loops[mloops[mlfan_curr_index].e];
e2lfan_curr = edge_to_loops[corner_edges[mlfan_curr_index]];
if (IS_EDGE_SHARP(e2lfan_curr)) {
/* Sharp loop/edge, so not a cyclic smooth fan. */
@@ -1241,12 +1252,13 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
const Span<MLoop> loops = common_data->loops;
const Span<int> corner_verts = common_data->corner_verts;
const Span<int> corner_edges = common_data->corner_edges;
const Span<MPoly> polys = common_data->polys;
const Span<int> loop_to_poly = common_data->loop_to_poly;
const Span<int2> edge_to_loops = common_data->edge_to_loops;
BitVector<> skip_loops(loops.size(), false);
BitVector<> skip_loops(corner_verts.size(), false);
LoopSplitTaskData *data_buff = nullptr;
int data_idx = 0;
@@ -1277,9 +1289,9 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
#if 0
printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",
ml_curr_index,
loops[ml_curr_index].e,
loops[ml_curr_index].v,
IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]),
corner_edges[ml_curr_index],
corner_verts[ml_curr_index],
IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]),
skip_loops[ml_curr_index]);
#endif
@@ -1293,17 +1305,18 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
* However, this would complicate the code, add more memory usage, and despite its logical
* complexity, #loop_manifold_fan_around_vert_next() is quite cheap in term of CPU cycles,
* so really think it's not worth it. */
if (!IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]) &&
(skip_loops[ml_curr_index] ||
!loop_split_generator_check_cyclic_smooth_fan(loops,
polys,
edge_to_loops,
loop_to_poly,
edge_to_loops[loops[ml_prev_index].e],
skip_loops,
ml_curr_index,
ml_prev_index,
poly_index))) {
if (!IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]) &&
(skip_loops[ml_curr_index] || !loop_split_generator_check_cyclic_smooth_fan(
corner_verts,
corner_edges,
polys,
edge_to_loops,
loop_to_poly,
edge_to_loops[corner_edges[ml_prev_index]],
skip_loops,
ml_curr_index,
ml_prev_index,
poly_index))) {
// printf("SKIPPING!\n");
}
else {
@@ -1323,8 +1336,8 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
memset(data, 0, sizeof(*data));
}
if (IS_EDGE_SHARP(edge_to_loops[loops[ml_curr_index].e]) &&
IS_EDGE_SHARP(edge_to_loops[loops[ml_prev_index].e])) {
if (IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]) &&
IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_prev_index]])) {
data->ml_curr_index = ml_curr_index;
data->ml_prev_index = ml_prev_index;
data->flag = LoopSplitTaskData::Type::Single;
@@ -1376,7 +1389,8 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
void normals_calc_loop(const Span<float3> vert_positions,
const Span<MEdge> edges,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<int> loop_to_poly_map,
const Span<float3> vert_normals,
const Span<float3> poly_normals,
@@ -1410,7 +1424,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
copy_v3_v3(r_loop_normals[ml_index], poly_normals[poly_index]);
}
else {
copy_v3_v3(r_loop_normals[ml_index], vert_normals[loops[ml_index].v]);
copy_v3_v3(r_loop_normals[ml_index], vert_normals[corner_verts[ml_index]]);
}
}
}
@@ -1437,7 +1451,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
Span<int> loop_to_poly;
Array<int> local_loop_to_poly_map;
if (loop_to_poly_map.is_empty()) {
local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, loops.size());
local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, corner_verts.size());
loop_to_poly = local_loop_to_poly_map;
}
else {
@@ -1458,7 +1472,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
BKE_lnor_spacearr_init(r_lnors_spacearr, loops.size(), MLNOR_SPACEARR_LOOP_INDEX);
BKE_lnor_spacearr_init(r_lnors_spacearr, corner_verts.size(), MLNOR_SPACEARR_LOOP_INDEX);
}
/* Init data common to all tasks. */
@@ -1466,11 +1480,12 @@ void normals_calc_loop(const Span<float3> vert_positions,
common_data.lnors_spacearr = r_lnors_spacearr;
common_data.loop_normals = r_loop_normals;
common_data.clnors_data = {reinterpret_cast<short2 *>(clnors_data),
clnors_data ? loops.size() : 0};
clnors_data ? corner_verts.size() : 0};
common_data.positions = vert_positions;
common_data.edges = edges;
common_data.polys = polys;
common_data.loops = loops;
common_data.corner_verts = corner_verts;
common_data.corner_edges = corner_edges;
common_data.edge_to_loops = edge_to_loops;
common_data.loop_to_poly = loop_to_poly;
common_data.poly_normals = poly_normals;
@@ -1482,14 +1497,15 @@ void normals_calc_loop(const Span<float3> vert_positions,
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) {
copy_v3_v3(r_loop_normals[loop_i], vert_normals[loops[loop_i].v]);
copy_v3_v3(r_loop_normals[loop_i], vert_normals[corner_verts[loop_i]]);
}
}
});
/* This first loop check which edges are actually smooth, and compute edge vectors. */
mesh_edges_sharp_tag(polys,
loops,
corner_verts,
corner_edges,
loop_to_poly,
poly_normals,
Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
@@ -1499,7 +1515,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
edge_to_loops,
{});
if (loops.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
if (corner_verts.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead. */
loop_split_generator(nullptr, &common_data);
}
@@ -1537,7 +1553,8 @@ void normals_calc_loop(const Span<float3> vert_positions,
static void mesh_normals_loop_custom_set(Span<float3> positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> corner_verts,
Span<int> corner_edges,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_faces,
@@ -1552,9 +1569,10 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
* when importing custom normals, and modifier (and perhaps from some editing tools later?). So
* better to keep some simplicity here, and just call #bke::mesh::normals_calc_loop() twice! */
MLoopNorSpaceArray lnors_spacearr = {nullptr};
BitVector<> done_loops(loops.size(), false);
Array<float3> loop_normals(loops.size());
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size());
BitVector<> done_loops(corner_verts.size(), false);
Array<float3> loop_normals(corner_verts.size());
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys,
corner_verts.size());
/* In this case we always consider split nors as ON,
* and do not want to use angle to define smooth fans! */
const bool use_split_normals = true;
@@ -1566,7 +1584,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
normals_calc_loop(positions,
edges,
polys,
loops,
corner_verts,
corner_edges,
loop_to_poly,
vert_normals,
poly_normals,
@@ -1587,7 +1606,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
}
}
else {
for (const int i : loops.index_range()) {
for (const int i : corner_verts.index_range()) {
if (is_zero_v3(r_custom_loop_normals[i])) {
copy_v3_v3(r_custom_loop_normals[i], loop_normals[i]);
}
@@ -1606,7 +1625,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
done_loops.fill(true);
}
else {
for (const int i : loops.index_range()) {
for (const int i : corner_verts.index_range()) {
if (!lnors_spacearr.lspacearr[i]) {
/* This should not happen in theory, but in some rare case (probably ugly geometry)
* we can get some nullptr loopspacearr at this point. :/
@@ -1636,14 +1655,12 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
}
LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops;
const MLoop *prev_ml = nullptr;
int prev_corner = -1;
const float *org_nor = nullptr;
while (loop_link) {
const int lidx = POINTER_AS_INT(loop_link->link);
const MLoop *ml = &loops[lidx];
const int nidx = lidx;
float *nor = r_custom_loop_normals[nidx];
float *nor = r_custom_loop_normals[lidx];
if (!org_nor) {
org_nor = nor;
@@ -1654,14 +1671,16 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
* We know those two loops do not point to the same edge,
* since we do not allow reversed winding in a same smooth fan. */
const MPoly &poly = polys[loop_to_poly[lidx]];
const MLoop *mlp =
&loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1];
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1;
const int edge = corner_edges[lidx];
const int edge_p = corner_edges[mlp];
const int prev_edge = corner_edges[prev_corner];
sharp_edges[prev_edge == edge_p ? prev_edge : edge] = true;
org_nor = nor;
}
prev_ml = ml;
prev_corner = lidx;
loop_link = loop_link->next;
done_loops[lidx].set();
}
@@ -1673,15 +1692,15 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
loop_link = lnors_spacearr.lspacearr[i]->loops;
if (loop_link && org_nor) {
const int lidx = POINTER_AS_INT(loop_link->link);
const MLoop *ml = &loops[lidx];
const int nidx = lidx;
float *nor = r_custom_loop_normals[nidx];
float *nor = r_custom_loop_normals[lidx];
if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
const MPoly &poly = polys[loop_to_poly[lidx]];
const MLoop *mlp =
&loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1];
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
const int mlp = (lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1;
const int edge = corner_edges[lidx];
const int edge_p = corner_edges[mlp];
const int prev_edge = corner_edges[prev_corner];
sharp_edges[prev_edge == edge_p ? prev_edge : edge] = true;
}
}
}
@@ -1691,7 +1710,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
normals_calc_loop(positions,
edges,
polys,
loops,
corner_verts,
corner_edges,
loop_to_poly,
vert_normals,
poly_normals,
@@ -1706,7 +1726,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
/* And we just have to convert plain object-space custom normals to our
* lnor space-encoded ones. */
for (const int i : loops.index_range()) {
for (const int i : corner_verts.index_range()) {
if (!lnors_spacearr.lspacearr[i]) {
done_loops[i].reset();
if (G.debug & G_DEBUG) {
@@ -1723,7 +1743,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops;
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
BLI_assert(POINTER_AS_INT(loop_link) == i);
const int nidx = use_vertices ? int(loops[i].v) : i;
const int nidx = use_vertices ? corner_verts[i] : i;
float *nor = r_custom_loop_normals[nidx];
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
@@ -1737,7 +1757,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
zero_v3(avg_nor);
while (loop_link) {
const int lidx = POINTER_AS_INT(loop_link->link);
const int nidx = use_vertices ? int(loops[lidx].v) : lidx;
const int nidx = use_vertices ? corner_verts[lidx] : lidx;
float *nor = r_custom_loop_normals[nidx];
avg_nor_count++;
@@ -1765,7 +1785,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
void normals_loop_custom_set(const Span<float3> vert_positions,
const Span<MEdge> edges,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<float3> vert_normals,
const Span<float3> poly_normals,
const bool *sharp_faces,
@@ -1776,7 +1797,8 @@ void normals_loop_custom_set(const Span<float3> vert_positions,
mesh_normals_loop_custom_set(vert_positions,
edges,
polys,
loops,
corner_verts,
corner_edges,
vert_normals,
poly_normals,
sharp_faces,
@@ -1789,7 +1811,8 @@ void normals_loop_custom_set(const Span<float3> vert_positions,
void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
const Span<MEdge> edges,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<int> corner_edges,
const Span<float3> vert_normals,
const Span<float3> poly_normals,
const bool *sharp_faces,
@@ -1800,7 +1823,8 @@ void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
mesh_normals_loop_custom_set(vert_positions,
edges,
polys,
loops,
corner_verts,
corner_edges,
vert_normals,
poly_normals,
sharp_faces,
@@ -1833,7 +1857,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
mesh_normals_loop_custom_set(mesh->vert_positions(),
mesh->edges(),
mesh->polys(),
mesh->loops(),
mesh->corner_verts(),
mesh->corner_edges(),
mesh->vert_normals(),
mesh->poly_normals(),
sharp_faces,
@@ -1859,7 +1884,7 @@ void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float (*r_custom_vert_no
}
void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const MLoop *mloops,
const int *corner_verts,
const int numLoops,
const float (*clnors)[3],
float (*r_vert_clnors)[3])
@@ -1870,12 +1895,10 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts,
copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f);
int i;
const MLoop *ml;
for (i = 0, ml = mloops; i < numLoops; i++, ml++) {
const uint v = ml->v;
add_v3_v3(r_vert_clnors[v], clnors[i]);
vert_loops_count[v]++;
for (i = 0; i < numLoops; i++) {
const int vert = corner_verts[i];
add_v3_v3(r_vert_clnors[vert], clnors[i]);
vert_loops_count[vert]++;
}
for (i = 0; i < numVerts; i++) {
+72 -74
View File
@@ -369,7 +369,7 @@ void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index)
}
static int mesh_remap_interp_poly_data_get(const MPoly &poly,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_verts,
const float (*vcos_src)[3],
const float point[3],
size_t *buff_size,
@@ -380,7 +380,6 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly,
const bool do_weights,
int *r_closest_index)
{
const MLoop *ml;
float(*vco)[3];
float ref_dist_sq = FLT_MAX;
int *index;
@@ -396,10 +395,10 @@ static int mesh_remap_interp_poly_data_get(const MPoly &poly,
}
}
for (i = 0, ml = &loops[poly.loopstart], vco = *vcos, index = *indices; i < sources_num;
i++, ml++, vco++, index++) {
*index = use_loops ? int(poly.loopstart) + i : int(ml->v);
copy_v3_v3(*vco, vcos_src[ml->v]);
for (i = 0, vco = *vcos, index = *indices; i < sources_num; i++, vco++, index++) {
const int vert = corner_verts[poly.loopstart + i];
*index = use_loops ? int(poly.loopstart) + i : vert;
copy_v3_v3(*vco, vcos_src[vert]);
if (r_closest_index) {
/* Find closest vert/loop in this case. */
const float dist_sq = len_squared_v3v3(point, *vco);
@@ -564,7 +563,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
MREMAP_MODE_VERT_POLYINTERP_NEAREST,
MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) {
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
const blender::Span<int> corner_verts_src = me_src->corner_verts();
const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src);
const blender::Span<blender::float3> vert_normals_dst = me_dst->vert_normals();
@@ -592,7 +591,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
&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],
loops_src,
corner_verts_src,
vcos_src,
rayhit.co,
&tmp_buff_size,
@@ -629,7 +628,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
int index;
mesh_remap_interp_poly_data_get(polys_src[lt->poly],
loops_src,
corner_verts_src,
vcos_src,
nearest.co,
&tmp_buff_size,
@@ -644,7 +643,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
}
else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) {
const int sources_num = mesh_remap_interp_poly_data_get(polys_src[lt->poly],
loops_src,
corner_verts_src,
vcos_src,
nearest.co,
&tmp_buff_size,
@@ -866,7 +865,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) {
const blender::Span<MEdge> edges_src = me_src->edges();
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
const blender::Span<int> corner_edges_src = me_src->corner_edges();
const float(*vcos_src)[3] = BKE_mesh_vert_positions(me_src);
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2);
@@ -886,13 +885,13 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
const MLoopTri *lt = &treedata.looptri[nearest.index];
const MPoly &poly_src = polys_src[lt->poly];
const MLoop *ml_src = &loops_src[poly_src.loopstart];
const int *corner_edge_src = &corner_edges_src[poly_src.loopstart];
int nloops = poly_src.totloop;
float best_dist_sq = FLT_MAX;
int best_eidx_src = -1;
for (; nloops--; ml_src++) {
const MEdge *edge_src = &edges_src[ml_src->e];
for (; nloops--; corner_edge_src++) {
const MEdge *edge_src = &edges_src[*corner_edge_src];
const float *co1_src = vcos_src[edge_src->v1];
const float *co2_src = vcos_src[edge_src->v2];
float co_src[3];
@@ -902,7 +901,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
dist_sq = len_squared_v3v3(tmp_co, co_src);
if (dist_sq < best_dist_sq) {
best_dist_sq = dist_sq;
best_eidx_src = int(ml_src->e);
best_eidx_src = *corner_edge_src;
}
}
if (best_eidx_src >= 0) {
@@ -1036,7 +1035,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands,
BLI_AStarGraph *as_graph,
const blender::Span<blender::float3> positions,
const blender::Span<MPoly> polys,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_verts,
const int edge_idx,
BLI_bitmap *done_edges,
MeshElemMap *edge_to_poly_map,
@@ -1067,8 +1066,8 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands,
if (poly_status[pidx_isld] == POLY_UNSET) {
copy_v3_v3(poly_centers[pidx_isld],
blender::bke::mesh::poly_center_calc(positions,
loops.slice(poly.loopstart, poly.totloop)));
blender::bke::mesh::poly_center_calc(
positions, corner_verts.slice(poly.loopstart, poly.totloop)));
BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]);
poly_status[pidx_isld] = POLY_CENTER_INIT;
}
@@ -1097,7 +1096,8 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
MeshElemMap *edge_to_poly_map,
const int numedges,
const blender::Span<MPoly> polys,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_verts,
const blender::Span<int> corner_edges,
const int numpolys,
BLI_AStarGraph *r_as_graph)
{
@@ -1136,7 +1136,7 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
r_as_graph,
positions,
polys,
loops,
corner_verts,
island_einnercut_map->indices[i],
done_edges,
edge_to_poly_map,
@@ -1157,9 +1157,9 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
}
for (pl_idx = 0, l_idx = poly.loopstart; pl_idx < poly.totloop; pl_idx++, l_idx++) {
const MLoop *ml = &loops[l_idx];
const int edge = corner_edges[l_idx];
if (BLI_BITMAP_TEST(done_edges, ml->e)) {
if (BLI_BITMAP_TEST(done_edges, edge)) {
continue;
}
@@ -1168,8 +1168,8 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
r_as_graph,
positions,
polys,
loops,
int(ml->e),
corner_verts,
edge,
done_edges,
edge_to_poly_map,
false,
@@ -1229,7 +1229,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const int numverts_dst,
const MEdge *edges_dst,
const int numedges_dst,
const MLoop *loops_dst,
const int *corner_verts_dst,
const int *corner_edges_dst,
const int numloops_dst,
const MPoly *polys_dst,
const int numpolys_dst,
@@ -1302,7 +1303,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const float(*vcos_src)[3] = nullptr;
const blender::Span<MEdge> edges_src = me_src->edges();
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
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;
size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
@@ -1310,8 +1312,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
int *indices_interp = nullptr;
float *weights_interp = nullptr;
const MLoop *ml_src;
const MLoop *ml_dst;
const MPoly *mp_dst;
int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
@@ -1362,7 +1362,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{edges_dst, numedges_dst},
{polys_dst, numpolys_dst},
{loops_dst, numloops_dst},
{corner_verts_dst, numloops_dst},
{corner_edges_dst, numloops_dst},
{},
mesh_dst->vert_normals(),
mesh_dst->poly_normals(),
@@ -1392,18 +1393,18 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src,
&vert_to_loop_map_src_buff,
polys_src.data(),
loops_src.data(),
corner_verts_src.data(),
num_verts_src,
int(polys_src.size()),
int(loops_src.size()));
int(corner_verts_src.size()));
if (mode & MREMAP_USE_POLY) {
BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src,
&vert_to_poly_map_src_buff,
polys_src.data(),
loops_src.data(),
corner_verts_src.data(),
num_verts_src,
int(polys_src.size()),
int(loops_src.size()));
int(corner_verts_src.size()));
}
}
@@ -1413,21 +1414,20 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
int(edges_src.size()),
polys_src.data(),
int(polys_src.size()),
loops_src.data(),
int(loops_src.size()));
corner_edges_src.data(),
int(corner_edges_src.size()));
if (use_from_vert) {
loop_to_poly_map_src = static_cast<int *>(
MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(loops_src.size()), __func__));
MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(corner_verts_src.size()), __func__));
poly_cents_src.reinitialize(polys_src.size());
for (pidx_src = 0; pidx_src < polys_src.size(); pidx_src++) {
const MPoly &poly = polys_src[pidx_src];
ml_src = &loops_src[poly.loopstart];
for (plidx_src = 0, lidx_src = poly.loopstart; plidx_src < poly.totloop;
plidx_src++, lidx_src++) {
loop_to_poly_map_src[lidx_src] = pidx_src;
}
poly_cents_src[pidx_src] = blender::bke::mesh::poly_center_calc(
positions_src, loops_src.slice(poly.loopstart, poly.totloop));
positions_src, corner_verts_src.slice(poly.loopstart, poly.totloop));
}
}
@@ -1449,8 +1449,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
uv_seams,
polys_src.data(),
int(polys_src.size()),
loops_src.data(),
int(loops_src.size()),
corner_verts_src.data(),
corner_edges_src.data(),
int(corner_verts_src.size()),
&island_store);
num_trees = use_islands ? island_store.islands_num : 1;
@@ -1487,7 +1488,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
edge_to_poly_map_src,
int(edges_src.size()),
polys_src,
loops_src,
corner_verts_src,
corner_edges_src,
int(polys_src.size()),
&as_graphdata[tindex]);
}
@@ -1505,7 +1507,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
for (int i = 0; i < isld->count; i++) {
const MPoly &poly = polys_src[isld->indices[i]];
for (lidx_src = poly.loopstart; lidx_src < poly.loopstart + poly.totloop; lidx_src++) {
const uint vidx_src = loops_src[lidx_src].v;
const int vidx_src = corner_verts_src[lidx_src];
if (!verts_active[vidx_src]) {
verts_active[vidx_src].set();
num_verts_active++;
@@ -1544,7 +1546,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
bvhtree_from_mesh_looptri_ex(&treedata[tindex],
reinterpret_cast<const float(*)[3]>(positions_src.data()),
loops_src.data(),
corner_verts_src.data(),
looptris_src.data(),
int(looptris_src.size()),
looptri_active,
@@ -1594,12 +1596,12 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
for (tindex = 0; tindex < num_trees; tindex++) {
BVHTreeFromMesh *tdata = &treedata[tindex];
ml_dst = &loops_dst[mp_dst->loopstart];
for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
const int vert_dst = corner_verts_dst[mp_dst->loopstart + plidx_dst];
if (use_from_vert) {
MeshElemMap *vert_to_refelem_map_src = nullptr;
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
nearest.index = -1;
/* Convert the vertex to tree coordinates, if needed. */
@@ -1657,14 +1659,11 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
float *pcent_src;
float sqdist;
const MPoly &poly = polys_src[pidx_src];
ml_src = &loops_src[poly.loopstart];
if (!pcent_dst_valid) {
pcent_dst = blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions_dst),
numverts_dst},
{&loops_dst[mp_dst->loopstart], mp_dst->totloop});
{&corner_verts_dst[mp_dst->loopstart], mp_dst->totloop});
pcent_dst_valid = true;
}
pcent_src = poly_cents_src[pidx_src];
@@ -1686,9 +1685,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
/* Our best_index_src is a poly one for now!
* Have to find its loop matching our closest vertex. */
const MPoly &poly = polys_src[best_index_src];
ml_src = &loops_src[poly.loopstart];
for (plidx_src = 0; plidx_src < poly.totloop; plidx_src++, ml_src++) {
if (int(ml_src->v) == nearest.index) {
for (plidx_src = 0; plidx_src < poly.totloop; plidx_src++) {
const int vert_src = corner_verts_src[poly.loopstart + plidx_src];
if (vert_src == nearest.index) {
best_index_src = plidx_src + poly.loopstart;
break;
}
@@ -1710,7 +1709,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
float w = 1.0f;
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
copy_v3_v3(tmp_no, loop_normals_dst[plidx_dst + mp_dst->loopstart]);
/* We do our transform here, since we may do several raycast/nearest queries. */
@@ -1738,7 +1737,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
* is null, it means none of its loop mapped to this source island,
* hence we can skip it later.
*/
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
nearest.index = -1;
/* Convert the vertex to tree coordinates, if needed. */
@@ -1764,7 +1763,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
}
else { /* Nearest poly either to use all its loops/verts or just closest one. */
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
nearest.index = -1;
/* Convert the vertex to tree coordinates, if needed. */
@@ -1893,8 +1892,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
int j;
float best_dist_sq = FLT_MAX;
ml_dst = &loops_dst[lidx_dst];
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]);
/* We do our transform here,
* since we may do several raycast/nearest queries. */
@@ -1905,9 +1903,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] :
last_valid_pidx_isld_src);
const MPoly &poly = polys_src[pidx_src];
ml_src = &loops_src[poly.loopstart];
for (j = 0; j < poly.totloop; j++, ml_src++) {
const float dist_sq = len_squared_v3v3(positions_src[ml_src->v], tmp_co);
for (j = 0; j < poly.totloop; j++) {
const int vert_src = corner_verts_src[poly.loopstart + j];
const float dist_sq = len_squared_v3v3(positions_src[vert_src], tmp_co);
if (dist_sq < best_dist_sq) {
best_dist_sq = dist_sq;
lidx_src = poly.loopstart + j;
@@ -1986,8 +1984,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
float best_dist_sq = FLT_MAX;
int j;
ml_dst = &loops_dst[lidx_dst];
copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]);
const int vert_dst = corner_verts_dst[lidx_dst];
copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
/* We do our transform here,
* since we may do several raycast/nearest queries. */
@@ -2016,9 +2014,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
closest_on_tri_to_point_v3(h,
tmp_co,
vcos_src[loops_src[lt->tri[0]].v],
vcos_src[loops_src[lt->tri[1]].v],
vcos_src[loops_src[lt->tri[2]].v]);
vcos_src[corner_verts_src[lt->tri[0]]],
vcos_src[corner_verts_src[lt->tri[1]]],
vcos_src[corner_verts_src[lt->tri[2]]]);
dist_sq = len_squared_v3v3(tmp_co, h);
if (dist_sq < best_dist_sq) {
copy_v3_v3(hit_co, h);
@@ -2031,7 +2029,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) {
mesh_remap_interp_poly_data_get(poly,
loops_src,
corner_verts_src,
vcos_src,
hit_co,
&buff_size_interp,
@@ -2052,7 +2050,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
else {
const int sources_num = mesh_remap_interp_poly_data_get(poly,
loops_src,
corner_verts_src,
vcos_src,
hit_co,
&buff_size_interp,
@@ -2149,7 +2147,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
const Mesh *mesh_dst,
const float (*vert_positions_dst)[3],
const int numverts_dst,
const MLoop *loops_dst,
const int *corner_verts_dst,
const MPoly *polys_dst,
const int numpolys_dst,
Mesh *me_src,
@@ -2190,7 +2188,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
const MPoly &poly = polys_dst[i];
tmp_co = blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
{&corner_verts_dst[poly.loopstart], poly.totloop});
/* Convert the vertex to tree coordinates, if needed. */
if (space_transform) {
@@ -2215,7 +2213,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
tmp_co = blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
{&corner_verts_dst[poly.loopstart], poly.totloop});
copy_v3_v3(tmp_no, poly_normals_dst[i]);
/* Convert the vertex to tree coordinates, if needed. */
@@ -2280,7 +2278,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
pcent_dst = blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
{&corner_verts_dst[poly.loopstart], poly.totloop});
copy_v3_v3(tmp_no, poly_normals_dst[i]);
@@ -2310,8 +2308,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max);
for (j = 0; j < poly.totloop; j++) {
const MLoop *ml = &loops_dst[j + poly.loopstart];
copy_v3_v3(tmp_co, vert_positions_dst[ml->v]);
const int vert = corner_verts_dst[poly.loopstart + j];
copy_v3_v3(tmp_co, vert_positions_dst[vert]);
if (space_transform) {
BLI_space_transform_apply(space_transform, tmp_co);
}
@@ -64,13 +64,13 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
void *update_cb_data)
{
const Span<float3> input_positions = input_mesh->vert_positions();
const Span<MLoop> input_loops = input_mesh->loops();
const Span<int> input_corner_verts = input_mesh->corner_verts();
const Span<MLoopTri> looptris = input_mesh->looptris();
/* Gather the required data for export to the internal quadriflow mesh format. */
Array<MVertTri> verttri(looptris.size());
BKE_mesh_runtime_verttri_from_looptri(
verttri.data(), input_loops.data(), looptris.data(), looptris.size());
verttri.data(), input_corner_verts.data(), looptris.data(), looptris.size());
const int totfaces = looptris.size();
const int totverts = input_mesh->totvert;
@@ -120,7 +120,7 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces * 4, qrd.out_totfaces);
BKE_mesh_copy_parameters(mesh, input_mesh);
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
mesh->vert_positions_for_write().copy_from(
Span(reinterpret_cast<float3 *>(qrd.out_verts), qrd.out_totverts));
@@ -130,10 +130,10 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
const int loopstart = i * 4;
poly.loopstart = loopstart;
poly.totloop = 4;
loops[loopstart].v = qrd.out_faces[loopstart];
loops[loopstart + 1].v = qrd.out_faces[loopstart + 1];
loops[loopstart + 2].v = qrd.out_faces[loopstart + 2];
loops[loopstart + 3].v = qrd.out_faces[loopstart + 3];
corner_verts[loopstart] = qrd.out_faces[loopstart];
corner_verts[loopstart + 1] = qrd.out_faces[loopstart + 1];
corner_verts[loopstart + 2] = qrd.out_faces[loopstart + 2];
corner_verts[loopstart + 3] = qrd.out_faces[loopstart + 3];
}
BKE_mesh_calc_edges(mesh, false, false);
@@ -184,7 +184,7 @@ static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh,
const float voxel_size)
{
const Span<float3> positions = mesh->vert_positions();
const Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
const Span<MLoopTri> looptris = mesh->looptris();
std::vector<openvdb::Vec3s> points(mesh->totvert);
@@ -197,8 +197,9 @@ static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh,
for (const int i : IndexRange(looptris.size())) {
const MLoopTri &loop_tri = looptris[i];
triangles[i] = openvdb::Vec3I(
loops[loop_tri.tri[0]].v, loops[loop_tri.tri[1]].v, loops[loop_tri.tri[2]].v);
triangles[i] = openvdb::Vec3I(corner_verts[loop_tri.tri[0]],
corner_verts[loop_tri.tri[1]],
corner_verts[loop_tri.tri[2]]);
}
openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
@@ -224,7 +225,7 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set
vertices.size(), 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size());
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
MutableSpan<MPoly> mesh_polys = mesh->polys_for_write();
MutableSpan<MLoop> mesh_loops = mesh->loops_for_write();
MutableSpan<int> mesh_corner_verts = mesh->corner_verts_for_write();
for (const int i : vert_positions.index_range()) {
vert_positions[i] = float3(vertices[i].x(), vertices[i].y(), vertices[i].z());
@@ -235,10 +236,10 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set
const int loopstart = i * 4;
poly.loopstart = loopstart;
poly.totloop = 4;
mesh_loops[loopstart].v = quads[i][0];
mesh_loops[loopstart + 1].v = quads[i][3];
mesh_loops[loopstart + 2].v = quads[i][2];
mesh_loops[loopstart + 3].v = quads[i][1];
mesh_corner_verts[loopstart] = quads[i][0];
mesh_corner_verts[loopstart + 1] = quads[i][3];
mesh_corner_verts[loopstart + 2] = quads[i][2];
mesh_corner_verts[loopstart + 3] = quads[i][1];
}
const int triangle_loop_start = quads.size() * 4;
@@ -247,9 +248,9 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set
const int loopstart = triangle_loop_start + i * 3;
poly.loopstart = loopstart;
poly.totloop = 3;
mesh_loops[loopstart].v = tris[i][2];
mesh_loops[loopstart + 1].v = tris[i][1];
mesh_loops[loopstart + 2].v = tris[i][0];
mesh_corner_verts[loopstart] = tris[i][2];
mesh_corner_verts[loopstart + 1] = tris[i][1];
mesh_corner_verts[loopstart + 2] = tris[i][0];
}
BKE_mesh_calc_edges(mesh, false, false);
@@ -316,7 +317,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
MutableAttributeAccessor dst_attributes = target->attributes_for_write();
const Span<float3> target_positions = target->vert_positions();
const Span<MPoly> target_polys = target->polys();
const Span<MLoop> target_loops = target->loops();
const Span<int> target_corner_verts = target->corner_verts();
const VArray<int> src_face_sets = src_attributes.lookup<int>(".sculpt_face_set",
ATTR_DOMAIN_FACE);
@@ -343,7 +344,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
nearest.dist_sq = FLT_MAX;
const MPoly &poly = target_polys[i];
const float3 from_co = mesh::poly_center_calc(
target_positions, target_loops.slice(poly.loopstart, poly.totloop));
target_positions, target_corner_verts.slice(poly.loopstart, poly.totloop));
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
@@ -416,7 +417,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
BKE_mesh_vert_loop_map_create(&source_lmap,
&source_lmap_mem,
source->polys().data(),
source->loops().data(),
source->corner_verts().data(),
source->totvert,
source->totpoly,
source->totloop);
@@ -424,7 +425,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
BKE_mesh_vert_loop_map_create(&target_lmap,
&target_lmap_mem,
target->polys().data(),
target->loops().data(),
target->corner_verts().data(),
target->totvert,
target->totpoly,
target->totloop);
@@ -117,9 +117,9 @@ const blender::bke::LooseEdgeCache &Mesh::loose_edges() const
loose_edges.resize(this->totedge, true);
int count = this->totedge;
for (const MLoop &loop : this->loops()) {
if (loose_edges[loop.e]) {
loose_edges[loop.e].reset();
for (const int edge : this->corner_edges()) {
if (loose_edges[edge]) {
loose_edges[edge].reset();
count--;
}
}
@@ -146,16 +146,16 @@ blender::Span<MLoopTri> Mesh::looptris() const
this->runtime->looptris_cache.ensure([&](blender::Array<MLoopTri> &r_data) {
const Span<float3> positions = this->vert_positions();
const Span<MPoly> polys = this->polys();
const Span<MLoop> loops = this->loops();
const Span<int> corner_verts = this->corner_verts();
r_data.reinitialize(poly_to_tri_count(polys.size(), loops.size()));
r_data.reinitialize(poly_to_tri_count(polys.size(), corner_verts.size()));
if (BKE_mesh_poly_normals_are_dirty(this)) {
blender::bke::mesh::looptris_calc(positions, polys, loops, r_data);
blender::bke::mesh::looptris_calc(positions, polys, corner_verts, r_data);
}
else {
blender::bke::mesh::looptris_calc_with_normals(
positions, polys, loops, this->poly_normals(), r_data);
positions, polys, corner_verts, this->poly_normals(), r_data);
}
});
@@ -174,14 +174,14 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
}
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
const MLoop *mloop,
const int *corner_verts,
const MLoopTri *looptri,
int looptri_num)
{
for (int i = 0; i < looptri_num; i++) {
r_verttri[i].tri[0] = mloop[looptri[i].tri[0]].v;
r_verttri[i].tri[1] = mloop[looptri[i].tri[1]].v;
r_verttri[i].tri[2] = mloop[looptri[i].tri[2]].v;
r_verttri[i].tri[0] = corner_verts[looptri[i].tri[0]];
r_verttri[i].tri[1] = corner_verts[looptri[i].tri[1]];
r_verttri[i].tri[2] = corner_verts[looptri[i].tri[2]];
}
}
@@ -318,7 +318,8 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
MutableSpan<float3> positions = me_eval->vert_positions_for_write();
MutableSpan<MEdge> edges = me_eval->edges_for_write();
MutableSpan<MPoly> polys = me_eval->polys_for_write();
MutableSpan<MLoop> loops = me_eval->loops_for_write();
MutableSpan<int> corner_verts = me_eval->corner_verts_for_write();
MutableSpan<int> corner_edges = me_eval->corner_edges_for_write();
is_valid &= BKE_mesh_validate_all_customdata(
&me_eval->vdata,
@@ -342,8 +343,9 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
static_cast<MFace *>(CustomData_get_layer_for_write(
&me_eval->fdata, CD_MFACE, me_eval->totface)),
me_eval->totface,
loops.data(),
loops.size(),
corner_verts.data(),
corner_edges.data(),
corner_verts.size(),
polys.data(),
polys.size(),
me_eval->deform_verts_for_write().data(),
+22 -30
View File
@@ -21,7 +21,7 @@ BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh,
const IndexMask mask,
const MutableSpan<T> dst)
{
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
const Span<MLoopTri> looptris = mesh.looptris();
for (const int i : mask) {
@@ -29,9 +29,9 @@ BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh,
const MLoopTri &looptri = looptris[looptri_index];
const float3 &bary_coord = bary_coords[i];
const int v0_index = loops[looptri.tri[0]].v;
const int v1_index = loops[looptri.tri[1]].v;
const int v2_index = loops[looptri.tri[2]].v;
const int v0_index = corner_verts[looptri.tri[0]];
const int v1_index = corner_verts[looptri.tri[1]];
const int v2_index = corner_verts[looptri.tri[2]];
const T v0 = src[v0_index];
const T v1 = src[v1_index];
@@ -157,21 +157,17 @@ Span<float3> MeshAttributeInterpolator::ensure_barycentric_coords()
bary_coords_.reinitialize(mask_.min_array_size());
const Span<float3> positions = mesh_->vert_positions();
const Span<MLoop> loops = mesh_->loops();
const Span<int> corner_verts = mesh_->corner_verts();
const Span<MLoopTri> looptris = mesh_->looptris();
for (const int i : mask_) {
const int looptri_index = looptri_indices_[i];
const MLoopTri &looptri = looptris[looptri_index];
const int v0_index = loops[looptri.tri[0]].v;
const int v1_index = loops[looptri.tri[1]].v;
const int v2_index = loops[looptri.tri[2]].v;
interp_weights_tri_v3(bary_coords_[i],
positions[v0_index],
positions[v1_index],
positions[v2_index],
positions[corner_verts[looptri.tri[0]]],
positions[corner_verts[looptri.tri[1]]],
positions[corner_verts[looptri.tri[2]]],
positions_[i]);
}
return bary_coords_;
@@ -186,20 +182,16 @@ Span<float3> MeshAttributeInterpolator::ensure_nearest_weights()
nearest_weights_.reinitialize(mask_.min_array_size());
const Span<float3> positions = mesh_->vert_positions();
const Span<MLoop> loops = mesh_->loops();
const Span<int> corner_verts = mesh_->corner_verts();
const Span<MLoopTri> looptris = mesh_->looptris();
for (const int i : mask_) {
const int looptri_index = looptri_indices_[i];
const MLoopTri &looptri = looptris[looptri_index];
const int v0_index = loops[looptri.tri[0]].v;
const int v1_index = loops[looptri.tri[1]].v;
const int v2_index = loops[looptri.tri[2]].v;
const float d0 = len_squared_v3v3(positions_[i], positions[v0_index]);
const float d1 = len_squared_v3v3(positions_[i], positions[v1_index]);
const float d2 = len_squared_v3v3(positions_[i], positions[v2_index]);
const float d0 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[0]]]);
const float d1 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[1]]]);
const float d2 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[2]]]);
nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
}
@@ -259,7 +251,7 @@ int sample_surface_points_spherical(RandomNumberGenerator &rng,
Vector<float3> &r_positions)
{
const Span<float3> positions = mesh.vert_positions();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
const Span<MLoopTri> looptris = mesh.looptris();
const float sample_radius_sq = pow2f(sample_radius);
@@ -272,9 +264,9 @@ int sample_surface_points_spherical(RandomNumberGenerator &rng,
for (const int looptri_index : looptri_indices_to_sample) {
const MLoopTri &looptri = looptris[looptri_index];
const float3 &v0 = positions[loops[looptri.tri[0]].v];
const float3 &v1 = positions[loops[looptri.tri[1]].v];
const float3 &v2 = positions[loops[looptri.tri[2]].v];
const float3 &v0 = positions[corner_verts[looptri.tri[0]]];
const float3 &v1 = positions[corner_verts[looptri.tri[1]]];
const float3 &v2 = positions[corner_verts[looptri.tri[2]]];
const float looptri_area = area_tri_v3(v0, v1, v2);
@@ -356,7 +348,7 @@ int sample_surface_points_projected(
Vector<float3> &r_positions)
{
const Span<float3> positions = mesh.vert_positions();
const Span<MLoop> loops = mesh.loops();
const Span<int> corner_verts = mesh.corner_verts();
const Span<MLoopTri> looptris = mesh.looptris();
int point_count = 0;
@@ -398,7 +390,7 @@ int sample_surface_points_projected(
const float3 pos = ray_hit.co;
const float3 bary_coords = compute_bary_coord_in_triangle(
positions, loops, looptris[looptri_index], pos);
positions, corner_verts, looptris[looptri_index], pos);
r_positions.append(pos);
r_bary_coords.append(bary_coords);
@@ -409,13 +401,13 @@ int sample_surface_points_projected(
}
float3 compute_bary_coord_in_triangle(const Span<float3> vert_positions,
const Span<MLoop> loops,
const Span<int> corner_verts,
const MLoopTri &looptri,
const float3 &position)
{
const float3 &v0 = vert_positions[loops[looptri.tri[0]].v];
const float3 &v1 = vert_positions[loops[looptri.tri[1]].v];
const float3 &v2 = vert_positions[loops[looptri.tri[2]].v];
const float3 &v0 = vert_positions[corner_verts[looptri.tri[0]]];
const float3 &v1 = vert_positions[corner_verts[looptri.tri[1]]];
const float3 &v2 = vert_positions[corner_verts[looptri.tri[2]]];
float3 bary_coords;
interp_weights_tri_v3(bary_coords, v0, v1, v2, position);
return bary_coords;
@@ -50,7 +50,7 @@ struct BKEMeshToTangent {
mikk::float3 GetPosition(const uint face_num, const uint vert_num)
{
const uint loop_idx = uint(polys[face_num].loopstart) + vert_num;
return mikk::float3(positions[mloops[loop_idx].v]);
return mikk::float3(positions[corner_verts[loop_idx]]);
}
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
@@ -71,7 +71,7 @@ struct BKEMeshToTangent {
}
const MPoly *polys; /* faces */
const MLoop *mloops; /* faces vertices */
const int *corner_verts; /* faces vertices */
const float (*positions)[3]; /* vertices */
const float (*luvs)[2]; /* texture coordinates */
const float (*loop_normals)[3]; /* loops' normals */
@@ -81,7 +81,7 @@ struct BKEMeshToTangent {
void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
const int /*numVerts*/,
const MLoop *mloops,
const int *corner_verts,
float (*r_looptangent)[4],
const float (*loop_normals)[3],
const float (*loop_uvs)[2],
@@ -93,7 +93,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
/* Compute Mikktspace's tangent normals. */
BKEMeshToTangent mesh_to_tangent;
mesh_to_tangent.polys = polys;
mesh_to_tangent.mloops = mloops;
mesh_to_tangent.corner_verts = corner_verts;
mesh_to_tangent.positions = vert_positions;
mesh_to_tangent.luvs = loop_uvs;
mesh_to_tangent.loop_normals = loop_normals;
@@ -146,7 +146,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_vert_positions(mesh),
mesh->totvert,
mesh->loops().data(),
mesh->corner_verts().data(),
r_looptangents,
loop_normals,
reinterpret_cast<const float(*)[2]>(uv_map.data()),
@@ -216,7 +216,7 @@ struct SGLSLMeshToTangent {
{
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
return mikk::float3(positions[mloop[loop_index].v]);
return mikk::float3(positions[corner_verts[loop_index]]);
}
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
@@ -227,7 +227,7 @@ struct SGLSLMeshToTangent {
const float2 &uv = mloopuv[loop_index];
return mikk::float3(uv[0], uv[1], 1.0f);
}
const float *l_orco = orco[mloop[loop_index].v];
const float *l_orco = orco[corner_verts[loop_index]];
float u, v;
map_to_sphere(&u, &v, l_orco[0], l_orco[1], l_orco[2]);
return mikk::float3(u, v, 1.0f);
@@ -249,22 +249,22 @@ struct SGLSLMeshToTangent {
float normal[3];
if (poly.totloop == 4) {
normal_quad_v3(normal,
positions[mloop[poly.loopstart + 0].v],
positions[mloop[poly.loopstart + 1].v],
positions[mloop[poly.loopstart + 2].v],
positions[mloop[poly.loopstart + 3].v]);
positions[corner_verts[poly.loopstart + 0]],
positions[corner_verts[poly.loopstart + 1]],
positions[corner_verts[poly.loopstart + 2]],
positions[corner_verts[poly.loopstart + 3]]);
}
else
#endif
{
normal_tri_v3(normal,
positions[mloop[lt->tri[0]].v],
positions[mloop[lt->tri[1]].v],
positions[mloop[lt->tri[2]].v]);
positions[corner_verts[lt->tri[0]]],
positions[corner_verts[lt->tri[1]]],
positions[corner_verts[lt->tri[2]]]);
}
return mikk::float3(normal);
}
return mikk::float3(vert_normals[mloop[loop_index].v]);
return mikk::float3(vert_normals[corner_verts[loop_index]]);
}
void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation)
@@ -280,7 +280,7 @@ struct SGLSLMeshToTangent {
const MLoopTri *looptri;
const float2 *mloopuv; /* texture coordinates */
const MPoly *polys; /* indices */
const MLoop *mloop; /* indices */
const int *corner_verts; /* indices */
const float (*positions)[3]; /* vertex coordinates */
const float (*vert_normals)[3];
const float (*orco)[3];
@@ -391,7 +391,7 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
const MPoly *polys,
const uint polys_len,
const MLoop *mloop,
const int *corner_verts,
const MLoopTri *looptri,
const uint looptri_len,
const bool *sharp_faces,
@@ -497,7 +497,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
mesh2tangent->positions = vert_positions;
mesh2tangent->vert_normals = vert_normals;
mesh2tangent->polys = polys;
mesh2tangent->mloop = mloop;
mesh2tangent->corner_verts = corner_verts;
mesh2tangent->looptri = looptri;
mesh2tangent->sharp_faces = sharp_faces;
/* NOTE: we assume we do have tessellated loop normals at this point
@@ -582,7 +582,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
BKE_mesh_vert_positions(me_eval),
me_eval->polys().data(),
uint(me_eval->totpoly),
me_eval->loops().data(),
me_eval->corner_verts().data(),
looptris.data(),
uint(looptris.size()),
static_cast<const bool *>(
@@ -34,7 +34,7 @@ namespace blender::bke::mesh {
/**
* \param face_normal: This will be optimized out as a constant.
*/
BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<int> corner_verts,
const Span<MPoly> polys,
const Span<float3> positions,
uint poly_index,
@@ -46,37 +46,37 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
const uint mp_loopstart = uint(polys[poly_index].loopstart);
const uint mp_totloop = uint(polys[poly_index].totloop);
#define ML_TO_MLT(i1, i2, i3) \
{ \
ARRAY_SET_ITEMS(mlt->tri, mp_loopstart + i1, mp_loopstart + i2, mp_loopstart + i3); \
mlt->poly = poly_index; \
} \
((void)0)
auto create_tri = [&](uint i1, uint i2, uint i3) {
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) {
case 3: {
ML_TO_MLT(0, 1, 2);
create_tri(0, 1, 2);
break;
}
case 4: {
ML_TO_MLT(0, 1, 2);
create_tri(0, 1, 2);
MLoopTri *mlt_a = mlt++;
ML_TO_MLT(0, 2, 3);
create_tri(0, 2, 3);
MLoopTri *mlt_b = mlt;
if (UNLIKELY(face_normal ? is_quad_flip_v3_first_third_fast_with_normal(
/* Simpler calculation (using the normal). */
positions[mloop[mlt_a->tri[0]].v],
positions[mloop[mlt_a->tri[1]].v],
positions[mloop[mlt_a->tri[2]].v],
positions[mloop[mlt_b->tri[2]].v],
positions[corner_verts[mlt_a->tri[0]]],
positions[corner_verts[mlt_a->tri[1]]],
positions[corner_verts[mlt_a->tri[2]]],
positions[corner_verts[mlt_b->tri[2]]],
normal_precalc) :
is_quad_flip_v3_first_third_fast(
/* Expensive calculation (no normal). */
positions[mloop[mlt_a->tri[0]].v],
positions[mloop[mlt_a->tri[1]].v],
positions[mloop[mlt_a->tri[2]].v],
positions[mloop[mlt_b->tri[2]].v]))) {
positions[corner_verts[mlt_a->tri[0]]],
positions[corner_verts[mlt_a->tri[1]]],
positions[corner_verts[mlt_a->tri[2]]],
positions[corner_verts[mlt_b->tri[2]]]))) {
/* Flip out of degenerate 0-2 state. */
mlt_a->tri[2] = mlt_b->tri[2];
mlt_b->tri[0] = mlt_a->tri[1];
@@ -84,7 +84,6 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
break;
}
default: {
const MLoop *ml;
float axis_mat[3][3];
/* Calculate `axis_mat` to project verts to 2D. */
@@ -95,10 +94,9 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
zero_v3(normal);
/* Calc normal, flipped: to get a positive 2D cross product. */
ml = mloop.data() + mp_loopstart;
co_prev = positions[ml[mp_totloop - 1].v];
for (uint j = 0; j < mp_totloop; j++, ml++) {
co_curr = positions[ml->v];
co_prev = positions[corner_verts[mp_totloop - 1]];
for (uint j = 0; j < mp_totloop; j++) {
co_curr = positions[corner_verts[mp_loopstart + j]];
add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
co_prev = co_curr;
}
@@ -123,9 +121,8 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
float(*projverts)[2] = static_cast<float(*)[2]>(
BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(mp_totloop)));
ml = mloop.data() + mp_loopstart;
for (uint j = 0; j < mp_totloop; j++, ml++) {
mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]);
for (uint j = 0; j < mp_totloop; j++) {
mul_v2_m3v3(projverts[j], axis_mat, positions[corner_verts[mp_loopstart + j]]);
}
BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, pf_arena);
@@ -133,7 +130,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
/* Apply fill. */
for (uint j = 0; j < totfilltri; j++, mlt++) {
const uint *tri = tris[j];
ML_TO_MLT(tri[0], tri[1], tri[2]);
create_tri(tri[0], tri[1], tri[2]);
}
BLI_memarena_clear(pf_arena);
@@ -144,7 +141,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
#undef ML_TO_MLT
}
static void mesh_calc_tessellation_for_face(const Span<MLoop> mloop,
static void mesh_calc_tessellation_for_face(const Span<int> corner_verts,
const Span<MPoly> polys,
const Span<float3> positions,
uint poly_index,
@@ -152,10 +149,10 @@ static void mesh_calc_tessellation_for_face(const Span<MLoop> mloop,
MemArena **pf_arena_p)
{
mesh_calc_tessellation_for_face_impl(
mloop, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr);
corner_verts, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr);
}
static void mesh_calc_tessellation_for_face_with_normal(const Span<MLoop> mloop,
static void mesh_calc_tessellation_for_face_with_normal(const Span<int> corner_verts,
const Span<MPoly> polys,
const Span<float3> positions,
uint poly_index,
@@ -164,10 +161,10 @@ static void mesh_calc_tessellation_for_face_with_normal(const Span<MLoop> mloop,
const float normal_precalc[3])
{
mesh_calc_tessellation_for_face_impl(
mloop, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc);
corner_verts, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc);
}
static void mesh_recalc_looptri__single_threaded(const Span<MLoop> mloop,
static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
const Span<MPoly> polys,
const Span<float3> positions,
int totloop,
@@ -181,7 +178,7 @@ static void mesh_recalc_looptri__single_threaded(const Span<MLoop> mloop,
if (poly_normals != nullptr) {
for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) {
mesh_calc_tessellation_for_face_with_normal(mloop,
mesh_calc_tessellation_for_face_with_normal(corner_verts,
polys,
positions,
poly_index,
@@ -194,7 +191,7 @@ static void mesh_recalc_looptri__single_threaded(const Span<MLoop> mloop,
else {
for (uint poly_index = 0; poly_index < uint(totpoly); poly_index++, poly++) {
mesh_calc_tessellation_for_face(
mloop, polys, positions, poly_index, &mlooptri[tri_index], &pf_arena);
corner_verts, polys, positions, poly_index, &mlooptri[tri_index], &pf_arena);
tri_index += uint(poly->totloop - 2);
}
}
@@ -208,7 +205,7 @@ static void mesh_recalc_looptri__single_threaded(const Span<MLoop> mloop,
}
struct TessellationUserData {
Span<MLoop> mloop;
Span<int> corner_verts;
Span<MPoly> polys;
Span<float3> positions;
@@ -230,7 +227,7 @@ static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata,
const TessellationUserData *data = static_cast<const TessellationUserData *>(userdata);
TessellationUserTLS *tls_data = static_cast<TessellationUserTLS *>(tls->userdata_chunk);
const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart);
mesh_calc_tessellation_for_face_impl(data->mloop,
mesh_calc_tessellation_for_face_impl(data->corner_verts,
data->polys,
data->positions,
uint(index),
@@ -247,7 +244,7 @@ static void mesh_calc_tessellation_for_face_with_normal_fn(void *__restrict user
const TessellationUserData *data = static_cast<const TessellationUserData *>(userdata);
TessellationUserTLS *tls_data = static_cast<TessellationUserTLS *>(tls->userdata_chunk);
const int tri_index = poly_to_tri_count(index, data->polys[index].loopstart);
mesh_calc_tessellation_for_face_impl(data->mloop,
mesh_calc_tessellation_for_face_impl(data->corner_verts,
data->polys,
data->positions,
uint(index),
@@ -268,15 +265,15 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*use
static void looptris_calc_all(const Span<float3> positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris)
{
if (loops.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
mesh_recalc_looptri__single_threaded(loops,
if (corner_verts.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
mesh_recalc_looptri__single_threaded(corner_verts,
polys,
positions,
int(loops.size()),
int(corner_verts.size()),
int(polys.size()),
looptris.data(),
reinterpret_cast<const float(*)[3]>(poly_normals.data()));
@@ -286,7 +283,7 @@ static void looptris_calc_all(const Span<float3> positions,
struct TessellationUserData data {
};
data.mloop = loops;
data.corner_verts = corner_verts;
data.polys = polys;
data.positions = positions;
data.mlooptri = looptris;
@@ -310,25 +307,25 @@ static void looptris_calc_all(const Span<float3> positions,
void looptris_calc(const Span<float3> vert_positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
MutableSpan<MLoopTri> looptris)
{
looptris_calc_all(vert_positions, polys, loops, {}, looptris);
looptris_calc_all(vert_positions, polys, corner_verts, {}, looptris);
}
void looptris_calc_with_normals(const Span<float3> vert_positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris)
{
BLI_assert(!poly_normals.is_empty() || polys.is_empty());
looptris_calc_all(vert_positions, polys, loops, poly_normals, looptris);
looptris_calc_all(vert_positions, polys, corner_verts, poly_normals, looptris);
}
} // namespace blender::bke::mesh
void BKE_mesh_recalc_looptri(const MLoop *mloop,
void BKE_mesh_recalc_looptri(const int *corner_verts,
const MPoly *polys,
const float (*vert_positions)[3],
int totvert,
@@ -339,7 +336,7 @@ void BKE_mesh_recalc_looptri(const MLoop *mloop,
blender::bke::mesh::looptris_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions), totvert},
{polys, totpoly},
{mloop, totloop},
{corner_verts, totloop},
{mlooptri, poly_to_tri_count(totpoly, totloop)});
}
@@ -216,7 +216,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
uint totedge,
MFace *mfaces,
uint totface,
MLoop *mloops,
int *corner_verts,
int *corner_edges,
uint totloop,
MPoly *polys,
uint totpoly,
@@ -233,9 +234,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
(void)0
#define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)
#define REMOVE_LOOP_TAG(_ml) \
#define REMOVE_LOOP_TAG(corner) \
{ \
_ml->e = INVALID_LOOP_EDGE_MARKER; \
corner_edges[corner] = INVALID_LOOP_EDGE_MARKER; \
free_flag.polyloops = do_fixes; \
} \
(void)0
@@ -251,7 +252,6 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
blender::MutableVArraySpan<int> material_indices_span(material_indices.varray);
MEdge *edge;
MLoop *ml;
uint i, j;
int *v;
@@ -575,27 +575,29 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
/* Ideally we would only have to do that once on all vertices
* before we start checking each poly, but several polys can use same vert,
* so we have to ensure here all verts of current poly are cleared. */
for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++) {
if (ml->v < totvert) {
BLI_BITMAP_DISABLE(vert_tag, ml->v);
for (j = 0; j < poly.totloop; j++) {
const int vert = corner_verts[sp->loopstart + j];
if (vert < totvert) {
BLI_BITMAP_DISABLE(vert_tag, vert);
}
}
/* Test all poly's loops' vert idx. */
for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++, v++) {
if (ml->v >= totvert) {
for (j = 0; j < poly.totloop; j++, v++) {
const int vert = corner_verts[sp->loopstart + j];
if (vert >= totvert) {
/* Invalid vert idx. */
PRINT_ERR("\tLoop %u has invalid vert reference (%u)", sp->loopstart + j, ml->v);
PRINT_ERR("\tLoop %u has invalid vert reference (%d)", sp->loopstart + j, vert);
sp->invalid = true;
}
else if (BLI_BITMAP_TEST(vert_tag, ml->v)) {
else if (BLI_BITMAP_TEST(vert_tag, vert)) {
PRINT_ERR("\tPoly %u has duplicated vert reference at corner (%u)", uint(i), j);
sp->invalid = true;
}
else {
BLI_BITMAP_ENABLE(vert_tag, ml->v);
BLI_BITMAP_ENABLE(vert_tag, vert);
}
*v = ml->v;
*v = vert;
}
if (sp->invalid) {
@@ -604,9 +606,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
/* Test all poly's loops. */
for (j = 0, ml = &mloops[sp->loopstart]; j < poly.totloop; j++, ml++) {
v1 = ml->v;
v2 = mloops[sp->loopstart + (j + 1) % poly.totloop].v;
for (j = 0; j < poly.totloop; j++) {
const int corner = sp->loopstart + j;
const int vert = corner_verts[corner];
const int edge_i = corner_edges[corner];
v1 = vert;
v2 = corner_verts[sp->loopstart + (j + 1) % poly.totloop];
if (!BLI_edgehash_haskey(edge_hash, v1, v2)) {
/* Edge not existing. */
PRINT_ERR("\tPoly %u needs missing edge (%d, %d)", sp->index, v1, v2);
@@ -617,44 +622,44 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
sp->invalid = true;
}
}
else if (ml->e >= totedge) {
else if (edge_i >= totedge) {
/* Invalid edge idx.
* We already know from previous text that a valid edge exists, use it (if allowed)! */
if (do_fixes) {
int prev_e = ml->e;
ml->e = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2));
int prev_e = edge_i;
corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2));
fix_flag.loops_edge = true;
PRINT_ERR("\tLoop %u has invalid edge reference (%d), fixed using edge %u",
sp->loopstart + j,
PRINT_ERR("\tLoop %d has invalid edge reference (%d), fixed using edge %d",
corner,
prev_e,
ml->e);
corner_edges[corner]);
}
else {
PRINT_ERR("\tLoop %u has invalid edge reference (%u)", sp->loopstart + j, ml->e);
PRINT_ERR("\tLoop %d has invalid edge reference (%d)", corner, edge_i);
sp->invalid = true;
}
}
else {
edge = &edges[ml->e];
edge = &edges[edge_i];
if (IS_REMOVED_EDGE(edge) ||
!((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1))) {
/* The pointed edge is invalid (tagged as removed, or vert idx mismatch),
* and we already know from previous test that a valid one exists,
* use it (if allowed)! */
if (do_fixes) {
int prev_e = ml->e;
ml->e = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2));
int prev_e = edge_i;
corner_edges[corner] = POINTER_AS_INT(BLI_edgehash_lookup(edge_hash, v1, v2));
fix_flag.loops_edge = true;
PRINT_ERR(
"\tPoly %u has invalid edge reference (%d, is_removed: %d), fixed using edge "
"%u",
"%d",
sp->index,
prev_e,
IS_REMOVED_EDGE(edge),
ml->e);
corner_edges[corner]);
}
else {
PRINT_ERR("\tPoly %u has invalid edge reference (%u)", sp->index, ml->e);
PRINT_ERR("\tPoly %u has invalid edge reference (%d)", sp->index, edge_i);
sp->invalid = true;
}
}
@@ -733,10 +738,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
else {
/* Unused loops. */
if (prev_end < sp->loopstart) {
for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) {
int corner;
for (j = prev_end, corner = prev_end; j < sp->loopstart; j++, corner++) {
PRINT_ERR("\tLoop %u is unused.", j);
if (do_fixes) {
REMOVE_LOOP_TAG(ml);
REMOVE_LOOP_TAG(corner);
}
}
prev_end = sp->loopstart + sp->numverts;
@@ -766,10 +772,11 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
/* We may have some remaining unused loops to get rid of! */
if (prev_end < totloop) {
for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) {
int corner;
for (j = prev_end, corner = prev_end; j < totloop; j++, corner++) {
PRINT_ERR("\tLoop %u is unused.", j);
if (do_fixes) {
REMOVE_LOOP_TAG(ml);
REMOVE_LOOP_TAG(corner);
}
}
}
@@ -1043,7 +1050,8 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_
MutableSpan<float3> positions = me->vert_positions_for_write();
MutableSpan<MEdge> edges = me->edges_for_write();
MutableSpan<MPoly> polys = me->polys_for_write();
MutableSpan<MLoop> loops = me->loops_for_write();
MutableSpan<int> corner_verts = me->corner_verts_for_write();
MutableSpan<int> corner_edges = me->corner_edges_for_write();
BKE_mesh_validate_arrays(
me,
@@ -1053,8 +1061,9 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_
edges.size(),
(MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface),
me->totface,
loops.data(),
loops.size(),
corner_verts.data(),
corner_edges.data(),
corner_verts.size(),
polys.data(),
polys.size(),
me->deform_verts_for_write().data(),
@@ -1095,7 +1104,8 @@ bool BKE_mesh_is_valid(Mesh *me)
MutableSpan<float3> positions = me->vert_positions_for_write();
MutableSpan<MEdge> edges = me->edges_for_write();
MutableSpan<MPoly> polys = me->polys_for_write();
MutableSpan<MLoop> loops = me->loops_for_write();
MutableSpan<int> corner_verts = me->corner_verts_for_write();
MutableSpan<int> corner_edges = me->corner_edges_for_write();
is_valid &= BKE_mesh_validate_arrays(
me,
@@ -1105,8 +1115,9 @@ bool BKE_mesh_is_valid(Mesh *me)
edges.size(),
(MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface),
me->totface,
loops.data(),
loops.size(),
corner_verts.data(),
corner_edges.data(),
corner_verts.size(),
polys.data(),
polys.size(),
me->deform_verts_for_write().data(),
@@ -1175,9 +1186,8 @@ void BKE_mesh_strip_loose_faces(Mesh *me)
void mesh_strip_polysloops(Mesh *me)
{
MutableSpan<MPoly> polys = me->polys_for_write();
MutableSpan<MLoop> loops = me->loops_for_write();
MutableSpan<int> corner_edges = me->corner_edges_for_write();
MLoop *l;
int a, b;
/* New loops idx! */
int *new_idx = (int *)MEM_mallocN(sizeof(int) * me->totloop, __func__);
@@ -1192,14 +1202,11 @@ void mesh_strip_polysloops(Mesh *me)
invalid = true;
}
else {
l = &loops[i];
i = stop - i;
/* If one of the poly's loops is invalid, the whole poly is invalid! */
for (; i--; l++) {
if (l->e == INVALID_LOOP_EDGE_MARKER) {
invalid = true;
break;
}
if (corner_edges.slice(poly.loopstart, poly.totloop)
.as_span()
.contains(INVALID_LOOP_EDGE_MARKER)) {
invalid = true;
}
}
@@ -1217,10 +1224,10 @@ void mesh_strip_polysloops(Mesh *me)
}
/* And now, get rid of invalid loops. */
for (a = b = 0, l = loops.data(); a < me->totloop; a++, l++) {
if (l->e != INVALID_LOOP_EDGE_MARKER) {
int corner = 0;
for (a = b = 0; a < me->totloop; a++, corner++) {
if (corner_edges[corner] != INVALID_LOOP_EDGE_MARKER) {
if (a != b) {
memcpy(&loops[b], l, sizeof(loops[b]));
CustomData_copy_data(&me->ldata, &me->ldata, a, b, 1);
}
new_idx[a] = b;
@@ -1274,9 +1281,9 @@ void mesh_strip_edges(Mesh *me)
/* And now, update loops' edge indices. */
/* XXX We hope no loop was pointing to a striped edge!
* Else, its e will be set to INVALID_LOOP_EDGE_MARKER :/ */
MutableSpan<MLoop> loops = me->loops_for_write();
for (MLoop &loop : loops) {
loop.e = new_idx[loop.e];
MutableSpan<int> corner_edges = me->corner_edges_for_write();
for (const int i : corner_edges.index_range()) {
corner_edges[i] = new_idx[corner_edges[i]];
}
MEM_freeN(new_idx);
@@ -7,7 +7,7 @@
* output of a modified mesh.
*
* This API handles the case when the modifier stack outputs a mesh which does not have
* #Mesh data (#MPoly, #MLoop, #MEdge, etc).
* #Mesh data (#MPoly, corner verts, corner edges, #MEdge, etc).
* Currently this is used so the resulting mesh can have #BMEditMesh data,
* postponing the converting until it's needed or avoiding conversion entirely
* which can be an expensive operation.
+1 -2
View File
@@ -673,7 +673,6 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
if (mdisps && levels > 0) {
if (lvl > 0) {
// MLoop *ml = me->mloop; /*UNUSED*/
int nsize = multires_side_tot[lvl];
int hsize = multires_side_tot[mmd->totlvl];
int j;
@@ -1629,7 +1628,7 @@ int mdisp_rot_face_to_crn(
float mindist = FLT_MAX;
for (i = 0; i < poly->totloop; i++) {
float len = len_v3v3(nullptr, positions[mloop[poly->loopstart + i].v]);
float len = len_v3v3(nullptr, positions[corner_verts[poly->loopstart + i]]);
if (len < mindist) {
mindist = len;
minS = i;
@@ -17,7 +17,6 @@ struct GridPaintMask;
struct MDisps;
struct MEdge;
struct Mesh;
struct MLoop;
struct MPoly;
struct MultiresModifierData;
struct Object;
@@ -37,7 +36,8 @@ struct MultiresReshapeContext {
const float (*base_positions)[3];
blender::Span<MEdge> base_edges;
blender::Span<MPoly> base_polys;
blender::Span<MLoop> base_loops;
blender::Span<int> base_corner_verts;
blender::Span<int> base_corner_edges;
/* Subdivision surface created for multires modifier.
*
@@ -34,9 +34,8 @@ void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *resh
/* Update the context in case the vertices were duplicated. */
reshape_context->base_positions = base_positions;
const blender::Span<MLoop> loops = reshape_context->base_loops;
for (const int loop_index : loops.index_range()) {
const MLoop *loop = &loops[loop_index];
const blender::Span<int> corner_verts = reshape_context->base_corner_verts;
for (const int loop_index : corner_verts.index_range()) {
GridCoord grid_coord;
grid_coord.grid_index = loop_index;
@@ -52,7 +51,7 @@ void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *resh
float D[3];
mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
add_v3_v3v3(base_positions[loop->v], P, D);
add_v3_v3v3(base_positions[corner_verts[loop_index]], P, D);
}
}
@@ -76,7 +75,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
BKE_mesh_vert_poly_map_create(&pmap,
&pmap_mem,
reshape_context->base_polys.data(),
reshape_context->base_loops.data(),
reshape_context->base_corner_verts.data(),
base_mesh->totvert,
base_mesh->totpoly,
base_mesh->totloop);
@@ -102,7 +101,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
/* This double counts, not sure if that's bad or good. */
for (int k = 0; k < poly.totloop; k++) {
const int vndx = reshape_context->base_loops[poly.loopstart + k].v;
const int vndx = reshape_context->base_corner_verts[poly.loopstart + k];
if (vndx != i) {
add_v3_v3(center, origco[vndx]);
tot++;
@@ -116,13 +115,13 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]];
/* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */
blender::Array<MLoop> fake_loops(poly.totloop);
blender::Array<int> poly_verts(poly.totloop);
blender::Array<blender::float3> fake_co(poly.totloop);
for (int k = 0; k < poly.totloop; k++) {
const int vndx = reshape_context->base_loops[poly.loopstart + k].v;
const int vndx = reshape_context->base_corner_verts[poly.loopstart + k];
fake_loops[k].v = k;
poly_verts[k] = k;
if (vndx == i) {
copy_v3_v3(fake_co[k], center);
@@ -132,7 +131,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
}
}
const blender::float3 no = blender::bke::mesh::poly_normal_calc(fake_co, fake_loops);
const blender::float3 no = blender::bke::mesh::poly_normal_calc(fake_co, poly_verts);
add_v3_v3(avg_no, no);
}
normalize_v3(avg_no);
@@ -850,7 +850,7 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
const Mesh *base_mesh = reshape_context->base_mesh;
const blender::Span<MPoly> base_polys = reshape_context->base_polys;
const blender::Span<MLoop> base_loops = reshape_context->base_loops;
const blender::Span<int> base_corner_edges = reshape_context->base_corner_edges;
reshape_smooth_context->non_loose_base_edge_map = BLI_BITMAP_NEW(base_mesh->totedge,
"non_loose_base_edge_map");
@@ -858,12 +858,11 @@ static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshap
int num_used_edges = 0;
for (const int poly_index : base_polys.index_range()) {
const MPoly &base_poly = base_polys[poly_index];
for (int corner = 0; corner < base_poly.totloop; corner++) {
const MLoop *loop = &base_loops[base_poly.loopstart + corner];
if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, loop->e)) {
BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, loop->e);
for (const int edge : base_corner_edges.slice(base_poly.loopstart, base_poly.totloop)) {
if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, edge)) {
BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, edge);
const float crease = get_effective_crease(reshape_smooth_context, loop->e);
const float crease = get_effective_crease(reshape_smooth_context, edge);
if (crease > 0.0f) {
++num_used_edges;
}
@@ -32,14 +32,14 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
using namespace blender::bke;
const Span<float3> positions = mesh->vert_positions();
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
MDisps *mdisps = static_cast<MDisps *>(
CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop));
for (const int p : polys.index_range()) {
const MPoly &poly = polys[p];
const float3 poly_center = mesh::poly_center_calc(positions,
loops.slice(poly.loopstart, poly.totloop));
const float3 poly_center = mesh::poly_center_calc(
positions, corner_verts.slice(poly.loopstart, poly.totloop));
for (int l = 0; l < poly.totloop; l++) {
const int loop_index = poly.loopstart + l;
@@ -50,14 +50,14 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly.totloop - 1;
int next_loop_index = l + 1 < poly.totloop ? loop_index + 1 : poly.loopstart;
const MLoop *loop = &loops[loop_index];
const MLoop *loop_next = &loops[next_loop_index];
const MLoop *loop_prev = &loops[prev_loop_index];
const int vert = corner_verts[loop_index];
const int vert_next = corner_verts[next_loop_index];
const int vert_prev = corner_verts[prev_loop_index];
copy_v3_v3(disps[0], poly_center);
mid_v3_v3v3(disps[1], positions[loop->v], positions[loop_next->v]);
mid_v3_v3v3(disps[2], positions[loop->v], positions[loop_prev->v]);
copy_v3_v3(disps[3], positions[loop->v]);
mid_v3_v3v3(disps[1], positions[vert], positions[vert_next]);
mid_v3_v3v3(disps[2], positions[vert], positions[vert_prev]);
copy_v3_v3(disps[3], positions[vert]);
}
}
}
@@ -158,7 +158,8 @@ bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *resh
reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh);
reshape_context->base_edges = base_mesh->edges();
reshape_context->base_polys = base_mesh->polys();
reshape_context->base_loops = base_mesh->loops();
reshape_context->base_corner_verts = base_mesh->corner_verts();
reshape_context->base_corner_edges = base_mesh->corner_edges();
reshape_context->subdiv = multires_reshape_create_subdiv(nullptr, object, mmd);
reshape_context->need_free_subdiv = true;
@@ -195,7 +196,8 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape
reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh);
reshape_context->base_edges = base_mesh->edges();
reshape_context->base_polys = base_mesh->polys();
reshape_context->base_loops = base_mesh->loops();
reshape_context->base_corner_verts = base_mesh->corner_verts();
reshape_context->base_corner_edges = base_mesh->corner_edges();
reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd);
reshape_context->need_free_subdiv = true;
@@ -229,7 +231,8 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co
reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh);
reshape_context->base_edges = base_mesh->edges();
reshape_context->base_polys = base_mesh->polys();
reshape_context->base_loops = base_mesh->loops();
reshape_context->base_corner_verts = base_mesh->corner_verts();
reshape_context->base_corner_edges = base_mesh->corner_edges();
reshape_context->subdiv = subdiv_ccg->subdiv;
reshape_context->need_free_subdiv = false;
@@ -276,7 +279,8 @@ bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape
reshape_context->base_positions = BKE_mesh_vert_positions(base_mesh);
reshape_context->base_edges = base_mesh->edges();
reshape_context->base_polys = base_mesh->polys();
reshape_context->base_loops = base_mesh->loops();
reshape_context->base_corner_verts = base_mesh->corner_verts();
reshape_context->base_corner_edges = base_mesh->corner_edges();
reshape_context->cd_vertex_crease = (const float *)CustomData_get_layer(&base_mesh->edata,
CD_CREASE);
@@ -643,7 +643,7 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
{
Mesh *original_mesh = context->original_mesh;
const blender::Span<MPoly> polys = original_mesh->polys();
const blender::Span<MLoop> loops = original_mesh->loops();
const blender::Span<int> corner_verts = original_mesh->corner_verts();
const MPoly &poly = polys[BM_elem_index_get(f)];
const int corner_vertex_index = BM_elem_index_get(v);
@@ -653,8 +653,7 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
int loop_offset = 0;
for (int i = 0; i < poly.totloop; i++) {
const int loop_index = poly.loopstart + i;
const MLoop *l = &loops[loop_index];
if (l->v == corner_vertex_index) {
if (corner_verts[loop_index] == corner_vertex_index) {
loop_offset = i;
break;
}
@@ -967,22 +966,22 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
* necessary.
*/
static bool multires_unsubdivide_flip_grid_x_axis(const blender::Span<MPoly> polys,
const blender::Span<MLoop> loops,
const blender::Span<int> corner_verts,
int poly_index,
int loop,
int v_x)
{
const MPoly &poly = polys[poly_index];
const MLoop *l_first = &loops[poly.loopstart];
if ((loop == (poly.loopstart + (poly.totloop - 1))) && l_first->v == v_x) {
const int v_first = corner_verts[poly.loopstart];
if ((loop == (poly.loopstart + (poly.totloop - 1))) && v_first == v_x) {
return true;
}
int next_l_index = loop + 1;
if (next_l_index < poly.loopstart + poly.totloop) {
const MLoop *l_next = &loops[next_l_index];
if (l_next->v == v_x) {
const int v_next = corner_verts[next_l_index];
if (v_next == v_x) {
return true;
}
}
@@ -1045,7 +1044,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
&bm_base_mesh->ldata, CD_PROP_INT32, base_l_layer_index);
const blender::Span<MPoly> polys = base_mesh->polys();
const blender::Span<MLoop> loops = base_mesh->loops();
const blender::Span<int> corner_verts = base_mesh->corner_verts();
/* Main loop for extracting the grids. Iterates over the base mesh vertices. */
BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) {
@@ -1084,7 +1083,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
/* Check the orientation of the loops in case that is needed to flip the x and y axis
* when extracting the grid. */
const bool flip_grid = multires_unsubdivide_flip_grid_x_axis(
polys, loops, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
polys, corner_verts, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
/* Extract the grid for that loop. */
context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index;
@@ -1057,7 +1057,7 @@ struct FaceDupliData_Mesh {
int totface;
const MPoly *polys;
const MLoop *mloop;
const int *corner_verts;
Span<float3> vert_positions;
const float (*orco)[3];
const float2 *mloopuv;
@@ -1156,15 +1156,14 @@ static DupliObject *face_dupli_from_mesh(const DupliContext *ctx,
/* Mesh variables. */
const MPoly &poly,
const MLoop *mloopstart,
const int *poly_verts,
const Span<float3> vert_positions)
{
const int coords_len = poly.totloop;
Array<float3, 64> coords(coords_len);
const MLoop *ml = mloopstart;
for (int i = 0; i < coords_len; i++, ml++) {
coords[i] = vert_positions[ml->v];
for (int i = 0; i < coords_len; i++) {
coords[i] = vert_positions[poly_verts[i]];
}
return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords);
@@ -1207,7 +1206,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
{
FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata;
const MPoly *polys = fdd->polys;
const MLoop *mloop = fdd->mloop;
const int *corner_verts = fdd->corner_verts;
const float(*orco)[3] = fdd->orco;
const float2 *mloopuv = fdd->mloopuv;
const int totface = fdd->totface;
@@ -1222,7 +1221,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
for (const int a : blender::IndexRange(totface)) {
const MPoly &poly = polys[a];
const MLoop *loopstart = mloop + poly.loopstart;
const int *poly_verts = &corner_verts[poly.loopstart];
DupliObject *dob = face_dupli_from_mesh(fdd->params.ctx,
inst_ob,
child_imat,
@@ -1230,13 +1229,13 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
use_scale,
scale_fac,
poly,
loopstart,
poly_verts,
fdd->vert_positions);
const float w = 1.0f / float(poly.totloop);
if (orco) {
for (int j = 0; j < poly.totloop; j++) {
madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
madd_v3_v3fl(dob->orco, orco[poly_verts[j]], w);
}
}
if (mloopuv) {
@@ -1320,7 +1319,7 @@ static void make_duplis_faces(const DupliContext *ctx)
fdd.params = fdd_params;
fdd.totface = me_eval->totpoly;
fdd.polys = me_eval->polys().data();
fdd.mloop = me_eval->loops().data();
fdd.corner_verts = me_eval->corner_verts().data();
fdd.vert_positions = me_eval->vert_positions();
fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n(
&me_eval->ldata, CD_PROP_FLOAT2, uv_idx) :
@@ -1331,9 +1330,8 @@ static void make_duplis_faces(const DupliContext *ctx)
}
}
static const DupliGenerator gen_dupli_faces = {
/*type*/ OB_DUPLIFACES,
/*make_duplis*/ make_duplis_faces};
static const DupliGenerator gen_dupli_faces = {/*type*/ OB_DUPLIFACES,
/*make_duplis*/ make_duplis_faces};
/** \} */
@@ -1680,9 +1678,8 @@ static void make_duplis_particles(const DupliContext *ctx)
}
}
static const DupliGenerator gen_dupli_particles = {
/*type*/ OB_DUPLIPARTS,
/*make_duplis*/ make_duplis_particles};
static const DupliGenerator gen_dupli_particles = {/*type*/ OB_DUPLIPARTS,
/*make_duplis*/ make_duplis_particles};
/** \} */
+15 -15
View File
@@ -1697,7 +1697,7 @@ static void sculpt_update_object(
* and tools use the Face Sets data from the base mesh when Multires is active. */
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
ss->polys = me->polys().data();
ss->mloop = me->loops().data();
ss->corner_verts = me->corner_verts().data();
}
else {
ss->totvert = me->totvert;
@@ -1705,7 +1705,7 @@ static void sculpt_update_object(
ss->totfaces = me->totpoly;
ss->vert_positions = BKE_mesh_vert_positions_for_write(me);
ss->polys = me->polys().data();
ss->mloop = me->loops().data();
ss->corner_verts = me->corner_verts().data();
ss->multires.active = false;
ss->multires.modifier = nullptr;
ss->multires.level = 0;
@@ -1766,7 +1766,7 @@ static void sculpt_update_object(
BKE_mesh_vert_poly_map_create(&ss->pmap,
&ss->pmap_mem,
me->polys().data(),
me->loops().data(),
me->corner_verts().data(),
me->totvert,
me->totpoly,
me->totloop);
@@ -1986,7 +1986,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
{
Mesh *me = static_cast<Mesh *>(ob->data);
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
int ret = 0;
const float *paint_mask = static_cast<const float *>(
@@ -2020,22 +2020,22 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
/* mask center */
for (j = 0; j < poly.totloop; j++) {
const MLoop *l = &loops[poly.loopstart + j];
avg += paint_mask[l->v];
const int vert = corner_verts[poly.loopstart + j];
avg += paint_mask[vert];
}
avg /= float(poly.totloop);
/* fill in multires mask corner */
for (j = 0; j < poly.totloop; j++) {
GridPaintMask *gpm = &gmask[poly.loopstart + j];
const MLoop *l = &loops[poly.loopstart + j];
const MLoop *prev = ME_POLY_LOOP_PREV(loops, &poly, j);
const MLoop *next = ME_POLY_LOOP_NEXT(loops, &poly, j);
const int vert = corner_verts[poly.loopstart + j];
const int prev = ME_POLY_LOOP_PREV(&poly, j);
const int next = ME_POLY_LOOP_NEXT(&poly, j);
gpm->data[0] = avg;
gpm->data[1] = (paint_mask[l->v] + paint_mask[next->v]) * 0.5f;
gpm->data[2] = (paint_mask[l->v] + paint_mask[prev->v]) * 0.5f;
gpm->data[3] = paint_mask[l->v];
gpm->data[1] = (paint_mask[vert] + paint_mask[corner_verts[next]]) * 0.5f;
gpm->data[2] = (paint_mask[vert] + paint_mask[corner_verts[prev]]) * 0.5f;
gpm->data[3] = paint_mask[vert];
}
}
}
@@ -2183,17 +2183,17 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
MutableSpan<float3> positions = me->vert_positions_for_write();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
const Span<int> corner_verts = me->corner_verts();
MLoopTri *looptri = static_cast<MLoopTri *>(
MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__));
blender::bke::mesh::looptris_calc(positions, polys, loops, {looptri, looptris_num});
blender::bke::mesh::looptris_calc(positions, polys, corner_verts, {looptri, looptris_num});
BKE_pbvh_build_mesh(pbvh,
me,
polys.data(),
loops.data(),
corner_verts.data(),
reinterpret_cast<float(*)[3]>(positions.data()),
me->totvert,
&me->vdata,
+28 -27
View File
@@ -336,7 +336,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]];
for (int j = 0; j < 3; j++) {
face_vert_indices[i][j] = map_insert_vert(
pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v);
pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->corner_verts[lt->tri[j]]);
}
if (has_visible == false) {
@@ -688,7 +688,8 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
args->face_sets_color_default = pbvh->face_sets_color_default;
args->face_sets_color_seed = pbvh->face_sets_color_seed;
args->vert_positions = pbvh->vert_positions;
args->mloop = pbvh->mloop;
args->corner_verts = {pbvh->corner_verts, pbvh->mesh->totloop};
args->corner_edges = pbvh->mesh ? pbvh->mesh->corner_edges() : blender::Span<int>();
args->polys = pbvh->polys;
args->mlooptri = pbvh->looptri;
@@ -823,7 +824,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
void BKE_pbvh_build_mesh(PBVH *pbvh,
Mesh *mesh,
const MPoly *polys,
const MLoop *mloop,
const int *corner_verts,
float (*vert_positions)[3],
int totvert,
CustomData *vdata,
@@ -842,7 +843,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
pbvh->material_indices = static_cast<const int *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index"));
pbvh->mloop = mloop;
pbvh->corner_verts = corner_verts;
pbvh->looptri = looptri;
pbvh->vert_positions = vert_positions;
/* Make sure cached normals start out calculated. */
@@ -884,7 +885,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
BB_reset((BB *)bbc);
for (int j = 0; j < sides; j++) {
BB_expand((BB *)bbc, vert_positions[pbvh->mloop[lt->tri[j]].v]);
BB_expand((BB *)bbc, vert_positions[pbvh->corner_verts[lt->tri[j]]]);
}
BBC_update_centroid(bbc);
@@ -955,7 +956,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->pdata = &me->pdata;
pbvh->polys = me->polys().data();
pbvh->mloop = me->loops().data();
pbvh->corner_verts = me->corner_verts().data();
/* We also need the base mesh for PBVH draw. */
pbvh->mesh = me;
@@ -1417,10 +1418,10 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
for (int i = 0; i < totface; i++) {
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const uint vtri[3] = {
pbvh->mloop[lt->tri[0]].v,
pbvh->mloop[lt->tri[1]].v,
pbvh->mloop[lt->tri[2]].v,
const int vtri[3] = {
pbvh->corner_verts[lt->tri[0]],
pbvh->corner_verts[lt->tri[1]],
pbvh->corner_verts[lt->tri[2]],
};
const int sides = 3;
@@ -1429,7 +1430,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const MPoly &poly = pbvh->polys[lt->poly];
fn = blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const blender::float3 *>(pbvh->vert_positions), pbvh->totvert},
{&pbvh->mloop[poly.loopstart], poly.totloop});
{&pbvh->corner_verts[poly.loopstart], poly.totloop});
mpoly_prev = lt->poly;
}
@@ -2206,7 +2207,7 @@ void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, PBVHVertRef vertex)
void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
const MLoop **r_loops)
const int **r_corner_verts)
{
BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES);
@@ -2214,8 +2215,8 @@ void BKE_pbvh_node_get_loops(PBVH *pbvh,
*r_loop_indices = node->loop_indices;
}
if (r_loops) {
*r_loops = pbvh->mloop;
if (r_corner_verts) {
*r_corner_verts = pbvh->corner_verts;
}
}
@@ -2548,7 +2549,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
float *r_face_normal)
{
const float(*positions)[3] = pbvh->vert_positions;
const MLoop *mloop = pbvh->mloop;
const int *corner_verts = pbvh->corner_verts;
const int *faces = node->prim_indices;
int totface = node->totprim;
bool hit = false;
@@ -2571,9 +2572,9 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
}
else {
/* intersect with current coordinates */
co[0] = positions[mloop[lt->tri[0]].v];
co[1] = positions[mloop[lt->tri[1]].v];
co[2] = positions[mloop[lt->tri[2]].v];
co[0] = positions[corner_verts[lt->tri[0]]];
co[1] = positions[corner_verts[lt->tri[1]]];
co[2] = positions[corner_verts[lt->tri[2]]];
}
if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) {
@@ -2593,7 +2594,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
if (j == 0 ||
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 = mloop[lt->tri[j]].v;
r_active_vertex->i = corner_verts[lt->tri[j]];
*r_active_face_index = lt->poly;
}
}
@@ -2858,7 +2859,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
float *dist_sq)
{
const float(*positions)[3] = pbvh->vert_positions;
const MLoop *mloop = pbvh->mloop;
const int *corner_verts = pbvh->corner_verts;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
@@ -2885,9 +2886,9 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
/* intersect with current coordinates */
hit |= ray_face_nearest_tri(ray_start,
ray_normal,
positions[mloop[lt->tri[0]].v],
positions[mloop[lt->tri[1]].v],
positions[mloop[lt->tri[2]].v],
positions[corner_verts[lt->tri[0]]],
positions[corner_verts[lt->tri[1]]],
positions[corner_verts[lt->tri[2]]],
depth,
dist_sq);
}
@@ -3740,16 +3741,16 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
pbvh_face_iter_verts_reserve(fd, poly.totloop);
const MLoop *ml = fd->mloop_ + poly.loopstart;
const int *poly_verts = &fd->corner_verts_[poly.loopstart];
const int grid_area = fd->subdiv_key_.grid_area;
for (int i = 0; i < poly.totloop; i++, ml++) {
for (int i = 0; i < poly.totloop; i++) {
if (fd->pbvh_type_ == PBVH_GRIDS) {
/* Grid corners. */
fd->verts[i].i = (poly.loopstart + i) * grid_area + grid_area - 1;
}
else {
fd->verts[i].i = ml->v;
fd->verts[i].i = poly_verts[i];
}
}
break;
@@ -3778,7 +3779,7 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd)
ATTR_FALLTHROUGH;
case PBVH_FACES:
fd->polys_ = pbvh->polys;
fd->mloop_ = pbvh->mloop;
fd->corner_verts_ = pbvh->corner_verts;
fd->looptri_ = pbvh->looptri;
fd->hide_poly_ = pbvh->hide_poly;
fd->face_sets_ = pbvh->face_sets;
@@ -97,12 +97,12 @@ static void pbvh_vertex_color_get(const PBVH &pbvh, PBVHVertRef vertex, float r_
const MPoly &poly = pbvh.polys[i_poly];
Span<T> colors{static_cast<const T *>(pbvh.color_layer->data) + poly.loopstart,
poly.totloop};
Span<MLoop> loops{pbvh.mloop + poly.loopstart, poly.totloop};
Span<int> poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop};
for (const int i_loop : IndexRange(poly.totloop)) {
if (loops[i_loop].v == index) {
for (const int i : poly_verts.index_range()) {
if (poly_verts[i] == index) {
float temp[4];
to_float(colors[i_loop], temp);
to_float(colors[i], temp);
add_v4_v4(r_color, temp);
count++;
@@ -131,11 +131,11 @@ static void pbvh_vertex_color_set(PBVH &pbvh, PBVHVertRef vertex, const float co
const MPoly &poly = pbvh.polys[i_poly];
MutableSpan<T> colors{static_cast<T *>(pbvh.color_layer->data) + poly.loopstart,
poly.totloop};
Span<MLoop> loops{pbvh.mloop + poly.loopstart, poly.totloop};
Span<int> poly_verts{pbvh.corner_verts + poly.loopstart, poly.totloop};
for (const int i_loop : IndexRange(poly.totloop)) {
if (loops[i_loop].v == index) {
from_float(color, colors[i_loop]);
for (const int i : poly_verts.index_range()) {
if (poly_verts[i] == index) {
from_float(color, colors[i]);
}
}
}
@@ -7,7 +7,6 @@
*/
struct PBVHGPUFormat;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct MeshElemMap;
@@ -71,7 +70,7 @@ struct PBVHNode {
const int *vert_indices;
unsigned int uniq_verts, face_verts;
/* Array of indices into the Mesh's MLoop array.
/* Array of indices into the Mesh's corner array.
* PBVH_FACES only.
*/
int *loop_indices;
@@ -161,7 +160,7 @@ struct PBVH {
bool *hide_poly;
/** Material indices. Only valid for polygon meshes. */
const int *material_indices;
const MLoop *mloop;
const int *corner_verts;
const MLoopTri *looptri;
CustomData *vdata;
CustomData *ldata;
@@ -409,9 +409,9 @@ static void update_geom_primitives(PBVH &pbvh, const uv_islands::MeshData &mesh_
PBVHData &pbvh_data = BKE_pbvh_pixels_data_get(pbvh);
pbvh_data.clear_data();
for (const MLoopTri &looptri : mesh_data.looptris) {
pbvh_data.geom_primitives.append(int3(mesh_data.loops[looptri.tri[0]].v,
mesh_data.loops[looptri.tri[1]].v,
mesh_data.loops[looptri.tri[2]].v));
pbvh_data.geom_primitives.append(int3(mesh_data.corner_verts[looptri.tri[0]],
mesh_data.corner_verts[looptri.tri[1]],
mesh_data.corner_verts[looptri.tri[2]]));
}
}
@@ -672,7 +672,7 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
uv_islands::MeshData mesh_data(
{pbvh->looptri, pbvh->totprim},
{pbvh->mloop, mesh->totloop},
{pbvh->corner_verts, mesh->totloop},
uv_map,
{static_cast<blender::float3 *>(static_cast<void *>(pbvh->vert_positions)), pbvh->totvert});
uv_islands::UVIslands islands(mesh_data);
@@ -157,9 +157,9 @@ class NonManifoldUVEdges : public Vector<Edge<CoordSpace::UV>> {
int vertex_i)
{
for (int i = 0; i < 3; i++) {
int loop_i = loop_tri.tri[i];
const MLoop &loop = mesh_data.loops[loop_i];
if (loop.v == vertex_i) {
const int loop_i = loop_tri.tri[i];
const int vert = mesh_data.corner_verts[loop_i];
if (vert == vertex_i) {
return mesh_data.uv_map[loop_i];
}
}
@@ -38,17 +38,17 @@ static int primitive_get_other_uv_vertex(const MeshData &mesh_data,
const int v1,
const int v2)
{
const Span<MLoop> mesh_loops = mesh_data.loops;
const Span<int> corner_verts = mesh_data.corner_verts;
BLI_assert(ELEM(v1,
mesh_loops[looptri.tri[0]].v,
mesh_loops[looptri.tri[1]].v,
mesh_loops[looptri.tri[2]].v));
corner_verts[looptri.tri[0]],
corner_verts[looptri.tri[1]],
corner_verts[looptri.tri[2]]));
BLI_assert(ELEM(v2,
mesh_loops[looptri.tri[0]].v,
mesh_loops[looptri.tri[1]].v,
mesh_loops[looptri.tri[2]].v));
corner_verts[looptri.tri[0]],
corner_verts[looptri.tri[1]],
corner_verts[looptri.tri[2]]));
for (const int loop : looptri.tri) {
const int vert = mesh_loops[loop].v;
const int vert = corner_verts[loop];
if (!ELEM(vert, v1, v2)) {
return vert;
}
@@ -74,7 +74,7 @@ static bool primitive_has_shared_uv_edge(const Span<float2> uv_map,
static int get_uv_loop(const MeshData &mesh_data, const MLoopTri &looptri, const int vert)
{
for (const int loop : looptri.tri) {
if (mesh_data.loops[loop].v == vert) {
if (mesh_data.corner_verts[loop] == vert) {
return loop;
}
}
@@ -106,8 +106,8 @@ static void mesh_data_init_edges(MeshData &mesh_data)
const MLoopTri &tri = mesh_data.looptris[i];
Vector<int, 3> edges;
for (int j = 0; j < 3; j++) {
int v1 = mesh_data.loops[tri.tri[j]].v;
int v2 = mesh_data.loops[tri.tri[(j + 1) % 3]].v;
int v1 = mesh_data.corner_verts[tri.tri[j]];
int v2 = mesh_data.corner_verts[tri.tri[(j + 1) % 3]];
void **edge_index_ptr;
int64_t edge_index;
@@ -199,11 +199,11 @@ static void mesh_data_init(MeshData &mesh_data)
}
MeshData::MeshData(const Span<MLoopTri> looptris,
const Span<MLoop> loops,
const Span<int> corner_verts,
const Span<float2> uv_map,
const Span<float3> vert_positions)
: looptris(looptris),
loops(loops),
corner_verts(corner_verts),
uv_map(uv_map),
vert_positions(vert_positions),
vert_to_edge_map(vert_positions.size()),
@@ -231,7 +231,7 @@ UVVertex::UVVertex()
}
UVVertex::UVVertex(const MeshData &mesh_data, const int loop)
: vertex(mesh_data.loops[loop].v), uv(mesh_data.uv_map[loop])
: vertex(mesh_data.corner_verts[loop]), uv(mesh_data.uv_map[loop])
{
uv_vertex_init_flags(*this);
}
@@ -520,18 +520,18 @@ struct FanSegment {
flags.found = false;
/* Reorder so the first edge starts with the given vertex. */
if (mesh_data.loops[primitive->tri[1]].v == vertex) {
if (mesh_data.corner_verts[primitive->tri[1]] == vertex) {
vert_order[0] = 1;
vert_order[1] = 2;
vert_order[2] = 0;
}
else if (mesh_data.loops[primitive->tri[2]].v == vertex) {
else if (mesh_data.corner_verts[primitive->tri[2]] == vertex) {
vert_order[0] = 2;
vert_order[1] = 0;
vert_order[2] = 1;
}
else {
BLI_assert(mesh_data.loops[primitive->tri[0]].v == vertex);
BLI_assert(mesh_data.corner_verts[primitive->tri[0]] == vertex);
vert_order[0] = 0;
vert_order[1] = 1;
vert_order[2] = 2;
@@ -542,9 +542,9 @@ struct FanSegment {
{
std::stringstream ss;
ss << "# p:" << primitive->poly;
ss << " v1:" << mesh_data.loops[primitive->tri[vert_order[0]]].v;
ss << " v2:" << mesh_data.loops[primitive->tri[vert_order[1]]].v;
ss << " v3:" << mesh_data.loops[primitive->tri[vert_order[2]]].v;
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]]];
ss << " uv1:" << uvs[0];
ss << " uv2:" << uvs[1];
ss << " uv3:" << uvs[2];
@@ -633,9 +633,9 @@ struct Fan {
void init_uv_coordinates(const MeshData &mesh_data, UVVertex &uv_vertex)
{
for (FanSegment &fan_edge : segments) {
int other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[0]]].v;
int other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[0]]];
if (other_v == uv_vertex.vertex) {
other_v = mesh_data.loops[fan_edge.primitive->tri[fan_edge.vert_order[1]]].v;
other_v = mesh_data.corner_verts[fan_edge.primitive->tri[fan_edge.vert_order[1]]];
}
for (UVEdge *edge : uv_vertex.uv_edges) {
@@ -663,7 +663,7 @@ struct Fan {
bool contains_vertex_on_outside(const MeshData &mesh_data, const int vertex_index) const
{
for (const FanSegment &segment : segments) {
int v2 = mesh_data.loops[segment.primitive->tri[segment.vert_order[1]]].v;
int v2 = mesh_data.corner_verts[segment.primitive->tri[segment.vert_order[1]]];
if (vertex_index == v2) {
return true;
}
@@ -680,8 +680,8 @@ struct Fan {
{
int current_vert = from_vertex;
for (FanSegment *segment : path) {
int v1 = mesh_data.loops[segment->primitive->tri[segment->vert_order[1]]].v;
int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[2]]].v;
int v1 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[1]]];
int v2 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[2]]];
if (!ELEM(current_vert, v1, v2)) {
return false;
}
@@ -711,7 +711,8 @@ struct Fan {
int index = 0;
while (true) {
FanSegment *segment = edge_order[index];
int v2 = mesh_data.loops[segment->primitive->tri[segment->vert_order[from_vert_order]]].v;
int v2 =
mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[from_vert_order]]];
if (v2 == from_vertex) {
break;
}
@@ -722,7 +723,7 @@ struct Fan {
FanSegment *segment = edge_order[index];
result.append(segment);
int v3 = mesh_data.loops[segment->primitive->tri[segment->vert_order[to_vert_order]]].v;
int v3 = mesh_data.corner_verts[segment->primitive->tri[segment->vert_order[to_vert_order]]];
if (v3 == to_vertex) {
break;
}
@@ -817,12 +818,12 @@ static void add_uv_primitive_shared_uv_edge(const MeshData &mesh_data,
const int loop_1 = get_uv_loop(mesh_data, looptri, connected_vert_1->vertex);
vert_template.uv = connected_vert_1->uv;
vert_template.vertex = mesh_data.loops[loop_1].v;
vert_template.vertex = mesh_data.corner_verts[loop_1];
UVVertex *vert_1_ptr = island.lookup_or_create(vert_template);
const int loop_2 = get_uv_loop(mesh_data, looptri, connected_vert_2->vertex);
vert_template.uv = connected_vert_2->uv;
vert_template.vertex = mesh_data.loops[loop_2].v;
vert_template.vertex = mesh_data.corner_verts[loop_2];
UVVertex *vert_2_ptr = island.lookup_or_create(vert_template);
UVEdge edge_template;
@@ -1337,7 +1338,7 @@ const UVVertex *UVPrimitive::get_uv_vertex(const MeshData &mesh_data,
const uint8_t mesh_vert_index) const
{
const MLoopTri &looptri = mesh_data.looptris[this->primitive_i];
const int mesh_vertex = mesh_data.loops[looptri.tri[mesh_vert_index]].v;
const int mesh_vertex = mesh_data.corner_verts[looptri.tri[mesh_vert_index]];
for (const UVEdge *uv_edge : edges) {
for (const UVVertex *uv_vert : uv_edge->vertices) {
if (uv_vert->vertex == mesh_vertex) {
@@ -119,7 +119,7 @@ class TriangleToEdgeMap {
struct MeshData {
public:
const Span<MLoopTri> looptris;
const Span<MLoop> loops;
const Span<int> corner_verts;
const Span<float2> uv_map;
const Span<float3> vert_positions;
@@ -140,7 +140,7 @@ struct MeshData {
public:
explicit MeshData(Span<MLoopTri> looptris,
Span<MLoop> loops,
Span<int> corner_verts,
const Span<float2> uv_map,
const Span<float3> vert_positions);
};
+8 -8
View File
@@ -406,7 +406,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
totvert = mesh->totvert;
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
const int *corner_verts = BKE_mesh_corner_verts(mesh);
/* sanity checking - potential case when no data will be present */
if ((totvert == 0) || (tottri == 0)) {
@@ -431,9 +431,9 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
const MLoopTri *lt = &looptri[i];
int vtri[3];
vtri[0] = mloop[lt->tri[0]].v;
vtri[1] = mloop[lt->tri[1]].v;
vtri[2] = mloop[lt->tri[2]].v;
vtri[0] = corner_verts[lt->tri[0]];
vtri[1] = corner_verts[lt->tri[1]];
vtri[2] = corner_verts[lt->tri[2]];
RB_trimesh_add_triangle_indices(mdata, i, UNPACK3(vtri));
}
@@ -681,10 +681,10 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
totvert = mesh->totvert;
lt = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
const int *corner_verts = BKE_mesh_corner_verts(mesh);
if (totvert > 0 && tottri > 0) {
BKE_mesh_calc_volume(positions, totvert, lt, tottri, mloop, &volume, NULL);
BKE_mesh_calc_volume(positions, totvert, lt, tottri, corner_verts, &volume, NULL);
const float volume_scale = mat4_to_volume_scale(ob->object_to_world);
volume *= fabsf(volume_scale);
}
@@ -755,10 +755,10 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
totvert = mesh->totvert;
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
if (totvert > 0 && tottri > 0) {
BKE_mesh_calc_volume(positions, totvert, looptri, tottri, mloop, NULL, r_center);
BKE_mesh_calc_volume(
positions, totvert, looptri, tottri, BKE_mesh_corner_verts(mesh), NULL, r_center);
}
}
break;
+20 -15
View File
@@ -115,6 +115,7 @@ bool BKE_shrinkwrap_init_tree(
data->mesh = mesh;
data->polys = mesh->polys().data();
data->corner_edges = mesh->corner_edges().data();
data->vert_normals = reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data()),
data->sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_face"));
@@ -190,16 +191,18 @@ static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
{
using namespace blender;
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const blender::Span<MEdge> edges = mesh->edges();
const blender::Span<MLoop> loops = mesh->loops();
const Span<int> corner_verts = mesh->corner_verts();
const Span<int> corner_edges = mesh->corner_edges();
/* Count faces per edge (up to 2). */
char *edge_mode = static_cast<char *>(
MEM_calloc_arrayN(size_t(mesh->totedge), sizeof(char), __func__));
for (int i = 0; i < mesh->totloop; i++) {
uint eidx = loops[i].e;
const int eidx = corner_edges[i];
if (edge_mode[eidx] < 2) {
edge_mode[eidx]++;
@@ -240,7 +243,8 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
for (const int64_t i : looptris.index_range()) {
int real_edges[3];
BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &looptris[i], real_edges);
BKE_mesh_looptri_get_real_edges(
edges.data(), corner_verts.data(), corner_edges.data(), &looptris[i], real_edges);
for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
@@ -1012,11 +1016,12 @@ static void mesh_looptri_target_project(void *userdata,
const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata;
const BVHTreeFromMesh *data = &tree->treeData;
const MLoopTri *lt = &data->looptri[index];
const MLoop *loop[3] = {
&data->loop[lt->tri[0]], &data->loop[lt->tri[1]], &data->loop[lt->tri[2]]};
const float *vtri_co[3] = {data->vert_positions[loop[0]->v],
data->vert_positions[loop[1]->v],
data->vert_positions[loop[2]->v]};
const int tri_verts[3] = {data->corner_verts[lt->tri[0]],
data->corner_verts[lt->tri[1]],
data->corner_verts[lt->tri[2]]};
const float *vtri_co[3] = {data->vert_positions[tri_verts[0]],
data->vert_positions[tri_verts[1]],
data->vert_positions[tri_verts[2]]};
float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3];
/* First find the closest point and bail out if it's worse than the current solution. */
@@ -1038,9 +1043,9 @@ static void mesh_looptri_target_project(void *userdata,
}
/* Decode normals */
copy_v3_v3(vtri_no[0], tree->vert_normals[loop[0]->v]);
copy_v3_v3(vtri_no[1], tree->vert_normals[loop[1]->v]);
copy_v3_v3(vtri_no[2], tree->vert_normals[loop[2]->v]);
copy_v3_v3(vtri_no[0], tree->vert_normals[tri_verts[0]]);
copy_v3_v3(vtri_no[1], tree->vert_normals[tri_verts[1]]);
copy_v3_v3(vtri_no[2], tree->vert_normals[tri_verts[2]]);
/* Solve the equations for the triangle */
if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) {
@@ -1051,7 +1056,7 @@ static void mesh_looptri_target_project(void *userdata,
const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary;
int edges[3];
BKE_mesh_looptri_get_real_edges(data->edge, data->loop, lt, edges);
BKE_mesh_looptri_get_real_edges(data->edge, data->corner_verts, tree->corner_edges, lt, edges);
for (int i = 0; i < 3; i++) {
if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) {
@@ -1178,9 +1183,9 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
/* Interpolate smooth normals if enabled. */
if (!(tree->sharp_faces && tree->sharp_faces[tri->poly])) {
const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v,
treeData->loop[tri->tri[1]].v,
treeData->loop[tri->tri[2]].v};
const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]],
treeData->corner_verts[tri->tri[1]],
treeData->corner_verts[tri->tri[2]]};
float w[3], no[3][3], tmp_co[3];
/* Custom and auto smooth split normals. */
+10 -10
View File
@@ -588,7 +588,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
nofquads = count_mesh_quads(me);
if (nofquads) {
const MLoop *mloop = BKE_mesh_loops(me);
const int *corner_verts = BKE_mesh_corner_verts(me);
const MPoly *polys = BKE_mesh_polys(me);
BodySpring *bs;
@@ -602,12 +602,12 @@ static void add_mesh_quad_diag_springs(Object *ob)
for (int a = 0; a < me->totpoly; a++) {
const MPoly *poly = &polys[a];
if (poly->totloop == 4) {
bs->v1 = mloop[poly->loopstart + 0].v;
bs->v2 = mloop[poly->loopstart + 2].v;
bs->v1 = corner_verts[poly->loopstart + 0];
bs->v2 = corner_verts[poly->loopstart + 2];
bs->springtype = SB_STIFFQUAD;
bs++;
bs->v1 = mloop[poly->loopstart + 1].v;
bs->v2 = mloop[poly->loopstart + 3].v;
bs->v1 = corner_verts[poly->loopstart + 1];
bs->v2 = corner_verts[poly->loopstart + 3];
bs->springtype = SB_STIFFQUAD;
bs++;
}
@@ -2753,22 +2753,22 @@ static void mesh_faces_to_scratch(Object *ob)
int a;
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
const MPoly *polys = BKE_mesh_polys(me);
const MLoop *loops = BKE_mesh_loops(me);
const int *corner_verts = BKE_mesh_corner_verts(me);
/* Allocate and copy faces. */
sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop);
looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
BKE_mesh_recalc_looptri(
loops, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri);
corner_verts, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri);
bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface,
"SB_body_Faces");
for (a = 0; a < sb->scratch->totface; a++, lt++, bodyface++) {
bodyface->v1 = loops[lt->tri[0]].v;
bodyface->v2 = loops[lt->tri[1]].v;
bodyface->v3 = loops[lt->tri[2]].v;
bodyface->v1 = corner_verts[lt->tri[0]];
bodyface->v2 = corner_verts[lt->tri[1]];
bodyface->v3 = corner_verts[lt->tri[2]];
zero_v3(bodyface->ext_force);
bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
bodyface->flag = 0;
+12 -11
View File
@@ -1986,7 +1986,7 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg)
static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const MLoop *mloop,
const int *corner_verts,
const MPoly *polys,
int *r_v1,
int *r_v2)
@@ -1994,22 +1994,22 @@ static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_cc
const int grid_size_1 = subdiv_ccg->grid_size - 1;
const int poly_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index);
const MPoly &poly = polys[poly_index];
*r_v1 = mloop[coord->grid_index].v;
*r_v1 = corner_verts[coord->grid_index];
const int corner = poly_find_loop_from_vert(&poly, &mloop[poly.loopstart], *r_v1);
const int corner = poly_find_loop_from_vert(&poly, &corner_verts[poly.loopstart], *r_v1);
if (coord->x == grid_size_1) {
const MLoop *next = ME_POLY_LOOP_NEXT(mloop, &poly, corner);
*r_v2 = next->v;
const int next = ME_POLY_LOOP_NEXT(&poly, corner);
*r_v2 = corner_verts[next];
}
if (coord->y == grid_size_1) {
const MLoop *prev = ME_POLY_LOOP_PREV(mloop, &poly, corner);
*r_v2 = prev->v;
const int prev = ME_POLY_LOOP_PREV(&poly, corner);
*r_v2 = corner_verts[prev];
}
}
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord,
const MLoop *mloop,
const int *corner_verts,
const MPoly *polys,
int *r_v1,
int *r_v2)
@@ -2023,18 +2023,19 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const Subdi
}
if (coord->x == grid_size_1 && coord->y == grid_size_1) {
/* Grid corner adjacent to a coarse mesh vertex. */
*r_v1 = *r_v2 = mloop[coord->grid_index].v;
*r_v1 = *r_v2 = corner_verts[coord->grid_index];
return SUBDIV_CCG_ADJACENT_VERTEX;
}
/* Grid corner adjacent to the middle of a coarse mesh edge. */
adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, polys, r_v1, r_v2);
adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
return SUBDIV_CCG_ADJACENT_EDGE;
}
if (is_boundary_grid_coord(subdiv_ccg, coord)) {
if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
/* Grid boundary adjacent to a coarse mesh edge. */
adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, polys, r_v1, r_v2);
adjacet_vertices_index_from_adjacent_edge(
subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
return SUBDIV_CCG_ADJACENT_EDGE;
}
}
@@ -37,7 +37,8 @@ struct ConverterStorage {
const float (*vert_positions)[3];
blender::Span<MEdge> edges;
blender::Span<MPoly> polys;
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
/* CustomData layer for vertex sharpnesses. */
const float *cd_vertex_crease;
@@ -135,10 +136,9 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter,
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
const MPoly &poly = storage->polys[manifold_face_index];
const blender::Span<MLoop> loops = storage->loops;
for (int corner = 0; corner < poly.totloop; corner++) {
manifold_face_vertices[corner] =
storage->manifold_vertex_index[loops[poly.loopstart + corner].v];
for (int i = 0; i < poly.totloop; i++) {
const int vert = storage->corner_verts[poly.loopstart + i];
manifold_face_vertices[i] = storage->manifold_vertex_index[vert];
}
}
@@ -216,7 +216,7 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
storage->polys.data(),
(const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly"),
(const bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".select_poly"),
storage->loops.data(),
storage->corner_verts.data(),
mloopuv,
num_poly,
num_vert,
@@ -355,17 +355,18 @@ static void initialize_manifold_indices(ConverterStorage *storage)
{
const Mesh *mesh = storage->mesh;
const blender::Span<MEdge> edges = storage->edges;
const blender::Span<MLoop> loops = storage->loops;
const blender::Span<MPoly> polys = storage->polys;
const blender::Span<int> corner_verts = storage->corner_verts;
const blender::Span<int> corner_edges = storage->corner_edges;
/* Set bits of elements which are not loose. */
BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
const MPoly &poly = polys[poly_index];
for (int corner = 0; corner < poly.totloop; corner++) {
const MLoop *loop = &loops[poly.loopstart + corner];
BLI_BITMAP_ENABLE(vert_used_map, loop->v);
BLI_BITMAP_ENABLE(edge_used_map, loop->e);
for (int i = 0; i < poly.totloop; i++) {
const int corner = poly.loopstart + i;
BLI_BITMAP_ENABLE(vert_used_map, corner_verts[corner]);
BLI_BITMAP_ENABLE(edge_used_map, corner_edges[corner]);
}
}
initialize_manifold_index_array(vert_used_map,
@@ -403,7 +404,8 @@ static void init_user_data(OpenSubdiv_Converter *converter,
user_data->vert_positions = BKE_mesh_vert_positions(mesh);
user_data->edges = mesh->edges();
user_data->polys = mesh->polys();
user_data->loops = mesh->loops();
user_data->corner_verts = mesh->corner_verts();
user_data->corner_edges = mesh->corner_edges();
user_data->cd_vertex_crease = static_cast<const float *>(
CustomData_get_layer(&mesh->vdata, CD_CREASE));
user_data->cd_edge_crease = static_cast<const float *>(
@@ -83,7 +83,7 @@ static void set_coarse_positions(Subdiv *subdiv,
{
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const blender::Span<int> corner_verts = mesh->corner_verts();
/* Mark vertices which needs new coordinates. */
/* TODO(sergey): This is annoying to calculate this on every update,
* maybe it's better to cache this mapping. Or make it possible to have
@@ -91,9 +91,8 @@ static void set_coarse_positions(Subdiv *subdiv,
BLI_bitmap *vertex_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
const MPoly &poly = polys[poly_index];
for (int corner = 0; corner < poly.totloop; corner++) {
const MLoop *loop = &loops[poly.loopstart + corner];
BLI_BITMAP_ENABLE(vertex_used_map, loop->v);
for (int i = 0; i < poly.totloop; i++) {
BLI_BITMAP_ENABLE(vertex_used_map, corner_verts[poly.loopstart + i]);
}
}
/* Use a temporary buffer so we do not upload vertices one at a time to the GPU. */
@@ -69,7 +69,8 @@ struct SubdivForeachTaskContext {
const Mesh *coarse_mesh;
blender::Span<MEdge> coarse_edges;
blender::Span<MPoly> coarse_polys;
blender::Span<MLoop> coarse_loops;
blender::Span<int> coarse_corner_verts;
blender::Span<int> coarse_corner_edges;
const SubdivToMeshSettings *settings;
/* Callbacks. */
const SubdivForeachContext *foreach_context;
@@ -290,12 +291,12 @@ static void subdiv_foreach_corner_vertices_regular_do(
const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data();
const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) {
continue;
}
const int coarse_vertex_index = coarse_loop->v;
const int coarse_vertex_index = coarse_vert;
const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index;
const float u = weights[corner][0];
const float v = weights[corner][1];
@@ -329,12 +330,12 @@ static void subdiv_foreach_corner_vertices_special_do(
const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data();
int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_vert)) {
continue;
}
const int coarse_vertex_index = coarse_loop->v;
const int coarse_vertex_index = coarse_vert;
const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index;
vertex_corner(ctx->foreach_context,
tls,
@@ -416,14 +417,14 @@ static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ct
const int coarse_poly_index = coarse_poly - ctx->coarse_polys.data();
const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_edge_index = coarse_loop->e;
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
continue;
}
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
const bool flip = (coarse_edge->v2 == coarse_vert);
int subdiv_vertex_index = ctx->vertices_edge_offset +
coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
for (int vertex_index = 0; vertex_index < num_subdiv_vertices_per_coarse_edge;
@@ -479,14 +480,14 @@ static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ct
const int ptex_face_start_index = ctx->face_ptex_offset[coarse_poly_index];
int ptex_face_index = ptex_face_start_index;
for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_edge_index = coarse_loop->e;
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
continue;
}
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
const bool flip = (coarse_edge->v2 == coarse_vert);
int subdiv_vertex_index = ctx->vertices_edge_offset +
coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
int vertex_delta = 1;
@@ -778,11 +779,12 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c
}
/* Connect inner part of patch to boundary. */
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const int coarse_vert_index = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_index = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_vert_index);
int side_start_index = start_vertex_index;
int side_stride = 0;
/* Calculate starting vertex of corresponding inner part of ptex. */
@@ -886,15 +888,16 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
}
}
/* Connect inner path of patch to boundary. */
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
int prev_corner = coarse_poly->totloop - 1;
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner];
{
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
coarse_edge_i * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_vert);
int side_start_index;
if (ptex_face_resolution >= 3) {
side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner;
@@ -911,10 +914,10 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
}
}
if (ptex_face_resolution >= 3) {
const MEdge *coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_prev_edge];
const int start_edge_vertex = ctx->vertices_edge_offset +
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
coarse_prev_edge * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_vert);
int side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner;
for (int i = 0; i < ptex_face_resolution - 2; i++, subdiv_edge_index++) {
const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) :
@@ -924,7 +927,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, false, v1, v2);
}
}
prev_coarse_loop = coarse_loop;
prev_corner = corner;
}
}
@@ -1134,30 +1137,35 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
}
}
/* Loops for faces connecting inner ptex part with boundary. */
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
int prev_corner_index = coarse_poly->totloop - 1;
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
const int coase_prev_vert =
ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner_index];
const int coarse_prev_edge =
ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner_index];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
coarse_edge_i * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_vert);
int side_start_index = start_vertex_index;
int side_stride = 0;
int v0 = ctx->vertices_corner_offset + coarse_loop->v;
int v0 = ctx->vertices_corner_offset + coarse_vert;
int v3, e3;
int e2_offset, e2_stride;
float u, v, delta_u, delta_v;
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
if (coase_prev_vert == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge +
num_subdiv_vertices_per_coarse_edge - 1;
e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge +
num_subdiv_edges_per_coarse_edge - 1;
}
else {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge;
e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge;
}
/* Calculate starting vertex of corresponding inner part of ptex. */
if (corner == 0) {
@@ -1214,11 +1222,11 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
const int v2 = side_start_index + side_stride * i;
int e0;
if (flip) {
e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge +
e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge +
num_subdiv_edges_per_coarse_edge - i - 1;
}
else {
e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i;
e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + i;
}
int e1 = start_edge_index + num_edges_per_ptex_face_get(resolution - 2) +
corner * num_subdiv_vertices_per_coarse_edge + i;
@@ -1259,7 +1267,7 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
v3 = v2;
e3 = e1;
}
prev_coarse_loop = coarse_loop;
prev_corner_index = corner;
}
}
@@ -1436,30 +1444,32 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
}
}
/* Loops for faces connecting inner ptex part with boundary. */
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
for (int prev_corner = coarse_poly->totloop - 1, corner = 0; corner < coarse_poly->totloop;
prev_corner = corner, corner++) {
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
const int coarse_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + corner];
const int coarse_edge_i = ctx->coarse_corner_edges[coarse_poly->loopstart + corner];
const int coase_prev_vert = ctx->coarse_corner_verts[coarse_poly->loopstart + prev_corner];
const int coarse_prev_edge = ctx->coarse_corner_edges[coarse_poly->loopstart + prev_corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_i];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[coarse_prev_edge];
const bool flip = (coarse_edge->v2 == coarse_vert);
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
coarse_edge_i * num_subdiv_vertices_per_coarse_edge;
const int corner_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex;
const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face;
/* Create loops for polygons along U axis. */
int v0 = ctx->vertices_corner_offset + coarse_loop->v;
int v0 = ctx->vertices_corner_offset + coarse_vert;
int v3, e3;
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
if (coase_prev_vert == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge +
num_subdiv_vertices_per_coarse_edge - 1;
e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge +
num_subdiv_edges_per_coarse_edge - 1;
}
else {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge;
e3 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge;
}
for (int i = 0; i <= ptex_face_inner_resolution; i++, subdiv_loop_index += 4) {
int v1;
@@ -1478,11 +1488,11 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
}
int e0;
if (flip) {
e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge +
e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge +
num_subdiv_edges_per_coarse_edge - i - 1;
}
else {
e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i;
e0 = ctx->edge_boundary_offset + coarse_edge_i * num_subdiv_edges_per_coarse_edge + i;
}
int e1 = start_edge_index + corner * (2 * ptex_face_inner_resolution + 1);
if (ptex_face_resolution >= 3) {
@@ -1529,14 +1539,14 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
e3 = e1;
}
/* Create loops for polygons along V axis. */
const bool flip_prev = (prev_coarse_edge->v2 == coarse_loop->v);
const bool flip_prev = (prev_coarse_edge->v2 == coarse_vert);
v0 = corner_vertex_index;
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
if (coase_prev_vert == prev_coarse_edge->v1) {
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge +
num_subdiv_vertices_per_coarse_edge - 1;
}
else {
v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
v3 = ctx->vertices_edge_offset + coarse_prev_edge * num_subdiv_vertices_per_coarse_edge;
}
e3 = start_edge_index +
coarse_poly->totloop * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) +
@@ -1563,12 +1573,12 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
int v2 = flip_prev ? v3 - 1 : v3 + 1;
int e2;
if (flip_prev) {
e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
e2 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge +
num_subdiv_edges_per_coarse_edge - 2 - i;
}
else {
e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1 + i;
e2 = ctx->edge_boundary_offset + coarse_prev_edge * num_subdiv_edges_per_coarse_edge + 1 +
i;
}
const float u = 0.0f;
const float v = du * (i + 1);
@@ -1595,7 +1605,6 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
v3 = v2;
e3 = e1;
}
prev_coarse_loop = coarse_loop;
}
}
@@ -1724,9 +1733,10 @@ static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly &coarse_poly = ctx->coarse_polys[poly_index];
for (int corner = 0; corner < coarse_poly.totloop; corner++) {
const MLoop *loop = &ctx->coarse_loops[coarse_poly.loopstart + corner];
BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, loop->v);
BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map,
ctx->coarse_corner_verts[coarse_poly.loopstart + corner]);
BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map,
ctx->coarse_corner_verts[coarse_poly.loopstart + corner]);
}
}
}
@@ -1797,7 +1807,8 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
ctx.coarse_mesh = coarse_mesh;
ctx.coarse_edges = coarse_mesh->edges();
ctx.coarse_polys = coarse_mesh->polys();
ctx.coarse_loops = coarse_mesh->loops();
ctx.coarse_corner_verts = coarse_mesh->corner_verts();
ctx.coarse_corner_edges = coarse_mesh->corner_edges();
ctx.settings = mesh_settings;
ctx.foreach_context = context;
subdiv_foreach_ctx_init(subdiv, &ctx);
+41 -50
View File
@@ -32,6 +32,7 @@
using blender::float2;
using blender::float3;
using blender::MutableSpan;
using blender::Span;
/* -------------------------------------------------------------------- */
@@ -44,14 +45,15 @@ struct SubdivMeshContext {
const float (*coarse_positions)[3];
blender::Span<MEdge> coarse_edges;
blender::Span<MPoly> coarse_polys;
blender::Span<MLoop> coarse_loops;
blender::Span<int> coarse_corner_verts;
Subdiv *subdiv;
Mesh *subdiv_mesh;
blender::MutableSpan<float3> subdiv_positions;
blender::MutableSpan<MEdge> subdiv_edges;
blender::MutableSpan<MPoly> subdiv_polys;
blender::MutableSpan<MLoop> subdiv_loops;
blender::MutableSpan<int> subdiv_corner_verts;
blender::MutableSpan<int> subdiv_corner_edges;
/* Cached custom data arrays for faster access. */
int *vert_origindex;
@@ -95,7 +97,8 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
ctx->subdiv_positions = subdiv_mesh->vert_positions_for_write();
ctx->subdiv_edges = subdiv_mesh->edges_for_write();
ctx->subdiv_polys = subdiv_mesh->polys_for_write();
ctx->subdiv_loops = subdiv_mesh->loops_for_write();
ctx->subdiv_corner_verts = subdiv_mesh->corner_verts_for_write();
ctx->subdiv_corner_edges = subdiv_mesh->corner_edges_for_write();
/* Pointers to original indices layers. */
ctx->vert_origindex = static_cast<int *>(
CustomData_get_layer_for_write(&subdiv_mesh->vdata, CD_ORIGINDEX, subdiv_mesh->totvert));
@@ -138,16 +141,15 @@ static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
struct LoopsOfPtex {
/* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
const MLoop *first_loop;
int first_loop;
/* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
const MLoop *last_loop;
int last_loop;
/* For quad coarse faces only. */
const MLoop *second_loop;
const MLoop *third_loop;
int second_loop;
int third_loop;
};
static void loops_of_ptex_get(const SubdivMeshContext *ctx,
LoopsOfPtex *loops_of_ptex,
static void loops_of_ptex_get(LoopsOfPtex *loops_of_ptex,
const MPoly *coarse_poly,
const int ptex_of_poly_index)
{
@@ -159,15 +161,15 @@ static void loops_of_ptex_get(const SubdivMeshContext *ctx,
const int last_ptex_loop_index = coarse_poly->loopstart +
(ptex_of_poly_index + coarse_poly->totloop - 1) %
coarse_poly->totloop;
loops_of_ptex->first_loop = &ctx->coarse_loops[first_ptex_loop_index];
loops_of_ptex->last_loop = &ctx->coarse_loops[last_ptex_loop_index];
loops_of_ptex->first_loop = first_ptex_loop_index;
loops_of_ptex->last_loop = last_ptex_loop_index;
if (coarse_poly->totloop == 4) {
loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
}
else {
loops_of_ptex->second_loop = nullptr;
loops_of_ptex->third_loop = nullptr;
loops_of_ptex->second_loop = -1;
loops_of_ptex->third_loop = -1;
}
}
@@ -206,13 +208,12 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
const MPoly &coarse_poly)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const blender::Span<MLoop> coarse_loops = ctx->coarse_loops;
if (coarse_poly.totloop == 4) {
vertex_interpolation->vertex_data = &coarse_mesh->vdata;
vertex_interpolation->vertex_indices[0] = coarse_loops[coarse_poly.loopstart + 0].v;
vertex_interpolation->vertex_indices[1] = coarse_loops[coarse_poly.loopstart + 1].v;
vertex_interpolation->vertex_indices[2] = coarse_loops[coarse_poly.loopstart + 2].v;
vertex_interpolation->vertex_indices[3] = coarse_loops[coarse_poly.loopstart + 3].v;
vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_poly.loopstart + 0];
vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_poly.loopstart + 1];
vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_poly.loopstart + 2];
vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_poly.loopstart + 3];
vertex_interpolation->vertex_data_storage_allocated = false;
}
else {
@@ -236,7 +237,7 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
blender::Array<int, 32> indices(coarse_poly.totloop);
for (int i = 0; i < coarse_poly.totloop; i++) {
weights[i] = weight;
indices[i] = coarse_loops[coarse_poly.loopstart + i].v;
indices[i] = ctx->coarse_corner_verts[coarse_poly.loopstart + i];
}
CustomData_interp(&coarse_mesh->vdata,
&vertex_interpolation->vertex_data_storage,
@@ -258,13 +259,12 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx,
}
else {
const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
const blender::Span<MLoop> coarse_loops = ctx->coarse_loops;
LoopsOfPtex loops_of_ptex;
loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner);
/* Ptex face corner corresponds to a poly loop with same index. */
CustomData_copy_data(vertex_data,
&vertex_interpolation->vertex_data_storage,
coarse_loops[coarse_poly->loopstart + corner].v,
ctx->coarse_corner_verts[coarse_poly->loopstart + corner],
0,
1);
/* Interpolate remaining ptex face corners, which hits loops
@@ -273,17 +273,15 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx,
* TODO(sergey): Re-use one of interpolation results from previous
* iteration. */
const float weights[2] = {0.5f, 0.5f};
const int first_loop_index = loops_of_ptex.first_loop - coarse_loops.data();
const int last_loop_index = loops_of_ptex.last_loop - coarse_loops.data();
const int first_loop_index = loops_of_ptex.first_loop;
const int last_loop_index = loops_of_ptex.last_loop;
const int first_indices[2] = {
int(coarse_loops[first_loop_index].v),
int(coarse_loops[coarse_poly->loopstart +
(first_loop_index - coarse_poly->loopstart + 1) % coarse_poly->totloop]
.v)};
const int last_indices[2] = {
int(coarse_loops[first_loop_index].v),
int(coarse_loops[last_loop_index].v),
};
ctx->coarse_corner_verts[first_loop_index],
ctx->coarse_corner_verts[coarse_poly->loopstart +
(first_loop_index - coarse_poly->loopstart + 1) %
coarse_poly->totloop]};
const int last_indices[2] = {ctx->coarse_corner_verts[first_loop_index],
ctx->coarse_corner_verts[last_loop_index]};
CustomData_interp(vertex_data,
&vertex_interpolation->vertex_data_storage,
first_indices,
@@ -391,9 +389,8 @@ static void loop_interpolation_from_corner(const SubdivMeshContext *ctx,
}
else {
const CustomData *loop_data = &ctx->coarse_mesh->ldata;
const blender::Span<MLoop> coarse_loops = ctx->coarse_loops;
LoopsOfPtex loops_of_ptex;
loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner);
/* Ptex face corner corresponds to a poly loop with same index. */
CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
CustomData_copy_data(
@@ -405,14 +402,11 @@ static void loop_interpolation_from_corner(const SubdivMeshContext *ctx,
* iteration. */
const float weights[2] = {0.5f, 0.5f};
const int base_loop_index = coarse_poly->loopstart;
const int first_loop_index = loops_of_ptex.first_loop - coarse_loops.data();
const int first_loop_index = loops_of_ptex.first_loop;
const int second_loop_index = base_loop_index +
(first_loop_index - base_loop_index + 1) % coarse_poly->totloop;
const int first_indices[2] = {first_loop_index, second_loop_index};
const int last_indices[2] = {
int(loops_of_ptex.last_loop - coarse_loops.data()),
int(loops_of_ptex.first_loop - coarse_loops.data()),
};
const int last_indices[2] = {loops_of_ptex.last_loop, loops_of_ptex.first_loop};
CustomData_interp(
loop_data, &loop_interpolation->loop_data_storage, first_indices, weights, nullptr, 2, 1);
CustomData_interp(
@@ -828,12 +822,11 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
* \{ */
static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx,
MLoop *subdiv_loop,
const int subdiv_loop_index,
const LoopsForInterpolation *loop_interpolation,
const float u,
const float v)
{
const int subdiv_loop_index = subdiv_loop - ctx->subdiv_loops.data();
const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
CustomData_interp(loop_interpolation->loop_data,
&ctx->subdiv_mesh->ldata,
@@ -846,7 +839,7 @@ static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx,
}
static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
MLoop *subdiv_loop,
const int corner_index,
const int ptex_face_index,
const float u,
const float v)
@@ -855,10 +848,9 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
return;
}
Subdiv *subdiv = ctx->subdiv;
const int mloop_index = subdiv_loop - ctx->subdiv_loops.data();
for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
BKE_subdiv_eval_face_varying(
subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][mloop_index]);
subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][corner_index]);
}
}
@@ -905,12 +897,11 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
SubdivMeshTLS *tls = static_cast<SubdivMeshTLS *>(tls_v);
const MPoly &coarse_poly = ctx->coarse_polys[coarse_poly_index];
MLoop *subdiv_loop = &ctx->subdiv_loops[subdiv_loop_index];
subdiv_mesh_ensure_loop_interpolation(ctx, tls, &coarse_poly, coarse_corner);
subdiv_interpolate_loop_data(ctx, subdiv_loop, &tls->loop_interpolation, u, v);
subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v);
subdiv_loop->v = subdiv_vertex_index;
subdiv_loop->e = subdiv_edge_index;
subdiv_interpolate_loop_data(ctx, subdiv_loop_index, &tls->loop_interpolation, u, v);
subdiv_eval_uv_layer(ctx, subdiv_loop_index, ptex_face_index, u, v);
ctx->subdiv_corner_verts[subdiv_loop_index] = subdiv_vertex_index;
ctx->subdiv_corner_edges[subdiv_loop_index] = subdiv_edge_index;
}
/** \} */
@@ -1182,7 +1173,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
subdiv_context.coarse_positions = BKE_mesh_vert_positions(coarse_mesh);
subdiv_context.coarse_edges = coarse_mesh->edges();
subdiv_context.coarse_polys = coarse_mesh->polys();
subdiv_context.coarse_loops = coarse_mesh->loops();
subdiv_context.coarse_corner_verts = coarse_mesh->corner_verts();
subdiv_context.subdiv = subdiv;
subdiv_context.have_displacement = (subdiv->displacement_evaluator != nullptr);
+84 -37
View File
@@ -228,13 +228,13 @@ static int getFaceIndex(
}
static void get_face_uv_map_vert(
UvVertMap *vmap, const MPoly *polys, MLoop *ml, int fi, CCGVertHDL *fverts)
UvVertMap *vmap, const MPoly *polys, const int *poly_verts, int fi, CCGVertHDL *fverts)
{
UvMapVert *v, *nv;
int j, nverts = polys[fi].totloop;
for (j = 0; j < nverts; j++) {
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) {
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, poly_verts[j]); v; v = v->next) {
if (v->separate) {
nv = v;
}
@@ -253,7 +253,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
const float (*mloopuv)[2])
{
MPoly *polys = dm->getPolyArray(dm);
MLoop *mloop = dm->getLoopArray(dm);
int *corner_verts = dm->getCornerVertArray(dm);
int totvert = dm->getNumVerts(dm);
int totface = dm->getNumPolys(dm);
int i, seam;
@@ -270,7 +270,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
* Also, initially intention is to treat merged vertices from mirror modifier as seams.
* This fixes a very old regression (2.49 was correct here) */
vmap = BKE_mesh_uv_vert_map_create(
polys, nullptr, nullptr, mloop, mloopuv, totface, totvert, limit, false, true);
polys, nullptr, nullptr, corner_verts, mloopuv, totface, totvert, limit, false, true);
if (!vmap) {
return 0;
}
@@ -312,12 +312,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
int nverts = poly.totloop;
int j, j_next;
CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i));
// uint *fv = &poly.v1;
MLoop *ml = mloop + poly.loopstart;
/* uint *fv = &poly.v1; */
fverts.reinitialize(nverts);
get_face_uv_map_vert(vmap, polys, ml, i, fverts.data());
get_face_uv_map_vert(vmap, &poly, &corner_verts[poly.loopstart], i, fverts.data());
for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
uint v0 = POINTER_AS_UINT(fverts[j_next]);
@@ -338,13 +337,12 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
/* create faces */
for (i = 0; i < totface; i++) {
const MPoly &poly = polys[i];
MLoop *ml = &mloop[poly.loopstart];
int nverts = poly.totloop;
CCGFace *f;
fverts.reinitialize(nverts);
get_face_uv_map_vert(vmap, polys, ml, i, fverts.data());
get_face_uv_map_vert(vmap, polys, &corner_verts[poly.loopstart], i, fverts.data());
ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f);
}
@@ -539,7 +537,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
float(*positions)[3] = (float(*)[3])dm->getVertArray(dm);
MEdge *edges = dm->getEdgeArray(dm);
MEdge *edge;
MLoop *mloop = dm->getLoopArray(dm), *ml;
int *corner_verts = dm->getCornerVertArray(dm);
MPoly *polys = dm->getPolyArray(dm);
int totvert = dm->getNumVerts(dm);
int totedge = dm->getNumEdges(dm);
@@ -588,9 +586,9 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
fverts.reinitialize(poly.totloop);
ml = mloop + poly.loopstart;
for (j = 0; j < poly.totloop; j++, ml++) {
fverts[j] = POINTER_FROM_UINT(ml->v);
int corner = poly.loopstart;
for (j = 0; j < poly.totloop; j++, corner++) {
fverts[j] = POINTER_FROM_UINT(corner_verts[corner]);
}
/* This is very bad, means mesh is internally inconsistent.
@@ -965,7 +963,8 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *edges)
struct CopyFinalLoopArrayData {
CCGDerivedMesh *ccgdm;
MLoop *mloop;
int *corner_verts;
int *corner_edges;
int grid_size;
int *grid_offset;
int edge_size;
@@ -984,38 +983,39 @@ static void copyFinalLoopArray_task_cb(void *__restrict userdata,
CCGFace *f = ccgdm->faceMap[iter].face;
const int num_verts = ccgSubSurf_getFaceNumVerts(f);
const int grid_index = data->grid_offset[iter];
const size_t loop_index = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1);
MLoop *ml = &data->mloop[loop_index];
int *corner_verts = data->corner_verts;
int *corner_edges = data->corner_edges;
size_t loop_i = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1);
for (int S = 0; S < num_verts; S++) {
for (int y = 0; y < grid_size - 1; y++) {
for (int x = 0; x < grid_size - 1; x++) {
uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size);
uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size);
uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size);
uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size);
const int v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size);
const int v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size);
const int v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size);
const int v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size);
ml->v = v1;
ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2));
ml++;
if (corner_verts) {
corner_verts[loop_i + 0] = v1;
corner_verts[loop_i + 1] = v2;
corner_verts[loop_i + 2] = v3;
corner_verts[loop_i + 3] = v4;
}
if (corner_edges) {
corner_edges[loop_i + 0] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2));
corner_edges[loop_i + 1] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3));
corner_edges[loop_i + 2] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4));
corner_edges[loop_i + 3] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1));
}
ml->v = v2;
ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3));
ml++;
ml->v = v3;
ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4));
ml++;
ml->v = v4;
ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1));
ml++;
loop_i += 4;
}
}
}
}
static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
static void ccgDM_copyFinalCornerVertArray(DerivedMesh *dm, int *r_corner_verts)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
CCGSubSurf *ss = ccgdm->ss;
@@ -1040,7 +1040,53 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
CopyFinalLoopArrayData data;
data.ccgdm = ccgdm;
data.mloop = mloop;
data.corner_verts = r_corner_verts;
data.corner_edges = NULL;
data.grid_size = ccgSubSurf_getGridSize(ss);
data.grid_offset = dm->getGridOffset(dm);
data.edge_size = ccgSubSurf_getEdgeSize(ss);
/* NOTE: For a dense subdivision we've got enough work for each face and
* hence can dedicate whole thread to single face. For less dense
* subdivision we handle multiple faces per thread.
*/
data.mloop_index = data.grid_size >= 5 ? 1 : 8;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1;
BLI_task_parallel_range(
0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings);
}
static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
CCGSubSurf *ss = ccgdm->ss;
if (!ccgdm->ehash) {
BLI_mutex_lock(&ccgdm->loops_cache_lock);
if (!ccgdm->ehash) {
MEdge *medge;
EdgeHash *ehash;
ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData);
medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm);
for (int i = 0; i < ccgdm->dm.numEdgeData; i++) {
BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i));
}
atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
}
BLI_mutex_unlock(&ccgdm->loops_cache_lock);
}
CopyFinalLoopArrayData data;
data.ccgdm = ccgdm;
data.corner_verts = NULL;
data.corner_edges = r_corner_edges;
data.grid_size = ccgSubSurf_getGridSize(ss);
data.grid_offset = dm->getGridOffset(dm);
data.edge_size = ccgSubSurf_getEdgeSize(ss);
@@ -1446,7 +1492,8 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
ccgdm->dm.copyCornerVertArray = ccgDM_copyFinalCornerVertArray;
ccgdm->dm.copyCornerEdgeArray = ccgDM_copyFinalCornerEdgeArray;
ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
@@ -115,7 +115,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
const int loop_offset,
MutableSpan<float3> vert_positions,
MutableSpan<MPoly> polys,
MutableSpan<MLoop> loops)
MutableSpan<int> corner_verts)
{
/* Write vertices. */
vert_positions.slice(vert_offset, vdb_verts.size()).copy_from(vdb_verts.cast<float3>());
@@ -126,7 +126,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
polys[poly_offset + i].totloop = 3;
for (int j = 0; j < 3; j++) {
/* Reverse vertex order to get correct normals. */
loops[loop_offset + 3 * i + j].v = vert_offset + vdb_tris[i][2 - j];
corner_verts[loop_offset + 3 * i + j] = vert_offset + vdb_tris[i][2 - j];
}
}
@@ -138,7 +138,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
polys[quad_offset + i].totloop = 4;
for (int j = 0; j < 4; j++) {
/* Reverse vertex order to get correct normals. */
loops[quad_loop_offset + 4 * i + j].v = vert_offset + vdb_quads[i][3 - j];
corner_verts[quad_loop_offset + 4 * i + j] = vert_offset + vdb_quads[i][3 - j];
}
}
}
@@ -177,7 +177,7 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
0,
mesh->vert_positions_for_write(),
mesh->polys_for_write(),
mesh->loops_for_write());
mesh->corner_verts_for_write());
BKE_mesh_calc_edges(mesh, false, false);
BKE_mesh_smooth_flag_set(mesh, false);
@@ -49,6 +49,7 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.h"
#include "BKE_multires.h"
#include "BKE_node.h"
@@ -820,6 +821,7 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain)
for (const int i : polys.index_range()) {
if (polys[i].totloop == 2) {
bool changed;
BKE_mesh_legacy_convert_loops_to_corners(me);
BKE_mesh_validate_arrays(
me,
BKE_mesh_vert_positions_for_write(me),
@@ -828,7 +830,8 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain)
me->totedge,
(MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface),
me->totface,
me->loops_for_write().data(),
me->corner_verts_for_write().data(),
me->corner_edges_for_write().data(),
polys.size(),
polys.data(),
me->totpoly,
@@ -39,6 +39,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
BKE_mesh_legacy_uv_seam_from_flags(&mesh);
BKE_mesh_legacy_convert_verts_to_positions(&mesh);
BKE_mesh_legacy_attribute_flags_to_strings(&mesh);
BKE_mesh_legacy_convert_loops_to_corners(&mesh);
}
static void version_motion_tracking_legacy_camera_object(MovieClip &movieclip)
@@ -118,6 +118,8 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
{
return ELEM(name,
"position",
".corner_vert",
".corner_edge",
".hide_vert",
".hide_edge",
".hide_poly",
@@ -131,19 +133,21 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
}
static BMFace *bm_face_create_from_mpoly(BMesh &bm,
Span<MLoop> loops,
Span<int> poly_verts,
Span<int> poly_edges,
Span<BMVert *> vtable,
Span<BMEdge *> etable)
{
Array<BMVert *, BM_DEFAULT_NGON_STACK_SIZE> verts(loops.size());
Array<BMEdge *, BM_DEFAULT_NGON_STACK_SIZE> edges(loops.size());
const int size = poly_verts.size();
Array<BMVert *, BM_DEFAULT_NGON_STACK_SIZE> verts(size);
Array<BMEdge *, BM_DEFAULT_NGON_STACK_SIZE> edges(size);
for (const int i : loops.index_range()) {
verts[i] = vtable[loops[i].v];
edges[i] = etable[loops[i].e];
for (const int i : IndexRange(size)) {
verts[i] = vtable[poly_verts[i]];
edges[i] = etable[poly_edges[i]];
}
return BM_face_create(&bm, verts.data(), edges.data(), loops.size(), nullptr, BM_CREATE_SKIP_CD);
return BM_face_create(&bm, verts.data(), edges.data(), size, nullptr, BM_CREATE_SKIP_CD);
}
struct MeshToBMeshLayerInfo {
@@ -484,7 +488,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
}
const Span<MPoly> polys = me->polys();
const Span<MLoop> mloop = me->loops();
const Span<int> corner_verts = me->corner_verts();
const Span<int> corner_edges = me->corner_edges();
/* Only needed for selection. */
@@ -495,8 +500,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
int totloops = 0;
for (const int i : polys.index_range()) {
BMFace *f = bm_face_create_from_mpoly(
*bm, mloop.slice(polys[i].loopstart, polys[i].totloop), vtable, etable);
BMFace *f = bm_face_create_from_mpoly(*bm,
corner_verts.slice(polys[i].loopstart, polys[i].totloop),
corner_edges.slice(polys[i].loopstart, polys[i].totloop),
vtable,
etable);
if (!ftable.is_empty()) {
ftable[i] = f;
}
@@ -950,6 +958,8 @@ static void assert_bmesh_has_no_mesh_only_attributes(const BMesh &bm)
{
(void)bm; /* Unused in the release builds. */
BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_FLOAT3, "position") == nullptr);
BLI_assert(CustomData_get_layer_named(&bm.ldata, CD_PROP_FLOAT3, ".corner_vert") == nullptr);
BLI_assert(CustomData_get_layer_named(&bm.ldata, CD_PROP_FLOAT3, ".corner_edge") == nullptr);
/* The "hide" attributes are stored as flags on #BMesh. */
BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr);
@@ -1354,15 +1364,16 @@ static void bm_to_mesh_faces(const BMesh &bm,
static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loops, Mesh &mesh)
{
CustomData_add_layer(&mesh.ldata, CD_MLOOP, CD_SET_DEFAULT, mesh.totloop);
CustomData_add_layer_named(&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, bm.totloop, ".corner_vert");
CustomData_add_layer_named(&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, bm.totloop, ".corner_edge");
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata);
MutableSpan<MLoop> dst_loops = mesh.loops_for_write();
threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) {
MutableSpan<int> dst_corner_verts = mesh.corner_verts_for_write();
MutableSpan<int> dst_corner_edges = mesh.corner_edges_for_write();
threading::parallel_for(dst_corner_verts.index_range(), 1024, [&](const IndexRange range) {
for (const int loop_i : range) {
const BMLoop &src_loop = *bm_loops[loop_i];
MLoop &dst_loop = dst_loops[loop_i];
dst_loop.v = BM_elem_index_get(src_loop.v);
dst_loop.e = BM_elem_index_get(src_loop.e);
dst_corner_verts[loop_i] = BM_elem_index_get(src_loop.v);
dst_corner_edges[loop_i] = BM_elem_index_get(src_loop.e);
bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data);
}
});
+3 -2
View File
@@ -10,6 +10,7 @@
/* Needed for BKE_ccg.h. */
#include "BLI_assert.h"
#include "BLI_bitmap.h"
#include "BLI_span.hh"
#include "BKE_ccg.h"
@@ -23,7 +24,6 @@ struct DMFlagMat;
struct Mesh;
struct MLoopTri;
struct CustomData;
struct MLoop;
struct MPoly;
struct SubdivCCG;
struct BMesh;
@@ -34,7 +34,8 @@ struct PBVH_GPU_Args {
BMesh *bm;
const Mesh *me;
const float (*vert_positions)[3];
const MLoop *mloop;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
const MPoly *polys;
int mesh_verts_num, mesh_faces_num, mesh_grids_num;
CustomData *vdata, *ldata, *pdata;
@@ -365,7 +365,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
mr->poly_normals = mr->me->poly_normals();
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
mr->loop_normals.reinitialize(mr->loops.size());
mr->loop_normals.reinitialize(mr->corner_verts.size());
short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop));
const bool *sharp_edges = static_cast<const bool *>(
@@ -373,7 +373,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
blender::bke::mesh::normals_calc_loop(mr->vert_positions,
mr->edges,
mr->polys,
mr->loops,
mr->corner_verts,
mr->corner_edges,
{},
mr->vert_normals,
mr->poly_normals,
@@ -548,7 +549,8 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->vert_positions = mr->me->vert_positions();
mr->edges = mr->me->edges();
mr->polys = mr->me->polys();
mr->loops = mr->me->loops();
mr->corner_verts = mr->me->corner_verts();
mr->corner_edges = mr->me->corner_edges();
mr->v_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX));
mr->e_origindex = static_cast<const int *>(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX));
+7 -5
View File
@@ -347,7 +347,7 @@ struct PBVHBatches {
const MPoly &poly = args->polys[tri->poly];
const float3 fno = blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const float3 *>(args->vert_positions), args->mesh_verts_num},
{&args->mloop[poly.loopstart], poly.totloop});
{&args->corner_verts[poly.loopstart], poly.totloop});
normal_float_to_short_v3(no, fno);
}
}
@@ -546,10 +546,10 @@ struct PBVHBatches {
void fill_vbo_faces(PBVHVbo &vbo, PBVH_GPU_Args *args)
{
const blender::Span<int> corner_verts = args->corner_verts;
auto foreach_faces =
[&](std::function<void(int buffer_i, int tri_i, int vertex_i, const MLoopTri *tri)> func) {
int buffer_i = 0;
const MLoop *mloop = args->mloop;
for (int i : IndexRange(args->totprim)) {
int face_index = args->mlooptri[args->prim_indices[i]].poly;
@@ -561,7 +561,7 @@ struct PBVHBatches {
const MLoopTri *tri = args->mlooptri + args->prim_indices[i];
for (int j : IndexRange(3)) {
func(buffer_i, j, mloop[tri->tri[j]].v, tri);
func(buffer_i, j, corner_verts[tri->tri[j]], tri);
buffer_i++;
}
}
@@ -990,7 +990,8 @@ struct PBVHBatches {
}
int r_edges[3];
BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges);
BKE_mesh_looptri_get_real_edges(
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);
if (r_edges[0] != -1) {
edge_count++;
@@ -1015,7 +1016,8 @@ struct PBVHBatches {
}
int r_edges[3];
BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges);
BKE_mesh_looptri_get_real_edges(
edges.data(), args->corner_verts.data(), args->corner_edges.data(), lt, r_edges);
if (r_edges[0] != -1) {
GPU_indexbuf_add_line_verts(&elb_lines, vertex_i, vertex_i + 1);
@@ -78,7 +78,8 @@ struct MeshRenderData {
blender::Span<blender::float3> vert_positions;
blender::Span<MEdge> edges;
blender::Span<MPoly> polys;
blender::Span<MLoop> loops;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
BMVert *eve_act;
BMEdge *eed_act;
BMFace *efa_act;
@@ -209,7 +209,6 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
const MLoop *mloop = mr->loops.data();
const int ml_index_end = poly->loopstart + poly->totloop;
bool mp_hidden, mp_select;
@@ -224,12 +223,11 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr,
}
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mloop[ml_index];
const int edge = mr->corner_edges[ml_index];
const int ml_index_last = poly->totloop + poly->loopstart - 1;
const int ml_index_next = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1);
const bool real_edge = (mr->e_origindex == nullptr ||
mr->e_origindex[ml->e] != ORIGINDEX_NONE);
const bool real_edge = (mr->e_origindex == nullptr || mr->e_origindex[edge] != ORIGINDEX_NONE);
edituv_edge_add(data, mp_hidden || !real_edge, mp_select, ml_index, ml_index_next);
}
}
@@ -402,9 +400,9 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
const int vert = mr->corner_verts[ml_index];
const bool real_vert = !mr->v_origindex || mr->v_origindex[ml->v] != ORIGINDEX_NONE;
const bool real_vert = !mr->v_origindex || mr->v_origindex[vert] != ORIGINDEX_NONE;
edituv_point_add(data, mp_hidden || !real_vert, mp_select, ml_index);
}
}
@@ -560,10 +558,10 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
const int vert = mr->corner_verts[ml_index];
const bool real_fdot = !mr->p_origindex || (mr->p_origindex[poly_index] != ORIGINDEX_NONE);
const bool subd_fdot = facedot_tags[ml->v];
const bool subd_fdot = facedot_tags[vert];
edituv_facedot_add(data, mp_hidden || !real_fdot || !subd_fdot, mp_select, poly_index);
}
}
@@ -50,8 +50,8 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
if (facedot_tags[ml->v] && !hidden) {
const int vert = mr->corner_verts[ml_index];
if (facedot_tags[vert] && !hidden) {
GPU_indexbuf_set_point_vert(elb, poly_index, poly_index);
return;
}
@@ -62,13 +62,13 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_last = poly->loopstart + (poly->totloop - 1);
int ml_index = ml_index_last, ml_index_next = poly->loopstart;
do {
const MLoop *ml = &mr->loops[ml_index];
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[ml->e]) ||
((e_origindex) && (e_origindex[ml->e] == ORIGINDEX_NONE)))) {
GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
const int edge = mr->corner_edges[ml_index];
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[edge]) ||
((e_origindex) && (e_origindex[edge] == ORIGINDEX_NONE)))) {
GPU_indexbuf_set_line_verts(elb, edge, ml_index, ml_index_next);
}
else {
GPU_indexbuf_set_line_restart(elb, ml->e);
GPU_indexbuf_set_line_restart(elb, edge);
}
} while ((ml_index = ml_index_next++) != ml_index_last);
}
@@ -76,8 +76,8 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_last = poly->loopstart + (poly->totloop - 1);
int ml_index = ml_index_last, ml_index_next = poly->loopstart;
do {
const MLoop *ml = &mr->loops[ml_index];
GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next);
const int edge = mr->corner_edges[ml_index];
GPU_indexbuf_set_line_verts(elb, edge, ml_index, ml_index_next);
} while ((ml_index = ml_index_next++) != ml_index_last);
}
}
@@ -123,9 +123,9 @@ static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr,
if (hidden) {
return;
}
lines_adjacency_triangle(mr->loops[mlt->tri[0]].v,
mr->loops[mlt->tri[1]].v,
mr->loops[mlt->tri[2]].v,
lines_adjacency_triangle(mr->corner_verts[mlt->tri[0]],
mr->corner_verts[mlt->tri[1]],
mr->corner_verts[mlt->tri[2]],
mlt->tri[0],
mlt->tri[1],
mlt->tri[2],
@@ -43,9 +43,8 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr,
MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data);
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
const int e_index = mr->corner_edges[ml_index];
const int e_index = ml->e;
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[e_index]) ||
((mr->e_origindex) && (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) {
@@ -76,8 +76,7 @@ static void extract_points_iter_poly_mesh(const MeshRenderData *mr,
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata);
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
vert_set_mesh(elb, mr, ml->v, ml_index);
vert_set_mesh(elb, mr, mr->corner_verts[ml_index], ml_index);
}
}
@@ -185,7 +185,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr,
BLI_assert(custom_data);
const int layer_index = request.layer_index;
const MLoop *mloop = mr->loops.data();
const Span<int> corner_verts = mr->corner_verts;
const Span<int> corner_edges = mr->corner_edges;
const AttributeType *attr_data = static_cast<const AttributeType *>(
CustomData_get_layer_n(custom_data, request.cd_type, layer_index));
@@ -194,8 +195,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr,
switch (request.domain) {
case ATTR_DOMAIN_POINT:
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) {
*vbo_data = Converter::convert_value(attr_data[mloop->v]);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) {
*vbo_data = Converter::convert_value(attr_data[corner_verts[ml_index]]);
}
break;
case ATTR_DOMAIN_CORNER:
@@ -204,8 +205,8 @@ static void fill_vertbuf_with_attribute(const MeshRenderData *mr,
}
break;
case ATTR_DOMAIN_EDGE:
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) {
*vbo_data = Converter::convert_value(attr_data[mloop->e]);
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) {
*vbo_data = Converter::convert_value(attr_data[corner_edges[ml_index]]);
}
break;
case ATTR_DOMAIN_FACE:
@@ -106,26 +106,27 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
const int vert = mr->corner_verts[ml_index];
const int edge = mr->corner_edges[ml_index];
if (data->use_edge_render) {
data->vbo_data[ml_index] = optimal_display_edges[ml->e] ? 255 : 0;
data->vbo_data[ml_index] = optimal_display_edges[edge] ? 255 : 0;
}
else {
/* Count loop per edge to detect non-manifold. */
if (data->edge_loop_count[ml->e] < 3) {
data->edge_loop_count[ml->e]++;
if (data->edge_loop_count[edge] < 3) {
data->edge_loop_count[edge]++;
}
if (data->edge_loop_count[ml->e] == 2) {
if (data->edge_loop_count[edge] == 2) {
/* Manifold */
const int ml_index_last = poly->totloop + poly->loopstart - 1;
const int ml_index_other = (ml_index == ml_index_last) ? poly->loopstart : (ml_index + 1);
const MLoop *ml_next = &mr->loops[ml_index_other];
const int vert_next = mr->corner_verts[ml_index_other];
float ratio = loop_edge_factor_get(mr->poly_normals[poly_index],
mr->vert_positions[ml->v],
mr->vert_normals[ml->v],
mr->vert_positions[ml_next->v]);
mr->vert_positions[vert],
mr->vert_normals[vert],
mr->vert_positions[vert_next]);
data->vbo_data[ml_index] = ratio * 253 + 1;
}
else {
@@ -153,12 +153,11 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
EditLoopData *data = vbo_data + ml_index;
memset(data, 0x0, sizeof(*data));
BMFace *efa = bm_original_face_get(mr, poly_index);
BMEdge *eed = bm_original_edge_get(mr, ml->e);
BMVert *eve = bm_original_vert_get(mr, ml->v);
BMVert *eve = bm_original_vert_get(mr, mr->corner_verts[ml_index]);
BMEdge *eed = bm_original_edge_get(mr, mr->corner_edges[ml_index]);
if (efa) {
mesh_render_data_face_flag(mr, efa, {-1, -1, -1, -1}, data);
}
@@ -77,14 +77,12 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
const int ml_index_end = poly->loopstart + poly->totloop;
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index];
EditLoopData *eldata = &data->vbo_data[ml_index];
memset(eldata, 0x0, sizeof(*eldata));
BMFace *efa = bm_original_face_get(mr, poly_index);
if (efa) {
BMEdge *eed = bm_original_edge_get(mr, ml->e);
BMVert *eve = bm_original_vert_get(mr, ml->v);
BMVert *eve = bm_original_vert_get(mr, mr->corner_verts[ml_index]);
BMEdge *eed = bm_original_edge_get(mr, mr->corner_edges[ml_index]);
if (eed && eve) {
/* Loop on an edge endpoint. */
BMLoop *l = BM_face_edge_share_loop(efa, eed);
@@ -97,8 +95,7 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
* For this, we check if the previous loop was on an edge. */
const int ml_index_last = poly->loopstart + poly->totloop - 1;
const int l_prev = (ml_index == poly->loopstart) ? ml_index_last : (ml_index - 1);
const MLoop *ml_prev = &mr->loops[l_prev];
eed = bm_original_edge_get(mr, ml_prev->e);
eed = bm_original_edge_get(mr, mr->corner_edges[l_prev]);
}
if (eed) {
/* Mapped points on an edge between two edit verts. */
@@ -173,8 +173,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
av,
data->uv[ml_index_last],
data->uv[l_next_tmp],
mr->vert_positions[mr->loops[ml_index_last].v],
mr->vert_positions[mr->loops[l_next_tmp].v]);
mr->vert_positions[mr->corner_verts[ml_index_last]],
mr->vert_positions[mr->corner_verts[l_next_tmp]]);
/* Save last edge. */
copy_v2_v2(last_auv, auv[1]);
copy_v3_v3(last_av, av[1]);
@@ -193,8 +193,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
av,
data->uv[ml_index],
data->uv[l_next],
mr->vert_positions[mr->loops[ml_index].v],
mr->vert_positions[mr->loops[l_next].v]);
mr->vert_positions[mr->corner_verts[ml_index]],
mr->vert_positions[mr->corner_verts[l_next]]);
}
edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]);
}
@@ -77,8 +77,8 @@ static void compute_area_ratio(const MeshRenderData *mr,
const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2);
for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) {
const MPoly &poly = mr->polys[poly_index];
const float area = bke::mesh::poly_area_calc(mr->vert_positions,
mr->loops.slice(poly.loopstart, poly.totloop));
const float area = bke::mesh::poly_area_calc(
mr->vert_positions, mr->corner_verts.slice(poly.loopstart, poly.totloop));
float uvarea = area_poly_v2(reinterpret_cast<const float(*)[2]>(&uv_data[poly.loopstart]),
poly.totloop);
tot_area += area;

Some files were not shown because too many files have changed in this diff Show More