Mesh: Rename "polys" to "faces"
Implements part of #101689. The "poly" name was chosen to distinguish the `MLoop` + `MPoly` combination from the `MFace` struct it replaced. Those two structures persisted together for a long time, but nowadays `MPoly` is gone, and `MFace` is only used in some legacy code like the particle system. To avoid unnecessarily using a different term, increase consistency with the UI and with BMesh, and generally make code a bit easier to read, this commit replaces the `poly` term with `poly`. Most variables that use the term are renamed too. `Mesh.totface` and `Mesh.fdata` now have a `_legacy` suffix to reduce confusion. In a next step, `pdata` can be renamed to `face_data` as well. Pull Request: https://projects.blender.org/blender/blender/pulls/109819
This commit is contained in:
@@ -247,10 +247,10 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
|
||||
if (polys_num == 0) {
|
||||
return;
|
||||
}
|
||||
const int *poly_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
const int *face_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
for (int i = 0; i < polys_num; i++) {
|
||||
const int poly_start = poly_offsets[i];
|
||||
const int poly_size = poly_offsets[i + 1] - poly_start;
|
||||
const int poly_start = face_offsets[i];
|
||||
const int poly_size = face_offsets[i + 1] - poly_start;
|
||||
for (int j = 0; j < poly_size; j++) {
|
||||
*data = get_value_at_index(poly_start + j);
|
||||
data++;
|
||||
@@ -320,10 +320,10 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
|
||||
}
|
||||
else {
|
||||
const int tris_num = b_mesh.loop_triangles.length();
|
||||
const int *looptri_polys = static_cast<const int *>(
|
||||
const int *looptri_faces = static_cast<const int *>(
|
||||
b_mesh.loop_triangle_polygons[0].ptr.data);
|
||||
for (int i = 0; i < tris_num; i++) {
|
||||
data[i] = get_value_at_index(looptri_polys[i]);
|
||||
data[i] = get_value_at_index(looptri_faces[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -624,7 +624,7 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
if (polys_num == 0) {
|
||||
return;
|
||||
}
|
||||
const int *poly_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
const int *face_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
|
||||
if (!b_mesh.uv_layers.empty()) {
|
||||
BL::Mesh::uv_layers_iterator l;
|
||||
@@ -660,8 +660,8 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
float2 *fdata = uv_attr->data_float2();
|
||||
|
||||
for (int i = 0; i < polys_num; i++) {
|
||||
const int poly_start = poly_offsets[i];
|
||||
const int poly_size = poly_offsets[i + 1] - poly_start;
|
||||
const int poly_start = face_offsets[i];
|
||||
const int poly_size = face_offsets[i + 1] - poly_start;
|
||||
for (int j = 0; j < poly_size; j++) {
|
||||
*(fdata++) = get_float2(l->data[poly_start + j].uv());
|
||||
}
|
||||
@@ -937,9 +937,9 @@ static void attr_create_random_per_island(Scene *scene,
|
||||
else {
|
||||
const int polys_num = b_mesh.polygons.length();
|
||||
if (polys_num != 0) {
|
||||
const int *poly_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
const int *face_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
for (int i = 0; i < polys_num; i++) {
|
||||
const int vert = corner_verts[poly_offsets[i]];
|
||||
const int vert = corner_verts[face_offsets[i]];
|
||||
data[i] = hash_uint_to_float(vertices_sets.find(vert));
|
||||
}
|
||||
}
|
||||
@@ -1068,10 +1068,10 @@ static void create_mesh(Scene *scene,
|
||||
numtris = numfaces;
|
||||
}
|
||||
else {
|
||||
const int *poly_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
const int *face_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
for (int i = 0; i < polys_num; i++) {
|
||||
const int poly_start = poly_offsets[i];
|
||||
const int poly_size = poly_offsets[i + 1] - poly_start;
|
||||
const int poly_start = face_offsets[i];
|
||||
const int poly_size = face_offsets[i + 1] - poly_start;
|
||||
numngons += (poly_size == 4) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
@@ -1138,10 +1138,10 @@ static void create_mesh(Scene *scene,
|
||||
}
|
||||
|
||||
if (material_indices) {
|
||||
const int *looptri_polys = static_cast<const int *>(
|
||||
const int *looptri_faces = static_cast<const int *>(
|
||||
b_mesh.loop_triangle_polygons[0].ptr.data);
|
||||
for (int i = 0; i < numtris; i++) {
|
||||
shader[i] = clamp_material_index(material_indices[looptri_polys[i]]);
|
||||
shader[i] = clamp_material_index(material_indices[looptri_faces[i]]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1149,10 +1149,10 @@ static void create_mesh(Scene *scene,
|
||||
}
|
||||
|
||||
if (sharp_faces && !(use_loop_normals && corner_normals)) {
|
||||
const int *looptri_polys = static_cast<const int *>(
|
||||
const int *looptri_faces = static_cast<const int *>(
|
||||
b_mesh.loop_triangle_polygons[0].ptr.data);
|
||||
for (int i = 0; i < numtris; i++) {
|
||||
smooth[i] = !sharp_faces[looptri_polys[i]];
|
||||
smooth[i] = !sharp_faces[looptri_faces[i]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1203,11 +1203,11 @@ static void create_mesh(Scene *scene,
|
||||
|
||||
std::copy(corner_verts, corner_verts + numcorners, subd_face_corners);
|
||||
|
||||
const int *poly_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
const int *face_offsets = static_cast<const int *>(b_mesh.polygons[0].ptr.data);
|
||||
int ptex_offset = 0;
|
||||
for (int i = 0; i < numfaces; i++) {
|
||||
const int poly_start = poly_offsets[i];
|
||||
const int poly_size = poly_offsets[i + 1] - poly_start;
|
||||
const int poly_start = face_offsets[i];
|
||||
const int poly_size = face_offsets[i + 1] - poly_start;
|
||||
|
||||
subd_start_corner[i] = poly_start;
|
||||
subd_num_corners[i] = poly_size;
|
||||
|
||||
@@ -90,7 +90,7 @@ struct DerivedMesh {
|
||||
int numVertData, numEdgeData, numTessFaceData, numLoopData, numPolyData;
|
||||
DerivedMeshType type;
|
||||
/* Always owned by this object. */
|
||||
int *poly_offsets;
|
||||
int *face_offsets;
|
||||
|
||||
short tangent_mask; /* which tangent layers are calculated */
|
||||
|
||||
@@ -123,7 +123,7 @@ struct DerivedMesh {
|
||||
void (*copyEdgeArray)(DerivedMesh *dm, struct vec2i *r_edge);
|
||||
void (*copyCornerVertArray)(DerivedMesh *dm, int *r_corner_verts);
|
||||
void (*copyCornerEdgeArray)(DerivedMesh *dm, int *r_corner_edges);
|
||||
void (*copyPolyArray)(DerivedMesh *dm, int *r_poly_offsets);
|
||||
void (*copyPolyArray)(DerivedMesh *dm, int *r_face_offsets);
|
||||
|
||||
/** Return a pointer to the entire array of vert/edge/face custom data
|
||||
* from the derived mesh (this gives a pointer to the actual data, not
|
||||
|
||||
@@ -698,7 +698,7 @@ enum {
|
||||
/* Multiple types of mesh elements... */
|
||||
CD_FAKE_UV =
|
||||
CD_FAKE |
|
||||
CD_PROP_FLOAT2, /* UV flag, because we handle both loop's UVs and poly's textures. */
|
||||
CD_PROP_FLOAT2, /* UV flag, because we handle both loop's UVs and face's textures. */
|
||||
|
||||
CD_FAKE_LNOR = CD_FAKE |
|
||||
CD_CUSTOMLOOPNORMAL, /* Because we play with clnor and temp lnor layers here. */
|
||||
|
||||
@@ -85,7 +85,7 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(int dtdata_type);
|
||||
DT_TYPE_FREESTYLE_EDGE)
|
||||
#define DT_DATATYPE_IS_LOOP(_dt) \
|
||||
ELEM(_dt, DT_TYPE_UV, DT_TYPE_LNOR, DT_TYPE_MLOOPCOL_LOOP, DT_TYPE_MPROPCOL_LOOP)
|
||||
#define DT_DATATYPE_IS_POLY(_dt) ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE)
|
||||
#define DT_DATATYPE_IS_FACE(_dt) ELEM(_dt, DT_TYPE_UV, DT_TYPE_SHARP_FACE, DT_TYPE_FREESTYLE_FACE)
|
||||
|
||||
#define DT_DATATYPE_IS_MULTILAYERS(_dt) \
|
||||
ELEM(_dt, \
|
||||
|
||||
@@ -252,7 +252,7 @@ void BKE_defvert_normalize_lock_map(struct MDeformVert *dvert,
|
||||
int defbase_num);
|
||||
|
||||
/* Utilities to 'extract' a given vgroup into a simple float array,
|
||||
* for verts, but also edges/polys/loops. */
|
||||
* for verts, but also edges/faces/loops. */
|
||||
|
||||
void BKE_defvert_extract_vgroup_to_vertweights(const struct MDeformVert *dvert,
|
||||
int defgroup,
|
||||
@@ -281,12 +281,12 @@ void BKE_defvert_extract_vgroup_to_loopweights(const struct MDeformVert *dvert,
|
||||
bool invert_vgroup,
|
||||
float *r_weights);
|
||||
|
||||
void BKE_defvert_extract_vgroup_to_polyweights(const struct MDeformVert *dvert,
|
||||
void BKE_defvert_extract_vgroup_to_faceweights(const struct MDeformVert *dvert,
|
||||
int defgroup,
|
||||
int verts_num,
|
||||
const int *corner_verts,
|
||||
int loops_num,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
bool invert_vgroup,
|
||||
float *r_weights);
|
||||
|
||||
|
||||
@@ -16,22 +16,22 @@ struct BMEditMesh;
|
||||
namespace blender::bke {
|
||||
|
||||
struct EditMeshData {
|
||||
/** when set, \a vertexNos, polyNos are lazy initialized */
|
||||
/** when set, \a vertexNos, faceNos are lazy initialized */
|
||||
Array<float3> vertexCos;
|
||||
|
||||
/** lazy initialize (when \a vertexCos is set) */
|
||||
Array<float3> vertexNos;
|
||||
Array<float3> polyNos;
|
||||
Array<float3> faceNos;
|
||||
/** also lazy init but don't depend on \a vertexCos */
|
||||
Array<float3> polyCos;
|
||||
Array<float3> faceCos;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, blender::bke::EditMeshData *emd);
|
||||
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh *em, blender::bke::EditMeshData *emd);
|
||||
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, blender::bke::EditMeshData *emd);
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, blender::bke::EditMeshData *emd);
|
||||
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh *em, blender::bke::EditMeshData *emd);
|
||||
|
||||
bool BKE_editmesh_cache_calc_minmax(BMEditMesh *em,
|
||||
blender::bke::EditMeshData *emd,
|
||||
|
||||
@@ -24,7 +24,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
const float (*poly_normals)[3],
|
||||
const float (*face_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
CustomData *dm_loopdata_out,
|
||||
|
||||
@@ -137,18 +137,18 @@ void BKE_keyblock_convert_to_mesh(const struct KeyBlock *kb,
|
||||
int totvert);
|
||||
|
||||
/**
|
||||
* Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key.
|
||||
* Computes normals (vertices, faces and/or loops ones) of given mesh for given shape key.
|
||||
*
|
||||
* \param kb: the KeyBlock to use to compute normals.
|
||||
* \param mesh: the Mesh to apply key-block to.
|
||||
* \param r_vert_normals: if non-NULL, an array of vectors, same length as number of vertices.
|
||||
* \param r_poly_normals: if non-NULL, an array of vectors, same length as number of polygons.
|
||||
* \param r_face_normals: if non-NULL, an array of vectors, same length as number of faces.
|
||||
* \param r_loop_normals: if non-NULL, an array of vectors, same length as number of loops.
|
||||
*/
|
||||
void BKE_keyblock_mesh_calc_normals(const struct KeyBlock *kb,
|
||||
struct Mesh *mesh,
|
||||
float (*r_vert_normals)[3],
|
||||
float (*r_poly_normals)[3],
|
||||
float (*r_face_normals)[3],
|
||||
float (*r_loop_normals)[3]);
|
||||
|
||||
void BKE_keyblock_update_from_vertcos(const struct Object *ob,
|
||||
|
||||
@@ -146,17 +146,17 @@ void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *m
|
||||
void BKE_mesh_copy_parameters(struct Mesh *me_dst, const struct Mesh *me_src);
|
||||
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
|
||||
|
||||
/** Add poly offsets to describe faces to a new mesh. */
|
||||
void BKE_mesh_poly_offsets_ensure_alloc(struct Mesh *mesh);
|
||||
/** Add face offsets to describe faces to a new mesh. */
|
||||
void BKE_mesh_face_offsets_ensure_alloc(struct Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_new_nomain(int verts_num, int edges_num, int polys_num, int loops_num);
|
||||
struct Mesh *BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int loops_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template(
|
||||
const struct Mesh *me_src, int verts_num, int edges_num, int polys_num, int loops_num);
|
||||
const struct Mesh *me_src, int verts_num, int edges_num, int faces_num, int loops_num);
|
||||
struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
|
||||
int verts_num,
|
||||
int edges_num,
|
||||
int tessface_num,
|
||||
int polys_num,
|
||||
int faces_num,
|
||||
int loops_num,
|
||||
struct CustomData_MeshMasks mask);
|
||||
|
||||
@@ -298,11 +298,11 @@ 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 int *corner_verts,
|
||||
const int *poly_offsets,
|
||||
const int *face_offsets,
|
||||
const float (*vert_positions)[3],
|
||||
int totvert,
|
||||
int totloop,
|
||||
int totpoly,
|
||||
int faces_num,
|
||||
struct MLoopTri *mlooptri);
|
||||
|
||||
/* *** mesh_normals.cc *** */
|
||||
@@ -339,10 +339,10 @@ void BKE_mesh_vert_normals_clear_dirty(struct Mesh *mesh);
|
||||
bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Return true if the mesh polygon normals either are not stored or are dirty.
|
||||
* Return true if the mesh face normals either are not stored or are dirty.
|
||||
* This can be used to help decide whether to transfer them when copying a mesh.
|
||||
*/
|
||||
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
|
||||
bool BKE_mesh_face_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Called after calculating all modifiers.
|
||||
@@ -507,14 +507,14 @@ float BKE_mesh_calc_area(const struct Mesh *me);
|
||||
|
||||
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
|
||||
/**
|
||||
* Calculate the center from polygons,
|
||||
* Calculate the center from faces,
|
||||
* use when we want to ignore vertex locations that don't have connected faces.
|
||||
*/
|
||||
bool BKE_mesh_center_median_from_polys(const struct Mesh *me, float r_cent[3]);
|
||||
bool BKE_mesh_center_median_from_faces(const struct Mesh *me, float r_cent[3]);
|
||||
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
|
||||
/**
|
||||
* \note Mesh must be manifold with consistent face-winding,
|
||||
* see #mesh_calc_poly_volume_centroid for details.
|
||||
* see #mesh_calc_face_volume_centroid for details.
|
||||
*/
|
||||
bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
|
||||
|
||||
@@ -539,38 +539,38 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
|
||||
void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
|
||||
|
||||
/**
|
||||
* Flip (invert winding of) the given \a poly, i.e. reverse order of its loops
|
||||
* Flip (invert winding of) the given \a face, i.e. reverse order of its loops
|
||||
* (keeping the same vertex as 'start point').
|
||||
*
|
||||
* \param poly: the polygon to flip.
|
||||
* \param face: the face to flip.
|
||||
* \param mloop: the full loops array.
|
||||
* \param ldata: the loops custom data.
|
||||
*/
|
||||
void BKE_mesh_polygon_flip_ex(int poly_offset,
|
||||
int poly_size,
|
||||
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(int poly_offset,
|
||||
int poly_size,
|
||||
void BKE_mesh_face_flip_ex(int face_offset,
|
||||
int face_size,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
struct CustomData *ldata,
|
||||
int totloop);
|
||||
float (*lnors)[3],
|
||||
struct MDisps *mdisp,
|
||||
bool use_loop_mdisp_flip);
|
||||
void BKE_mesh_face_flip(int face_offset,
|
||||
int face_size,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
struct CustomData *ldata,
|
||||
int totloop);
|
||||
|
||||
/**
|
||||
* Flip (invert winding of) all polygons (used to inverse their normals).
|
||||
* Flip (invert winding of) all faces (used to inverse their normals).
|
||||
*
|
||||
* \note Invalidates tessellation, caller must handle that.
|
||||
*/
|
||||
void BKE_mesh_polys_flip(const int *poly_offsets,
|
||||
void BKE_mesh_faces_flip(const int *face_offsets,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
struct CustomData *ldata,
|
||||
int totpoly);
|
||||
int faces_num);
|
||||
|
||||
/**
|
||||
* Account for custom-data such as UVs becoming detached because of imprecision
|
||||
@@ -586,9 +586,9 @@ void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *me);
|
||||
* Update the hide flag for edges and faces from the corresponding flag in verts.
|
||||
*/
|
||||
void BKE_mesh_flush_hidden_from_verts(struct Mesh *me);
|
||||
void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
|
||||
void BKE_mesh_flush_hidden_from_faces(struct Mesh *me);
|
||||
|
||||
void BKE_mesh_flush_select_from_polys(struct Mesh *me);
|
||||
void BKE_mesh_flush_select_from_faces(struct Mesh *me);
|
||||
void BKE_mesh_flush_select_from_verts(struct Mesh *me);
|
||||
|
||||
/* spatial evaluation */
|
||||
@@ -603,8 +603,8 @@ void BKE_mesh_flush_select_from_verts(struct Mesh *me);
|
||||
* \param vert_cos_org: reference for the output location.
|
||||
* \param vert_cos_new: resulting coords.
|
||||
*/
|
||||
void BKE_mesh_calc_relative_deform(const int *poly_offsets,
|
||||
int totpoly,
|
||||
void BKE_mesh_calc_relative_deform(const int *face_offsets,
|
||||
int faces_num,
|
||||
const int *corner_verts,
|
||||
int totvert,
|
||||
|
||||
@@ -628,7 +628,7 @@ bool BKE_mesh_validate(struct Mesh *me, bool do_verbose, bool cddata_check_mask)
|
||||
*/
|
||||
bool BKE_mesh_is_valid(struct Mesh *me);
|
||||
/**
|
||||
* Check all material indices of polygons are valid, invalid ones are set to 0.
|
||||
* Check all material indices of faces are valid, invalid ones are set to 0.
|
||||
* \returns True if the material indices are valid.
|
||||
*/
|
||||
bool BKE_mesh_validate_material_indices(struct Mesh *me);
|
||||
@@ -660,8 +660,8 @@ bool BKE_mesh_validate_arrays(struct Mesh *me,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
unsigned int totloop,
|
||||
int *poly_offsets,
|
||||
unsigned int totpoly,
|
||||
int *face_offsets,
|
||||
unsigned int faces_num,
|
||||
struct MDeformVert *dverts, /* assume totvert length */
|
||||
bool do_verbose,
|
||||
bool do_fixes,
|
||||
@@ -679,7 +679,7 @@ bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
|
||||
struct CustomData *ldata,
|
||||
uint totloop,
|
||||
struct CustomData *pdata,
|
||||
uint totpoly,
|
||||
uint faces_num,
|
||||
bool check_meshmask,
|
||||
bool do_verbose,
|
||||
bool do_fixes,
|
||||
@@ -688,7 +688,7 @@ bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
|
||||
void BKE_mesh_strip_loose_faces(struct Mesh *me);
|
||||
|
||||
/**
|
||||
* Calculate edges from polygons.
|
||||
* Calculate edges from faces.
|
||||
*/
|
||||
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool select_new_edges);
|
||||
/**
|
||||
@@ -726,27 +726,28 @@ void BKE_mesh_debug_print(const struct Mesh *me) ATTR_NONNULL(1);
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \return The material index for each polygon. May be null.
|
||||
* \return The material index for each face. May be null.
|
||||
* \note In C++ code, prefer using the attribute API (#AttributeAccessor).
|
||||
*/
|
||||
BLI_INLINE const int *BKE_mesh_material_indices(const Mesh *mesh)
|
||||
{
|
||||
return (const int *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index");
|
||||
return (const int *)CustomData_get_layer_named(
|
||||
&mesh->pdata, CD_PROP_INT32, "material_index");
|
||||
}
|
||||
|
||||
/**
|
||||
* \return The material index for each polygon. Create the layer if it doesn't exist.
|
||||
* \return The material index for each face. Create the layer if it doesn't exist.
|
||||
* \note In C++ code, prefer using the attribute API (#MutableAttributeAccessor).
|
||||
*/
|
||||
BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
|
||||
{
|
||||
int *indices = (int *)CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_INT32, "material_index", mesh->totpoly);
|
||||
&mesh->pdata, CD_PROP_INT32, "material_index", mesh->faces_num);
|
||||
if (indices) {
|
||||
return indices;
|
||||
}
|
||||
return (int *)CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totpoly, "material_index");
|
||||
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->faces_num, "material_index");
|
||||
}
|
||||
|
||||
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
|
||||
@@ -759,9 +760,9 @@ BLI_INLINE float (*BKE_mesh_vert_positions_for_write(Mesh *mesh))[3]
|
||||
&mesh->vdata, CD_PROP_FLOAT3, "position", mesh->totvert);
|
||||
}
|
||||
|
||||
BLI_INLINE const int *BKE_mesh_poly_offsets(const Mesh *mesh)
|
||||
BLI_INLINE const int *BKE_mesh_face_offsets(const Mesh *mesh)
|
||||
{
|
||||
return mesh->poly_offset_indices;
|
||||
return mesh->face_offset_indices;
|
||||
}
|
||||
|
||||
BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh)
|
||||
|
||||
@@ -16,40 +16,40 @@ namespace blender::bke::mesh {
|
||||
/** \name Polygon Data Evaluation
|
||||
* \{ */
|
||||
|
||||
/** Calculate the up direction for the polygon, depending on its winding direction. */
|
||||
float3 poly_normal_calc(Span<float3> vert_positions, Span<int> poly_verts);
|
||||
/** Calculate the up direction for the face, depending on its winding direction. */
|
||||
float3 face_normal_calc(Span<float3> vert_positions, Span<int> face_verts);
|
||||
|
||||
/**
|
||||
* Calculate tessellation into #MLoopTri which exist only for this purpose.
|
||||
*/
|
||||
void looptris_calc(Span<float3> vert_positions,
|
||||
OffsetIndices<int> polys,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
MutableSpan<MLoopTri> looptris);
|
||||
/**
|
||||
* A version of #looptris_calc which takes pre-calculated polygon normals
|
||||
* A version of #looptris_calc which takes pre-calculated face normals
|
||||
* (used to avoid having to calculate the face normal for NGON tessellation).
|
||||
*
|
||||
* \note Only use this function if normals have already been calculated, there is no need
|
||||
* to calculate normals just to use this function.
|
||||
*/
|
||||
void looptris_calc_with_normals(Span<float3> vert_positions,
|
||||
OffsetIndices<int> polys,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
MutableSpan<MLoopTri> looptris);
|
||||
|
||||
void looptris_calc_poly_indices(OffsetIndices<int> polys, MutableSpan<int> looptri_polys);
|
||||
void looptris_calc_face_indices(OffsetIndices<int> faces, MutableSpan<int> looptri_faces);
|
||||
|
||||
/** Calculate the average position of the vertices in the polygon. */
|
||||
float3 poly_center_calc(Span<float3> vert_positions, Span<int> poly_verts);
|
||||
/** Calculate the average position of the vertices in the face. */
|
||||
float3 face_center_calc(Span<float3> vert_positions, Span<int> face_verts);
|
||||
|
||||
/** Calculate the surface area of the polygon described by the indexed vertices. */
|
||||
float poly_area_calc(Span<float3> vert_positions, Span<int> poly_verts);
|
||||
/** Calculate the surface area of the face described by the indexed vertices. */
|
||||
float face_area_calc(Span<float3> vert_positions, Span<int> face_verts);
|
||||
|
||||
/** Calculate the angles at each of the polygons corners. */
|
||||
void poly_angles_calc(Span<float3> vert_positions,
|
||||
Span<int> poly_verts,
|
||||
/** Calculate the angles at each of the faces corners. */
|
||||
void face_angles_calc(Span<float3> vert_positions,
|
||||
Span<int> face_verts,
|
||||
MutableSpan<float> angles);
|
||||
|
||||
/** \} */
|
||||
@@ -61,13 +61,13 @@ void poly_angles_calc(Span<float3> vert_positions,
|
||||
/**
|
||||
* Calculate face normals directly into a result array.
|
||||
*
|
||||
* \note Usually #Mesh::poly_normals() is the preferred way to access face normals,
|
||||
* \note Usually #Mesh::face_normals() is the preferred way to access face normals,
|
||||
* since they may already be calculated and cached on the mesh.
|
||||
*/
|
||||
void normals_calc_polys(Span<float3> vert_positions,
|
||||
OffsetIndices<int> polys,
|
||||
void normals_calc_faces(Span<float3> vert_positions,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals);
|
||||
MutableSpan<float3> face_normals);
|
||||
|
||||
/**
|
||||
* Calculate face and vertex normals directly into result arrays.
|
||||
@@ -75,10 +75,10 @@ void normals_calc_polys(Span<float3> vert_positions,
|
||||
* \note Usually #Mesh::vert_normals() is the preferred way to access vertex normals,
|
||||
* since they may already be calculated and cached on the mesh.
|
||||
*/
|
||||
void normals_calc_poly_vert(Span<float3> vert_positions,
|
||||
OffsetIndices<int> polys,
|
||||
void normals_calc_face_vert(Span<float3> vert_positions,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals,
|
||||
MutableSpan<float3> face_normals,
|
||||
MutableSpan<float3> vert_normals);
|
||||
|
||||
/** \} */
|
||||
@@ -136,11 +136,11 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
||||
const float3 &custom_lnor);
|
||||
|
||||
/**
|
||||
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
|
||||
* Compute split normals, i.e. vertex normals associated with each face (hence 'loop normals').
|
||||
* 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 corners to their polygon.
|
||||
* \param loop_to_face_map: Optional pre-created map from corners to their face.
|
||||
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
|
||||
* each side of the edge.
|
||||
* \param r_lnors_spacearr: Optional return data filled with information about the custom
|
||||
@@ -148,12 +148,12 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
||||
*/
|
||||
void normals_calc_loop(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> polys,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<int> loop_to_poly_map,
|
||||
Span<int> loop_to_face_map,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
bool use_split_normals,
|
||||
@@ -164,11 +164,11 @@ void normals_calc_loop(Span<float3> vert_positions,
|
||||
|
||||
void normals_loop_custom_set(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> polys,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_loop_normals,
|
||||
@@ -176,11 +176,11 @@ void normals_loop_custom_set(Span<float3> vert_positions,
|
||||
|
||||
void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> polys,
|
||||
OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_vert_normals,
|
||||
@@ -194,10 +194,10 @@ 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(OffsetIndices<int> polys,
|
||||
void edges_sharp_from_angle_set(OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
const float split_angle,
|
||||
MutableSpan<bool> sharp_edges);
|
||||
@@ -209,48 +209,48 @@ void edges_sharp_from_angle_set(OffsetIndices<int> polys,
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Find the index of the next corner in the polygon, looping to the start if necessary.
|
||||
* The indices are into the entire corners array, not just the polygon's corners.
|
||||
* Find the index of the next corner in the face, looping to the start if necessary.
|
||||
* The indices are into the entire corners array, not just the face's corners.
|
||||
*/
|
||||
inline int poly_corner_prev(const IndexRange poly, const int corner)
|
||||
inline int face_corner_prev(const IndexRange face, const int corner)
|
||||
{
|
||||
return corner - 1 + (corner == poly.start()) * poly.size();
|
||||
return corner - 1 + (corner == face.start()) * face.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the previous corner in the polygon, looping to the end if necessary.
|
||||
* The indices are into the entire corners array, not just the polygon's corners.
|
||||
* Find the index of the previous corner in the face, looping to the end if necessary.
|
||||
* The indices are into the entire corners array, not just the face's corners.
|
||||
*/
|
||||
inline int poly_corner_next(const IndexRange poly, const int corner)
|
||||
inline int face_corner_next(const IndexRange face, const int corner)
|
||||
{
|
||||
if (corner == poly.last()) {
|
||||
return poly.start();
|
||||
if (corner == face.last()) {
|
||||
return face.start();
|
||||
}
|
||||
return corner + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the corner in the polygon that uses the given vertex.
|
||||
* The index is into the entire corners array, not just the polygon's corners.
|
||||
* Find the index of the corner in the face that uses the given vertex.
|
||||
* The index is into the entire corners array, not just the face's corners.
|
||||
*/
|
||||
inline int poly_find_corner_from_vert(const IndexRange poly,
|
||||
inline int face_find_corner_from_vert(const IndexRange face,
|
||||
const Span<int> corner_verts,
|
||||
const int vert)
|
||||
{
|
||||
return poly[corner_verts.slice(poly).first_index(vert)];
|
||||
return face[corner_verts.slice(face).first_index(vert)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the vertex indices on either side of the given vertex, ordered based on the winding
|
||||
* direction of the polygon. The vertex must be in the polygon.
|
||||
* direction of the face. The vertex must be in the face.
|
||||
*/
|
||||
inline int2 poly_find_adjecent_verts(const IndexRange poly,
|
||||
inline int2 face_find_adjecent_verts(const IndexRange face,
|
||||
const Span<int> corner_verts,
|
||||
const int vert)
|
||||
{
|
||||
const int corner = poly_find_corner_from_vert(poly, corner_verts, vert);
|
||||
return {corner_verts[poly_corner_prev(poly, corner)],
|
||||
corner_verts[poly_corner_next(poly, corner)]};
|
||||
const int corner = face_find_corner_from_vert(face, corner_verts, vert);
|
||||
return {corner_verts[face_corner_prev(face, corner)],
|
||||
corner_verts[face_corner_next(face, corner)]};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,16 +302,16 @@ inline blender::MutableSpan<blender::int2> Mesh::edges_for_write()
|
||||
this->totedge};
|
||||
}
|
||||
|
||||
inline blender::OffsetIndices<int> Mesh::polys() const
|
||||
inline blender::OffsetIndices<int> Mesh::faces() const
|
||||
{
|
||||
return blender::Span(this->poly_offset_indices, this->totpoly + 1);
|
||||
return blender::Span(this->face_offset_indices, this->faces_num + 1);
|
||||
}
|
||||
inline blender::Span<int> Mesh::poly_offsets() const
|
||||
inline blender::Span<int> Mesh::face_offsets() const
|
||||
{
|
||||
if (this->totpoly == 0) {
|
||||
if (this->faces_num == 0) {
|
||||
return {};
|
||||
}
|
||||
return {this->poly_offset_indices, this->totpoly + 1};
|
||||
return {this->face_offset_indices, this->faces_num + 1};
|
||||
}
|
||||
|
||||
inline blender::Span<int> Mesh::corner_verts() const
|
||||
|
||||
@@ -112,10 +112,10 @@ void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
|
||||
* but oriented to be used in #do_versions from `readfile.c`
|
||||
* the difference is how active/render/clone/stencil indices are handled here.
|
||||
*
|
||||
* normally they're being set from `pdata` which totally makes sense for meshes which are already
|
||||
* converted to #BMesh structures, but when loading older files indices shall be updated in other
|
||||
* way around, so newly added `pdata` and `ldata` would have this indices set
|
||||
* based on `fdata` layer.
|
||||
* normally they're being set from `pdata` which totally makes sense for meshes which are
|
||||
* already converted to #BMesh structures, but when loading older files indices shall be updated in
|
||||
* other way around, so newly added `pdata` and `ldata` would have this indices set based on
|
||||
* `pdata` layer.
|
||||
*
|
||||
* this is normally only needed when reading older files,
|
||||
* in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
|
||||
|
||||
@@ -30,8 +30,8 @@ typedef struct UvVertMap {
|
||||
|
||||
typedef struct UvMapVert {
|
||||
struct UvMapVert *next;
|
||||
unsigned int poly_index;
|
||||
unsigned short loop_of_poly_index;
|
||||
unsigned int face_index;
|
||||
unsigned short loop_of_face_index;
|
||||
bool separate;
|
||||
} UvMapVert;
|
||||
|
||||
@@ -44,7 +44,7 @@ typedef struct UvElement {
|
||||
/* Face the element belongs to */
|
||||
struct BMLoop *l;
|
||||
/* index in loop. */
|
||||
unsigned short loop_of_poly_index;
|
||||
unsigned short loop_of_face_index;
|
||||
/* Whether this element is the first of coincident elements */
|
||||
bool separate;
|
||||
/* general use flag */
|
||||
@@ -104,7 +104,7 @@ typedef struct MeshElemMap {
|
||||
|
||||
/* mapping */
|
||||
|
||||
UvVertMap *BKE_mesh_uv_vert_map_create(blender::OffsetIndices<int> polys,
|
||||
UvVertMap *BKE_mesh_uv_vert_map_create(blender::OffsetIndices<int> faces,
|
||||
const bool *hide_poly,
|
||||
const bool *select_poly,
|
||||
const int *corner_verts,
|
||||
@@ -134,7 +134,7 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
|
||||
const int *corner_verts,
|
||||
int totloop);
|
||||
/**
|
||||
* This function creates a map so the source-data (vert/edge/loop/poly)
|
||||
* This function creates a map so the source-data (vert/edge/loop/face)
|
||||
* can loop over the destination data (using the destination arrays origindex).
|
||||
*
|
||||
* This has the advantage that it can operate on any data-types.
|
||||
@@ -143,20 +143,20 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
|
||||
* \param totfinal: The size of \a final_origindex
|
||||
* \param final_origindex: The size of the final array.
|
||||
*
|
||||
* \note `totsource` could be `totpoly`,
|
||||
* \note `totsource` could be `faces_num`,
|
||||
* `totfinal` could be `tottessface` and `final_origindex` its ORIGINDEX custom-data.
|
||||
* This would allow a poly to loop over its tessfaces.
|
||||
* This would allow a face to loop over its tessfaces.
|
||||
*/
|
||||
void BKE_mesh_origindex_map_create(
|
||||
MeshElemMap **r_map, int **r_mem, int totsource, const int *final_origindex, int totfinal);
|
||||
/**
|
||||
* A version of #BKE_mesh_origindex_map_create that takes a looptri array.
|
||||
* Making a poly -> looptri map.
|
||||
* Making a face -> looptri map.
|
||||
*/
|
||||
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
blender::OffsetIndices<int> polys,
|
||||
const int *looptri_polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
const int *looptri_faces,
|
||||
int looptri_num);
|
||||
|
||||
/* islands */
|
||||
@@ -206,7 +206,7 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3],
|
||||
const blender::int2 *edges,
|
||||
int totedge,
|
||||
const bool *uv_seams,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
int totloop,
|
||||
@@ -219,12 +219,12 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3],
|
||||
* Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams),
|
||||
* not some UV layers coordinates.
|
||||
*/
|
||||
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
|
||||
bool BKE_mesh_calc_islands_loop_face_edgeseam(const float (*vert_positions)[3],
|
||||
int totvert,
|
||||
const blender::int2 *edges,
|
||||
int totedge,
|
||||
const bool *uv_seams,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
int totloop,
|
||||
@@ -243,12 +243,12 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
|
||||
* Not sure it would be worth the more complex code, though,
|
||||
* those loops are supposed to be really quick to do.
|
||||
*/
|
||||
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
|
||||
bool BKE_mesh_calc_islands_loop_face_uvmap(float (*vert_positions)[3],
|
||||
int totvert,
|
||||
blender::int2 *edges,
|
||||
int totedge,
|
||||
const bool *uv_seams,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
int totloop,
|
||||
@@ -266,8 +266,8 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
|
||||
* Note it's callers's responsibility to MEM_freeN returned array.
|
||||
*/
|
||||
int *BKE_mesh_calc_smoothgroups(int totedge,
|
||||
const int *poly_offsets,
|
||||
int totpoly,
|
||||
const int *face_offsets,
|
||||
int faces_num,
|
||||
const int *corner_edges,
|
||||
int totloop,
|
||||
const bool *sharp_edges,
|
||||
@@ -293,14 +293,14 @@ int *BKE_mesh_calc_smoothgroups(int totedge,
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
|
||||
Array<int> build_loop_to_poly_map(OffsetIndices<int> polys);
|
||||
Array<int> build_loop_to_face_map(OffsetIndices<int> faces);
|
||||
|
||||
GroupedSpan<int> build_vert_to_edge_map(Span<int2> edges,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
GroupedSpan<int> build_vert_to_poly_map(OffsetIndices<int> polys,
|
||||
GroupedSpan<int> build_vert_to_face_map(OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
@@ -316,7 +316,7 @@ GroupedSpan<int> build_edge_to_loop_map(Span<int> corner_edges,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
GroupedSpan<int> build_edge_to_poly_map(OffsetIndices<int> polys,
|
||||
GroupedSpan<int> build_edge_to_face_map(OffsetIndices<int> faces,
|
||||
Span<int> corner_edges,
|
||||
int edges_num,
|
||||
Array<int> &r_offsets,
|
||||
|
||||
@@ -78,10 +78,10 @@ enum {
|
||||
MREMAP_MODE_VERT_EDGEINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_EDGE | MREMAP_USE_NEAREST |
|
||||
MREMAP_USE_INTERP,
|
||||
|
||||
/* Nearest vertex of nearest poly. */
|
||||
MREMAP_MODE_VERT_POLY_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
|
||||
/* Those two use all verts of selected poly (weighted interpolation). */
|
||||
/* Nearest point on nearest poly. */
|
||||
/* Nearest vertex of nearest face. */
|
||||
MREMAP_MODE_VERT_FACE_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
|
||||
/* Those two use all verts of selected face (weighted interpolation). */
|
||||
/* Nearest point on nearest face. */
|
||||
MREMAP_MODE_VERT_POLYINTERP_NEAREST = MREMAP_MODE_VERT | MREMAP_USE_POLY | MREMAP_USE_NEAREST |
|
||||
MREMAP_USE_INTERP,
|
||||
/* Point on nearest face hit by ray from target vertex's normal. */
|
||||
@@ -97,7 +97,7 @@ enum {
|
||||
/* Nearest source edge (using mid-point). */
|
||||
MREMAP_MODE_EDGE_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_EDGE | MREMAP_USE_NEAREST,
|
||||
|
||||
/* Nearest edge of nearest poly (using mid-point). */
|
||||
/* Nearest edge of nearest face (using mid-point). */
|
||||
MREMAP_MODE_EDGE_POLY_NEAREST = MREMAP_MODE_EDGE | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
|
||||
|
||||
/* Cast a set of rays from along destination edge,
|
||||
@@ -114,30 +114,30 @@ enum {
|
||||
/* Best normal-matching loop from nearest vert. */
|
||||
MREMAP_MODE_LOOP_NEAREST_LOOPNOR = MREMAP_MODE_LOOP | MREMAP_USE_LOOP | MREMAP_USE_VERT |
|
||||
MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
|
||||
/* Loop from best normal-matching poly from nearest vert. */
|
||||
/* Loop from best normal-matching face from nearest vert. */
|
||||
MREMAP_MODE_LOOP_NEAREST_POLYNOR = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_VERT |
|
||||
MREMAP_USE_NEAREST | MREMAP_USE_NORMAL,
|
||||
|
||||
/* Loop from nearest vertex of nearest poly. */
|
||||
/* Loop from nearest vertex of nearest face. */
|
||||
MREMAP_MODE_LOOP_POLY_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
|
||||
/* Those two use all verts of selected poly (weighted interpolation). */
|
||||
/* Nearest point on nearest poly. */
|
||||
/* Those two use all verts of selected face (weighted interpolation). */
|
||||
/* Nearest point on nearest face. */
|
||||
MREMAP_MODE_LOOP_POLYINTERP_NEAREST = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NEAREST |
|
||||
MREMAP_USE_INTERP,
|
||||
/* Point on nearest face hit by ray from target loop's normal. */
|
||||
MREMAP_MODE_LOOP_POLYINTERP_LNORPROJ = MREMAP_MODE_LOOP | MREMAP_USE_POLY | MREMAP_USE_NORPROJ |
|
||||
MREMAP_USE_INTERP,
|
||||
|
||||
/* ***** Target's polygons ***** */
|
||||
/* ***** Target's faces ***** */
|
||||
MREMAP_MODE_POLY = 1 << 27,
|
||||
|
||||
/* Nearest source poly. */
|
||||
/* Nearest source face. */
|
||||
MREMAP_MODE_POLY_NEAREST = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NEAREST,
|
||||
/* Source poly from best normal-matching destination poly. */
|
||||
/* Source face from best normal-matching destination face. */
|
||||
MREMAP_MODE_POLY_NOR = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORMAL,
|
||||
|
||||
/* Project destination poly onto source mesh using its normal,
|
||||
* and use interpolation of all intersecting source polys. */
|
||||
/* Project destination face onto source mesh using its normal,
|
||||
* and use interpolation of all intersecting source faces. */
|
||||
MREMAP_MODE_POLY_POLYINTERP_PNORPROJ = MREMAP_MODE_POLY | MREMAP_USE_POLY | MREMAP_USE_NORPROJ |
|
||||
MREMAP_USE_INTERP,
|
||||
|
||||
@@ -149,7 +149,7 @@ void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes(
|
||||
int vert_mode,
|
||||
int edge_mode,
|
||||
int loop_mode,
|
||||
int poly_mode,
|
||||
int face_mode,
|
||||
struct CustomData_MeshMasks *cddata_mask);
|
||||
|
||||
/**
|
||||
@@ -217,7 +217,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
|
||||
const int *corner_verts_dst,
|
||||
const int *corner_edges_dst,
|
||||
int numloops_dst,
|
||||
const blender::OffsetIndices<int> polys_dst,
|
||||
const blender::OffsetIndices<int> faces_dst,
|
||||
struct CustomData *ldata_dst,
|
||||
bool use_split_nors_dst,
|
||||
float split_angle_dst,
|
||||
@@ -227,7 +227,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
|
||||
float islands_precision_src,
|
||||
struct MeshPairRemap *r_map);
|
||||
|
||||
void BKE_mesh_remap_calc_polys_from_mesh(int mode,
|
||||
void BKE_mesh_remap_calc_faces_from_mesh(int mode,
|
||||
const struct SpaceTransform *space_transform,
|
||||
float max_dist,
|
||||
float ray_radius,
|
||||
@@ -235,7 +235,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode,
|
||||
const float (*vert_positions_dst)[3],
|
||||
int numverts_dst,
|
||||
const int *corner_verts,
|
||||
const blender::OffsetIndices<int> polys_dst,
|
||||
const blender::OffsetIndices<int> faces_dst,
|
||||
const struct Mesh *me_src,
|
||||
struct MeshPairRemap *r_map);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
||||
* \note Prefer #Mesh::looptris() in C++ code.
|
||||
*/
|
||||
const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh);
|
||||
const int *BKE_mesh_runtime_looptri_polys_ensure(const struct Mesh *mesh);
|
||||
const int *BKE_mesh_runtime_looptri_faces_ensure(const struct Mesh *mesh);
|
||||
|
||||
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
|
||||
|
||||
@@ -59,7 +59,7 @@ void sample_corner_normals(Span<MLoopTri> looptris,
|
||||
const IndexMask &mask,
|
||||
MutableSpan<float3> dst);
|
||||
|
||||
void sample_face_attribute(Span<int> looptri_polys,
|
||||
void sample_face_attribute(Span<int> looptri_faces,
|
||||
Span<int> looptri_indices,
|
||||
const GVArray &src,
|
||||
const IndexMask &mask,
|
||||
|
||||
@@ -29,7 +29,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*loopuv)[2],
|
||||
int numLoops,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
struct ReportList *reports);
|
||||
|
||||
#endif
|
||||
@@ -59,10 +59,10 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh,
|
||||
* See: #BKE_editmesh_loop_tangent_calc (matching logic).
|
||||
*/
|
||||
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const struct MLoopTri *looptri,
|
||||
const int *looptri_polys,
|
||||
const int *looptri_faces,
|
||||
uint looptri_len,
|
||||
const bool *sharp_faces,
|
||||
|
||||
@@ -71,7 +71,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
const float (*vert_normals)[3],
|
||||
const float (*poly_normals)[3],
|
||||
const float (*face_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
/* result */
|
||||
|
||||
@@ -49,7 +49,7 @@ typedef enum eMeshBatchDirtyMode {
|
||||
|
||||
/** #MeshRuntime.wrapper_type */
|
||||
typedef enum eMeshWrapperType {
|
||||
/** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.corner_verts(), #Mesh.mpoly). */
|
||||
/** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.corner_verts(), #Mesh.faces()). */
|
||||
ME_WRAPPER_TYPE_MDATA = 0,
|
||||
/** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */
|
||||
ME_WRAPPER_TYPE_BMESH = 1,
|
||||
@@ -101,8 +101,8 @@ struct MeshRuntime {
|
||||
/** Needed to ensure some thread-safety during render data pre-processing. */
|
||||
std::mutex render_mutex;
|
||||
|
||||
/** Implicit sharing user count for #Mesh::poly_offset_indices. */
|
||||
const ImplicitSharingInfoHandle *poly_offsets_sharing_info;
|
||||
/** Implicit sharing user count for #Mesh::face_offset_indices. */
|
||||
const ImplicitSharingInfoHandle *face_offsets_sharing_info;
|
||||
|
||||
/**
|
||||
* A cache of bounds shared between data-blocks with unchanged positions. When changing positions
|
||||
@@ -121,7 +121,7 @@ struct MeshRuntime {
|
||||
|
||||
/** Cache for derived triangulation of the mesh, accessed with #Mesh::looptris(). */
|
||||
SharedCache<Array<MLoopTri>> looptris_cache;
|
||||
SharedCache<Array<int>> looptri_polys_cache;
|
||||
SharedCache<Array<int>> looptri_faces_cache;
|
||||
|
||||
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
|
||||
BVHCache *bvh_cache = nullptr;
|
||||
@@ -162,14 +162,14 @@ struct MeshRuntime {
|
||||
SubsurfRuntimeData *subsurf_runtime_data = nullptr;
|
||||
|
||||
/**
|
||||
* Caches for lazily computed vertex and polygon normals. These are stored here rather than in
|
||||
* Caches for lazily computed vertex and face normals. These are stored here rather than in
|
||||
* #CustomData because they can be calculated on a `const` mesh, and adding custom data layers on
|
||||
* a `const` mesh is not thread-safe.
|
||||
*/
|
||||
bool vert_normals_dirty = true;
|
||||
bool poly_normals_dirty = true;
|
||||
bool face_normals_dirty = true;
|
||||
mutable Vector<float3> vert_normals;
|
||||
mutable Vector<float3> poly_normals;
|
||||
mutable Vector<float3> face_normals;
|
||||
|
||||
/** Cache of data about edges not used by faces. See #Mesh::loose_edges(). */
|
||||
SharedCache<LooseEdgeCache> loose_edges_cache;
|
||||
@@ -180,8 +180,8 @@ struct MeshRuntime {
|
||||
|
||||
/**
|
||||
* A bit vector the size of the number of vertices, set to true for the center vertices of
|
||||
* subdivided polygons. The values are set by the subdivision surface modifier and used by
|
||||
* drawing code instead of polygon center face dots. Otherwise this will be empty.
|
||||
* subdivided faces. The values are set by the subdivision surface modifier and used by
|
||||
* drawing code instead of face center face dots. Otherwise this will be empty.
|
||||
*/
|
||||
BitVector<> subsurf_face_dot_tags;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3]);
|
||||
int BKE_mesh_wrapper_vert_len(const struct Mesh *me);
|
||||
int BKE_mesh_wrapper_edge_len(const struct Mesh *me);
|
||||
int BKE_mesh_wrapper_loop_len(const struct Mesh *me);
|
||||
int BKE_mesh_wrapper_poly_len(const struct Mesh *me);
|
||||
int BKE_mesh_wrapper_face_len(const struct Mesh *me);
|
||||
|
||||
/**
|
||||
* Return a contiguous array of vertex position values, if available.
|
||||
@@ -36,7 +36,7 @@ const float (*BKE_mesh_wrapper_vert_coords(const struct Mesh *mesh))[3];
|
||||
* Return a contiguous array of face normal values, if available.
|
||||
* Otherwise, normals are stored in BMesh faces.
|
||||
*/
|
||||
const float (*BKE_mesh_wrapper_poly_normals(struct Mesh *mesh))[3];
|
||||
const float (*BKE_mesh_wrapper_face_normals(struct Mesh *mesh))[3];
|
||||
|
||||
void BKE_mesh_wrapper_tag_positions_changed(struct Mesh *mesh);
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ bool BKE_paint_always_hide_test(struct Object *ob);
|
||||
/**
|
||||
* Returns non-zero if any of the face's vertices are hidden, zero otherwise.
|
||||
*/
|
||||
bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, int tri_index);
|
||||
bool paint_is_face_hidden(const int *looptri_faces, const bool *hide_poly, int tri_index);
|
||||
/**
|
||||
* Returns non-zero if any of the corners of the grid
|
||||
* face whose inner corner is at (x, y) are hidden, zero otherwise.
|
||||
@@ -288,9 +288,9 @@ struct SculptVertexPaintGeomMap {
|
||||
blender::Array<int> vert_to_loop_indices;
|
||||
blender::GroupedSpan<int> vert_to_loop;
|
||||
|
||||
blender::Array<int> vert_to_poly_offsets;
|
||||
blender::Array<int> vert_to_poly_indices;
|
||||
blender::GroupedSpan<int> vert_to_poly;
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
blender::GroupedSpan<int> vert_to_face;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -596,11 +596,11 @@ typedef struct SculptSession {
|
||||
|
||||
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> corner_verts;
|
||||
|
||||
/* These contain the vertex and poly counts of the final mesh. */
|
||||
int totvert, totpoly;
|
||||
int totvert, faces_num;
|
||||
|
||||
struct KeyBlock *shapekey_active;
|
||||
struct MPropCol *vcol;
|
||||
@@ -612,14 +612,14 @@ typedef struct SculptSession {
|
||||
float *vmask;
|
||||
|
||||
/* Mesh connectivity maps. */
|
||||
/* Vertices to adjacent polys. */
|
||||
blender::Array<int> vert_to_poly_offsets;
|
||||
blender::Array<int> vert_to_poly_indices;
|
||||
/* Vertices to adjacent faces. */
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
blender::GroupedSpan<int> pmap;
|
||||
|
||||
/* Edges to adjacent polys. */
|
||||
blender::Array<int> edge_to_poly_offsets;
|
||||
blender::Array<int> edge_to_poly_indices;
|
||||
/* Edges to adjacent faces. */
|
||||
blender::Array<int> edge_to_face_offsets;
|
||||
blender::Array<int> edge_to_face_indices;
|
||||
blender::GroupedSpan<int> epmap;
|
||||
|
||||
/* Vertices to adjacent edges. */
|
||||
@@ -628,7 +628,7 @@ typedef struct SculptSession {
|
||||
blender::GroupedSpan<int> vemap;
|
||||
|
||||
/* Mesh Face Sets */
|
||||
/* Total number of polys of the base mesh. */
|
||||
/* Total number of faces of the base mesh. */
|
||||
int totfaces;
|
||||
|
||||
/* The 0 ID is not used by the tools or the visibility system, it is just used when creating new
|
||||
@@ -637,7 +637,7 @@ typedef struct SculptSession {
|
||||
* to 0. */
|
||||
int *face_sets;
|
||||
/**
|
||||
* A reference to the ".hide_poly" attribute, to store whether (base) polygons are hidden.
|
||||
* A reference to the ".hide_poly" attribute, to store whether (base) faces are hidden.
|
||||
* May be null.
|
||||
*/
|
||||
bool *hide_poly;
|
||||
|
||||
@@ -646,7 +646,7 @@ void psys_calc_dmcache(struct Object *ob,
|
||||
* \param findex_orig: The input tessface index.
|
||||
* \param fw: Face weights (position of the particle inside the \a findex_orig tessface).
|
||||
* \param poly_nodes: May be NULL, otherwise an array of linked list,
|
||||
* one for each final \a mesh_final polygon, containing all its tessfaces indices.
|
||||
* one for each final \a mesh_final face, containing all its tessfaces indices.
|
||||
* \return The \a mesh_final tessface index.
|
||||
*/
|
||||
int psys_particle_dm_face_lookup(struct Mesh *mesh_final,
|
||||
|
||||
@@ -617,15 +617,15 @@ struct PBVHFaceIter {
|
||||
int cd_hide_poly_, cd_face_set_;
|
||||
bool *hide_poly_;
|
||||
int *face_sets_;
|
||||
const int *poly_offsets_;
|
||||
const int *looptri_polys_;
|
||||
const int *face_offsets_;
|
||||
const int *looptri_faces_;
|
||||
const int *corner_verts_;
|
||||
int prim_index_;
|
||||
const SubdivCCG *subdiv_ccg_;
|
||||
const BMesh *bm;
|
||||
CCGKey subdiv_key_;
|
||||
|
||||
int last_poly_index_;
|
||||
int last_face_index_;
|
||||
};
|
||||
|
||||
void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd);
|
||||
|
||||
@@ -73,10 +73,10 @@ typedef struct ShrinkwrapTreeData {
|
||||
BVHTree *bvh;
|
||||
BVHTreeFromMesh treeData;
|
||||
|
||||
const int *poly_offsets;
|
||||
const int *face_offsets;
|
||||
const float (*vert_normals)[3];
|
||||
const int *corner_edges;
|
||||
const float (*poly_normals)[3];
|
||||
const float (*face_normals)[3];
|
||||
const bool *sharp_faces;
|
||||
const float (*clnors)[3];
|
||||
ShrinkwrapBoundaryData *boundary;
|
||||
|
||||
@@ -128,7 +128,7 @@ typedef struct SubdivDisplacement {
|
||||
/* Return displacement which is to be added to the original coordinate.
|
||||
*
|
||||
* NOTE: This function is supposed to return "continuous" displacement for
|
||||
* each pf PTex faces created for special (non-quad) polygon. This means,
|
||||
* each pf PTex faces created for special (non-quad) face. This means,
|
||||
* if displacement is stored on per-corner manner (like MDisps for multires)
|
||||
* this is up the displacement implementation to average boundaries of the
|
||||
* displacement grids if needed.
|
||||
|
||||
@@ -71,10 +71,10 @@ void BKE_subdiv_ccg_material_flags_init_from_mesh(
|
||||
*/
|
||||
|
||||
typedef struct SubdivToCCGSettings {
|
||||
/* Resolution at which regular ptex (created for quad polygon) are being
|
||||
/* Resolution at which regular ptex (created for quad face) are being
|
||||
* evaluated. This defines how many vertices final mesh will have: every
|
||||
* regular ptex has resolution^2 vertices. Special (irregular, or ptex
|
||||
* created for a corner of non-quad polygon) will have resolution of
|
||||
* created for a corner of non-quad face) will have resolution of
|
||||
* `resolution - 1`. */
|
||||
int resolution;
|
||||
/* Denotes which extra layers to be added to CCG elements. */
|
||||
@@ -127,7 +127,7 @@ typedef struct SubdivCCG {
|
||||
* resolution. It is NOT the topology refinement level. */
|
||||
int level;
|
||||
/* Resolution of grid. All grids have matching resolution, and resolution
|
||||
* is same as ptex created for non-quad polygons. */
|
||||
* is same as ptex created for non-quad faces. */
|
||||
int grid_size;
|
||||
/* Size of a single element of a grid (including coordinate and all the other layers).
|
||||
* Measured in bytes. */
|
||||
@@ -211,7 +211,7 @@ typedef struct SubdivCCG {
|
||||
/* Create CCG representation of subdivision surface.
|
||||
*
|
||||
* NOTE: CCG stores dense vertices in a grid-like storage. There is no edges or
|
||||
* polygons information's for the high-poly surface.
|
||||
* faces information's for the high-poly surface.
|
||||
*
|
||||
* NOTE: Subdiv is expected to be refined and ready for evaluation.
|
||||
* NOTE: CCG becomes an owner of subdiv.
|
||||
@@ -317,7 +317,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
blender::Span<int> corner_verts,
|
||||
blender::OffsetIndices<int> polys,
|
||||
blender::OffsetIndices<int> faces,
|
||||
int *r_v1,
|
||||
int *r_v2);
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ using SubdivForeachTopologyInformationCb = bool (*)(const SubdivForeachContext *
|
||||
int num_vertices,
|
||||
int num_edges,
|
||||
int num_loops,
|
||||
int num_polygons,
|
||||
const int *subdiv_polygon_offset);
|
||||
int num_faces,
|
||||
const int *subdiv_face_offset);
|
||||
|
||||
using SubdivForeachVertexFromCornerCb = void (*)(const SubdivForeachContext *context,
|
||||
void *tls,
|
||||
@@ -28,7 +28,7 @@ using SubdivForeachVertexFromCornerCb = void (*)(const SubdivForeachContext *con
|
||||
float u,
|
||||
float v,
|
||||
int coarse_vertex_index,
|
||||
int coarse_poly_index,
|
||||
int coarse_face_index,
|
||||
int coarse_corner,
|
||||
int subdiv_vertex_index);
|
||||
|
||||
@@ -38,7 +38,7 @@ using SubdivForeachVertexFromEdgeCb = void (*)(const SubdivForeachContext *conte
|
||||
float u,
|
||||
float v,
|
||||
int coarse_edge_index,
|
||||
int coarse_poly_index,
|
||||
int coarse_face_index,
|
||||
int coarse_corner,
|
||||
int subdiv_vertex_index);
|
||||
|
||||
@@ -47,7 +47,7 @@ using SubdivForeachVertexInnerCb = void (*)(const SubdivForeachContext *context,
|
||||
int ptex_face_index,
|
||||
float u,
|
||||
float v,
|
||||
int coarse_poly_index,
|
||||
int coarse_face_index,
|
||||
int coarse_corner,
|
||||
int subdiv_vertex_index);
|
||||
|
||||
@@ -65,7 +65,7 @@ using SubdivForeachLoopCb = void (*)(const SubdivForeachContext *context,
|
||||
float u,
|
||||
float v,
|
||||
int coarse_loop_index,
|
||||
int coarse_poly_index,
|
||||
int coarse_face_index,
|
||||
int coarse_corner,
|
||||
int subdiv_loop_index,
|
||||
int subdiv_vertex_index,
|
||||
@@ -73,8 +73,8 @@ using SubdivForeachLoopCb = void (*)(const SubdivForeachContext *context,
|
||||
|
||||
using SubdivForeachPolygonCb = void (*)(const SubdivForeachContext *context,
|
||||
void *tls,
|
||||
int coarse_poly_index,
|
||||
int subdiv_poly_index,
|
||||
int coarse_face_index,
|
||||
int subdiv_face_index,
|
||||
int start_loop_index,
|
||||
int num_loops);
|
||||
|
||||
@@ -143,7 +143,7 @@ struct SubdivForeachContext {
|
||||
* of final subdivided mesh.
|
||||
*
|
||||
* Main goal is to abstract all the traversal routines to give geometry element
|
||||
* indices (for vertices, edges, loops, polygons) in the same way as subdivision
|
||||
* indices (for vertices, edges, loops, faces) in the same way as subdivision
|
||||
* modifier will do for a dense mesh.
|
||||
*
|
||||
* Returns true if the whole topology was traversed, without any early exits.
|
||||
|
||||
@@ -17,10 +17,10 @@ struct Subdiv;
|
||||
|
||||
struct SubdivToMeshSettings {
|
||||
/**
|
||||
* Resolution at which regular PTEX (created for quad polygon) are being
|
||||
* Resolution at which regular PTEX (created for quad face) are being
|
||||
* evaluated. This defines how many vertices final mesh will have: every
|
||||
* regular PTEX has resolution^2 vertices. Special (irregular, or PTEX
|
||||
* created for a corner of non-quad polygon) will have resolution of
|
||||
* created for a corner of non-quad face) will have resolution of
|
||||
* `resolution - 1`.
|
||||
*/
|
||||
int resolution;
|
||||
|
||||
@@ -51,7 +51,7 @@ typedef struct SubsurfRuntimeData {
|
||||
/* Cached from the draw code for stats display. */
|
||||
int stats_totvert;
|
||||
int stats_totedge;
|
||||
int stats_totpoly;
|
||||
int stats_faces_num;
|
||||
int stats_totloop;
|
||||
} SubsurfRuntimeData;
|
||||
|
||||
|
||||
@@ -62,10 +62,10 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
|
||||
const Span<openvdb::Vec3I> vdb_tris,
|
||||
const Span<openvdb::Vec4I> vdb_quads,
|
||||
int vert_offset,
|
||||
int poly_offset,
|
||||
int face_offset,
|
||||
int loop_offset,
|
||||
MutableSpan<float3> vert_positions,
|
||||
MutableSpan<int> poly_offsets,
|
||||
MutableSpan<int> face_offsets,
|
||||
MutableSpan<int> corner_verts);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -154,11 +154,11 @@ static int *dm_getCornerEdgeArray(DerivedMesh *dm)
|
||||
|
||||
static int *dm_getPolyArray(DerivedMesh *dm)
|
||||
{
|
||||
if (!dm->poly_offsets) {
|
||||
dm->poly_offsets = MEM_cnew_array<int>(dm->getNumPolys(dm) + 1, __func__);
|
||||
dm->copyPolyArray(dm, dm->poly_offsets);
|
||||
if (!dm->face_offsets) {
|
||||
dm->face_offsets = MEM_cnew_array<int>(dm->getNumPolys(dm) + 1, __func__);
|
||||
dm->copyPolyArray(dm, dm->face_offsets);
|
||||
}
|
||||
return dm->poly_offsets;
|
||||
return dm->face_offsets;
|
||||
}
|
||||
|
||||
void DM_init_funcs(DerivedMesh *dm)
|
||||
@@ -217,7 +217,7 @@ void DM_from_template(DerivedMesh *dm,
|
||||
&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
|
||||
CustomData_copy_layout(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
|
||||
CustomData_copy_layout(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
|
||||
dm->poly_offsets = static_cast<int *>(MEM_dupallocN(source->poly_offsets));
|
||||
dm->face_offsets = static_cast<int *>(MEM_dupallocN(source->face_offsets));
|
||||
|
||||
dm->type = type;
|
||||
dm->numVertData = numVerts;
|
||||
@@ -236,7 +236,7 @@ void DM_release(DerivedMesh *dm)
|
||||
CustomData_free(&dm->faceData, dm->numTessFaceData);
|
||||
CustomData_free(&dm->loopData, dm->numLoopData);
|
||||
CustomData_free(&dm->polyData, dm->numPolyData);
|
||||
MEM_SAFE_FREE(dm->poly_offsets);
|
||||
MEM_SAFE_FREE(dm->face_offsets);
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_eval_to_meshkey(Mesh *me_deformed, Mesh *me, KeyBlock *kb)
|
||||
@@ -271,7 +271,7 @@ static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask)
|
||||
{
|
||||
CustomData_set_only_copy(&mesh->vdata, mask->vmask);
|
||||
CustomData_set_only_copy(&mesh->edata, mask->emask);
|
||||
CustomData_set_only_copy(&mesh->fdata, mask->fmask);
|
||||
CustomData_set_only_copy(&mesh->fdata_legacy, mask->fmask);
|
||||
/* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
|
||||
* weight paint mode when there are modifiers applied, needs further investigation,
|
||||
* see replies to r50969, Campbell */
|
||||
@@ -470,7 +470,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
}
|
||||
|
||||
if (calc_loop_normals) {
|
||||
/* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case
|
||||
/* Compute loop normals (NOTE: will compute face and vert normals as well, if needed!). In case
|
||||
* of deferred CPU subdivision, this will be computed when the wrapper is generated. */
|
||||
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
|
||||
BKE_mesh_calc_normals_split(mesh_final);
|
||||
@@ -480,7 +480,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
if (sculpt_dyntopo == false) {
|
||||
/* without this, drawing ngon tri's faces will show ugly tessellated face
|
||||
* normals and will also have to calculate normals on the fly, try avoid
|
||||
* this where possible since calculating polygon normals isn't fast,
|
||||
* this where possible since calculating face normals isn't fast,
|
||||
* note that this isn't a problem for subsurf (only quads) or edit-mode
|
||||
* which deals with drawing differently. */
|
||||
BKE_mesh_ensure_normals_for_display(mesh_final);
|
||||
@@ -829,7 +829,7 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
|
||||
CustomData_add_layer(
|
||||
&mesh_final->edata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totedge);
|
||||
CustomData_add_layer(
|
||||
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totpoly);
|
||||
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->faces_num);
|
||||
|
||||
/* Not worth parallelizing this,
|
||||
* gives less than 0.1% overall speedup in best of best cases... */
|
||||
@@ -842,8 +842,8 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
|
||||
mesh_final->totedge,
|
||||
0);
|
||||
range_vn_i((int *)CustomData_get_layer_for_write(
|
||||
&mesh_final->pdata, CD_ORIGINDEX, mesh_final->totpoly),
|
||||
mesh_final->totpoly,
|
||||
&mesh_final->pdata, CD_ORIGINDEX, mesh_final->faces_num),
|
||||
mesh_final->faces_num,
|
||||
0);
|
||||
}
|
||||
}
|
||||
@@ -1103,7 +1103,7 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
|
||||
}
|
||||
else {
|
||||
/* Same as #mesh_calc_modifiers.
|
||||
* If using loop normals, poly normals have already been computed. */
|
||||
* If using loop normals, face normals have already been computed. */
|
||||
BKE_mesh_ensure_normals_for_display(mesh_final);
|
||||
|
||||
/* Some modifiers, like data-transfer, may generate those data, we do not want to keep them,
|
||||
@@ -1728,19 +1728,19 @@ static void mesh_init_origspace(Mesh *mesh)
|
||||
OrigSpaceLoop *lof_array = (OrigSpaceLoop *)CustomData_get_layer_for_write(
|
||||
&mesh->ldata, CD_ORIGSPACE_MLOOP, mesh->totloop);
|
||||
const Span<float3> positions = mesh->vert_positions();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
int j, k;
|
||||
|
||||
blender::Vector<blender::float2, 64> vcos_2d;
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
OrigSpaceLoop *lof = lof_array + poly.start();
|
||||
for (const int i : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
OrigSpaceLoop *lof = lof_array + face.start();
|
||||
|
||||
if (ELEM(poly.size(), 3, 4)) {
|
||||
for (j = 0; j < poly.size(); j++, lof++) {
|
||||
if (ELEM(face.size(), 3, 4)) {
|
||||
for (j = 0; j < face.size(); j++, lof++) {
|
||||
copy_v2_v2(lof->uv, default_osf[j]);
|
||||
}
|
||||
}
|
||||
@@ -1751,14 +1751,14 @@ static void mesh_init_origspace(Mesh *mesh)
|
||||
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
|
||||
float translate[2], scale[2];
|
||||
|
||||
const float3 p_nor = blender::bke::mesh::poly_normal_calc(positions,
|
||||
corner_verts.slice(poly));
|
||||
const float3 p_nor = blender::bke::mesh::face_normal_calc(positions,
|
||||
corner_verts.slice(face));
|
||||
|
||||
axis_dominant_v3_to_m3(mat, p_nor);
|
||||
|
||||
vcos_2d.resize(poly.size());
|
||||
for (j = 0; j < poly.size(); j++) {
|
||||
mul_v3_m3v3(co, mat, positions[corner_verts[poly[j]]]);
|
||||
vcos_2d.resize(face.size());
|
||||
for (j = 0; j < face.size(); j++) {
|
||||
mul_v3_m3v3(co, mat, positions[corner_verts[face[j]]]);
|
||||
copy_v2_v2(vcos_2d[j], co);
|
||||
|
||||
for (k = 0; k < 2; k++) {
|
||||
@@ -1786,7 +1786,7 @@ static void mesh_init_origspace(Mesh *mesh)
|
||||
|
||||
/* Finally, transform all vcos_2d into ((0, 0), (1, 1))
|
||||
* square and assign them as origspace. */
|
||||
for (j = 0; j < poly.size(); j++, lof++) {
|
||||
for (j = 0; j < face.size(); j++, lof++) {
|
||||
add_v2_v2v2(lof->uv, vcos_2d[j], translate);
|
||||
mul_v2_v2(lof->uv, scale);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
|
||||
info[ATTR_DOMAIN_CORNER].customdata = &mesh->ldata;
|
||||
info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
|
||||
info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata;
|
||||
info[ATTR_DOMAIN_FACE].length = mesh->totpoly;
|
||||
info[ATTR_DOMAIN_FACE].length = mesh->faces_num;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1090,7 +1090,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
|
||||
return tree;
|
||||
}
|
||||
|
||||
static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices<int> polys,
|
||||
static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices<int> faces,
|
||||
const VArray<bool> &hide_poly,
|
||||
const int looptri_len,
|
||||
int *r_looptri_active_len)
|
||||
@@ -1102,8 +1102,8 @@ static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices<int> p
|
||||
|
||||
int looptri_no_hidden_len = 0;
|
||||
int looptri_index = 0;
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
const int triangles_num = ME_POLY_TRI_TOT(polys[i].size());
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
const int triangles_num = ME_FACE_TRI_TOT(faces[i].size());
|
||||
if (hide_poly[i]) {
|
||||
looptri_index += triangles_num;
|
||||
}
|
||||
@@ -1142,7 +1142,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
||||
bvh_cache_type,
|
||||
positions,
|
||||
edges.data(),
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
corner_verts.data(),
|
||||
looptris,
|
||||
data);
|
||||
@@ -1189,14 +1189,14 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
||||
break;
|
||||
}
|
||||
case BVHTREE_FROM_FACES: {
|
||||
BLI_assert(!(mesh->totface == 0 && mesh->totpoly != 0));
|
||||
BLI_assert(!(mesh->totface_legacy == 0 && mesh->faces_num != 0));
|
||||
data->tree = bvhtree_from_mesh_faces_create_tree(
|
||||
0.0f,
|
||||
tree_type,
|
||||
6,
|
||||
positions,
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
|
||||
mesh->totface,
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
mesh->totface_legacy,
|
||||
{},
|
||||
-1);
|
||||
break;
|
||||
@@ -1205,7 +1205,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
||||
blender::bke::AttributeAccessor attributes = mesh->attributes();
|
||||
int mask_bits_act_len = -1;
|
||||
const BitVector<> mask = looptri_no_hidden_map_get(
|
||||
mesh->polys(),
|
||||
mesh->faces(),
|
||||
*attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
|
||||
looptris.size(),
|
||||
&mask_bits_act_len);
|
||||
|
||||
@@ -99,9 +99,9 @@ static void cdDM_copyCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
|
||||
memcpy(r_corner_edges, cddm->corner_edges, sizeof(*r_corner_edges) * dm->numLoopData);
|
||||
}
|
||||
|
||||
static void cdDM_copyPolyArray(DerivedMesh *dm, int *r_poly_offsets)
|
||||
static void cdDM_copyPolyArray(DerivedMesh *dm, int *r_face_offsets)
|
||||
{
|
||||
memcpy(r_poly_offsets, dm->poly_offsets, sizeof(int) * (dm->numPolyData + 1));
|
||||
memcpy(r_face_offsets, dm->face_offsets, sizeof(int) * (dm->numPolyData + 1));
|
||||
}
|
||||
|
||||
static void cdDM_free_internal(CDDerivedMesh *cddm)
|
||||
@@ -164,16 +164,16 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, const CustomData_MeshMasks *ma
|
||||
mesh->totedge,
|
||||
0 /* `mesh->totface` */,
|
||||
mesh->totloop,
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
|
||||
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, mesh->totvert);
|
||||
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, mesh->totedge);
|
||||
CustomData_merge(&mesh->fdata,
|
||||
CustomData_merge(&mesh->fdata_legacy,
|
||||
&dm->faceData,
|
||||
cddata_masks.fmask | CD_MASK_ORIGINDEX,
|
||||
0 /* `mesh->totface` */);
|
||||
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, mesh->totloop);
|
||||
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, mesh->totpoly);
|
||||
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, mesh->faces_num);
|
||||
|
||||
cddm->vert_positions = static_cast<float(*)[3]>(CustomData_get_layer_named_for_write(
|
||||
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
|
||||
@@ -183,7 +183,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, const CustomData_MeshMasks *ma
|
||||
&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));
|
||||
dm->poly_offsets = static_cast<int *>(MEM_dupallocN(mesh->poly_offset_indices));
|
||||
dm->face_offsets = static_cast<int *>(MEM_dupallocN(mesh->face_offset_indices));
|
||||
#if 0
|
||||
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
|
||||
#else
|
||||
|
||||
@@ -52,7 +52,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, Mesh *mesh);
|
||||
|
||||
struct BendSpringRef {
|
||||
int index;
|
||||
int polys;
|
||||
int face;
|
||||
ClothSpring *spring;
|
||||
};
|
||||
|
||||
@@ -1297,11 +1297,11 @@ void cloth_parallel_transport_hair_frame(float mat[3][3],
|
||||
mul_m3_m3m3(mat, rot, mat);
|
||||
}
|
||||
|
||||
/* Add a shear and a bend spring between two verts within a poly. */
|
||||
/* Add a shear and a bend spring between two verts within a face. */
|
||||
static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
|
||||
LinkNodePair *edgelist,
|
||||
const blender::Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
int i,
|
||||
int j,
|
||||
int k)
|
||||
@@ -1319,7 +1319,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
|
||||
return false;
|
||||
}
|
||||
|
||||
spring_verts_ordered_set(spring, corner_verts[polys[i][j]], corner_verts[polys[i][k]]);
|
||||
spring_verts_ordered_set(spring, corner_verts[faces[i][j]], corner_verts[faces[i][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) *
|
||||
@@ -1339,7 +1339,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
|
||||
spring->type |= CLOTH_SPRING_TYPE_BENDING;
|
||||
|
||||
spring->la = k - j + 1;
|
||||
spring->lb = polys[i].size() - k + j + 1;
|
||||
spring->lb = faces[i].size() - k + j + 1;
|
||||
|
||||
spring->pa = static_cast<int *>(MEM_mallocN(sizeof(*spring->pa) * spring->la, "spring poly"));
|
||||
if (!spring->pa) {
|
||||
@@ -1351,7 +1351,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp_corner = &corner_verts[polys[i].start()];
|
||||
tmp_corner = &corner_verts[faces[i].start()];
|
||||
|
||||
for (x = 0; x < spring->la; x++) {
|
||||
spring->pa[x] = tmp_corner[j + x];
|
||||
@@ -1361,7 +1361,7 @@ static bool cloth_add_shear_bend_spring(ClothModifierData *clmd,
|
||||
spring->pb[x] = tmp_corner[x];
|
||||
}
|
||||
|
||||
for (y = k; y < polys[i].size(); x++, y++) {
|
||||
for (y = k; y < faces[i].size(); x++, y++) {
|
||||
spring->pb[x] = tmp_corner[y];
|
||||
}
|
||||
|
||||
@@ -1484,10 +1484,10 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
uint struct_springs = 0, shear_springs = 0, bend_springs = 0, struct_springs_real = 0;
|
||||
uint mvert_num = uint(mesh->totvert);
|
||||
uint numedges = uint(mesh->totedge);
|
||||
uint numpolys = uint(mesh->totpoly);
|
||||
uint numface = uint(mesh->faces_num);
|
||||
float shrink_factor;
|
||||
const blender::Span<int2> edges = mesh->edges();
|
||||
const OffsetIndices polys = mesh->polys();
|
||||
const OffsetIndices faces = mesh->faces();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
const Span<int> corner_edges = mesh->corner_edges();
|
||||
int index2 = 0; /* our second vertex index */
|
||||
@@ -1527,7 +1527,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
|
||||
bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS);
|
||||
|
||||
if (use_internal_springs && numpolys > 0) {
|
||||
if (use_internal_springs && numface > 0) {
|
||||
BVHTreeFromMesh treedata = {nullptr};
|
||||
uint tar_v_idx;
|
||||
Mesh *tmp_mesh = nullptr;
|
||||
@@ -1681,14 +1681,14 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
edgeset = BLI_edgeset_new_ex(__func__, numedges);
|
||||
cloth->edgeset = edgeset;
|
||||
|
||||
if (numpolys) {
|
||||
for (int i = 0; i < numpolys; i++) {
|
||||
if (numface) {
|
||||
for (int i = 0; i < numface; i++) {
|
||||
/* Shear springs. */
|
||||
/* Triangle faces already have shear springs due to structural geometry. */
|
||||
if (polys[i].size() > 3) {
|
||||
for (int j = 1; j < polys[i].size() - 1; j++) {
|
||||
if (faces[i].size() > 3) {
|
||||
for (int j = 1; j < faces[i].size() - 1; j++) {
|
||||
if (j > 1) {
|
||||
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, 0, j)) {
|
||||
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, faces, i, 0, j)) {
|
||||
shear_springs++;
|
||||
|
||||
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
|
||||
@@ -1701,8 +1701,8 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = j + 2; k < polys[i].size(); k++) {
|
||||
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, polys, i, j, k)) {
|
||||
for (int k = j + 2; k < faces[i].size(); k++) {
|
||||
if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, faces, i, j, k)) {
|
||||
shear_springs++;
|
||||
|
||||
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
|
||||
@@ -1719,28 +1719,28 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
|
||||
/* Angular bending springs along struct springs. */
|
||||
if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) {
|
||||
for (int j = 0; j < polys[i].size(); j++) {
|
||||
const int edge_i = corner_edges[polys[i][j]];
|
||||
for (int j = 0; j < faces[i].size(); j++) {
|
||||
const int edge_i = corner_edges[faces[i][j]];
|
||||
BendSpringRef *curr_ref = &spring_ref[edge_i];
|
||||
curr_ref->polys++;
|
||||
curr_ref->face++;
|
||||
|
||||
/* First poly found for this edge, store poly index. */
|
||||
if (curr_ref->polys == 1) {
|
||||
if (curr_ref->face == 1) {
|
||||
curr_ref->index = i;
|
||||
}
|
||||
/* Second poly found for this edge, add bending data. */
|
||||
else if (curr_ref->polys == 2) {
|
||||
else if (curr_ref->face == 2) {
|
||||
spring = curr_ref->spring;
|
||||
|
||||
spring->type |= CLOTH_SPRING_TYPE_BENDING;
|
||||
|
||||
spring->la = polys[curr_ref->index].size();
|
||||
spring->lb = polys[i].size();
|
||||
spring->la = faces[curr_ref->index].size();
|
||||
spring->lb = faces[i].size();
|
||||
|
||||
if (!cloth_bend_set_poly_vert_array(
|
||||
&spring->pa, spring->la, &corner_verts[polys[curr_ref->index].start()]) ||
|
||||
&spring->pa, spring->la, &corner_verts[faces[curr_ref->index].start()]) ||
|
||||
!cloth_bend_set_poly_vert_array(
|
||||
&spring->pb, spring->lb, &corner_verts[polys[i].start()]))
|
||||
&spring->pb, spring->lb, &corner_verts[faces[i].start()]))
|
||||
{
|
||||
cloth_free_errorsprings(cloth, edgelist, spring_ref);
|
||||
return false;
|
||||
@@ -1763,7 +1763,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
bend_springs++;
|
||||
}
|
||||
/* Third poly found for this edge, remove bending data. */
|
||||
else if (curr_ref->polys == 3) {
|
||||
else if (curr_ref->face == 3) {
|
||||
spring = curr_ref->spring;
|
||||
|
||||
spring->type &= ~CLOTH_SPRING_TYPE_BENDING;
|
||||
@@ -1911,12 +1911,12 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
||||
BLI_edgeset_add(edgeset, edges[i][0], edges[i][1]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numpolys; i++) { /* edge springs */
|
||||
if (polys[i].size() == 4) {
|
||||
for (int i = 0; i < numface; i++) { /* edge springs */
|
||||
if (faces[i].size() == 4) {
|
||||
BLI_edgeset_add(
|
||||
edgeset, corner_verts[polys[i].start() + 0], corner_verts[polys[i].start() + 2]);
|
||||
edgeset, corner_verts[faces[i].start() + 0], corner_verts[faces[i].start() + 2]);
|
||||
BLI_edgeset_add(
|
||||
edgeset, corner_verts[polys[i].start() + 1], corner_verts[polys[i].start() + 3]);
|
||||
edgeset, corner_verts[faces[i].start() + 1], corner_verts[faces[i].start() + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -192,16 +192,16 @@ 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 OffsetIndices polys = me->polys();
|
||||
const OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
|
||||
for (int i = 0; i < me->totpoly; i++) {
|
||||
const IndexRange poly = polys[i];
|
||||
const int *corner_vert_next = &corner_verts[poly.start()];
|
||||
const int *corner_vert_curr = &corner_vert_next[poly.size() - 1];
|
||||
const int *corner_vert_prev = &corner_vert_next[poly.size() - 2];
|
||||
for (int i = 0; i < me->faces_num; i++) {
|
||||
const IndexRange face = faces[i];
|
||||
const int *corner_vert_next = &corner_verts[face.start()];
|
||||
const int *corner_vert_curr = &corner_vert_next[face.size() - 1];
|
||||
const int *corner_vert_prev = &corner_vert_next[face.size() - 2];
|
||||
|
||||
for (int j = 0; j < poly.size(); j++) {
|
||||
for (int j = 0; j < face.size(); j++) {
|
||||
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 */
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace blender::bke {
|
||||
|
||||
static void fill_mesh_topology(const int vert_offset,
|
||||
const int edge_offset,
|
||||
const int poly_offset,
|
||||
const int face_offset,
|
||||
const int loop_offset,
|
||||
const int main_point_num,
|
||||
const int profile_point_num,
|
||||
@@ -33,7 +33,7 @@ static void fill_mesh_topology(const int vert_offset,
|
||||
MutableSpan<int2> edges,
|
||||
MutableSpan<int> corner_verts,
|
||||
MutableSpan<int> corner_edges,
|
||||
MutableSpan<int> poly_offsets)
|
||||
MutableSpan<int> face_offsets)
|
||||
{
|
||||
const int main_segment_num = curves::segments_num(main_point_num, main_cyclic);
|
||||
const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic);
|
||||
@@ -84,7 +84,7 @@ static void fill_mesh_topology(const int vert_offset,
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate poly and corner indices. */
|
||||
/* Calculate face and corner indices. */
|
||||
for (const int i_ring : IndexRange(main_segment_num)) {
|
||||
const int i_next_ring = (i_ring == main_point_num - 1) ? 0 : i_ring + 1;
|
||||
|
||||
@@ -94,7 +94,7 @@ static void fill_mesh_topology(const int vert_offset,
|
||||
const int ring_edge_start = profile_edges_start + profile_segment_num * i_ring;
|
||||
const int next_ring_edge_offset = profile_edges_start + profile_segment_num * i_next_ring;
|
||||
|
||||
const int ring_poly_offset = poly_offset + i_ring * profile_segment_num;
|
||||
const int ring_face_offset = face_offset + i_ring * profile_segment_num;
|
||||
const int ring_loop_offset = loop_offset + i_ring * profile_segment_num * 4;
|
||||
|
||||
for (const int i_profile : IndexRange(profile_segment_num)) {
|
||||
@@ -104,7 +104,7 @@ static void fill_mesh_topology(const int vert_offset,
|
||||
const int main_edge_start = main_edges_start + main_segment_num * i_profile;
|
||||
const int next_main_edge_start = main_edges_start + main_segment_num * i_next_profile;
|
||||
|
||||
poly_offsets[ring_poly_offset + i_profile] = ring_segment_loop_offset;
|
||||
face_offsets[ring_face_offset + i_profile] = ring_segment_loop_offset;
|
||||
|
||||
corner_verts[ring_segment_loop_offset] = ring_vert_offset + i_profile;
|
||||
corner_edges[ring_segment_loop_offset] = ring_edge_start + i_profile;
|
||||
@@ -122,12 +122,12 @@ static void fill_mesh_topology(const int vert_offset,
|
||||
|
||||
const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2;
|
||||
if (has_caps) {
|
||||
const int poly_num = main_segment_num * profile_segment_num;
|
||||
const int cap_loop_offset = loop_offset + poly_num * 4;
|
||||
const int cap_poly_offset = poly_offset + poly_num;
|
||||
const int face_num = main_segment_num * profile_segment_num;
|
||||
const int cap_loop_offset = loop_offset + face_num * 4;
|
||||
const int cap_face_offset = face_offset + face_num;
|
||||
|
||||
poly_offsets[cap_poly_offset] = cap_loop_offset;
|
||||
poly_offsets[cap_poly_offset + 1] = cap_loop_offset + profile_segment_num;
|
||||
face_offsets[cap_face_offset] = cap_loop_offset;
|
||||
face_offsets[cap_face_offset + 1] = cap_loop_offset + profile_segment_num;
|
||||
|
||||
const int last_ring_index = main_point_num - 1;
|
||||
const int last_ring_vert_offset = vert_offset + profile_point_num * last_ring_index;
|
||||
@@ -233,7 +233,7 @@ struct ResultOffsets {
|
||||
Array<int> vert;
|
||||
Array<int> edge;
|
||||
Array<int> loop;
|
||||
Array<int> poly;
|
||||
Array<int> face;
|
||||
|
||||
/* The indices of the main and profile curves that form each combination. */
|
||||
Array<int> main_indices;
|
||||
@@ -257,13 +257,13 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
|
||||
result.vert.reinitialize(result.total + 1);
|
||||
result.edge.reinitialize(result.total + 1);
|
||||
result.loop.reinitialize(result.total + 1);
|
||||
result.poly.reinitialize(result.total + 1);
|
||||
result.face.reinitialize(result.total + 1);
|
||||
|
||||
int mesh_index = 0;
|
||||
int vert_offset = 0;
|
||||
int edge_offset = 0;
|
||||
int loop_offset = 0;
|
||||
int poly_offset = 0;
|
||||
int face_offset = 0;
|
||||
for (const int i_main : main_offsets.index_range()) {
|
||||
const bool main_cyclic = info.main_cyclic[i_main];
|
||||
const int main_point_num = main_offsets[i_main].size();
|
||||
@@ -272,7 +272,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
|
||||
result.vert[mesh_index] = vert_offset;
|
||||
result.edge[mesh_index] = edge_offset;
|
||||
result.loop[mesh_index] = loop_offset;
|
||||
result.poly[mesh_index] = poly_offset;
|
||||
result.face[mesh_index] = face_offset;
|
||||
|
||||
const bool profile_cyclic = info.profile_cyclic[i_profile];
|
||||
const int profile_point_num = profile_offsets[i_profile].size();
|
||||
@@ -291,7 +291,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
|
||||
main_segment_num * profile_point_num;
|
||||
|
||||
/* Add two cap N-gons for every ending. */
|
||||
poly_offset += tube_face_num + (has_caps ? 2 : 0);
|
||||
face_offset += tube_face_num + (has_caps ? 2 : 0);
|
||||
|
||||
/* All faces on the tube are quads, and all cap faces are N-gons with an edge for each
|
||||
* profile edge. */
|
||||
@@ -304,7 +304,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool
|
||||
result.vert.last() = vert_offset;
|
||||
result.edge.last() = edge_offset;
|
||||
result.loop.last() = loop_offset;
|
||||
result.poly.last() = poly_offset;
|
||||
result.face.last() = face_offset;
|
||||
},
|
||||
[&]() {
|
||||
result.main_indices.reinitialize(result.total);
|
||||
@@ -394,7 +394,7 @@ struct CombinationInfo {
|
||||
|
||||
IndexRange vert_range;
|
||||
IndexRange edge_range;
|
||||
IndexRange poly_range;
|
||||
IndexRange face_range;
|
||||
IndexRange loop_range;
|
||||
};
|
||||
template<typename Fn>
|
||||
@@ -406,7 +406,7 @@ static void foreach_curve_combination(const CurvesInfo &info,
|
||||
const OffsetIndices<int> profile_offsets = info.profile.evaluated_points_by_curve();
|
||||
const OffsetIndices<int> vert_offsets(offsets.vert);
|
||||
const OffsetIndices<int> edge_offsets(offsets.edge);
|
||||
const OffsetIndices<int> poly_offsets(offsets.poly);
|
||||
const OffsetIndices<int> face_offsets(offsets.face);
|
||||
const OffsetIndices<int> loop_offsets(offsets.loop);
|
||||
threading::parallel_for(IndexRange(offsets.total), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@@ -432,7 +432,7 @@ static void foreach_curve_combination(const CurvesInfo &info,
|
||||
curves::segments_num(profile_points.size(), profile_cyclic),
|
||||
vert_offsets[i],
|
||||
edge_offsets[i],
|
||||
poly_offsets[i],
|
||||
face_offsets[i],
|
||||
loop_offsets[i]});
|
||||
}
|
||||
});
|
||||
@@ -602,7 +602,7 @@ static void copy_main_point_domain_attribute_to_mesh(const CurvesInfo &curves_in
|
||||
copy_main_point_data_to_mesh_faces(src.slice(info.main_points),
|
||||
info.main_segment_num,
|
||||
info.profile_segment_num,
|
||||
dst.slice(info.poly_range));
|
||||
dst.slice(info.face_range));
|
||||
});
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
@@ -682,7 +682,7 @@ static void copy_profile_point_domain_attribute_to_mesh(const CurvesInfo &curves
|
||||
copy_profile_point_data_to_mesh_faces(src.slice(info.profile_points),
|
||||
info.main_segment_num,
|
||||
info.profile_segment_num,
|
||||
dst.slice(info.poly_range));
|
||||
dst.slice(info.face_range));
|
||||
});
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
@@ -728,7 +728,7 @@ static void copy_curve_domain_attribute_to_mesh(const ResultOffsets &mesh_offset
|
||||
offsets = mesh_offsets.edge;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
offsets = mesh_offsets.poly;
|
||||
offsets = mesh_offsets.face;
|
||||
break;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
offsets = mesh_offsets.loop;
|
||||
@@ -791,14 +791,14 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
|
||||
/* Add the position attribute later so it can be shared in some cases.*/
|
||||
Mesh *mesh = BKE_mesh_new_nomain(
|
||||
0, offsets.edge.last(), offsets.poly.last(), offsets.loop.last());
|
||||
0, offsets.edge.last(), offsets.face.last(), offsets.loop.last());
|
||||
CustomData_free_layer_named(&mesh->vdata, "position", 0);
|
||||
mesh->totvert = offsets.vert.last();
|
||||
|
||||
mesh->flag |= ME_AUTOSMOOTH;
|
||||
mesh->smoothresh = DEG2RADF(180.0f);
|
||||
MutableSpan<int2> edges = mesh->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = mesh->face_offsets_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();
|
||||
@@ -806,7 +806,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
|
||||
fill_mesh_topology(info.vert_range.start(),
|
||||
info.edge_range.start(),
|
||||
info.poly_range.start(),
|
||||
info.face_range.start(),
|
||||
info.loop_range.start(),
|
||||
info.main_points.size(),
|
||||
info.profile_points.size(),
|
||||
@@ -816,7 +816,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
edges,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
poly_offsets);
|
||||
face_offsets);
|
||||
});
|
||||
|
||||
if (fill_caps) {
|
||||
@@ -827,10 +827,10 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
||||
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
|
||||
const bool has_caps = fill_caps && !info.main_cyclic && info.profile_cyclic;
|
||||
if (has_caps) {
|
||||
const int poly_num = info.main_segment_num * info.profile_segment_num;
|
||||
const int cap_poly_offset = info.poly_range.start() + poly_num;
|
||||
sharp_faces.span[cap_poly_offset] = true;
|
||||
sharp_faces.span[cap_poly_offset + 1] = true;
|
||||
const int face_num = info.main_segment_num * info.profile_segment_num;
|
||||
const int cap_face_offset = info.face_range.start() + face_num;
|
||||
sharp_faces.span[cap_face_offset] = true;
|
||||
sharp_faces.span[cap_face_offset + 1] = true;
|
||||
}
|
||||
});
|
||||
sharp_faces.finish();
|
||||
|
||||
@@ -59,7 +59,7 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
|
||||
else if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
|
||||
r_data_masks->lmask |= 1LL << cddata_type;
|
||||
}
|
||||
else if (DT_DATATYPE_IS_POLY(dtdata_type)) {
|
||||
else if (DT_DATATYPE_IS_FACE(dtdata_type)) {
|
||||
r_data_masks->pmask |= 1LL << cddata_type;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types)
|
||||
if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
|
||||
ret |= ME_LOOP;
|
||||
}
|
||||
if (DT_DATATYPE_IS_POLY(dtdata_type)) {
|
||||
if (DT_DATATYPE_IS_FACE(dtdata_type)) {
|
||||
ret |= ME_POLY;
|
||||
}
|
||||
}
|
||||
@@ -390,12 +390,12 @@ static void data_transfer_dtdata_type_preprocess(const Mesh *me_src,
|
||||
CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
blender::bke::mesh::normals_calc_loop(me_dst->vert_positions(),
|
||||
me_dst->edges(),
|
||||
me_dst->polys(),
|
||||
me_dst->faces(),
|
||||
me_dst->corner_verts(),
|
||||
me_dst->corner_edges(),
|
||||
{},
|
||||
me_dst->vert_normals(),
|
||||
me_dst->poly_normals(),
|
||||
me_dst->face_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
use_split_nors_dst,
|
||||
@@ -437,11 +437,11 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst,
|
||||
/* Note loop_nors_dst contains our custom normals as transferred from source... */
|
||||
blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(),
|
||||
me_dst->edges(),
|
||||
me_dst->polys(),
|
||||
me_dst->faces(),
|
||||
me_dst->corner_verts(),
|
||||
me_dst->corner_edges(),
|
||||
me_dst->vert_normals(),
|
||||
me_dst->poly_normals(),
|
||||
me_dst->face_normals(),
|
||||
sharp_faces,
|
||||
sharp_edges.span,
|
||||
{loop_nors_dst, me_dst->totloop},
|
||||
@@ -456,7 +456,7 @@ static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int c
|
||||
{
|
||||
switch (cddata_type) {
|
||||
case CD_FAKE_UV:
|
||||
return BKE_mesh_calc_islands_loop_poly_edgeseam;
|
||||
return BKE_mesh_calc_islands_loop_face_edgeseam;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1148,7 +1148,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
|
||||
if (r_map && cddata_type == CD_FAKE_SHARP) {
|
||||
if (!CustomData_has_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")) {
|
||||
CustomData_add_layer_named(
|
||||
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->totpoly, "sharp_face");
|
||||
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->faces_num, "sharp_face");
|
||||
}
|
||||
data_transfer_layersmapping_add_item_cd(
|
||||
r_map,
|
||||
@@ -1291,8 +1291,8 @@ void BKE_object_data_transfer_layout(Depsgraph *depsgraph,
|
||||
me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
|
||||
}
|
||||
}
|
||||
if (DT_DATATYPE_IS_POLY(dtdata_type)) {
|
||||
const int num_elem_dst = me_dst->totpoly;
|
||||
if (DT_DATATYPE_IS_FACE(dtdata_type)) {
|
||||
const int num_elem_dst = me_dst->faces_num;
|
||||
|
||||
data_transfer_layersmapping_generate(nullptr,
|
||||
ob_src,
|
||||
@@ -1323,7 +1323,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
const int map_vert_mode,
|
||||
const int map_edge_mode,
|
||||
const int map_loop_mode,
|
||||
const int map_poly_mode,
|
||||
const int map_face_mode,
|
||||
SpaceTransform *space_transform,
|
||||
const bool auto_transform,
|
||||
const float max_distance,
|
||||
@@ -1451,7 +1451,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
"None of the 'Edge' mappings can be used in this case");
|
||||
continue;
|
||||
}
|
||||
if ((map_vert_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) {
|
||||
if ((map_vert_mode & MREMAP_USE_POLY) && (me_src->faces_num == 0)) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Source mesh doesn't have any faces, "
|
||||
@@ -1533,7 +1533,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
"'Topology' mapping cannot be used in this case");
|
||||
continue;
|
||||
}
|
||||
if ((map_edge_mode & MREMAP_USE_POLY) && (me_src->totpoly == 0)) {
|
||||
if ((map_edge_mode & MREMAP_USE_POLY) && (me_src->faces_num == 0)) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Source mesh doesn't have any faces, "
|
||||
@@ -1610,7 +1610,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
const blender::Span<blender::float3> positions_dst = me_dst->vert_positions();
|
||||
const int num_verts_dst = me_dst->totvert;
|
||||
const blender::Span<blender::int2> edges_dst = me_dst->edges();
|
||||
const blender::OffsetIndices polys_dst = me_dst->polys();
|
||||
const blender::OffsetIndices faces_dst = me_dst->faces();
|
||||
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;
|
||||
@@ -1656,7 +1656,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
corner_verts_dst.data(),
|
||||
corner_edges_dst.data(),
|
||||
corner_verts_dst.size(),
|
||||
polys_dst,
|
||||
faces_dst,
|
||||
ldata_dst,
|
||||
(me_dst->flag & ME_AUTOSMOOTH) != 0,
|
||||
me_dst->smoothresh,
|
||||
@@ -1710,30 +1710,30 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
BLI_freelistN(&lay_map);
|
||||
}
|
||||
}
|
||||
if (DT_DATATYPE_IS_POLY(dtdata_type)) {
|
||||
if (DT_DATATYPE_IS_FACE(dtdata_type)) {
|
||||
const blender::Span<blender::float3> positions_dst = me_dst->vert_positions();
|
||||
const int num_verts_dst = me_dst->totvert;
|
||||
const blender::OffsetIndices polys_dst = me_dst->polys();
|
||||
const blender::OffsetIndices faces_dst = me_dst->faces();
|
||||
const blender::Span<int> corner_verts_dst = me_dst->corner_verts();
|
||||
|
||||
if (!geom_map_init[PDATA]) {
|
||||
const int num_polys_src = me_src->totpoly;
|
||||
const int num_faces_src = me_src->faces_num;
|
||||
|
||||
if ((map_poly_mode == MREMAP_MODE_TOPOLOGY) && (polys_dst.size() != num_polys_src)) {
|
||||
if ((map_face_mode == MREMAP_MODE_TOPOLOGY) && (faces_dst.size() != num_faces_src)) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Source and destination meshes do not have the same amount of faces, "
|
||||
"'Topology' mapping cannot be used in this case");
|
||||
continue;
|
||||
}
|
||||
if ((map_poly_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) {
|
||||
if ((map_face_mode & MREMAP_USE_EDGE) && (me_src->totedge == 0)) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Source mesh doesn't have any edges, "
|
||||
"None of the 'Edge' mappings can be used in this case");
|
||||
continue;
|
||||
}
|
||||
if (ELEM(0, polys_dst.size(), num_polys_src)) {
|
||||
if (ELEM(0, faces_dst.size(), num_faces_src)) {
|
||||
BKE_report(
|
||||
reports,
|
||||
RPT_ERROR,
|
||||
@@ -1741,8 +1741,8 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_mesh_remap_calc_polys_from_mesh(
|
||||
map_poly_mode,
|
||||
BKE_mesh_remap_calc_faces_from_mesh(
|
||||
map_face_mode,
|
||||
space_transform,
|
||||
max_distance,
|
||||
ray_radius,
|
||||
@@ -1750,7 +1750,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
reinterpret_cast<const float(*)[3]>(positions_dst.data()),
|
||||
num_verts_dst,
|
||||
corner_verts_dst.data(),
|
||||
polys_dst,
|
||||
faces_dst,
|
||||
me_src,
|
||||
&geom_map[PDATA]);
|
||||
geom_map_init[PDATA] = true;
|
||||
@@ -1758,13 +1758,13 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
|
||||
if (mdef && vg_idx != -1 && !weights[PDATA]) {
|
||||
weights[PDATA] = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*weights[PDATA]) * polys_dst.size(), __func__));
|
||||
BKE_defvert_extract_vgroup_to_polyweights(mdef,
|
||||
MEM_mallocN(sizeof(*weights[PDATA]) * faces_dst.size(), __func__));
|
||||
BKE_defvert_extract_vgroup_to_faceweights(mdef,
|
||||
vg_idx,
|
||||
num_verts_dst,
|
||||
corner_verts_dst.data(),
|
||||
corner_verts_dst.size(),
|
||||
polys_dst,
|
||||
faces_dst,
|
||||
invert_vgroup,
|
||||
weights[PDATA]);
|
||||
}
|
||||
@@ -1779,7 +1779,7 @@ bool BKE_object_data_transfer_ex(Depsgraph *depsgraph,
|
||||
mix_mode,
|
||||
mix_factor,
|
||||
weights[PDATA],
|
||||
polys_dst.size(),
|
||||
faces_dst.size(),
|
||||
use_create,
|
||||
use_delete,
|
||||
fromlayers,
|
||||
@@ -1825,7 +1825,7 @@ bool BKE_object_data_transfer_mesh(Depsgraph *depsgraph,
|
||||
const int map_vert_mode,
|
||||
const int map_edge_mode,
|
||||
const int map_loop_mode,
|
||||
const int map_poly_mode,
|
||||
const int map_face_mode,
|
||||
SpaceTransform *space_transform,
|
||||
const bool auto_transform,
|
||||
const float max_distance,
|
||||
@@ -1848,7 +1848,7 @@ bool BKE_object_data_transfer_mesh(Depsgraph *depsgraph,
|
||||
map_vert_mode,
|
||||
map_edge_mode,
|
||||
map_loop_mode,
|
||||
map_poly_mode,
|
||||
map_face_mode,
|
||||
space_transform,
|
||||
auto_transform,
|
||||
max_distance,
|
||||
|
||||
@@ -1099,17 +1099,17 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert,
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert,
|
||||
void BKE_defvert_extract_vgroup_to_faceweights(const MDeformVert *dvert,
|
||||
const int defgroup,
|
||||
const int verts_num,
|
||||
const int *corner_verts,
|
||||
const int /*loops_num*/,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const bool invert_vgroup,
|
||||
float *r_weights)
|
||||
{
|
||||
if (dvert && defgroup != -1) {
|
||||
int i = polys.size();
|
||||
int i = faces.size();
|
||||
float *tmp_weights = static_cast<float *>(
|
||||
MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
|
||||
|
||||
@@ -1117,21 +1117,21 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert,
|
||||
dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
|
||||
|
||||
while (i--) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
const int *corner_vert = &corner_verts[poly.start()];
|
||||
int j = poly.size();
|
||||
const blender::IndexRange face = faces[i];
|
||||
const int *corner_vert = &corner_verts[face.start()];
|
||||
int j = face.size();
|
||||
float w = 0.0f;
|
||||
|
||||
for (; j--; corner_vert++) {
|
||||
w += tmp_weights[*corner_vert];
|
||||
}
|
||||
r_weights[i] = w / float(poly.size());
|
||||
r_weights[i] = w / float(face.size());
|
||||
}
|
||||
|
||||
MEM_freeN(tmp_weights);
|
||||
}
|
||||
else {
|
||||
copy_vn_fl(r_weights, polys.size(), 0.0f);
|
||||
copy_vn_fl(r_weights, faces.size(), 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1427,9 +1427,9 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
|
||||
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
|
||||
/* For vertex format, count every vertex that is connected by an edge */
|
||||
int numOfEdges = mesh->totedge;
|
||||
int numOfPolys = mesh->totpoly;
|
||||
int numOfPolys = mesh->faces_num;
|
||||
const blender::Span<blender::int2> edges = mesh->edges();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
/* count number of edges per vertex */
|
||||
@@ -1444,7 +1444,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
|
||||
/* also add number of vertices to temp_data
|
||||
* to locate points on "mesh edge" */
|
||||
for (int i = 0; i < numOfPolys; i++) {
|
||||
for (const int vert : corner_verts.slice(polys[i])) {
|
||||
for (const int vert : corner_verts.slice(faces[i])) {
|
||||
temp_data[vert]++;
|
||||
}
|
||||
}
|
||||
@@ -1804,7 +1804,7 @@ struct DynamicPaintModifierApplyData {
|
||||
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> corner_verts;
|
||||
|
||||
float (*fcolor)[4];
|
||||
@@ -1882,7 +1882,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata,
|
||||
MLoopCol *mloopcol = data->mloopcol;
|
||||
MLoopCol *mloopcol_wet = data->mloopcol_wet;
|
||||
|
||||
for (const int l_index : data->polys[p_index]) {
|
||||
for (const int l_index : data->faces[p_index]) {
|
||||
const int v_index = corner_verts[l_index];
|
||||
|
||||
/* save layer data to output layer */
|
||||
@@ -1942,7 +1942,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
||||
|
||||
/* vertex color paint */
|
||||
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
|
||||
const blender::OffsetIndices polys = result->polys();
|
||||
const blender::OffsetIndices faces = result->faces();
|
||||
const blender::Span<int> corner_verts = result->corner_verts();
|
||||
|
||||
/* paint is stored on dry and wet layers, so mix final color first */
|
||||
@@ -1991,16 +1991,16 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
||||
|
||||
data.ob = ob;
|
||||
data.corner_verts = corner_verts;
|
||||
data.polys = polys;
|
||||
data.faces = faces;
|
||||
data.mloopcol = mloopcol;
|
||||
data.mloopcol_wet = mloopcol_wet;
|
||||
|
||||
{
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
settings.use_threading = (polys.size() > 1000);
|
||||
settings.use_threading = (faces.size() > 1000);
|
||||
BLI_task_parallel_range(
|
||||
0, polys.size(), &data, dynamic_paint_apply_surface_vpaint_cb, &settings);
|
||||
0, faces.size(), &data, dynamic_paint_apply_surface_vpaint_cb, &settings);
|
||||
}
|
||||
|
||||
MEM_freeN(fcolor);
|
||||
@@ -2379,7 +2379,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
|
||||
atomic_add_and_fetch_uint32(&tPoint->neighbor_pixel, 1);
|
||||
tPoint->tri_index = i;
|
||||
|
||||
/* Now calculate pixel data for this pixel as it was on polygon surface */
|
||||
/* Now calculate pixel data for this pixel as it was on face surface */
|
||||
/* Add b-weights per anti-aliasing sample */
|
||||
for (int j = 0; j < aa_samples; j++) {
|
||||
uv[0] = point[0] + jitter5sample[j * 2] / w;
|
||||
@@ -2460,7 +2460,7 @@ static int dynamic_paint_find_neighbor_pixel(const DynamicPaintCreateUVSurfaceDa
|
||||
const int py,
|
||||
const int n_index)
|
||||
{
|
||||
/* NOTE: Current method only uses polygon edges to detect neighboring pixels.
|
||||
/* NOTE: Current method only uses face edges to detect neighboring pixels.
|
||||
* -> It doesn't always lead to the optimum pixel but is accurate enough
|
||||
* and faster/simpler than including possible face tip point links)
|
||||
*/
|
||||
@@ -2950,7 +2950,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
|
||||
/*
|
||||
* Now loop through every pixel that was left without index
|
||||
* and find if they have neighboring pixels that have an index.
|
||||
* If so use that polygon as pixel surface.
|
||||
* If so use that face as pixel surface.
|
||||
* (To avoid seams on uv island edges)
|
||||
*/
|
||||
data.active_points = &active_points;
|
||||
@@ -3180,7 +3180,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
|
||||
if (uvPoint->neighbor_pixel != -1) {
|
||||
pPoint->color[2] = 1.0f;
|
||||
}
|
||||
/* and every pixel that finally got an polygon gets red color */
|
||||
/* and every pixel that finally got an face gets red color */
|
||||
/* green color shows pixel face index hash */
|
||||
if (uvPoint->tri_index != -1) {
|
||||
pPoint->color[0] = 1.0f;
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
/** \name Ensure Data (derived from coords)
|
||||
* \{ */
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, blender::bke::EditMeshData *emd)
|
||||
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh *em, blender::bke::EditMeshData *emd)
|
||||
{
|
||||
if (emd->vertexCos.is_empty() || !emd->polyNos.is_empty()) {
|
||||
if (emd->vertexCos.is_empty() || !emd->faceNos.is_empty()) {
|
||||
return;
|
||||
}
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
emd->polyNos.reinitialize(bm->totface);
|
||||
emd->faceNos.reinitialize(bm->totface);
|
||||
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
BMFace *efa;
|
||||
@@ -39,7 +39,7 @@ void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, blender::bke::EditMe
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_elem_index_set(efa, i); /* set_inline */
|
||||
BM_face_calc_normal_vcos(
|
||||
bm, efa, emd->polyNos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()));
|
||||
bm, efa, emd->faceNos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()));
|
||||
}
|
||||
bm->elem_index_dirty &= ~BM_FACE;
|
||||
}
|
||||
@@ -51,40 +51,40 @@ void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, blender::bke::EditMe
|
||||
}
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
/* Calculate vertex normals from poly normals. */
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, emd);
|
||||
/* Calculate vertex normals from face normals. */
|
||||
BKE_editmesh_cache_ensure_face_normals(em, emd);
|
||||
|
||||
emd->vertexNos.reinitialize(bm->totvert);
|
||||
|
||||
BM_mesh_elem_index_ensure(bm, BM_FACE);
|
||||
BM_verts_calc_normal_vcos(bm,
|
||||
reinterpret_cast<const float(*)[3]>(emd->polyNos.data()),
|
||||
reinterpret_cast<const float(*)[3]>(emd->faceNos.data()),
|
||||
reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()),
|
||||
reinterpret_cast<float(*)[3]>(emd->vertexNos.data()));
|
||||
}
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, blender::bke::EditMeshData *emd)
|
||||
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh *em, blender::bke::EditMeshData *emd)
|
||||
{
|
||||
if (!emd->polyCos.is_empty()) {
|
||||
if (!emd->faceCos.is_empty()) {
|
||||
return;
|
||||
}
|
||||
BMesh *bm = em->bm;
|
||||
|
||||
emd->polyCos.reinitialize(bm->totface);
|
||||
emd->faceCos.reinitialize(bm->totface);
|
||||
|
||||
BMFace *efa;
|
||||
BMIter fiter;
|
||||
int i;
|
||||
if (emd->vertexCos.is_empty()) {
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_face_calc_center_median(efa, emd->polyCos[i]);
|
||||
BM_face_calc_center_median(efa, emd->faceCos[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_face_calc_center_median_vcos(
|
||||
bm, efa, emd->polyCos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()));
|
||||
bm, efa, emd->faceCos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
const float (*poly_normals)[3],
|
||||
const float (*face_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
/* result */
|
||||
@@ -253,7 +253,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
|
||||
mesh2tangent->face_as_quad_map = face_as_quad_map;
|
||||
mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
|
||||
#endif
|
||||
mesh2tangent->precomputedFaceNormals = poly_normals;
|
||||
mesh2tangent->precomputedFaceNormals = face_normals;
|
||||
/* NOTE: we assume we do have tessellated loop normals at this point
|
||||
* (in case it is object-enabled), have to check this is valid. */
|
||||
mesh2tangent->precomputedLoopNormals = loop_normals;
|
||||
|
||||
@@ -3247,7 +3247,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
return nullptr;
|
||||
}
|
||||
blender::MutableSpan<blender::float3> positions = me->vert_positions_for_write();
|
||||
blender::MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> face_offsets = me->face_offsets_for_write();
|
||||
blender::MutableSpan<int> corner_verts = me->corner_verts_for_write();
|
||||
|
||||
const bool is_sharp = orgmesh->attributes()
|
||||
@@ -3339,11 +3339,11 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
||||
int *material_indices = BKE_mesh_material_indices_for_write(me);
|
||||
|
||||
/* Loop for triangles. */
|
||||
for (const int i : poly_offsets.index_range().drop_back(1)) {
|
||||
for (const int i : face_offsets.index_range().drop_back(1)) {
|
||||
/* Initialize from existing face. */
|
||||
material_indices[i] = mp_mat_nr;
|
||||
|
||||
poly_offsets[i] = i * 3;
|
||||
face_offsets[i] = i * 3;
|
||||
|
||||
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);
|
||||
@@ -3382,7 +3382,7 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
|
||||
|
||||
result = BKE_mesh_new_nomain(num_verts, 0, num_faces, num_faces * 4);
|
||||
blender::MutableSpan<blender::float3> positions = result->vert_positions_for_write();
|
||||
blender::MutableSpan<int> poly_offsets = result->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> face_offsets = result->face_offsets_for_write();
|
||||
blender::MutableSpan<int> corner_verts = result->corner_verts_for_write();
|
||||
|
||||
if (num_verts) {
|
||||
@@ -3426,8 +3426,8 @@ static Mesh *create_smoke_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obje
|
||||
co[1] = max[1];
|
||||
co[2] = min[2];
|
||||
|
||||
poly_offsets.fill(4);
|
||||
blender::offset_indices::accumulate_counts_to_offsets(poly_offsets);
|
||||
face_offsets.fill(4);
|
||||
blender::offset_indices::accumulate_counts_to_offsets(face_offsets);
|
||||
|
||||
/* Create faces. */
|
||||
/* Top side. */
|
||||
|
||||
@@ -122,7 +122,7 @@ VArray<float3> mesh_normals_varray(const Mesh &mesh,
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
return VArray<float3>::ForSpan(mesh.poly_normals());
|
||||
return VArray<float3>::ForSpan(mesh.face_normals());
|
||||
}
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
return VArray<float3>::ForSpan(mesh.vert_normals());
|
||||
@@ -149,7 +149,7 @@ VArray<float3> mesh_normals_varray(const Mesh &mesh,
|
||||
* component's generic domain interpolation is fine, the data will still be normalized,
|
||||
* since the face normal is just copied to every corner. */
|
||||
return mesh.attributes().adapt_domain(
|
||||
VArray<float3>::ForSpan(mesh.poly_normals()), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
|
||||
VArray<float3>::ForSpan(mesh.face_normals()), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
@@ -244,7 +244,7 @@ static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray
|
||||
|
||||
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
@@ -252,9 +252,9 @@ static GVArray adapt_mesh_domain_corner_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(
|
||||
polys.size(), [polys, varray = varray.typed<bool>()](const int face_index) {
|
||||
faces.size(), [faces, varray = varray.typed<bool>()](const int face_index) {
|
||||
/* A face is selected if all of its corners were selected. */
|
||||
for (const int loop_index : polys[face_index]) {
|
||||
for (const int loop_index : faces[face_index]) {
|
||||
if (!varray[loop_index]) {
|
||||
return false;
|
||||
}
|
||||
@@ -264,10 +264,10 @@ static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray
|
||||
}
|
||||
else {
|
||||
new_varray = VArray<T>::ForFunc(
|
||||
polys.size(), [polys, varray = varray.typed<T>()](const int face_index) {
|
||||
faces.size(), [faces, varray = varray.typed<T>()](const int face_index) {
|
||||
T return_value;
|
||||
attribute_math::DefaultMixer<T> mixer({&return_value, 1});
|
||||
for (const int loop_index : polys[face_index]) {
|
||||
for (const int loop_index : faces[face_index]) {
|
||||
const T value = varray[loop_index];
|
||||
mixer.mix_in(0, value);
|
||||
}
|
||||
@@ -286,17 +286,17 @@ static void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totedge);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const IndexRange face = faces[face_index];
|
||||
|
||||
/* For every edge, mix values from the two adjacent corners (the current and next corner). */
|
||||
for (const int corner : poly) {
|
||||
const int next_corner = mesh::poly_corner_next(poly, corner);
|
||||
for (const int corner : face) {
|
||||
const int next_corner = mesh::face_corner_next(face, corner);
|
||||
const int edge_index = corner_edges[corner];
|
||||
mixer.mix_in(edge_index, old_values[corner]);
|
||||
mixer.mix_in(edge_index, old_values[next_corner]);
|
||||
@@ -313,15 +313,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
|
||||
MutableSpan<bool> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totedge);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
r_values.fill(true);
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const IndexRange face = faces[face_index];
|
||||
|
||||
for (const int corner : poly) {
|
||||
const int next_corner = mesh::poly_corner_next(poly, corner);
|
||||
for (const int corner : face) {
|
||||
const int next_corner = mesh::face_corner_next(face, corner);
|
||||
const int edge_index = corner_edges[corner];
|
||||
if (!old_values[corner] || !old_values[next_corner]) {
|
||||
r_values[edge_index] = false;
|
||||
@@ -361,14 +361,14 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totvert);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const T value = old_values[poly_index];
|
||||
for (const int vert : corner_verts.slice(polys[poly_index])) {
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const T value = old_values[face_index];
|
||||
for (const int vert : corner_verts.slice(faces[face_index])) {
|
||||
mixer.mix_in(vert, value);
|
||||
}
|
||||
}
|
||||
@@ -383,14 +383,14 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
||||
MutableSpan<bool> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totvert);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
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]) {
|
||||
for (const int vert : corner_verts.slice(polys[poly_index])) {
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
if (old_values[face_index]) {
|
||||
for (const int vert : corner_verts.slice(faces[face_index])) {
|
||||
r_values[vert] = true;
|
||||
}
|
||||
}
|
||||
@@ -418,12 +418,12 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totloop);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
|
||||
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
MutableSpan<T> poly_corner_values = r_values.slice(polys[poly_index]);
|
||||
poly_corner_values.fill(old_values[poly_index]);
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
MutableSpan<T> face_corner_values = r_values.slice(faces[face_index]);
|
||||
face_corner_values.fill(old_values[face_index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -447,14 +447,14 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totedge);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const T value = old_values[poly_index];
|
||||
for (const int edge : corner_edges.slice(polys[poly_index])) {
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const T value = old_values[face_index];
|
||||
for (const int edge : corner_edges.slice(faces[face_index])) {
|
||||
mixer.mix_in(edge, value);
|
||||
}
|
||||
}
|
||||
@@ -468,14 +468,14 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
||||
MutableSpan<bool> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totedge);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
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]) {
|
||||
for (const int edge : corner_edges.slice(polys[poly_index])) {
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
if (old_values[face_index]) {
|
||||
for (const int edge : corner_edges.slice(faces[face_index])) {
|
||||
r_values[edge] = true;
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,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 OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
|
||||
GVArray new_varray;
|
||||
@@ -507,10 +507,10 @@ 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,
|
||||
[corner_verts, polys, varray = varray.typed<bool>()](const int face_index) {
|
||||
mesh.faces_num,
|
||||
[corner_verts, faces, varray = varray.typed<bool>()](const int face_index) {
|
||||
/* A face is selected if all of its vertices were selected. */
|
||||
for (const int vert : corner_verts.slice(polys[face_index])) {
|
||||
for (const int vert : corner_verts.slice(faces[face_index])) {
|
||||
if (!varray[vert]) {
|
||||
return false;
|
||||
}
|
||||
@@ -520,10 +520,11 @@ static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &
|
||||
}
|
||||
else {
|
||||
new_varray = VArray<T>::ForFunc(
|
||||
mesh.totpoly, [corner_verts, polys, varray = varray.typed<T>()](const int face_index) {
|
||||
mesh.faces_num,
|
||||
[corner_verts, faces, varray = varray.typed<T>()](const int face_index) {
|
||||
T return_value;
|
||||
attribute_math::DefaultMixer<T> mixer({&return_value, 1});
|
||||
for (const int vert : corner_verts.slice(polys[face_index])) {
|
||||
for (const int vert : corner_verts.slice(faces[face_index])) {
|
||||
mixer.mix_in(0, varray[vert]);
|
||||
}
|
||||
mixer.finalize();
|
||||
@@ -574,17 +575,17 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totloop);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const IndexRange face = faces[face_index];
|
||||
|
||||
/* For every corner, mix the values from the adjacent edges on the face. */
|
||||
for (const int loop_index : poly) {
|
||||
const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index);
|
||||
for (const int loop_index : face) {
|
||||
const int loop_index_prev = mesh::face_corner_prev(face, loop_index);
|
||||
const int edge = corner_edges[loop_index];
|
||||
const int edge_prev = corner_edges[loop_index_prev];
|
||||
mixer.mix_in(loop_index, old_values[edge]);
|
||||
@@ -602,16 +603,16 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
||||
MutableSpan<bool> r_values)
|
||||
{
|
||||
BLI_assert(r_values.size() == mesh.totloop);
|
||||
const OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
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) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
for (const int loop_index : poly) {
|
||||
const int loop_index_prev = mesh::poly_corner_prev(poly, loop_index);
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const IndexRange face = faces[face_index];
|
||||
for (const int loop_index : face) {
|
||||
const int loop_index_prev = mesh::face_corner_prev(face, loop_index);
|
||||
const int edge = corner_edges[loop_index];
|
||||
const int edge_prev = corner_edges[loop_index_prev];
|
||||
if (old_values[edge] && old_values[edge_prev]) {
|
||||
@@ -693,7 +694,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 OffsetIndices polys = mesh.polys();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_edges = mesh.corner_edges();
|
||||
|
||||
GVArray new_varray;
|
||||
@@ -703,8 +704,8 @@ 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(), [corner_edges, polys, varray = varray.typed<T>()](const int face_index) {
|
||||
for (const int edge : corner_edges.slice(polys[face_index])) {
|
||||
faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
|
||||
for (const int edge : corner_edges.slice(faces[face_index])) {
|
||||
if (!varray[edge]) {
|
||||
return false;
|
||||
}
|
||||
@@ -714,10 +715,10 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v
|
||||
}
|
||||
else {
|
||||
new_varray = VArray<T>::ForFunc(
|
||||
polys.size(), [corner_edges, polys, varray = varray.typed<T>()](const int face_index) {
|
||||
faces.size(), [corner_edges, faces, varray = varray.typed<T>()](const int face_index) {
|
||||
T return_value;
|
||||
attribute_math::DefaultMixer<T> mixer({&return_value, 1});
|
||||
for (const int edge : corner_edges.slice(polys[face_index])) {
|
||||
for (const int edge : corner_edges.slice(faces[face_index])) {
|
||||
mixer.mix_in(0, varray[edge]);
|
||||
}
|
||||
mixer.finalize();
|
||||
@@ -1093,7 +1094,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
||||
MAKE_GET_ELEMENT_NUM_GETTER(totedge)};
|
||||
static CustomDataAccessInfo face_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata),
|
||||
MAKE_CONST_CUSTOM_DATA_GETTER(pdata),
|
||||
MAKE_GET_ELEMENT_NUM_GETTER(totpoly)};
|
||||
MAKE_GET_ELEMENT_NUM_GETTER(faces_num)};
|
||||
|
||||
#undef MAKE_CONST_CUSTOM_DATA_GETTER
|
||||
#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER
|
||||
@@ -1227,7 +1228,7 @@ static AttributeAccessorFunctions get_mesh_accessor_functions()
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return mesh.totedge;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return mesh.totpoly;
|
||||
return mesh.faces_num;
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return mesh.totloop;
|
||||
default:
|
||||
|
||||
@@ -228,7 +228,7 @@ std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
|
||||
if (const Mesh *mesh = geometry_set.get_mesh_for_read()) {
|
||||
parts.append(std::to_string(mesh->totvert) + " verts");
|
||||
parts.append(std::to_string(mesh->totedge) + " edges");
|
||||
parts.append(std::to_string(mesh->totpoly) + " polys");
|
||||
parts.append(std::to_string(mesh->faces_num) + " faces");
|
||||
parts.append(std::to_string(mesh->totloop) + " corners");
|
||||
}
|
||||
if (const Curves *curves = geometry_set.get_curves_for_read()) {
|
||||
|
||||
@@ -2720,9 +2720,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh);
|
||||
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
|
||||
const Span<float3> positions = me_eval->vert_positions();
|
||||
const OffsetIndices polys = me_eval->polys();
|
||||
const OffsetIndices faces = me_eval->faces();
|
||||
const Span<int> corner_verts = me_eval->corner_verts();
|
||||
int polys_len = me_eval->totpoly;
|
||||
int faces_len = me_eval->faces_num;
|
||||
char element_name[200];
|
||||
|
||||
/* Need at least an edge. */
|
||||
@@ -2746,7 +2746,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
}
|
||||
|
||||
/* Export faces as filled strokes. */
|
||||
if (use_faces && polys_len > 0) {
|
||||
if (use_faces && faces_len > 0) {
|
||||
/* Read all polygons and create fill for each. */
|
||||
make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
|
||||
/* Create Layer and Frame. */
|
||||
@@ -2760,8 +2760,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
|
||||
const VArray<int> mesh_material_indices = *me_eval->attributes().lookup_or_default<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE, 0);
|
||||
for (i = 0; i < polys_len; i++) {
|
||||
const IndexRange poly = polys[i];
|
||||
for (i = 0; i < faces_len; i++) {
|
||||
const IndexRange face = faces[i];
|
||||
|
||||
/* Find material. */
|
||||
int mat_idx = 0;
|
||||
@@ -2781,19 +2781,19 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx);
|
||||
}
|
||||
|
||||
bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, poly.size(), 10, false);
|
||||
bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, face.size(), 10, false);
|
||||
gps_fill->flag |= GP_STROKE_CYCLIC;
|
||||
|
||||
/* Create dvert data. */
|
||||
const Span<MDeformVert> dverts = me_eval->deform_verts();
|
||||
if (use_vgroups && !dverts.is_empty()) {
|
||||
gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * poly.size(),
|
||||
gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * face.size(),
|
||||
"gp_fill_dverts");
|
||||
}
|
||||
|
||||
/* Add points to strokes. */
|
||||
for (int j = 0; j < poly.size(); j++) {
|
||||
const int vert = corner_verts[poly[j]];
|
||||
for (int j = 0; j < face.size(); j++) {
|
||||
const int vert = corner_verts[face[j]];
|
||||
|
||||
bGPDspoint *pt = &gps_fill->points[j];
|
||||
copy_v3_v3(&pt->x, positions[vert]);
|
||||
@@ -2815,7 +2815,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
||||
}
|
||||
}
|
||||
/* If has only 3 points subdivide. */
|
||||
if (poly.size() == 3) {
|
||||
if (face.size() == 3) {
|
||||
BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE);
|
||||
}
|
||||
|
||||
|
||||
@@ -2231,53 +2231,53 @@ void BKE_keyblock_convert_to_mesh(const KeyBlock *kb,
|
||||
void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
Mesh *mesh,
|
||||
float (*r_vert_normals)[3],
|
||||
float (*r_poly_normals)[3],
|
||||
float (*r_face_normals)[3],
|
||||
float (*r_loop_normals)[3])
|
||||
{
|
||||
if (r_vert_normals == nullptr && r_poly_normals == nullptr && r_loop_normals == nullptr) {
|
||||
if (r_vert_normals == nullptr && r_face_normals == nullptr && r_loop_normals == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
blender::Array<blender::float3> positions(mesh->vert_positions());
|
||||
BKE_keyblock_convert_to_mesh(kb, reinterpret_cast<float(*)[3]>(positions.data()), mesh->totvert);
|
||||
const blender::Span<blender::int2> edges = mesh->edges();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
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;
|
||||
const bool poly_normals_needed = r_poly_normals != nullptr || vert_normals_needed ||
|
||||
const bool face_normals_needed = r_face_normals != nullptr || vert_normals_needed ||
|
||||
loop_normals_needed;
|
||||
|
||||
float(*vert_normals)[3] = r_vert_normals;
|
||||
float(*poly_normals)[3] = r_poly_normals;
|
||||
float(*face_normals)[3] = r_face_normals;
|
||||
bool free_vert_normals = false;
|
||||
bool free_poly_normals = false;
|
||||
bool free_face_normals = false;
|
||||
if (vert_normals_needed && r_vert_normals == nullptr) {
|
||||
vert_normals = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(mesh->totvert, sizeof(float[3]), __func__));
|
||||
free_vert_normals = true;
|
||||
}
|
||||
if (poly_normals_needed && r_poly_normals == nullptr) {
|
||||
poly_normals = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__));
|
||||
free_poly_normals = true;
|
||||
if (face_normals_needed && r_face_normals == nullptr) {
|
||||
face_normals = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(mesh->faces_num, sizeof(float[3]), __func__));
|
||||
free_face_normals = true;
|
||||
}
|
||||
|
||||
if (poly_normals_needed) {
|
||||
blender::bke::mesh::normals_calc_polys(
|
||||
if (face_normals_needed) {
|
||||
blender::bke::mesh::normals_calc_faces(
|
||||
positions,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()});
|
||||
{reinterpret_cast<blender::float3 *>(face_normals), faces.size()});
|
||||
}
|
||||
if (vert_normals_needed) {
|
||||
blender::bke::mesh::normals_calc_poly_vert(
|
||||
blender::bke::mesh::normals_calc_face_vert(
|
||||
positions,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
|
||||
{reinterpret_cast<blender::float3 *>(face_normals), faces.size()},
|
||||
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert});
|
||||
}
|
||||
if (loop_normals_needed) {
|
||||
@@ -2290,12 +2290,12 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
blender::bke::mesh::normals_calc_loop(
|
||||
positions,
|
||||
edges,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
{},
|
||||
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert},
|
||||
{reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
|
||||
{reinterpret_cast<blender::float3 *>(face_normals), faces.size()},
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
(mesh->flag & ME_AUTOSMOOTH) != 0,
|
||||
@@ -2308,8 +2308,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
||||
if (free_vert_normals) {
|
||||
MEM_freeN(vert_normals);
|
||||
}
|
||||
if (free_poly_normals) {
|
||||
MEM_freeN(poly_normals);
|
||||
if (free_face_normals) {
|
||||
MEM_freeN(face_normals);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1464,15 +1464,15 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
|
||||
Mesh *mesh = BKE_mesh_new_nomain(int(process.co.size()), 0, int(process.curindex), corners_num);
|
||||
mesh->vert_positions_for_write().copy_from(process.co);
|
||||
blender::MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
|
||||
blender::MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
||||
|
||||
int loop_offset = 0;
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
for (int i = 0; i < mesh->faces_num; i++) {
|
||||
const int *indices = process.indices[i];
|
||||
|
||||
const int count = indices[2] != indices[3] ? 4 : 3;
|
||||
poly_offsets[i] = loop_offset;
|
||||
face_offsets[i] = loop_offset;
|
||||
|
||||
corner_verts[loop_offset] = indices[0];
|
||||
corner_verts[loop_offset + 1] = indices[1];
|
||||
|
||||
@@ -86,7 +86,7 @@ static void mesh_init_data(ID *id)
|
||||
|
||||
CustomData_reset(&mesh->vdata);
|
||||
CustomData_reset(&mesh->edata);
|
||||
CustomData_reset(&mesh->fdata);
|
||||
CustomData_reset(&mesh->fdata_legacy);
|
||||
CustomData_reset(&mesh->pdata);
|
||||
CustomData_reset(&mesh->ldata);
|
||||
|
||||
@@ -135,10 +135,10 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
||||
mesh_dst->runtime->verts_no_face_cache = mesh_src->runtime->verts_no_face_cache;
|
||||
mesh_dst->runtime->loose_edges_cache = mesh_src->runtime->loose_edges_cache;
|
||||
mesh_dst->runtime->looptris_cache = mesh_src->runtime->looptris_cache;
|
||||
mesh_dst->runtime->looptri_polys_cache = mesh_src->runtime->looptri_polys_cache;
|
||||
mesh_dst->runtime->looptri_faces_cache = mesh_src->runtime->looptri_faces_cache;
|
||||
|
||||
/* Only do tessface if we have no polys. */
|
||||
const bool do_tessface = ((mesh_src->totface != 0) && (mesh_src->totpoly == 0));
|
||||
/* Only do tessface if we have no faces. */
|
||||
const bool do_tessface = ((mesh_src->totface_legacy != 0) && (mesh_src->faces_num == 0));
|
||||
|
||||
CustomData_MeshMasks mask = CD_MASK_MESH;
|
||||
|
||||
@@ -158,13 +158,13 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_dst->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_dst->totedge);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_dst->totloop);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_dst->totpoly);
|
||||
blender::implicit_sharing::copy_shared_pointer(mesh_src->poly_offset_indices,
|
||||
mesh_src->runtime->poly_offsets_sharing_info,
|
||||
&mesh_dst->poly_offset_indices,
|
||||
&mesh_dst->runtime->poly_offsets_sharing_info);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_dst->faces_num);
|
||||
blender::implicit_sharing::copy_shared_pointer(mesh_src->face_offset_indices,
|
||||
mesh_src->runtime->face_offsets_sharing_info,
|
||||
&mesh_dst->face_offset_indices,
|
||||
&mesh_dst->runtime->face_offsets_sharing_info);
|
||||
if (do_tessface) {
|
||||
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, mesh_dst->totface);
|
||||
CustomData_copy(&mesh_src->fdata_legacy, &mesh_dst->fdata_legacy, mask.fmask, mesh_dst->totface_legacy);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(mesh_dst, false);
|
||||
@@ -235,12 +235,12 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
||||
Vector<CustomDataLayer, 16> vert_layers;
|
||||
Vector<CustomDataLayer, 16> edge_layers;
|
||||
Vector<CustomDataLayer, 16> loop_layers;
|
||||
Vector<CustomDataLayer, 16> poly_layers;
|
||||
Vector<CustomDataLayer, 16> face_layers;
|
||||
|
||||
/* Cache only - don't write. */
|
||||
mesh->mface = nullptr;
|
||||
mesh->totface = 0;
|
||||
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
|
||||
mesh->totface_legacy = 0;
|
||||
memset(&mesh->fdata_legacy, 0, sizeof(mesh->fdata_legacy));
|
||||
|
||||
/* Do not store actual geometry data in case this is a library override ID. */
|
||||
if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
|
||||
@@ -253,15 +253,15 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
||||
mesh->totloop = 0;
|
||||
memset(&mesh->ldata, 0, sizeof(mesh->ldata));
|
||||
|
||||
mesh->totpoly = 0;
|
||||
mesh->faces_num = 0;
|
||||
memset(&mesh->pdata, 0, sizeof(mesh->pdata));
|
||||
mesh->poly_offset_indices = nullptr;
|
||||
mesh->face_offset_indices = nullptr;
|
||||
}
|
||||
else {
|
||||
CustomData_blend_write_prepare(mesh->vdata, vert_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->edata, edge_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->ldata, loop_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->pdata, poly_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->pdata, face_layers, {});
|
||||
}
|
||||
|
||||
mesh->runtime = nullptr;
|
||||
@@ -285,14 +285,15 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
||||
CustomData_blend_write(
|
||||
writer, &mesh->edata, edge_layers, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
|
||||
/* `fdata` is cleared above but written so slots align. */
|
||||
CustomData_blend_write(writer, &mesh->fdata, {}, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
|
||||
CustomData_blend_write(
|
||||
writer, &mesh->fdata_legacy, {}, mesh->totface_legacy, CD_MASK_MESH.fmask, &mesh->id);
|
||||
CustomData_blend_write(
|
||||
writer, &mesh->ldata, loop_layers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
|
||||
CustomData_blend_write(
|
||||
writer, &mesh->pdata, poly_layers, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id);
|
||||
writer, &mesh->pdata, face_layers, mesh->faces_num, CD_MASK_MESH.pmask, &mesh->id);
|
||||
|
||||
if (mesh->poly_offset_indices) {
|
||||
BLO_write_int32_array(writer, mesh->totpoly + 1, mesh->poly_offset_indices);
|
||||
if (mesh->face_offset_indices) {
|
||||
BLO_write_int32_array(writer, mesh->faces_num + 1, mesh->face_offset_indices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,9 +321,9 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
||||
CustomData_blend_read(reader, &mesh->vdata, mesh->totvert);
|
||||
CustomData_blend_read(reader, &mesh->edata, mesh->totedge);
|
||||
CustomData_blend_read(reader, &mesh->fdata, mesh->totface);
|
||||
CustomData_blend_read(reader, &mesh->fdata_legacy, mesh->totface_legacy);
|
||||
CustomData_blend_read(reader, &mesh->ldata, mesh->totloop);
|
||||
CustomData_blend_read(reader, &mesh->pdata, mesh->totpoly);
|
||||
CustomData_blend_read(reader, &mesh->pdata, mesh->faces_num);
|
||||
if (mesh->deform_verts().is_empty()) {
|
||||
/* Vertex group data was also an owning pointer in old Blender versions.
|
||||
* Don't read them again if they were read as part of #CustomData. */
|
||||
@@ -336,10 +337,10 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
||||
mesh->runtime = new blender::bke::MeshRuntime();
|
||||
|
||||
if (mesh->poly_offset_indices) {
|
||||
BLO_read_int32_array(reader, mesh->totpoly + 1, &mesh->poly_offset_indices);
|
||||
mesh->runtime->poly_offsets_sharing_info = blender::implicit_sharing::info_for_mem_free(
|
||||
mesh->poly_offset_indices);
|
||||
if (mesh->face_offset_indices) {
|
||||
BLO_read_int32_array(reader, mesh->faces_num + 1, &mesh->face_offset_indices);
|
||||
mesh->runtime->face_offsets_sharing_info = blender::implicit_sharing::info_for_mem_free(
|
||||
mesh->face_offset_indices);
|
||||
}
|
||||
|
||||
if (mesh->mselect == nullptr) {
|
||||
@@ -348,7 +349,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
||||
if (BLO_read_requires_endian_switch(reader) && mesh->tface) {
|
||||
TFace *tf = mesh->tface;
|
||||
for (int i = 0; i < mesh->totface; i++, tf++) {
|
||||
for (int i = 0; i < mesh->totface_legacy; i++, tf++) {
|
||||
BLI_endian_switch_uint32_array(tf->col, 4);
|
||||
}
|
||||
}
|
||||
@@ -754,7 +755,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
|
||||
return "Number of edges don't match";
|
||||
}
|
||||
|
||||
if (me1->totpoly != me2->totpoly) {
|
||||
if (me1->faces_num != me2->faces_num) {
|
||||
return "Number of faces don't match";
|
||||
}
|
||||
|
||||
@@ -763,7 +764,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
|
||||
}
|
||||
|
||||
if (!std::equal(
|
||||
me1->poly_offsets().begin(), me1->poly_offsets().end(), me2->poly_offsets().begin()))
|
||||
me1->face_offsets().begin(), me1->face_offsets().end(), me2->face_offsets().begin()))
|
||||
{
|
||||
return "Face sizes don't match";
|
||||
}
|
||||
@@ -780,7 +781,7 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
|
||||
return cmpcode_to_str(c);
|
||||
}
|
||||
|
||||
if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, thresh))) {
|
||||
if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->faces_num, me1, thresh))) {
|
||||
return cmpcode_to_str(c);
|
||||
}
|
||||
|
||||
@@ -855,20 +856,20 @@ static void mesh_clear_geometry(Mesh &mesh)
|
||||
{
|
||||
CustomData_free(&mesh.vdata, mesh.totvert);
|
||||
CustomData_free(&mesh.edata, mesh.totedge);
|
||||
CustomData_free(&mesh.fdata, mesh.totface);
|
||||
CustomData_free(&mesh.fdata_legacy, mesh.totface_legacy);
|
||||
CustomData_free(&mesh.ldata, mesh.totloop);
|
||||
CustomData_free(&mesh.pdata, mesh.totpoly);
|
||||
if (mesh.poly_offset_indices) {
|
||||
blender::implicit_sharing::free_shared_data(&mesh.poly_offset_indices,
|
||||
&mesh.runtime->poly_offsets_sharing_info);
|
||||
CustomData_free(&mesh.pdata, mesh.faces_num);
|
||||
if (mesh.face_offset_indices) {
|
||||
blender::implicit_sharing::free_shared_data(&mesh.face_offset_indices,
|
||||
&mesh.runtime->face_offsets_sharing_info);
|
||||
}
|
||||
MEM_SAFE_FREE(mesh.mselect);
|
||||
|
||||
mesh.totvert = 0;
|
||||
mesh.totedge = 0;
|
||||
mesh.totface = 0;
|
||||
mesh.totface_legacy = 0;
|
||||
mesh.totloop = 0;
|
||||
mesh.totpoly = 0;
|
||||
mesh.faces_num = 0;
|
||||
mesh.act_face = -1;
|
||||
mesh.totselect = 0;
|
||||
}
|
||||
@@ -896,13 +897,13 @@ void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh)
|
||||
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
|
||||
{
|
||||
if (free_customdata) {
|
||||
CustomData_free(&mesh->fdata, mesh->totface);
|
||||
CustomData_free(&mesh->fdata_legacy, mesh->totface_legacy);
|
||||
}
|
||||
else {
|
||||
CustomData_reset(&mesh->fdata);
|
||||
CustomData_reset(&mesh->fdata_legacy);
|
||||
}
|
||||
|
||||
mesh->totface = 0;
|
||||
mesh->totface_legacy = 0;
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_add(Main *bmain, const char *name)
|
||||
@@ -910,35 +911,35 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
|
||||
return static_cast<Mesh *>(BKE_id_new(bmain, ID_ME, name));
|
||||
}
|
||||
|
||||
void BKE_mesh_poly_offsets_ensure_alloc(Mesh *mesh)
|
||||
void BKE_mesh_face_offsets_ensure_alloc(Mesh *mesh)
|
||||
{
|
||||
BLI_assert(mesh->poly_offset_indices == nullptr);
|
||||
BLI_assert(mesh->runtime->poly_offsets_sharing_info == nullptr);
|
||||
if (mesh->totpoly == 0) {
|
||||
BLI_assert(mesh->face_offset_indices == nullptr);
|
||||
BLI_assert(mesh->runtime->face_offsets_sharing_info == nullptr);
|
||||
if (mesh->faces_num == 0) {
|
||||
return;
|
||||
}
|
||||
mesh->poly_offset_indices = static_cast<int *>(
|
||||
MEM_malloc_arrayN(mesh->totpoly + 1, sizeof(int), __func__));
|
||||
mesh->runtime->poly_offsets_sharing_info = blender::implicit_sharing::info_for_mem_free(
|
||||
mesh->poly_offset_indices);
|
||||
mesh->face_offset_indices = static_cast<int *>(
|
||||
MEM_malloc_arrayN(mesh->faces_num + 1, sizeof(int), __func__));
|
||||
mesh->runtime->face_offsets_sharing_info = blender::implicit_sharing::info_for_mem_free(
|
||||
mesh->face_offset_indices);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Fill offsets with obviously bad values to simplify finding missing initialization. */
|
||||
mesh->poly_offsets_for_write().fill(-1);
|
||||
mesh->face_offsets_for_write().fill(-1);
|
||||
#endif
|
||||
/* Set common values for convenience. */
|
||||
mesh->poly_offset_indices[0] = 0;
|
||||
mesh->poly_offset_indices[mesh->totpoly] = mesh->totloop;
|
||||
mesh->face_offset_indices[0] = 0;
|
||||
mesh->face_offset_indices[mesh->faces_num] = mesh->totloop;
|
||||
}
|
||||
|
||||
MutableSpan<int> Mesh::poly_offsets_for_write()
|
||||
MutableSpan<int> Mesh::face_offsets_for_write()
|
||||
{
|
||||
if (this->totpoly == 0) {
|
||||
if (this->faces_num == 0) {
|
||||
return {};
|
||||
}
|
||||
blender::implicit_sharing::make_trivial_data_mutable(
|
||||
&this->poly_offset_indices, &this->runtime->poly_offsets_sharing_info, this->totpoly + 1);
|
||||
return {this->poly_offset_indices, this->totpoly + 1};
|
||||
&this->face_offset_indices, &this->runtime->face_offsets_sharing_info, this->faces_num + 1);
|
||||
return {this->face_offset_indices, this->faces_num + 1};
|
||||
}
|
||||
|
||||
static void mesh_ensure_cdlayers_primary(Mesh &mesh)
|
||||
@@ -955,7 +956,7 @@ static void mesh_ensure_cdlayers_primary(Mesh &mesh)
|
||||
|
||||
Mesh *BKE_mesh_new_nomain(const int verts_num,
|
||||
const int edges_num,
|
||||
const int polys_num,
|
||||
const int faces_num,
|
||||
const int loops_num)
|
||||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(BKE_libblock_alloc(
|
||||
@@ -964,11 +965,11 @@ Mesh *BKE_mesh_new_nomain(const int verts_num,
|
||||
|
||||
mesh->totvert = verts_num;
|
||||
mesh->totedge = edges_num;
|
||||
mesh->totpoly = polys_num;
|
||||
mesh->faces_num = faces_num;
|
||||
mesh->totloop = loops_num;
|
||||
|
||||
mesh_ensure_cdlayers_primary(*mesh);
|
||||
BKE_mesh_poly_offsets_ensure_alloc(mesh);
|
||||
BKE_mesh_face_offsets_ensure_alloc(mesh);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
@@ -1032,12 +1033,13 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
const int verts_num,
|
||||
const int edges_num,
|
||||
const int tessface_num,
|
||||
const int polys_num,
|
||||
const int faces_num,
|
||||
const int loops_num,
|
||||
const CustomData_MeshMasks mask)
|
||||
{
|
||||
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
|
||||
const bool do_tessface = (tessface_num || ((me_src->totface != 0) && (me_src->totpoly == 0)));
|
||||
const bool do_tessface = (tessface_num ||
|
||||
((me_src->totface_legacy != 0) && (me_src->faces_num == 0)));
|
||||
|
||||
Mesh *me_dst = static_cast<Mesh *>(BKE_id_new_nomain(ID_ME, nullptr));
|
||||
|
||||
@@ -1045,19 +1047,19 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
|
||||
me_dst->totvert = verts_num;
|
||||
me_dst->totedge = edges_num;
|
||||
me_dst->totpoly = polys_num;
|
||||
me_dst->faces_num = faces_num;
|
||||
me_dst->totloop = loops_num;
|
||||
me_dst->totface = tessface_num;
|
||||
me_dst->totface_legacy = tessface_num;
|
||||
|
||||
BKE_mesh_copy_parameters_for_eval(me_dst, me_src);
|
||||
|
||||
CustomData_copy_layout(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_num);
|
||||
CustomData_copy_layout(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_num);
|
||||
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_num);
|
||||
CustomData_copy_layout(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, faces_num);
|
||||
CustomData_copy_layout(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_num);
|
||||
if (do_tessface) {
|
||||
CustomData_copy_layout(
|
||||
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_num);
|
||||
&me_src->fdata_legacy, &me_dst->fdata_legacy, mask.fmask, CD_SET_DEFAULT, tessface_num);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
@@ -1066,9 +1068,9 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
/* The destination mesh should at least have valid primary CD layers,
|
||||
* even in cases where the source mesh does not. */
|
||||
mesh_ensure_cdlayers_primary(*me_dst);
|
||||
BKE_mesh_poly_offsets_ensure_alloc(me_dst);
|
||||
if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) {
|
||||
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, me_dst->totface);
|
||||
BKE_mesh_face_offsets_ensure_alloc(me_dst);
|
||||
if (do_tessface && !CustomData_get_layer(&me_dst->fdata_legacy, CD_MFACE)) {
|
||||
CustomData_add_layer(&me_dst->fdata_legacy, CD_MFACE, CD_SET_DEFAULT, me_dst->totface_legacy);
|
||||
}
|
||||
|
||||
/* Expect that normals aren't copied at all, since the destination mesh is new. */
|
||||
@@ -1080,11 +1082,11 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src,
|
||||
const int verts_num,
|
||||
const int edges_num,
|
||||
const int polys_num,
|
||||
const int faces_num,
|
||||
const int loops_num)
|
||||
{
|
||||
return BKE_mesh_new_nomain_from_template_ex(
|
||||
me_src, verts_num, edges_num, 0, polys_num, loops_num, CD_MASK_EVERYTHING);
|
||||
me_src, verts_num, edges_num, 0, faces_num, loops_num, CD_MASK_EVERYTHING);
|
||||
}
|
||||
|
||||
void BKE_mesh_eval_delete(Mesh *mesh_eval)
|
||||
@@ -1168,7 +1170,7 @@ void BKE_mesh_ensure_default_orig_index_customdata_no_check(Mesh *mesh)
|
||||
{
|
||||
ensure_orig_index_layer(mesh->vdata, mesh->totvert);
|
||||
ensure_orig_index_layer(mesh->edata, mesh->totedge);
|
||||
ensure_orig_index_layer(mesh->pdata, mesh->totpoly);
|
||||
ensure_orig_index_layer(mesh->pdata, mesh->faces_num);
|
||||
}
|
||||
|
||||
BoundBox *BKE_mesh_boundbox_get(Object *ob)
|
||||
@@ -1800,12 +1802,12 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
||||
blender::bke::mesh::normals_calc_loop(
|
||||
mesh->vert_positions(),
|
||||
mesh->edges(),
|
||||
mesh->polys(),
|
||||
mesh->faces(),
|
||||
mesh->corner_verts(),
|
||||
mesh->corner_edges(),
|
||||
{},
|
||||
mesh->vert_normals(),
|
||||
mesh->poly_normals(),
|
||||
mesh->face_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
use_split_normals,
|
||||
|
||||
@@ -73,12 +73,12 @@ class MeshesToIMeshInfo {
|
||||
Array<int> mesh_vert_offset;
|
||||
/* Similarly for edges of meshes. */
|
||||
Array<int> mesh_edge_offset;
|
||||
/* Similarly for polys of meshes. */
|
||||
Array<int> mesh_poly_offset;
|
||||
/* Similarly for faces of meshes. */
|
||||
Array<int> mesh_face_offset;
|
||||
/* For each Mesh vertex in all the meshes (with concatenated indexing),
|
||||
* what is the IMesh Vert* allocated for it in the input IMesh? */
|
||||
Array<const Vert *> mesh_to_imesh_vert;
|
||||
/* Similarly for each Mesh poly. */
|
||||
/* Similarly for each Mesh face. */
|
||||
Array<Face *> mesh_to_imesh_face;
|
||||
/* Transformation matrix to transform a coordinate in the corresponding
|
||||
* Mesh to the local space of the first Mesh. */
|
||||
@@ -98,10 +98,10 @@ class MeshesToIMeshInfo {
|
||||
int input_mesh_for_imesh_vert(int imesh_v) const;
|
||||
int input_mesh_for_imesh_edge(int imesh_e) const;
|
||||
int input_mesh_for_imesh_face(int imesh_f) const;
|
||||
const IndexRange input_mpoly_for_orig_index(int orig_index,
|
||||
const Mesh **r_orig_mesh,
|
||||
int *r_orig_mesh_index,
|
||||
int *r_index_in_orig_mesh) const;
|
||||
const IndexRange input_face_for_orig_index(int orig_index,
|
||||
const Mesh **r_orig_mesh,
|
||||
int *r_orig_mesh_index,
|
||||
int *r_index_in_orig_mesh) const;
|
||||
void input_mvert_for_orig_index(int orig_index,
|
||||
const Mesh **r_orig_mesh,
|
||||
int *r_index_in_orig_mesh) const;
|
||||
@@ -137,12 +137,12 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const
|
||||
}
|
||||
|
||||
/* Given an index `imesh_f` in the `IMesh`, return the index of the
|
||||
* input `Mesh` that contained the polygon that it came from. */
|
||||
* input `Mesh` that contained the face that it came from. */
|
||||
int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const
|
||||
{
|
||||
int n = int(mesh_poly_offset.size());
|
||||
int n = int(mesh_face_offset.size());
|
||||
for (int i = 0; i < n - 1; ++i) {
|
||||
if (imesh_f < mesh_poly_offset[i + 1]) {
|
||||
if (imesh_f < mesh_face_offset[i + 1]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -152,20 +152,20 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const
|
||||
/* Given an index of an original face in the `IMesh`, find out the input
|
||||
* `Mesh` that it came from and return it in `*r_orig_mesh`,
|
||||
* and also return the index of that `Mesh` in `*r_orig_mesh_index`.
|
||||
* Finally, return the index of the corresponding polygon in that `Mesh`
|
||||
* Finally, return the index of the corresponding face in that `Mesh`
|
||||
* in `*r_index_in_orig_mesh`. */
|
||||
const IndexRange MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index,
|
||||
const Mesh **r_orig_mesh,
|
||||
int *r_orig_mesh_index,
|
||||
int *r_index_in_orig_mesh) const
|
||||
const IndexRange MeshesToIMeshInfo::input_face_for_orig_index(int orig_index,
|
||||
const Mesh **r_orig_mesh,
|
||||
int *r_orig_mesh_index,
|
||||
int *r_index_in_orig_mesh) const
|
||||
{
|
||||
int orig_mesh_index = input_mesh_for_imesh_face(orig_index);
|
||||
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
|
||||
const Mesh *me = meshes[orig_mesh_index];
|
||||
const OffsetIndices polys = me->polys();
|
||||
int index_in_mesh = orig_index - mesh_poly_offset[orig_mesh_index];
|
||||
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totpoly);
|
||||
const IndexRange poly = polys[index_in_mesh];
|
||||
const OffsetIndices faces = me->faces();
|
||||
int index_in_mesh = orig_index - mesh_face_offset[orig_mesh_index];
|
||||
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->faces_num);
|
||||
const IndexRange face = faces[index_in_mesh];
|
||||
if (r_orig_mesh) {
|
||||
*r_orig_mesh = me;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ const IndexRange MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index,
|
||||
if (r_index_in_orig_mesh) {
|
||||
*r_index_in_orig_mesh = index_in_mesh;
|
||||
}
|
||||
return poly;
|
||||
return face;
|
||||
}
|
||||
|
||||
/* Given an index of an original vertex in the `IMesh`, find out the input
|
||||
@@ -223,7 +223,7 @@ void MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
|
||||
* first Mesh. To do this transformation, we also need the transformation
|
||||
* obmats corresponding to the Meshes, so they are in the `obmats` argument.
|
||||
* The 'original' indexes in the IMesh are the indexes you get by
|
||||
* a scheme that offsets each vertex, edge, and polygon index by the sum of the
|
||||
* a scheme that offsets each vertex, edge, and face index by the sum of the
|
||||
* vertices, edges, and polys in the preceding Meshes in the mesh span.
|
||||
* The `*r_info class` is filled in with information needed to make the
|
||||
* correspondence between the Mesh MVerts/MPolys and the IMesh Verts/Faces.
|
||||
@@ -243,24 +243,24 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
|
||||
r_info->tot_meshes_polys = 0;
|
||||
int &totvert = r_info->tot_meshes_verts;
|
||||
int &totedge = r_info->tot_meshes_edges;
|
||||
int &totpoly = r_info->tot_meshes_polys;
|
||||
int &faces_num = r_info->tot_meshes_polys;
|
||||
for (const Mesh *me : meshes) {
|
||||
totvert += me->totvert;
|
||||
totedge += me->totedge;
|
||||
totpoly += me->totpoly;
|
||||
faces_num += me->faces_num;
|
||||
}
|
||||
|
||||
/* Estimate the number of vertices and faces in the boolean output,
|
||||
* so that the memory arena can reserve some space. It is OK if these
|
||||
* estimates are wrong. */
|
||||
const int estimate_num_outv = 3 * totvert;
|
||||
const int estimate_num_outf = 4 * totpoly;
|
||||
const int estimate_num_outf = 4 * faces_num;
|
||||
arena.reserve(estimate_num_outv, estimate_num_outf);
|
||||
r_info->mesh_to_imesh_vert.reinitialize(totvert);
|
||||
r_info->mesh_to_imesh_face.reinitialize(totpoly);
|
||||
r_info->mesh_to_imesh_face.reinitialize(faces_num);
|
||||
r_info->mesh_vert_offset.reinitialize(nmeshes);
|
||||
r_info->mesh_edge_offset.reinitialize(nmeshes);
|
||||
r_info->mesh_poly_offset.reinitialize(nmeshes);
|
||||
r_info->mesh_face_offset.reinitialize(nmeshes);
|
||||
r_info->to_target_transform.reinitialize(nmeshes);
|
||||
r_info->has_negative_transform.reinitialize(nmeshes);
|
||||
r_info->material_remaps = material_remaps;
|
||||
@@ -289,7 +289,7 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
|
||||
const Mesh *me = meshes[mi];
|
||||
r_info->mesh_vert_offset[mi] = v;
|
||||
r_info->mesh_edge_offset[mi] = e;
|
||||
r_info->mesh_poly_offset[mi] = f;
|
||||
r_info->mesh_face_offset[mi] = f;
|
||||
/* Get matrix that transforms a coordinate in meshes[mi]'s local space
|
||||
* to the target space. */
|
||||
const float4x4 objn_mat = (obmats.is_empty() || obmats[mi] == nullptr) ?
|
||||
@@ -305,7 +305,7 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
|
||||
|
||||
Vector<Vert *> verts(me->totvert);
|
||||
const Span<float3> vert_positions = me->vert_positions();
|
||||
const OffsetIndices polys = me->polys();
|
||||
const OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
const Span<int> corner_edges = me->corner_edges();
|
||||
|
||||
@@ -338,13 +338,13 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes,
|
||||
++v;
|
||||
}
|
||||
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
const IndexRange poly = polys[poly_i];
|
||||
int flen = poly.size();
|
||||
for (const int face_i : faces.index_range()) {
|
||||
const IndexRange face = faces[face_i];
|
||||
int flen = face.size();
|
||||
face_vert.resize(flen);
|
||||
face_edge_orig.resize(flen);
|
||||
for (int i = 0; i < flen; ++i) {
|
||||
const int corner_i = poly[i];
|
||||
const int corner_i = face[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) {
|
||||
@@ -392,10 +392,10 @@ static void copy_vert_attributes(Mesh *dest_mesh,
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar to copy_vert_attributes but for poly attributes. */
|
||||
static void copy_poly_attributes(Mesh *dest_mesh,
|
||||
/* Similar to copy_vert_attributes but for face attributes. */
|
||||
static void copy_face_attributes(Mesh *dest_mesh,
|
||||
const Mesh *orig_me,
|
||||
int poly_index,
|
||||
int face_index,
|
||||
int index_in_orig_me,
|
||||
Span<short> material_remap,
|
||||
MutableSpan<int> dst_material_indices)
|
||||
@@ -408,7 +408,7 @@ static void copy_poly_attributes(Mesh *dest_mesh,
|
||||
int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name);
|
||||
if (target_layer_i != -1) {
|
||||
CustomData_copy_data_layer(
|
||||
source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, poly_index, 1);
|
||||
source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, face_index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,12 +418,12 @@ static void copy_poly_attributes(Mesh *dest_mesh,
|
||||
const int src_index = src_material_indices[index_in_orig_me];
|
||||
if (material_remap.index_range().contains(src_index)) {
|
||||
const int remapped_index = material_remap[src_index];
|
||||
dst_material_indices[poly_index] = remapped_index >= 0 ? remapped_index : src_index;
|
||||
dst_material_indices[face_index] = remapped_index >= 0 ? remapped_index : src_index;
|
||||
}
|
||||
else {
|
||||
dst_material_indices[poly_index] = src_index;
|
||||
dst_material_indices[face_index] = src_index;
|
||||
}
|
||||
BLI_assert(dst_material_indices[poly_index] >= 0);
|
||||
BLI_assert(dst_material_indices[face_index] >= 0);
|
||||
}
|
||||
|
||||
/* Similar to copy_vert_attributes but for edge attributes. */
|
||||
@@ -451,17 +451,17 @@ static void copy_edge_attributes(Mesh *dest_mesh,
|
||||
}
|
||||
|
||||
/**
|
||||
* For #IMesh face `f`, with corresponding output Mesh poly `poly`,
|
||||
* where the original Mesh poly is `orig_poly`, coming from the Mesh
|
||||
* For #IMesh face `f`, with corresponding output Mesh face `face`,
|
||||
* where the original Mesh face is `orig_face`, coming from the Mesh
|
||||
* `orig_me`, which has index `orig_me_index` in `mim`:
|
||||
* fill in the `orig_loops` Array with corresponding indices of MLoops from `orig_me`
|
||||
* where they have the same start and end vertices; for cases where that is
|
||||
* not true, put -1 in the `orig_loops` slot.
|
||||
* For now, we only try to do this if `poly` and `orig_poly` have the same size.
|
||||
* For now, we only try to do this if `face` and `orig_face` have the same size.
|
||||
* Return the number of non-null MLoops filled in.
|
||||
*/
|
||||
static int fill_orig_loops(const Face *f,
|
||||
const IndexRange orig_poly,
|
||||
const IndexRange orig_face,
|
||||
const Mesh *orig_me,
|
||||
int orig_me_index,
|
||||
MeshesToIMeshInfo &mim,
|
||||
@@ -470,7 +470,7 @@ static int fill_orig_loops(const Face *f,
|
||||
r_orig_loops.fill(-1);
|
||||
const Span<int> orig_corner_verts = orig_me->corner_verts();
|
||||
|
||||
int orig_mplen = orig_poly.size();
|
||||
int orig_mplen = orig_face.size();
|
||||
if (f->size() != orig_mplen) {
|
||||
return 0;
|
||||
}
|
||||
@@ -495,7 +495,7 @@ static int fill_orig_loops(const Face *f,
|
||||
/* Assume all vertices in an mpoly are unique. */
|
||||
int offset = -1;
|
||||
for (int i = 0; i < orig_mplen; ++i) {
|
||||
int loop_i = i + orig_poly.start();
|
||||
int loop_i = i + orig_face.start();
|
||||
if (orig_corner_verts[loop_i] == first_orig_v_in_orig_me) {
|
||||
offset = i;
|
||||
break;
|
||||
@@ -507,7 +507,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 int vert_i = orig_corner_verts[orig_poly.start() + orig_mp_loop_index];
|
||||
const int vert_i = orig_corner_verts[orig_face.start() + orig_mp_loop_index];
|
||||
int fv_orig = f->vert[mp_loop_index]->orig;
|
||||
if (fv_orig != NO_INDEX) {
|
||||
fv_orig -= orig_me_vert_offset;
|
||||
@@ -517,7 +517,7 @@ static int fill_orig_loops(const Face *f,
|
||||
}
|
||||
if (vert_i == fv_orig) {
|
||||
const int vert_next =
|
||||
orig_corner_verts[orig_poly.start() + ((orig_mp_loop_index + 1) % orig_mplen)];
|
||||
orig_corner_verts[orig_face.start() + ((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;
|
||||
@@ -526,7 +526,7 @@ static int fill_orig_loops(const Face *f,
|
||||
}
|
||||
}
|
||||
if (vert_next == fvnext_orig) {
|
||||
r_orig_loops[mp_loop_index] = orig_poly.start() + orig_mp_loop_index;
|
||||
r_orig_loops[mp_loop_index] = orig_face.start() + orig_mp_loop_index;
|
||||
++num_orig_loops_found;
|
||||
}
|
||||
}
|
||||
@@ -534,74 +534,74 @@ static int fill_orig_loops(const Face *f,
|
||||
return num_orig_loops_found;
|
||||
}
|
||||
|
||||
/* Fill `cos_2d` with the 2d coordinates found by projection polygon `poly` along
|
||||
/* Fill `cos_2d` with the 2d coordinates found by projection face `face` along
|
||||
* its normal. Also fill in r_axis_mat with the matrix that does that projection.
|
||||
* But before projecting, also transform the 3d coordinate by multiplying by trans_mat.
|
||||
* `cos_2d` should have room for `poly.size()` entries. */
|
||||
* `cos_2d` should have room for `face.size()` entries. */
|
||||
static void get_poly2d_cos(const Mesh *me,
|
||||
const IndexRange poly,
|
||||
const IndexRange face,
|
||||
float (*cos_2d)[2],
|
||||
const float4x4 &trans_mat,
|
||||
float r_axis_mat[3][3])
|
||||
{
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
const Span<int> poly_verts = corner_verts.slice(poly);
|
||||
const Span<int> face_verts = corner_verts.slice(face);
|
||||
|
||||
/* Project coordinates to 2d in cos_2d, using normal as projection axis. */
|
||||
const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_verts);
|
||||
const float3 axis_dominant = bke::mesh::face_normal_calc(positions, face_verts);
|
||||
axis_dominant_v3_to_m3(r_axis_mat, axis_dominant);
|
||||
for (const int i : poly_verts.index_range()) {
|
||||
float3 co = positions[poly_verts[i]];
|
||||
for (const int i : face_verts.index_range()) {
|
||||
float3 co = positions[face_verts[i]];
|
||||
co = math::transform_point(trans_mat, co);
|
||||
*reinterpret_cast<float2 *>(&cos_2d[i]) = (float3x3(r_axis_mat) * co).xy();
|
||||
}
|
||||
}
|
||||
|
||||
/* For the loops of `poly`, see if the face is unchanged from `orig_poly`, and if so,
|
||||
/* For the loops of `face`, see if the face is unchanged from `orig_face`, and if so,
|
||||
* copy the Loop attributes from corresponding loops to corresponding loops.
|
||||
* Otherwise, interpolate the Loop attributes in the face `orig_poly`. */
|
||||
* Otherwise, interpolate the Loop attributes in the face `orig_face`. */
|
||||
static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
|
||||
const Face *f,
|
||||
const IndexRange poly,
|
||||
const IndexRange orig_poly,
|
||||
const IndexRange face,
|
||||
const IndexRange orig_face,
|
||||
const Mesh *orig_me,
|
||||
int orig_me_index,
|
||||
MeshesToIMeshInfo &mim)
|
||||
{
|
||||
Array<int> orig_loops(poly.size());
|
||||
int norig = fill_orig_loops(f, orig_poly, orig_me, orig_me_index, mim, orig_loops);
|
||||
Array<int> orig_loops(face.size());
|
||||
int norig = fill_orig_loops(f, orig_face, orig_me, orig_me_index, mim, orig_loops);
|
||||
/* We may need these arrays if we have to interpolate Loop attributes rather than just copy.
|
||||
* Right now, trying Array<float[2]> complains, so declare cos_2d a different way. */
|
||||
float(*cos_2d)[2];
|
||||
Array<float> weights;
|
||||
Array<const void *> src_blocks_ofs;
|
||||
float axis_mat[3][3];
|
||||
if (norig != poly.size()) {
|
||||
/* We will need to interpolate. Make `cos_2d` hold 2d-projected coordinates of `orig_poly`,
|
||||
if (norig != face.size()) {
|
||||
/* We will need to interpolate. Make `cos_2d` hold 2d-projected coordinates of `orig_face`,
|
||||
* which are transformed into object 0's local space before projecting.
|
||||
* At this point we cannot yet calculate the interpolation weights, as they depend on
|
||||
* the coordinate where interpolation is to happen, but we can allocate the needed arrays,
|
||||
* so they don't have to be allocated per-layer. */
|
||||
cos_2d = (float(*)[2])BLI_array_alloca(cos_2d, orig_poly.size());
|
||||
weights = Array<float>(orig_poly.size());
|
||||
src_blocks_ofs = Array<const void *>(orig_poly.size());
|
||||
get_poly2d_cos(orig_me, orig_poly, cos_2d, mim.to_target_transform[orig_me_index], axis_mat);
|
||||
cos_2d = (float(*)[2])BLI_array_alloca(cos_2d, orig_face.size());
|
||||
weights = Array<float>(orig_face.size());
|
||||
src_blocks_ofs = Array<const void *>(orig_face.size());
|
||||
get_poly2d_cos(orig_me, orig_face, cos_2d, mim.to_target_transform[orig_me_index], axis_mat);
|
||||
}
|
||||
CustomData *target_cd = &dest_mesh->ldata;
|
||||
const Span<float3> dst_positions = dest_mesh->vert_positions();
|
||||
const Span<int> dst_corner_verts = dest_mesh->corner_verts();
|
||||
for (int i = 0; i < poly.size(); ++i) {
|
||||
int loop_index = poly[i];
|
||||
for (int i = 0; i < face.size(); ++i) {
|
||||
int loop_index = face[i];
|
||||
int orig_loop_index = norig > 0 ? orig_loops[i] : -1;
|
||||
const CustomData *source_cd = &orig_me->ldata;
|
||||
if (orig_loop_index == -1) {
|
||||
/* Will need interpolation weights for this loop's vertex's coordinates.
|
||||
* The coordinate needs to be projected into 2d, just like the interpolating polygon's
|
||||
* The coordinate needs to be projected into 2d, just like the interpolating face'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_corner_verts[loop_index]]);
|
||||
interp_weights_poly_v2(weights.data(), cos_2d, orig_poly.size(), co);
|
||||
interp_weights_poly_v2(weights.data(), cos_2d, orig_face.size(), co);
|
||||
}
|
||||
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
||||
const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type);
|
||||
@@ -630,9 +630,9 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
|
||||
int source_layer_type_index = source_layer_i - source_cd->typemap[ty];
|
||||
BLI_assert(target_layer_type_index != -1 && source_layer_type_index >= 0);
|
||||
const int size = CustomData_sizeof(ty);
|
||||
for (int j = 0; j < orig_poly.size(); ++j) {
|
||||
for (int j = 0; j < orig_face.size(); ++j) {
|
||||
const void *layer = CustomData_get_layer_n(source_cd, ty, source_layer_type_index);
|
||||
src_blocks_ofs[j] = POINTER_OFFSET(layer, size * (orig_poly[j]));
|
||||
src_blocks_ofs[j] = POINTER_OFFSET(layer, size * (orig_face[j]));
|
||||
}
|
||||
void *dst_layer = CustomData_get_layer_n_for_write(
|
||||
target_cd, ty, target_layer_type_index, dest_mesh->totloop);
|
||||
@@ -641,7 +641,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
|
||||
src_blocks_ofs.data(),
|
||||
weights.data(),
|
||||
nullptr,
|
||||
orig_poly.size(),
|
||||
orig_face.size(),
|
||||
dst_block_ofs,
|
||||
target_layer_i);
|
||||
}
|
||||
@@ -655,7 +655,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
|
||||
* (The target should already have layers for those in the first operand mesh).
|
||||
* Edges done separately -- will have to be done later, after edges are made.
|
||||
*/
|
||||
static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
|
||||
static void merge_vertex_loop_face_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
|
||||
{
|
||||
for (int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
|
||||
const Mesh *me = mim.meshes[mesh_index];
|
||||
@@ -667,9 +667,12 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh
|
||||
CustomData_merge_layout(
|
||||
&me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop);
|
||||
}
|
||||
if (me->totpoly) {
|
||||
CustomData_merge_layout(
|
||||
&me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly);
|
||||
if (me->faces_num) {
|
||||
CustomData_merge_layout(&me->pdata,
|
||||
&target->pdata,
|
||||
CD_MASK_MESH.pmask,
|
||||
CD_SET_DEFAULT,
|
||||
target->faces_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -695,16 +698,16 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
||||
|
||||
im->populate_vert();
|
||||
int out_totvert = im->vert_size();
|
||||
int out_totpoly = im->face_size();
|
||||
int out_faces_num = im->face_size();
|
||||
int out_totloop = 0;
|
||||
for (const Face *f : im->faces()) {
|
||||
out_totloop += f->size();
|
||||
}
|
||||
/* Will calculate edges later. */
|
||||
Mesh *result = BKE_mesh_new_nomain_from_template(
|
||||
mim.meshes[0], out_totvert, 0, out_totpoly, out_totloop);
|
||||
mim.meshes[0], out_totvert, 0, out_faces_num, out_totloop);
|
||||
|
||||
merge_vertex_loop_poly_customdata_layers(result, mim);
|
||||
merge_vertex_loop_face_customdata_layers(result, mim);
|
||||
/* Set the vertex coordinate values and other data. */
|
||||
MutableSpan<float3> positions = result->vert_positions_for_write();
|
||||
for (int vi : im->vert_index_range()) {
|
||||
@@ -718,22 +721,22 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
||||
copy_v3fl_v3db(positions[vi], v->co);
|
||||
}
|
||||
|
||||
/* Set the loop-start and total-loops for each output poly,
|
||||
/* Set the loop-start and total-loops for each output face,
|
||||
* and set the vertices in the appropriate loops. */
|
||||
bke::SpanAttributeWriter<int> dst_material_indices =
|
||||
result->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index",
|
||||
ATTR_DOMAIN_FACE);
|
||||
int cur_loop_index = 0;
|
||||
MutableSpan<int> dst_corner_verts = result->corner_verts_for_write();
|
||||
MutableSpan<int> dst_poly_offsets = result->poly_offsets_for_write();
|
||||
MutableSpan<int> dst_face_offsets = result->face_offsets_for_write();
|
||||
for (int fi : im->face_index_range()) {
|
||||
const Face *f = im->face(fi);
|
||||
const Mesh *orig_me;
|
||||
int index_in_orig_me;
|
||||
int orig_me_index;
|
||||
const IndexRange orig_poly = mim.input_mpoly_for_orig_index(
|
||||
const IndexRange orig_face = mim.input_face_for_orig_index(
|
||||
f->orig, &orig_me, &orig_me_index, &index_in_orig_me);
|
||||
dst_poly_offsets[fi] = cur_loop_index;
|
||||
dst_face_offsets[fi] = cur_loop_index;
|
||||
for (int j : f->index_range()) {
|
||||
const Vert *vf = f->vert[j];
|
||||
const int vfi = im->lookup_vert(vf);
|
||||
@@ -741,7 +744,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
||||
++cur_loop_index;
|
||||
}
|
||||
|
||||
copy_poly_attributes(result,
|
||||
copy_face_attributes(result,
|
||||
orig_me,
|
||||
fi,
|
||||
index_in_orig_me,
|
||||
@@ -751,8 +754,8 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
||||
dst_material_indices.span);
|
||||
copy_or_interp_loop_attributes(result,
|
||||
f,
|
||||
IndexRange(dst_poly_offsets[fi], f->size()),
|
||||
orig_poly,
|
||||
IndexRange(dst_face_offsets[fi], f->size()),
|
||||
orig_face,
|
||||
orig_me,
|
||||
orig_me_index,
|
||||
mim);
|
||||
@@ -766,17 +769,17 @@ 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 OffsetIndices dst_polys = result->polys();
|
||||
const OffsetIndices dst_polys = result->faces();
|
||||
const Span<int> dst_corner_edges = result->corner_edges();
|
||||
for (int fi : im->face_index_range()) {
|
||||
const Face *f = im->face(fi);
|
||||
const IndexRange poly = dst_polys[fi];
|
||||
const IndexRange face = dst_polys[fi];
|
||||
for (int j : f->index_range()) {
|
||||
if (f->edge_orig[j] != NO_INDEX) {
|
||||
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_corner_edges[poly[j]];
|
||||
int e_index = dst_corner_edges[face[j]];
|
||||
copy_edge_attributes(result, orig_me, e_index, index_in_orig_me);
|
||||
}
|
||||
}
|
||||
@@ -814,12 +817,12 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
|
||||
IMeshArena arena;
|
||||
IMesh m_in = meshes_to_imesh(meshes, transforms, material_remaps, target_transform, arena, &mim);
|
||||
std::function<int(int)> shape_fn = [&mim](int f) {
|
||||
for (int mi = 0; mi < mim.mesh_poly_offset.size() - 1; ++mi) {
|
||||
if (f < mim.mesh_poly_offset[mi + 1]) {
|
||||
for (int mi = 0; mi < mim.mesh_face_offset.size() - 1; ++mi) {
|
||||
if (f < mim.mesh_face_offset[mi + 1]) {
|
||||
return mi;
|
||||
}
|
||||
}
|
||||
return int(mim.mesh_poly_offset.size()) - 1;
|
||||
return int(mim.mesh_face_offset.size()) - 1;
|
||||
};
|
||||
IMesh m_out = boolean_mesh(m_in,
|
||||
static_cast<BoolOpType>(boolean_mode),
|
||||
@@ -838,14 +841,14 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
|
||||
|
||||
/* Store intersecting edge indices. */
|
||||
if (r_intersecting_edges != nullptr) {
|
||||
const OffsetIndices polys = result->polys();
|
||||
const OffsetIndices faces = result->faces();
|
||||
const Span<int> corner_edges = result->corner_edges();
|
||||
for (int fi : m_out.face_index_range()) {
|
||||
const Face &face = *m_out.face(fi);
|
||||
const IndexRange poly = polys[fi];
|
||||
const IndexRange mesh_face = faces[fi];
|
||||
for (int i : face.index_range()) {
|
||||
if (face.is_intersect[i]) {
|
||||
int e_index = corner_edges[poly[i]];
|
||||
int e_index = corner_edges[mesh_face[i]];
|
||||
r_intersecting_edges->append(e_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ static void reserve_hash_maps(const Mesh *mesh,
|
||||
const bool keep_existing_edges,
|
||||
MutableSpan<EdgeMap> edge_maps)
|
||||
{
|
||||
const int totedge_guess = std::max(keep_existing_edges ? mesh->totedge : 0, mesh->totpoly * 2);
|
||||
const int totedge_guess = std::max(keep_existing_edges ? mesh->totedge : 0, mesh->faces_num * 2);
|
||||
threading::parallel_for_each(
|
||||
edge_maps, [&](EdgeMap &edge_map) { edge_map.reserve(totedge_guess / edge_maps.size()); });
|
||||
}
|
||||
@@ -65,18 +65,18 @@ static void add_existing_edges_to_hash_maps(Mesh *mesh,
|
||||
});
|
||||
}
|
||||
|
||||
static void add_polygon_edges_to_hash_maps(Mesh *mesh,
|
||||
MutableSpan<EdgeMap> edge_maps,
|
||||
uint32_t parallel_mask)
|
||||
static void add_face_edges_to_hash_maps(Mesh *mesh,
|
||||
MutableSpan<EdgeMap> edge_maps,
|
||||
uint32_t parallel_mask)
|
||||
{
|
||||
const OffsetIndices polys = mesh->polys();
|
||||
const OffsetIndices faces = mesh->faces();
|
||||
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 int i : polys.index_range()) {
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[i]);
|
||||
int vert_prev = poly_verts.last();
|
||||
for (const int vert : poly_verts) {
|
||||
for (const int i : faces.index_range()) {
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
int vert_prev = face_verts.last();
|
||||
for (const int vert : face_verts) {
|
||||
/* Can only be the same when the mesh data is invalid. */
|
||||
if (vert_prev != vert) {
|
||||
OrderedEdge ordered_edge{vert_prev, vert};
|
||||
@@ -125,17 +125,17 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
|
||||
});
|
||||
}
|
||||
|
||||
static void update_edge_indices_in_poly_loops(const OffsetIndices<int> polys,
|
||||
static void update_edge_indices_in_face_loops(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<EdgeMap> edge_maps,
|
||||
const uint32_t parallel_mask,
|
||||
MutableSpan<int> corner_edges)
|
||||
{
|
||||
threading::parallel_for(polys.index_range(), 100, [&](IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
int prev_corner = poly.last();
|
||||
for (const int next_corner : poly) {
|
||||
threading::parallel_for(faces.index_range(), 100, [&](IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const IndexRange face = faces[face_index];
|
||||
int prev_corner = face.last();
|
||||
for (const int next_corner : face) {
|
||||
const int vert = corner_verts[next_corner];
|
||||
const int vert_prev = corner_verts[prev_corner];
|
||||
|
||||
@@ -162,7 +162,7 @@ static void update_edge_indices_in_poly_loops(const OffsetIndices<int> polys,
|
||||
static int get_parallel_maps_count(const Mesh *mesh)
|
||||
{
|
||||
/* Don't use parallelization when the mesh is small. */
|
||||
if (mesh->totpoly < 1000) {
|
||||
if (mesh->faces_num < 1000) {
|
||||
return 1;
|
||||
}
|
||||
/* Use at most 8 separate hash tables. Using more threads has diminishing returns. These threads
|
||||
@@ -196,7 +196,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
|
||||
if (keep_existing_edges) {
|
||||
calc_edges::add_existing_edges_to_hash_maps(mesh, edge_maps, parallel_mask);
|
||||
}
|
||||
calc_edges::add_polygon_edges_to_hash_maps(mesh, edge_maps, parallel_mask);
|
||||
calc_edges::add_face_edges_to_hash_maps(mesh, edge_maps, parallel_mask);
|
||||
|
||||
/* Compute total number of edges. */
|
||||
int new_totedge = 0;
|
||||
@@ -210,7 +210,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
|
||||
MutableSpan<int2> new_edges{
|
||||
static_cast<int2 *>(MEM_calloc_arrayN(new_totedge, sizeof(int2), __func__)), new_totedge};
|
||||
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges);
|
||||
calc_edges::update_edge_indices_in_poly_loops(mesh->polys(),
|
||||
calc_edges::update_edge_indices_in_face_loops(mesh->faces(),
|
||||
mesh->corner_verts(),
|
||||
edge_maps,
|
||||
parallel_mask,
|
||||
|
||||
@@ -81,7 +81,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
/* count */
|
||||
int totvert = 0;
|
||||
int totedge = 0;
|
||||
int totpoly = 0;
|
||||
int faces_num = 0;
|
||||
int totloop = 0;
|
||||
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
|
||||
if (dl->type == DL_SEGM) {
|
||||
@@ -100,7 +100,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
totvert += dl->parts * dl->nr;
|
||||
tot = (((dl->flag & DL_CYCL_U) ? 1 : 0) + (dl->nr - 1)) *
|
||||
(((dl->flag & DL_CYCL_V) ? 1 : 0) + (dl->parts - 1));
|
||||
totpoly += tot;
|
||||
faces_num += tot;
|
||||
totloop += tot * 4;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
int tot;
|
||||
totvert += dl->nr;
|
||||
tot = dl->parts;
|
||||
totpoly += tot;
|
||||
faces_num += tot;
|
||||
totloop += tot * 3;
|
||||
}
|
||||
}
|
||||
@@ -117,10 +117,10 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
return BKE_mesh_new_nomain(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, totpoly, totloop);
|
||||
Mesh *mesh = BKE_mesh_new_nomain(totvert, totedge, faces_num, totloop);
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
MutableSpan<blender::int2> edges = mesh->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
||||
|
||||
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
@@ -201,7 +201,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
corner_verts[dst_loop + 0] = startvert + index[0];
|
||||
corner_verts[dst_loop + 1] = startvert + index[2];
|
||||
corner_verts[dst_loop + 2] = startvert + index[1];
|
||||
poly_offsets[dst_poly] = dst_loop;
|
||||
face_offsets[dst_poly] = dst_loop;
|
||||
material_indices.span[dst_poly] = dl->col;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@@ -256,7 +256,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
corner_verts[dst_loop + 1] = p3;
|
||||
corner_verts[dst_loop + 2] = p4;
|
||||
corner_verts[dst_loop + 3] = p2;
|
||||
poly_offsets[dst_poly] = dst_loop;
|
||||
face_offsets[dst_poly] = dst_loop;
|
||||
material_indices.span[dst_poly] = dl->col;
|
||||
|
||||
int orco_sizeu = dl->nr - 1;
|
||||
@@ -302,7 +302,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
||||
}
|
||||
}
|
||||
|
||||
if (totpoly) {
|
||||
if (faces_num) {
|
||||
BKE_mesh_calc_edges(mesh, true, false);
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
||||
{
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const Span<blender::int2> mesh_edges = me->edges();
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices polys = me->faces();
|
||||
const Span<int> corner_edges = me->corner_edges();
|
||||
|
||||
/* only to detect edge polylines */
|
||||
@@ -412,16 +412,16 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
||||
|
||||
ListBase polyline = {nullptr, nullptr}; /* store a list of VertLink's */
|
||||
bool closed = false;
|
||||
int totpoly = 0;
|
||||
int faces_num = 0;
|
||||
blender::int2 &edge_current = *(blender::int2 *)((EdgeLink *)edges.last)->edge;
|
||||
uint startVert = edge_current[0];
|
||||
uint endVert = edge_current[1];
|
||||
bool ok = true;
|
||||
|
||||
appendPolyLineVert(&polyline, startVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
appendPolyLineVert(&polyline, endVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
BLI_freelinkN(&edges, edges.last);
|
||||
|
||||
while (ok) { /* while connected edges are found... */
|
||||
@@ -435,28 +435,28 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
||||
if (edge[0] == endVert) {
|
||||
endVert = edge[1];
|
||||
appendPolyLineVert(&polyline, endVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
BLI_freelinkN(&edges, edl);
|
||||
ok = true;
|
||||
}
|
||||
else if (edge[1] == endVert) {
|
||||
endVert = edge[0];
|
||||
appendPolyLineVert(&polyline, endVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
BLI_freelinkN(&edges, edl);
|
||||
ok = true;
|
||||
}
|
||||
else if (edge[0] == startVert) {
|
||||
startVert = edge[1];
|
||||
prependPolyLineVert(&polyline, startVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
BLI_freelinkN(&edges, edl);
|
||||
ok = true;
|
||||
}
|
||||
else if (edge[1] == startVert) {
|
||||
startVert = edge[0];
|
||||
prependPolyLineVert(&polyline, startVert);
|
||||
totpoly++;
|
||||
faces_num++;
|
||||
BLI_freelinkN(&edges, edl);
|
||||
ok = true;
|
||||
}
|
||||
@@ -468,7 +468,7 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
||||
/* Now we have a polyline, make into a curve */
|
||||
if (startVert == endVert) {
|
||||
BLI_freelinkN(&polyline, polyline.last);
|
||||
totpoly--;
|
||||
faces_num--;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@@ -481,18 +481,18 @@ void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int ed
|
||||
/* create new 'nurb' within the curve */
|
||||
nu = MEM_new<Nurb>("MeshNurb", blender::dna::shallow_zero_initialize());
|
||||
|
||||
nu->pntsu = totpoly;
|
||||
nu->pntsu = faces_num;
|
||||
nu->pntsv = 1;
|
||||
nu->orderu = 4;
|
||||
nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */
|
||||
nu->resolu = 12;
|
||||
|
||||
nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints");
|
||||
nu->bp = (BPoint *)MEM_calloc_arrayN(faces_num, sizeof(BPoint), "bpoints");
|
||||
|
||||
/* add points */
|
||||
vl = (VertLink *)polyline.first;
|
||||
int i;
|
||||
for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) {
|
||||
for (i = 0, bp = nu->bp; i < faces_num; i++, bp++, vl = (VertLink *)vl->next) {
|
||||
copy_v3_v3(bp->vec, positions[vl->index]);
|
||||
bp->f1 = SELECT;
|
||||
bp->radius = bp->weight = 1.0;
|
||||
@@ -1027,18 +1027,18 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
|
||||
const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
|
||||
mesh_dst->totvert = mesh_src->totvert;
|
||||
mesh_dst->totedge = mesh_src->totedge;
|
||||
mesh_dst->totpoly = mesh_src->totpoly;
|
||||
mesh_dst->faces_num = mesh_src->faces_num;
|
||||
mesh_dst->totloop = mesh_src->totloop;
|
||||
|
||||
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
|
||||
const CustomData_MeshMasks mask = CD_MASK_MESH;
|
||||
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_src->totvert);
|
||||
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_src->totedge);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_src->totpoly);
|
||||
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_src->faces_num);
|
||||
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_src->totloop);
|
||||
std::swap(mesh_dst->poly_offset_indices, mesh_src->poly_offset_indices);
|
||||
std::swap(mesh_dst->runtime->poly_offsets_sharing_info,
|
||||
mesh_src->runtime->poly_offsets_sharing_info);
|
||||
std::swap(mesh_dst->face_offset_indices, mesh_src->face_offset_indices);
|
||||
std::swap(mesh_dst->runtime->face_offsets_sharing_info,
|
||||
mesh_src->runtime->face_offsets_sharing_info);
|
||||
|
||||
/* Make sure attribute names are moved. */
|
||||
std::swap(mesh_dst->active_color_attribute, mesh_src->active_color_attribute);
|
||||
|
||||
@@ -40,8 +40,8 @@ char *BKE_mesh_debug_info(const Mesh *me)
|
||||
BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)me);
|
||||
BLI_dynstr_appendf(dynstr, " 'totvert': %d,\n", me->totvert);
|
||||
BLI_dynstr_appendf(dynstr, " 'totedge': %d,\n", me->totedge);
|
||||
BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me->totface);
|
||||
BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me->totpoly);
|
||||
BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me->totface_legacy);
|
||||
BLI_dynstr_appendf(dynstr, " 'faces_num': %d,\n", me->faces_num);
|
||||
|
||||
BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime->deformed_only);
|
||||
BLI_dynstr_appendf(
|
||||
@@ -64,7 +64,7 @@ char *BKE_mesh_debug_info(const Mesh *me)
|
||||
BLI_dynstr_append(dynstr, " ),\n");
|
||||
|
||||
BLI_dynstr_append(dynstr, " 'tessface_layers': (\n");
|
||||
CustomData_debug_info_from_layers(&me->fdata, indent8, dynstr);
|
||||
CustomData_debug_info_from_layers(&me->fdata_legacy, indent8, dynstr);
|
||||
BLI_dynstr_append(dynstr, " ),\n");
|
||||
|
||||
BLI_dynstr_append(dynstr, "}\n");
|
||||
|
||||
@@ -41,51 +41,51 @@ using blender::VArray;
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
|
||||
static float3 poly_center_calc_ngon(const Span<float3> vert_positions, const Span<int> poly_verts)
|
||||
static float3 face_center_calc_ngon(const Span<float3> vert_positions, const Span<int> face_verts)
|
||||
{
|
||||
const float w = 1.0f / float(poly_verts.size());
|
||||
const float w = 1.0f / float(face_verts.size());
|
||||
|
||||
float3 center(0);
|
||||
for (const int i : poly_verts.index_range()) {
|
||||
center += vert_positions[poly_verts[i]] * w;
|
||||
for (const int i : face_verts.index_range()) {
|
||||
center += vert_positions[face_verts[i]] * w;
|
||||
}
|
||||
return center;
|
||||
}
|
||||
|
||||
float3 poly_center_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
|
||||
float3 face_center_calc(const Span<float3> vert_positions, const Span<int> face_verts)
|
||||
{
|
||||
if (poly_verts.size() == 3) {
|
||||
if (face_verts.size() == 3) {
|
||||
float3 center;
|
||||
mid_v3_v3v3v3(center,
|
||||
vert_positions[poly_verts[0]],
|
||||
vert_positions[poly_verts[1]],
|
||||
vert_positions[poly_verts[2]]);
|
||||
vert_positions[face_verts[0]],
|
||||
vert_positions[face_verts[1]],
|
||||
vert_positions[face_verts[2]]);
|
||||
return center;
|
||||
}
|
||||
if (poly_verts.size() == 4) {
|
||||
if (face_verts.size() == 4) {
|
||||
float3 center;
|
||||
mid_v3_v3v3v3v3(center,
|
||||
vert_positions[poly_verts[0]],
|
||||
vert_positions[poly_verts[1]],
|
||||
vert_positions[poly_verts[2]],
|
||||
vert_positions[poly_verts[3]]);
|
||||
vert_positions[face_verts[0]],
|
||||
vert_positions[face_verts[1]],
|
||||
vert_positions[face_verts[2]],
|
||||
vert_positions[face_verts[3]]);
|
||||
return center;
|
||||
}
|
||||
return poly_center_calc_ngon(vert_positions, poly_verts);
|
||||
return face_center_calc_ngon(vert_positions, face_verts);
|
||||
}
|
||||
|
||||
float poly_area_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
|
||||
float face_area_calc(const Span<float3> vert_positions, const Span<int> face_verts)
|
||||
{
|
||||
if (poly_verts.size() == 3) {
|
||||
return area_tri_v3(vert_positions[poly_verts[0]],
|
||||
vert_positions[poly_verts[1]],
|
||||
vert_positions[poly_verts[2]]);
|
||||
if (face_verts.size() == 3) {
|
||||
return area_tri_v3(vert_positions[face_verts[0]],
|
||||
vert_positions[face_verts[1]],
|
||||
vert_positions[face_verts[2]]);
|
||||
}
|
||||
Array<float3, 32> poly_coords(poly_verts.size());
|
||||
for (const int i : poly_verts.index_range()) {
|
||||
poly_coords[i] = vert_positions[poly_verts[i]];
|
||||
Array<float3, 32> coords(face_verts.size());
|
||||
for (const int i : face_verts.index_range()) {
|
||||
coords[i] = vert_positions[face_verts[i]];
|
||||
}
|
||||
return area_poly_v3((const float(*)[3])poly_coords.data(), poly_verts.size());
|
||||
return area_poly_v3((const float(*)[3])coords.data(), face_verts.size());
|
||||
}
|
||||
|
||||
} // namespace blender::bke::mesh
|
||||
@@ -93,18 +93,18 @@ float poly_area_calc(const Span<float3> vert_positions, const Span<int> poly_ver
|
||||
float BKE_mesh_calc_area(const Mesh *me)
|
||||
{
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
|
||||
float total_area = 0.0f;
|
||||
for (const int i : polys.index_range()) {
|
||||
total_area += blender::bke::mesh::poly_area_calc(positions, corner_verts.slice(polys[i]));
|
||||
for (const int i : faces.index_range()) {
|
||||
total_area += blender::bke::mesh::face_area_calc(positions, corner_verts.slice(faces[i]));
|
||||
}
|
||||
return total_area;
|
||||
}
|
||||
|
||||
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const int *poly_verts,
|
||||
const int poly_size,
|
||||
static float UNUSED_FUNCTION(mesh_calc_face_volume_centroid)(const int *face_verts,
|
||||
const int face_size,
|
||||
const float (*positions)[3],
|
||||
float r_cent[3])
|
||||
{
|
||||
@@ -113,11 +113,11 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const int *poly_ver
|
||||
|
||||
zero_v3(r_cent);
|
||||
|
||||
v_pivot = positions[poly_verts[0]];
|
||||
v_step1 = positions[poly_verts[1]];
|
||||
v_pivot = positions[face_verts[0]];
|
||||
v_step1 = positions[face_verts[1]];
|
||||
|
||||
for (int i = 2; i < poly_size; i++) {
|
||||
const float *v_step2 = positions[poly_verts[i]];
|
||||
for (int i = 2; i < face_size; i++) {
|
||||
const float *v_step2 = positions[face_verts[i]];
|
||||
|
||||
/* Calculate the 6x volume of the tetrahedron formed by the 3 vertices
|
||||
* of the triangle and the origin as the fourth vertex */
|
||||
@@ -143,24 +143,24 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const int *poly_ver
|
||||
namespace blender::bke::mesh {
|
||||
|
||||
/**
|
||||
* A version of mesh_calc_poly_volume_centroid that takes an initial reference center,
|
||||
* A version of mesh_calc_face_volume_centroid that takes an initial reference center,
|
||||
* use this to increase numeric stability as the quality of the result becomes
|
||||
* 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<int> poly_verts,
|
||||
static float mesh_calc_face_volume_centroid_with_reference_center(const Span<float3> positions,
|
||||
const Span<int> face_verts,
|
||||
const float3 &reference_center,
|
||||
float r_cent[3])
|
||||
{
|
||||
/* See: mesh_calc_poly_volume_centroid for comments. */
|
||||
/* See: mesh_calc_face_volume_centroid for comments. */
|
||||
float v_pivot[3], v_step1[3];
|
||||
float total_volume = 0.0f;
|
||||
zero_v3(r_cent);
|
||||
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++) {
|
||||
sub_v3_v3v3(v_pivot, positions[face_verts[0]], reference_center);
|
||||
sub_v3_v3v3(v_step1, positions[face_verts[1]], reference_center);
|
||||
for (int i = 2; i < face_verts.size(); i++) {
|
||||
float v_step2[3];
|
||||
sub_v3_v3v3(v_step2, positions[poly_verts[i]], reference_center);
|
||||
sub_v3_v3v3(v_step2, positions[face_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++) {
|
||||
@@ -173,26 +173,26 @@ static float mesh_calc_poly_volume_centroid_with_reference_center(const Span<flo
|
||||
|
||||
/**
|
||||
* \note
|
||||
* - Results won't be correct if polygon is non-planar.
|
||||
* - This has the advantage over #mesh_calc_poly_volume_centroid
|
||||
* - Results won't be correct if face is non-planar.
|
||||
* - This has the advantage over #mesh_calc_face_volume_centroid
|
||||
* 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<int> poly_verts,
|
||||
static float face_area_centroid_calc(const Span<float3> positions,
|
||||
const Span<int> face_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_verts);
|
||||
const float3 normal = blender::bke::mesh::face_normal_calc(positions, face_verts);
|
||||
|
||||
copy_v3_v3(v1, positions[poly_verts[0]]);
|
||||
copy_v3_v3(v2, positions[poly_verts[1]]);
|
||||
copy_v3_v3(v1, positions[face_verts[0]]);
|
||||
copy_v3_v3(v2, positions[face_verts[1]]);
|
||||
|
||||
zero_v3(r_cent);
|
||||
|
||||
for (int i = 2; i < poly_verts.size(); i++) {
|
||||
copy_v3_v3(v3, positions[poly_verts[i]]);
|
||||
for (int i = 2; i < face_verts.size(); i++) {
|
||||
copy_v3_v3(v3, positions[face_verts[i]]);
|
||||
|
||||
float tri_area = area_tri_signed_v3(v1, v2, v3, normal);
|
||||
total_area += tri_area;
|
||||
@@ -208,22 +208,22 @@ static float poly_area_centroid_calc(const Span<float3> positions,
|
||||
return total_area;
|
||||
}
|
||||
|
||||
void poly_angles_calc(const Span<float3> vert_positions,
|
||||
const Span<int> poly_verts,
|
||||
void face_angles_calc(const Span<float3> vert_positions,
|
||||
const Span<int> face_verts,
|
||||
MutableSpan<float> angles)
|
||||
{
|
||||
float nor_prev[3];
|
||||
float nor_next[3];
|
||||
|
||||
int i_this = poly_verts.size() - 1;
|
||||
int i_this = face_verts.size() - 1;
|
||||
int i_next = 0;
|
||||
|
||||
sub_v3_v3v3(
|
||||
nor_prev, vert_positions[poly_verts[i_this - 1]], vert_positions[poly_verts[i_this]]);
|
||||
nor_prev, vert_positions[face_verts[i_this - 1]], vert_positions[face_verts[i_this]]);
|
||||
normalize_v3(nor_prev);
|
||||
|
||||
while (i_next < poly_verts.size()) {
|
||||
sub_v3_v3v3(nor_next, vert_positions[poly_verts[i_this]], vert_positions[poly_verts[i_next]]);
|
||||
while (i_next < face_verts.size()) {
|
||||
sub_v3_v3v3(nor_next, vert_positions[face_verts[i_this]], vert_positions[face_verts[i_next]]);
|
||||
normalize_v3(nor_next);
|
||||
angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next);
|
||||
|
||||
@@ -256,47 +256,47 @@ bool BKE_mesh_center_median(const Mesh *me, float r_cent[3])
|
||||
return (me->totvert != 0);
|
||||
}
|
||||
|
||||
bool BKE_mesh_center_median_from_polys(const Mesh *me, float r_cent[3])
|
||||
bool BKE_mesh_center_median_from_faces(const Mesh *me, float r_cent[3])
|
||||
{
|
||||
int tot = 0;
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
zero_v3(r_cent);
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int vert : corner_verts.slice(polys[i])) {
|
||||
for (const int i : faces.index_range()) {
|
||||
for (const int vert : corner_verts.slice(faces[i])) {
|
||||
add_v3_v3(r_cent, positions[vert]);
|
||||
}
|
||||
tot += polys[i].size();
|
||||
tot += faces[i].size();
|
||||
}
|
||||
/* otherwise we get NAN for 0 verts */
|
||||
if (me->totpoly) {
|
||||
if (me->faces_num) {
|
||||
mul_v3_fl(r_cent, 1.0f / float(tot));
|
||||
}
|
||||
return (me->totpoly != 0);
|
||||
return (me->faces_num != 0);
|
||||
}
|
||||
|
||||
bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
|
||||
{
|
||||
float poly_area;
|
||||
float face_area;
|
||||
float total_area = 0.0f;
|
||||
float poly_cent[3];
|
||||
float face_cent[3];
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
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, corner_verts.slice(polys[i]), poly_cent);
|
||||
/* calculate a weighted average of face centroids */
|
||||
for (const int i : faces.index_range()) {
|
||||
face_area = blender::bke::mesh::face_area_centroid_calc(
|
||||
positions, corner_verts.slice(faces[i]), face_cent);
|
||||
|
||||
madd_v3_v3fl(r_cent, poly_cent, poly_area);
|
||||
total_area += poly_area;
|
||||
madd_v3_v3fl(r_cent, face_cent, face_area);
|
||||
total_area += face_area;
|
||||
}
|
||||
/* otherwise we get NAN for 0 polys */
|
||||
if (me->totpoly) {
|
||||
/* otherwise we get NAN for 0 faces */
|
||||
if (me->faces_num) {
|
||||
mul_v3_fl(r_cent, 1.0f / total_area);
|
||||
}
|
||||
|
||||
@@ -305,34 +305,34 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
|
||||
return BKE_mesh_center_median(me, r_cent);
|
||||
}
|
||||
|
||||
return (me->totpoly != 0);
|
||||
return (me->faces_num != 0);
|
||||
}
|
||||
|
||||
bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
|
||||
{
|
||||
float poly_volume;
|
||||
float face_volume;
|
||||
float total_volume = 0.0f;
|
||||
float poly_cent[3];
|
||||
float face_cent[3];
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
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];
|
||||
const bool init_cent_result = BKE_mesh_center_median_from_polys(me, init_cent);
|
||||
const bool init_cent_result = BKE_mesh_center_median_from_faces(me, init_cent);
|
||||
|
||||
zero_v3(r_cent);
|
||||
|
||||
/* 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, corner_verts.slice(polys[i]), init_cent, poly_cent);
|
||||
for (const int i : faces.index_range()) {
|
||||
face_volume = blender::bke::mesh::mesh_calc_face_volume_centroid_with_reference_center(
|
||||
positions, corner_verts.slice(faces[i]), init_cent, face_cent);
|
||||
|
||||
/* poly_cent is already volume-weighted, so no need to multiply by the volume */
|
||||
add_v3_v3(r_cent, poly_cent);
|
||||
total_volume += poly_volume;
|
||||
/* face_cent is already volume-weighted, so no need to multiply by the volume */
|
||||
add_v3_v3(r_cent, face_cent);
|
||||
total_volume += face_volume;
|
||||
}
|
||||
/* otherwise we get NAN for 0 polys */
|
||||
/* otherwise we get NAN for 0 faces */
|
||||
if (total_volume != 0.0f) {
|
||||
/* multiply by 0.25 to get the correct centroid */
|
||||
/* no need to divide volume by 6 as the centroid is weighted by 6x the volume,
|
||||
@@ -346,7 +346,7 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
|
||||
return init_cent_result;
|
||||
}
|
||||
add_v3_v3(r_cent, init_cent);
|
||||
return (me->totpoly != 0);
|
||||
return (me->faces_num != 0);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -498,17 +498,17 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_polygon_flip_ex(const int poly_offset,
|
||||
const int poly_size,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
CustomData *ldata,
|
||||
float (*lnors)[3],
|
||||
MDisps *mdisp,
|
||||
const bool use_loop_mdisp_flip)
|
||||
void BKE_mesh_face_flip_ex(const int face_offset,
|
||||
const int face_size,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
CustomData *ldata,
|
||||
float (*lnors)[3],
|
||||
MDisps *mdisp,
|
||||
const bool use_loop_mdisp_flip)
|
||||
{
|
||||
int loopstart = poly_offset;
|
||||
int loopend = loopstart + poly_size - 1;
|
||||
int loopstart = face_offset;
|
||||
int loopend = loopstart + face_size - 1;
|
||||
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(
|
||||
@@ -549,32 +549,35 @@ void BKE_mesh_polygon_flip_ex(const int poly_offset,
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_polygon_flip(const int poly_offset,
|
||||
const int poly_size,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
CustomData *ldata,
|
||||
const int totloop)
|
||||
void BKE_mesh_face_flip(const int face_offset,
|
||||
const int face_size,
|
||||
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_offset, poly_size, corner_verts, corner_edges, ldata, nullptr, mdisp, true);
|
||||
BKE_mesh_face_flip_ex(
|
||||
face_offset, face_size, corner_verts, corner_edges, ldata, nullptr, mdisp, true);
|
||||
}
|
||||
|
||||
void BKE_mesh_polys_flip(
|
||||
const int *poly_offsets, int *corner_verts, int *corner_edges, CustomData *ldata, int totpoly)
|
||||
void BKE_mesh_faces_flip(const int *face_offsets,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
CustomData *ldata,
|
||||
int faces_num)
|
||||
{
|
||||
const blender::OffsetIndices polys(blender::Span(poly_offsets, totpoly + 1));
|
||||
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, totpoly);
|
||||
for (const int i : polys.index_range()) {
|
||||
BKE_mesh_polygon_flip_ex(polys[i].start(),
|
||||
polys[i].size(),
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
ldata,
|
||||
nullptr,
|
||||
mdisp,
|
||||
true);
|
||||
const blender::OffsetIndices faces(blender::Span(face_offsets, faces_num + 1));
|
||||
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(ldata, CD_MDISPS, faces_num);
|
||||
for (const int i : faces.index_range()) {
|
||||
BKE_mesh_face_flip_ex(faces[i].start(),
|
||||
faces[i].size(),
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
ldata,
|
||||
nullptr,
|
||||
mdisp,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +600,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
|
||||
}
|
||||
const VArraySpan<bool> hide_vert_span{hide_vert};
|
||||
const Span<int2> edges = me->edges();
|
||||
const OffsetIndices polys = me->polys();
|
||||
const OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
|
||||
/* Hide edges when either of their vertices are hidden. */
|
||||
@@ -609,19 +612,19 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
|
||||
}
|
||||
hide_edge.finish();
|
||||
|
||||
/* Hide polygons when any of their vertices are hidden. */
|
||||
/* Hide faces when any of their vertices are hidden. */
|
||||
SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
".hide_poly", ATTR_DOMAIN_FACE);
|
||||
for (const int i : polys.index_range()) {
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[i]);
|
||||
hide_poly.span[i] = std::any_of(poly_verts.begin(), poly_verts.end(), [&](const int vert) {
|
||||
for (const int i : faces.index_range()) {
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
hide_poly.span[i] = std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
|
||||
return hide_vert_span[vert];
|
||||
});
|
||||
}
|
||||
hide_poly.finish();
|
||||
}
|
||||
|
||||
void BKE_mesh_flush_hidden_from_polys(Mesh *me)
|
||||
void BKE_mesh_flush_hidden_from_faces(Mesh *me)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
@@ -635,7 +638,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
|
||||
return;
|
||||
}
|
||||
const VArraySpan<bool> hide_poly_span{hide_poly};
|
||||
const OffsetIndices polys = me->polys();
|
||||
const OffsetIndices faces = me->faces();
|
||||
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>(
|
||||
@@ -644,18 +647,18 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
|
||||
".hide_edge", ATTR_DOMAIN_EDGE);
|
||||
|
||||
/* Hide all edges or vertices connected to hidden polygons. */
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int i : faces.index_range()) {
|
||||
if (hide_poly_span[i]) {
|
||||
for (const int corner : polys[i]) {
|
||||
for (const int corner : faces[i]) {
|
||||
hide_vert.span[corner_verts[corner]] = true;
|
||||
hide_edge.span[corner_edges[corner]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Unhide vertices and edges connected to visible polygons. */
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int i : faces.index_range()) {
|
||||
if (!hide_poly_span[i]) {
|
||||
for (const int corner : polys[i]) {
|
||||
for (const int corner : faces[i]) {
|
||||
hide_vert.span[corner_verts[corner]] = false;
|
||||
hide_edge.span[corner_edges[corner]] = false;
|
||||
}
|
||||
@@ -666,7 +669,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
|
||||
hide_edge.finish();
|
||||
}
|
||||
|
||||
void BKE_mesh_flush_select_from_polys(Mesh *me)
|
||||
void BKE_mesh_flush_select_from_faces(Mesh *me)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
@@ -682,7 +685,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
|
||||
SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
".select_edge", ATTR_DOMAIN_EDGE);
|
||||
|
||||
/* Use generic domain interpolation to read the polygon attribute on the other domains.
|
||||
/* Use generic domain interpolation to read the face attribute on the other domains.
|
||||
* Assume selected faces are not hidden and none of their vertices/edges are hidden. */
|
||||
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false)
|
||||
.varray.materialize(select_vert.span);
|
||||
@@ -694,7 +697,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
|
||||
}
|
||||
|
||||
static void mesh_flush_select_from_verts(const Span<blender::int2> edges,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const VArray<bool> &hide_edge,
|
||||
const VArray<bool> &hide_poly,
|
||||
@@ -711,11 +714,11 @@ static void mesh_flush_select_from_verts(const Span<blender::int2> edges,
|
||||
}
|
||||
|
||||
/* Select visible faces that have all of their vertices selected. */
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int i : faces.index_range()) {
|
||||
if (!hide_poly[i]) {
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[i]);
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
select_poly[i] = std::all_of(
|
||||
poly_verts.begin(), poly_verts.end(), [&](const int vert) { return select_vert[vert]; });
|
||||
face_verts.begin(), face_verts.end(), [&](const int vert) { return select_vert[vert]; });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -737,7 +740,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
|
||||
".select_poly", ATTR_DOMAIN_FACE);
|
||||
mesh_flush_select_from_verts(
|
||||
me->edges(),
|
||||
me->polys(),
|
||||
me->faces(),
|
||||
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),
|
||||
@@ -754,8 +757,8 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
|
||||
/** \name Mesh Spatial Calculation
|
||||
* \{ */
|
||||
|
||||
void BKE_mesh_calc_relative_deform(const int *poly_offsets,
|
||||
const int totpoly,
|
||||
void BKE_mesh_calc_relative_deform(const int *face_offsets,
|
||||
const int faces_num,
|
||||
const int *corner_verts,
|
||||
const int totvert,
|
||||
|
||||
@@ -765,20 +768,20 @@ void BKE_mesh_calc_relative_deform(const int *poly_offsets,
|
||||
const float (*vert_cos_org)[3],
|
||||
float (*vert_cos_new)[3])
|
||||
{
|
||||
const blender::OffsetIndices<int> polys({poly_offsets, totpoly + 1});
|
||||
const blender::OffsetIndices<int> faces({face_offsets, faces_num + 1});
|
||||
|
||||
int *vert_accum = (int *)MEM_calloc_arrayN(size_t(totvert), sizeof(*vert_accum), __func__);
|
||||
|
||||
memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * size_t(totvert));
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
const int *poly_verts = &corner_verts[poly.start()];
|
||||
for (const int i : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
const int *face_verts = &corner_verts[face.start()];
|
||||
|
||||
for (int j = 0; j < poly.size(); j++) {
|
||||
const int v_prev = poly_verts[(poly.size() + (j - 1)) % poly.size()];
|
||||
const int v_curr = poly_verts[j];
|
||||
const int v_next = poly_verts[(j + 1) % poly.size()];
|
||||
for (int j = 0; j < face.size(); j++) {
|
||||
const int v_prev = face_verts[(face.size() + (j - 1)) % face.size()];
|
||||
const int v_curr = face_verts[j];
|
||||
const int v_next = face_verts[(j + 1) % face.size()];
|
||||
|
||||
float tvec[3];
|
||||
|
||||
|
||||
@@ -200,11 +200,11 @@ class MeshFairingContext : public FairingContext {
|
||||
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
edges_ = mesh->edges();
|
||||
polys = mesh->polys();
|
||||
faces = mesh->faces();
|
||||
corner_verts_ = mesh->corner_verts();
|
||||
corner_edges_ = mesh->corner_edges();
|
||||
vlmap_ = blender::bke::mesh::build_vert_to_loop_map(
|
||||
corner_verts_, positions.size(), vert_to_poly_offsets_, vert_to_poly_indices_);
|
||||
corner_verts_, positions.size(), vert_to_face_offsets_, vert_to_face_indices_);
|
||||
|
||||
/* Deformation coords. */
|
||||
co_.reserve(mesh->totvert);
|
||||
@@ -219,7 +219,7 @@ class MeshFairingContext : public FairingContext {
|
||||
}
|
||||
}
|
||||
|
||||
loop_to_poly_map_ = blender::bke::mesh::build_loop_to_poly_map(polys);
|
||||
loop_to_face_map_ = blender::bke::mesh::build_loop_to_face_map(faces);
|
||||
}
|
||||
|
||||
void adjacents_coords_from_loop(const int loop,
|
||||
@@ -228,8 +228,8 @@ class MeshFairingContext : public FairingContext {
|
||||
{
|
||||
using namespace blender;
|
||||
const int vert = corner_verts_[loop];
|
||||
const blender::IndexRange poly = polys[loop_to_poly_map_[loop]];
|
||||
const int2 adjecent_verts = bke::mesh::poly_find_adjecent_verts(poly, corner_verts_, vert);
|
||||
const blender::IndexRange face = faces[loop_to_face_map_[loop]];
|
||||
const int2 adjecent_verts = bke::mesh::face_find_adjecent_verts(face, corner_verts_, vert);
|
||||
copy_v3_v3(r_adj_next, co_[adjecent_verts[0]]);
|
||||
copy_v3_v3(r_adj_prev, co_[adjecent_verts[1]]);
|
||||
}
|
||||
@@ -244,11 +244,11 @@ class MeshFairingContext : public FairingContext {
|
||||
Mesh *mesh_;
|
||||
Span<int> corner_verts_;
|
||||
Span<int> corner_edges_;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
Span<blender::int2> edges_;
|
||||
Array<int> loop_to_poly_map_;
|
||||
Array<int> vert_to_poly_offsets_;
|
||||
Array<int> vert_to_poly_indices_;
|
||||
Array<int> loop_to_face_map_;
|
||||
Array<int> vert_to_face_offsets_;
|
||||
Array<int> vert_to_face_indices_;
|
||||
};
|
||||
|
||||
class BMeshFairingContext : public FairingContext {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
/* General note on iterating verts/loops/edges/polys and end mode.
|
||||
/* General note on iterating verts/loops/edges/faces and end mode.
|
||||
*
|
||||
* The edit mesh pointer is set for both final and cage meshes in both cases when there are
|
||||
* modifiers applied and not. This helps consistency of checks in the draw manager, where the
|
||||
@@ -198,7 +198,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
||||
}
|
||||
|
||||
const blender::Span<blender::float3> positions = mesh->vert_positions();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
const int *v_index = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX));
|
||||
@@ -206,11 +206,11 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
||||
CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
|
||||
|
||||
if (v_index || f_index) {
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
for (const int corner : polys[poly_i]) {
|
||||
for (const int face_i : faces.index_range()) {
|
||||
for (const int corner : faces[face_i]) {
|
||||
const int vert = corner_verts[corner];
|
||||
const int v_idx = v_index ? v_index[vert] : vert;
|
||||
const int f_idx = f_index ? f_index[poly_i] : poly_i;
|
||||
const int f_idx = f_index ? f_index[face_i] : face_i;
|
||||
const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x;
|
||||
if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
|
||||
continue;
|
||||
@@ -220,11 +220,11 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
for (const int corner : polys[poly_i]) {
|
||||
for (const int face_i : faces.index_range()) {
|
||||
for (const int corner : faces[face_i]) {
|
||||
const int vert = corner_verts[corner];
|
||||
const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x;
|
||||
func(userData, vert, poly_i, positions[vert], no);
|
||||
func(userData, vert, face_i, positions[vert], no);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,49 +241,49 @@ void BKE_mesh_foreach_mapped_face_center(
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
BMesh *bm = em->bm;
|
||||
blender::Span<blender::float3> poly_centers;
|
||||
blender::Span<blender::float3> poly_normals;
|
||||
blender::Span<blender::float3> face_centers;
|
||||
blender::Span<blender::float3> face_normals;
|
||||
BMFace *efa;
|
||||
BMIter iter;
|
||||
int i;
|
||||
|
||||
BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime->edit_data);
|
||||
poly_centers = mesh->runtime->edit_data->polyCos; /* always set */
|
||||
BKE_editmesh_cache_ensure_face_centers(em, mesh->runtime->edit_data);
|
||||
face_centers = mesh->runtime->edit_data->faceCos; /* always set */
|
||||
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime->edit_data);
|
||||
poly_normals = mesh->runtime->edit_data->polyNos; /* maybe nullptr */
|
||||
BKE_editmesh_cache_ensure_face_normals(em, mesh->runtime->edit_data);
|
||||
face_normals = mesh->runtime->edit_data->faceNos; /* maybe nullptr */
|
||||
}
|
||||
|
||||
if (!poly_normals.is_empty()) {
|
||||
if (!face_normals.is_empty()) {
|
||||
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
|
||||
const float *no = poly_normals[i];
|
||||
func(userData, i, poly_centers[i], no);
|
||||
const float *no = face_normals[i];
|
||||
func(userData, i, face_centers[i], no);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : nullptr;
|
||||
func(userData, i, poly_centers[i], no);
|
||||
func(userData, i, face_centers[i], no);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const blender::Span<float3> positions = mesh->vert_positions();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
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) {
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int i : faces.index_range()) {
|
||||
const int orig = *index++;
|
||||
if (orig == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[i]);
|
||||
const float3 center = bke::mesh::poly_center_calc(positions, poly_verts);
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
const float3 center = bke::mesh::face_center_calc(positions, face_verts);
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts);
|
||||
const float3 normal = bke::mesh::face_normal_calc(positions, face_verts);
|
||||
func(userData, orig, center, normal);
|
||||
}
|
||||
else {
|
||||
@@ -292,11 +292,11 @@ void BKE_mesh_foreach_mapped_face_center(
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : polys.index_range()) {
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[i]);
|
||||
const float3 center = bke::mesh::poly_center_calc(positions, poly_verts);
|
||||
for (const int i : faces.index_range()) {
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
const float3 center = bke::mesh::face_center_calc(positions, face_verts);
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
const float3 normal = bke::mesh::poly_normal_calc(positions, poly_verts);
|
||||
const float3 normal = bke::mesh::face_normal_calc(positions, face_verts);
|
||||
func(userData, i, center, normal);
|
||||
}
|
||||
else {
|
||||
@@ -314,7 +314,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
MeshForeachFlag flag)
|
||||
{
|
||||
const blender::Span<blender::float3> positions = mesh->vert_positions();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
@@ -324,12 +324,12 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
const blender::BitSpan facedot_tags = mesh->runtime->subsurf_face_dot_tags;
|
||||
|
||||
if (index) {
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int i : faces.index_range()) {
|
||||
const int orig = *index++;
|
||||
if (orig == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
for (const int vert : corner_verts.slice(polys[i])) {
|
||||
for (const int vert : corner_verts.slice(faces[i])) {
|
||||
if (facedot_tags[vert]) {
|
||||
func(userData,
|
||||
orig,
|
||||
@@ -340,8 +340,8 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int vert : corner_verts.slice(polys[i])) {
|
||||
for (const int i : faces.index_range()) {
|
||||
for (const int vert : corner_verts.slice(faces[i])) {
|
||||
if (facedot_tags[vert]) {
|
||||
func(userData,
|
||||
i,
|
||||
|
||||
@@ -89,7 +89,7 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
||||
int /*totvert*/,
|
||||
int totface,
|
||||
int /*totloop*/,
|
||||
int totpoly,
|
||||
int faces_num,
|
||||
MEdge **r_medge,
|
||||
int *r_totedge)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
||||
}
|
||||
|
||||
mpoly = allpoly;
|
||||
for (a = 0; a < totpoly; a++, mpoly++) {
|
||||
for (a = 0; a < faces_num; a++, mpoly++) {
|
||||
MLoop *ml, *ml_next;
|
||||
int i = mpoly->totloop;
|
||||
|
||||
@@ -216,9 +216,9 @@ void BKE_mesh_calc_edges_legacy(Mesh *me)
|
||||
static_cast<MLoop *>(CustomData_get_layer_for_write(&me->ldata, CD_MLOOP, me->totloop)),
|
||||
static_cast<const MPoly *>(CustomData_get_layer(&me->pdata, CD_MPOLY)),
|
||||
verts.size(),
|
||||
me->totface,
|
||||
me->totface_legacy,
|
||||
me->totloop,
|
||||
me->totpoly,
|
||||
me->faces_num,
|
||||
&edges,
|
||||
&totedge);
|
||||
|
||||
@@ -242,18 +242,18 @@ void BKE_mesh_strip_loose_faces(Mesh *me)
|
||||
int a, b;
|
||||
MFace *mfaces = me->mface;
|
||||
|
||||
for (a = b = 0, f = mfaces; a < me->totface; a++, f++) {
|
||||
for (a = b = 0, f = mfaces; a < me->totface_legacy; a++, f++) {
|
||||
if (f->v3) {
|
||||
if (a != b) {
|
||||
memcpy(&mfaces[b], f, sizeof(mfaces[b]));
|
||||
CustomData_copy_data(&me->fdata, &me->fdata, a, b, 1);
|
||||
CustomData_copy_data(&me->fdata_legacy, &me->fdata_legacy, a, b, 1);
|
||||
}
|
||||
b++;
|
||||
}
|
||||
}
|
||||
if (a != b) {
|
||||
CustomData_free_elem(&me->fdata, b, a - b);
|
||||
me->totface = b;
|
||||
CustomData_free_elem(&me->fdata_legacy, b, a - b);
|
||||
me->totface_legacy = b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
|
||||
(void)0
|
||||
|
||||
static void bm_corners_to_loops_ex(ID *id,
|
||||
CustomData *fdata,
|
||||
CustomData *fdata_legacy,
|
||||
const int totface,
|
||||
CustomData *ldata,
|
||||
MFace *mface,
|
||||
@@ -330,7 +330,7 @@ static void bm_corners_to_loops_ex(ID *id,
|
||||
|
||||
for (int i = 0; i < numTex; i++) {
|
||||
const MTFace *texface = (const MTFace *)CustomData_get_n_for_write(
|
||||
fdata, CD_MTFACE, findex, i, totface);
|
||||
fdata_legacy, CD_MTFACE, findex, i, totface);
|
||||
|
||||
blender::float2 *uv = static_cast<blender::float2 *>(
|
||||
CustomData_get_n_for_write(ldata, CD_PROP_FLOAT2, loopstart, i, totloop));
|
||||
@@ -351,7 +351,7 @@ static void bm_corners_to_loops_ex(ID *id,
|
||||
MLoopCol *mloopcol = (MLoopCol *)CustomData_get_n_for_write(
|
||||
ldata, CD_PROP_BYTE_COLOR, loopstart, i, totloop);
|
||||
const MCol *mcol = (const MCol *)CustomData_get_n_for_write(
|
||||
fdata, CD_MCOL, findex, i, totface);
|
||||
fdata_legacy, CD_MCOL, findex, i, totface);
|
||||
|
||||
MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]);
|
||||
mloopcol++;
|
||||
@@ -365,11 +365,11 @@ static void bm_corners_to_loops_ex(ID *id,
|
||||
}
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_TESSLOOPNORMAL)) {
|
||||
if (CustomData_has_layer(fdata_legacy, CD_TESSLOOPNORMAL)) {
|
||||
float(*loop_normals)[3] = (float(*)[3])CustomData_get_for_write(
|
||||
ldata, loopstart, CD_NORMAL, totloop);
|
||||
const short(*tessloop_normals)[3] = (short(*)[3])CustomData_get_for_write(
|
||||
fdata, findex, CD_TESSLOOPNORMAL, totface);
|
||||
fdata_legacy, findex, CD_TESSLOOPNORMAL, totface);
|
||||
const int max = mf->v4 ? 4 : 3;
|
||||
|
||||
for (int i = 0; i < max; i++, loop_normals++, tessloop_normals++) {
|
||||
@@ -377,16 +377,17 @@ static void bm_corners_to_loops_ex(ID *id,
|
||||
}
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_MDISPS)) {
|
||||
if (CustomData_has_layer(fdata_legacy, CD_MDISPS)) {
|
||||
MDisps *ld = (MDisps *)CustomData_get_for_write(ldata, loopstart, CD_MDISPS, totloop);
|
||||
const MDisps *fd = (const MDisps *)CustomData_get_for_write(fdata, findex, CD_MDISPS, totface);
|
||||
const MDisps *fd = (const MDisps *)CustomData_get_for_write(
|
||||
fdata_legacy, findex, CD_MDISPS, totface);
|
||||
const float(*disps)[3] = fd->disps;
|
||||
int tot = mf->v4 ? 4 : 3;
|
||||
int corners;
|
||||
|
||||
if (CustomData_external_test(fdata, CD_MDISPS)) {
|
||||
if (id && fdata->external) {
|
||||
CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filepath);
|
||||
if (CustomData_external_test(fdata_legacy, CD_MDISPS)) {
|
||||
if (id && fdata_legacy->external) {
|
||||
CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata_legacy->external->filepath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,67 +424,69 @@ static void bm_corners_to_loops_ex(ID *id,
|
||||
}
|
||||
}
|
||||
|
||||
static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
|
||||
static void CustomData_to_bmeshpoly(CustomData *fdata_legacy, CustomData *ldata, int totloop)
|
||||
{
|
||||
for (int i = 0; i < fdata->totlayer; i++) {
|
||||
if (fdata->layers[i].type == CD_MTFACE) {
|
||||
for (int i = 0; i < fdata_legacy->totlayer; i++) {
|
||||
if (fdata_legacy->layers[i].type == CD_MTFACE) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, totloop, fdata_legacy->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_MCOL) {
|
||||
else if (fdata_legacy->layers[i].type == CD_MCOL) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, totloop, fdata_legacy->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_MDISPS) {
|
||||
CustomData_add_layer_named(ldata, CD_MDISPS, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
else if (fdata_legacy->layers[i].type == CD_MDISPS) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_MDISPS, CD_SET_DEFAULT, totloop, fdata_legacy->layers[i].name);
|
||||
}
|
||||
else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
|
||||
CustomData_add_layer_named(ldata, CD_NORMAL, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
|
||||
else if (fdata_legacy->layers[i].type == CD_TESSLOOPNORMAL) {
|
||||
CustomData_add_layer_named(
|
||||
ldata, CD_NORMAL, CD_SET_DEFAULT, totloop, fdata_legacy->layers[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_mfaces_to_mpolys(ID *id,
|
||||
CustomData *fdata,
|
||||
CustomData *fdata_legacy,
|
||||
CustomData *ldata,
|
||||
CustomData *pdata,
|
||||
int totedge_i,
|
||||
int totface_i,
|
||||
int totloop_i,
|
||||
int totpoly_i,
|
||||
int faces_num_i,
|
||||
blender::int2 *edges,
|
||||
MFace *mface,
|
||||
int *r_totloop,
|
||||
int *r_totpoly)
|
||||
int *r_faces_num)
|
||||
{
|
||||
MFace *mf;
|
||||
MLoop *ml, *mloop;
|
||||
MPoly *poly, *mpoly;
|
||||
EdgeHash *eh;
|
||||
int numTex, numCol;
|
||||
int i, j, totloop, totpoly, *polyindex;
|
||||
int i, j, totloop, faces_num, *polyindex;
|
||||
|
||||
/* just in case some of these layers are filled in (can happen with python created meshes) */
|
||||
CustomData_free(ldata, totloop_i);
|
||||
CustomData_free(pdata, totpoly_i);
|
||||
CustomData_free(pdata, faces_num_i);
|
||||
|
||||
totpoly = totface_i;
|
||||
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly);
|
||||
faces_num = totface_i;
|
||||
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, faces_num);
|
||||
int *material_indices = static_cast<int *>(
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_INT32, "material_index", totpoly));
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_INT32, "material_index", faces_num));
|
||||
if (material_indices == nullptr) {
|
||||
material_indices = static_cast<int *>(CustomData_add_layer_named(
|
||||
pdata, CD_PROP_INT32, CD_SET_DEFAULT, totpoly, "material_index"));
|
||||
pdata, CD_PROP_INT32, CD_SET_DEFAULT, faces_num, "material_index"));
|
||||
}
|
||||
bool *sharp_faces = static_cast<bool *>(
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_BOOL, "sharp_face", totpoly));
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_BOOL, "sharp_face", faces_num));
|
||||
if (!sharp_faces) {
|
||||
sharp_faces = static_cast<bool *>(
|
||||
CustomData_add_layer_named(pdata, CD_PROP_BOOL, CD_SET_DEFAULT, totpoly, "sharp_face"));
|
||||
CustomData_add_layer_named(pdata, CD_PROP_BOOL, CD_SET_DEFAULT, faces_num, "sharp_face"));
|
||||
}
|
||||
|
||||
numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
|
||||
numCol = CustomData_number_of_layers(fdata, CD_MCOL);
|
||||
numTex = CustomData_number_of_layers(fdata_legacy, CD_MTFACE);
|
||||
numCol = CustomData_number_of_layers(fdata_legacy, CD_MCOL);
|
||||
|
||||
totloop = 0;
|
||||
mf = mface;
|
||||
@@ -493,12 +496,12 @@ static void convert_mfaces_to_mpolys(ID *id,
|
||||
|
||||
mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, totloop);
|
||||
|
||||
CustomData_to_bmeshpoly(fdata, ldata, totloop);
|
||||
CustomData_to_bmeshpoly(fdata_legacy, ldata, totloop);
|
||||
|
||||
if (id) {
|
||||
/* ensure external data is transferred */
|
||||
/* TODO(sergey): Use multiresModifier_ensure_external_read(). */
|
||||
CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
|
||||
CustomData_external_read(fdata_legacy, id, CD_MASK_MDISPS, totface_i);
|
||||
}
|
||||
|
||||
eh = BLI_edgehash_new_ex(__func__, uint(totedge_i));
|
||||
@@ -508,7 +511,7 @@ static void convert_mfaces_to_mpolys(ID *id,
|
||||
BLI_edgehash_insert(eh, edges[i][0], edges[i][1], POINTER_FROM_UINT(i));
|
||||
}
|
||||
|
||||
polyindex = (int *)CustomData_get_layer(fdata, CD_ORIGINDEX);
|
||||
polyindex = (int *)CustomData_get_layer(fdata_legacy, CD_ORIGINDEX);
|
||||
|
||||
j = 0; /* current loop index */
|
||||
ml = mloop;
|
||||
@@ -544,7 +547,7 @@ static void convert_mfaces_to_mpolys(ID *id,
|
||||
#undef ML
|
||||
|
||||
bm_corners_to_loops_ex(
|
||||
id, fdata, totface_i, ldata, mface, totloop, i, poly->loopstart, numTex, numCol);
|
||||
id, fdata_legacy, totface_i, ldata, mface, totloop, i, poly->loopstart, numTex, numCol);
|
||||
|
||||
if (polyindex) {
|
||||
*polyindex = i;
|
||||
@@ -557,44 +560,44 @@ static void convert_mfaces_to_mpolys(ID *id,
|
||||
|
||||
BLI_edgehash_free(eh, nullptr);
|
||||
|
||||
*r_totpoly = totpoly;
|
||||
*r_faces_num = faces_num;
|
||||
*r_totloop = totloop;
|
||||
}
|
||||
|
||||
static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata)
|
||||
static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata_legacy, CustomData *ldata)
|
||||
{
|
||||
int act;
|
||||
|
||||
if (CustomData_has_layer(ldata, CD_PROP_FLOAT2)) {
|
||||
act = CustomData_get_active_layer(ldata, CD_PROP_FLOAT2);
|
||||
CustomData_set_layer_active(fdata, CD_MTFACE, act);
|
||||
CustomData_set_layer_active(fdata_legacy, CD_MTFACE, act);
|
||||
|
||||
act = CustomData_get_render_layer(ldata, CD_PROP_FLOAT2);
|
||||
CustomData_set_layer_render(fdata, CD_MTFACE, act);
|
||||
CustomData_set_layer_render(fdata_legacy, CD_MTFACE, act);
|
||||
|
||||
act = CustomData_get_clone_layer(ldata, CD_PROP_FLOAT2);
|
||||
CustomData_set_layer_clone(fdata, CD_MTFACE, act);
|
||||
CustomData_set_layer_clone(fdata_legacy, CD_MTFACE, act);
|
||||
|
||||
act = CustomData_get_stencil_layer(ldata, CD_PROP_FLOAT2);
|
||||
CustomData_set_layer_stencil(fdata, CD_MTFACE, act);
|
||||
CustomData_set_layer_stencil(fdata_legacy, CD_MTFACE, act);
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(ldata, CD_PROP_BYTE_COLOR)) {
|
||||
if (mesh.active_color_attribute != nullptr) {
|
||||
act = CustomData_get_named_layer(ldata, CD_PROP_BYTE_COLOR, mesh.active_color_attribute);
|
||||
CustomData_set_layer_active(fdata, CD_MCOL, act);
|
||||
CustomData_set_layer_active(fdata_legacy, CD_MCOL, act);
|
||||
}
|
||||
|
||||
if (mesh.default_color_attribute != nullptr) {
|
||||
act = CustomData_get_named_layer(ldata, CD_PROP_BYTE_COLOR, mesh.default_color_attribute);
|
||||
CustomData_set_layer_render(fdata, CD_MCOL, act);
|
||||
CustomData_set_layer_render(fdata_legacy, CD_MCOL, act);
|
||||
}
|
||||
|
||||
act = CustomData_get_clone_layer(ldata, CD_PROP_BYTE_COLOR);
|
||||
CustomData_set_layer_clone(fdata, CD_MCOL, act);
|
||||
CustomData_set_layer_clone(fdata_legacy, CD_MCOL, act);
|
||||
|
||||
act = CustomData_get_stencil_layer(ldata, CD_PROP_BYTE_COLOR);
|
||||
CustomData_set_layer_stencil(fdata, CD_MCOL, act);
|
||||
CustomData_set_layer_stencil(fdata_legacy, CD_MCOL, act);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,29 +608,31 @@ static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata, CustomData
|
||||
* \param fallback: Use when there are no layers to handle,
|
||||
* since callers may expect success or failure.
|
||||
*/
|
||||
static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ldata, bool fallback)
|
||||
static bool check_matching_legacy_layer_counts(CustomData *fdata_legacy,
|
||||
CustomData *ldata,
|
||||
bool fallback)
|
||||
{
|
||||
int a_num = 0, b_num = 0;
|
||||
# define LAYER_CMP(l_a, t_a, l_b, t_b) \
|
||||
((a_num += CustomData_number_of_layers(l_a, t_a)) == \
|
||||
(b_num += CustomData_number_of_layers(l_b, t_b)))
|
||||
|
||||
if (!LAYER_CMP(ldata, CD_PROP_FLOAT2, fdata, CD_MTFACE)) {
|
||||
if (!LAYER_CMP(ldata, CD_PROP_FLOAT2, fdata_legacy, CD_MTFACE)) {
|
||||
return false;
|
||||
}
|
||||
if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) {
|
||||
if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata_legacy, CD_MCOL)) {
|
||||
return false;
|
||||
}
|
||||
if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL)) {
|
||||
if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata_legacy, CD_PREVIEW_MCOL)) {
|
||||
return false;
|
||||
}
|
||||
if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE)) {
|
||||
if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata_legacy, CD_ORIGSPACE)) {
|
||||
return false;
|
||||
}
|
||||
if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL)) {
|
||||
if (!LAYER_CMP(ldata, CD_NORMAL, fdata_legacy, CD_TESSLOOPNORMAL)) {
|
||||
return false;
|
||||
}
|
||||
if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) {
|
||||
if (!LAYER_CMP(ldata, CD_TANGENT, fdata_legacy, CD_TANGENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -639,41 +644,44 @@ static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ld
|
||||
}
|
||||
#endif
|
||||
|
||||
static void add_mface_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata, int total)
|
||||
static void add_mface_layers(Mesh &mesh, CustomData *fdata_legacy, CustomData *ldata, int total)
|
||||
{
|
||||
/* avoid accumulating extra layers */
|
||||
BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false));
|
||||
BLI_assert(!check_matching_legacy_layer_counts(fdata_legacy, ldata, false));
|
||||
|
||||
for (int i = 0; i < ldata->totlayer; i++) {
|
||||
if (ldata->layers[i].type == CD_PROP_FLOAT2) {
|
||||
CustomData_add_layer_named(fdata, CD_MTFACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(
|
||||
fdata_legacy, CD_MTFACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) {
|
||||
CustomData_add_layer_named(fdata, CD_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(
|
||||
fdata_legacy, CD_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
fdata_legacy, CD_PREVIEW_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_ORIGSPACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
fdata_legacy, CD_ORIGSPACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_NORMAL) {
|
||||
CustomData_add_layer_named(
|
||||
fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
fdata_legacy, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
else if (ldata->layers[i].type == CD_TANGENT) {
|
||||
CustomData_add_layer_named(fdata, CD_TANGENT, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
CustomData_add_layer_named(
|
||||
fdata_legacy, CD_TANGENT, CD_SET_DEFAULT, total, ldata->layers[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
update_active_fdata_layers(mesh, fdata, ldata);
|
||||
update_active_fdata_layers(mesh, fdata_legacy, ldata);
|
||||
}
|
||||
|
||||
static void mesh_ensure_tessellation_customdata(Mesh *me)
|
||||
{
|
||||
if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) {
|
||||
if (UNLIKELY((me->totface_legacy != 0) && (me->faces_num == 0))) {
|
||||
/* Pass, otherwise this function clears 'mface' before
|
||||
* versioning 'mface -> mpoly' code kicks in #30583.
|
||||
*
|
||||
@@ -683,13 +691,13 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
|
||||
const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
|
||||
const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR);
|
||||
|
||||
const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
|
||||
const int totcol_tessface = CustomData_number_of_layers(&me->fdata, CD_MCOL);
|
||||
const int tottex_tessface = CustomData_number_of_layers(&me->fdata_legacy, CD_MTFACE);
|
||||
const int totcol_tessface = CustomData_number_of_layers(&me->fdata_legacy, CD_MCOL);
|
||||
|
||||
if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) {
|
||||
BKE_mesh_tessface_clear(me);
|
||||
|
||||
add_mface_layers(*me, &me->fdata, &me->ldata, me->totface);
|
||||
add_mface_layers(*me, &me->fdata_legacy, &me->ldata, me->totface_legacy);
|
||||
|
||||
/* TODO: add some `--debug-mesh` option. */
|
||||
if (G.debug & G_DEBUG) {
|
||||
@@ -715,17 +723,17 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
|
||||
void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
|
||||
{
|
||||
convert_mfaces_to_mpolys(&mesh->id,
|
||||
&mesh->fdata,
|
||||
&mesh->fdata_legacy,
|
||||
&mesh->ldata,
|
||||
&mesh->pdata,
|
||||
mesh->totedge,
|
||||
mesh->totface,
|
||||
mesh->totface_legacy,
|
||||
mesh->totloop,
|
||||
mesh->totpoly,
|
||||
mesh->faces_num,
|
||||
mesh->edges_for_write().data(),
|
||||
(MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
|
||||
(MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
&mesh->totloop,
|
||||
&mesh->totpoly);
|
||||
&mesh->faces_num);
|
||||
BKE_mesh_legacy_convert_loops_to_corners(mesh);
|
||||
BKE_mesh_legacy_convert_polys_to_offsets(mesh);
|
||||
|
||||
@@ -734,39 +742,40 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
|
||||
|
||||
/**
|
||||
* Update active indices for active/render/clone/stencil custom data layers
|
||||
* based on indices from fdata layers
|
||||
* used when creating pdata and ldata for pre-bmesh
|
||||
* based on indices from fdata_legacy layers
|
||||
* used when creating fdata_legacy and ldata for pre-bmesh
|
||||
* meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files.
|
||||
*/
|
||||
static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
|
||||
static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata_legacy,
|
||||
CustomData *ldata)
|
||||
{
|
||||
int act;
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_MTFACE)) {
|
||||
act = CustomData_get_active_layer(fdata, CD_MTFACE);
|
||||
if (CustomData_has_layer(fdata_legacy, CD_MTFACE)) {
|
||||
act = CustomData_get_active_layer(fdata_legacy, CD_MTFACE);
|
||||
CustomData_set_layer_active(ldata, CD_PROP_FLOAT2, act);
|
||||
|
||||
act = CustomData_get_render_layer(fdata, CD_MTFACE);
|
||||
act = CustomData_get_render_layer(fdata_legacy, CD_MTFACE);
|
||||
CustomData_set_layer_render(ldata, CD_PROP_FLOAT2, act);
|
||||
|
||||
act = CustomData_get_clone_layer(fdata, CD_MTFACE);
|
||||
act = CustomData_get_clone_layer(fdata_legacy, CD_MTFACE);
|
||||
CustomData_set_layer_clone(ldata, CD_PROP_FLOAT2, act);
|
||||
|
||||
act = CustomData_get_stencil_layer(fdata, CD_MTFACE);
|
||||
act = CustomData_get_stencil_layer(fdata_legacy, CD_MTFACE);
|
||||
CustomData_set_layer_stencil(ldata, CD_PROP_FLOAT2, act);
|
||||
}
|
||||
|
||||
if (CustomData_has_layer(fdata, CD_MCOL)) {
|
||||
act = CustomData_get_active_layer(fdata, CD_MCOL);
|
||||
if (CustomData_has_layer(fdata_legacy, CD_MCOL)) {
|
||||
act = CustomData_get_active_layer(fdata_legacy, CD_MCOL);
|
||||
CustomData_set_layer_active(ldata, CD_PROP_BYTE_COLOR, act);
|
||||
|
||||
act = CustomData_get_render_layer(fdata, CD_MCOL);
|
||||
act = CustomData_get_render_layer(fdata_legacy, CD_MCOL);
|
||||
CustomData_set_layer_render(ldata, CD_PROP_BYTE_COLOR, act);
|
||||
|
||||
act = CustomData_get_clone_layer(fdata, CD_MCOL);
|
||||
act = CustomData_get_clone_layer(fdata_legacy, CD_MCOL);
|
||||
CustomData_set_layer_clone(ldata, CD_PROP_BYTE_COLOR, act);
|
||||
|
||||
act = CustomData_get_stencil_layer(fdata, CD_MCOL);
|
||||
act = CustomData_get_stencil_layer(fdata_legacy, CD_MCOL);
|
||||
CustomData_set_layer_stencil(ldata, CD_PROP_BYTE_COLOR, act);
|
||||
}
|
||||
}
|
||||
@@ -774,21 +783,21 @@ static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata,
|
||||
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
|
||||
{
|
||||
convert_mfaces_to_mpolys(&mesh->id,
|
||||
&mesh->fdata,
|
||||
&mesh->fdata_legacy,
|
||||
&mesh->ldata,
|
||||
&mesh->pdata,
|
||||
mesh->totedge,
|
||||
mesh->totface,
|
||||
mesh->totface_legacy,
|
||||
mesh->totloop,
|
||||
mesh->totpoly,
|
||||
mesh->faces_num,
|
||||
mesh->edges_for_write().data(),
|
||||
(MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
|
||||
(MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
&mesh->totloop,
|
||||
&mesh->totpoly);
|
||||
&mesh->faces_num);
|
||||
BKE_mesh_legacy_convert_loops_to_corners(mesh);
|
||||
BKE_mesh_legacy_convert_polys_to_offsets(mesh);
|
||||
|
||||
CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->ldata);
|
||||
CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata_legacy, &mesh->ldata);
|
||||
|
||||
mesh_ensure_tessellation_customdata(mesh);
|
||||
}
|
||||
@@ -821,7 +830,7 @@ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
|
||||
* \note when mface is not null, mface[face_index].v4
|
||||
* is used to test quads, else, loopindices[face_index][3] is used.
|
||||
*/
|
||||
static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
static void mesh_loops_to_tessdata(CustomData *fdata_legacy,
|
||||
CustomData *ldata,
|
||||
MFace *mface,
|
||||
const int *polyindices,
|
||||
@@ -843,7 +852,8 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
uint(*lidx)[4];
|
||||
|
||||
for (i = 0; i < numUV; i++) {
|
||||
MTFace *texface = (MTFace *)CustomData_get_layer_n_for_write(fdata, CD_MTFACE, i, num_faces);
|
||||
MTFace *texface = (MTFace *)CustomData_get_layer_n_for_write(
|
||||
fdata_legacy, CD_MTFACE, i, num_faces);
|
||||
const blender::float2 *uv = static_cast<const blender::float2 *>(
|
||||
CustomData_get_layer_n(ldata, CD_PROP_FLOAT2, i));
|
||||
|
||||
@@ -857,7 +867,8 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
}
|
||||
|
||||
for (i = 0; i < numCol; i++) {
|
||||
MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer_n_for_write(fdata, CD_MCOL, i, num_faces);
|
||||
MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer_n_for_write(
|
||||
fdata_legacy, CD_MCOL, i, num_faces);
|
||||
const MLoopCol *mloopcol = (const MLoopCol *)CustomData_get_layer_n(
|
||||
ldata, CD_PROP_BYTE_COLOR, i);
|
||||
|
||||
@@ -869,7 +880,7 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
}
|
||||
|
||||
if (hasPCol) {
|
||||
MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer(fdata, CD_PREVIEW_MCOL);
|
||||
MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer(fdata_legacy, CD_PREVIEW_MCOL);
|
||||
const MLoopCol *mloopcol = (const MLoopCol *)CustomData_get_layer(ldata, CD_PREVIEW_MLOOPCOL);
|
||||
|
||||
for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
|
||||
@@ -880,7 +891,7 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
}
|
||||
|
||||
if (hasOrigSpace) {
|
||||
OrigSpaceFace *of = (OrigSpaceFace *)CustomData_get_layer(fdata, CD_ORIGSPACE);
|
||||
OrigSpaceFace *of = (OrigSpaceFace *)CustomData_get_layer(fdata_legacy, CD_ORIGSPACE);
|
||||
const OrigSpaceLoop *lof = (const OrigSpaceLoop *)CustomData_get_layer(ldata,
|
||||
CD_ORIGSPACE_MLOOP);
|
||||
|
||||
@@ -892,7 +903,8 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
}
|
||||
|
||||
if (hasLoopNormal) {
|
||||
short(*face_normals)[4][3] = (short(*)[4][3])CustomData_get_layer(fdata, CD_TESSLOOPNORMAL);
|
||||
short(*face_normals)[4][3] = (short(*)[4][3])CustomData_get_layer(fdata_legacy,
|
||||
CD_TESSLOOPNORMAL);
|
||||
const float(*loop_normals)[3] = (const float(*)[3])CustomData_get_layer(ldata, CD_NORMAL);
|
||||
|
||||
for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, face_normals++) {
|
||||
@@ -904,7 +916,7 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
|
||||
if (hasLoopTangent) {
|
||||
/* Need to do for all UV maps at some point. */
|
||||
float(*ftangents)[4] = (float(*)[4])CustomData_get_layer(fdata, CD_TANGENT);
|
||||
float(*ftangents)[4] = (float(*)[4])CustomData_get_layer(fdata_legacy, CD_TANGENT);
|
||||
const float(*ltangents)[4] = (const float(*)[4])CustomData_get_layer(ldata, CD_TANGENT);
|
||||
|
||||
for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
|
||||
@@ -918,7 +930,7 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
|
||||
}
|
||||
}
|
||||
|
||||
int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, int nr)
|
||||
int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata_legacy, int mfindex, int nr)
|
||||
{
|
||||
/* first test if the face is legal */
|
||||
if ((mface->v3 || nr == 4) && mface->v3 == mface->v4) {
|
||||
@@ -967,8 +979,8 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
|
||||
std::swap(mface->v1, mface->v2);
|
||||
std::swap(mface->v2, mface->v3);
|
||||
|
||||
if (fdata) {
|
||||
CustomData_swap_corners(fdata, mfindex, corner_indices);
|
||||
if (fdata_legacy) {
|
||||
CustomData_swap_corners(fdata_legacy, mfindex, corner_indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -979,8 +991,8 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
|
||||
std::swap(mface->v1, mface->v3);
|
||||
std::swap(mface->v2, mface->v4);
|
||||
|
||||
if (fdata) {
|
||||
CustomData_swap_corners(fdata, mfindex, corner_indices);
|
||||
if (fdata_legacy) {
|
||||
CustomData_swap_corners(fdata_legacy, mfindex, corner_indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -989,13 +1001,13 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
|
||||
}
|
||||
|
||||
static int mesh_tessface_calc(Mesh &mesh,
|
||||
CustomData *fdata,
|
||||
CustomData *fdata_legacy,
|
||||
CustomData *ldata,
|
||||
CustomData *pdata,
|
||||
float (*positions)[3],
|
||||
int totface,
|
||||
int totloop,
|
||||
int totpoly)
|
||||
int faces_num)
|
||||
{
|
||||
#define USE_TESSFACE_SPEEDUP
|
||||
#define USE_TESSFACE_QUADS
|
||||
@@ -1003,7 +1015,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
/* We abuse #MFace.edcode to tag quad faces. See below for details. */
|
||||
#define TESSFACE_IS_QUAD 1
|
||||
|
||||
const int looptri_num = poly_to_tri_count(totpoly, totloop);
|
||||
const int looptri_num = poly_to_tri_count(faces_num, totloop);
|
||||
|
||||
MFace *mface, *mf;
|
||||
MemArena *arena = nullptr;
|
||||
@@ -1012,7 +1024,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
int poly_index, mface_index;
|
||||
uint j;
|
||||
|
||||
const blender::OffsetIndices polys = mesh.polys();
|
||||
const blender::OffsetIndices faces = mesh.faces();
|
||||
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"));
|
||||
@@ -1028,9 +1040,9 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
lindices = (uint(*)[4])MEM_malloc_arrayN(size_t(looptri_num), sizeof(*lindices), __func__);
|
||||
|
||||
mface_index = 0;
|
||||
for (poly_index = 0; poly_index < totpoly; poly_index++) {
|
||||
const uint mp_loopstart = uint(polys[poly_index].start());
|
||||
const uint mp_totloop = uint(polys[poly_index].size());
|
||||
for (poly_index = 0; poly_index < faces_num; poly_index++) {
|
||||
const uint mp_loopstart = uint(faces[poly_index].start());
|
||||
const uint mp_totloop = uint(faces[poly_index].size());
|
||||
uint l1, l2, l3, l4;
|
||||
uint *lidx;
|
||||
if (mp_totloop < 3) {
|
||||
@@ -1179,7 +1191,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
arena = nullptr;
|
||||
}
|
||||
|
||||
CustomData_free(fdata, totface);
|
||||
CustomData_free(fdata_legacy, totface);
|
||||
totface = mface_index;
|
||||
|
||||
BLI_assert(totface <= looptri_num);
|
||||
@@ -1191,12 +1203,12 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
sizeof(*mface_to_poly_map) * size_t(totface));
|
||||
}
|
||||
|
||||
CustomData_add_layer_with_data(fdata, CD_MFACE, mface, totface, nullptr);
|
||||
CustomData_add_layer_with_data(fdata_legacy, CD_MFACE, mface, totface, nullptr);
|
||||
|
||||
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
|
||||
* they are directly tessellated from. */
|
||||
CustomData_add_layer_with_data(fdata, CD_ORIGINDEX, mface_to_poly_map, totface, nullptr);
|
||||
add_mface_layers(mesh, fdata, ldata, totface);
|
||||
CustomData_add_layer_with_data(fdata_legacy, CD_ORIGINDEX, mface_to_poly_map, totface, nullptr);
|
||||
add_mface_layers(mesh, fdata_legacy, ldata, totface);
|
||||
|
||||
/* NOTE: quad detection issue - fourth vertex-index vs fourth loop-index:
|
||||
* Polygons take care of their loops ordering, hence not of their vertices ordering.
|
||||
@@ -1205,7 +1217,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
* (because they are sorted for polygons, and our quads are still mere copies of their polygons).
|
||||
* So we pass nullptr as #MFace pointer, and #mesh_loops_to_tessdata
|
||||
* will use the fourth loop index as quad test. */
|
||||
mesh_loops_to_tessdata(fdata, ldata, nullptr, mface_to_poly_map, lindices, totface);
|
||||
mesh_loops_to_tessdata(fdata_legacy, ldata, nullptr, mface_to_poly_map, lindices, totface);
|
||||
|
||||
/* NOTE: quad detection issue - fourth vert-index vs fourth loop-index:
|
||||
* ...However, most #TFace code uses `MFace->v4 == 0` test to check whether it is a tri or quad.
|
||||
@@ -1215,7 +1227,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
mf = mface;
|
||||
for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
|
||||
if (mf->edcode == TESSFACE_IS_QUAD) {
|
||||
BKE_mesh_mface_index_validate(mf, fdata, mface_index, 4);
|
||||
BKE_mesh_mface_index_validate(mf, fdata_legacy, mface_index, 4);
|
||||
mf->edcode = 0;
|
||||
}
|
||||
}
|
||||
@@ -1234,22 +1246,22 @@ static int mesh_tessface_calc(Mesh &mesh,
|
||||
|
||||
void BKE_mesh_tessface_calc(Mesh *mesh)
|
||||
{
|
||||
mesh->totface = mesh_tessface_calc(
|
||||
mesh->totface_legacy = mesh_tessface_calc(
|
||||
*mesh,
|
||||
&mesh->fdata,
|
||||
&mesh->fdata_legacy,
|
||||
&mesh->ldata,
|
||||
&mesh->pdata,
|
||||
reinterpret_cast<float(*)[3]>(mesh->vert_positions_for_write().data()),
|
||||
mesh->totface,
|
||||
mesh->totface_legacy,
|
||||
mesh->totloop,
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
|
||||
mesh_ensure_tessellation_customdata(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_tessface_ensure(Mesh *mesh)
|
||||
{
|
||||
if (mesh->totpoly && mesh->totface == 0) {
|
||||
if (mesh->faces_num && mesh->totface_legacy == 0) {
|
||||
BKE_mesh_tessface_calc(mesh);
|
||||
}
|
||||
}
|
||||
@@ -1269,7 +1281,7 @@ void BKE_mesh_legacy_sharp_faces_from_flags(Mesh *mesh)
|
||||
return;
|
||||
}
|
||||
const Span<MPoly> polys(static_cast<const MPoly *>(CustomData_get_layer(&mesh->pdata, CD_MPOLY)),
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return !(poly.flag_legacy & ME_SMOOTH);
|
||||
}))
|
||||
@@ -1309,7 +1321,7 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
||||
faceset_sharing_info = layer.sharing_info;
|
||||
layer.data = nullptr;
|
||||
layer.sharing_info = nullptr;
|
||||
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
|
||||
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->faces_num, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1317,7 +1329,7 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
|
||||
CustomData_add_layer_named_with_data(&mesh->pdata,
|
||||
CD_PROP_INT32,
|
||||
faceset_data,
|
||||
mesh->totpoly,
|
||||
mesh->faces_num,
|
||||
".sculpt_face_set",
|
||||
faceset_sharing_info);
|
||||
}
|
||||
@@ -1347,13 +1359,13 @@ void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
|
||||
sharing_info = layer.sharing_info;
|
||||
layer.data = nullptr;
|
||||
layer.sharing_info = nullptr;
|
||||
CustomData_free_layer(&mesh->pdata, CD_FACEMAP, mesh->totpoly, i);
|
||||
CustomData_free_layer(&mesh->pdata, CD_FACEMAP, mesh->faces_num, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data != nullptr) {
|
||||
CustomData_add_layer_named_with_data(
|
||||
&mesh->pdata, CD_PROP_INT32, data, mesh->totpoly, "face_maps", sharing_info);
|
||||
&mesh->pdata, CD_PROP_INT32, data, mesh->faces_num, "face_maps", sharing_info);
|
||||
}
|
||||
if (sharing_info != nullptr) {
|
||||
sharing_info->remove_user_and_delete_if_last();
|
||||
@@ -1585,7 +1597,7 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
|
||||
}
|
||||
|
||||
const Span<MPoly> polys(static_cast<const MPoly *>(CustomData_get_layer(&mesh->pdata, CD_MPOLY)),
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return poly.flag_legacy & ME_HIDE;
|
||||
}))
|
||||
@@ -1616,7 +1628,7 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
|
||||
return;
|
||||
}
|
||||
const Span<MPoly> polys(static_cast<const MPoly *>(CustomData_get_layer(&mesh->pdata, CD_MPOLY)),
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
if (std::any_of(
|
||||
polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr_legacy != 0; }))
|
||||
{
|
||||
@@ -1809,7 +1821,7 @@ void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh)
|
||||
}
|
||||
|
||||
const Span<MPoly> polys(static_cast<const MPoly *>(CustomData_get_layer(&mesh->pdata, CD_MPOLY)),
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return poly.flag_legacy & ME_FACE_SEL;
|
||||
}))
|
||||
@@ -2008,14 +2020,14 @@ static bool poly_loops_orders_match(const Span<MPoly> polys)
|
||||
void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
if (mesh->poly_offset_indices) {
|
||||
if (mesh->face_offset_indices) {
|
||||
return;
|
||||
}
|
||||
const Span<MPoly> polys(static_cast<const MPoly *>(CustomData_get_layer(&mesh->pdata, CD_MPOLY)),
|
||||
mesh->totpoly);
|
||||
mesh->faces_num);
|
||||
|
||||
BKE_mesh_poly_offsets_ensure_alloc(mesh);
|
||||
MutableSpan<int> offsets = mesh->poly_offsets_for_write();
|
||||
BKE_mesh_face_offsets_ensure_alloc(mesh);
|
||||
MutableSpan<int> offsets = mesh->face_offsets_for_write();
|
||||
|
||||
if (poly_loops_orders_match(polys)) {
|
||||
for (const int i : polys.index_range()) {
|
||||
@@ -2032,7 +2044,7 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
|
||||
CustomData old_poly_data = mesh->pdata;
|
||||
CustomData_reset(&mesh->pdata);
|
||||
CustomData_copy_layout(
|
||||
&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->totpoly);
|
||||
&old_poly_data, &mesh->pdata, CD_MASK_MESH.pmask, CD_CONSTRUCT, mesh->faces_num);
|
||||
|
||||
int offset = 0;
|
||||
for (const int i : orig_indices.index_range()) {
|
||||
@@ -2046,10 +2058,10 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
|
||||
}
|
||||
});
|
||||
|
||||
CustomData_free(&old_poly_data, mesh->totpoly);
|
||||
CustomData_free(&old_poly_data, mesh->faces_num);
|
||||
}
|
||||
|
||||
CustomData_free_layers(&mesh->pdata, CD_MPOLY, mesh->totpoly);
|
||||
CustomData_free_layers(&mesh->pdata, CD_MPOLY, mesh->faces_num);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \ingroup bke
|
||||
*
|
||||
* Functions for accessing mesh connectivity data.
|
||||
* eg: polys connected to verts, UVs connected to verts.
|
||||
* eg: faces connected to verts, UVs connected to verts.
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@@ -33,7 +33,7 @@
|
||||
/** \name Mesh Connectivity Mapping
|
||||
* \{ */
|
||||
|
||||
UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> polys,
|
||||
UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
|
||||
const bool *hide_poly,
|
||||
const bool *select_poly,
|
||||
const int *corner_verts,
|
||||
@@ -54,9 +54,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> polys,
|
||||
totuv = 0;
|
||||
|
||||
/* generate UvMapVert array */
|
||||
for (const int64_t a : polys.index_range()) {
|
||||
for (const int64_t a : faces.index_range()) {
|
||||
if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) {
|
||||
totuv += int(polys[a].size());
|
||||
totuv += int(faces[a].size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,29 +76,29 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> polys,
|
||||
bool *winding = nullptr;
|
||||
if (use_winding) {
|
||||
winding = static_cast<bool *>(
|
||||
MEM_calloc_arrayN(sizeof(*winding), size_t(polys.size()), "winding"));
|
||||
MEM_calloc_arrayN(sizeof(*winding), size_t(faces.size()), "winding"));
|
||||
}
|
||||
|
||||
for (const int64_t a : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[a];
|
||||
for (const int64_t a : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[a];
|
||||
if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) {
|
||||
float(*tf_uv)[2] = nullptr;
|
||||
|
||||
if (use_winding) {
|
||||
tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, size_t(poly.size()));
|
||||
tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, size_t(face.size()));
|
||||
}
|
||||
|
||||
nverts = int(poly.size());
|
||||
nverts = int(face.size());
|
||||
|
||||
for (i = 0; i < nverts; i++) {
|
||||
buf->loop_of_poly_index = ushort(i);
|
||||
buf->poly_index = uint(a);
|
||||
buf->loop_of_face_index = ushort(i);
|
||||
buf->face_index = uint(a);
|
||||
buf->separate = false;
|
||||
buf->next = vmap->vert[corner_verts[poly[i]]];
|
||||
vmap->vert[corner_verts[poly[i]]] = buf;
|
||||
buf->next = vmap->vert[corner_verts[face[i]]];
|
||||
vmap->vert[corner_verts[face[i]]] = buf;
|
||||
|
||||
if (use_winding) {
|
||||
copy_v2_v2(tf_uv[i], mloopuv[poly[i]]);
|
||||
copy_v2_v2(tf_uv[i], mloopuv[face[i]]);
|
||||
}
|
||||
|
||||
buf++;
|
||||
@@ -123,18 +123,18 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> polys,
|
||||
v->next = newvlist;
|
||||
newvlist = v;
|
||||
|
||||
uv = mloopuv[polys[v->poly_index].start() + v->loop_of_poly_index];
|
||||
uv = mloopuv[faces[v->face_index].start() + v->loop_of_face_index];
|
||||
lastv = nullptr;
|
||||
iterv = vlist;
|
||||
|
||||
while (iterv) {
|
||||
next = iterv->next;
|
||||
|
||||
uv2 = mloopuv[polys[iterv->poly_index].start() + iterv->loop_of_poly_index];
|
||||
uv2 = mloopuv[faces[iterv->face_index].start() + iterv->loop_of_face_index];
|
||||
sub_v2_v2v2(uvdiff, uv2, uv);
|
||||
|
||||
if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
|
||||
(!use_winding || winding[iterv->poly_index] == winding[v->poly_index]))
|
||||
(!use_winding || winding[iterv->face_index] == winding[v->face_index]))
|
||||
{
|
||||
if (lastv) {
|
||||
lastv->next = next;
|
||||
@@ -257,7 +257,7 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
|
||||
map[i].count = 0;
|
||||
}
|
||||
|
||||
/* assign poly-tessface users */
|
||||
/* assign face-tessface users */
|
||||
for (i = 0; i < totfinal; i++) {
|
||||
if (final_origindex[i] != ORIGINDEX_NONE) {
|
||||
MeshElemMap *map_ele = &map[final_origindex[i]];
|
||||
@@ -271,24 +271,24 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map,
|
||||
|
||||
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const int *looptri_polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const int *looptri_faces,
|
||||
const int looptri_num)
|
||||
{
|
||||
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(polys.size()), __func__);
|
||||
MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(faces.size()), __func__);
|
||||
int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(looptri_num), __func__));
|
||||
int *index_step;
|
||||
|
||||
/* create offsets */
|
||||
index_step = indices;
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
map[i].indices = index_step;
|
||||
index_step += ME_POLY_TRI_TOT(polys[i].size());
|
||||
index_step += ME_FACE_TRI_TOT(faces[i].size());
|
||||
}
|
||||
|
||||
/* assign poly-tessface users */
|
||||
/* assign face-tessface users */
|
||||
for (int i = 0; i < looptri_num; i++) {
|
||||
MeshElemMap *map_ele = &map[looptri_polys[i]];
|
||||
MeshElemMap *map_ele = &map[looptri_faces[i]];
|
||||
map_ele->indices[map_ele->count++] = i;
|
||||
}
|
||||
|
||||
@@ -305,10 +305,10 @@ static Array<int> create_reverse_offsets(const Span<int> indices, const int item
|
||||
return offsets;
|
||||
}
|
||||
|
||||
Array<int> build_loop_to_poly_map(const OffsetIndices<int> polys)
|
||||
Array<int> build_loop_to_face_map(const OffsetIndices<int> faces)
|
||||
{
|
||||
Array<int> map(polys.total_size());
|
||||
offset_indices::build_reverse_map(polys, map);
|
||||
Array<int> map(faces.total_size());
|
||||
offset_indices::build_reverse_map(faces, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ GroupedSpan<int> build_vert_to_edge_map(const Span<int2> edges,
|
||||
return {OffsetIndices<int>(r_offsets), r_indices};
|
||||
}
|
||||
|
||||
GroupedSpan<int> build_vert_to_poly_map(const OffsetIndices<int> polys,
|
||||
GroupedSpan<int> build_vert_to_face_map(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
@@ -340,9 +340,9 @@ GroupedSpan<int> build_vert_to_poly_map(const OffsetIndices<int> polys,
|
||||
r_indices.reinitialize(r_offsets.last());
|
||||
Array<int> counts(verts_num, 0);
|
||||
|
||||
for (const int64_t poly_i : polys.index_range()) {
|
||||
for (const int vert : corner_verts.slice(polys[poly_i])) {
|
||||
r_indices[r_offsets[vert] + counts[vert]] = int(poly_i);
|
||||
for (const int64_t face_i : faces.index_range()) {
|
||||
for (const int vert : corner_verts.slice(faces[face_i])) {
|
||||
r_indices[r_offsets[vert] + counts[vert]] = int(face_i);
|
||||
counts[vert]++;
|
||||
}
|
||||
}
|
||||
@@ -383,7 +383,7 @@ GroupedSpan<int> build_edge_to_loop_map(const Span<int> corner_edges,
|
||||
return {OffsetIndices<int>(r_offsets), r_indices};
|
||||
}
|
||||
|
||||
GroupedSpan<int> build_edge_to_poly_map(const OffsetIndices<int> polys,
|
||||
GroupedSpan<int> build_edge_to_face_map(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_edges,
|
||||
const int edges_num,
|
||||
Array<int> &r_offsets,
|
||||
@@ -393,9 +393,9 @@ GroupedSpan<int> build_edge_to_poly_map(const OffsetIndices<int> polys,
|
||||
r_indices.reinitialize(r_offsets.last());
|
||||
Array<int> counts(edges_num, 0);
|
||||
|
||||
for (const int64_t poly_i : polys.index_range()) {
|
||||
for (const int edge : corner_edges.slice(polys[poly_i])) {
|
||||
r_indices[r_offsets[edge] + counts[edge]] = int(poly_i);
|
||||
for (const int64_t face_i : faces.index_range()) {
|
||||
for (const int edge : corner_edges.slice(faces[face_i])) {
|
||||
r_indices[r_offsets[edge] + counts[edge]] = int(face_i);
|
||||
counts[edge]++;
|
||||
}
|
||||
}
|
||||
@@ -407,49 +407,49 @@ GroupedSpan<int> build_edge_to_poly_map(const OffsetIndices<int> polys,
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Mesh loops/poly islands.
|
||||
/** \name Mesh loops/face islands.
|
||||
* Used currently for UVs and 'smooth groups'.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Callback deciding whether the given poly/loop/edge define an island boundary or not.
|
||||
* Callback deciding whether the given face/loop/edge define an island boundary or not.
|
||||
*/
|
||||
using MeshRemap_CheckIslandBoundary =
|
||||
blender::FunctionRef<bool(int poly_index,
|
||||
blender::FunctionRef<bool(int face_index,
|
||||
int loop_index,
|
||||
int edge_index,
|
||||
int edge_user_count,
|
||||
const blender::Span<int> edge_poly_map_elem)>;
|
||||
const blender::Span<int> edge_face_map_elem)>;
|
||||
|
||||
static void poly_edge_loop_islands_calc(const int totedge,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
static void face_edge_loop_islands_calc(const int totedge,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const blender::Span<int> corner_edges,
|
||||
blender::GroupedSpan<int> edge_poly_map,
|
||||
blender::GroupedSpan<int> edge_face_map,
|
||||
const bool use_bitflags,
|
||||
MeshRemap_CheckIslandBoundary edge_boundary_check,
|
||||
int **r_poly_groups,
|
||||
int **r_face_groups,
|
||||
int *r_totgroup,
|
||||
BLI_bitmap **r_edge_borders,
|
||||
int *r_totedgeborder)
|
||||
{
|
||||
int *poly_groups;
|
||||
int *poly_stack;
|
||||
int *face_groups;
|
||||
int *face_stack;
|
||||
|
||||
BLI_bitmap *edge_borders = nullptr;
|
||||
int num_edgeborders = 0;
|
||||
|
||||
int poly_prev = 0;
|
||||
const int temp_poly_group_id = 3; /* Placeholder value. */
|
||||
int face_prev = 0;
|
||||
const int temp_face_group_id = 3; /* Placeholder value. */
|
||||
|
||||
/* Group we could not find any available bit, will be reset to 0 at end. */
|
||||
const int poly_group_id_overflowed = 5;
|
||||
const int face_group_id_overflowed = 5;
|
||||
|
||||
int tot_group = 0;
|
||||
bool group_id_overflow = false;
|
||||
|
||||
if (polys.size() == 0) {
|
||||
if (faces.size() == 0) {
|
||||
*r_totgroup = 0;
|
||||
*r_poly_groups = nullptr;
|
||||
*r_face_groups = nullptr;
|
||||
if (r_edge_borders) {
|
||||
*r_edge_borders = nullptr;
|
||||
*r_totedgeborder = 0;
|
||||
@@ -462,59 +462,59 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
*r_totedgeborder = 0;
|
||||
}
|
||||
|
||||
blender::Array<int> edge_to_poly_src_offsets;
|
||||
blender::Array<int> edge_to_poly_src_indices;
|
||||
if (edge_poly_map.is_empty()) {
|
||||
edge_poly_map = blender::bke::mesh::build_edge_to_poly_map(
|
||||
polys, corner_edges, totedge, edge_to_poly_src_offsets, edge_to_poly_src_indices);
|
||||
blender::Array<int> edge_to_face_src_offsets;
|
||||
blender::Array<int> edge_to_face_src_indices;
|
||||
if (edge_face_map.is_empty()) {
|
||||
edge_face_map = blender::bke::mesh::build_edge_to_face_map(
|
||||
faces, corner_edges, totedge, edge_to_face_src_offsets, edge_to_face_src_indices);
|
||||
}
|
||||
|
||||
poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__));
|
||||
poly_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(polys.size()), __func__));
|
||||
face_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(faces.size()), __func__));
|
||||
face_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(faces.size()), __func__));
|
||||
|
||||
while (true) {
|
||||
int poly;
|
||||
int bit_poly_group_mask = 0;
|
||||
int poly_group_id;
|
||||
int face;
|
||||
int bit_face_group_mask = 0;
|
||||
int face_group_id;
|
||||
int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */
|
||||
|
||||
for (poly = poly_prev; poly < int(polys.size()); poly++) {
|
||||
if (poly_groups[poly] == 0) {
|
||||
for (face = face_prev; face < int(faces.size()); face++) {
|
||||
if (face_groups[face] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (poly == int(polys.size())) {
|
||||
if (face == int(faces.size())) {
|
||||
/* all done */
|
||||
break;
|
||||
}
|
||||
|
||||
poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group;
|
||||
face_group_id = use_bitflags ? temp_face_group_id : ++tot_group;
|
||||
|
||||
/* start searching from here next time */
|
||||
poly_prev = poly + 1;
|
||||
face_prev = face + 1;
|
||||
|
||||
poly_groups[poly] = poly_group_id;
|
||||
poly_stack[ps_end_idx++] = poly;
|
||||
face_groups[face] = face_group_id;
|
||||
face_stack[ps_end_idx++] = face;
|
||||
|
||||
while (ps_curr_idx != ps_end_idx) {
|
||||
poly = poly_stack[ps_curr_idx++];
|
||||
BLI_assert(poly_groups[poly] == poly_group_id);
|
||||
face = face_stack[ps_curr_idx++];
|
||||
BLI_assert(face_groups[face] == face_group_id);
|
||||
|
||||
for (const int64_t loop : polys[poly]) {
|
||||
for (const int64_t loop : faces[face]) {
|
||||
const int edge = corner_edges[loop];
|
||||
/* loop over poly users */
|
||||
const blender::Span<int> map_ele = edge_poly_map[edge];
|
||||
/* loop over face users */
|
||||
const blender::Span<int> map_ele = edge_face_map[edge];
|
||||
const int *p = map_ele.data();
|
||||
int i = int(map_ele.size());
|
||||
if (!edge_boundary_check(poly, int(loop), edge, i, map_ele)) {
|
||||
if (!edge_boundary_check(face, int(loop), edge, i, map_ele)) {
|
||||
for (; i--; p++) {
|
||||
/* if we meet other non initialized its a bug */
|
||||
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
|
||||
BLI_assert(ELEM(face_groups[*p], 0, face_group_id));
|
||||
|
||||
if (poly_groups[*p] == 0) {
|
||||
poly_groups[*p] = poly_group_id;
|
||||
poly_stack[ps_end_idx++] = *p;
|
||||
if (face_groups[*p] == 0) {
|
||||
face_groups[*p] = face_group_id;
|
||||
face_stack[ps_end_idx++] = *p;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,27 +527,27 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
/* Find contiguous smooth groups already assigned,
|
||||
* these are the values we can't reuse! */
|
||||
for (; i--; p++) {
|
||||
int bit = poly_groups[*p];
|
||||
if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
|
||||
!(bit_poly_group_mask & bit)) {
|
||||
bit_poly_group_mask |= bit;
|
||||
int bit = face_groups[*p];
|
||||
if (!ELEM(bit, 0, face_group_id, face_group_id_overflowed) &&
|
||||
!(bit_face_group_mask & bit)) {
|
||||
bit_face_group_mask |= bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* And now, we have all our poly from current group in poly_stack
|
||||
/* And now, we have all our face from current group in face_stack
|
||||
* (from 0 to (ps_end_idx - 1)),
|
||||
* as well as all smoothgroups bits we can't use in bit_poly_group_mask.
|
||||
* as well as all smoothgroups bits we can't use in bit_face_group_mask.
|
||||
*/
|
||||
if (use_bitflags) {
|
||||
int i, *p, gid_bit = 0;
|
||||
poly_group_id = 1;
|
||||
face_group_id = 1;
|
||||
|
||||
/* Find first bit available! */
|
||||
for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) {
|
||||
poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */
|
||||
for (; (face_group_id & bit_face_group_mask) && (gid_bit < 32); gid_bit++) {
|
||||
face_group_id <<= 1; /* will 'overflow' on last possible iteration. */
|
||||
}
|
||||
if (UNLIKELY(gid_bit > 31)) {
|
||||
/* All bits used in contiguous smooth groups, we can't do much!
|
||||
@@ -561,16 +561,16 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
"as out of any smooth group...\n");
|
||||
|
||||
/* Can't use 0, will have to set them to this value later. */
|
||||
poly_group_id = poly_group_id_overflowed;
|
||||
face_group_id = face_group_id_overflowed;
|
||||
|
||||
group_id_overflow = true;
|
||||
}
|
||||
if (gid_bit > tot_group) {
|
||||
tot_group = gid_bit;
|
||||
}
|
||||
/* And assign the final smooth group id to that poly group! */
|
||||
for (i = ps_end_idx, p = poly_stack; i--; p++) {
|
||||
poly_groups[*p] = poly_group_id;
|
||||
/* And assign the final smooth group id to that face group! */
|
||||
for (i = ps_end_idx, p = face_stack; i--; p++) {
|
||||
face_groups[*p] = face_group_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -581,9 +581,9 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
}
|
||||
|
||||
if (UNLIKELY(group_id_overflow)) {
|
||||
int i = int(polys.size()), *gid = poly_groups;
|
||||
int i = int(faces.size()), *gid = face_groups;
|
||||
for (; i--; gid++) {
|
||||
if (*gid == poly_group_id_overflowed) {
|
||||
if (*gid == face_group_id_overflowed) {
|
||||
*gid = 0;
|
||||
}
|
||||
}
|
||||
@@ -591,10 +591,10 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
tot_group++;
|
||||
}
|
||||
|
||||
MEM_freeN(poly_stack);
|
||||
MEM_freeN(face_stack);
|
||||
|
||||
*r_totgroup = tot_group;
|
||||
*r_poly_groups = poly_groups;
|
||||
*r_face_groups = face_groups;
|
||||
if (r_edge_borders) {
|
||||
*r_edge_borders = edge_borders;
|
||||
*r_totedgeborder = num_edgeborders;
|
||||
@@ -602,8 +602,8 @@ static void poly_edge_loop_islands_calc(const int totedge,
|
||||
}
|
||||
|
||||
int *BKE_mesh_calc_smoothgroups(const int totedge,
|
||||
const int *poly_offsets,
|
||||
const int totpoly,
|
||||
const int *face_offsets,
|
||||
const int faces_num,
|
||||
const int *corner_edges,
|
||||
const int totloop,
|
||||
const bool *sharp_edges,
|
||||
@@ -611,40 +611,40 @@ int *BKE_mesh_calc_smoothgroups(const int totedge,
|
||||
int *r_totgroup,
|
||||
const bool use_bitflags)
|
||||
{
|
||||
int *poly_groups = nullptr;
|
||||
int *face_groups = nullptr;
|
||||
|
||||
auto poly_is_smooth = [&](const int i) { return !(sharp_faces && sharp_faces[i]); };
|
||||
auto face_is_smooth = [&](const int i) { return !(sharp_faces && sharp_faces[i]); };
|
||||
|
||||
auto poly_is_island_boundary_smooth = [&](const int poly_index,
|
||||
auto face_is_island_boundary_smooth = [&](const int face_index,
|
||||
const int /*loop_index*/,
|
||||
const int edge_index,
|
||||
const int edge_user_count,
|
||||
const blender::Span<int> edge_poly_map_elem) {
|
||||
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
|
||||
* or edge is not used by exactly two polygons. */
|
||||
if (poly_is_smooth(poly_index) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
const blender::Span<int> edge_face_map_elem) {
|
||||
/* Edge is sharp if one of its faces is flat, or edge itself is sharp,
|
||||
* or edge is not used by exactly two faces. */
|
||||
if (face_is_smooth(face_index) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
(edge_user_count == 2))
|
||||
{
|
||||
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
|
||||
const int other_poly_index = (poly_index == edge_poly_map_elem[0]) ? edge_poly_map_elem[1] :
|
||||
edge_poly_map_elem[0];
|
||||
return !poly_is_smooth(other_poly_index);
|
||||
/* In that case, edge appears to be smooth, but we need to check its other face too. */
|
||||
const int other_face_index = (face_index == edge_face_map_elem[0]) ? edge_face_map_elem[1] :
|
||||
edge_face_map_elem[0];
|
||||
return !face_is_smooth(other_face_index);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
poly_edge_loop_islands_calc(totedge,
|
||||
blender::Span(poly_offsets, totpoly + 1),
|
||||
face_edge_loop_islands_calc(totedge,
|
||||
blender::Span(face_offsets, faces_num + 1),
|
||||
{corner_edges, totloop},
|
||||
{},
|
||||
use_bitflags,
|
||||
poly_is_island_boundary_smooth,
|
||||
&poly_groups,
|
||||
face_is_island_boundary_smooth,
|
||||
&face_groups,
|
||||
r_totgroup,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
return poly_groups;
|
||||
return face_groups;
|
||||
}
|
||||
|
||||
#define MISLAND_DEFAULT_BUFSIZE 64
|
||||
@@ -762,9 +762,9 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
|
||||
sizeof(*innrcut->indices) * size_t(num_innercut_items));
|
||||
}
|
||||
|
||||
static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
static bool mesh_calc_islands_loop_face_uv(const int totedge,
|
||||
const bool *uv_seams,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
const int totloop,
|
||||
@@ -772,15 +772,15 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
MeshIslandStore *r_island_store)
|
||||
{
|
||||
using namespace blender;
|
||||
int *poly_groups = nullptr;
|
||||
int num_poly_groups;
|
||||
int *face_groups = nullptr;
|
||||
int num_face_groups;
|
||||
|
||||
int *poly_indices;
|
||||
int *face_indices;
|
||||
int *loop_indices;
|
||||
int num_pidx, num_lidx;
|
||||
|
||||
/* Those are used to detect 'inner cuts', i.e. edges that are borders,
|
||||
* and yet have two or more polys of a same group using them
|
||||
* and yet have two or more faces of a same group using them
|
||||
* (typical case: seam used to unwrap properly a cylinder). */
|
||||
BLI_bitmap *edge_borders = nullptr;
|
||||
int num_edge_borders = 0;
|
||||
@@ -794,10 +794,10 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
BKE_mesh_loop_islands_init(
|
||||
r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
|
||||
|
||||
Array<int> edge_to_poly_offsets;
|
||||
Array<int> edge_to_poly_indices;
|
||||
const GroupedSpan<int> edge_to_poly_map = bke::mesh::build_edge_to_poly_map(
|
||||
polys, {corner_edges, totloop}, totedge, edge_to_poly_offsets, edge_to_poly_indices);
|
||||
Array<int> edge_to_face_offsets;
|
||||
Array<int> edge_to_face_indices;
|
||||
const GroupedSpan<int> edge_to_face_map = bke::mesh::build_edge_to_face_map(
|
||||
faces, {corner_edges, totloop}, totedge, edge_to_face_offsets, edge_to_face_indices);
|
||||
|
||||
Array<int> edge_to_loop_offsets;
|
||||
Array<int> edge_to_loop_indices;
|
||||
@@ -813,11 +813,11 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
* Would make things much more complex though,
|
||||
* and each UVMap would then need its own mesh mapping, not sure we want that at all!
|
||||
*/
|
||||
auto mesh_check_island_boundary_uv = [&](const int /*poly_index*/,
|
||||
auto mesh_check_island_boundary_uv = [&](const int /*face_index*/,
|
||||
const int loop_index,
|
||||
const int edge_index,
|
||||
const int /*edge_user_count*/,
|
||||
const Span<int> /*edge_poly_map_elem*/) -> bool {
|
||||
const Span<int> /*edge_face_map_elem*/) -> bool {
|
||||
if (luvs) {
|
||||
const Span<int> edge_to_loops = edge_to_loop_map[corner_edges[loop_index]];
|
||||
|
||||
@@ -852,18 +852,18 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
return uv_seams && uv_seams[edge_index];
|
||||
};
|
||||
|
||||
poly_edge_loop_islands_calc(totedge,
|
||||
polys,
|
||||
face_edge_loop_islands_calc(totedge,
|
||||
faces,
|
||||
{corner_edges, totloop},
|
||||
edge_to_poly_map,
|
||||
edge_to_face_map,
|
||||
false,
|
||||
mesh_check_island_boundary_uv,
|
||||
&poly_groups,
|
||||
&num_poly_groups,
|
||||
&face_groups,
|
||||
&num_face_groups,
|
||||
&edge_borders,
|
||||
&num_edge_borders);
|
||||
|
||||
if (!num_poly_groups) {
|
||||
if (!num_face_groups) {
|
||||
if (edge_borders) {
|
||||
MEM_freeN(edge_borders);
|
||||
}
|
||||
@@ -877,25 +877,25 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
MEM_mallocN(sizeof(*edge_innercut_indices) * size_t(num_edge_borders), __func__));
|
||||
}
|
||||
|
||||
poly_indices = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*poly_indices) * size_t(polys.size()), __func__));
|
||||
face_indices = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*face_indices) * size_t(faces.size()), __func__));
|
||||
loop_indices = static_cast<int *>(
|
||||
MEM_mallocN(sizeof(*loop_indices) * size_t(totloop), __func__));
|
||||
|
||||
/* NOTE: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
|
||||
for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
|
||||
for (grp_idx = 1; grp_idx <= num_face_groups; grp_idx++) {
|
||||
num_pidx = num_lidx = 0;
|
||||
if (num_edge_borders) {
|
||||
num_einnercuts = 0;
|
||||
memset(edge_border_count, 0, sizeof(*edge_border_count) * size_t(totedge));
|
||||
}
|
||||
|
||||
for (const int64_t p_idx : polys.index_range()) {
|
||||
if (poly_groups[p_idx] != grp_idx) {
|
||||
for (const int64_t p_idx : faces.index_range()) {
|
||||
if (face_groups[p_idx] != grp_idx) {
|
||||
continue;
|
||||
}
|
||||
poly_indices[num_pidx++] = int(p_idx);
|
||||
for (const int64_t corner : polys[p_idx]) {
|
||||
face_indices[num_pidx++] = int(p_idx);
|
||||
for (const int64_t corner : faces[p_idx]) {
|
||||
const int edge_i = corner_edges[corner];
|
||||
loop_indices[num_lidx++] = int(corner);
|
||||
if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, edge_i) &&
|
||||
@@ -912,14 +912,14 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
num_lidx,
|
||||
loop_indices,
|
||||
num_pidx,
|
||||
poly_indices,
|
||||
face_indices,
|
||||
num_einnercuts,
|
||||
edge_innercut_indices);
|
||||
}
|
||||
|
||||
MEM_freeN(poly_indices);
|
||||
MEM_freeN(face_indices);
|
||||
MEM_freeN(loop_indices);
|
||||
MEM_freeN(poly_groups);
|
||||
MEM_freeN(face_groups);
|
||||
|
||||
if (edge_borders) {
|
||||
MEM_freeN(edge_borders);
|
||||
@@ -932,28 +932,28 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
|
||||
bool BKE_mesh_calc_islands_loop_face_edgeseam(const float (*vert_positions)[3],
|
||||
const int totvert,
|
||||
const blender::int2 *edges,
|
||||
const int totedge,
|
||||
const bool *uv_seams,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
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, corner_verts, corner_edges, totloop, nullptr, r_island_store);
|
||||
return mesh_calc_islands_loop_face_uv(
|
||||
totedge, uv_seams, faces, corner_verts, corner_edges, totloop, nullptr, r_island_store);
|
||||
}
|
||||
|
||||
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
|
||||
bool BKE_mesh_calc_islands_loop_face_uvmap(float (*vert_positions)[3],
|
||||
const int totvert,
|
||||
blender::int2 *edges,
|
||||
const int totedge,
|
||||
const bool *uv_seams,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
const int totloop,
|
||||
@@ -962,8 +962,8 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
|
||||
{
|
||||
UNUSED_VARS(vert_positions, totvert, edges);
|
||||
BLI_assert(luvs != nullptr);
|
||||
return mesh_calc_islands_loop_poly_uv(
|
||||
totedge, uv_seams, polys, corner_verts, corner_edges, totloop, luvs, r_island_store);
|
||||
return mesh_calc_islands_loop_face_uv(
|
||||
totedge, uv_seams, faces, corner_verts, corner_edges, totloop, luvs, r_island_store);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -188,22 +188,23 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
|
||||
const int src_verts_num = mesh->totvert;
|
||||
const int src_edges_num = mesh->totedge;
|
||||
const blender::OffsetIndices src_polys = mesh->polys();
|
||||
const blender::OffsetIndices src_faces = mesh->faces();
|
||||
const int src_loops_num = mesh->totloop;
|
||||
|
||||
Mesh *result = BKE_mesh_new_nomain_from_template(
|
||||
mesh, src_verts_num * 2, src_edges_num * 2, src_polys.size() * 2, src_loops_num * 2);
|
||||
mesh, src_verts_num * 2, src_edges_num * 2, src_faces.size() * 2, src_loops_num * 2);
|
||||
|
||||
/* Copy custom-data to original geometry. */
|
||||
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, src_verts_num);
|
||||
CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, src_edges_num);
|
||||
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, src_polys.size());
|
||||
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, src_faces.size());
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, src_loops_num);
|
||||
|
||||
/* Copy custom data to mirrored geometry. Loops are copied later. */
|
||||
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, src_verts_num, src_verts_num);
|
||||
CustomData_copy_data(&mesh->edata, &result->edata, 0, src_edges_num, src_edges_num);
|
||||
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, src_polys.size(), src_polys.size());
|
||||
CustomData_copy_data(
|
||||
&mesh->pdata, &result->pdata, 0, src_faces.size(), src_faces.size());
|
||||
|
||||
if (do_vtargetmap) {
|
||||
/* second half is filled with -1 */
|
||||
@@ -288,7 +289,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
}
|
||||
|
||||
blender::MutableSpan<blender::int2> result_edges = result->edges_for_write();
|
||||
blender::MutableSpan<int> result_poly_offsets = result->poly_offsets_for_write();
|
||||
blender::MutableSpan<int> result_face_offsets = result->face_offsets_for_write();
|
||||
blender::MutableSpan<int> result_corner_verts = result->corner_verts_for_write();
|
||||
blender::MutableSpan<int> result_corner_edges = result->corner_edges_for_write();
|
||||
|
||||
@@ -297,32 +298,32 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
result_edges[i] += src_verts_num;
|
||||
}
|
||||
|
||||
result_poly_offsets.take_front(src_polys.size()).copy_from(mesh->poly_offsets().drop_back(1));
|
||||
for (const int i : src_polys.index_range()) {
|
||||
result_poly_offsets[src_polys.size() + i] = src_polys[i].start() + src_loops_num;
|
||||
result_face_offsets.take_front(src_faces.size()).copy_from(mesh->face_offsets().drop_back(1));
|
||||
for (const int i : src_faces.index_range()) {
|
||||
result_face_offsets[src_faces.size() + i] = src_faces[i].start() + src_loops_num;
|
||||
}
|
||||
const blender::OffsetIndices result_polys = result->polys();
|
||||
const blender::OffsetIndices result_faces = result->faces();
|
||||
|
||||
/* reverse loop order (normals) */
|
||||
for (const int i : src_polys.index_range()) {
|
||||
const blender::IndexRange src_poly = src_polys[i];
|
||||
const int mirror_i = src_polys.size() + i;
|
||||
const blender::IndexRange mirror_poly = result_polys[mirror_i];
|
||||
for (const int i : src_faces.index_range()) {
|
||||
const blender::IndexRange src_face = src_faces[i];
|
||||
const int mirror_i = src_faces.size() + i;
|
||||
const blender::IndexRange mirror_face = result_faces[mirror_i];
|
||||
|
||||
/* reverse the loop, but we keep the first vertex in the face the same,
|
||||
* to ensure that quads are split the same way as on the other side */
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly.start(), mirror_poly.start(), 1);
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, src_face.start(), mirror_face.start(), 1);
|
||||
|
||||
for (int j = 1; j < mirror_poly.size(); j++) {
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly[j], mirror_poly.last(j - 1), 1);
|
||||
for (int j = 1; j < mirror_face.size(); j++) {
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, src_face[j], mirror_face.last(j - 1), 1);
|
||||
}
|
||||
|
||||
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_poly_edges[j] = mirror_poly_edges[j + 1];
|
||||
blender::MutableSpan<int> mirror_face_edges = result_corner_edges.slice(mirror_face);
|
||||
const int e = mirror_face_edges.first();
|
||||
for (int j = 0; j < mirror_face.size() - 1; j++) {
|
||||
mirror_face_edges[j] = mirror_face_edges[j + 1];
|
||||
}
|
||||
mirror_poly_edges.last() = e;
|
||||
mirror_face_edges.last() = e;
|
||||
}
|
||||
|
||||
/* adjust mirrored loop vertex and edge indices */
|
||||
@@ -385,7 +386,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)
|
||||
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->faces_num > 0)
|
||||
{
|
||||
blender::Array<blender::float3> loop_normals(result_corner_verts.size());
|
||||
CustomData *ldata = &result->ldata;
|
||||
@@ -407,12 +408,12 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
blender::bke::mesh::normals_calc_loop(result->vert_positions(),
|
||||
result_edges,
|
||||
result_polys,
|
||||
result_faces,
|
||||
result_corner_verts,
|
||||
result_corner_edges,
|
||||
{},
|
||||
result->vert_normals(),
|
||||
result->poly_normals(),
|
||||
result->face_normals(),
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
true,
|
||||
@@ -421,15 +422,15 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
&lnors_spacearr,
|
||||
loop_normals);
|
||||
|
||||
/* mirroring has to account for loops being reversed in polys in second half */
|
||||
for (const int i : src_polys.index_range()) {
|
||||
const blender::IndexRange src_poly = src_polys[i];
|
||||
const int mirror_i = src_polys.size() + i;
|
||||
/* mirroring has to account for loops being reversed in faces in second half */
|
||||
for (const int i : src_faces.index_range()) {
|
||||
const blender::IndexRange src_face = src_faces[i];
|
||||
const int mirror_i = src_faces.size() + i;
|
||||
|
||||
for (const int j : src_poly) {
|
||||
int mirrorj = result_polys[mirror_i].start();
|
||||
if (j > src_poly.start()) {
|
||||
mirrorj += result_polys[mirror_i].size() - (j - src_poly.start());
|
||||
for (const int j : src_face) {
|
||||
int mirrorj = result_faces[mirror_i].start();
|
||||
if (j > src_face.start()) {
|
||||
mirrorj += result_faces[mirror_i].size() - (j - src_face.start());
|
||||
}
|
||||
|
||||
copy_v3_v3(loop_normals[mirrorj], loop_normals[j]);
|
||||
|
||||
@@ -106,9 +106,9 @@ bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh)
|
||||
return mesh->runtime->vert_normals_dirty;
|
||||
}
|
||||
|
||||
bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
|
||||
bool BKE_mesh_face_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime->poly_normals_dirty;
|
||||
return mesh->runtime->face_normals_dirty;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -123,17 +123,17 @@ namespace blender::bke::mesh {
|
||||
* COMPUTE POLY NORMAL
|
||||
*
|
||||
* Computes the normal of a planar
|
||||
* polygon See Graphics Gems for
|
||||
* face See Graphics Gems for
|
||||
* computing newell normal.
|
||||
*/
|
||||
static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<int> poly_verts)
|
||||
static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<int> face_verts)
|
||||
{
|
||||
float3 normal(0);
|
||||
|
||||
/* Newell's Method */
|
||||
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]];
|
||||
const float *v_prev = vert_positions[face_verts.last()];
|
||||
for (const int i : face_verts.index_range()) {
|
||||
const float *v_curr = vert_positions[face_verts[i]];
|
||||
add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
|
||||
v_prev = v_curr;
|
||||
}
|
||||
@@ -145,23 +145,23 @@ static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<int
|
||||
return normal;
|
||||
}
|
||||
|
||||
float3 poly_normal_calc(const Span<float3> vert_positions, const Span<int> poly_verts)
|
||||
float3 face_normal_calc(const Span<float3> vert_positions, const Span<int> face_verts)
|
||||
{
|
||||
if (poly_verts.size() > 4) {
|
||||
return normal_calc_ngon(vert_positions, poly_verts);
|
||||
if (face_verts.size() > 4) {
|
||||
return normal_calc_ngon(vert_positions, face_verts);
|
||||
}
|
||||
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 (face_verts.size() == 3) {
|
||||
return math::normal_tri(vert_positions[face_verts[0]],
|
||||
vert_positions[face_verts[1]],
|
||||
vert_positions[face_verts[2]]);
|
||||
}
|
||||
if (poly_verts.size() == 4) {
|
||||
if (face_verts.size() == 4) {
|
||||
float3 normal;
|
||||
normal_quad_v3(normal,
|
||||
vert_positions[poly_verts[0]],
|
||||
vert_positions[poly_verts[1]],
|
||||
vert_positions[poly_verts[2]],
|
||||
vert_positions[poly_verts[3]]);
|
||||
vert_positions[face_verts[0]],
|
||||
vert_positions[face_verts[1]],
|
||||
vert_positions[face_verts[2]],
|
||||
vert_positions[face_verts[3]]);
|
||||
return normal;
|
||||
}
|
||||
/* horrible, two sided face! */
|
||||
@@ -177,23 +177,23 @@ float3 poly_normal_calc(const Span<float3> vert_positions, const Span<int> poly_
|
||||
* meshes can slow down high-poly meshes. For details on performance, see D11993.
|
||||
* \{ */
|
||||
|
||||
void normals_calc_polys(const Span<float3> positions,
|
||||
const OffsetIndices<int> polys,
|
||||
void normals_calc_faces(const Span<float3> positions,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals)
|
||||
MutableSpan<float3> face_normals)
|
||||
{
|
||||
BLI_assert(polys.size() == poly_normals.size());
|
||||
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
|
||||
BLI_assert(faces.size() == face_normals.size());
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
poly_normals[i] = poly_normal_calc(positions, corner_verts.slice(polys[i]));
|
||||
face_normals[i] = face_normal_calc(positions, corner_verts.slice(faces[i]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void normals_calc_poly_vert(const Span<float3> positions,
|
||||
const OffsetIndices<int> polys,
|
||||
void normals_calc_face_vert(const Span<float3> positions,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals,
|
||||
MutableSpan<float3> face_normals,
|
||||
MutableSpan<float3> vert_normals)
|
||||
{
|
||||
|
||||
@@ -202,24 +202,24 @@ void normals_calc_poly_vert(const Span<float3> positions,
|
||||
memset(vert_normals.data(), 0, vert_normals.as_span().size_in_bytes());
|
||||
}
|
||||
|
||||
/* Compute poly normals, accumulating them into vertex normals. */
|
||||
/* Compute face normals, accumulating them into vertex normals. */
|
||||
{
|
||||
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int poly_i : range) {
|
||||
const Span<int> poly_verts = corner_verts.slice(polys[poly_i]);
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int face_i : range) {
|
||||
const Span<int> face_verts = corner_verts.slice(faces[face_i]);
|
||||
|
||||
float3 &pnor = poly_normals[poly_i];
|
||||
float3 &pnor = face_normals[face_i];
|
||||
|
||||
const int i_end = poly_verts.size() - 1;
|
||||
const int i_end = face_verts.size() - 1;
|
||||
|
||||
/* Polygon Normal and edge-vector. */
|
||||
/* Inline version of #poly_normal_calc, also does edge-vectors. */
|
||||
/* Inline version of #face_normal_calc, also does edge-vectors. */
|
||||
{
|
||||
zero_v3(pnor);
|
||||
/* Newell's Method */
|
||||
const float *v_curr = positions[poly_verts[i_end]];
|
||||
const float *v_curr = positions[face_verts[i_end]];
|
||||
for (int i_next = 0; i_next <= i_end; i_next++) {
|
||||
const float *v_next = positions[poly_verts[i_next]];
|
||||
const float *v_next = positions[face_verts[i_next]];
|
||||
add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
|
||||
v_curr = v_next;
|
||||
}
|
||||
@@ -232,13 +232,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_verts[i_end]];
|
||||
sub_v3_v3v3(edvec_prev, positions[poly_verts[i_end - 1]], v_curr);
|
||||
const float *v_curr = positions[face_verts[i_end]];
|
||||
sub_v3_v3v3(edvec_prev, positions[face_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_verts[i_next]];
|
||||
const float *v_next = positions[face_verts[i_next]];
|
||||
|
||||
/* Skip an extra normalization by reusing the first calculated edge. */
|
||||
if (i_next != i_end) {
|
||||
@@ -249,11 +249,11 @@ void normals_calc_poly_vert(const Span<float3> positions,
|
||||
copy_v3_v3(edvec_next, edvec_end);
|
||||
}
|
||||
|
||||
/* Calculate angle between the two poly edges incident on this vertex. */
|
||||
/* Calculate angle between the two face edges incident on this vertex. */
|
||||
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_verts[i_curr]];
|
||||
float *vnor = vert_normals[face_verts[i_curr]];
|
||||
add_v3_v3_atomic(vnor, vnor_add);
|
||||
v_curr = v_next;
|
||||
copy_v3_v3(edvec_prev, edvec_next);
|
||||
@@ -303,48 +303,48 @@ blender::Span<blender::float3> Mesh::vert_normals() const
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
threading::isolate_task([&]() {
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const OffsetIndices polys = this->polys();
|
||||
const OffsetIndices faces = this->faces();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
|
||||
this->runtime->vert_normals.reinitialize(positions.size());
|
||||
this->runtime->poly_normals.reinitialize(polys.size());
|
||||
bke::mesh::normals_calc_poly_vert(
|
||||
positions, polys, corner_verts, this->runtime->poly_normals, this->runtime->vert_normals);
|
||||
this->runtime->face_normals.reinitialize(faces.size());
|
||||
bke::mesh::normals_calc_face_vert(
|
||||
positions, faces, corner_verts, this->runtime->face_normals, this->runtime->vert_normals);
|
||||
|
||||
this->runtime->vert_normals_dirty = false;
|
||||
this->runtime->poly_normals_dirty = false;
|
||||
this->runtime->face_normals_dirty = false;
|
||||
});
|
||||
|
||||
return this->runtime->vert_normals;
|
||||
}
|
||||
|
||||
blender::Span<blender::float3> Mesh::poly_normals() const
|
||||
blender::Span<blender::float3> Mesh::face_normals() const
|
||||
{
|
||||
using namespace blender;
|
||||
if (!this->runtime->poly_normals_dirty) {
|
||||
BLI_assert(this->runtime->poly_normals.size() == this->totpoly);
|
||||
return this->runtime->poly_normals;
|
||||
if (!this->runtime->face_normals_dirty) {
|
||||
BLI_assert(this->runtime->face_normals.size() == this->faces_num);
|
||||
return this->runtime->face_normals;
|
||||
}
|
||||
|
||||
std::lock_guard lock{this->runtime->normals_mutex};
|
||||
if (!this->runtime->poly_normals_dirty) {
|
||||
BLI_assert(this->runtime->poly_normals.size() == this->totpoly);
|
||||
return this->runtime->poly_normals;
|
||||
if (!this->runtime->face_normals_dirty) {
|
||||
BLI_assert(this->runtime->face_normals.size() == this->faces_num);
|
||||
return this->runtime->face_normals;
|
||||
}
|
||||
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
threading::isolate_task([&]() {
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const OffsetIndices polys = this->polys();
|
||||
const OffsetIndices faces = this->faces();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
|
||||
this->runtime->poly_normals.reinitialize(polys.size());
|
||||
bke::mesh::normals_calc_polys(positions, polys, corner_verts, this->runtime->poly_normals);
|
||||
this->runtime->face_normals.reinitialize(faces.size());
|
||||
bke::mesh::normals_calc_faces(positions, faces, corner_verts, this->runtime->face_normals);
|
||||
|
||||
this->runtime->poly_normals_dirty = false;
|
||||
this->runtime->face_normals_dirty = false;
|
||||
});
|
||||
|
||||
return this->runtime->poly_normals;
|
||||
return this->runtime->face_normals;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
|
||||
@@ -358,14 +358,14 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
mesh->vert_normals();
|
||||
mesh->poly_normals();
|
||||
mesh->face_normals();
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
if (blender::bke::EditMeshData *emd = mesh->runtime->edit_data) {
|
||||
if (!emd->vertexCos.is_empty()) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(em, emd);
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, emd);
|
||||
BKE_editmesh_cache_ensure_face_normals(em, emd);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -707,10 +707,10 @@ struct LoopSplitTaskDataCommon {
|
||||
Span<int2> edges;
|
||||
Span<int> corner_verts;
|
||||
Span<int> corner_edges;
|
||||
OffsetIndices<int> polys;
|
||||
OffsetIndices<int> faces;
|
||||
Span<int2> edge_to_loops;
|
||||
Span<int> loop_to_poly;
|
||||
Span<float3> poly_normals;
|
||||
Span<int> loop_to_face;
|
||||
Span<float3> face_normals;
|
||||
Span<float3> vert_normals;
|
||||
};
|
||||
|
||||
@@ -719,11 +719,11 @@ struct LoopSplitTaskDataCommon {
|
||||
/* See comment about edge_to_loops below. */
|
||||
#define IS_EDGE_SHARP(_e2l) ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)
|
||||
|
||||
static void mesh_edges_sharp_tag(const OffsetIndices<int> polys,
|
||||
static void mesh_edges_sharp_tag(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<int> loop_to_poly_map,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<int> loop_to_face_map,
|
||||
const Span<float3> face_normals,
|
||||
const Span<bool> sharp_faces,
|
||||
const Span<bool> sharp_edges,
|
||||
const bool check_angle,
|
||||
@@ -732,12 +732,12 @@ static void mesh_edges_sharp_tag(const OffsetIndices<int> polys,
|
||||
MutableSpan<bool> r_sharp_edges)
|
||||
{
|
||||
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
|
||||
auto poly_is_smooth = [&](const int poly_i) {
|
||||
return sharp_faces.is_empty() || !sharp_faces[poly_i];
|
||||
auto face_is_smooth = [&](const int face_i) {
|
||||
return sharp_faces.is_empty() || !sharp_faces[face_i];
|
||||
};
|
||||
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
for (const int loop_index : polys[poly_i]) {
|
||||
for (const int face_i : faces.index_range()) {
|
||||
for (const int loop_index : faces[face_i]) {
|
||||
const int vert_i = corner_verts[loop_index];
|
||||
const int edge_i = corner_edges[loop_index];
|
||||
|
||||
@@ -748,19 +748,19 @@ static void mesh_edges_sharp_tag(const OffsetIndices<int> polys,
|
||||
/* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
|
||||
e2l[0] = loop_index;
|
||||
/* We have to check this here too, else we might miss some flat faces!!! */
|
||||
e2l[1] = poly_is_smooth(poly_i) ? INDEX_UNSET : INDEX_INVALID;
|
||||
e2l[1] = face_is_smooth(face_i) ? INDEX_UNSET : INDEX_INVALID;
|
||||
}
|
||||
else if (e2l[1] == INDEX_UNSET) {
|
||||
const bool is_angle_sharp = (check_angle &&
|
||||
dot_v3v3(poly_normals[loop_to_poly_map[e2l[0]]],
|
||||
poly_normals[poly_i]) < split_angle_cos);
|
||||
dot_v3v3(face_normals[loop_to_face_map[e2l[0]]],
|
||||
face_normals[face_i]) < split_angle_cos);
|
||||
|
||||
/* Second loop using this edge, time to test its sharpness.
|
||||
* An edge is sharp if it is tagged as such, or its face is not smooth,
|
||||
* or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the
|
||||
* same vertex, or angle between both its polys' normals is above split_angle value.
|
||||
* or both faces have opposed (flipped) normals, i.e. both loops on the same edge share the
|
||||
* same vertex, or angle between both its faces' normals is above split_angle value.
|
||||
*/
|
||||
if (!poly_is_smooth(poly_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) ||
|
||||
if (!face_is_smooth(face_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) ||
|
||||
vert_i == corner_verts[e2l[0]] || is_angle_sharp)
|
||||
{
|
||||
/* NOTE: we are sure that loop != 0 here ;). */
|
||||
@@ -791,10 +791,10 @@ static void mesh_edges_sharp_tag(const OffsetIndices<int> polys,
|
||||
}
|
||||
}
|
||||
|
||||
void edges_sharp_from_angle_set(const OffsetIndices<int> polys,
|
||||
void edges_sharp_from_angle_set(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
const float split_angle,
|
||||
MutableSpan<bool> sharp_edges)
|
||||
@@ -807,15 +807,15 @@ void edges_sharp_from_angle_set(const OffsetIndices<int> polys,
|
||||
/* Mapping edge -> loops. See #bke::mesh::normals_calc_loop for details. */
|
||||
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 = build_loop_to_poly_map(polys);
|
||||
/* Simple mapping from a loop to its face index. */
|
||||
const Array<int> loop_to_face = build_loop_to_face_map(faces);
|
||||
|
||||
mesh_edges_sharp_tag(polys,
|
||||
mesh_edges_sharp_tag(faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
loop_to_poly,
|
||||
poly_normals,
|
||||
Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
|
||||
loop_to_face,
|
||||
face_normals,
|
||||
Span<bool>(sharp_faces, sharp_faces ? faces.size() : 0),
|
||||
sharp_edges,
|
||||
true,
|
||||
split_angle,
|
||||
@@ -824,8 +824,8 @@ void edges_sharp_from_angle_set(const OffsetIndices<int> polys,
|
||||
}
|
||||
|
||||
static void loop_manifold_fan_around_vert_next(const Span<int> corner_verts,
|
||||
const OffsetIndices<int> polys,
|
||||
const Span<int> loop_to_poly,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> loop_to_face,
|
||||
const int *e2lfan_curr,
|
||||
const int vert_pivot,
|
||||
int *r_mlfan_curr_index,
|
||||
@@ -843,26 +843,26 @@ static void loop_manifold_fan_around_vert_next(const Span<int> corner_verts,
|
||||
* mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
|
||||
* (i.e. not the future `mlfan_curr`). */
|
||||
*r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
|
||||
*r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index];
|
||||
*r_mpfan_curr_index = loop_to_face[*r_mlfan_curr_index];
|
||||
|
||||
BLI_assert(*r_mlfan_curr_index >= 0);
|
||||
BLI_assert(*r_mpfan_curr_index >= 0);
|
||||
|
||||
const int vert_fan_next = corner_verts[*r_mlfan_curr_index];
|
||||
const IndexRange poly_fan_next = polys[*r_mpfan_curr_index];
|
||||
const IndexRange face_fan_next = faces[*r_mpfan_curr_index];
|
||||
if ((vert_fan_orig == vert_fan_next && vert_fan_orig == vert_pivot) ||
|
||||
!ELEM(vert_fan_orig, vert_fan_next, vert_pivot))
|
||||
{
|
||||
/* We need the previous loop, but current one is our vertex's loop. */
|
||||
*r_mlfan_vert_index = *r_mlfan_curr_index;
|
||||
if (--(*r_mlfan_curr_index) < poly_fan_next.start()) {
|
||||
*r_mlfan_curr_index = poly_fan_next.start() + poly_fan_next.size() - 1;
|
||||
if (--(*r_mlfan_curr_index) < face_fan_next.start()) {
|
||||
*r_mlfan_curr_index = face_fan_next.start() + face_fan_next.size() - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We need the next loop, which is also our vertex's loop. */
|
||||
if (++(*r_mlfan_curr_index) >= poly_fan_next.start() + poly_fan_next.size()) {
|
||||
*r_mlfan_curr_index = poly_fan_next.start();
|
||||
if (++(*r_mlfan_curr_index) >= face_fan_next.start() + face_fan_next.size()) {
|
||||
*r_mlfan_curr_index = face_fan_next.start();
|
||||
}
|
||||
*r_mlfan_vert_index = *r_mlfan_curr_index;
|
||||
}
|
||||
@@ -872,24 +872,24 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
||||
const int ml_curr_index,
|
||||
const int space_index)
|
||||
{
|
||||
const Span<int> loop_to_poly = common_data->loop_to_poly;
|
||||
const Span<float3> poly_normals = common_data->poly_normals;
|
||||
const Span<int> loop_to_face = common_data->loop_to_face;
|
||||
const Span<float3> face_normals = common_data->face_normals;
|
||||
MutableSpan<float3> loop_normals = common_data->loop_normals;
|
||||
|
||||
loop_normals[ml_curr_index] = poly_normals[loop_to_poly[ml_curr_index]];
|
||||
loop_normals[ml_curr_index] = face_normals[loop_to_face[ml_curr_index]];
|
||||
|
||||
if (CornerNormalSpaceArray *lnors_spacearr = common_data->lnors_spacearr) {
|
||||
const Span<float3> positions = common_data->positions;
|
||||
const Span<int2> edges = common_data->edges;
|
||||
const OffsetIndices polys = common_data->polys;
|
||||
const OffsetIndices faces = common_data->faces;
|
||||
const Span<int> corner_verts = common_data->corner_verts;
|
||||
const Span<int> corner_edges = common_data->corner_edges;
|
||||
const Span<short2> clnors_data = common_data->clnors_data;
|
||||
|
||||
float3 vec_curr;
|
||||
float3 vec_prev;
|
||||
const int poly_index = loop_to_poly[ml_curr_index];
|
||||
const int ml_prev_index = mesh::poly_corner_prev(polys[poly_index], ml_curr_index);
|
||||
const int face_index = loop_to_face[ml_curr_index];
|
||||
const int ml_prev_index = mesh::face_corner_prev(faces[face_index], ml_curr_index);
|
||||
|
||||
/* The vertex we are "fanning" around. */
|
||||
const int vert_pivot = corner_verts[ml_curr_index];
|
||||
@@ -927,15 +927,15 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
|
||||
const Span<float3> positions = common_data->positions;
|
||||
const Span<int2> edges = common_data->edges;
|
||||
const OffsetIndices polys = common_data->polys;
|
||||
const OffsetIndices faces = common_data->faces;
|
||||
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;
|
||||
const Span<int> loop_to_face = common_data->loop_to_face;
|
||||
const Span<float3> face_normals = common_data->face_normals;
|
||||
|
||||
const int poly_index = loop_to_poly[ml_curr_index];
|
||||
const int ml_prev_index = poly_corner_prev(polys[poly_index], ml_curr_index);
|
||||
const int face_index = loop_to_face[ml_curr_index];
|
||||
const int ml_prev_index = face_corner_prev(faces[face_index], ml_curr_index);
|
||||
|
||||
/* Sigh! we have to fan around current vertex, until we find the other non-smooth edge,
|
||||
* and accumulate face normals into the vertex!
|
||||
@@ -965,7 +965,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
*/
|
||||
int mlfan_curr_index = ml_prev_index;
|
||||
int mlfan_vert_index = ml_curr_index;
|
||||
int mpfan_curr_index = poly_index;
|
||||
int mpfan_curr_index = face_index;
|
||||
|
||||
BLI_assert(mlfan_curr_index >= 0);
|
||||
BLI_assert(mlfan_vert_index >= 0);
|
||||
@@ -1001,8 +1001,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
// printf("\thandling edge %d / loop %d\n", corner_edges[mlfan_curr_index], mlfan_curr_index);
|
||||
|
||||
/* Code similar to accumulate_vertex_normals_poly_v3. */
|
||||
/* Calculate angle between the two poly edges incident on this vertex. */
|
||||
lnor += poly_normals[mpfan_curr_index] * saacos(math::dot(vec_curr, vec_prev));
|
||||
/* Calculate angle between the two face edges incident on this vertex. */
|
||||
lnor += face_normals[mpfan_curr_index] * saacos(math::dot(vec_curr, vec_prev));
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
/* Accumulate all clnors, if they are not all equal we have to fix that! */
|
||||
@@ -1039,8 +1039,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
|
||||
/* Find next loop of the smooth fan. */
|
||||
loop_manifold_fan_around_vert_next(corner_verts,
|
||||
polys,
|
||||
loop_to_poly,
|
||||
faces,
|
||||
loop_to_face,
|
||||
edge_to_loops[corner_edges[mlfan_curr_index]],
|
||||
vert_pivot,
|
||||
&mlfan_curr_index,
|
||||
@@ -1097,9 +1097,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
*/
|
||||
static bool loop_split_generator_check_cyclic_smooth_fan(const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int2> edge_to_loops,
|
||||
const Span<int> loop_to_poly,
|
||||
const Span<int> loop_to_face,
|
||||
const int *e2l_prev,
|
||||
MutableBitSpan skip_loops,
|
||||
const int ml_curr_index,
|
||||
@@ -1131,8 +1131,8 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span<int> corner_
|
||||
while (true) {
|
||||
/* Find next loop of the smooth fan. */
|
||||
loop_manifold_fan_around_vert_next(corner_verts,
|
||||
polys,
|
||||
loop_to_poly,
|
||||
faces,
|
||||
loop_to_face,
|
||||
e2lfan_curr,
|
||||
vert_pivot,
|
||||
&mlfan_curr_index,
|
||||
@@ -1167,8 +1167,8 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
||||
{
|
||||
const Span<int> corner_verts = common_data->corner_verts;
|
||||
const Span<int> corner_edges = common_data->corner_edges;
|
||||
const OffsetIndices polys = common_data->polys;
|
||||
const Span<int> loop_to_poly = common_data->loop_to_poly;
|
||||
const OffsetIndices faces = common_data->faces;
|
||||
const Span<int> loop_to_face = common_data->loop_to_face;
|
||||
const Span<int2> edge_to_loops = common_data->edge_to_loops;
|
||||
|
||||
BitVector<> skip_loops(corner_verts.size(), false);
|
||||
@@ -1180,11 +1180,11 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
||||
/* We now know edges that can be smoothed (with their vector, and their two loops),
|
||||
* and edges that will be hard! Now, time to generate the normals.
|
||||
*/
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const IndexRange poly = polys[poly_index];
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const IndexRange face = faces[face_index];
|
||||
|
||||
for (const int ml_curr_index : poly) {
|
||||
const int ml_prev_index = mesh::poly_corner_prev(poly, ml_curr_index);
|
||||
for (const int ml_curr_index : face) {
|
||||
const int ml_prev_index = mesh::face_corner_prev(face, ml_curr_index);
|
||||
|
||||
#if 0
|
||||
printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",
|
||||
@@ -1209,14 +1209,14 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
||||
(skip_loops[ml_curr_index] || !loop_split_generator_check_cyclic_smooth_fan(
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
polys,
|
||||
faces,
|
||||
edge_to_loops,
|
||||
loop_to_poly,
|
||||
loop_to_face,
|
||||
edge_to_loops[corner_edges[ml_prev_index]],
|
||||
skip_loops,
|
||||
ml_curr_index,
|
||||
ml_prev_index,
|
||||
poly_index)))
|
||||
face_index)))
|
||||
{
|
||||
// printf("SKIPPING!\n");
|
||||
}
|
||||
@@ -1224,14 +1224,14 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
||||
if (IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_curr_index]]) &&
|
||||
IS_EDGE_SHARP(edge_to_loops[corner_edges[ml_prev_index]]))
|
||||
{
|
||||
/* Simple case (both edges around that vertex are sharp in current polygon),
|
||||
* this corner just takes its poly normal. */
|
||||
/* Simple case (both edges around that vertex are sharp in current face),
|
||||
* this corner just takes its face normal. */
|
||||
r_single_corners.append(ml_curr_index);
|
||||
}
|
||||
else {
|
||||
/* We do not need to check/tag loops as already computed. Due to the fact that a loop
|
||||
* only points to one of its two edges, the same fan will never be walked more than once.
|
||||
* Since we consider edges that have neighbor polys with inverted (flipped) normals as
|
||||
* Since we consider edges that have neighbor faces with inverted (flipped) normals as
|
||||
* sharp, we are sure that no fan will be skipped, even only considering the case (sharp
|
||||
* current edge, smooth previous edge), and not the alternative (smooth current edge,
|
||||
* sharp previous edge). All this due/thanks to the link between normals and loop
|
||||
@@ -1245,12 +1245,12 @@ static void loop_split_generator(LoopSplitTaskDataCommon *common_data,
|
||||
|
||||
void normals_calc_loop(const Span<float3> vert_positions,
|
||||
const Span<int2> edges,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<int> loop_to_poly_map,
|
||||
const Span<int> loop_to_face_map,
|
||||
const Span<float3> vert_normals,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
bool use_split_normals,
|
||||
@@ -1265,16 +1265,16 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
|
||||
if (!use_split_normals) {
|
||||
/* In this case, simply fill `r_loop_normals` with `vert_normals`
|
||||
* (or `poly_normals` for flat faces), quite simple!
|
||||
* (or `face_normals` for flat faces), quite simple!
|
||||
* Note this is done here to keep some logic and consistency in this quite complex code,
|
||||
* since we may want to use loop_normals even when mesh's 'autosmooth' is disabled
|
||||
* (see e.g. mesh mapping code). As usual, we could handle that on case-by-case basis,
|
||||
* but simpler to keep it well confined here. */
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const bool is_poly_flat = sharp_faces && sharp_faces[poly_index];
|
||||
for (const int corner : polys[poly_index]) {
|
||||
if (is_poly_flat) {
|
||||
copy_v3_v3(r_loop_normals[corner], poly_normals[poly_index]);
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const bool is_face_flat = sharp_faces && sharp_faces[face_index];
|
||||
for (const int corner : faces[face_index]) {
|
||||
if (is_face_flat) {
|
||||
copy_v3_v3(r_loop_normals[corner], face_normals[face_index]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(r_loop_normals[corner], vert_normals[corner_verts[corner]]);
|
||||
@@ -1286,7 +1286,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
|
||||
/**
|
||||
* Mapping edge -> loops.
|
||||
* If that edge is used by more than two loops (polys),
|
||||
* If that edge is used by more than two loops (faces),
|
||||
* it is always sharp (and tagged as such, see below).
|
||||
* We also use the second loop index as a kind of flag:
|
||||
*
|
||||
@@ -1300,15 +1300,15 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
* Note also that loose edges always have both values set to 0! */
|
||||
Array<int2> edge_to_loops(edges.size(), int2(0));
|
||||
|
||||
/* Simple mapping from a loop to its polygon index. */
|
||||
Span<int> loop_to_poly;
|
||||
Array<int> local_loop_to_poly_map;
|
||||
if (loop_to_poly_map.is_empty()) {
|
||||
local_loop_to_poly_map = build_loop_to_poly_map(polys);
|
||||
loop_to_poly = local_loop_to_poly_map;
|
||||
/* Simple mapping from a loop to its face index. */
|
||||
Span<int> loop_to_face;
|
||||
Array<int> local_loop_to_face_map;
|
||||
if (loop_to_face_map.is_empty()) {
|
||||
local_loop_to_face_map = build_loop_to_face_map(faces);
|
||||
loop_to_face = local_loop_to_face_map;
|
||||
}
|
||||
else {
|
||||
loop_to_poly = loop_to_poly_map;
|
||||
loop_to_face = loop_to_face_map;
|
||||
}
|
||||
|
||||
/* When using custom loop normals, disable the angle feature! */
|
||||
@@ -1333,12 +1333,12 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
clnors_data ? corner_verts.size() : 0};
|
||||
common_data.positions = vert_positions;
|
||||
common_data.edges = edges;
|
||||
common_data.polys = polys;
|
||||
common_data.faces = faces;
|
||||
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;
|
||||
common_data.loop_to_face = loop_to_face;
|
||||
common_data.face_normals = face_normals;
|
||||
common_data.vert_normals = vert_normals;
|
||||
|
||||
/* Pre-populate all loop normals as if their verts were all smooth.
|
||||
@@ -1346,12 +1346,12 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
array_utils::gather(vert_normals, corner_verts, r_loop_normals, 1024);
|
||||
|
||||
/* This first loop check which edges are actually smooth, and compute edge vectors. */
|
||||
mesh_edges_sharp_tag(polys,
|
||||
mesh_edges_sharp_tag(faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
loop_to_poly,
|
||||
poly_normals,
|
||||
Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
|
||||
loop_to_face,
|
||||
face_normals,
|
||||
Span<bool>(sharp_faces, sharp_faces ? faces.size() : 0),
|
||||
Span<bool>(sharp_edges, sharp_edges ? edges.size() : 0),
|
||||
check_angle,
|
||||
split_angle,
|
||||
@@ -1403,11 +1403,11 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
||||
|
||||
static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
Span<int2> edges,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> vert_normals,
|
||||
Span<float3> poly_normals,
|
||||
Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
const bool use_vertices,
|
||||
MutableSpan<float3> r_custom_loop_normals,
|
||||
@@ -1423,7 +1423,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
lnors_spacearr.create_corners_by_space = true;
|
||||
BitVector<> done_loops(corner_verts.size(), false);
|
||||
Array<float3> loop_normals(corner_verts.size());
|
||||
const Array<int> loop_to_poly = build_loop_to_poly_map(polys);
|
||||
const Array<int> loop_to_face = build_loop_to_face_map(faces);
|
||||
/* 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;
|
||||
@@ -1432,12 +1432,12 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
/* Compute current lnor spacearr. */
|
||||
normals_calc_loop(positions,
|
||||
edges,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
loop_to_poly,
|
||||
loop_to_face,
|
||||
vert_normals,
|
||||
poly_normals,
|
||||
face_normals,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
use_split_normals,
|
||||
@@ -1518,8 +1518,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
* previous loop's face and current's one as sharp.
|
||||
* 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 IndexRange poly = polys[loop_to_poly[lidx]];
|
||||
const int mlp = (lidx == poly.start()) ? poly.start() + poly.size() - 1 : lidx - 1;
|
||||
const IndexRange face = faces[loop_to_face[lidx]];
|
||||
const int mlp = (lidx == face.start()) ? face.start() + face.size() - 1 : lidx - 1;
|
||||
const int edge = corner_edges[lidx];
|
||||
const int edge_p = corner_edges[mlp];
|
||||
const int prev_edge = corner_edges[prev_corner];
|
||||
@@ -1541,8 +1541,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
float *nor = r_custom_loop_normals[lidx];
|
||||
|
||||
if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
|
||||
const IndexRange poly = polys[loop_to_poly[lidx]];
|
||||
const int mlp = (lidx == poly.start()) ? poly.start() + poly.size() - 1 : lidx - 1;
|
||||
const IndexRange face = faces[loop_to_face[lidx]];
|
||||
const int mlp = (lidx == face.start()) ? face.start() + face.size() - 1 : lidx - 1;
|
||||
const int edge = corner_edges[lidx];
|
||||
const int edge_p = corner_edges[mlp];
|
||||
const int prev_edge = corner_edges[prev_corner];
|
||||
@@ -1554,12 +1554,12 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
/* And now, recompute our new auto `loop_normals` and lnor spacearr! */
|
||||
normals_calc_loop(positions,
|
||||
edges,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
loop_to_poly,
|
||||
loop_to_face,
|
||||
vert_normals,
|
||||
poly_normals,
|
||||
face_normals,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
use_split_normals,
|
||||
@@ -1615,11 +1615,11 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
||||
|
||||
void normals_loop_custom_set(const Span<float3> vert_positions,
|
||||
const Span<int2> edges,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<float3> vert_normals,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_loop_normals,
|
||||
@@ -1627,11 +1627,11 @@ void normals_loop_custom_set(const Span<float3> vert_positions,
|
||||
{
|
||||
mesh_normals_loop_custom_set(vert_positions,
|
||||
edges,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
vert_normals,
|
||||
poly_normals,
|
||||
face_normals,
|
||||
sharp_faces,
|
||||
false,
|
||||
r_custom_loop_normals,
|
||||
@@ -1641,11 +1641,11 @@ void normals_loop_custom_set(const Span<float3> vert_positions,
|
||||
|
||||
void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
|
||||
const Span<int2> edges,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<float3> vert_normals,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
const bool *sharp_faces,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
MutableSpan<float3> r_custom_vert_normals,
|
||||
@@ -1653,11 +1653,11 @@ void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
|
||||
{
|
||||
mesh_normals_loop_custom_set(vert_positions,
|
||||
edges,
|
||||
polys,
|
||||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
vert_normals,
|
||||
poly_normals,
|
||||
face_normals,
|
||||
sharp_faces,
|
||||
true,
|
||||
r_custom_vert_normals,
|
||||
@@ -1685,11 +1685,11 @@ 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->faces(),
|
||||
mesh->corner_verts(),
|
||||
mesh->corner_edges(),
|
||||
mesh->vert_normals(),
|
||||
mesh->poly_normals(),
|
||||
mesh->face_normals(),
|
||||
sharp_faces,
|
||||
use_vertices,
|
||||
{reinterpret_cast<float3 *>(r_custom_nors), use_vertices ? mesh->totvert : mesh->totloop},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -122,10 +122,10 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
/* Construct the new output mesh */
|
||||
Mesh *mesh = BKE_mesh_new_nomain(qrd.out_totverts, 0, qrd.out_totfaces, qrd.out_totfaces * 4);
|
||||
BKE_mesh_copy_parameters(mesh, input_mesh);
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
|
||||
|
||||
blender::offset_indices::fill_constant_group_size(4, 0, poly_offsets);
|
||||
blender::offset_indices::fill_constant_group_size(4, 0, face_offsets);
|
||||
|
||||
mesh->vert_positions_for_write().copy_from(
|
||||
Span(reinterpret_cast<float3 *>(qrd.out_verts), qrd.out_totverts));
|
||||
@@ -226,14 +226,14 @@ static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set
|
||||
Mesh *mesh = BKE_mesh_new_nomain(
|
||||
vertices.size(), 0, quads.size() + tris.size(), quads.size() * 4 + tris.size() * 3);
|
||||
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||
MutableSpan<int> poly_offsets = mesh->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
|
||||
MutableSpan<int> mesh_corner_verts = mesh->corner_verts_for_write();
|
||||
|
||||
const int triangle_loop_start = quads.size() * 4;
|
||||
if (!poly_offsets.is_empty()) {
|
||||
blender::offset_indices::fill_constant_group_size(4, 0, poly_offsets.take_front(quads.size()));
|
||||
if (!face_offsets.is_empty()) {
|
||||
blender::offset_indices::fill_constant_group_size(4, 0, face_offsets.take_front(quads.size()));
|
||||
blender::offset_indices::fill_constant_group_size(
|
||||
3, triangle_loop_start, poly_offsets.drop_front(quads.size()));
|
||||
3, triangle_loop_start, face_offsets.drop_front(quads.size()));
|
||||
}
|
||||
|
||||
for (const int i : vert_positions.index_range()) {
|
||||
@@ -318,7 +318,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
|
||||
const AttributeAccessor src_attributes = source->attributes();
|
||||
MutableAttributeAccessor dst_attributes = target->attributes_for_write();
|
||||
const Span<float3> target_positions = target->vert_positions();
|
||||
const OffsetIndices target_polys = target->polys();
|
||||
const OffsetIndices target_polys = target->faces();
|
||||
const Span<int> target_corner_verts = target->corner_verts();
|
||||
|
||||
const VArray src_face_sets = *src_attributes.lookup<int>(".sculpt_face_set", ATTR_DOMAIN_FACE);
|
||||
@@ -334,27 +334,28 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
|
||||
const VArraySpan<int> src(src_face_sets);
|
||||
MutableSpan<int> dst = dst_face_sets.span;
|
||||
|
||||
const blender::Span<int> looptri_polys = source->looptri_polys();
|
||||
const blender::Span<int> looptri_faces = source->looptri_faces();
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
|
||||
|
||||
blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
const float3 from_co = mesh::poly_center_calc(target_positions,
|
||||
target_corner_verts.slice(target_polys[i]));
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
if (nearest.index != -1) {
|
||||
dst[i] = src[looptri_polys[nearest.index]];
|
||||
}
|
||||
else {
|
||||
dst[i] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
blender::threading::parallel_for(
|
||||
IndexRange(target->faces_num), 2048, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
const float3 from_co = mesh::face_center_calc(
|
||||
target_positions, target_corner_verts.slice(target_polys[i]));
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
if (nearest.index != -1) {
|
||||
dst[i] = src[looptri_faces[nearest.index]];
|
||||
}
|
||||
else {
|
||||
dst[i] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
dst_face_sets.finish();
|
||||
}
|
||||
|
||||
@@ -65,9 +65,9 @@ static void free_bvh_cache(MeshRuntime &mesh_runtime)
|
||||
static void reset_normals(MeshRuntime &mesh_runtime)
|
||||
{
|
||||
mesh_runtime.vert_normals.clear_and_shrink();
|
||||
mesh_runtime.poly_normals.clear_and_shrink();
|
||||
mesh_runtime.face_normals.clear_and_shrink();
|
||||
mesh_runtime.vert_normals_dirty = true;
|
||||
mesh_runtime.poly_normals_dirty = true;
|
||||
mesh_runtime.face_normals_dirty = true;
|
||||
}
|
||||
|
||||
static void free_batch_cache(MeshRuntime &mesh_runtime)
|
||||
@@ -187,38 +187,38 @@ blender::Span<MLoopTri> Mesh::looptris() const
|
||||
{
|
||||
this->runtime->looptris_cache.ensure([&](blender::Array<MLoopTri> &r_data) {
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const blender::OffsetIndices polys = this->polys();
|
||||
const blender::OffsetIndices faces = this->faces();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
|
||||
r_data.reinitialize(poly_to_tri_count(polys.size(), corner_verts.size()));
|
||||
r_data.reinitialize(poly_to_tri_count(faces.size(), corner_verts.size()));
|
||||
|
||||
if (BKE_mesh_poly_normals_are_dirty(this)) {
|
||||
blender::bke::mesh::looptris_calc(positions, polys, corner_verts, r_data);
|
||||
if (BKE_mesh_face_normals_are_dirty(this)) {
|
||||
blender::bke::mesh::looptris_calc(positions, faces, corner_verts, r_data);
|
||||
}
|
||||
else {
|
||||
blender::bke::mesh::looptris_calc_with_normals(
|
||||
positions, polys, corner_verts, this->poly_normals(), r_data);
|
||||
positions, faces, corner_verts, this->face_normals(), r_data);
|
||||
}
|
||||
});
|
||||
|
||||
return this->runtime->looptris_cache.data();
|
||||
}
|
||||
|
||||
blender::Span<int> Mesh::looptri_polys() const
|
||||
blender::Span<int> Mesh::looptri_faces() const
|
||||
{
|
||||
using namespace blender;
|
||||
this->runtime->looptri_polys_cache.ensure([&](blender::Array<int> &r_data) {
|
||||
const OffsetIndices polys = this->polys();
|
||||
r_data.reinitialize(poly_to_tri_count(polys.size(), this->totloop));
|
||||
bke::mesh::looptris_calc_poly_indices(polys, r_data);
|
||||
this->runtime->looptri_faces_cache.ensure([&](blender::Array<int> &r_data) {
|
||||
const OffsetIndices faces = this->faces();
|
||||
r_data.reinitialize(poly_to_tri_count(faces.size(), this->totloop));
|
||||
bke::mesh::looptris_calc_face_indices(faces, r_data);
|
||||
});
|
||||
return this->runtime->looptri_polys_cache.data();
|
||||
return this->runtime->looptri_faces_cache.data();
|
||||
}
|
||||
|
||||
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
|
||||
{
|
||||
/* Allow returning the size without calculating the cache. */
|
||||
return poly_to_tri_count(mesh->totpoly, mesh->totloop);
|
||||
return poly_to_tri_count(mesh->faces_num, mesh->totloop);
|
||||
}
|
||||
|
||||
const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
|
||||
@@ -226,9 +226,9 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
|
||||
return mesh->looptris().data();
|
||||
}
|
||||
|
||||
const int *BKE_mesh_runtime_looptri_polys_ensure(const Mesh *mesh)
|
||||
const int *BKE_mesh_runtime_looptri_faces_ensure(const Mesh *mesh)
|
||||
{
|
||||
return mesh->looptri_polys().data();
|
||||
return mesh->looptri_faces().data();
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
|
||||
@@ -281,7 +281,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
||||
mesh->runtime->loose_verts_cache.tag_dirty();
|
||||
mesh->runtime->verts_no_face_cache.tag_dirty();
|
||||
mesh->runtime->looptris_cache.tag_dirty();
|
||||
mesh->runtime->looptri_polys_cache.tag_dirty();
|
||||
mesh->runtime->looptri_faces_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
if (mesh->runtime->shrinkwrap_data) {
|
||||
@@ -324,13 +324,13 @@ void BKE_mesh_tag_edges_split(Mesh *mesh)
|
||||
void BKE_mesh_tag_face_winding_changed(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
mesh->runtime->face_normals_dirty = true;
|
||||
}
|
||||
|
||||
void BKE_mesh_tag_positions_changed(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
mesh->runtime->face_normals_dirty = true;
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
mesh->runtime->looptris_cache.tag_dirty();
|
||||
mesh->runtime->bounds_cache.tag_dirty();
|
||||
@@ -402,7 +402,7 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
|
||||
|
||||
MutableSpan<float3> positions = me_eval->vert_positions_for_write();
|
||||
MutableSpan<blender::int2> edges = me_eval->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = me_eval->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = me_eval->face_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = me_eval->corner_verts_for_write();
|
||||
MutableSpan<int> corner_edges = me_eval->corner_edges_for_write();
|
||||
|
||||
@@ -414,7 +414,7 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
|
||||
&me_eval->ldata,
|
||||
me_eval->totloop,
|
||||
&me_eval->pdata,
|
||||
me_eval->totpoly,
|
||||
me_eval->faces_num,
|
||||
false, /* setting mask here isn't useful, gives false positives */
|
||||
do_verbose,
|
||||
do_fixes,
|
||||
@@ -426,13 +426,13 @@ bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
static_cast<MFace *>(CustomData_get_layer_for_write(
|
||||
&me_eval->fdata, CD_MFACE, me_eval->totface)),
|
||||
me_eval->totface,
|
||||
&me_eval->fdata_legacy, CD_MFACE, me_eval->totface_legacy)),
|
||||
me_eval->totface_legacy,
|
||||
corner_verts.data(),
|
||||
corner_edges.data(),
|
||||
corner_verts.size(),
|
||||
poly_offsets.data(),
|
||||
me_eval->totpoly,
|
||||
face_offsets.data(),
|
||||
me_eval->faces_num,
|
||||
me_eval->deform_verts_for_write().data(),
|
||||
do_verbose,
|
||||
do_fixes,
|
||||
|
||||
@@ -127,7 +127,7 @@ void sample_corner_attribute(const Span<MLoopTri> looptris,
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sample_face_attribute(const Span<int> looptri_polys,
|
||||
void sample_face_attribute(const Span<int> looptri_faces,
|
||||
const Span<int> looptri_indices,
|
||||
const VArray<T> &src,
|
||||
const IndexMask &mask,
|
||||
@@ -135,12 +135,12 @@ void sample_face_attribute(const Span<int> looptri_polys,
|
||||
{
|
||||
mask.foreach_index([&](const int i) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
const int poly_index = looptri_polys[looptri_index];
|
||||
dst[i] = src[poly_index];
|
||||
const int face_index = looptri_faces[looptri_index];
|
||||
dst[i] = src[face_index];
|
||||
});
|
||||
}
|
||||
|
||||
void sample_face_attribute(const Span<int> looptri_polys,
|
||||
void sample_face_attribute(const Span<int> looptri_faces,
|
||||
const Span<int> looptri_indices,
|
||||
const GVArray &src,
|
||||
const IndexMask &mask,
|
||||
@@ -151,7 +151,7 @@ void sample_face_attribute(const Span<int> looptri_polys,
|
||||
const CPPType &type = src.type();
|
||||
attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
sample_face_attribute<T>(looptri_polys, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
|
||||
sample_face_attribute<T>(looptri_faces, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -40,44 +40,44 @@ using blender::float2;
|
||||
struct BKEMeshToTangent {
|
||||
uint GetNumFaces()
|
||||
{
|
||||
return uint(num_polys);
|
||||
return uint(num_faces);
|
||||
}
|
||||
|
||||
uint GetNumVerticesOfFace(const uint face_num)
|
||||
{
|
||||
return uint(polys[face_num].size());
|
||||
return uint(faces[face_num].size());
|
||||
}
|
||||
|
||||
mikk::float3 GetPosition(const uint face_num, const uint vert_num)
|
||||
{
|
||||
const uint loop_idx = uint(polys[face_num].start()) + vert_num;
|
||||
const uint loop_idx = uint(faces[face_num].start()) + vert_num;
|
||||
return mikk::float3(positions[corner_verts[loop_idx]]);
|
||||
}
|
||||
|
||||
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
|
||||
{
|
||||
const float *uv = luvs[uint(polys[face_num].start()) + vert_num];
|
||||
const float *uv = luvs[uint(faces[face_num].start()) + vert_num];
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
}
|
||||
|
||||
mikk::float3 GetNormal(const uint face_num, const uint vert_num)
|
||||
{
|
||||
return mikk::float3(loop_normals[uint(polys[face_num].start()) + vert_num]);
|
||||
return mikk::float3(loop_normals[uint(faces[face_num].start()) + vert_num]);
|
||||
}
|
||||
|
||||
void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation)
|
||||
{
|
||||
float *p_res = tangents[uint(polys[face_num].start()) + vert_num];
|
||||
float *p_res = tangents[uint(faces[face_num].start()) + vert_num];
|
||||
copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
blender::OffsetIndices<int> polys; /* faces */
|
||||
blender::OffsetIndices<int> faces; /* faces */
|
||||
const int *corner_verts; /* faces vertices */
|
||||
const float (*positions)[3]; /* vertices */
|
||||
const float (*luvs)[2]; /* texture coordinates */
|
||||
const float (*loop_normals)[3]; /* loops' normals */
|
||||
float (*tangents)[4]; /* output tangents */
|
||||
int num_polys; /* number of polygons */
|
||||
int num_faces; /* number of polygons */
|
||||
};
|
||||
|
||||
void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
|
||||
@@ -87,24 +87,24 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*loop_uvs)[2],
|
||||
const int /*numLoops*/,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
ReportList *reports)
|
||||
{
|
||||
/* Compute Mikktspace's tangent normals. */
|
||||
BKEMeshToTangent mesh_to_tangent;
|
||||
mesh_to_tangent.polys = polys;
|
||||
mesh_to_tangent.faces = faces;
|
||||
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;
|
||||
mesh_to_tangent.tangents = r_looptangent;
|
||||
mesh_to_tangent.num_polys = int(polys.size());
|
||||
mesh_to_tangent.num_faces = int(faces.size());
|
||||
|
||||
mikk::Mikktspace<BKEMeshToTangent> mikk(mesh_to_tangent);
|
||||
|
||||
/* First check we do have a tris/quads only mesh. */
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
if (polys[i].size() > 4) {
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
if (faces[i].size() > 4) {
|
||||
BKE_report(
|
||||
reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting");
|
||||
return;
|
||||
@@ -152,7 +152,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
|
||||
loop_normals,
|
||||
reinterpret_cast<const float(*)[2]>(uv_map.data()),
|
||||
mesh->totloop,
|
||||
mesh->polys(),
|
||||
mesh->faces(),
|
||||
reports);
|
||||
}
|
||||
|
||||
@@ -179,8 +179,8 @@ struct SGLSLMeshToTangent {
|
||||
{
|
||||
#ifdef USE_LOOPTRI_DETECT_QUADS
|
||||
if (face_as_quad_map) {
|
||||
const int poly_index = looptri_polys[face_as_quad_map[face_num]];
|
||||
if (polys[poly_index].size() == 4) {
|
||||
const int face_index = looptri_faces[face_as_quad_map[face_num]];
|
||||
if (faces[face_index].size() == 4) {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -191,20 +191,20 @@ struct SGLSLMeshToTangent {
|
||||
#endif
|
||||
}
|
||||
|
||||
uint GetLoop(const uint face_num, const uint vert_num, MLoopTri <, int &poly_index)
|
||||
uint GetLoop(const uint face_num, const uint vert_num, MLoopTri <, int &face_index)
|
||||
{
|
||||
#ifdef USE_LOOPTRI_DETECT_QUADS
|
||||
if (face_as_quad_map) {
|
||||
lt = looptri[face_as_quad_map[face_num]];
|
||||
poly_index = looptri_polys[face_as_quad_map[face_num]];
|
||||
if (polys[poly_index].size() == 4) {
|
||||
return uint(polys[poly_index][vert_num]);
|
||||
face_index = looptri_faces[face_as_quad_map[face_num]];
|
||||
if (faces[face_index].size() == 4) {
|
||||
return uint(faces[face_index][vert_num]);
|
||||
}
|
||||
/* fall through to regular triangle */
|
||||
}
|
||||
else {
|
||||
lt = looptri[face_num];
|
||||
poly_index = looptri_polys[face_num];
|
||||
face_index = looptri_faces[face_num];
|
||||
}
|
||||
#else
|
||||
lt = &looptri[face_num];
|
||||
@@ -215,16 +215,16 @@ struct SGLSLMeshToTangent {
|
||||
mikk::float3 GetPosition(const uint face_num, const uint vert_num)
|
||||
{
|
||||
MLoopTri lt;
|
||||
int poly_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
|
||||
int face_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, face_index);
|
||||
return mikk::float3(positions[corner_verts[loop_index]]);
|
||||
}
|
||||
|
||||
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
|
||||
{
|
||||
MLoopTri lt;
|
||||
int poly_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
|
||||
int face_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, face_index);
|
||||
if (mloopuv != nullptr) {
|
||||
const float2 &uv = mloopuv[loop_index];
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
@@ -238,24 +238,24 @@ struct SGLSLMeshToTangent {
|
||||
mikk::float3 GetNormal(const uint face_num, const uint vert_num)
|
||||
{
|
||||
MLoopTri lt;
|
||||
int poly_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
|
||||
int face_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, face_index);
|
||||
if (precomputedLoopNormals) {
|
||||
return mikk::float3(precomputedLoopNormals[loop_index]);
|
||||
}
|
||||
if (sharp_faces && sharp_faces[poly_index]) { /* flat */
|
||||
if (sharp_faces && sharp_faces[face_index]) { /* flat */
|
||||
if (precomputedFaceNormals) {
|
||||
return mikk::float3(precomputedFaceNormals[poly_index]);
|
||||
return mikk::float3(precomputedFaceNormals[face_index]);
|
||||
}
|
||||
#ifdef USE_LOOPTRI_DETECT_QUADS
|
||||
const blender::IndexRange poly = polys[poly_index];
|
||||
const blender::IndexRange face = faces[face_index];
|
||||
float normal[3];
|
||||
if (poly.size() == 4) {
|
||||
if (face.size() == 4) {
|
||||
normal_quad_v3(normal,
|
||||
positions[corner_verts[poly[0]]],
|
||||
positions[corner_verts[poly[1]]],
|
||||
positions[corner_verts[poly[2]]],
|
||||
positions[corner_verts[poly[3]]]);
|
||||
positions[corner_verts[face[0]]],
|
||||
positions[corner_verts[face[1]]],
|
||||
positions[corner_verts[face[2]]],
|
||||
positions[corner_verts[face[3]]]);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -273,8 +273,8 @@ struct SGLSLMeshToTangent {
|
||||
void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation)
|
||||
{
|
||||
MLoopTri lt;
|
||||
int poly_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, poly_index);
|
||||
int face_index;
|
||||
uint loop_index = GetLoop(face_num, vert_num, lt, face_index);
|
||||
|
||||
copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
|
||||
}
|
||||
@@ -282,9 +282,9 @@ struct SGLSLMeshToTangent {
|
||||
const float (*precomputedFaceNormals)[3];
|
||||
const float (*precomputedLoopNormals)[3];
|
||||
const MLoopTri *looptri;
|
||||
const int *looptri_polys;
|
||||
const int *looptri_faces;
|
||||
const float2 *mloopuv; /* texture coordinates */
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
const int *corner_verts; /* indices */
|
||||
const float (*positions)[3]; /* vertex coordinates */
|
||||
const float (*vert_normals)[3];
|
||||
@@ -398,10 +398,10 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const int *corner_verts,
|
||||
const MLoopTri *looptri,
|
||||
const int *looptri_polys,
|
||||
const int *looptri_faces,
|
||||
const uint looptri_len,
|
||||
const bool *sharp_faces,
|
||||
|
||||
@@ -410,7 +410,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
const float (*vert_normals)[3],
|
||||
const float (*poly_normals)[3],
|
||||
const float (*face_normals)[3],
|
||||
const float (*loop_normals)[3],
|
||||
const float (*vert_orco)[3],
|
||||
/* result */
|
||||
@@ -467,7 +467,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
int *face_as_quad_map = nullptr;
|
||||
|
||||
/* map faces to quads */
|
||||
if (looptri_len != uint(polys.size())) {
|
||||
if (looptri_len != uint(faces.size())) {
|
||||
/* Over allocate, since we don't know how many ngon or quads we have. */
|
||||
|
||||
/* map fake face index to looptri */
|
||||
@@ -476,7 +476,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
for (k = 0, j = 0; j < int(looptri_len); k++, j++) {
|
||||
face_as_quad_map[k] = j;
|
||||
/* step over all quads */
|
||||
if (polys[looptri_polys[j]].size() == 4) {
|
||||
if (faces[looptri_faces[j]].size() == 4) {
|
||||
j++; /* skips the nest looptri */
|
||||
}
|
||||
}
|
||||
@@ -506,15 +506,15 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
||||
#endif
|
||||
mesh2tangent->positions = vert_positions;
|
||||
mesh2tangent->vert_normals = vert_normals;
|
||||
mesh2tangent->polys = polys;
|
||||
mesh2tangent->faces = faces;
|
||||
mesh2tangent->corner_verts = corner_verts;
|
||||
mesh2tangent->looptri = looptri;
|
||||
mesh2tangent->looptri_polys = looptri_polys;
|
||||
mesh2tangent->looptri_faces = looptri_faces;
|
||||
mesh2tangent->sharp_faces = sharp_faces;
|
||||
/* NOTE: we assume we do have tessellated loop normals at this point
|
||||
* (in case it is object-enabled), have to check this is valid. */
|
||||
mesh2tangent->precomputedLoopNormals = loop_normals;
|
||||
mesh2tangent->precomputedFaceNormals = poly_normals;
|
||||
mesh2tangent->precomputedFaceNormals = face_normals;
|
||||
|
||||
mesh2tangent->orco = nullptr;
|
||||
mesh2tangent->mloopuv = static_cast<const float2 *>(CustomData_get_layer_named(
|
||||
@@ -591,10 +591,10 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
||||
short tangent_mask = 0;
|
||||
BKE_mesh_calc_loop_tangent_ex(
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->vert_positions().data()),
|
||||
me_eval->polys(),
|
||||
me_eval->faces(),
|
||||
me_eval->corner_verts().data(),
|
||||
looptris.data(),
|
||||
me_eval->looptri_polys().data(),
|
||||
me_eval->looptri_faces().data(),
|
||||
uint(looptris.size()),
|
||||
static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&me_eval->pdata, CD_PROP_BOOL, "sharp_face")),
|
||||
@@ -603,7 +603,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->vert_normals().data()),
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->poly_normals().data()),
|
||||
reinterpret_cast<const float(*)[3]>(me_eval->face_normals().data()),
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
|
||||
/* may be nullptr */
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* This file contains code for polygon tessellation
|
||||
* This file contains code for face tessellation
|
||||
* (creating triangles from polygons).
|
||||
*
|
||||
* \see bmesh_mesh_tessellate.c for the #BMesh equivalent of this file.
|
||||
@@ -37,16 +37,16 @@ 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<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<float3> positions,
|
||||
uint poly_index,
|
||||
uint face_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p,
|
||||
const bool face_normal,
|
||||
const float normal_precalc[3])
|
||||
{
|
||||
const uint mp_loopstart = uint(polys[poly_index].start());
|
||||
const uint mp_totloop = uint(polys[poly_index].size());
|
||||
const uint mp_loopstart = uint(faces[face_index].start());
|
||||
const uint mp_totloop = uint(faces[face_index].size());
|
||||
|
||||
auto create_tri = [&](uint i1, uint i2, uint i3) {
|
||||
mlt->tri[0] = mp_loopstart + i1;
|
||||
@@ -134,54 +134,54 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<int> corner_vert
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face(const Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<float3> positions,
|
||||
uint poly_index,
|
||||
uint face_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p)
|
||||
{
|
||||
mesh_calc_tessellation_for_face_impl(
|
||||
corner_verts, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr);
|
||||
corner_verts, faces, positions, face_index, mlt, pf_arena_p, false, nullptr);
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face_with_normal(const Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<float3> positions,
|
||||
uint poly_index,
|
||||
uint face_index,
|
||||
MLoopTri *mlt,
|
||||
MemArena **pf_arena_p,
|
||||
const float normal_precalc[3])
|
||||
{
|
||||
mesh_calc_tessellation_for_face_impl(
|
||||
corner_verts, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc);
|
||||
corner_verts, faces, positions, face_index, mlt, pf_arena_p, true, normal_precalc);
|
||||
}
|
||||
|
||||
static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<float3> positions,
|
||||
MLoopTri *mlooptri,
|
||||
const float (*poly_normals)[3])
|
||||
const float (*face_normals)[3])
|
||||
{
|
||||
MemArena *pf_arena = nullptr;
|
||||
uint looptri_i = 0;
|
||||
|
||||
if (poly_normals != nullptr) {
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
if (face_normals != nullptr) {
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
mesh_calc_tessellation_for_face_with_normal(corner_verts,
|
||||
polys,
|
||||
faces,
|
||||
positions,
|
||||
uint(i),
|
||||
&mlooptri[looptri_i],
|
||||
&pf_arena,
|
||||
poly_normals[i]);
|
||||
looptri_i += uint(polys[i].size() - 2);
|
||||
face_normals[i]);
|
||||
looptri_i += uint(faces[i].size() - 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
mesh_calc_tessellation_for_face(
|
||||
corner_verts, polys, positions, uint(i), &mlooptri[looptri_i], &pf_arena);
|
||||
looptri_i += uint(polys[i].size() - 2);
|
||||
corner_verts, faces, positions, uint(i), &mlooptri[looptri_i], &pf_arena);
|
||||
looptri_i += uint(faces[i].size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,19 +189,19 @@ static void mesh_recalc_looptri__single_threaded(const Span<int> corner_verts,
|
||||
BLI_memarena_free(pf_arena);
|
||||
pf_arena = nullptr;
|
||||
}
|
||||
BLI_assert(looptri_i == uint(poly_to_tri_count(int(polys.size()), int(corner_verts.size()))));
|
||||
BLI_assert(looptri_i == uint(poly_to_tri_count(int(faces.size()), int(corner_verts.size()))));
|
||||
}
|
||||
|
||||
struct TessellationUserData {
|
||||
Span<int> corner_verts;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
Span<float3> positions;
|
||||
|
||||
/** Output array. */
|
||||
MutableSpan<MLoopTri> mlooptri;
|
||||
|
||||
/** Optional pre-calculated polygon normals array. */
|
||||
const float (*poly_normals)[3];
|
||||
/** Optional pre-calculated face normals array. */
|
||||
const float (*face_normals)[3];
|
||||
};
|
||||
|
||||
struct TessellationUserTLS {
|
||||
@@ -214,9 +214,9 @@ 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 looptri_i = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
const int looptri_i = poly_to_tri_count(index, int(data->faces[index].start()));
|
||||
mesh_calc_tessellation_for_face_impl(data->corner_verts,
|
||||
data->polys,
|
||||
data->faces,
|
||||
data->positions,
|
||||
uint(index),
|
||||
&data->mlooptri[looptri_i],
|
||||
@@ -231,15 +231,15 @@ 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 looptri_i = poly_to_tri_count(index, int(data->polys[index].start()));
|
||||
const int looptri_i = poly_to_tri_count(index, int(data->faces[index].start()));
|
||||
mesh_calc_tessellation_for_face_impl(data->corner_verts,
|
||||
data->polys,
|
||||
data->faces,
|
||||
data->positions,
|
||||
uint(index),
|
||||
&data->mlooptri[looptri_i],
|
||||
&tls_data->pf_arena,
|
||||
true,
|
||||
data->poly_normals[index]);
|
||||
data->face_normals[index]);
|
||||
}
|
||||
|
||||
static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*userdata*/,
|
||||
@@ -252,27 +252,27 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*use
|
||||
}
|
||||
|
||||
static void looptris_calc_all(const Span<float3> positions,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
MutableSpan<MLoopTri> looptris)
|
||||
{
|
||||
if (corner_verts.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
|
||||
mesh_recalc_looptri__single_threaded(corner_verts,
|
||||
polys,
|
||||
faces,
|
||||
positions,
|
||||
looptris.data(),
|
||||
reinterpret_cast<const float(*)[3]>(poly_normals.data()));
|
||||
reinterpret_cast<const float(*)[3]>(face_normals.data()));
|
||||
return;
|
||||
}
|
||||
TessellationUserTLS tls_data_dummy = {nullptr};
|
||||
|
||||
TessellationUserData data{};
|
||||
data.corner_verts = corner_verts;
|
||||
data.polys = polys;
|
||||
data.faces = faces;
|
||||
data.positions = positions;
|
||||
data.mlooptri = looptris;
|
||||
data.poly_normals = reinterpret_cast<const float(*)[3]>(poly_normals.data());
|
||||
data.face_normals = reinterpret_cast<const float(*)[3]>(face_normals.data());
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
@@ -283,41 +283,41 @@ static void looptris_calc_all(const Span<float3> positions,
|
||||
settings.func_free = mesh_calc_tessellation_for_face_free_fn;
|
||||
|
||||
BLI_task_parallel_range(0,
|
||||
int(polys.size()),
|
||||
int(faces.size()),
|
||||
&data,
|
||||
data.poly_normals ? mesh_calc_tessellation_for_face_with_normal_fn :
|
||||
data.face_normals ? mesh_calc_tessellation_for_face_with_normal_fn :
|
||||
mesh_calc_tessellation_for_face_fn,
|
||||
&settings);
|
||||
}
|
||||
|
||||
void looptris_calc(const Span<float3> vert_positions,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
MutableSpan<MLoopTri> looptris)
|
||||
{
|
||||
looptris_calc_all(vert_positions, polys, corner_verts, {}, looptris);
|
||||
looptris_calc_all(vert_positions, faces, corner_verts, {}, looptris);
|
||||
}
|
||||
|
||||
void looptris_calc_poly_indices(const OffsetIndices<int> polys, MutableSpan<int> looptri_polys)
|
||||
void looptris_calc_face_indices(const OffsetIndices<int> faces, MutableSpan<int> looptri_faces)
|
||||
{
|
||||
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int64_t i : range) {
|
||||
const IndexRange poly = polys[i];
|
||||
const int start = poly_to_tri_count(int(i), int(poly.start()));
|
||||
const int num = ME_POLY_TRI_TOT(int(poly.size()));
|
||||
looptri_polys.slice(start, num).fill(int(i));
|
||||
const IndexRange face = faces[i];
|
||||
const int start = poly_to_tri_count(int(i), int(face.start()));
|
||||
const int num = ME_FACE_TRI_TOT(int(face.size()));
|
||||
looptri_faces.slice(start, num).fill(int(i));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void looptris_calc_with_normals(const Span<float3> vert_positions,
|
||||
const OffsetIndices<int> polys,
|
||||
const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<float3> face_normals,
|
||||
MutableSpan<MLoopTri> looptris)
|
||||
{
|
||||
BLI_assert(!poly_normals.is_empty() || polys.size() == 0);
|
||||
looptris_calc_all(vert_positions, polys, corner_verts, poly_normals, looptris);
|
||||
BLI_assert(!face_normals.is_empty() || faces.size() == 0);
|
||||
looptris_calc_all(vert_positions, faces, corner_verts, face_normals, looptris);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -325,16 +325,16 @@ void looptris_calc_with_normals(const Span<float3> vert_positions,
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
void BKE_mesh_recalc_looptri(const int *corner_verts,
|
||||
const int *poly_offsets,
|
||||
const int *face_offsets,
|
||||
const float (*vert_positions)[3],
|
||||
int totvert,
|
||||
int totloop,
|
||||
int totpoly,
|
||||
int faces_num,
|
||||
MLoopTri *mlooptri)
|
||||
{
|
||||
blender::bke::mesh::looptris_calc(
|
||||
{reinterpret_cast<const blender::float3 *>(vert_positions), totvert},
|
||||
blender::Span(poly_offsets, totpoly + 1),
|
||||
blender::Span(face_offsets, faces_num + 1),
|
||||
{corner_verts, totloop},
|
||||
{mlooptri, poly_to_tri_count(totpoly, totloop)});
|
||||
{mlooptri, poly_to_tri_count(faces_num, totloop)});
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ using blender::Span;
|
||||
|
||||
static CLG_LogRef LOG = {"bke.mesh"};
|
||||
|
||||
void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove);
|
||||
void strip_loose_facesloops(Mesh *me, blender::BitSpan faces_to_remove);
|
||||
void mesh_strip_edges(Mesh *me);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -60,8 +60,8 @@ struct SortFace {
|
||||
uint index;
|
||||
};
|
||||
|
||||
/* Used to detect polys (faces) using exactly the same vertices. */
|
||||
/* Used to detect loops used by no (disjoint) or more than one (intersect) polys. */
|
||||
/* Used to detect faces using exactly the same vertices. */
|
||||
/* Used to detect loops used by no (disjoint) or more than one (intersect) faces. */
|
||||
struct SortPoly {
|
||||
int *verts;
|
||||
int numverts;
|
||||
@@ -160,11 +160,11 @@ static int search_poly_cmp(const void *v1, const void *v2)
|
||||
const SortPoly *sp1 = static_cast<const SortPoly *>(v1);
|
||||
const SortPoly *sp2 = static_cast<const SortPoly *>(v2);
|
||||
|
||||
/* Reject all invalid polys at end of list! */
|
||||
/* Reject all invalid faces at end of list! */
|
||||
if (sp1->invalid || sp2->invalid) {
|
||||
return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1;
|
||||
}
|
||||
/* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */
|
||||
/* Else, sort on first non-equal verts (remember verts of valid faces are sorted). */
|
||||
const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts;
|
||||
for (int idx = 0; idx < max_idx; idx++) {
|
||||
const int v1_i = sp1->verts[idx];
|
||||
@@ -181,7 +181,7 @@ static int search_polyloop_cmp(const void *v1, const void *v2)
|
||||
const SortPoly *sp1 = static_cast<const SortPoly *>(v1);
|
||||
const SortPoly *sp2 = static_cast<const SortPoly *>(v2);
|
||||
|
||||
/* Reject all invalid polys at end of list! */
|
||||
/* Reject all invalid faces at end of list! */
|
||||
if (sp1->invalid || sp2->invalid) {
|
||||
return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1;
|
||||
}
|
||||
@@ -220,8 +220,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
int *corner_verts,
|
||||
int *corner_edges,
|
||||
uint totloop,
|
||||
int *poly_offsets,
|
||||
uint totpoly,
|
||||
int *face_offsets,
|
||||
uint faces_num,
|
||||
MDeformVert *dverts, /* assume totvert length */
|
||||
const bool do_verbose,
|
||||
const bool do_fixes,
|
||||
@@ -241,16 +241,16 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
free_flag.polyloops = do_fixes; \
|
||||
} \
|
||||
(void)0
|
||||
blender::BitVector<> polys_to_remove(totpoly);
|
||||
blender::BitVector<> faces_to_remove(faces_num);
|
||||
|
||||
blender::bke::AttributeWriter<int> material_indices =
|
||||
mesh->attributes_for_write().lookup_for_write<int>("material_index");
|
||||
blender::MutableVArraySpan<int> material_indices_span(material_indices.varray);
|
||||
|
||||
#if 0
|
||||
const blender::OffsetIndices<int> polys({poly_offsets, totpoly + 1});
|
||||
for (const int i : polys.index_range()) {
|
||||
BLI_assert(polys[i].size() > 2);
|
||||
const blender::OffsetIndices<int> faces({face_offsets, faces_num + 1});
|
||||
for (const int i : faces.index_range()) {
|
||||
BLI_assert(faces[i].size() > 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -272,7 +272,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
struct {
|
||||
int edges : 1;
|
||||
int faces : 1;
|
||||
/* This regroups loops and polys! */
|
||||
/* This regroups loops and faces! */
|
||||
int polyloops : 1;
|
||||
int mselect : 1;
|
||||
};
|
||||
@@ -294,10 +294,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
free_flag.as_flag = 0;
|
||||
recalc_flag.as_flag = 0;
|
||||
|
||||
PRINT_MSG("verts(%u), edges(%u), loops(%u), polygons(%u)", totvert, totedge, totloop, totpoly);
|
||||
PRINT_MSG("verts(%u), edges(%u), loops(%u), polygons(%u)", totvert, totedge, totloop, faces_num);
|
||||
|
||||
if (totedge == 0 && totpoly != 0) {
|
||||
PRINT_ERR("\tLogical error, %u polygons and 0 edges", totpoly);
|
||||
if (totedge == 0 && faces_num != 0) {
|
||||
PRINT_ERR("\tLogical error, %u polygons and 0 edges", faces_num);
|
||||
recalc_flag.edges = do_fixes;
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
}
|
||||
|
||||
if (mfaces && !poly_offsets) {
|
||||
if (mfaces && !face_offsets) {
|
||||
#define REMOVE_FACE_TAG(_mf) \
|
||||
{ \
|
||||
_mf->v3 = 0; \
|
||||
@@ -511,7 +511,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
#undef CHECK_FACE_EDGE
|
||||
}
|
||||
|
||||
/* Checking loops and polys is a bit tricky, as they are quite intricate...
|
||||
/* Checking loops and faces is a bit tricky, as they are quite intricate...
|
||||
*
|
||||
* Polys must have:
|
||||
* - a valid loopstart value.
|
||||
@@ -519,23 +519,23 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
*
|
||||
* Loops must have:
|
||||
* - a valid v value.
|
||||
* - a valid e value (corresponding to the edge it defines with the next loop in poly).
|
||||
* - a valid e value (corresponding to the edge it defines with the next loop in face).
|
||||
*
|
||||
* Also, loops not used by polys can be discarded.
|
||||
* And "intersecting" loops (i.e. loops used by more than one poly) are invalid,
|
||||
* so be sure to leave at most one poly per loop!
|
||||
* Also, loops not used by faces can be discarded.
|
||||
* And "intersecting" loops (i.e. loops used by more than one face) are invalid,
|
||||
* so be sure to leave at most one face per loop!
|
||||
*/
|
||||
{
|
||||
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(mesh->totvert, __func__);
|
||||
|
||||
SortPoly *sort_polys = (SortPoly *)MEM_callocN(sizeof(SortPoly) * totpoly,
|
||||
SortPoly *sort_polys = (SortPoly *)MEM_callocN(sizeof(SortPoly) * faces_num,
|
||||
"mesh validate's sort_polys");
|
||||
SortPoly *prev_sp, *sp = sort_polys;
|
||||
int prev_end;
|
||||
|
||||
for (const int64_t i : blender::IndexRange(totpoly)) {
|
||||
const int poly_start = poly_offsets[i];
|
||||
const int poly_size = poly_offsets[i + 1] - poly_start;
|
||||
for (const int64_t i : blender::IndexRange(faces_num)) {
|
||||
const int poly_start = face_offsets[i];
|
||||
const int poly_size = face_offsets[i + 1] - poly_start;
|
||||
sp->index = i;
|
||||
|
||||
/* Material index, isolated from other tests here. While large indices are clamped,
|
||||
@@ -574,8 +574,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
sp->loopstart = poly_start;
|
||||
|
||||
/* 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. */
|
||||
* before we start checking each face, but several faces can use same vert,
|
||||
* so we have to ensure here all verts of current face are cleared. */
|
||||
for (j = 0; j < poly_size; j++) {
|
||||
const int vert = corner_verts[sp->loopstart + j];
|
||||
if (vert < totvert) {
|
||||
@@ -583,7 +583,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
}
|
||||
|
||||
/* Test all poly's loops' vert idx. */
|
||||
/* Test all face's loops' vert idx. */
|
||||
for (j = 0; j < poly_size; j++, v++) {
|
||||
const int vert = corner_verts[sp->loopstart + j];
|
||||
if (vert >= totvert) {
|
||||
@@ -606,7 +606,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Test all poly's loops. */
|
||||
/* Test all face's loops. */
|
||||
for (j = 0; j < poly_size; j++) {
|
||||
const int corner = sp->loopstart + j;
|
||||
const int vert = corner_verts[corner];
|
||||
@@ -669,7 +669,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
|
||||
if (!sp->invalid) {
|
||||
/* Needed for checking polys using same verts below. */
|
||||
/* Needed for checking faces using same verts below. */
|
||||
qsort(sp->verts, sp->numverts, sizeof(int), int_cmp);
|
||||
}
|
||||
}
|
||||
@@ -678,22 +678,22 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
|
||||
MEM_freeN(vert_tag);
|
||||
|
||||
/* Second check pass, testing polys using the same verts. */
|
||||
qsort(sort_polys, totpoly, sizeof(SortPoly), search_poly_cmp);
|
||||
/* Second check pass, testing faces using the same verts. */
|
||||
qsort(sort_polys, faces_num, sizeof(SortPoly), search_poly_cmp);
|
||||
sp = prev_sp = sort_polys;
|
||||
sp++;
|
||||
|
||||
for (i = 1; i < totpoly; i++, sp++) {
|
||||
for (i = 1; i < faces_num; i++, sp++) {
|
||||
int p1_nv = sp->numverts, p2_nv = prev_sp->numverts;
|
||||
const int *p1_v = sp->verts, *p2_v = prev_sp->verts;
|
||||
|
||||
if (sp->invalid) {
|
||||
/* Break, because all known invalid polys have been put at the end
|
||||
/* Break, because all known invalid faces have been put at the end
|
||||
* by qsort with search_poly_cmp. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Test same polys. */
|
||||
/* Test same faces. */
|
||||
if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
|
||||
if (do_verbose) {
|
||||
/* TODO: convert list to string */
|
||||
@@ -701,7 +701,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
for (j = 1; j < p1_nv; j++) {
|
||||
PRINT_ERR(", %d", p1_v[j]);
|
||||
}
|
||||
PRINT_ERR("), considering poly %u as invalid.", sp->index);
|
||||
PRINT_ERR("), considering face %u as invalid.", sp->index);
|
||||
}
|
||||
else {
|
||||
is_valid = false;
|
||||
@@ -713,28 +713,28 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
}
|
||||
|
||||
/* Third check pass, testing loops used by none or more than one poly. */
|
||||
qsort(sort_polys, totpoly, sizeof(SortPoly), search_polyloop_cmp);
|
||||
/* Third check pass, testing loops used by none or more than one face. */
|
||||
qsort(sort_polys, faces_num, sizeof(SortPoly), search_polyloop_cmp);
|
||||
sp = sort_polys;
|
||||
prev_sp = nullptr;
|
||||
prev_end = 0;
|
||||
for (i = 0; i < totpoly; i++, sp++) {
|
||||
for (i = 0; i < faces_num; i++, sp++) {
|
||||
/* Free this now, we don't need it anymore, and avoid us another loop! */
|
||||
if (sp->verts) {
|
||||
MEM_freeN(sp->verts);
|
||||
}
|
||||
|
||||
/* Note above prev_sp: in following code, we make sure it is always valid poly (or nullptr).
|
||||
/* Note above prev_sp: in following code, we make sure it is always valid face (or nullptr).
|
||||
*/
|
||||
if (sp->invalid) {
|
||||
if (do_fixes) {
|
||||
polys_to_remove[sp->index].set();
|
||||
faces_to_remove[sp->index].set();
|
||||
free_flag.polyloops = do_fixes;
|
||||
/* DO NOT REMOVE ITS LOOPS!!!
|
||||
* As already invalid polys are at the end of the SortPoly list, the loops they
|
||||
* As already invalid faces are at the end of the SortPoly list, the loops they
|
||||
* were the only users have already been tagged as "to remove" during previous
|
||||
* iterations, and we don't want to remove some loops that may be used by
|
||||
* another valid poly! */
|
||||
* another valid face! */
|
||||
}
|
||||
}
|
||||
/* Test loops users. */
|
||||
@@ -753,17 +753,17 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
/* Multi-used loops. */
|
||||
else if (prev_end > sp->loopstart) {
|
||||
PRINT_ERR("\tPolys %u and %u share loops from %d to %d, considering poly %u as invalid.",
|
||||
PRINT_ERR("\tPolys %u and %u share loops from %d to %d, considering face %u as invalid.",
|
||||
prev_sp->index,
|
||||
sp->index,
|
||||
sp->loopstart,
|
||||
prev_end,
|
||||
sp->index);
|
||||
if (do_fixes) {
|
||||
polys_to_remove[sp->index].set();
|
||||
faces_to_remove[sp->index].set();
|
||||
free_flag.polyloops = do_fixes;
|
||||
/* DO NOT REMOVE ITS LOOPS!!!
|
||||
* They might be used by some next, valid poly!
|
||||
* They might be used by some next, valid face!
|
||||
* Just not updating prev_end/prev_sp vars is enough to ensure the loops
|
||||
* effectively no more needed will be marked as "to be removed"! */
|
||||
}
|
||||
@@ -847,7 +847,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
}
|
||||
|
||||
if (free_flag.polyloops) {
|
||||
strip_loose_polysloops(mesh, polys_to_remove);
|
||||
strip_loose_facesloops(mesh, faces_to_remove);
|
||||
}
|
||||
|
||||
if (free_flag.edges) {
|
||||
@@ -883,7 +883,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
||||
tot_elem = mesh->totedge;
|
||||
break;
|
||||
case ME_FSEL:
|
||||
tot_elem = mesh->totpoly;
|
||||
tot_elem = mesh->faces_num;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1027,7 +1027,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
|
||||
CustomData *ldata,
|
||||
const uint totloop,
|
||||
CustomData *pdata,
|
||||
const uint totpoly,
|
||||
const uint faces_num,
|
||||
const bool check_meshmask,
|
||||
const bool do_verbose,
|
||||
const bool do_fixes,
|
||||
@@ -1047,7 +1047,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
|
||||
is_valid &= mesh_validate_customdata(
|
||||
ldata, mask.lmask, totloop, do_verbose, do_fixes, &is_change_l);
|
||||
is_valid &= mesh_validate_customdata(
|
||||
pdata, mask.pmask, totpoly, do_verbose, do_fixes, &is_change_p);
|
||||
pdata, mask.pmask, faces_num, do_verbose, do_fixes, &is_change_p);
|
||||
|
||||
const int tot_uvloop = CustomData_number_of_layers(ldata, CD_PROP_FLOAT2);
|
||||
if (tot_uvloop > MAX_MTFACE) {
|
||||
@@ -1088,14 +1088,14 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_
|
||||
&me->ldata,
|
||||
me->totloop,
|
||||
&me->pdata,
|
||||
me->totpoly,
|
||||
me->faces_num,
|
||||
cddata_check_mask,
|
||||
do_verbose,
|
||||
true,
|
||||
&changed);
|
||||
MutableSpan<float3> positions = me->vert_positions_for_write();
|
||||
MutableSpan<blender::int2> edges = me->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = me->face_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = me->corner_verts_for_write();
|
||||
MutableSpan<int> corner_edges = me->corner_edges_for_write();
|
||||
|
||||
@@ -1105,13 +1105,13 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_
|
||||
positions.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
(MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface),
|
||||
me->totface,
|
||||
(MFace *)CustomData_get_layer_for_write(&me->fdata_legacy, CD_MFACE, me->totface_legacy),
|
||||
me->totface_legacy,
|
||||
corner_verts.data(),
|
||||
corner_edges.data(),
|
||||
corner_verts.size(),
|
||||
poly_offsets.data(),
|
||||
me->totpoly,
|
||||
face_offsets.data(),
|
||||
me->faces_num,
|
||||
me->deform_verts_for_write().data(),
|
||||
do_verbose,
|
||||
true,
|
||||
@@ -1141,7 +1141,7 @@ bool BKE_mesh_is_valid(Mesh *me)
|
||||
&me->ldata,
|
||||
me->totloop,
|
||||
&me->pdata,
|
||||
me->totpoly,
|
||||
me->faces_num,
|
||||
false, /* setting mask here isn't useful, gives false positives */
|
||||
do_verbose,
|
||||
do_fixes,
|
||||
@@ -1149,7 +1149,7 @@ bool BKE_mesh_is_valid(Mesh *me)
|
||||
|
||||
MutableSpan<float3> positions = me->vert_positions_for_write();
|
||||
MutableSpan<blender::int2> edges = me->edges_for_write();
|
||||
MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = me->face_offsets_for_write();
|
||||
MutableSpan<int> corner_verts = me->corner_verts_for_write();
|
||||
MutableSpan<int> corner_edges = me->corner_edges_for_write();
|
||||
|
||||
@@ -1159,13 +1159,13 @@ bool BKE_mesh_is_valid(Mesh *me)
|
||||
positions.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
(MFace *)CustomData_get_layer_for_write(&me->fdata, CD_MFACE, me->totface),
|
||||
me->totface,
|
||||
(MFace *)CustomData_get_layer_for_write(&me->fdata_legacy, CD_MFACE, me->totface_legacy),
|
||||
me->totface_legacy,
|
||||
corner_verts.data(),
|
||||
corner_edges.data(),
|
||||
corner_verts.size(),
|
||||
poly_offsets.data(),
|
||||
me->totpoly,
|
||||
face_offsets.data(),
|
||||
me->faces_num,
|
||||
me->deform_verts_for_write().data(),
|
||||
do_verbose,
|
||||
do_fixes,
|
||||
@@ -1207,29 +1207,29 @@ bool BKE_mesh_validate_material_indices(Mesh *me)
|
||||
/** \name Mesh Stripping (removing invalid data)
|
||||
* \{ */
|
||||
|
||||
void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove)
|
||||
void strip_loose_facesloops(Mesh *me, blender::BitSpan faces_to_remove)
|
||||
{
|
||||
MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
|
||||
MutableSpan<int> face_offsets = me->face_offsets_for_write();
|
||||
MutableSpan<int> corner_edges = me->corner_edges_for_write();
|
||||
|
||||
int a, b;
|
||||
/* New loops idx! */
|
||||
int *new_idx = (int *)MEM_mallocN(sizeof(int) * me->totloop, __func__);
|
||||
|
||||
for (a = b = 0; a < me->totpoly; a++) {
|
||||
for (a = b = 0; a < me->faces_num; a++) {
|
||||
bool invalid = false;
|
||||
int start = poly_offsets[a];
|
||||
int size = poly_offsets[a + 1] - start;
|
||||
int start = face_offsets[a];
|
||||
int size = face_offsets[a + 1] - start;
|
||||
int stop = start + size;
|
||||
|
||||
if (polys_to_remove[a]) {
|
||||
if (faces_to_remove[a]) {
|
||||
invalid = true;
|
||||
}
|
||||
else if (stop > me->totloop || stop < start || size < 0) {
|
||||
invalid = true;
|
||||
}
|
||||
else {
|
||||
/* If one of the poly's loops is invalid, the whole poly is invalid! */
|
||||
/* If one of the face's loops is invalid, the whole face is invalid! */
|
||||
if (corner_edges.slice(start, size).as_span().contains(INVALID_LOOP_EDGE_MARKER)) {
|
||||
invalid = true;
|
||||
}
|
||||
@@ -1237,7 +1237,7 @@ void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove)
|
||||
|
||||
if (size >= 3 && !invalid) {
|
||||
if (a != b) {
|
||||
poly_offsets[b] = poly_offsets[a];
|
||||
face_offsets[b] = face_offsets[a];
|
||||
CustomData_copy_data(&me->pdata, &me->pdata, a, b, 1);
|
||||
}
|
||||
b++;
|
||||
@@ -1245,7 +1245,7 @@ void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove)
|
||||
}
|
||||
if (a != b) {
|
||||
CustomData_free_elem(&me->pdata, b, a - b);
|
||||
me->totpoly = b;
|
||||
me->faces_num = b;
|
||||
}
|
||||
|
||||
/* And now, get rid of invalid loops. */
|
||||
@@ -1259,7 +1259,7 @@ void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove)
|
||||
b++;
|
||||
}
|
||||
else {
|
||||
/* XXX Theoretically, we should be able to not do this, as no remaining poly
|
||||
/* XXX Theoretically, we should be able to not do this, as no remaining face
|
||||
* should use any stripped loop. But for security's sake... */
|
||||
new_idx[a] = -a;
|
||||
}
|
||||
@@ -1269,13 +1269,13 @@ void strip_loose_polysloops(Mesh *me, blender::BitSpan polys_to_remove)
|
||||
me->totloop = b;
|
||||
}
|
||||
|
||||
poly_offsets[me->totpoly] = me->totloop;
|
||||
face_offsets[me->faces_num] = me->totloop;
|
||||
|
||||
/* And now, update polys' start loop index. */
|
||||
/* NOTE: At this point, there should never be any poly using a striped loop! */
|
||||
for (const int i : blender::IndexRange(me->totpoly)) {
|
||||
poly_offsets[i] = new_idx[poly_offsets[i]];
|
||||
BLI_assert(poly_offsets[i] >= 0);
|
||||
/* And now, update faces' start loop index. */
|
||||
/* NOTE: At this point, there should never be any face using a striped loop! */
|
||||
for (const int i : blender::IndexRange(me->faces_num)) {
|
||||
face_offsets[i] = new_idx[face_offsets[i]];
|
||||
BLI_assert(face_offsets[i] >= 0);
|
||||
}
|
||||
|
||||
MEM_freeN(new_idx);
|
||||
@@ -1325,9 +1325,10 @@ void mesh_strip_edges(Mesh *me)
|
||||
|
||||
void BKE_mesh_calc_edges_tessface(Mesh *mesh)
|
||||
{
|
||||
const int numFaces = mesh->totface;
|
||||
EdgeSet *eh = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(numFaces));
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
const int numFaces = mesh->totface_legacy;
|
||||
EdgeSet *eh = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(numFaces));
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
|
||||
MFace *mf = mfaces;
|
||||
for (int i = 0; i < numFaces; i++, mf++) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* output of a modified mesh.
|
||||
*
|
||||
* This API handles the case when the modifier stack outputs a mesh which does not have
|
||||
* #Mesh data (#Mesh::polys(), corner verts, corner edges, edges, etc).
|
||||
* #Mesh data (#Mesh::faces(), corner verts, corner edges, edges, 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.
|
||||
@@ -76,12 +76,12 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
|
||||
#ifdef DEBUG
|
||||
me->totvert = INT_MAX;
|
||||
me->totedge = INT_MAX;
|
||||
me->totpoly = INT_MAX;
|
||||
me->faces_num = INT_MAX;
|
||||
me->totloop = INT_MAX;
|
||||
#else
|
||||
me->totvert = 0;
|
||||
me->totedge = 0;
|
||||
me->totpoly = 0;
|
||||
me->faces_num = 0;
|
||||
me->totloop = 0;
|
||||
#endif
|
||||
|
||||
@@ -105,7 +105,7 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
me->totvert = 0;
|
||||
me->totedge = 0;
|
||||
me->totpoly = 0;
|
||||
me->faces_num = 0;
|
||||
me->totloop = 0;
|
||||
|
||||
BLI_assert(me->edit_mesh != nullptr);
|
||||
@@ -185,18 +185,18 @@ const float (*BKE_mesh_wrapper_vert_coords(const Mesh *mesh))[3]
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_wrapper_poly_normals(Mesh *mesh))[3]
|
||||
const float (*BKE_mesh_wrapper_face_normals(Mesh *mesh))[3]
|
||||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
BKE_editmesh_cache_ensure_poly_normals(mesh->edit_mesh, mesh->runtime->edit_data);
|
||||
if (mesh->runtime->edit_data->polyNos.is_empty()) {
|
||||
BKE_editmesh_cache_ensure_face_normals(mesh->edit_mesh, mesh->runtime->edit_data);
|
||||
if (mesh->runtime->edit_data->faceNos.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->polyNos.data());
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->faceNos.data());
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->poly_normals().data());
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->face_normals().data());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -207,8 +207,8 @@ void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
if (mesh->runtime->edit_data) {
|
||||
mesh->runtime->edit_data->vertexNos = {};
|
||||
mesh->runtime->edit_data->polyCos = {};
|
||||
mesh->runtime->edit_data->polyNos = {};
|
||||
mesh->runtime->edit_data->faceCos = {};
|
||||
mesh->runtime->edit_data->faceNos = {};
|
||||
}
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
@@ -338,14 +338,14 @@ int BKE_mesh_wrapper_loop_len(const Mesh *me)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BKE_mesh_wrapper_poly_len(const Mesh *me)
|
||||
int BKE_mesh_wrapper_face_len(const Mesh *me)
|
||||
{
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return me->edit_mesh->bm->totface;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return me->totpoly;
|
||||
return me->faces_num;
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return -1;
|
||||
|
||||
@@ -184,7 +184,7 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidde
|
||||
|
||||
static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *me, int level)
|
||||
{
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
const MDisps *mdisps = static_cast<const MDisps *>(CustomData_get_layer(&me->ldata, CD_MDISPS));
|
||||
BLI_bitmap **grid_hidden = ccgdm->gridHidden;
|
||||
int *gridOffset;
|
||||
@@ -192,8 +192,8 @@ static void multires_output_hidden_to_ccgdm(CCGDerivedMesh *ccgdm, Mesh *me, int
|
||||
|
||||
gridOffset = ccgdm->dm.getGridOffset(&ccgdm->dm);
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
for (j = 0; j < polys[i].size(); j++) {
|
||||
for (const int i : faces.index_range()) {
|
||||
for (j = 0; j < faces[i].size(); j++) {
|
||||
int g = gridOffset[i] + j;
|
||||
const MDisps *md = &mdisps[g];
|
||||
BLI_bitmap *gh = md->hidden;
|
||||
@@ -468,8 +468,8 @@ void multires_force_sculpt_rebuild(Object *object)
|
||||
object->sculpt->pbvh = nullptr;
|
||||
}
|
||||
|
||||
ss->vert_to_poly_indices = {};
|
||||
ss->vert_to_poly_offsets = {};
|
||||
ss->vert_to_face_indices = {};
|
||||
ss->vert_to_face_offsets = {};
|
||||
ss->pmap = {};
|
||||
}
|
||||
|
||||
@@ -485,13 +485,13 @@ void multires_force_external_reload(Object *object)
|
||||
static int get_levels_from_disps(Object *ob)
|
||||
{
|
||||
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
int totlvl = 0;
|
||||
|
||||
const MDisps *mdisp = static_cast<const MDisps *>(CustomData_get_layer(&me->ldata, CD_MDISPS));
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int corner : polys[i]) {
|
||||
for (const int i : faces.index_range()) {
|
||||
for (const int corner : faces[i]) {
|
||||
const MDisps *md = &mdisp[corner];
|
||||
if (md->totdisp == 0) {
|
||||
continue;
|
||||
@@ -654,7 +654,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
|
||||
static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
|
||||
{
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
int levels = mmd->totlvl - lvl;
|
||||
MDisps *mdisps;
|
||||
GridPaintMask *gpm;
|
||||
@@ -673,8 +673,8 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
|
||||
int nsize = multires_side_tot[lvl];
|
||||
int hsize = multires_side_tot[mmd->totlvl];
|
||||
|
||||
for (const int i : polys.index_range()) {
|
||||
for (const int corner : polys[i]) {
|
||||
for (const int i : faces.index_range()) {
|
||||
for (const int corner : faces[i]) {
|
||||
MDisps *mdisp = &mdisps[corner];
|
||||
float(*disps)[3], (*ndisps)[3], (*hdisps)[3];
|
||||
int totdisp = multires_grid_tot[lvl];
|
||||
@@ -850,7 +850,7 @@ struct MultiresThreadedData {
|
||||
CCGElem **gridData, **subGridData;
|
||||
CCGKey *key;
|
||||
CCGKey *sub_key;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
MDisps *mdisps;
|
||||
GridPaintMask *grid_paint_mask;
|
||||
int *gridOffset;
|
||||
@@ -868,7 +868,7 @@ static void multires_disp_run_cb(void *__restrict userdata,
|
||||
CCGElem **gridData = tdata->gridData;
|
||||
CCGElem **subGridData = tdata->subGridData;
|
||||
CCGKey *key = tdata->key;
|
||||
blender::OffsetIndices<int> polys = tdata->polys;
|
||||
blender::OffsetIndices<int> faces = tdata->faces;
|
||||
MDisps *mdisps = tdata->mdisps;
|
||||
GridPaintMask *grid_paint_mask = tdata->grid_paint_mask;
|
||||
int *gridOffset = tdata->gridOffset;
|
||||
@@ -876,12 +876,12 @@ static void multires_disp_run_cb(void *__restrict userdata,
|
||||
int dGridSize = tdata->dGridSize;
|
||||
int dSkip = tdata->dSkip;
|
||||
|
||||
const int numVerts = polys[pidx].size();
|
||||
const int numVerts = faces[pidx].size();
|
||||
int S, x, y, gIndex = gridOffset[pidx];
|
||||
|
||||
for (S = 0; S < numVerts; S++, gIndex++) {
|
||||
GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : nullptr;
|
||||
MDisps *mdisp = &mdisps[polys[pidx][S]];
|
||||
MDisps *mdisp = &mdisps[faces[pidx][S]];
|
||||
CCGElem *grid = gridData[gIndex];
|
||||
CCGElem *subgrid = subGridData[gIndex];
|
||||
float(*dispgrid)[3] = nullptr;
|
||||
@@ -962,26 +962,26 @@ static void multiresModifier_disp_run(
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGElem **gridData, **subGridData;
|
||||
CCGKey key;
|
||||
blender::OffsetIndices polys = me->polys();
|
||||
blender::OffsetIndices faces = me->faces();
|
||||
MDisps *mdisps = static_cast<MDisps *>(
|
||||
CustomData_get_layer_for_write(&me->ldata, CD_MDISPS, me->totloop));
|
||||
GridPaintMask *grid_paint_mask = nullptr;
|
||||
int *gridOffset;
|
||||
int i, gridSize, dGridSize, dSkip;
|
||||
int totloop, totpoly;
|
||||
int totloop, faces_num;
|
||||
|
||||
/* this happens in the dm made by bmesh_mdisps_space_set */
|
||||
if (dm2 && CustomData_has_layer(&dm2->loopData, CD_MDISPS)) {
|
||||
polys = blender::OffsetIndices(
|
||||
faces = blender::OffsetIndices(
|
||||
blender::Span(dm2->getPolyArray(dm2), dm2->getNumPolys(dm2) + 1));
|
||||
mdisps = static_cast<MDisps *>(
|
||||
CustomData_get_layer_for_write(&dm2->loopData, CD_MDISPS, dm2->getNumLoops(dm)));
|
||||
totloop = dm2->numLoopData;
|
||||
totpoly = dm2->numPolyData;
|
||||
faces_num = dm2->numPolyData;
|
||||
}
|
||||
else {
|
||||
totloop = me->totloop;
|
||||
totpoly = me->totpoly;
|
||||
faces_num = me->faces_num;
|
||||
}
|
||||
|
||||
if (!mdisps) {
|
||||
@@ -1027,7 +1027,7 @@ static void multiresModifier_disp_run(
|
||||
data.gridData = gridData;
|
||||
data.subGridData = subGridData;
|
||||
data.key = &key;
|
||||
data.polys = polys;
|
||||
data.faces = faces;
|
||||
data.mdisps = mdisps;
|
||||
data.grid_paint_mask = grid_paint_mask;
|
||||
data.gridOffset = gridOffset;
|
||||
@@ -1035,7 +1035,7 @@ static void multiresModifier_disp_run(
|
||||
data.dGridSize = dGridSize;
|
||||
data.dSkip = dSkip;
|
||||
|
||||
BLI_task_parallel_range(0, totpoly, &data, multires_disp_run_cb, &settings);
|
||||
BLI_task_parallel_range(0, faces_num, &data, multires_disp_run_cb, &settings);
|
||||
|
||||
if (op == APPLY_DISPLACEMENTS) {
|
||||
ccgSubSurf_stitchFaces(ccgdm->ss, 0, nullptr, 0);
|
||||
|
||||
@@ -37,7 +37,7 @@ struct MultiresReshapeContext {
|
||||
Mesh *base_mesh;
|
||||
blender::Span<blender::float3> base_positions;
|
||||
blender::Span<blender::int2> base_edges;
|
||||
blender::OffsetIndices<int> base_polys;
|
||||
blender::OffsetIndices<int> base_faces;
|
||||
blender::Span<int> base_corner_verts;
|
||||
blender::Span<int> base_corner_edges;
|
||||
|
||||
@@ -83,8 +83,8 @@ struct MultiresReshapeContext {
|
||||
/* Indexed by face index, gives first grid index of the face. */
|
||||
int *face_start_grid_index;
|
||||
|
||||
/* Indexed by grid index, contains face (poly) index in the base mesh from which the grid has
|
||||
* been created (in other words, index of a poly which contains loop corresponding to the grid
|
||||
/* Indexed by grid index, contains face index in the base mesh from which the grid has
|
||||
* been created (in other words, index of a face which contains loop corresponding to the grid
|
||||
* index). */
|
||||
int *grid_to_face_index;
|
||||
|
||||
|
||||
@@ -71,14 +71,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
||||
blender::MutableSpan<blender::float3> base_positions = base_mesh->vert_positions_for_write();
|
||||
/* Update the context in case the vertices were duplicated. */
|
||||
reshape_context->base_positions = base_positions;
|
||||
blender::Array<int> vert_to_poly_offsets;
|
||||
blender::Array<int> vert_to_poly_indices;
|
||||
const blender::GroupedSpan<int> pmap = blender::bke::mesh::build_vert_to_poly_map(
|
||||
reshape_context->base_polys,
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
const blender::GroupedSpan<int> pmap = blender::bke::mesh::build_vert_to_face_map(
|
||||
reshape_context->base_faces,
|
||||
reshape_context->base_corner_verts,
|
||||
base_mesh->totvert,
|
||||
vert_to_poly_offsets,
|
||||
vert_to_poly_indices);
|
||||
vert_to_face_offsets,
|
||||
vert_to_face_indices);
|
||||
|
||||
float(*origco)[3] = static_cast<float(*)[3]>(
|
||||
MEM_calloc_arrayN(base_mesh->totvert, sizeof(float[3]), __func__));
|
||||
@@ -89,7 +89,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
||||
for (int i = 0; i < base_mesh->totvert; i++) {
|
||||
float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3];
|
||||
|
||||
/* Don't adjust vertices not used by at least one poly. */
|
||||
/* Don't adjust vertices not used by at least one face. */
|
||||
if (!pmap[i].size()) {
|
||||
continue;
|
||||
}
|
||||
@@ -97,10 +97,10 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
||||
/* Find center. */
|
||||
int tot = 0;
|
||||
for (int j = 0; j < pmap[i].size(); j++) {
|
||||
const blender::IndexRange poly = reshape_context->base_polys[pmap[i][j]];
|
||||
const blender::IndexRange face = reshape_context->base_faces[pmap[i][j]];
|
||||
|
||||
/* This double counts, not sure if that's bad or good. */
|
||||
for (const int corner : poly) {
|
||||
for (const int corner : face) {
|
||||
const int vndx = reshape_context->base_corner_verts[corner];
|
||||
if (vndx != i) {
|
||||
add_v3_v3(center, origco[vndx]);
|
||||
@@ -112,16 +112,16 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
||||
|
||||
/* Find normal. */
|
||||
for (int j = 0; j < pmap[i].size(); j++) {
|
||||
const blender::IndexRange poly = reshape_context->base_polys[pmap[i][j]];
|
||||
const blender::IndexRange face = reshape_context->base_faces[pmap[i][j]];
|
||||
|
||||
/* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */
|
||||
blender::Array<int> poly_verts(poly.size());
|
||||
blender::Array<blender::float3> fake_co(poly.size());
|
||||
/* Set up face, loops, and coords in order to call #bke::mesh::face_normal_calc(). */
|
||||
blender::Array<int> face_verts(face.size());
|
||||
blender::Array<blender::float3> fake_co(face.size());
|
||||
|
||||
for (int k = 0; k < poly.size(); k++) {
|
||||
const int vndx = reshape_context->base_corner_verts[poly[k]];
|
||||
for (int k = 0; k < face.size(); k++) {
|
||||
const int vndx = reshape_context->base_corner_verts[face[k]];
|
||||
|
||||
poly_verts[k] = k;
|
||||
face_verts[k] = k;
|
||||
|
||||
if (vndx == i) {
|
||||
copy_v3_v3(fake_co[k], center);
|
||||
@@ -131,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, poly_verts);
|
||||
const blender::float3 no = blender::bke::mesh::face_normal_calc(fake_co, face_verts);
|
||||
add_v3_v3(avg_no, no);
|
||||
}
|
||||
normalize_v3(avg_no);
|
||||
|
||||
@@ -568,8 +568,8 @@ static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
|
||||
const int num_vertices,
|
||||
const int num_edges,
|
||||
const int num_loops,
|
||||
const int num_polygons,
|
||||
const int * /*subdiv_polygon_offset*/)
|
||||
const int num_faces,
|
||||
const int * /*subdiv_face_offset*/)
|
||||
{
|
||||
MultiresReshapeSmoothContext *reshape_smooth_context =
|
||||
static_cast<MultiresReshapeSmoothContext *>(foreach_context->user_data);
|
||||
@@ -590,9 +590,9 @@ static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
|
||||
reshape_smooth_context->geometry.corners = static_cast<Corner *>(
|
||||
MEM_malloc_arrayN(num_loops, sizeof(Corner), "smooth corners"));
|
||||
|
||||
reshape_smooth_context->geometry.num_faces = num_polygons;
|
||||
reshape_smooth_context->geometry.num_faces = num_faces;
|
||||
reshape_smooth_context->geometry.faces = static_cast<Face *>(
|
||||
MEM_malloc_arrayN(num_polygons, sizeof(Face), "smooth faces"));
|
||||
MEM_malloc_arrayN(num_faces, sizeof(Face), "smooth faces"));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -646,7 +646,7 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context,
|
||||
const int face_index = multires_reshape_grid_to_face_index(reshape_context,
|
||||
grid_coord.grid_index);
|
||||
|
||||
const int num_corners = reshape_context->base_polys[face_index].size();
|
||||
const int num_corners = reshape_context->base_faces[face_index].size();
|
||||
const int start_grid_index = reshape_context->face_start_grid_index[face_index];
|
||||
const int corner = grid_coord.grid_index - start_grid_index;
|
||||
|
||||
@@ -688,7 +688,7 @@ static void foreach_vertex_inner(const SubdivForeachContext *foreach_context,
|
||||
const int ptex_face_index,
|
||||
const float ptex_face_u,
|
||||
const float ptex_face_v,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
@@ -739,7 +739,7 @@ static void foreach_loop(const SubdivForeachContext *foreach_context,
|
||||
const float /*ptex_face_u*/,
|
||||
const float /*ptex_face_v*/,
|
||||
const int /*coarse_loop_index*/,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner,
|
||||
const int subdiv_loop_index,
|
||||
const int subdiv_vertex_index,
|
||||
@@ -754,23 +754,23 @@ static void foreach_loop(const SubdivForeachContext *foreach_context,
|
||||
Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index];
|
||||
corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
|
||||
|
||||
const int first_grid_index = reshape_context->face_start_grid_index[coarse_poly_index];
|
||||
const int first_grid_index = reshape_context->face_start_grid_index[coarse_face_index];
|
||||
corner->grid_index = first_grid_index + coarse_corner;
|
||||
}
|
||||
|
||||
static void foreach_poly(const SubdivForeachContext *foreach_context,
|
||||
void * /*tls*/,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int subdiv_poly_index,
|
||||
const int /*coarse_face_index*/,
|
||||
const int subdiv_face_index,
|
||||
const int start_loop_index,
|
||||
const int num_loops)
|
||||
{
|
||||
const MultiresReshapeSmoothContext *reshape_smooth_context =
|
||||
static_cast<const MultiresReshapeSmoothContext *>(foreach_context->user_data);
|
||||
|
||||
BLI_assert(subdiv_poly_index < reshape_smooth_context->geometry.num_faces);
|
||||
BLI_assert(subdiv_face_index < reshape_smooth_context->geometry.num_faces);
|
||||
|
||||
Face *face = &reshape_smooth_context->geometry.faces[subdiv_poly_index];
|
||||
Face *face = &reshape_smooth_context->geometry.faces[subdiv_face_index];
|
||||
face->start_corner_index = start_loop_index;
|
||||
face->num_corners = num_loops;
|
||||
}
|
||||
|
||||
@@ -32,29 +32,29 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const Span<float3> positions = mesh->vert_positions();
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
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 blender::IndexRange poly = polys[p];
|
||||
const float3 poly_center = mesh::poly_center_calc(positions, corner_verts.slice(poly));
|
||||
for (int l = 0; l < poly.size(); l++) {
|
||||
const int loop_index = poly[l];
|
||||
for (const int p : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[p];
|
||||
const float3 face_center = mesh::face_center_calc(positions, corner_verts.slice(face));
|
||||
for (int l = 0; l < face.size(); l++) {
|
||||
const int loop_index = face[l];
|
||||
|
||||
float(*disps)[3] = mdisps[loop_index].disps;
|
||||
mdisps[loop_index].totdisp = 4;
|
||||
mdisps[loop_index].level = 1;
|
||||
|
||||
int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly.size() - 1;
|
||||
int next_loop_index = l + 1 < poly.size() ? loop_index + 1 : poly.start();
|
||||
int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + face.size() - 1;
|
||||
int next_loop_index = l + 1 < face.size() ? loop_index + 1 : face.start();
|
||||
|
||||
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);
|
||||
copy_v3_v3(disps[0], face_center);
|
||||
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]);
|
||||
@@ -78,7 +78,7 @@ void multires_subdivide_create_tangent_displacement_linear_grids(Object *object,
|
||||
}
|
||||
|
||||
if (new_top_level == 1) {
|
||||
/* No MDISPS. Create new grids for level 1 using the edges mid point and poly centers. */
|
||||
/* No MDISPS. Create new grids for level 1 using the edges mid point and face centers. */
|
||||
multires_reshape_ensure_grids(coarse_mesh, 1);
|
||||
multires_subdivide_create_object_space_linear_grids(coarse_mesh);
|
||||
}
|
||||
|
||||
@@ -70,15 +70,15 @@ static void context_zero(MultiresReshapeContext *reshape_context)
|
||||
static void context_init_lookup(MultiresReshapeContext *reshape_context)
|
||||
{
|
||||
const Mesh *base_mesh = reshape_context->base_mesh;
|
||||
const blender::OffsetIndices polys = reshape_context->base_polys;
|
||||
const int num_faces = base_mesh->totpoly;
|
||||
const blender::OffsetIndices faces = reshape_context->base_faces;
|
||||
const int num_faces = base_mesh->faces_num;
|
||||
|
||||
reshape_context->face_start_grid_index = static_cast<int *>(
|
||||
MEM_malloc_arrayN(num_faces, sizeof(int), "face_start_grid_index"));
|
||||
int num_grids = 0;
|
||||
int num_ptex_faces = 0;
|
||||
for (int face_index = 0; face_index < num_faces; ++face_index) {
|
||||
const int num_corners = polys[face_index].size();
|
||||
const int num_corners = faces[face_index].size();
|
||||
reshape_context->face_start_grid_index[face_index] = num_grids;
|
||||
num_grids += num_corners;
|
||||
num_ptex_faces += (num_corners == 4) ? 1 : num_corners;
|
||||
@@ -89,7 +89,7 @@ static void context_init_lookup(MultiresReshapeContext *reshape_context)
|
||||
reshape_context->ptex_start_grid_index = static_cast<int *>(
|
||||
MEM_malloc_arrayN(num_ptex_faces, sizeof(int), "ptex_start_grid_index"));
|
||||
for (int face_index = 0, grid_index = 0, ptex_index = 0; face_index < num_faces; ++face_index) {
|
||||
const int num_corners = polys[face_index].size();
|
||||
const int num_corners = faces[face_index].size();
|
||||
const int num_face_ptex_faces = (num_corners == 4) ? 1 : num_corners;
|
||||
for (int i = 0; i < num_face_ptex_faces; ++i) {
|
||||
reshape_context->ptex_start_grid_index[ptex_index + i] = grid_index + i;
|
||||
@@ -160,7 +160,7 @@ bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *resh
|
||||
reshape_context->base_mesh = base_mesh;
|
||||
reshape_context->base_positions = base_mesh->vert_positions();
|
||||
reshape_context->base_edges = base_mesh->edges();
|
||||
reshape_context->base_polys = base_mesh->polys();
|
||||
reshape_context->base_faces = base_mesh->faces();
|
||||
reshape_context->base_corner_verts = base_mesh->corner_verts();
|
||||
reshape_context->base_corner_edges = base_mesh->corner_edges();
|
||||
|
||||
@@ -199,7 +199,7 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape
|
||||
reshape_context->base_mesh = base_mesh;
|
||||
reshape_context->base_positions = base_mesh->vert_positions();
|
||||
reshape_context->base_edges = base_mesh->edges();
|
||||
reshape_context->base_polys = base_mesh->polys();
|
||||
reshape_context->base_faces = base_mesh->faces();
|
||||
reshape_context->base_corner_verts = base_mesh->corner_verts();
|
||||
reshape_context->base_corner_edges = base_mesh->corner_edges();
|
||||
|
||||
@@ -233,7 +233,7 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co
|
||||
reshape_context->base_mesh = base_mesh;
|
||||
reshape_context->base_positions = base_mesh->vert_positions();
|
||||
reshape_context->base_edges = base_mesh->edges();
|
||||
reshape_context->base_polys = base_mesh->polys();
|
||||
reshape_context->base_faces = base_mesh->faces();
|
||||
reshape_context->base_corner_verts = base_mesh->corner_verts();
|
||||
reshape_context->base_corner_edges = base_mesh->corner_edges();
|
||||
|
||||
@@ -282,7 +282,7 @@ bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape
|
||||
reshape_context->base_mesh = base_mesh;
|
||||
reshape_context->base_positions = base_mesh->vert_positions();
|
||||
reshape_context->base_edges = base_mesh->edges();
|
||||
reshape_context->base_polys = base_mesh->polys();
|
||||
reshape_context->base_faces = base_mesh->faces();
|
||||
reshape_context->base_corner_verts = base_mesh->corner_verts();
|
||||
reshape_context->base_corner_edges = base_mesh->corner_edges();
|
||||
|
||||
@@ -377,7 +377,7 @@ int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_contex
|
||||
|
||||
bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index)
|
||||
{
|
||||
return reshape_context->base_polys[face_index].size() == 4;
|
||||
return reshape_context->base_faces[face_index].size() == 4;
|
||||
}
|
||||
|
||||
int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
|
||||
@@ -673,11 +673,11 @@ static void foreach_grid_face_coordinate_task(void *__restrict userdata_v,
|
||||
|
||||
const MultiresReshapeContext *reshape_context = data->reshape_context;
|
||||
|
||||
const blender::OffsetIndices polys = reshape_context->base_polys;
|
||||
const blender::OffsetIndices faces = reshape_context->base_faces;
|
||||
const int grid_size = data->grid_size;
|
||||
const float grid_size_1_inv = 1.0f / (float(grid_size) - 1.0f);
|
||||
|
||||
const int num_corners = polys[face_index].size();
|
||||
const int num_corners = faces[face_index].size();
|
||||
int grid_index = reshape_context->face_start_grid_index[face_index];
|
||||
for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
|
||||
for (int y = 0; y < grid_size; ++y) {
|
||||
@@ -714,7 +714,7 @@ static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_contex
|
||||
parallel_range_settings.min_iter_per_thread = 1;
|
||||
|
||||
const Mesh *base_mesh = reshape_context->base_mesh;
|
||||
const int num_faces = base_mesh->totpoly;
|
||||
const int num_faces = base_mesh->faces_num;
|
||||
BLI_task_parallel_range(
|
||||
0, num_faces, &data, foreach_grid_face_coordinate_task, ¶llel_range_settings);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ static void multires_reshape_vertcos_foreach_vertex(const SubdivForeachContext *
|
||||
const int face_index = multires_reshape_grid_to_face_index(reshape_context,
|
||||
grid_coord.grid_index);
|
||||
|
||||
const int num_corners = reshape_context->base_polys[face_index].size();
|
||||
const int num_corners = reshape_context->base_faces[face_index].size();
|
||||
const int start_grid_index = reshape_context->face_start_grid_index[face_index];
|
||||
const int corner = grid_coord.grid_index - start_grid_index;
|
||||
|
||||
@@ -99,8 +99,8 @@ static bool multires_reshape_vertcos_foreach_topology_info(
|
||||
const int num_vertices,
|
||||
const int /*num_edges*/,
|
||||
const int /*num_loops*/,
|
||||
const int /*num_polygons*/,
|
||||
const int * /*subdiv_polygon_offset*/)
|
||||
const int /*num_faces*/,
|
||||
const int * /*subdiv_face_offset*/)
|
||||
{
|
||||
MultiresReshapeAssignVertcosContext *reshape_vertcos_context =
|
||||
static_cast<MultiresReshapeAssignVertcosContext *>(foreach_context->user_data);
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
* to original mesh
|
||||
* - Extract the grid from the original mesh from that loop. If there are no grids in the original
|
||||
* mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern
|
||||
* over them. If there are grids in the original mesh, iterate in a grid pattern over the polys,
|
||||
* reorder all the coordinates of the grid in that poly and copy those coordinates to the new
|
||||
* over them. If there are grids in the original mesh, iterate in a grid pattern over the faces,
|
||||
* reorder all the coordinates of the grid in that face and copy those coordinates to the new
|
||||
* base mesh grid.
|
||||
* - Copy the new grid data over to a new allocated MDISP layer with the appropriate size to store
|
||||
* the new levels.
|
||||
@@ -548,7 +548,7 @@ static BMEdge *get_initial_edge_y(BMFace *f, BMEdge *edge_x, BMVert *initial_ver
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the current mdisp data into the corresponding area of quad poly giving its corner's loop.
|
||||
* Writes the current mdisp data into the corresponding area of quad face giving its corner's loop.
|
||||
*/
|
||||
static void write_loop_in_face_grid(
|
||||
float (*face_grid)[3], MDisps *mdisp, int face_grid_size, int orig_grid_size, int loop)
|
||||
@@ -645,17 +645,17 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
|
||||
int grid_y)
|
||||
{
|
||||
Mesh *original_mesh = context->original_mesh;
|
||||
const blender::OffsetIndices polys = original_mesh->polys();
|
||||
const blender::OffsetIndices faces = original_mesh->faces();
|
||||
const blender::Span<int> corner_verts = original_mesh->corner_verts();
|
||||
const blender::IndexRange poly = polys[BM_elem_index_get(f)];
|
||||
const blender::IndexRange face = faces[BM_elem_index_get(f)];
|
||||
|
||||
const int corner_vertex_index = BM_elem_index_get(v);
|
||||
|
||||
/* Calculates an offset to write the grids correctly oriented in the main
|
||||
* #MultiresUnsubdivideGrid. */
|
||||
int loop_offset = 0;
|
||||
for (int i = 0; i < poly.size(); i++) {
|
||||
const int loop_index = poly[i];
|
||||
for (int i = 0; i < face.size(); i++) {
|
||||
const int loop_index = face[i];
|
||||
if (corner_verts[loop_index] == corner_vertex_index) {
|
||||
loop_offset = i;
|
||||
break;
|
||||
@@ -669,8 +669,8 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
|
||||
float(*face_grid)[3] = static_cast<float(*)[3]>(
|
||||
MEM_calloc_arrayN(face_grid_area, sizeof(float[3]), "face_grid"));
|
||||
|
||||
for (int i = 0; i < poly.size(); i++) {
|
||||
const int loop_index = poly[i];
|
||||
for (int i = 0; i < face.size(); i++) {
|
||||
const int loop_index = face[i];
|
||||
MDisps *mdisp = &context->original_mdisp[loop_index];
|
||||
int quad_loop = i - loop_offset;
|
||||
if (quad_loop < 0) {
|
||||
@@ -816,7 +816,7 @@ static void multires_unsubdivide_extract_single_grid_from_face_edge(
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the l+1 and l-1 vertices of the base mesh poly were the grid from the face f1 and edge
|
||||
* Returns the l+1 and l-1 vertices of the base mesh face were the grid from the face f1 and edge
|
||||
* e1 is going to be extracted.
|
||||
*
|
||||
* These vertices should always have an corresponding existing vertex on the base mesh.
|
||||
@@ -923,7 +923,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
|
||||
MultiresUnsubdivideContext *context)
|
||||
{
|
||||
Mesh *original_mesh = context->original_mesh;
|
||||
const blender::OffsetIndices original_polys = original_mesh->polys();
|
||||
const blender::OffsetIndices original_faces = original_mesh->faces();
|
||||
|
||||
Mesh *base_mesh = context->base_mesh;
|
||||
|
||||
@@ -951,28 +951,28 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
|
||||
BM_elem_flag_set(v, BM_ELEM_TAG, true);
|
||||
}
|
||||
|
||||
context->loop_to_face_map = blender::bke::mesh::build_loop_to_poly_map(original_polys);
|
||||
context->loop_to_face_map = blender::bke::mesh::build_loop_to_face_map(original_faces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the orientation of the loops to flip the x and y axis when extracting the grid if
|
||||
* necessary.
|
||||
*/
|
||||
static bool multires_unsubdivide_flip_grid_x_axis(const blender::OffsetIndices<int> polys,
|
||||
static bool multires_unsubdivide_flip_grid_x_axis(const blender::OffsetIndices<int> faces,
|
||||
const blender::Span<int> corner_verts,
|
||||
int poly_index,
|
||||
int face_index,
|
||||
int loop,
|
||||
int v_x)
|
||||
{
|
||||
const blender::IndexRange poly = polys[poly_index];
|
||||
const blender::IndexRange face = faces[face_index];
|
||||
|
||||
const int v_first = corner_verts[poly.start()];
|
||||
if ((loop == (poly.start() + (poly.size() - 1))) && v_first == v_x) {
|
||||
const int v_first = corner_verts[face.start()];
|
||||
if ((loop == (face.start() + (face.size() - 1))) && v_first == v_x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int next_l_index = loop + 1;
|
||||
if (next_l_index < poly.start() + poly.size()) {
|
||||
if (next_l_index < face.start() + face.size()) {
|
||||
const int v_next = corner_verts[next_l_index];
|
||||
if (v_next == v_x) {
|
||||
return true;
|
||||
@@ -1034,7 +1034,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
|
||||
const int base_l_offset = CustomData_get_offset_named(
|
||||
&bm_base_mesh->ldata, CD_PROP_INT32, lname);
|
||||
|
||||
const blender::OffsetIndices polys = base_mesh->polys();
|
||||
const blender::OffsetIndices faces = base_mesh->faces();
|
||||
const blender::Span<int> corner_verts = base_mesh->corner_verts();
|
||||
|
||||
/* Main loop for extracting the grids. Iterates over the base mesh vertices. */
|
||||
@@ -1048,7 +1048,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
|
||||
/* Iterate over the loops of that vertex in the original mesh. */
|
||||
BM_ITER_ELEM (l, &iter_a, vert_original, BM_LOOPS_OF_VERT) {
|
||||
/* For each loop, get the two vertices that should map to the l+1 and l-1 vertices in the
|
||||
* base mesh of the poly of grid that is going to be extracted. */
|
||||
* base mesh of the face of grid that is going to be extracted. */
|
||||
BMVert *corner_x, *corner_y;
|
||||
multires_unsubdivide_get_grid_corners_on_base_mesh(l->f, l->e, &corner_x, &corner_y);
|
||||
|
||||
@@ -1074,7 +1074,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, corner_verts, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
|
||||
faces, 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;
|
||||
|
||||
@@ -1065,7 +1065,7 @@ struct FaceDupliData_Mesh {
|
||||
FaceDupliData_Params params;
|
||||
|
||||
int totface;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
Span<int> corner_verts;
|
||||
Span<float3> vert_positions;
|
||||
const float (*orco)[3];
|
||||
@@ -1164,13 +1164,13 @@ static DupliObject *face_dupli_from_mesh(const DupliContext *ctx,
|
||||
const float scale_fac,
|
||||
|
||||
/* Mesh variables. */
|
||||
const Span<int> poly_verts,
|
||||
const Span<int> face_verts,
|
||||
const Span<float3> vert_positions)
|
||||
{
|
||||
Array<float3, 64> coords(poly_verts.size());
|
||||
Array<float3, 64> coords(face_verts.size());
|
||||
|
||||
for (int i = 0; i < poly_verts.size(); i++) {
|
||||
coords[i] = vert_positions[poly_verts[i]];
|
||||
for (int i = 0; i < face_verts.size(); i++) {
|
||||
coords[i] = vert_positions[face_verts[i]];
|
||||
}
|
||||
|
||||
return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords);
|
||||
@@ -1225,26 +1225,26 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
|
||||
const float scale_fac = ctx->object->instance_faces_scale;
|
||||
|
||||
for (const int a : blender::IndexRange(totface)) {
|
||||
const blender::IndexRange poly = fdd->polys[a];
|
||||
const Span<int> poly_verts = fdd->corner_verts.slice(poly);
|
||||
const blender::IndexRange face = fdd->faces[a];
|
||||
const Span<int> face_verts = fdd->corner_verts.slice(face);
|
||||
DupliObject *dob = face_dupli_from_mesh(fdd->params.ctx,
|
||||
inst_ob,
|
||||
child_imat,
|
||||
a,
|
||||
use_scale,
|
||||
scale_fac,
|
||||
poly_verts,
|
||||
face_verts,
|
||||
fdd->vert_positions);
|
||||
|
||||
const float w = 1.0f / float(poly.size());
|
||||
const float w = 1.0f / float(face.size());
|
||||
if (orco) {
|
||||
for (int j = 0; j < poly.size(); j++) {
|
||||
madd_v3_v3fl(dob->orco, orco[poly_verts[j]], w);
|
||||
for (int j = 0; j < face.size(); j++) {
|
||||
madd_v3_v3fl(dob->orco, orco[face_verts[j]], w);
|
||||
}
|
||||
}
|
||||
if (mloopuv) {
|
||||
for (int j = 0; j < poly.size(); j++) {
|
||||
madd_v2_v2fl(dob->uv, mloopuv[poly[j]], w);
|
||||
for (int j = 0; j < face.size(); j++) {
|
||||
madd_v2_v2fl(dob->uv, mloopuv[face[j]], w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1321,8 +1321,8 @@ static void make_duplis_faces(const DupliContext *ctx)
|
||||
const int uv_idx = CustomData_get_render_layer(&me_eval->ldata, CD_PROP_FLOAT2);
|
||||
FaceDupliData_Mesh fdd{};
|
||||
fdd.params = fdd_params;
|
||||
fdd.totface = me_eval->totpoly;
|
||||
fdd.polys = me_eval->polys();
|
||||
fdd.totface = me_eval->faces_num;
|
||||
fdd.faces = me_eval->faces();
|
||||
fdd.corner_verts = me_eval->corner_verts();
|
||||
fdd.vert_positions = me_eval->vert_positions();
|
||||
fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n(
|
||||
|
||||
@@ -1290,12 +1290,12 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p)
|
||||
}
|
||||
}
|
||||
|
||||
bool paint_is_face_hidden(const int *looptri_polys, const bool *hide_poly, const int tri_index)
|
||||
bool paint_is_face_hidden(const int *looptri_faces, const bool *hide_poly, const int tri_index)
|
||||
{
|
||||
if (!hide_poly) {
|
||||
return false;
|
||||
}
|
||||
return hide_poly[looptri_polys[tri_index]];
|
||||
return hide_poly[looptri_faces[tri_index]];
|
||||
}
|
||||
|
||||
bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y)
|
||||
@@ -1432,9 +1432,9 @@ void BKE_sculptsession_free_vwpaint_data(SculptSession *ss)
|
||||
gmap->vert_to_loop_offsets = {};
|
||||
gmap->vert_to_loop_indices = {};
|
||||
gmap->vert_to_loop = {};
|
||||
gmap->vert_to_poly_offsets = {};
|
||||
gmap->vert_to_poly_indices = {};
|
||||
gmap->vert_to_poly = {};
|
||||
gmap->vert_to_face_offsets = {};
|
||||
gmap->vert_to_face_indices = {};
|
||||
gmap->vert_to_face = {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1485,11 +1485,11 @@ static void sculptsession_free_pbvh(Object *object)
|
||||
ss->pbvh = nullptr;
|
||||
}
|
||||
|
||||
ss->vert_to_poly_offsets = {};
|
||||
ss->vert_to_poly_indices = {};
|
||||
ss->vert_to_face_offsets = {};
|
||||
ss->vert_to_face_indices = {};
|
||||
ss->pmap = {};
|
||||
ss->edge_to_poly_offsets = {};
|
||||
ss->edge_to_poly_indices = {};
|
||||
ss->edge_to_face_offsets = {};
|
||||
ss->edge_to_face_indices = {};
|
||||
ss->epmap = {};
|
||||
ss->vert_to_edge_offsets = {};
|
||||
ss->vert_to_edge_indices = {};
|
||||
@@ -1730,21 +1730,21 @@ static void sculpt_update_object(
|
||||
ss->multires.modifier = mmd;
|
||||
ss->multires.level = mmd->sculptlvl;
|
||||
ss->totvert = me_eval->totvert;
|
||||
ss->totpoly = me_eval->totpoly;
|
||||
ss->totfaces = me->totpoly;
|
||||
ss->faces_num = me_eval->faces_num;
|
||||
ss->totfaces = me->faces_num;
|
||||
|
||||
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
|
||||
* and tools use the Face Sets data from the base mesh when Multires is active. */
|
||||
ss->vert_positions = me->vert_positions_for_write();
|
||||
ss->polys = me->polys();
|
||||
ss->faces = me->faces();
|
||||
ss->corner_verts = me->corner_verts();
|
||||
}
|
||||
else {
|
||||
ss->totvert = me->totvert;
|
||||
ss->totpoly = me->totpoly;
|
||||
ss->totfaces = me->totpoly;
|
||||
ss->faces_num = me->faces_num;
|
||||
ss->totfaces = me->faces_num;
|
||||
ss->vert_positions = me->vert_positions_for_write();
|
||||
ss->polys = me->polys();
|
||||
ss->faces = me->faces();
|
||||
ss->corner_verts = me->corner_verts();
|
||||
ss->multires.active = false;
|
||||
ss->multires.modifier = nullptr;
|
||||
@@ -1777,14 +1777,14 @@ static void sculpt_update_object(
|
||||
/* Sculpt Face Sets. */
|
||||
if (use_face_sets) {
|
||||
ss->face_sets = static_cast<int *>(CustomData_get_layer_named_for_write(
|
||||
&me->pdata, CD_PROP_INT32, ".sculpt_face_set", me->totpoly));
|
||||
&me->pdata, CD_PROP_INT32, ".sculpt_face_set", me->faces_num));
|
||||
}
|
||||
else {
|
||||
ss->face_sets = nullptr;
|
||||
}
|
||||
|
||||
ss->hide_poly = (bool *)CustomData_get_layer_named_for_write(
|
||||
&me->pdata, CD_PROP_BOOL, ".hide_poly", me->totpoly);
|
||||
&me->pdata, CD_PROP_BOOL, ".hide_poly", me->faces_num);
|
||||
|
||||
ss->subdiv_ccg = me_eval->runtime->subdiv_ccg;
|
||||
|
||||
@@ -1802,11 +1802,11 @@ static void sculpt_update_object(
|
||||
sculpt_update_persistent_base(ob);
|
||||
|
||||
if (ob->type == OB_MESH && ss->pmap.is_empty()) {
|
||||
ss->pmap = blender::bke::mesh::build_vert_to_poly_map(me->polys(),
|
||||
ss->pmap = blender::bke::mesh::build_vert_to_face_map(me->faces(),
|
||||
me->corner_verts(),
|
||||
me->totvert,
|
||||
ss->vert_to_poly_offsets,
|
||||
ss->vert_to_poly_indices);
|
||||
ss->vert_to_face_offsets,
|
||||
ss->vert_to_face_indices);
|
||||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
@@ -1823,7 +1823,7 @@ static void sculpt_update_object(
|
||||
/* If the fully evaluated mesh has the same topology as the deform-only version, use it.
|
||||
* This matters because crazyspace evaluation is very restrictive and excludes even modifiers
|
||||
* that simply recompute vertex weights (which can even include Geometry Nodes). */
|
||||
if (me_eval_deform->totpoly == me_eval->totpoly &&
|
||||
if (me_eval_deform->faces_num == me_eval->faces_num &&
|
||||
me_eval_deform->totloop == me_eval->totloop &&
|
||||
me_eval_deform->totvert == me_eval->totvert)
|
||||
{
|
||||
@@ -2010,7 +2010,7 @@ int *BKE_sculpt_face_sets_ensure(Object *ob)
|
||||
}
|
||||
|
||||
int *face_sets = static_cast<int *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set", mesh->totpoly));
|
||||
&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set", mesh->faces_num));
|
||||
|
||||
if (ss->pbvh && ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_GRIDS)) {
|
||||
BKE_pbvh_face_sets_set(ss->pbvh, face_sets);
|
||||
@@ -2022,12 +2022,12 @@ int *BKE_sculpt_face_sets_ensure(Object *ob)
|
||||
bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh)
|
||||
{
|
||||
bool *hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->faces_num));
|
||||
if (hide_poly != nullptr) {
|
||||
return hide_poly;
|
||||
}
|
||||
return static_cast<bool *>(CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totpoly, ".hide_poly"));
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->faces_num, ".hide_poly"));
|
||||
}
|
||||
|
||||
int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
||||
@@ -2036,7 +2036,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
||||
MultiresModifierData *mmd)
|
||||
{
|
||||
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
const Span<int> corner_verts = me->corner_verts();
|
||||
int ret = 0;
|
||||
|
||||
@@ -2064,22 +2064,22 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
||||
|
||||
/* If vertices already have mask, copy into multires data. */
|
||||
if (paint_mask) {
|
||||
for (const int i : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
for (const int i : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
|
||||
/* Mask center. */
|
||||
float avg = 0.0f;
|
||||
for (const int vert : corner_verts.slice(poly)) {
|
||||
for (const int vert : corner_verts.slice(face)) {
|
||||
avg += paint_mask[vert];
|
||||
}
|
||||
avg /= float(poly.size());
|
||||
avg /= float(face.size());
|
||||
|
||||
/* Fill in multires mask corner. */
|
||||
for (const int corner : poly) {
|
||||
for (const int corner : face) {
|
||||
GridPaintMask *gpm = &gmask[corner];
|
||||
const int vert = corner_verts[corner];
|
||||
const int prev = corner_verts[blender::bke::mesh::poly_corner_prev(poly, vert)];
|
||||
const int next = corner_verts[blender::bke::mesh::poly_corner_next(poly, vert)];
|
||||
const int prev = corner_verts[blender::bke::mesh::face_corner_prev(face, vert)];
|
||||
const int next = corner_verts[blender::bke::mesh::face_corner_next(face, vert)];
|
||||
|
||||
gpm->data[0] = avg;
|
||||
gpm->data[1] = (paint_mask[vert] + paint_mask[next]) * 0.5f;
|
||||
|
||||
@@ -1892,7 +1892,7 @@ static float psys_interpolate_value_from_verts(
|
||||
case PART_FROM_FACE:
|
||||
case PART_FROM_VOLUME: {
|
||||
MFace *mfaces = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface));
|
||||
CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
|
||||
MFace *mf = &mfaces[index];
|
||||
return interpolate_particle_value(
|
||||
values[mf->v1], values[mf->v2], values[mf->v3], values[mf->v4], fw, mf->v4);
|
||||
@@ -1954,22 +1954,22 @@ int psys_particle_dm_face_lookup(Mesh *mesh_final,
|
||||
const int *index_mf_to_mpoly = nullptr;
|
||||
const int *index_mp_to_orig = nullptr;
|
||||
|
||||
const int totface_final = mesh_final->totface;
|
||||
const int totface_deformed = mesh_original ? mesh_original->totface : totface_final;
|
||||
const int totface_final = mesh_final->totface_legacy;
|
||||
const int totface_deformed = mesh_original ? mesh_original->totface_legacy : totface_final;
|
||||
|
||||
if (ELEM(0, totface_final, totface_deformed)) {
|
||||
return DMCACHE_NOTFOUND;
|
||||
}
|
||||
|
||||
index_mf_to_mpoly = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX));
|
||||
CustomData_get_layer(&mesh_final->fdata_legacy, CD_ORIGINDEX));
|
||||
index_mp_to_orig = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX));
|
||||
BLI_assert(index_mf_to_mpoly);
|
||||
|
||||
if (mesh_original) {
|
||||
index_mf_to_mpoly_deformed = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX));
|
||||
CustomData_get_layer(&mesh_original->fdata_legacy, CD_ORIGINDEX));
|
||||
}
|
||||
else {
|
||||
BLI_assert(BKE_mesh_is_deformed_only(mesh_final));
|
||||
@@ -1985,10 +1985,10 @@ int psys_particle_dm_face_lookup(Mesh *mesh_final,
|
||||
|
||||
index_mf_to_mpoly_deformed = nullptr;
|
||||
|
||||
mtessface_final = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh_final->fdata, CD_MFACE, mesh_final->totface));
|
||||
osface_final = static_cast<OrigSpaceFace *>(
|
||||
CustomData_get_layer_for_write(&mesh_final->fdata, CD_ORIGSPACE, mesh_final->totface));
|
||||
mtessface_final = static_cast<MFace *>(CustomData_get_layer_for_write(
|
||||
&mesh_final->fdata_legacy, CD_MFACE, mesh_final->totface_legacy));
|
||||
osface_final = static_cast<OrigSpaceFace *>(CustomData_get_layer_for_write(
|
||||
&mesh_final->fdata_legacy, CD_ORIGSPACE, mesh_final->totface_legacy));
|
||||
|
||||
if (osface_final == nullptr) {
|
||||
/* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
|
||||
@@ -2000,7 +2000,7 @@ int psys_particle_dm_face_lookup(Mesh *mesh_final,
|
||||
printf("\tNO CD_ORIGSPACE, error out of range\n");
|
||||
return DMCACHE_NOTFOUND;
|
||||
}
|
||||
if (findex_orig >= mesh_original->totface) {
|
||||
if (findex_orig >= mesh_original->totface_legacy) {
|
||||
return DMCACHE_NOTFOUND; /* index not in the original mesh */
|
||||
}
|
||||
|
||||
@@ -2075,7 +2075,7 @@ static int psys_map_index_on_dm(Mesh *mesh,
|
||||
*mapindex = index;
|
||||
}
|
||||
else { /* FROM_FACE/FROM_VOLUME */
|
||||
if (index >= mesh->totface) {
|
||||
if (index >= mesh->totface_legacy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2098,7 +2098,7 @@ static int psys_map_index_on_dm(Mesh *mesh,
|
||||
/* find a face on the derived mesh that uses this face */
|
||||
int i = index_dmcache;
|
||||
|
||||
if (i == DMCACHE_NOTFOUND || i >= mesh->totface) {
|
||||
if (i == DMCACHE_NOTFOUND || i >= mesh->totface_legacy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2107,9 +2107,9 @@ static int psys_map_index_on_dm(Mesh *mesh,
|
||||
/* modify the original weights to become
|
||||
* weights for the derived mesh face */
|
||||
OrigSpaceFace *osface = static_cast<OrigSpaceFace *>(
|
||||
CustomData_get_layer_for_write(&mesh->fdata, CD_ORIGSPACE, mesh->totface));
|
||||
CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_ORIGSPACE, mesh->totface_legacy));
|
||||
const MFace *mfaces = static_cast<const MFace *>(
|
||||
CustomData_get_layer(&mesh->fdata, CD_MFACE));
|
||||
CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE));
|
||||
const MFace *mface = &mfaces[i];
|
||||
|
||||
if (osface == nullptr) {
|
||||
@@ -2192,12 +2192,12 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
||||
MFace *mface;
|
||||
MTFace *mtface;
|
||||
|
||||
MFace *mfaces = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh_final->fdata, CD_MFACE, mesh_final->totface));
|
||||
MFace *mfaces = static_cast<MFace *>(CustomData_get_layer_for_write(
|
||||
&mesh_final->fdata_legacy, CD_MFACE, mesh_final->totface_legacy));
|
||||
mface = &mfaces[mapindex];
|
||||
const blender::Span<blender::float3> vert_positions = mesh_final->vert_positions();
|
||||
mtface = static_cast<MTFace *>(
|
||||
CustomData_get_layer_for_write(&mesh_final->fdata, CD_MTFACE, mesh_final->totface));
|
||||
mtface = static_cast<MTFace *>(CustomData_get_layer_for_write(
|
||||
&mesh_final->fdata_legacy, CD_MTFACE, mesh_final->totface_legacy));
|
||||
|
||||
if (mtface) {
|
||||
mtface += mapindex;
|
||||
@@ -3042,7 +3042,7 @@ static void psys_thread_create_path(ParticleTask *task,
|
||||
cpa_num = ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND) ? pa->num : pa->num_dmcache;
|
||||
|
||||
/* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
|
||||
if (cpa_num > ctx->sim.psmd->mesh_final->totface) {
|
||||
if (cpa_num > ctx->sim.psmd->mesh_final->totface_legacy) {
|
||||
cpa_num = 0;
|
||||
}
|
||||
cpa_fuv = pa->fuv;
|
||||
@@ -3899,16 +3899,16 @@ static void psys_face_mat(Object *ob, Mesh *mesh, ParticleData *pa, float mat[4]
|
||||
const float(*orcodata)[3];
|
||||
|
||||
int i = ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND) ? pa->num : pa->num_dmcache;
|
||||
if (i == -1 || i >= mesh->totface) {
|
||||
if (i == -1 || i >= mesh->totface_legacy) {
|
||||
unit_m4(mat);
|
||||
return;
|
||||
}
|
||||
|
||||
MFace *mfaces = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface));
|
||||
CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
|
||||
mface = &mfaces[i];
|
||||
const OrigSpaceFace *osface = static_cast<const OrigSpaceFace *>(
|
||||
CustomData_get_for_write(&mesh->fdata, i, CD_ORIGSPACE, mesh->totface));
|
||||
CustomData_get_for_write(&mesh->fdata_legacy, i, CD_ORIGSPACE, mesh->totface_legacy));
|
||||
|
||||
if (orco &&
|
||||
(orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->vdata, CD_ORCO))))
|
||||
@@ -4217,14 +4217,16 @@ static int get_particle_uv(Mesh *mesh,
|
||||
float *texco,
|
||||
bool from_vert)
|
||||
{
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
MFace *mf;
|
||||
const MTFace *tf;
|
||||
int i;
|
||||
|
||||
tf = static_cast<const MTFace *>(CustomData_get_layer_named(&mesh->fdata, CD_MTFACE, name));
|
||||
tf = static_cast<const MTFace *>(
|
||||
CustomData_get_layer_named(&mesh->fdata_legacy, CD_MTFACE, name));
|
||||
if (tf == nullptr) {
|
||||
tf = static_cast<const MTFace *>(CustomData_get_layer(&mesh->fdata, CD_MTFACE));
|
||||
tf = static_cast<const MTFace *>(CustomData_get_layer(&mesh->fdata_legacy, CD_MTFACE));
|
||||
}
|
||||
if (tf == nullptr) {
|
||||
return 0;
|
||||
@@ -4232,7 +4234,7 @@ static int get_particle_uv(Mesh *mesh,
|
||||
|
||||
if (pa) {
|
||||
i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache;
|
||||
if ((!from_vert && i >= mesh->totface) || (from_vert && i >= mesh->totvert)) {
|
||||
if ((!from_vert && i >= mesh->totface_legacy) || (from_vert && i >= mesh->totvert)) {
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
@@ -4252,7 +4254,7 @@ static int get_particle_uv(Mesh *mesh,
|
||||
/* This finds the first face to contain the emitting vertex,
|
||||
* this is not ideal, but is mostly fine as UV seams generally
|
||||
* map to equal-colored parts of a texture */
|
||||
for (int j = 0; j < mesh->totface; j++, mf++) {
|
||||
for (int j = 0; j < mesh->totface_legacy; j++, mf++) {
|
||||
if (ELEM(i, mf->v1, mf->v2, mf->v3, mf->v4)) {
|
||||
i = j;
|
||||
break;
|
||||
@@ -5122,15 +5124,18 @@ void psys_get_dupli_texture(ParticleSystem *psys,
|
||||
if (cpa) {
|
||||
if ((part->childtype == PART_CHILD_FACES) && (psmd->mesh_final != nullptr)) {
|
||||
if (!is_grid) {
|
||||
CustomData *mtf_data = &psmd->mesh_final->fdata;
|
||||
CustomData *mtf_data = &psmd->mesh_final->fdata_legacy;
|
||||
const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
|
||||
|
||||
if (uv_idx >= 0) {
|
||||
const MTFace *mtface = static_cast<const MTFace *>(
|
||||
CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx));
|
||||
if (mtface != nullptr) {
|
||||
const MFace *mface = static_cast<const MFace *>(CustomData_get_for_write(
|
||||
&psmd->mesh_final->fdata, cpa->num, CD_MFACE, psmd->mesh_final->totface));
|
||||
const MFace *mface = static_cast<const MFace *>(
|
||||
CustomData_get_for_write(&psmd->mesh_final->fdata_legacy,
|
||||
cpa->num,
|
||||
CD_MFACE,
|
||||
psmd->mesh_final->totface_legacy));
|
||||
mtface += cpa->num;
|
||||
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
|
||||
}
|
||||
@@ -5161,21 +5166,21 @@ void psys_get_dupli_texture(ParticleSystem *psys,
|
||||
num = pa->num;
|
||||
}
|
||||
|
||||
if (num >= psmd->mesh_final->totface) {
|
||||
if (num >= psmd->mesh_final->totface_legacy) {
|
||||
/* happens when simplify is enabled
|
||||
* gives invalid coords but would crash otherwise */
|
||||
num = DMCACHE_NOTFOUND;
|
||||
}
|
||||
|
||||
if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
|
||||
CustomData *mtf_data = &psmd->mesh_final->fdata;
|
||||
CustomData *mtf_data = &psmd->mesh_final->fdata_legacy;
|
||||
const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
|
||||
|
||||
if (uv_idx >= 0) {
|
||||
const MTFace *mtface = static_cast<const MTFace *>(
|
||||
CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx));
|
||||
const MFace *mface = static_cast<const MFace *>(CustomData_get_for_write(
|
||||
&psmd->mesh_final->fdata, num, CD_MFACE, psmd->mesh_final->totface));
|
||||
&psmd->mesh_final->fdata_legacy, num, CD_MFACE, psmd->mesh_final->totface_legacy));
|
||||
mtface += num;
|
||||
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
|
||||
}
|
||||
|
||||
@@ -180,9 +180,9 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys)
|
||||
int a, a1, a2, a0mul, a1mul, a2mul, totface;
|
||||
int amax = from == PART_FROM_FACE ? 3 : 1;
|
||||
|
||||
totface = mesh->totface;
|
||||
totface = mesh->totface_legacy;
|
||||
mface = mface_array = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface));
|
||||
CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
|
||||
|
||||
for (a = 0; a < amax; a++) {
|
||||
if (a == 0) {
|
||||
@@ -466,8 +466,8 @@ static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, i
|
||||
ParticleThreadContext *ctx = thread->ctx;
|
||||
MFace *mface;
|
||||
|
||||
mface = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&ctx->mesh->fdata, CD_MFACE, ctx->mesh->totface));
|
||||
mface = static_cast<MFace *>(CustomData_get_layer_for_write(
|
||||
&ctx->mesh->fdata_legacy, CD_MFACE, ctx->mesh->totface_legacy));
|
||||
|
||||
int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
|
||||
|
||||
@@ -481,7 +481,7 @@ static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, i
|
||||
/* This finds the first face to contain the emitting vertex,
|
||||
* this is not ideal, but is mostly fine as UV seams generally
|
||||
* map to equal-colored parts of a texture */
|
||||
for (int i = 0; i < ctx->mesh->totface; i++, mface++) {
|
||||
for (int i = 0; i < ctx->mesh->totface_legacy; i++, mface++) {
|
||||
if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) {
|
||||
uint *vert = &mface->v1;
|
||||
|
||||
@@ -528,7 +528,8 @@ static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, i
|
||||
int i;
|
||||
int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
|
||||
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
MFace *mface;
|
||||
|
||||
pa->num = i = ctx->index[p];
|
||||
@@ -583,7 +584,8 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
|
||||
pa->num = i = ctx->index[p];
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
mface = &mfaces[i];
|
||||
|
||||
switch (distr) {
|
||||
@@ -615,7 +617,7 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
|
||||
pa->foffset = 0.0f;
|
||||
|
||||
/* experimental */
|
||||
tot = mesh->totface;
|
||||
tot = mesh->totface_legacy;
|
||||
|
||||
psys_interpolate_face(
|
||||
mesh, positions, BKE_mesh_vert_normals_ensure(mesh), mface, 0, 0, pa->fuv, co, nor, 0, 0, 0);
|
||||
@@ -626,7 +628,7 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
|
||||
min_d = FLT_MAX;
|
||||
intersect = 0;
|
||||
mface = static_cast<MFace *>(
|
||||
CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface));
|
||||
CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
|
||||
for (i = 0; i < tot; i++, mface++) {
|
||||
if (i == pa->num) {
|
||||
continue;
|
||||
@@ -696,7 +698,8 @@ static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, i
|
||||
return;
|
||||
}
|
||||
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
mf = &mfaces[ctx->index[p]];
|
||||
|
||||
randu = BLI_rng_get_float(thread->rng);
|
||||
@@ -905,7 +908,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
||||
}
|
||||
|
||||
if (!BKE_mesh_is_deformed_only(final_mesh) &&
|
||||
!CustomData_get_layer(&final_mesh->fdata, CD_ORIGINDEX))
|
||||
!CustomData_get_layer(&final_mesh->fdata_legacy, CD_ORIGINDEX))
|
||||
{
|
||||
printf(
|
||||
"Can't create particles with the current modifier stack, disable destructive modifiers\n");
|
||||
@@ -1023,7 +1026,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
||||
}
|
||||
|
||||
/* Get total number of emission elements and allocate needed arrays */
|
||||
totelem = (from == PART_FROM_VERT) ? mesh->totvert : mesh->totface;
|
||||
totelem = (from == PART_FROM_VERT) ? mesh->totvert : mesh->totface_legacy;
|
||||
|
||||
if (totelem == 0) {
|
||||
distribute_invalid(sim, children ? PART_FROM_CHILD : 0);
|
||||
@@ -1056,7 +1059,8 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
||||
|
||||
orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->vdata, CD_ORCO));
|
||||
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
for (i = 0; i < totelem; i++) {
|
||||
MFace *mf = &mfaces[i];
|
||||
|
||||
@@ -1118,7 +1122,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
||||
}
|
||||
else { /* PART_FROM_FACE / PART_FROM_VOLUME */
|
||||
MFace *mfaces = (MFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata, CD_MFACE, mesh->totface);
|
||||
&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
|
||||
for (i = 0; i < totelem; i++) {
|
||||
MFace *mf = &mfaces[i];
|
||||
tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
|
||||
@@ -1243,8 +1247,9 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mesh->totface) {
|
||||
orig_index = static_cast<const int *>(CustomData_get_layer(&mesh->fdata, CD_ORIGINDEX));
|
||||
if (mesh->totface_legacy) {
|
||||
orig_index = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh->fdata_legacy, CD_ORIGINDEX));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
|
||||
}
|
||||
}
|
||||
else { /* FROM_FACE/FROM_VOLUME */
|
||||
totdmelem = mesh_final->totface;
|
||||
totdmelem = mesh_final->totface_legacy;
|
||||
|
||||
if (use_modifier_stack) {
|
||||
totelem = totdmelem;
|
||||
@@ -351,9 +351,9 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
|
||||
origindex_poly = nullptr;
|
||||
}
|
||||
else {
|
||||
totelem = mesh_original->totface;
|
||||
totelem = mesh_original->totface_legacy;
|
||||
origindex = static_cast<const int *>(
|
||||
CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX));
|
||||
CustomData_get_layer(&mesh_final->fdata_legacy, CD_ORIGINDEX));
|
||||
|
||||
/* for face lookups we need the poly origindex too */
|
||||
origindex_poly = static_cast<const int *>(
|
||||
|
||||
@@ -194,7 +194,7 @@ static int partition_indices_faces(int *prim_indices,
|
||||
int axis,
|
||||
float mid,
|
||||
BBC *prim_bbc,
|
||||
const int *looptri_polys)
|
||||
const int *looptri_faces)
|
||||
{
|
||||
for (int i = lo; i < hi; i++) {
|
||||
prim_scratch[i - lo] = prim_indices[i];
|
||||
@@ -204,10 +204,10 @@ static int partition_indices_faces(int *prim_indices,
|
||||
int i1 = lo, i2 = 0;
|
||||
|
||||
while (i1 < hi) {
|
||||
const int poly_i = looptri_polys[prim_scratch[i2]];
|
||||
const int face_i = looptri_faces[prim_scratch[i2]];
|
||||
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
|
||||
|
||||
while (i1 < hi && looptri_polys[prim_scratch[i2]] == poly_i) {
|
||||
while (i1 < hi && looptri_faces[prim_scratch[i2]] == face_i) {
|
||||
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
|
||||
i1++;
|
||||
i2++;
|
||||
@@ -234,10 +234,10 @@ static int partition_indices_grids(int *prim_indices,
|
||||
int i1 = lo, i2 = 0;
|
||||
|
||||
while (i1 < hi) {
|
||||
int poly_i = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
|
||||
int face_i = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
|
||||
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
|
||||
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == poly_i) {
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == face_i) {
|
||||
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
|
||||
i1++;
|
||||
i2++;
|
||||
@@ -251,20 +251,20 @@ static int partition_indices_grids(int *prim_indices,
|
||||
static int partition_indices_material(
|
||||
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi)
|
||||
{
|
||||
const int *looptri_polys = pbvh->looptri_polys;
|
||||
const int *looptri_faces = pbvh->looptri_faces;
|
||||
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
|
||||
const int *indices = pbvh->prim_indices;
|
||||
int i = lo, j = hi;
|
||||
|
||||
for (;;) {
|
||||
if (pbvh->looptri_polys) {
|
||||
const int first = looptri_polys[pbvh->prim_indices[lo]];
|
||||
for (; face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[i]]);
|
||||
if (pbvh->looptri_faces) {
|
||||
const int first = looptri_faces[pbvh->prim_indices[lo]];
|
||||
for (; face_materials_match(material_indices, sharp_faces, first, looptri_faces[indices[i]]);
|
||||
i++) {
|
||||
/* pass */
|
||||
}
|
||||
for (;
|
||||
!face_materials_match(material_indices, sharp_faces, first, looptri_polys[indices[j]]);
|
||||
!face_materials_match(material_indices, sharp_faces, first, looptri_faces[indices[j]]);
|
||||
j--) {
|
||||
/* pass */
|
||||
}
|
||||
@@ -351,7 +351,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
|
||||
}
|
||||
|
||||
if (has_visible == false) {
|
||||
if (!paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, node->prim_indices[i])) {
|
||||
if (!paint_is_face_hidden(pbvh->looptri_faces, pbvh->hide_poly, node->prim_indices[i])) {
|
||||
has_visible = true;
|
||||
}
|
||||
}
|
||||
@@ -477,10 +477,10 @@ static bool leaf_needs_material_split(
|
||||
}
|
||||
|
||||
if (pbvh->looptri) {
|
||||
const int first = pbvh->looptri_polys[pbvh->prim_indices[offset]];
|
||||
const int first = pbvh->looptri_faces[pbvh->prim_indices[offset]];
|
||||
for (int i = offset + count - 1; i > offset; i--) {
|
||||
int prim = pbvh->prim_indices[i];
|
||||
if (!face_materials_match(material_indices, sharp_faces, first, pbvh->looptri_polys[prim])) {
|
||||
if (!face_materials_match(material_indices, sharp_faces, first, pbvh->looptri_faces[prim])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -518,21 +518,21 @@ static void test_face_boundaries(PBVH *pbvh)
|
||||
switch (BKE_pbvh_type(pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
int face_i = pbvh->looptri_faces[node->prim_indices[j]];
|
||||
|
||||
if (node_map[poly_i] >= 0 && node_map[poly_i] != i) {
|
||||
int old_i = node_map[poly_i];
|
||||
if (node_map[face_i] >= 0 && node_map[face_i] != i) {
|
||||
int old_i = node_map[face_i];
|
||||
int prim_i = node->prim_indices - pbvh->prim_indices + j;
|
||||
|
||||
printf("PBVH split error; poly: %d, prim_i: %d, node1: %d, node2: %d, totprim: %d\n",
|
||||
poly_i,
|
||||
printf("PBVH split error; face: %d, prim_i: %d, node1: %d, node2: %d, totprim: %d\n",
|
||||
face_i,
|
||||
prim_i,
|
||||
old_i,
|
||||
i,
|
||||
node->totprim);
|
||||
}
|
||||
|
||||
node_map[poly_i] = i;
|
||||
node_map[face_i] = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -617,7 +617,7 @@ static void build_sub(PBVH *pbvh,
|
||||
axis,
|
||||
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
|
||||
prim_bbc,
|
||||
pbvh->looptri_polys);
|
||||
pbvh->looptri_faces);
|
||||
}
|
||||
else {
|
||||
end = partition_indices_grids(pbvh->prim_indices,
|
||||
@@ -712,7 +712,7 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
args->corner_verts = {pbvh->corner_verts, pbvh->mesh->totloop};
|
||||
args->corner_edges = pbvh->mesh->corner_edges();
|
||||
}
|
||||
args->polys = pbvh->polys;
|
||||
args->faces = pbvh->faces;
|
||||
args->mlooptri = pbvh->looptri;
|
||||
|
||||
if (ELEM(pbvh->header.type, PBVH_FACES, PBVH_GRIDS)) {
|
||||
@@ -723,13 +723,13 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
|
||||
switch (pbvh->header.type) {
|
||||
case PBVH_FACES:
|
||||
args->mesh_faces_num = pbvh->mesh->totpoly;
|
||||
args->mesh_faces_num = pbvh->mesh->faces_num;
|
||||
args->vdata = pbvh->vdata;
|
||||
args->ldata = pbvh->ldata;
|
||||
args->pdata = pbvh->pdata;
|
||||
args->totprim = node->totprim;
|
||||
args->me = pbvh->mesh;
|
||||
args->polys = pbvh->polys;
|
||||
args->faces = pbvh->faces;
|
||||
args->vert_normals = pbvh->vert_normals;
|
||||
|
||||
args->active_color = pbvh->mesh->active_color_attribute;
|
||||
@@ -737,7 +737,7 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
|
||||
args->prim_indices = node->prim_indices;
|
||||
args->face_sets = pbvh->face_sets;
|
||||
args->looptri_polys = pbvh->looptri_polys;
|
||||
args->looptri_faces = pbvh->looptri_faces;
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
args->vdata = pbvh->vdata;
|
||||
@@ -749,7 +749,7 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
args->grid_indices = node->prim_indices;
|
||||
args->subdiv_ccg = pbvh->subdiv_ccg;
|
||||
args->face_sets = pbvh->face_sets;
|
||||
args->polys = pbvh->polys;
|
||||
args->faces = pbvh->faces;
|
||||
|
||||
args->active_color = pbvh->mesh->active_color_attribute;
|
||||
args->render_color = pbvh->mesh->default_color_attribute;
|
||||
@@ -761,7 +761,7 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
args->vert_normals = pbvh->vert_normals;
|
||||
|
||||
args->face_sets = pbvh->face_sets;
|
||||
args->looptri_polys = pbvh->looptri_polys;
|
||||
args->looptri_faces = pbvh->looptri_faces;
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
args->bm = pbvh->header.bm;
|
||||
@@ -795,16 +795,16 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
|
||||
}
|
||||
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly_i;
|
||||
int face_i;
|
||||
|
||||
if (pbvh->header.type == PBVH_FACES) {
|
||||
poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
face_i = pbvh->looptri_faces[node->prim_indices[j]];
|
||||
}
|
||||
else {
|
||||
poly_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
face_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
}
|
||||
|
||||
totface = max_ii(totface, poly_i + 1);
|
||||
totface = max_ii(totface, face_i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,23 +822,23 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
|
||||
}
|
||||
|
||||
for (int j = 0; j < node->totprim; j++) {
|
||||
int poly_i;
|
||||
int face_i;
|
||||
|
||||
if (pbvh->header.type == PBVH_FACES) {
|
||||
poly_i = pbvh->looptri_polys[node->prim_indices[j]];
|
||||
face_i = pbvh->looptri_faces[node->prim_indices[j]];
|
||||
}
|
||||
else {
|
||||
poly_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
face_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
|
||||
}
|
||||
|
||||
if (facemap[poly_i] != -1 && facemap[poly_i] != i) {
|
||||
if (facemap[face_i] != -1 && facemap[face_i] != i) {
|
||||
printf("%s: error: face spanned multiple nodes (old: %d new: %d)\n",
|
||||
__func__,
|
||||
facemap[poly_i],
|
||||
facemap[face_i],
|
||||
i);
|
||||
}
|
||||
|
||||
facemap[poly_i] = i;
|
||||
facemap[face_i] = i;
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(facemap);
|
||||
@@ -849,9 +849,9 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_FACES);
|
||||
|
||||
pbvh->polys = mesh->polys();
|
||||
pbvh->faces = mesh->faces();
|
||||
pbvh->corner_verts = mesh->corner_verts().data();
|
||||
pbvh->looptri_polys = mesh->looptri_polys().data();
|
||||
pbvh->looptri_faces = mesh->looptri_faces().data();
|
||||
|
||||
if (!pbvh->deformed) {
|
||||
/* Deformed positions not matching the original mesh are owned directly by the PBVH, and are
|
||||
@@ -860,16 +860,16 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||
}
|
||||
|
||||
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->faces_num));
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
|
||||
|
||||
/* Make sure cached normals start out calculated. */
|
||||
mesh->vert_normals();
|
||||
mesh->poly_normals();
|
||||
mesh->face_normals();
|
||||
|
||||
pbvh->vert_normals = mesh->runtime->vert_normals;
|
||||
pbvh->poly_normals = mesh->runtime->poly_normals;
|
||||
pbvh->face_normals = mesh->runtime->face_normals;
|
||||
|
||||
pbvh->vdata = &mesh->vdata;
|
||||
pbvh->ldata = &mesh->ldata;
|
||||
@@ -882,15 +882,15 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||
BB cb;
|
||||
|
||||
const int totvert = mesh->totvert;
|
||||
const int looptri_num = poly_to_tri_count(mesh->totpoly, mesh->totloop);
|
||||
const int looptri_num = poly_to_tri_count(mesh->faces_num, mesh->totloop);
|
||||
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||
const blender::OffsetIndices<int> polys = mesh->polys();
|
||||
const blender::OffsetIndices<int> faces = mesh->faces();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
MLoopTri *looptri = static_cast<MLoopTri *>(
|
||||
MEM_malloc_arrayN(looptri_num, sizeof(*looptri), __func__));
|
||||
|
||||
blender::bke::mesh::looptris_calc(vert_positions, polys, corner_verts, {looptri, looptri_num});
|
||||
blender::bke::mesh::looptris_calc(vert_positions, faces, corner_verts, {looptri, looptri_num});
|
||||
|
||||
pbvh->mesh = mesh;
|
||||
pbvh->header.type = PBVH_FACES;
|
||||
@@ -912,7 +912,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||
pbvh->leaf_limit = LEAF_LIMIT;
|
||||
#endif
|
||||
|
||||
pbvh->faces_num = mesh->totpoly;
|
||||
pbvh->faces_num = mesh->faces_num;
|
||||
|
||||
pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
|
||||
pbvh->face_sets_color_default = mesh->face_sets_color_default;
|
||||
@@ -982,13 +982,13 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
||||
pbvh->gridkey = *key;
|
||||
pbvh->grid_hidden = grid_hidden;
|
||||
pbvh->subdiv_ccg = subdiv_ccg;
|
||||
pbvh->faces_num = me->totpoly;
|
||||
pbvh->faces_num = me->faces_num;
|
||||
|
||||
/* Find maximum number of grids per face. */
|
||||
int max_grids = 1;
|
||||
const blender::OffsetIndices polys = me->polys();
|
||||
for (const int i : polys.index_range()) {
|
||||
max_grids = max_ii(max_grids, polys[i].size());
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
for (const int i : faces.index_range()) {
|
||||
max_grids = max_ii(max_grids, faces[i].size());
|
||||
}
|
||||
|
||||
/* Ensure leaf limit is at least 4 so there's room
|
||||
@@ -1002,7 +1002,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
||||
pbvh->ldata = &me->ldata;
|
||||
pbvh->pdata = &me->pdata;
|
||||
|
||||
pbvh->polys = polys;
|
||||
pbvh->faces = faces;
|
||||
pbvh->corner_verts = me->corner_verts().data();
|
||||
|
||||
/* We also need the base mesh for PBVH draw. */
|
||||
@@ -1379,41 +1379,41 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const Span<float3> positions = pbvh->vert_positions;
|
||||
const OffsetIndices polys = pbvh->polys;
|
||||
const OffsetIndices faces = pbvh->faces;
|
||||
const Span<int> corner_verts(pbvh->corner_verts, pbvh->mesh->totloop);
|
||||
|
||||
MutableSpan<bool> update_tags(pbvh->vert_bitmap, pbvh->totvert);
|
||||
|
||||
VectorSet<int> polys_to_update;
|
||||
VectorSet<int> faces_to_update;
|
||||
for (const PBVHNode *node : nodes) {
|
||||
for (const int vert : Span(node->vert_indices, node->uniq_verts)) {
|
||||
if (update_tags[vert]) {
|
||||
polys_to_update.add_multiple(pbvh->pmap[vert]);
|
||||
faces_to_update.add_multiple(pbvh->pmap[vert]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (polys_to_update.is_empty()) {
|
||||
if (faces_to_update.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutableSpan<float3> vert_normals = pbvh->vert_normals;
|
||||
MutableSpan<float3> poly_normals = pbvh->poly_normals;
|
||||
MutableSpan<float3> face_normals = pbvh->face_normals;
|
||||
|
||||
VectorSet<int> verts_to_update;
|
||||
threading::parallel_invoke(
|
||||
[&]() {
|
||||
threading::parallel_for(polys_to_update.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int i : polys_to_update.as_span().slice(range)) {
|
||||
poly_normals[i] = mesh::poly_normal_calc(positions, corner_verts.slice(polys[i]));
|
||||
threading::parallel_for(faces_to_update.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int i : faces_to_update.as_span().slice(range)) {
|
||||
face_normals[i] = mesh::face_normal_calc(positions, corner_verts.slice(faces[i]));
|
||||
}
|
||||
});
|
||||
},
|
||||
[&]() {
|
||||
/* Update all normals connected to affected faces, even if not explicitly tagged. */
|
||||
verts_to_update.reserve(polys_to_update.size());
|
||||
for (const int poly : polys_to_update) {
|
||||
verts_to_update.add_multiple(corner_verts.slice(polys[poly]));
|
||||
verts_to_update.reserve(faces_to_update.size());
|
||||
for (const int face : faces_to_update) {
|
||||
verts_to_update.add_multiple(corner_verts.slice(faces[face]));
|
||||
}
|
||||
|
||||
for (const int vert : verts_to_update) {
|
||||
@@ -1427,8 +1427,8 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
|
||||
threading::parallel_for(verts_to_update.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int vert : verts_to_update.as_span().slice(range)) {
|
||||
float3 normal(0.0f);
|
||||
for (const int poly : pbvh->pmap[vert]) {
|
||||
normal += poly_normals[poly];
|
||||
for (const int face : pbvh->pmap[vert]) {
|
||||
normal += face_normals[face];
|
||||
}
|
||||
vert_normals[vert] = math::normalize(normal);
|
||||
}
|
||||
@@ -2456,7 +2456,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
||||
const MLoopTri *lt = &pbvh->looptri[looptri_i];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, looptri_i)) {
|
||||
if (paint_is_face_hidden(pbvh->looptri_faces, pbvh->hide_poly, looptri_i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2492,7 +2492,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
|
||||
len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
|
||||
copy_v3_v3(nearest_vertex_co, co[j]);
|
||||
r_active_vertex->i = corner_verts[lt->tri[j]];
|
||||
*r_active_face_index = pbvh->looptri_polys[looptri_i];
|
||||
*r_active_face_index = pbvh->looptri_faces[looptri_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2804,7 +2804,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
|
||||
const MLoopTri *lt = &pbvh->looptri[looptri_i];
|
||||
const int *face_verts = node->face_vert_indices[i];
|
||||
|
||||
if (paint_is_face_hidden(pbvh->looptri_polys, pbvh->hide_poly, looptri_i)) {
|
||||
if (paint_is_face_hidden(pbvh->looptri_faces, pbvh->hide_poly, looptri_i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3430,7 +3430,7 @@ void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh)
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&pbvh->mesh->vdata, CD_PROP_BOOL, ".hide_vert", pbvh->mesh->totvert));
|
||||
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&pbvh->mesh->pdata, CD_PROP_BOOL, ".hide_poly", pbvh->mesh->totpoly));
|
||||
&pbvh->mesh->pdata, CD_PROP_BOOL, ".hide_poly", pbvh->mesh->faces_num));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3546,7 +3546,7 @@ BLI_INLINE int face_iter_prim_to_face(PBVHFaceIter *fd, int prim_index)
|
||||
return BKE_subdiv_ccg_grid_to_face_index(fd->subdiv_ccg_, prim_index);
|
||||
}
|
||||
|
||||
return fd->looptri_polys_[prim_index];
|
||||
return fd->looptri_faces_[prim_index];
|
||||
}
|
||||
|
||||
static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
||||
@@ -3588,15 +3588,15 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
||||
}
|
||||
case PBVH_GRIDS:
|
||||
case PBVH_FACES: {
|
||||
int poly_i = 0;
|
||||
int face_i = 0;
|
||||
|
||||
if (do_step) {
|
||||
fd->prim_index_++;
|
||||
|
||||
while (fd->prim_index_ < fd->node_->totprim) {
|
||||
poly_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
face_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
|
||||
if (poly_i != fd->last_poly_index_) {
|
||||
if (face_i != fd->last_face_index_) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3604,29 +3604,29 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
||||
}
|
||||
}
|
||||
else if (fd->prim_index_ < fd->node_->totprim) {
|
||||
poly_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
face_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
|
||||
}
|
||||
|
||||
if (fd->prim_index_ >= fd->node_->totprim) {
|
||||
return;
|
||||
}
|
||||
|
||||
fd->last_poly_index_ = poly_i;
|
||||
const int poly_start = fd->poly_offsets_[poly_i];
|
||||
const int poly_size = fd->poly_offsets_[poly_i + 1] - poly_start;
|
||||
fd->last_face_index_ = face_i;
|
||||
const int poly_start = fd->face_offsets_[face_i];
|
||||
const int poly_size = fd->face_offsets_[face_i + 1] - poly_start;
|
||||
|
||||
fd->face.i = fd->index = poly_i;
|
||||
fd->face.i = fd->index = face_i;
|
||||
|
||||
if (fd->face_sets_) {
|
||||
fd->face_set = fd->face_sets_ + poly_i;
|
||||
fd->face_set = fd->face_sets_ + face_i;
|
||||
}
|
||||
if (fd->hide_poly_) {
|
||||
fd->hide = fd->hide_poly_ + poly_i;
|
||||
fd->hide = fd->hide_poly_ + face_i;
|
||||
}
|
||||
|
||||
pbvh_face_iter_verts_reserve(fd, poly_size);
|
||||
|
||||
const int *poly_verts = &fd->corner_verts_[poly_start];
|
||||
const int *face_verts = &fd->corner_verts_[poly_start];
|
||||
const int grid_area = fd->subdiv_key_.grid_area;
|
||||
|
||||
for (int i = 0; i < poly_size; i++) {
|
||||
@@ -3635,7 +3635,7 @@ static void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
|
||||
fd->verts[i].i = (poly_start + i) * grid_area + grid_area - 1;
|
||||
}
|
||||
else {
|
||||
fd->verts[i].i = poly_verts[i];
|
||||
fd->verts[i].i = face_verts[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3663,12 +3663,12 @@ void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd)
|
||||
fd->subdiv_key_ = pbvh->gridkey;
|
||||
ATTR_FALLTHROUGH;
|
||||
case PBVH_FACES:
|
||||
fd->poly_offsets_ = pbvh->polys.data();
|
||||
fd->face_offsets_ = pbvh->faces.data();
|
||||
fd->corner_verts_ = pbvh->corner_verts;
|
||||
fd->looptri_polys_ = pbvh->looptri_polys;
|
||||
fd->looptri_faces_ = pbvh->looptri_faces;
|
||||
fd->hide_poly_ = pbvh->hide_poly;
|
||||
fd->face_sets_ = pbvh->face_sets;
|
||||
fd->last_poly_index_ = -1;
|
||||
fd->last_face_index_ = -1;
|
||||
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
@@ -3745,19 +3745,19 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
CCGKey key = pbvh->gridkey;
|
||||
|
||||
bool *hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->faces_num));
|
||||
|
||||
bool delete_hide_poly = true;
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[poly_i];
|
||||
for (const int face_i : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[face_i];
|
||||
bool hidden = false;
|
||||
|
||||
for (int loop_index = 0; !hidden && loop_index < poly.size(); loop_index++) {
|
||||
int grid_index = poly[loop_index];
|
||||
for (int loop_index = 0; !hidden && loop_index < face.size(); loop_index++) {
|
||||
int grid_index = face[loop_index];
|
||||
|
||||
if (pbvh->grid_hidden[grid_index] &&
|
||||
BLI_BITMAP_TEST(pbvh->grid_hidden[grid_index], key.grid_area - 1))
|
||||
@@ -3770,25 +3770,25 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
|
||||
|
||||
if (hidden && !hide_poly) {
|
||||
hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->faces_num));
|
||||
|
||||
if (!hide_poly) {
|
||||
hide_poly = static_cast<bool *>(CustomData_add_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, mesh->totpoly, ".hide_poly"));
|
||||
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, mesh->faces_num, ".hide_poly"));
|
||||
}
|
||||
}
|
||||
|
||||
if (hide_poly) {
|
||||
delete_hide_poly = delete_hide_poly && !hidden;
|
||||
hide_poly[poly_i] = hidden;
|
||||
hide_poly[face_i] = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_hide_poly) {
|
||||
CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->totpoly);
|
||||
CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->faces_num);
|
||||
}
|
||||
|
||||
BKE_mesh_flush_hidden_from_polys(mesh);
|
||||
BKE_mesh_flush_hidden_from_faces(mesh);
|
||||
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -93,13 +93,13 @@ static void pbvh_vertex_color_get(const PBVH &pbvh, PBVHVertRef vertex, float r_
|
||||
if (pbvh.color_domain == ATTR_DOMAIN_CORNER) {
|
||||
int count = 0;
|
||||
zero_v4(r_color);
|
||||
for (const int i_poly : pbvh.pmap[index]) {
|
||||
const IndexRange poly = pbvh.polys[i_poly];
|
||||
Span<T> colors{static_cast<const T *>(pbvh.color_layer->data) + poly.start(), poly.size()};
|
||||
Span<int> poly_verts{pbvh.corner_verts + poly.start(), poly.size()};
|
||||
for (const int i_face : pbvh.pmap[index]) {
|
||||
const IndexRange face = pbvh.faces[i_face];
|
||||
Span<T> colors{static_cast<const T *>(pbvh.color_layer->data) + face.start(), face.size()};
|
||||
Span<int> face_verts{pbvh.corner_verts + face.start(), face.size()};
|
||||
|
||||
for (const int i : IndexRange(poly.size())) {
|
||||
if (poly_verts[i] == index) {
|
||||
for (const int i : IndexRange(face.size())) {
|
||||
if (face_verts[i] == index) {
|
||||
float temp[4];
|
||||
to_float(colors[i], temp);
|
||||
|
||||
@@ -124,13 +124,13 @@ static void pbvh_vertex_color_set(PBVH &pbvh, PBVHVertRef vertex, const float co
|
||||
int index = vertex.i;
|
||||
|
||||
if (pbvh.color_domain == ATTR_DOMAIN_CORNER) {
|
||||
for (const int i_poly : pbvh.pmap[index]) {
|
||||
const IndexRange poly = pbvh.polys[i_poly];
|
||||
MutableSpan<T> colors{static_cast<T *>(pbvh.color_layer->data) + poly.start(), poly.size()};
|
||||
Span<int> poly_verts{pbvh.corner_verts + poly.start(), poly.size()};
|
||||
for (const int i_face : pbvh.pmap[index]) {
|
||||
const IndexRange face = pbvh.faces[i_face];
|
||||
MutableSpan<T> colors{static_cast<T *>(pbvh.color_layer->data) + face.start(), face.size()};
|
||||
Span<int> face_verts{pbvh.corner_verts + face.start(), face.size()};
|
||||
|
||||
for (const int i : IndexRange(poly.size())) {
|
||||
if (poly_verts[i] == index) {
|
||||
for (const int i : IndexRange(face.size())) {
|
||||
if (face_verts[i] == index) {
|
||||
from_float(color, colors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,18 +158,18 @@ struct PBVH {
|
||||
|
||||
/* NOTE: Normals are not `const` because they can be updated for drawing by sculpt code. */
|
||||
blender::MutableSpan<blender::float3> vert_normals;
|
||||
blender::MutableSpan<blender::float3> poly_normals;
|
||||
blender::MutableSpan<blender::float3> face_normals;
|
||||
bool *hide_vert;
|
||||
blender::MutableSpan<blender::float3> vert_positions;
|
||||
/** Local vertex positions owned by the PVBH when not sculpting base mesh positions directly. */
|
||||
blender::Array<blender::float3> vert_positions_deformed;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
bool *hide_poly;
|
||||
/** Only valid for polygon meshes. */
|
||||
const int *corner_verts;
|
||||
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
|
||||
const MLoopTri *looptri;
|
||||
const int *looptri_polys;
|
||||
const int *looptri_faces;
|
||||
CustomData *vdata;
|
||||
CustomData *ldata;
|
||||
CustomData *pdata;
|
||||
|
||||
@@ -115,7 +115,7 @@ bool BKE_shrinkwrap_init_tree(
|
||||
}
|
||||
|
||||
data->mesh = mesh;
|
||||
data->poly_offsets = mesh->poly_offsets().data();
|
||||
data->face_offsets = mesh->face_offsets().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 *>(
|
||||
@@ -127,7 +127,7 @@ bool BKE_shrinkwrap_init_tree(
|
||||
return data->bvh != nullptr;
|
||||
}
|
||||
|
||||
if (mesh->totpoly <= 0) {
|
||||
if (mesh->faces_num <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ bool BKE_shrinkwrap_init_tree(
|
||||
}
|
||||
|
||||
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
|
||||
data->poly_normals = reinterpret_cast<const float(*)[3]>(mesh->poly_normals().data());
|
||||
data->face_normals = reinterpret_cast<const float(*)[3]>(mesh->face_normals().data());
|
||||
if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
|
||||
data->clnors = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
}
|
||||
@@ -1189,10 +1189,10 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
||||
const BVHTreeFromMesh *treeData = &tree->treeData;
|
||||
const MLoopTri *tri = &treeData->looptri[looptri_idx];
|
||||
const float(*vert_normals)[3] = tree->vert_normals;
|
||||
const int poly_i = tree->mesh->looptri_polys()[looptri_idx];
|
||||
const int face_i = tree->mesh->looptri_faces()[looptri_idx];
|
||||
|
||||
/* Interpolate smooth normals if enabled. */
|
||||
if (!(tree->sharp_faces && tree->sharp_faces[poly_i])) {
|
||||
if (!(tree->sharp_faces && tree->sharp_faces[face_i])) {
|
||||
const int vert_indices[3] = {treeData->corner_verts[tri->tri[0]],
|
||||
treeData->corner_verts[tri->tri[1]],
|
||||
treeData->corner_verts[tri->tri[2]]};
|
||||
@@ -1234,9 +1234,9 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
||||
normalize_v3(r_no);
|
||||
}
|
||||
}
|
||||
/* Use the polygon normal if flat. */
|
||||
else if (tree->poly_normals != nullptr) {
|
||||
copy_v3_v3(r_no, tree->poly_normals[poly_i]);
|
||||
/* Use the face normal if flat. */
|
||||
else if (tree->face_normals != nullptr) {
|
||||
copy_v3_v3(r_no, tree->face_normals[face_i]);
|
||||
}
|
||||
/* Finally fallback to the looptri normal. */
|
||||
else {
|
||||
|
||||
@@ -474,7 +474,7 @@ static Mesh *try_load_mesh(const DictionaryValue &io_geometry,
|
||||
CustomData_free_layer_named(&mesh->ldata, ".corner_edge", 0);
|
||||
mesh->totvert = io_mesh->lookup_int("num_vertices").value_or(0);
|
||||
mesh->totedge = io_mesh->lookup_int("num_edges").value_or(0);
|
||||
mesh->totpoly = io_mesh->lookup_int("num_polygons").value_or(0);
|
||||
mesh->faces_num = io_mesh->lookup_int("num_polygons").value_or(0);
|
||||
mesh->totloop = io_mesh->lookup_int("num_corners").value_or(0);
|
||||
|
||||
auto cancel = [&]() {
|
||||
@@ -482,17 +482,17 @@ static Mesh *try_load_mesh(const DictionaryValue &io_geometry,
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (mesh->totpoly > 0) {
|
||||
const auto io_poly_offsets = io_mesh->lookup_dict("poly_offsets");
|
||||
if (!io_poly_offsets) {
|
||||
if (mesh->faces_num > 0) {
|
||||
const auto io_face_offsets = io_mesh->lookup_dict("face_offsets");
|
||||
if (!io_face_offsets) {
|
||||
return cancel();
|
||||
}
|
||||
if (!read_bdata_shared_simple_span(*io_poly_offsets,
|
||||
if (!read_bdata_shared_simple_span(*io_face_offsets,
|
||||
bdata_reader,
|
||||
bdata_sharing,
|
||||
mesh->totpoly + 1,
|
||||
&mesh->poly_offset_indices,
|
||||
&mesh->runtime->poly_offsets_sharing_info))
|
||||
mesh->faces_num + 1,
|
||||
&mesh->face_offset_indices,
|
||||
&mesh->runtime->face_offsets_sharing_info))
|
||||
{
|
||||
return cancel();
|
||||
}
|
||||
@@ -647,15 +647,15 @@ static std::shared_ptr<DictionaryValue> serialize_geometry_set(const GeometrySet
|
||||
|
||||
io_mesh->append_int("num_vertices", mesh.totvert);
|
||||
io_mesh->append_int("num_edges", mesh.totedge);
|
||||
io_mesh->append_int("num_polygons", mesh.totpoly);
|
||||
io_mesh->append_int("num_polygons", mesh.faces_num);
|
||||
io_mesh->append_int("num_corners", mesh.totloop);
|
||||
|
||||
if (mesh.totpoly > 0) {
|
||||
io_mesh->append("poly_offsets",
|
||||
if (mesh.faces_num > 0) {
|
||||
io_mesh->append("face_offsets",
|
||||
write_bdata_shared_simple_gspan(bdata_writer,
|
||||
bdata_sharing,
|
||||
mesh.poly_offsets(),
|
||||
mesh.runtime->poly_offsets_sharing_info));
|
||||
mesh.face_offsets(),
|
||||
mesh.runtime->face_offsets_sharing_info));
|
||||
}
|
||||
|
||||
auto io_materials = serialize_material_slots({mesh.mat, mesh.totcol});
|
||||
|
||||
@@ -568,10 +568,10 @@ static void ccd_update_deflector_hash(Depsgraph *depsgraph,
|
||||
static int count_mesh_quads(Mesh *me)
|
||||
{
|
||||
int result = 0;
|
||||
const int *poly_offsets = BKE_mesh_poly_offsets(me);
|
||||
if (poly_offsets) {
|
||||
for (int i = 0; i < me->totpoly; i++) {
|
||||
const int poly_size = poly_offsets[i + 1] - poly_offsets[i];
|
||||
const int *face_offsets = BKE_mesh_face_offsets(me);
|
||||
if (face_offsets) {
|
||||
for (int i = 0; i < me->faces_num; i++) {
|
||||
const int poly_size = face_offsets[i + 1] - face_offsets[i];
|
||||
if (poly_size == 4) {
|
||||
result++;
|
||||
}
|
||||
@@ -591,7 +591,7 @@ static void add_mesh_quad_diag_springs(Object *ob)
|
||||
nofquads = count_mesh_quads(me);
|
||||
if (nofquads) {
|
||||
const int *corner_verts = BKE_mesh_corner_verts(me);
|
||||
const int *poly_offsets = BKE_mesh_poly_offsets(me);
|
||||
const int *face_offsets = BKE_mesh_face_offsets(me);
|
||||
BodySpring *bs;
|
||||
|
||||
/* resize spring-array to hold additional quad springs */
|
||||
@@ -601,15 +601,15 @@ static void add_mesh_quad_diag_springs(Object *ob)
|
||||
/* fill the tail */
|
||||
bs = &ob->soft->bspring[ob->soft->totspring];
|
||||
// bp = ob->soft->bpoint; /* UNUSED */
|
||||
for (int a = 0; a < me->totpoly; a++) {
|
||||
const int poly_size = poly_offsets[a + 1] - poly_offsets[a];
|
||||
for (int a = 0; a < me->faces_num; a++) {
|
||||
const int poly_size = face_offsets[a + 1] - face_offsets[a];
|
||||
if (poly_size == 4) {
|
||||
bs->v1 = corner_verts[poly_offsets[a] + 0];
|
||||
bs->v2 = corner_verts[poly_offsets[a] + 2];
|
||||
bs->v1 = corner_verts[face_offsets[a] + 0];
|
||||
bs->v2 = corner_verts[face_offsets[a] + 2];
|
||||
bs->springtype = SB_STIFFQUAD;
|
||||
bs++;
|
||||
bs->v1 = corner_verts[poly_offsets[a] + 1];
|
||||
bs->v2 = corner_verts[poly_offsets[a] + 3];
|
||||
bs->v1 = corner_verts[face_offsets[a] + 1];
|
||||
bs->v2 = corner_verts[face_offsets[a] + 3];
|
||||
bs->springtype = SB_STIFFQUAD;
|
||||
bs++;
|
||||
}
|
||||
@@ -2766,15 +2766,20 @@ static void mesh_faces_to_scratch(Object *ob)
|
||||
BodyFace *bodyface;
|
||||
int a;
|
||||
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
|
||||
const int *poly_offsets = BKE_mesh_poly_offsets(me);
|
||||
const int *face_offsets = BKE_mesh_face_offsets(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);
|
||||
sb->scratch->totface = poly_to_tri_count(me->faces_num, me->totloop);
|
||||
looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
|
||||
BKE_mesh_recalc_looptri(
|
||||
corner_verts, poly_offsets, vert_positions, me->totvert, me->totloop, me->totpoly, looptri);
|
||||
BKE_mesh_recalc_looptri(corner_verts,
|
||||
face_offsets,
|
||||
vert_positions,
|
||||
me->totvert,
|
||||
me->totloop,
|
||||
me->faces_num,
|
||||
looptri);
|
||||
|
||||
bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface,
|
||||
"SB_body_Faces");
|
||||
|
||||
@@ -598,7 +598,7 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv *subdiv,
|
||||
if (!BKE_subdiv_eval_begin_from_mesh(
|
||||
subdiv, coarse_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
|
||||
{
|
||||
if (coarse_mesh->totpoly) {
|
||||
if (coarse_mesh->faces_num) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1989,22 +1989,22 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg)
|
||||
static void adjacent_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
const blender::Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
int *r_v1,
|
||||
int *r_v2)
|
||||
{
|
||||
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 blender::IndexRange poly = polys[poly_index];
|
||||
const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index);
|
||||
const blender::IndexRange face = faces[face_index];
|
||||
*r_v1 = corner_verts[coord->grid_index];
|
||||
|
||||
const int corner = blender::bke::mesh::poly_find_corner_from_vert(poly, corner_verts, *r_v1);
|
||||
const int corner = blender::bke::mesh::face_find_corner_from_vert(face, corner_verts, *r_v1);
|
||||
if (coord->x == grid_size_1) {
|
||||
const int next = blender::bke::mesh::poly_corner_next(poly, corner);
|
||||
const int next = blender::bke::mesh::face_corner_next(face, corner);
|
||||
*r_v2 = corner_verts[next];
|
||||
}
|
||||
if (coord->y == grid_size_1) {
|
||||
const int prev = blender::bke::mesh::poly_corner_prev(poly, corner);
|
||||
const int prev = blender::bke::mesh::face_corner_prev(face, corner);
|
||||
*r_v2 = corner_verts[prev];
|
||||
}
|
||||
}
|
||||
@@ -2013,7 +2013,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
const blender::Span<int> corner_verts,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
int *r_v1,
|
||||
int *r_v2)
|
||||
{
|
||||
@@ -2021,7 +2021,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
const int grid_size_1 = subdiv_ccg->grid_size - 1;
|
||||
if (is_corner_grid_coord(subdiv_ccg, coord)) {
|
||||
if (coord->x == 0 && coord->y == 0) {
|
||||
/* Grid corner in the center of a poly. */
|
||||
/* Grid corner in the center of a face. */
|
||||
return SUBDIV_CCG_ADJACENT_NONE;
|
||||
}
|
||||
if (coord->x == grid_size_1 && coord->y == grid_size_1) {
|
||||
@@ -2030,7 +2030,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
return SUBDIV_CCG_ADJACENT_VERTEX;
|
||||
}
|
||||
/* Grid corner adjacent to the middle of a coarse mesh edge. */
|
||||
adjacent_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
|
||||
adjacent_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, faces, r_v1, r_v2);
|
||||
return SUBDIV_CCG_ADJACENT_EDGE;
|
||||
}
|
||||
|
||||
@@ -2038,7 +2038,7 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
|
||||
/* Grid boundary adjacent to a coarse mesh edge. */
|
||||
adjacent_vertices_index_from_adjacent_edge(
|
||||
subdiv_ccg, coord, corner_verts, polys, r_v1, r_v2);
|
||||
subdiv_ccg, coord, corner_verts, faces, r_v1, r_v2);
|
||||
return SUBDIV_CCG_ADJACENT_EDGE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,21 +24,21 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
struct PolyCornerIndex {
|
||||
int poly_index;
|
||||
int face_index;
|
||||
int corner;
|
||||
};
|
||||
|
||||
struct GridPaintMaskData {
|
||||
// int grid_size;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
const GridPaintMask *grid_paint_mask;
|
||||
/* Indexed by ptex face index, contains polygon/corner which corresponds
|
||||
/* Indexed by ptex face index, contains face/corner which corresponds
|
||||
* to it.
|
||||
*
|
||||
* NOTE: For quad polygon this is an index of first corner only, since
|
||||
* NOTE: For quad face this is an index of first corner only, since
|
||||
* there we only have one ptex.
|
||||
*/
|
||||
PolyCornerIndex *ptex_poly_corner;
|
||||
PolyCornerIndex *ptex_face_corner;
|
||||
};
|
||||
|
||||
static int mask_get_grid_and_coord(SubdivCCGMaskEvaluator *mask_evaluator,
|
||||
@@ -50,11 +50,11 @@ static int mask_get_grid_and_coord(SubdivCCGMaskEvaluator *mask_evaluator,
|
||||
float *grid_v)
|
||||
{
|
||||
GridPaintMaskData *data = static_cast<GridPaintMaskData *>(mask_evaluator->user_data);
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const blender::IndexRange poly = data->polys[poly_corner->poly_index];
|
||||
const int start_grid_index = poly.start() + poly_corner->corner;
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const blender::IndexRange face = data->faces[poly_corner->face_index];
|
||||
const int start_grid_index = face.start() + poly_corner->corner;
|
||||
int corner = 0;
|
||||
if (poly.size() == 4) {
|
||||
if (face.size() == 4) {
|
||||
float corner_u, corner_v;
|
||||
corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
|
||||
*r_mask_grid = &data->grid_paint_mask[start_grid_index + corner];
|
||||
@@ -94,7 +94,7 @@ static float eval_mask(SubdivCCGMaskEvaluator *mask_evaluator,
|
||||
static void free_mask_data(SubdivCCGMaskEvaluator *mask_evaluator)
|
||||
{
|
||||
GridPaintMaskData *data = static_cast<GridPaintMaskData *>(mask_evaluator->user_data);
|
||||
MEM_freeN(data->ptex_poly_corner);
|
||||
MEM_freeN(data->ptex_face_corner);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ static void free_mask_data(SubdivCCGMaskEvaluator *mask_evaluator)
|
||||
static int count_num_ptex_faces(const Mesh *mesh)
|
||||
{
|
||||
int num_ptex_faces = 0;
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
num_ptex_faces += (polys[poly_index].size() == 4) ? 1 : polys[poly_index].size();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
for (const int face_index : faces.index_range()) {
|
||||
num_ptex_faces += (faces[face_index].size() == 4) ? 1 : faces[face_index].size();
|
||||
}
|
||||
return num_ptex_faces;
|
||||
}
|
||||
@@ -114,25 +114,25 @@ static int count_num_ptex_faces(const Mesh *mesh)
|
||||
static void mask_data_init_mapping(SubdivCCGMaskEvaluator *mask_evaluator, const Mesh *mesh)
|
||||
{
|
||||
GridPaintMaskData *data = static_cast<GridPaintMaskData *>(mask_evaluator->user_data);
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const int num_ptex_faces = count_num_ptex_faces(mesh);
|
||||
/* Allocate memory. */
|
||||
data->ptex_poly_corner = static_cast<PolyCornerIndex *>(
|
||||
MEM_malloc_arrayN(num_ptex_faces, sizeof(*data->ptex_poly_corner), __func__));
|
||||
data->ptex_face_corner = static_cast<PolyCornerIndex *>(
|
||||
MEM_malloc_arrayN(num_ptex_faces, sizeof(*data->ptex_face_corner), __func__));
|
||||
/* Fill in offsets. */
|
||||
int ptex_face_index = 0;
|
||||
PolyCornerIndex *ptex_poly_corner = data->ptex_poly_corner;
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const blender::IndexRange poly = polys[poly_index];
|
||||
if (poly.size() == 4) {
|
||||
ptex_poly_corner[ptex_face_index].poly_index = poly_index;
|
||||
ptex_poly_corner[ptex_face_index].corner = 0;
|
||||
PolyCornerIndex *ptex_face_corner = data->ptex_face_corner;
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const blender::IndexRange face = faces[face_index];
|
||||
if (face.size() == 4) {
|
||||
ptex_face_corner[ptex_face_index].face_index = face_index;
|
||||
ptex_face_corner[ptex_face_index].corner = 0;
|
||||
ptex_face_index++;
|
||||
}
|
||||
else {
|
||||
for (int corner = 0; corner < poly.size(); corner++) {
|
||||
ptex_poly_corner[ptex_face_index].poly_index = poly_index;
|
||||
ptex_poly_corner[ptex_face_index].corner = corner;
|
||||
for (int corner = 0; corner < face.size(); corner++) {
|
||||
ptex_face_corner[ptex_face_index].face_index = face_index;
|
||||
ptex_face_corner[ptex_face_index].corner = corner;
|
||||
ptex_face_index++;
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,7 @@ static void mask_data_init_mapping(SubdivCCGMaskEvaluator *mask_evaluator, const
|
||||
static void mask_init_data(SubdivCCGMaskEvaluator *mask_evaluator, const Mesh *mesh)
|
||||
{
|
||||
GridPaintMaskData *data = static_cast<GridPaintMaskData *>(mask_evaluator->user_data);
|
||||
data->polys = mesh->polys();
|
||||
data->faces = mesh->faces();
|
||||
data->grid_paint_mask = static_cast<const GridPaintMask *>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_GRID_PAINT_MASK));
|
||||
mask_data_init_mapping(mask_evaluator, mesh);
|
||||
|
||||
@@ -24,7 +24,7 @@ static DMFlagMat subdiv_ccg_material_flags_eval(
|
||||
SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator, const int coarse_face_index)
|
||||
{
|
||||
CCGMaterialFromMeshData *data = (CCGMaterialFromMeshData *)material_flags_evaluator->user_data;
|
||||
BLI_assert(coarse_face_index < data->mesh->totpoly);
|
||||
BLI_assert(coarse_face_index < data->mesh->faces_num);
|
||||
DMFlagMat material_flags;
|
||||
material_flags.sharp = data->sharp_faces && data->sharp_faces[coarse_face_index];
|
||||
material_flags.mat_nr = data->material_indices ? data->material_indices[coarse_face_index] : 0;
|
||||
|
||||
@@ -36,7 +36,7 @@ struct ConverterStorage {
|
||||
const Mesh *mesh;
|
||||
blender::Span<blender::float3> vert_positions;
|
||||
blender::Span<blender::int2> edges;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> corner_verts;
|
||||
blender::Span<int> corner_edges;
|
||||
|
||||
@@ -109,7 +109,7 @@ static bool specifies_full_topology(const OpenSubdiv_Converter * /*converter*/)
|
||||
static int get_num_faces(const OpenSubdiv_Converter *converter)
|
||||
{
|
||||
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
|
||||
return storage->mesh->totpoly;
|
||||
return storage->mesh->faces_num;
|
||||
}
|
||||
|
||||
static int get_num_edges(const OpenSubdiv_Converter *converter)
|
||||
@@ -127,7 +127,7 @@ static int get_num_vertices(const OpenSubdiv_Converter *converter)
|
||||
static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index)
|
||||
{
|
||||
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
|
||||
return storage->polys[manifold_face_index].size();
|
||||
return storage->faces[manifold_face_index].size();
|
||||
}
|
||||
|
||||
static void get_face_vertices(const OpenSubdiv_Converter *converter,
|
||||
@@ -135,9 +135,9 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter,
|
||||
int *manifold_face_vertices)
|
||||
{
|
||||
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
|
||||
const blender::IndexRange poly = storage->polys[manifold_face_index];
|
||||
for (int i = 0; i < poly.size(); i++) {
|
||||
const int vert = storage->corner_verts[poly[i]];
|
||||
const blender::IndexRange face = storage->faces[manifold_face_index];
|
||||
for (int i = 0; i < face.size(); i++) {
|
||||
const int vert = storage->corner_verts[face[i]];
|
||||
manifold_face_vertices[i] = storage->manifold_vertex_index[vert];
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
|
||||
storage->loop_uv_indices = static_cast<int *>(
|
||||
MEM_malloc_arrayN(mesh->totloop, sizeof(int), "loop uv vertex index"));
|
||||
}
|
||||
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(storage->polys,
|
||||
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(storage->faces,
|
||||
nullptr,
|
||||
nullptr,
|
||||
storage->corner_verts.data(),
|
||||
@@ -231,8 +231,8 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
|
||||
if (uv_vert->separate) {
|
||||
storage->num_uv_coordinates++;
|
||||
}
|
||||
const blender::IndexRange poly = storage->polys[uv_vert->poly_index];
|
||||
const int global_loop_index = poly.start() + uv_vert->loop_of_poly_index;
|
||||
const blender::IndexRange face = storage->faces[uv_vert->face_index];
|
||||
const int global_loop_index = face.start() + uv_vert->loop_of_face_index;
|
||||
storage->loop_uv_indices[global_loop_index] = storage->num_uv_coordinates;
|
||||
uv_vert = uv_vert->next;
|
||||
}
|
||||
@@ -257,8 +257,8 @@ static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
|
||||
const int corner)
|
||||
{
|
||||
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
|
||||
const blender::IndexRange poly = storage->polys[face_index];
|
||||
return storage->loop_uv_indices[poly.start() + corner];
|
||||
const blender::IndexRange face = storage->faces[face_index];
|
||||
return storage->loop_uv_indices[face.start() + corner];
|
||||
}
|
||||
|
||||
static void free_user_data(const OpenSubdiv_Converter *converter)
|
||||
@@ -388,7 +388,7 @@ static void init_user_data(OpenSubdiv_Converter *converter,
|
||||
user_data->mesh = mesh;
|
||||
user_data->vert_positions = mesh->vert_positions();
|
||||
user_data->edges = mesh->edges();
|
||||
user_data->polys = mesh->polys();
|
||||
user_data->faces = mesh->faces();
|
||||
user_data->corner_verts = mesh->corner_verts();
|
||||
user_data->corner_edges = mesh->corner_edges();
|
||||
if (settings->use_creases) {
|
||||
|
||||
@@ -102,8 +102,8 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
|
||||
const int /*num_vertices*/,
|
||||
const int /*num_edges*/,
|
||||
const int /*num_loops*/,
|
||||
const int /*num_polygons*/,
|
||||
const int * /*subdiv_polygon_offset*/)
|
||||
const int /*num_faces*/,
|
||||
const int * /*subdiv_face_offset*/)
|
||||
{
|
||||
SubdivDeformContext *subdiv_context = static_cast<SubdivDeformContext *>(
|
||||
foreach_context->user_data);
|
||||
@@ -117,7 +117,7 @@ static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_
|
||||
const float u,
|
||||
const float v,
|
||||
const int coarse_vertex_index,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int /*subdiv_vertex_index*/)
|
||||
{
|
||||
@@ -131,7 +131,7 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex
|
||||
const float u,
|
||||
const float v,
|
||||
const int coarse_vertex_index,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int /*subdiv_vertex_index*/)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ void BKE_subdiv_deform_coarse_vertices(Subdiv *subdiv,
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
* topology.
|
||||
* In either way, we can't safely continue. */
|
||||
if (coarse_mesh->totpoly) {
|
||||
if (coarse_mesh->faces_num) {
|
||||
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
struct PolyCornerIndex {
|
||||
int poly_index;
|
||||
int face_index;
|
||||
int corner;
|
||||
};
|
||||
|
||||
@@ -36,14 +36,14 @@ struct MultiresDisplacementData {
|
||||
/* Mesh is used to read external displacement. */
|
||||
Mesh *mesh;
|
||||
const MultiresModifierData *mmd;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
const MDisps *mdisps;
|
||||
/* Indexed by PTEX face index, contains polygon/corner which corresponds
|
||||
/* Indexed by PTEX face index, contains face/corner which corresponds
|
||||
* to it.
|
||||
*
|
||||
* NOTE: For quad polygon this is an index of first corner only, since
|
||||
* NOTE: For quad face this is an index of first corner only, since
|
||||
* there we only have one PTEX. */
|
||||
PolyCornerIndex *ptex_poly_corner;
|
||||
PolyCornerIndex *ptex_face_corner;
|
||||
/* Indexed by coarse face index, returns first PTEX face index corresponding
|
||||
* to that coarse face. */
|
||||
int *face_ptex_offset;
|
||||
@@ -71,11 +71,11 @@ static int displacement_get_grid_and_coord(SubdivDisplacement *displacement,
|
||||
{
|
||||
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
|
||||
displacement->user_data);
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const blender::IndexRange poly = data->polys[poly_corner->poly_index];
|
||||
const int start_grid_index = poly.start() + poly_corner->corner;
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const blender::IndexRange face = data->faces[face_corner->face_index];
|
||||
const int start_grid_index = face.start() + face_corner->corner;
|
||||
int corner = 0;
|
||||
if (poly.size() == 4) {
|
||||
if (face.size() == 4) {
|
||||
float corner_u, corner_v;
|
||||
corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
|
||||
*r_displacement_grid = &data->mdisps[start_grid_index + corner];
|
||||
@@ -95,11 +95,11 @@ static const MDisps *displacement_get_other_grid(SubdivDisplacement *displacemen
|
||||
{
|
||||
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
|
||||
displacement->user_data);
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const blender::IndexRange poly = data->polys[poly_corner->poly_index];
|
||||
const int effective_corner = (poly.size() == 4) ? corner : poly_corner->corner;
|
||||
const int next_corner = (effective_corner + corner_delta + poly.size()) % poly.size();
|
||||
return &data->mdisps[poly[next_corner]];
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const blender::IndexRange face = data->faces[face_corner->face_index];
|
||||
const int effective_corner = (face.size() == 4) ? corner : face_corner->corner;
|
||||
const int next_corner = (effective_corner + corner_delta + face.size()) % face.size();
|
||||
return &data->mdisps[face[next_corner]];
|
||||
}
|
||||
|
||||
BLI_INLINE eAverageWith read_displacement_grid(const MDisps *displacement_grid,
|
||||
@@ -174,8 +174,8 @@ static void average_read_displacement_object(MultiresDisplacementData *data,
|
||||
const int corner_index,
|
||||
float r_D[3])
|
||||
{
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const int num_corners = data->polys[poly_corner->poly_index].size();
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const int num_corners = data->faces[face_corner->face_index].size();
|
||||
/* Get (u, v) coordinate within the other PTEX face which corresponds to
|
||||
* the grid coordinates. */
|
||||
float u, v;
|
||||
@@ -199,11 +199,11 @@ static void average_get_other_ptex_and_corner(MultiresDisplacementData *data,
|
||||
int *r_other_ptex_face_index,
|
||||
int *r_other_corner_index)
|
||||
{
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const int poly_index = poly_corner->poly_index;
|
||||
const int num_corners = data->polys[poly_corner->poly_index].size();
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const int face_index = face_corner->face_index;
|
||||
const int num_corners = data->faces[face_corner->face_index].size();
|
||||
const bool is_quad = (num_corners == 4);
|
||||
const int start_ptex_face_index = data->face_ptex_offset[poly_index];
|
||||
const int start_ptex_face_index = data->face_ptex_offset[face_index];
|
||||
*r_other_corner_index = (corner + corner_delta + num_corners) % num_corners;
|
||||
*r_other_ptex_face_index = is_quad ? start_ptex_face_index :
|
||||
start_ptex_face_index + *r_other_corner_index;
|
||||
@@ -248,8 +248,8 @@ static void average_with_all(SubdivDisplacement *displacement,
|
||||
{
|
||||
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
|
||||
displacement->user_data);
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const int num_corners = data->polys[poly_corner->poly_index].size();
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const int num_corners = data->faces[face_corner->face_index].size();
|
||||
for (int corner_delta = 1; corner_delta < num_corners; corner_delta++) {
|
||||
average_with_other(displacement, ptex_face_index, corner, 0.0f, 0.0f, corner_delta, r_D);
|
||||
}
|
||||
@@ -303,15 +303,15 @@ static int displacement_get_face_corner(MultiresDisplacementData *data,
|
||||
const float u,
|
||||
const float v)
|
||||
{
|
||||
const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
|
||||
const int num_corners = data->polys[poly_corner->poly_index].size();
|
||||
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
|
||||
const int num_corners = data->faces[face_corner->face_index].size();
|
||||
const bool is_quad = (num_corners == 4);
|
||||
if (is_quad) {
|
||||
float dummy_corner_u, dummy_corner_v;
|
||||
return BKE_subdiv_rotate_quad_to_corner(u, v, &dummy_corner_u, &dummy_corner_v);
|
||||
}
|
||||
|
||||
return poly_corner->corner;
|
||||
return face_corner->corner;
|
||||
}
|
||||
|
||||
static void initialize(SubdivDisplacement *displacement)
|
||||
@@ -357,7 +357,7 @@ static void free_displacement(SubdivDisplacement *displacement)
|
||||
{
|
||||
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
|
||||
displacement->user_data);
|
||||
MEM_freeN(data->ptex_poly_corner);
|
||||
MEM_freeN(data->ptex_face_corner);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
|
||||
@@ -366,9 +366,9 @@ static void free_displacement(SubdivDisplacement *displacement)
|
||||
static int count_num_ptex_faces(const Mesh *mesh)
|
||||
{
|
||||
int num_ptex_faces = 0;
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
|
||||
num_ptex_faces += (polys[poly_index].size() == 4) ? 1 : polys[poly_index].size();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
for (int face_index = 0; face_index < mesh->faces_num; face_index++) {
|
||||
num_ptex_faces += (faces[face_index].size() == 4) ? 1 : faces[face_index].size();
|
||||
}
|
||||
return num_ptex_faces;
|
||||
}
|
||||
@@ -377,25 +377,25 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, con
|
||||
{
|
||||
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
|
||||
displacement->user_data);
|
||||
const blender::OffsetIndices polys = mesh->polys();
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const int num_ptex_faces = count_num_ptex_faces(mesh);
|
||||
/* Allocate memory. */
|
||||
data->ptex_poly_corner = static_cast<PolyCornerIndex *>(
|
||||
MEM_malloc_arrayN(num_ptex_faces, sizeof(*data->ptex_poly_corner), "PTEX poly corner"));
|
||||
data->ptex_face_corner = static_cast<PolyCornerIndex *>(
|
||||
MEM_malloc_arrayN(num_ptex_faces, sizeof(*data->ptex_face_corner), "PTEX face corner"));
|
||||
/* Fill in offsets. */
|
||||
int ptex_face_index = 0;
|
||||
PolyCornerIndex *ptex_poly_corner = data->ptex_poly_corner;
|
||||
for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
|
||||
const blender::IndexRange poly = polys[poly_index];
|
||||
if (poly.size() == 4) {
|
||||
ptex_poly_corner[ptex_face_index].poly_index = poly_index;
|
||||
ptex_poly_corner[ptex_face_index].corner = 0;
|
||||
PolyCornerIndex *ptex_face_corner = data->ptex_face_corner;
|
||||
for (int face_index = 0; face_index < mesh->faces_num; face_index++) {
|
||||
const blender::IndexRange face = faces[face_index];
|
||||
if (face.size() == 4) {
|
||||
ptex_face_corner[ptex_face_index].face_index = face_index;
|
||||
ptex_face_corner[ptex_face_index].corner = 0;
|
||||
ptex_face_index++;
|
||||
}
|
||||
else {
|
||||
for (int corner = 0; corner < poly.size(); corner++) {
|
||||
ptex_poly_corner[ptex_face_index].poly_index = poly_index;
|
||||
ptex_poly_corner[ptex_face_index].corner = corner;
|
||||
for (int corner = 0; corner < face.size(); corner++) {
|
||||
ptex_face_corner[ptex_face_index].face_index = face_index;
|
||||
ptex_face_corner[ptex_face_index].corner = corner;
|
||||
ptex_face_index++;
|
||||
}
|
||||
}
|
||||
@@ -413,7 +413,7 @@ static void displacement_init_data(SubdivDisplacement *displacement,
|
||||
data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
|
||||
data->mesh = mesh;
|
||||
data->mmd = mmd;
|
||||
data->polys = mesh->polys();
|
||||
data->faces = mesh->faces();
|
||||
data->mdisps = static_cast<const MDisps *>(CustomData_get_layer(&mesh->ldata, CD_MDISPS));
|
||||
data->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
|
||||
data->is_initialized = false;
|
||||
|
||||
@@ -109,7 +109,7 @@ static void set_coarse_positions(Subdiv *subdiv,
|
||||
struct FaceVaryingDataFromUVContext {
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner;
|
||||
const Mesh *mesh;
|
||||
blender::OffsetIndices<int> polys;
|
||||
blender::OffsetIndices<int> faces;
|
||||
const float (*mloopuv)[2];
|
||||
float (*buffer)[2];
|
||||
int layer_index;
|
||||
@@ -122,7 +122,7 @@ static void set_face_varying_data_from_uv_task(void *__restrict userdata,
|
||||
FaceVaryingDataFromUVContext *ctx = static_cast<FaceVaryingDataFromUVContext *>(userdata);
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner = ctx->topology_refiner;
|
||||
const int layer_index = ctx->layer_index;
|
||||
const float(*mluv)[2] = &ctx->mloopuv[ctx->polys[face_index].start()];
|
||||
const float(*mluv)[2] = &ctx->mloopuv[ctx->faces[face_index].start()];
|
||||
|
||||
/* TODO(sergey): OpenSubdiv's C-API converter can change winding of
|
||||
* loops of a face, need to watch for that, to prevent wrong UVs assigned.
|
||||
@@ -155,7 +155,7 @@ static void set_face_varying_data_from_uv(Subdiv *subdiv,
|
||||
ctx.layer_index = layer_index;
|
||||
ctx.mloopuv = mluv;
|
||||
ctx.mesh = mesh;
|
||||
ctx.polys = mesh->polys();
|
||||
ctx.faces = mesh->faces();
|
||||
ctx.buffer = buffer;
|
||||
|
||||
TaskParallelSettings parallel_range_settings;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,14 +47,14 @@ struct SubdivMeshContext {
|
||||
const Mesh *coarse_mesh;
|
||||
blender::Span<float3> coarse_positions;
|
||||
blender::Span<int2> coarse_edges;
|
||||
blender::OffsetIndices<int> coarse_polys;
|
||||
blender::OffsetIndices<int> coarse_faces;
|
||||
blender::Span<int> coarse_corner_verts;
|
||||
|
||||
Subdiv *subdiv;
|
||||
Mesh *subdiv_mesh;
|
||||
blender::MutableSpan<float3> subdiv_positions;
|
||||
blender::MutableSpan<int2> subdiv_edges;
|
||||
blender::MutableSpan<int> subdiv_poly_offsets;
|
||||
blender::MutableSpan<int> subdiv_face_offsets;
|
||||
blender::MutableSpan<int> subdiv_corner_verts;
|
||||
blender::MutableSpan<int> subdiv_corner_edges;
|
||||
|
||||
@@ -62,7 +62,7 @@ struct SubdivMeshContext {
|
||||
int *vert_origindex;
|
||||
int *edge_origindex;
|
||||
int *loop_origindex;
|
||||
int *poly_origindex;
|
||||
int *face_origindex;
|
||||
/* UV layers interpolation. */
|
||||
int num_uv_layers;
|
||||
float2 *uv_layers[MAX_MTFACE];
|
||||
@@ -101,7 +101,7 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
|
||||
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
||||
ctx->subdiv_positions = subdiv_mesh->vert_positions_for_write();
|
||||
ctx->subdiv_edges = subdiv_mesh->edges_for_write();
|
||||
ctx->subdiv_poly_offsets = subdiv_mesh->poly_offsets_for_write();
|
||||
ctx->subdiv_face_offsets = subdiv_mesh->face_offsets_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. */
|
||||
@@ -111,8 +111,8 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
|
||||
CustomData_get_layer_for_write(&subdiv_mesh->edata, CD_ORIGINDEX, subdiv_mesh->totedge));
|
||||
ctx->loop_origindex = static_cast<int *>(
|
||||
CustomData_get_layer_for_write(&subdiv_mesh->ldata, CD_ORIGINDEX, subdiv_mesh->totloop));
|
||||
ctx->poly_origindex = static_cast<int *>(
|
||||
CustomData_get_layer_for_write(&subdiv_mesh->pdata, CD_ORIGINDEX, subdiv_mesh->totpoly));
|
||||
ctx->face_origindex = static_cast<int *>(CustomData_get_layer_for_write(
|
||||
&subdiv_mesh->pdata, CD_ORIGINDEX, subdiv_mesh->faces_num));
|
||||
/* UV layers interpolation. */
|
||||
subdiv_mesh_ctx_cache_uv_layers(ctx);
|
||||
/* Orco interpolation. */
|
||||
@@ -153,20 +153,20 @@ struct LoopsOfPtex {
|
||||
};
|
||||
|
||||
static void loops_of_ptex_get(LoopsOfPtex *loops_of_ptex,
|
||||
const IndexRange coarse_poly,
|
||||
const int ptex_of_poly_index)
|
||||
const IndexRange coarse_face,
|
||||
const int ptex_of_face_index)
|
||||
{
|
||||
const int first_ptex_loop_index = coarse_poly.start() + ptex_of_poly_index;
|
||||
const int first_ptex_loop_index = coarse_face.start() + ptex_of_face_index;
|
||||
/* Loop which look in the (opposite) V direction of the current
|
||||
* ptex face.
|
||||
*
|
||||
* TODO(sergey): Get rid of using module on every iteration. */
|
||||
const int last_ptex_loop_index = coarse_poly.start() +
|
||||
(ptex_of_poly_index + coarse_poly.size() - 1) %
|
||||
coarse_poly.size();
|
||||
const int last_ptex_loop_index = coarse_face.start() +
|
||||
(ptex_of_face_index + coarse_face.size() - 1) %
|
||||
coarse_face.size();
|
||||
loops_of_ptex->first_loop = first_ptex_loop_index;
|
||||
loops_of_ptex->last_loop = last_ptex_loop_index;
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
|
||||
loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
|
||||
}
|
||||
@@ -208,15 +208,15 @@ struct VerticesForInterpolation {
|
||||
|
||||
static void vertex_interpolation_init(const SubdivMeshContext *ctx,
|
||||
VerticesForInterpolation *vertex_interpolation,
|
||||
const IndexRange coarse_poly)
|
||||
const IndexRange coarse_face)
|
||||
{
|
||||
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
vertex_interpolation->vertex_data = &coarse_mesh->vdata;
|
||||
vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_poly.start() + 0];
|
||||
vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_poly.start() + 1];
|
||||
vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_poly.start() + 2];
|
||||
vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_poly.start() + 3];
|
||||
vertex_interpolation->vertex_indices[0] = ctx->coarse_corner_verts[coarse_face.start() + 0];
|
||||
vertex_interpolation->vertex_indices[1] = ctx->coarse_corner_verts[coarse_face.start() + 1];
|
||||
vertex_interpolation->vertex_indices[2] = ctx->coarse_corner_verts[coarse_face.start() + 2];
|
||||
vertex_interpolation->vertex_indices[3] = ctx->coarse_corner_verts[coarse_face.start() + 3];
|
||||
vertex_interpolation->vertex_data_storage_allocated = false;
|
||||
}
|
||||
else {
|
||||
@@ -233,41 +233,41 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
|
||||
vertex_interpolation->vertex_indices[2] = 2;
|
||||
vertex_interpolation->vertex_indices[3] = 3;
|
||||
vertex_interpolation->vertex_data_storage_allocated = true;
|
||||
/* Interpolate center of poly right away, it stays unchanged for all
|
||||
/* Interpolate center of face right away, it stays unchanged for all
|
||||
* ptex faces. */
|
||||
const float weight = 1.0f / float(coarse_poly.size());
|
||||
blender::Array<float, 32> weights(coarse_poly.size());
|
||||
blender::Array<int, 32> indices(coarse_poly.size());
|
||||
for (int i = 0; i < coarse_poly.size(); i++) {
|
||||
const float weight = 1.0f / float(coarse_face.size());
|
||||
blender::Array<float, 32> weights(coarse_face.size());
|
||||
blender::Array<int, 32> indices(coarse_face.size());
|
||||
for (int i = 0; i < coarse_face.size(); i++) {
|
||||
weights[i] = weight;
|
||||
indices[i] = ctx->coarse_corner_verts[coarse_poly.start() + i];
|
||||
indices[i] = ctx->coarse_corner_verts[coarse_face.start() + i];
|
||||
}
|
||||
CustomData_interp(&coarse_mesh->vdata,
|
||||
&vertex_interpolation->vertex_data_storage,
|
||||
indices.data(),
|
||||
weights.data(),
|
||||
nullptr,
|
||||
coarse_poly.size(),
|
||||
coarse_face.size(),
|
||||
2);
|
||||
}
|
||||
}
|
||||
|
||||
static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx,
|
||||
VerticesForInterpolation *vertex_interpolation,
|
||||
const IndexRange coarse_poly,
|
||||
const IndexRange coarse_face,
|
||||
const int corner)
|
||||
{
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
/* Nothing to do, all indices and data is already assigned. */
|
||||
}
|
||||
else {
|
||||
const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
|
||||
LoopsOfPtex loops_of_ptex;
|
||||
loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner);
|
||||
/* PTEX face corner corresponds to a poly loop with same index. */
|
||||
loops_of_ptex_get(&loops_of_ptex, coarse_face, corner);
|
||||
/* PTEX face corner corresponds to a face loop with same index. */
|
||||
CustomData_copy_data(vertex_data,
|
||||
&vertex_interpolation->vertex_data_storage,
|
||||
ctx->coarse_corner_verts[coarse_poly.start() + corner],
|
||||
ctx->coarse_corner_verts[coarse_face.start() + corner],
|
||||
0,
|
||||
1);
|
||||
/* Interpolate remaining ptex face corners, which hits loops
|
||||
@@ -280,9 +280,9 @@ static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx,
|
||||
const int last_loop_index = loops_of_ptex.last_loop;
|
||||
const int first_indices[2] = {
|
||||
ctx->coarse_corner_verts[first_loop_index],
|
||||
ctx->coarse_corner_verts[coarse_poly.start() +
|
||||
(first_loop_index - coarse_poly.start() + 1) %
|
||||
coarse_poly.size()]};
|
||||
ctx->coarse_corner_verts[coarse_face.start() +
|
||||
(first_loop_index - coarse_face.start() + 1) %
|
||||
coarse_face.size()]};
|
||||
const int last_indices[2] = {ctx->coarse_corner_verts[first_loop_index],
|
||||
ctx->coarse_corner_verts[last_loop_index]};
|
||||
CustomData_interp(vertex_data,
|
||||
@@ -338,15 +338,15 @@ struct LoopsForInterpolation {
|
||||
|
||||
static void loop_interpolation_init(const SubdivMeshContext *ctx,
|
||||
LoopsForInterpolation *loop_interpolation,
|
||||
const IndexRange coarse_poly)
|
||||
const IndexRange coarse_face)
|
||||
{
|
||||
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
loop_interpolation->loop_data = &coarse_mesh->ldata;
|
||||
loop_interpolation->loop_indices[0] = coarse_poly.start() + 0;
|
||||
loop_interpolation->loop_indices[1] = coarse_poly.start() + 1;
|
||||
loop_interpolation->loop_indices[2] = coarse_poly.start() + 2;
|
||||
loop_interpolation->loop_indices[3] = coarse_poly.start() + 3;
|
||||
loop_interpolation->loop_indices[0] = coarse_face.start() + 0;
|
||||
loop_interpolation->loop_indices[1] = coarse_face.start() + 1;
|
||||
loop_interpolation->loop_indices[2] = coarse_face.start() + 2;
|
||||
loop_interpolation->loop_indices[3] = coarse_face.start() + 3;
|
||||
loop_interpolation->loop_data_storage_allocated = false;
|
||||
}
|
||||
else {
|
||||
@@ -363,51 +363,51 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx,
|
||||
loop_interpolation->loop_indices[2] = 2;
|
||||
loop_interpolation->loop_indices[3] = 3;
|
||||
loop_interpolation->loop_data_storage_allocated = true;
|
||||
/* Interpolate center of poly right away, it stays unchanged for all
|
||||
/* Interpolate center of face right away, it stays unchanged for all
|
||||
* ptex faces. */
|
||||
const float weight = 1.0f / float(coarse_poly.size());
|
||||
blender::Array<float, 32> weights(coarse_poly.size());
|
||||
blender::Array<int, 32> indices(coarse_poly.size());
|
||||
for (int i = 0; i < coarse_poly.size(); i++) {
|
||||
const float weight = 1.0f / float(coarse_face.size());
|
||||
blender::Array<float, 32> weights(coarse_face.size());
|
||||
blender::Array<int, 32> indices(coarse_face.size());
|
||||
for (int i = 0; i < coarse_face.size(); i++) {
|
||||
weights[i] = weight;
|
||||
indices[i] = coarse_poly.start() + i;
|
||||
indices[i] = coarse_face.start() + i;
|
||||
}
|
||||
CustomData_interp(&coarse_mesh->ldata,
|
||||
&loop_interpolation->loop_data_storage,
|
||||
indices.data(),
|
||||
weights.data(),
|
||||
nullptr,
|
||||
coarse_poly.size(),
|
||||
coarse_face.size(),
|
||||
2);
|
||||
}
|
||||
}
|
||||
|
||||
static void loop_interpolation_from_corner(const SubdivMeshContext *ctx,
|
||||
LoopsForInterpolation *loop_interpolation,
|
||||
const IndexRange coarse_poly,
|
||||
const IndexRange coarse_face,
|
||||
const int corner)
|
||||
{
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
/* Nothing to do, all indices and data is already assigned. */
|
||||
}
|
||||
else {
|
||||
const CustomData *loop_data = &ctx->coarse_mesh->ldata;
|
||||
LoopsOfPtex loops_of_ptex;
|
||||
loops_of_ptex_get(&loops_of_ptex, coarse_poly, corner);
|
||||
/* PTEX face corner corresponds to a poly loop with same index. */
|
||||
loops_of_ptex_get(&loops_of_ptex, coarse_face, corner);
|
||||
/* PTEX face corner corresponds to a face loop with same index. */
|
||||
CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
|
||||
CustomData_copy_data(
|
||||
loop_data, &loop_interpolation->loop_data_storage, coarse_poly.start() + corner, 0, 1);
|
||||
loop_data, &loop_interpolation->loop_data_storage, coarse_face.start() + corner, 0, 1);
|
||||
/* Interpolate remaining ptex face corners, which hits loops
|
||||
* middle points.
|
||||
*
|
||||
* TODO(sergey): Re-use one of interpolation results from previous
|
||||
* iteration. */
|
||||
const float weights[2] = {0.5f, 0.5f};
|
||||
const int base_loop_index = coarse_poly.start();
|
||||
const int base_loop_index = coarse_face.start();
|
||||
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.size();
|
||||
(first_loop_index - base_loop_index + 1) % coarse_face.size();
|
||||
const int first_indices[2] = {first_loop_index, second_loop_index};
|
||||
const int last_indices[2] = {loops_of_ptex.last_loop, loops_of_ptex.first_loop};
|
||||
CustomData_interp(
|
||||
@@ -433,12 +433,12 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
|
||||
struct SubdivMeshTLS {
|
||||
bool vertex_interpolation_initialized;
|
||||
VerticesForInterpolation vertex_interpolation;
|
||||
int vertex_interpolation_coarse_poly_index;
|
||||
int vertex_interpolation_coarse_face_index;
|
||||
int vertex_interpolation_coarse_corner;
|
||||
|
||||
bool loop_interpolation_initialized;
|
||||
LoopsForInterpolation loop_interpolation;
|
||||
int loop_interpolation_coarse_poly_index;
|
||||
int loop_interpolation_coarse_face_index;
|
||||
int loop_interpolation_coarse_corner;
|
||||
};
|
||||
|
||||
@@ -518,8 +518,8 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
|
||||
const int num_vertices,
|
||||
const int num_edges,
|
||||
const int num_loops,
|
||||
const int num_polygons,
|
||||
const int * /*subdiv_polygon_offset*/)
|
||||
const int num_faces,
|
||||
const int * /*subdiv_face_offset*/)
|
||||
{
|
||||
/* Multi-resolution grid data will be applied or become invalid after subdivision,
|
||||
* so don't try to preserve it and use memory. Crease values should also not be interpolated. */
|
||||
@@ -528,7 +528,7 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
|
||||
|
||||
SubdivMeshContext *subdiv_context = static_cast<SubdivMeshContext *>(foreach_context->user_data);
|
||||
subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template_ex(
|
||||
subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_polygons, num_loops, mask);
|
||||
subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_faces, num_loops, mask);
|
||||
subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
|
||||
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
|
||||
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.clear();
|
||||
@@ -645,7 +645,7 @@ static void subdiv_mesh_vertex_displacement_every_corner(
|
||||
const float u,
|
||||
const float v,
|
||||
const int /*coarse_vertex_index*/,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
@@ -659,7 +659,7 @@ static void subdiv_mesh_vertex_displacement_every_edge(const SubdivForeachContex
|
||||
const float u,
|
||||
const float v,
|
||||
const int /*coarse_edge_index*/,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
@@ -673,7 +673,7 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex
|
||||
const float u,
|
||||
const float v,
|
||||
const int coarse_vertex_index,
|
||||
const int /*coarse_poly_index*/,
|
||||
const int /*coarse_face_index*/,
|
||||
const int /*coarse_corner*/,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
@@ -685,13 +685,13 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex
|
||||
|
||||
static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx,
|
||||
SubdivMeshTLS *tls,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner)
|
||||
{
|
||||
const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index];
|
||||
/* Check whether we've moved to another corner or polygon. */
|
||||
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
|
||||
/* Check whether we've moved to another corner or face. */
|
||||
if (tls->vertex_interpolation_initialized) {
|
||||
if (tls->vertex_interpolation_coarse_poly_index != coarse_poly_index ||
|
||||
if (tls->vertex_interpolation_coarse_face_index != coarse_face_index ||
|
||||
tls->vertex_interpolation_coarse_corner != coarse_corner)
|
||||
{
|
||||
vertex_interpolation_end(&tls->vertex_interpolation);
|
||||
@@ -700,17 +700,17 @@ static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx,
|
||||
}
|
||||
/* Initialize the interpolation. */
|
||||
if (!tls->vertex_interpolation_initialized) {
|
||||
vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly);
|
||||
vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_face);
|
||||
}
|
||||
/* Update it for a new corner if needed. */
|
||||
if (!tls->vertex_interpolation_initialized ||
|
||||
tls->vertex_interpolation_coarse_corner != coarse_corner)
|
||||
{
|
||||
vertex_interpolation_from_corner(ctx, &tls->vertex_interpolation, coarse_poly, coarse_corner);
|
||||
vertex_interpolation_from_corner(ctx, &tls->vertex_interpolation, coarse_face, coarse_corner);
|
||||
}
|
||||
/* Store settings used for the current state of interpolator. */
|
||||
tls->vertex_interpolation_initialized = true;
|
||||
tls->vertex_interpolation_coarse_poly_index = coarse_poly_index;
|
||||
tls->vertex_interpolation_coarse_face_index = coarse_face_index;
|
||||
tls->vertex_interpolation_coarse_corner = coarse_corner;
|
||||
}
|
||||
|
||||
@@ -720,22 +720,22 @@ static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
|
||||
const float u,
|
||||
const float v,
|
||||
const int /*coarse_edge_index*/,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
|
||||
SubdivMeshTLS *tls = static_cast<SubdivMeshTLS *>(tls_v);
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly_index, coarse_corner);
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_face_index, coarse_corner);
|
||||
evaluate_vertex_and_apply_displacement_interpolate(
|
||||
ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vertex_index);
|
||||
}
|
||||
|
||||
static bool subdiv_mesh_is_center_vertex(const IndexRange coarse_poly,
|
||||
static bool subdiv_mesh_is_center_vertex(const IndexRange coarse_face,
|
||||
const float u,
|
||||
const float v)
|
||||
{
|
||||
if (coarse_poly.size() == 4) {
|
||||
if (coarse_face.size() == 4) {
|
||||
if (u == 0.5f && v == 0.5f) {
|
||||
return true;
|
||||
}
|
||||
@@ -748,13 +748,13 @@ static bool subdiv_mesh_is_center_vertex(const IndexRange coarse_poly,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void subdiv_mesh_tag_center_vertex(const IndexRange coarse_poly,
|
||||
static void subdiv_mesh_tag_center_vertex(const IndexRange coarse_face,
|
||||
const int subdiv_vertex_index,
|
||||
const float u,
|
||||
const float v,
|
||||
Mesh *subdiv_mesh)
|
||||
{
|
||||
if (subdiv_mesh_is_center_vertex(coarse_poly, u, v)) {
|
||||
if (subdiv_mesh_is_center_vertex(coarse_face, u, v)) {
|
||||
subdiv_mesh->runtime->subsurf_face_dot_tags[subdiv_vertex_index].set();
|
||||
}
|
||||
}
|
||||
@@ -764,20 +764,20 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
|
||||
const int ptex_face_index,
|
||||
const float u,
|
||||
const float v,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner,
|
||||
const int subdiv_vertex_index)
|
||||
{
|
||||
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
|
||||
SubdivMeshTLS *tls = static_cast<SubdivMeshTLS *>(tls_v);
|
||||
Subdiv *subdiv = ctx->subdiv;
|
||||
const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index];
|
||||
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
|
||||
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
||||
float3 &subdiv_position = ctx->subdiv_positions[subdiv_vertex_index];
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly_index, coarse_corner);
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_face_index, coarse_corner);
|
||||
subdiv_vertex_data_interpolate(ctx, subdiv_vertex_index, &tls->vertex_interpolation, u, v);
|
||||
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_position);
|
||||
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh);
|
||||
subdiv_mesh_tag_center_vertex(coarse_face, subdiv_vertex_index, u, v, subdiv_mesh);
|
||||
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
|
||||
}
|
||||
|
||||
@@ -859,13 +859,13 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
|
||||
|
||||
static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx,
|
||||
SubdivMeshTLS *tls,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner)
|
||||
{
|
||||
const IndexRange coarse_poly = ctx->coarse_polys[coarse_poly_index];
|
||||
/* Check whether we've moved to another corner or polygon. */
|
||||
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
|
||||
/* Check whether we've moved to another corner or face. */
|
||||
if (tls->loop_interpolation_initialized) {
|
||||
if (tls->loop_interpolation_coarse_poly_index != coarse_poly_index ||
|
||||
if (tls->loop_interpolation_coarse_face_index != coarse_face_index ||
|
||||
tls->loop_interpolation_coarse_corner != coarse_corner)
|
||||
{
|
||||
loop_interpolation_end(&tls->loop_interpolation);
|
||||
@@ -874,16 +874,16 @@ static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx,
|
||||
}
|
||||
/* Initialize the interpolation. */
|
||||
if (!tls->loop_interpolation_initialized) {
|
||||
loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_poly);
|
||||
loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_face);
|
||||
}
|
||||
/* Update it for a new corner if needed. */
|
||||
if (!tls->loop_interpolation_initialized ||
|
||||
tls->loop_interpolation_coarse_corner != coarse_corner) {
|
||||
loop_interpolation_from_corner(ctx, &tls->loop_interpolation, coarse_poly, coarse_corner);
|
||||
loop_interpolation_from_corner(ctx, &tls->loop_interpolation, coarse_face, coarse_corner);
|
||||
}
|
||||
/* Store settings used for the current state of interpolator. */
|
||||
tls->loop_interpolation_initialized = true;
|
||||
tls->loop_interpolation_coarse_poly_index = coarse_poly_index;
|
||||
tls->loop_interpolation_coarse_face_index = coarse_face_index;
|
||||
tls->loop_interpolation_coarse_corner = coarse_corner;
|
||||
}
|
||||
|
||||
@@ -893,7 +893,7 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
|
||||
const float u,
|
||||
const float v,
|
||||
const int /*coarse_loop_index*/,
|
||||
const int coarse_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int coarse_corner,
|
||||
const int subdiv_loop_index,
|
||||
const int subdiv_vertex_index,
|
||||
@@ -901,7 +901,7 @@ 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);
|
||||
subdiv_mesh_ensure_loop_interpolation(ctx, tls, coarse_poly_index, coarse_corner);
|
||||
subdiv_mesh_ensure_loop_interpolation(ctx, tls, coarse_face_index, coarse_corner);
|
||||
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;
|
||||
@@ -914,18 +914,21 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
|
||||
/** \name Polygons subdivision process
|
||||
* \{ */
|
||||
|
||||
static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context,
|
||||
static void subdiv_mesh_face(const SubdivForeachContext *foreach_context,
|
||||
void * /*tls*/,
|
||||
const int coarse_poly_index,
|
||||
const int subdiv_poly_index,
|
||||
const int coarse_face_index,
|
||||
const int subdiv_face_index,
|
||||
const int start_loop_index,
|
||||
const int /*num_loops*/)
|
||||
{
|
||||
BLI_assert(coarse_poly_index != ORIGINDEX_NONE);
|
||||
BLI_assert(coarse_face_index != ORIGINDEX_NONE);
|
||||
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
|
||||
CustomData_copy_data(
|
||||
&ctx->coarse_mesh->pdata, &ctx->subdiv_mesh->pdata, coarse_poly_index, subdiv_poly_index, 1);
|
||||
ctx->subdiv_poly_offsets[subdiv_poly_index] = start_loop_index;
|
||||
CustomData_copy_data(&ctx->coarse_mesh->pdata,
|
||||
&ctx->subdiv_mesh->pdata,
|
||||
coarse_face_index,
|
||||
subdiv_face_index,
|
||||
1);
|
||||
ctx->subdiv_face_offsets[subdiv_face_index] = start_loop_index;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -1130,7 +1133,7 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
|
||||
foreach_context->vertex_inner = subdiv_mesh_vertex_inner;
|
||||
foreach_context->edge = subdiv_mesh_edge;
|
||||
foreach_context->loop = subdiv_mesh_loop;
|
||||
foreach_context->poly = subdiv_mesh_poly;
|
||||
foreach_context->poly = subdiv_mesh_face;
|
||||
foreach_context->vertex_loose = subdiv_mesh_vertex_loose;
|
||||
foreach_context->vertex_of_loose_edge = subdiv_mesh_vertex_of_loose_edge;
|
||||
foreach_context->user_data_tls_free = subdiv_mesh_tls_free;
|
||||
@@ -1158,7 +1161,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
* topology.
|
||||
* In either way, we can't safely continue. */
|
||||
if (coarse_mesh->totpoly) {
|
||||
if (coarse_mesh->faces_num) {
|
||||
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1170,7 +1173,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
||||
subdiv_context.coarse_mesh = coarse_mesh;
|
||||
subdiv_context.coarse_positions = coarse_mesh->vert_positions();
|
||||
subdiv_context.coarse_edges = coarse_mesh->edges();
|
||||
subdiv_context.coarse_polys = coarse_mesh->polys();
|
||||
subdiv_context.coarse_faces = coarse_mesh->faces();
|
||||
subdiv_context.coarse_corner_verts = coarse_mesh->corner_verts();
|
||||
|
||||
subdiv_context.subdiv = subdiv;
|
||||
@@ -1219,7 +1222,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
||||
* calculation. Since vertex normals are supposed to be a consistent cache, don't bother
|
||||
* calculating them here. The work may have been pointless anyway if the mesh is deformed or
|
||||
* changed afterwards. */
|
||||
BLI_assert(BKE_mesh_vert_normals_are_dirty(result) || BKE_mesh_poly_normals_are_dirty(result));
|
||||
BLI_assert(BKE_mesh_vert_normals_are_dirty(result) || BKE_mesh_face_normals_are_dirty(result));
|
||||
/* Free used memory. */
|
||||
subdiv_mesh_context_free(&subdiv_context);
|
||||
return result;
|
||||
|
||||
@@ -229,25 +229,25 @@ static int getFaceIndex(
|
||||
}
|
||||
|
||||
static void get_face_uv_map_vert(UvVertMap *vmap,
|
||||
const blender::OffsetIndices<int> polys,
|
||||
const int *poly_verts,
|
||||
const blender::OffsetIndices<int> faces,
|
||||
const int *face_verts,
|
||||
int fi,
|
||||
CCGVertHDL *fverts)
|
||||
{
|
||||
UvMapVert *v, *nv;
|
||||
int j, nverts = polys[fi].size();
|
||||
int j, nverts = faces[fi].size();
|
||||
|
||||
for (j = 0; j < nverts; j++) {
|
||||
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, poly_verts[j]); v; v = v->next) {
|
||||
for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, face_verts[j]); v; v = v->next) {
|
||||
if (v->separate) {
|
||||
nv = v;
|
||||
}
|
||||
if (v->poly_index == fi) {
|
||||
if (v->face_index == fi) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fverts[j] = POINTER_FROM_UINT(polys[nv->poly_index].start() + nv->loop_of_poly_index);
|
||||
fverts[j] = POINTER_FROM_UINT(faces[nv->face_index].start() + nv->loop_of_face_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
|
||||
DerivedMesh *dm,
|
||||
const float (*mloopuv)[2])
|
||||
{
|
||||
const blender::OffsetIndices polys(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1));
|
||||
const blender::OffsetIndices faces(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1));
|
||||
int *corner_verts = dm->getCornerVertArray(dm);
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
int totface = dm->getNumPolys(dm);
|
||||
@@ -274,7 +274,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, corner_verts, mloopuv, totvert, limit, false, true);
|
||||
faces, nullptr, nullptr, corner_verts, mloopuv, totvert, limit, false, true);
|
||||
if (!vmap) {
|
||||
return 0;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
|
||||
for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
|
||||
if (v->separate) {
|
||||
CCGVert *ssv;
|
||||
int loopid = polys[v->poly_index].start() + v->loop_of_poly_index;
|
||||
int loopid = faces[v->face_index].start() + v->loop_of_face_index;
|
||||
CCGVertHDL vhdl = POINTER_FROM_INT(loopid);
|
||||
|
||||
copy_v2_v2(uv, mloopuv[loopid]);
|
||||
@@ -309,18 +309,18 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
|
||||
}
|
||||
|
||||
/* create edges */
|
||||
eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
|
||||
eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(totface));
|
||||
|
||||
for (i = 0; i < totface; i++) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
int nverts = poly.size();
|
||||
const blender::IndexRange face = faces[i];
|
||||
int nverts = face.size();
|
||||
int j, j_next;
|
||||
CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i));
|
||||
// uint *fv = &poly.v1;
|
||||
// uint *fv = &face.v1;
|
||||
|
||||
fverts.reinitialize(nverts);
|
||||
|
||||
get_face_uv_map_vert(vmap, polys, &corner_verts[poly.start()], i, fverts.data());
|
||||
get_face_uv_map_vert(vmap, faces, &corner_verts[face.start()], i, fverts.data());
|
||||
|
||||
for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
|
||||
uint v0 = POINTER_AS_UINT(fverts[j_next]);
|
||||
@@ -328,7 +328,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
|
||||
|
||||
if (BLI_edgeset_add(eset, v0, v1)) {
|
||||
CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
|
||||
CCGEdgeHDL ehdl = POINTER_FROM_INT(poly[j_next]);
|
||||
CCGEdgeHDL ehdl = POINTER_FROM_INT(face[j_next]);
|
||||
float crease = ccgSubSurf_getEdgeCrease(orige);
|
||||
|
||||
ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
|
||||
@@ -340,13 +340,13 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
|
||||
|
||||
/* create faces */
|
||||
for (i = 0; i < totface; i++) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
int nverts = poly.size();
|
||||
const blender::IndexRange face = faces[i];
|
||||
int nverts = face.size();
|
||||
CCGFace *f;
|
||||
|
||||
fverts.reinitialize(nverts);
|
||||
|
||||
get_face_uv_map_vert(vmap, polys, &corner_verts[poly.start()], i, fverts.data());
|
||||
get_face_uv_map_vert(vmap, faces, &corner_verts[face.start()], i, fverts.data());
|
||||
ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f);
|
||||
}
|
||||
|
||||
@@ -542,7 +542,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
|
||||
float(*positions)[3] = (float(*)[3])dm->getVertArray(dm);
|
||||
const blender::int2 *edges = reinterpret_cast<const blender::int2 *>(dm->getEdgeArray(dm));
|
||||
int *corner_verts = dm->getCornerVertArray(dm);
|
||||
const blender::OffsetIndices polys(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1));
|
||||
const blender::OffsetIndices faces(blender::Span(dm->getPolyArray(dm), dm->getNumPolys(dm) + 1));
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
int totedge = dm->getNumEdges(dm);
|
||||
int i, j;
|
||||
@@ -585,21 +585,21 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
|
||||
|
||||
index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
|
||||
for (i = 0; i < dm->numPolyData; i++) {
|
||||
const blender::IndexRange poly = polys[i];
|
||||
const blender::IndexRange face = faces[i];
|
||||
|
||||
CCGFace *f;
|
||||
|
||||
fverts.reinitialize(poly.size());
|
||||
fverts.reinitialize(face.size());
|
||||
|
||||
for (j = 0; j < poly.size(); j++) {
|
||||
fverts[j] = POINTER_FROM_UINT(corner_verts[poly[j]]);
|
||||
for (j = 0; j < face.size(); j++) {
|
||||
fverts[j] = POINTER_FROM_UINT(corner_verts[face[j]]);
|
||||
}
|
||||
|
||||
/* This is very bad, means mesh is internally inconsistent.
|
||||
* it is not really possible to continue without modifying
|
||||
* other parts of code significantly to handle missing faces.
|
||||
* since this really shouldn't even be possible we just bail. */
|
||||
if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), poly.size(), fverts.data(), &f) ==
|
||||
if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), face.size(), fverts.data(), &f) ==
|
||||
eCCGError_InvalidValue)
|
||||
{
|
||||
static int hasGivenError = 0;
|
||||
@@ -986,7 +986,7 @@ static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges)
|
||||
0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings);
|
||||
}
|
||||
|
||||
static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_poly_offsets)
|
||||
static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_face_offsets)
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
@@ -1004,14 +1004,14 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, int *r_poly_offsets)
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
for (y = 0; y < gridSize - 1; y++) {
|
||||
for (x = 0; x < gridSize - 1; x++) {
|
||||
r_poly_offsets[i] = k;
|
||||
r_face_offsets[i] = k;
|
||||
k += 4;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r_poly_offsets[i] = k;
|
||||
r_face_offsets[i] = k;
|
||||
}
|
||||
|
||||
static void ccgDM_release(DerivedMesh *dm)
|
||||
@@ -1705,7 +1705,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
||||
&ccgdm->dm.loopData, ".corner_vert", ccgSubSurf_getNumFinalFaces(ss) * 4);
|
||||
CustomData_free_layer_named(
|
||||
&ccgdm->dm.loopData, ".corner_edge", ccgSubSurf_getNumFinalFaces(ss) * 4);
|
||||
MEM_SAFE_FREE(ccgdm->dm.poly_offsets);
|
||||
MEM_SAFE_FREE(ccgdm->dm.face_offsets);
|
||||
|
||||
ccgdm->reverseFaceMap = static_cast<int *>(
|
||||
MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap"));
|
||||
|
||||
@@ -114,10 +114,10 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
|
||||
const Span<openvdb::Vec3I> vdb_tris,
|
||||
const Span<openvdb::Vec4I> vdb_quads,
|
||||
const int vert_offset,
|
||||
const int poly_offset,
|
||||
const int face_offset,
|
||||
const int loop_offset,
|
||||
MutableSpan<float3> vert_positions,
|
||||
MutableSpan<int> poly_offsets,
|
||||
MutableSpan<int> face_offsets,
|
||||
MutableSpan<int> corner_verts)
|
||||
{
|
||||
/* Write vertices. */
|
||||
@@ -125,7 +125,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
|
||||
|
||||
/* Write triangles. */
|
||||
for (const int i : vdb_tris.index_range()) {
|
||||
poly_offsets[poly_offset + i] = loop_offset + 3 * i;
|
||||
face_offsets[face_offset + i] = loop_offset + 3 * i;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
/* Reverse vertex order to get correct normals. */
|
||||
corner_verts[loop_offset + 3 * i + j] = vert_offset + vdb_tris[i][2 - j];
|
||||
@@ -133,10 +133,10 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
|
||||
}
|
||||
|
||||
/* Write quads. */
|
||||
const int quad_offset = poly_offset + vdb_tris.size();
|
||||
const int quad_offset = face_offset + vdb_tris.size();
|
||||
const int quad_loop_offset = loop_offset + vdb_tris.size() * 3;
|
||||
for (const int i : vdb_quads.index_range()) {
|
||||
poly_offsets[quad_offset + i] = quad_loop_offset + 4 * i;
|
||||
face_offsets[quad_offset + i] = quad_loop_offset + 4 * i;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
/* Reverse vertex order to get correct normals. */
|
||||
corner_verts[quad_loop_offset + 4 * i + j] = vert_offset + vdb_quads[i][3 - j];
|
||||
@@ -167,8 +167,8 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
|
||||
grid, resolution, threshold, adaptivity);
|
||||
|
||||
const int tot_loops = 3 * mesh_data.tris.size() + 4 * mesh_data.quads.size();
|
||||
const int tot_polys = mesh_data.tris.size() + mesh_data.quads.size();
|
||||
Mesh *mesh = BKE_mesh_new_nomain(mesh_data.verts.size(), 0, tot_polys, tot_loops);
|
||||
const int tot_faces = mesh_data.tris.size() + mesh_data.quads.size();
|
||||
Mesh *mesh = BKE_mesh_new_nomain(mesh_data.verts.size(), 0, tot_faces, tot_loops);
|
||||
|
||||
fill_mesh_from_openvdb_data(mesh_data.verts,
|
||||
mesh_data.tris,
|
||||
@@ -177,7 +177,7 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
|
||||
0,
|
||||
0,
|
||||
mesh->vert_positions_for_write(),
|
||||
mesh->poly_offsets_for_write(),
|
||||
mesh->face_offsets_for_write(),
|
||||
mesh->corner_verts_for_write());
|
||||
|
||||
BKE_mesh_calc_edges(mesh, false, false);
|
||||
|
||||
@@ -180,7 +180,7 @@ BLI_INLINE void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
|
||||
}
|
||||
|
||||
#define BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(totloop) ((totloop) / 2)
|
||||
#define BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly) ((totpoly)*2)
|
||||
#define BLI_EDGEHASH_SIZE_GUESS_FROM_FACES(faces_num) ((faces_num)*2)
|
||||
|
||||
/* *** EdgeSet *** */
|
||||
|
||||
|
||||
@@ -2098,7 +2098,7 @@ static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena)
|
||||
const double3 &poly_normal = f->plane->norm;
|
||||
int axis = math::dominant_axis(poly_normal);
|
||||
/* If project down y axis as opposed to x or z, the orientation
|
||||
* of the polygon will be reversed.
|
||||
* of the face will be reversed.
|
||||
* Yet another reversal happens if the poly normal in the dominant
|
||||
* direction is opposite that of the positive dominant axis. */
|
||||
bool rev1 = (axis == 1);
|
||||
|
||||
@@ -1109,7 +1109,7 @@ void blo_do_versions_250(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
|
||||
if (bmain->versionfile == 250 && bmain->subversionfile > 1) {
|
||||
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
|
||||
CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
|
||||
CustomData_free_layer_active(&me->fdata_legacy, CD_MDISPS, me->totface_legacy);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
|
||||
@@ -2924,7 +2924,7 @@ void do_versions_after_linking_280(FileData *fd, Main *bmain)
|
||||
* harm to be expected anyway for being over-conservative. */
|
||||
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
|
||||
/* Check if we need to convert mfaces to polys. */
|
||||
if (me->totface && !me->totpoly) {
|
||||
if (me->totface_legacy && !me->faces_num) {
|
||||
/* temporarily switch main so that reading from
|
||||
* external CustomData works */
|
||||
Main *orig_gmain = BKE_blender_globals_main_swap(bmain);
|
||||
@@ -3199,7 +3199,7 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2))
|
||||
{
|
||||
CustomData_update_typemap(&me->pdata);
|
||||
CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->totpoly);
|
||||
CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->faces_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6364,7 +6364,7 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
|
||||
/* Default Face Set Color. */
|
||||
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
|
||||
if (me->totpoly > 0) {
|
||||
if (me->faces_num > 0) {
|
||||
const int *face_sets = static_cast<const int *>(
|
||||
CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS));
|
||||
if (face_sets) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user