#70267 Retopology Overlay #104599
|
@ -364,6 +364,7 @@ const bTheme U_theme_default = {
|
|||
.handle_sel_vect = RGBA(0x40c030ff),
|
||||
.handle_sel_align = RGBA(0xf090a0ff),
|
||||
.vertex_size = 3,
|
||||
.edge_width = 1,
|
||||
.outline_width = 1,
|
||||
.obcenter_dia = 6,
|
||||
.facedot_size = 3,
|
||||
|
@ -718,6 +719,7 @@ const bTheme U_theme_default = {
|
|||
.handle_sel_auto = RGBA(0xf0ff40ff),
|
||||
.handle_sel_align = RGBA(0xf090a0ff),
|
||||
.vertex_size = 3,
|
||||
.edge_width = 1,
|
||||
.outline_width = 1,
|
||||
.facedot_size = 3,
|
||||
.editmesh_active = RGBA(0xffffff40),
|
||||
|
|
|
@ -60,12 +60,12 @@ extern "C" {
|
|||
/**
|
||||
* Call after changing vertex positions to tag lazily calculated caches for recomputation.
|
||||
*/
|
||||
void BKE_mesh_tag_coords_changed(struct Mesh *mesh);
|
||||
void BKE_mesh_tag_positions_changed(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Call after moving every mesh vertex by the same translation.
|
||||
*/
|
||||
void BKE_mesh_tag_coords_changed_uniformly(struct Mesh *mesh);
|
||||
void BKE_mesh_tag_positions_changed_uniformly(struct Mesh *mesh);
|
||||
|
||||
void BKE_mesh_tag_topology_changed(struct Mesh *mesh);
|
||||
|
||||
|
@ -164,6 +164,7 @@ struct Mesh *BKE_mesh_new_nomain_from_template(
|
|||
struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
|
||||
int verts_len,
|
||||
int edges_len,
|
||||
int tessface_len,
|
||||
int loops_len,
|
||||
int polys_len,
|
||||
struct CustomData_MeshMasks mask);
|
||||
|
@ -341,7 +342,7 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
|
|||
* from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
|
||||
* \warning May still return null if the mesh is empty.
|
||||
*/
|
||||
const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
|
||||
const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Return the normal direction of every polygon, which is defined by the winding direction of its
|
||||
|
@ -364,13 +365,13 @@ void BKE_mesh_normals_tag_dirty(struct Mesh *mesh);
|
|||
* calculated automatically.
|
||||
*
|
||||
* \note In order to clear the dirty flag, this function should be followed by a call to
|
||||
* #BKE_mesh_vertex_normals_clear_dirty. This is separate so that normals are still tagged dirty
|
||||
* #BKE_mesh_vert_normals_clear_dirty. This is separate so that normals are still tagged dirty
|
||||
* while they are being assigned.
|
||||
*
|
||||
* \warning The memory returned by this function is not initialized if it was not previously
|
||||
* allocated.
|
||||
*/
|
||||
float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
|
||||
float (*BKE_mesh_vert_normals_for_write(struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Retrieve write access to the cached polygon normals, ensuring that they are allocated but *not*
|
||||
|
@ -389,7 +390,7 @@ float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3];
|
|||
/**
|
||||
* Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually.
|
||||
*/
|
||||
void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
|
||||
void BKE_mesh_vert_normals_clear_dirty(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Mark the mesh's poly normals non-dirty, for when they are calculated or assigned manually.
|
||||
|
@ -400,7 +401,7 @@ void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh);
|
|||
* Return true if the mesh vertex 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_vertex_normals_are_dirty(const 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.
|
||||
|
@ -430,7 +431,7 @@ void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
|
|||
/**
|
||||
* Calculate face and vertex normals directly into result arrays.
|
||||
*
|
||||
* \note Usually #BKE_mesh_vertex_normals_ensure is the preferred way to access vertex normals,
|
||||
* \note Usually #BKE_mesh_vert_normals_ensure is the preferred way to access vertex normals,
|
||||
* since they may already be calculated and cached on the mesh.
|
||||
*/
|
||||
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
|
||||
|
@ -446,7 +447,7 @@ void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
|
|||
* Calculate vertex and face normals, storing the result in custom data layers on the mesh.
|
||||
*
|
||||
* \note It is usually preferable to calculate normals lazily with
|
||||
* #BKE_mesh_vertex_normals_ensure, but some areas (perhaps unnecessarily)
|
||||
* #BKE_mesh_vert_normals_ensure, but some areas (perhaps unnecessarily)
|
||||
* can also calculate them eagerly.
|
||||
*/
|
||||
void BKE_mesh_calc_normals(struct Mesh *me);
|
||||
|
@ -1059,9 +1060,9 @@ inline blender::Span<blender::float3> Mesh::poly_normals() const
|
|||
this->totpoly};
|
||||
}
|
||||
|
||||
inline blender::Span<blender::float3> Mesh::vertex_normals() const
|
||||
inline blender::Span<blender::float3> Mesh::vert_normals() const
|
||||
{
|
||||
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vertex_normals_ensure(this)),
|
||||
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_normals_ensure(this)),
|
||||
this->totvert};
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
|
|||
* directly or making other large changes to topology. It does not need to be called on new meshes.
|
||||
*
|
||||
* For "smaller" changes to meshes like updating positions, consider calling a more specific update
|
||||
* function like #BKE_mesh_tag_coords_changed.
|
||||
* function like #BKE_mesh_tag_positions_changed.
|
||||
*
|
||||
* Also note that some derived caches like #CD_NORMAL and #CD_TANGENT are stored directly in
|
||||
* #CustomData.
|
||||
|
|
|
@ -222,7 +222,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
|
|||
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
|
||||
/* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
|
||||
* or dirty normals. */
|
||||
cddm->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
cddm->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
cddm->medge = static_cast<MEdge *>(
|
||||
CustomData_get_layer_for_write(&dm->edgeData, CD_MEDGE, mesh->totedge));
|
||||
cddm->mloop = static_cast<MLoop *>(
|
||||
|
|
|
@ -1185,7 +1185,7 @@ static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
|
|||
for (const int i : positions.index_range()) {
|
||||
positions[i] = verts[i].xrest;
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(new_mesh);
|
||||
BKE_mesh_tag_positions_changed(new_mesh);
|
||||
|
||||
return new_mesh;
|
||||
}
|
||||
|
@ -1531,7 +1531,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
|
|||
BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2);
|
||||
rng = BLI_rng_new_srandom(0);
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
|
||||
|
||||
for (int i = 0; i < mvert_num; i++) {
|
||||
if (find_internal_spring_target_vertex(
|
||||
|
|
|
@ -546,7 +546,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
|
|||
}
|
||||
}
|
||||
else if (me_eval) {
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me_eval);
|
||||
const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
|
||||
int numVerts = me_eval->totvert;
|
||||
|
|
|
@ -383,7 +383,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
|||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
BKE_mesh_normals_loop_split(positions_dst,
|
||||
BKE_mesh_vertex_normals_ensure(me_dst),
|
||||
BKE_mesh_vert_normals_ensure(me_dst),
|
||||
num_verts_dst,
|
||||
edges_dst.data(),
|
||||
edges_dst.size(),
|
||||
|
@ -442,7 +442,7 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
|
|||
|
||||
/* Note loop_nors_dst contains our custom normals as transferred from source... */
|
||||
BKE_mesh_normals_loop_custom_set(positions_dst,
|
||||
BKE_mesh_vertex_normals_ensure(me_dst),
|
||||
BKE_mesh_vert_normals_ensure(me_dst),
|
||||
num_verts_dst,
|
||||
edges_dst.data(),
|
||||
edges_dst.size(),
|
||||
|
@ -1344,7 +1344,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
|
|||
BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
|
||||
|
||||
if (me_dst) {
|
||||
dirty_nors_dst = BKE_mesh_vertex_normals_are_dirty(me_dst);
|
||||
dirty_nors_dst = BKE_mesh_vert_normals_are_dirty(me_dst);
|
||||
/* Never create needed custom layers on passed destination mesh
|
||||
* (assumed to *not* be ob_dst->data, aka modifier case). */
|
||||
use_create = false;
|
||||
|
|
|
@ -1828,7 +1828,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh
|
|||
DynamicPaintModifierApplyData data{};
|
||||
data.surface = surface;
|
||||
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
|
||||
data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
|
@ -2029,20 +2029,20 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
|
|||
DynamicPaintModifierApplyData data{};
|
||||
data.surface = surface;
|
||||
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
|
||||
data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
settings.use_threading = (sData->total_points > 1000);
|
||||
BLI_task_parallel_range(
|
||||
0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings);
|
||||
BKE_mesh_tag_coords_changed(result);
|
||||
BKE_mesh_tag_positions_changed(result);
|
||||
}
|
||||
|
||||
/* displace */
|
||||
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
|
||||
dynamicPaint_applySurfaceDisplace(surface, result);
|
||||
BKE_mesh_tag_coords_changed(result);
|
||||
BKE_mesh_tag_positions_changed(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4293,7 +4293,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
|
|||
|
||||
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
|
||||
float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
|
||||
const blender::Span<MLoop> loops = mesh->loops();
|
||||
numOfVerts = mesh->totvert;
|
||||
|
@ -6154,7 +6154,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
|
|||
data.surface = surface;
|
||||
data.ob = ob;
|
||||
data.positions = positions;
|
||||
data.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
data.canvas_verts = canvas_verts;
|
||||
data.do_velocity_data = do_velocity_data;
|
||||
data.new_bdata = new_bdata;
|
||||
|
|
|
@ -703,7 +703,7 @@ bool get_effector_data(EffectorCache *eff,
|
|||
/* TODO: hair and points object support */
|
||||
const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me_eval);
|
||||
if (me_eval != NULL) {
|
||||
copy_v3_v3(efd->loc, positions[*efd->index]);
|
||||
copy_v3_v3(efd->nor, vert_normals[*efd->index]);
|
||||
|
|
|
@ -2092,8 +2092,8 @@ static void emit_from_mesh(
|
|||
|
||||
/* Transform mesh vertices to domain grid space for fast lookups.
|
||||
* This is valid because the mesh is copied above. */
|
||||
BKE_mesh_vertex_normals_ensure(me);
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me);
|
||||
BKE_mesh_vert_normals_ensure(me);
|
||||
float(*vert_normals)[3] = BKE_mesh_vert_normals_for_write(me);
|
||||
for (i = 0; i < numverts; i++) {
|
||||
/* Vertex position. */
|
||||
mul_m4_v3(flow_ob->object_to_world, positions[i]);
|
||||
|
|
|
@ -127,14 +127,14 @@ VArray<float3> mesh_normals_varray(const Mesh &mesh,
|
|||
return VArray<float3>::ForSpan(mesh.poly_normals());
|
||||
}
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
return VArray<float3>::ForSpan(mesh.vertex_normals());
|
||||
return VArray<float3>::ForSpan(mesh.vert_normals());
|
||||
}
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
/* In this case, start with vertex normals and convert to the edge domain, since the
|
||||
* conversion from edges to vertices is very simple. Use "manual" domain interpolation
|
||||
* instead of the GeometryComponent API to avoid calculating unnecessary values and to
|
||||
* allow normalizing the result more simply. */
|
||||
Span<float3> vert_normals = mesh.vertex_normals();
|
||||
Span<float3> vert_normals = mesh.vert_normals();
|
||||
const Span<MEdge> edges = mesh.edges();
|
||||
Array<float3> edge_normals(mask.min_array_size());
|
||||
for (const int i : mask) {
|
||||
|
@ -909,7 +909,7 @@ static void tag_component_positions_changed(void *owner)
|
|||
{
|
||||
Mesh *mesh = static_cast<Mesh *>(owner);
|
||||
if (mesh != nullptr) {
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2497,7 +2497,7 @@ static void gpencil_generate_edgeloops(Object *ob,
|
|||
const Span<float3> vert_positions = me->vert_positions();
|
||||
const Span<MEdge> edges = me->edges();
|
||||
const Span<MDeformVert> dverts = me->deform_verts();
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
|
||||
|
||||
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
|
||||
* This is reused for each edge-loop to create gpencil stroke. */
|
||||
|
|
|
@ -1496,11 +1496,10 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
normalize_v3(process.no[i]);
|
||||
}
|
||||
memcpy(BKE_mesh_vertex_normals_for_write(mesh),
|
||||
process.no,
|
||||
sizeof(float[3]) * size_t(mesh->totvert));
|
||||
memcpy(
|
||||
BKE_mesh_vert_normals_for_write(mesh), process.no, sizeof(float[3]) * size_t(mesh->totvert));
|
||||
MEM_freeN(process.no);
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
BKE_mesh_vert_normals_clear_dirty(mesh);
|
||||
|
||||
mesh->totloop = loop_offset;
|
||||
|
||||
|
|
|
@ -1054,17 +1054,21 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
|
|||
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
||||
int verts_len,
|
||||
int edges_len,
|
||||
int tessface_len,
|
||||
int loops_len,
|
||||
int polys_len,
|
||||
CustomData_MeshMasks mask)
|
||||
{
|
||||
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
|
||||
const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0)));
|
||||
|
||||
Mesh *me_dst = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
|
||||
|
||||
me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect);
|
||||
|
||||
me_dst->totvert = verts_len;
|
||||
me_dst->totedge = edges_len;
|
||||
me_dst->totface = 0;
|
||||
me_dst->totface = tessface_len;
|
||||
me_dst->totloop = loops_len;
|
||||
me_dst->totpoly = polys_len;
|
||||
|
||||
|
@ -1074,14 +1078,22 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
|
|||
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
|
||||
CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
|
||||
CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
if (do_tessface) {
|
||||
CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
|
||||
}
|
||||
else {
|
||||
mesh_tessface_clear_intern(me_dst, false);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) {
|
||||
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, me_dst->totface);
|
||||
}
|
||||
|
||||
/* Expect that normals aren't copied at all, since the destination mesh is new. */
|
||||
BLI_assert(BKE_mesh_vertex_normals_are_dirty(me_dst));
|
||||
BLI_assert(BKE_mesh_vert_normals_are_dirty(me_dst));
|
||||
|
||||
return me_dst;
|
||||
}
|
||||
|
@ -1090,7 +1102,7 @@ Mesh *BKE_mesh_new_nomain_from_template(
|
|||
const Mesh *me_src, int verts_len, int edges_len, int loops_len, int polys_len)
|
||||
{
|
||||
return BKE_mesh_new_nomain_from_template_ex(
|
||||
me_src, verts_len, edges_len, loops_len, polys_len, CD_MASK_EVERYTHING);
|
||||
me_src, verts_len, edges_len, 0, loops_len, polys_len, CD_MASK_EVERYTHING);
|
||||
}
|
||||
|
||||
void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
|
||||
|
@ -1597,7 +1609,7 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
|
|||
mul_m3_v3(m3, *lnors);
|
||||
}
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(me);
|
||||
BKE_mesh_tag_positions_changed(me);
|
||||
}
|
||||
|
||||
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
|
||||
|
@ -1616,7 +1628,7 @@ void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
|
|||
}
|
||||
}
|
||||
}
|
||||
BKE_mesh_tag_coords_changed_uniformly(me);
|
||||
BKE_mesh_tag_positions_changed_uniformly(me);
|
||||
}
|
||||
|
||||
void BKE_mesh_tessface_clear(Mesh *mesh)
|
||||
|
@ -1782,7 +1794,7 @@ void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
|
|||
for (const int i : positions.index_range()) {
|
||||
copy_v3_v3(positions[i], vert_coords[i]);
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
|
||||
|
@ -1793,7 +1805,7 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
|
|||
for (const int i : positions.index_range()) {
|
||||
mul_v3_m4v3(positions[i], mat, vert_coords[i]);
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
}
|
||||
|
||||
static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
|
||||
|
@ -1835,7 +1847,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
|||
const Span<MLoop> loops = mesh->loops();
|
||||
|
||||
BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
BKE_mesh_vert_normals_ensure(mesh),
|
||||
positions.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
|
|
|
@ -68,7 +68,7 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX));
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vertex_normals_ensure(mesh) :
|
||||
BKE_mesh_vert_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
|
||||
if (index) {
|
||||
|
@ -311,7 +311,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
|||
const blender::Span<MPoly> polys = mesh->polys();
|
||||
const blender::Span<MLoop> loops = mesh->loops();
|
||||
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
BKE_mesh_vertex_normals_ensure(mesh) :
|
||||
BKE_mesh_vert_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
|
||||
const blender::BitSpan facedot_tags = mesh->runtime->subsurf_face_dot_tags;
|
||||
|
|
|
@ -400,7 +400,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
BKE_mesh_normals_loop_split(BKE_mesh_vert_positions(result),
|
||||
BKE_mesh_vertex_normals_ensure(result),
|
||||
BKE_mesh_vert_normals_ensure(result),
|
||||
result->totvert,
|
||||
result->edges().data(),
|
||||
result->totedge,
|
||||
|
|
|
@ -106,7 +106,7 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
|
|||
mesh->runtime->poly_normals_dirty = true;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
|
||||
float (*BKE_mesh_vert_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime->vert_normals == nullptr) {
|
||||
mesh->runtime->vert_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
|
@ -130,7 +130,7 @@ float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
|
|||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
|
||||
void BKE_mesh_vert_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = false;
|
||||
BLI_assert(mesh->runtime->vert_normals || mesh->totvert == 0);
|
||||
|
@ -142,7 +142,7 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
|
|||
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
|
||||
}
|
||||
|
||||
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
|
||||
bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime->vert_normals_dirty;
|
||||
}
|
||||
|
@ -368,9 +368,9 @@ void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
|
|||
/** \name Mesh Normal Calculation
|
||||
* \{ */
|
||||
|
||||
const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
||||
const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr || mesh->totvert == 0);
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
|||
}
|
||||
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr);
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
|||
const Span<MPoly> polys = mesh_mutable.polys();
|
||||
const Span<MLoop> loops = mesh_mutable.loops();
|
||||
|
||||
vert_normals = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
|
||||
vert_normals = BKE_mesh_vert_normals_for_write(&mesh_mutable);
|
||||
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
|
||||
BKE_mesh_calc_normals_poly_and_vertex(reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
|
@ -407,7 +407,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
|||
poly_normals,
|
||||
vert_normals);
|
||||
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_vert_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
|
@ -461,7 +461,7 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
|||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
BKE_mesh_vert_normals_ensure(mesh);
|
||||
BKE_mesh_poly_normals_ensure(mesh);
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
|
@ -481,7 +481,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
|
|||
#ifdef DEBUG_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
#endif
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
BKE_mesh_vert_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
|
||||
|
@ -1932,7 +1932,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
|||
"sharp_edge", ATTR_DOMAIN_EDGE);
|
||||
|
||||
mesh_normals_loop_custom_set(reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
BKE_mesh_vert_normals_ensure(mesh),
|
||||
positions.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
|
|
|
@ -571,7 +571,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
|
|||
const blender::Span<MPoly> polys_src = me_src->polys();
|
||||
const blender::Span<MLoop> loops_src = me_src->loops();
|
||||
float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr);
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst);
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
|
||||
|
||||
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
|
||||
float(*vcos)[3] = static_cast<float(*)[3]>(
|
||||
|
@ -937,7 +937,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
|||
|
||||
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
|
||||
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst);
|
||||
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
|
||||
|
||||
for (i = 0; i < numedges_dst; i++) {
|
||||
/* For each dst edge, we sample some rays from it (interpolated from its vertices)
|
||||
|
@ -1365,7 +1365,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
BKE_mesh_normals_loop_split(vert_positions_dst,
|
||||
BKE_mesh_vertex_normals_ensure(mesh_dst),
|
||||
BKE_mesh_vert_normals_ensure(mesh_dst),
|
||||
numverts_dst,
|
||||
edges_dst,
|
||||
numedges_dst,
|
||||
|
|
|
@ -124,7 +124,9 @@ const blender::bke::LooseEdgeCache &Mesh::loose_edges() const
|
|||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
loose_edges.clear_and_shrink();
|
||||
}
|
||||
r_data.count = count;
|
||||
});
|
||||
|
||||
|
@ -135,7 +137,7 @@ void Mesh::loose_edges_tag_none() const
|
|||
{
|
||||
using namespace blender::bke;
|
||||
this->runtime->loose_edges_cache.ensure([&](LooseEdgeCache &r_data) {
|
||||
r_data.is_loose_bits.resize(0);
|
||||
r_data.is_loose_bits.clear_and_shrink();
|
||||
r_data.count = 0;
|
||||
});
|
||||
}
|
||||
|
@ -252,7 +254,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_tag_coords_changed(Mesh *mesh)
|
||||
void BKE_mesh_tag_positions_changed(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
|
@ -260,7 +262,7 @@ void BKE_mesh_tag_coords_changed(Mesh *mesh)
|
|||
mesh->runtime->bounds_cache.tag_dirty();
|
||||
}
|
||||
|
||||
void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
|
||||
void BKE_mesh_tag_positions_changed_uniformly(Mesh *mesh)
|
||||
{
|
||||
/* The normals and triangulation didn't change, since all verts moved by the same amount. */
|
||||
free_bvh_cache(*mesh->runtime);
|
||||
|
|
|
@ -586,7 +586,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
|||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
BKE_mesh_vertex_normals_ensure(me_eval),
|
||||
BKE_mesh_vert_normals_ensure(me_eval),
|
||||
BKE_mesh_poly_normals_ensure(me_eval),
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
|
||||
/* may be nullptr */
|
||||
|
|
|
@ -298,8 +298,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
|
|||
}
|
||||
|
||||
const float(*vert_normals)[3] = nullptr;
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
|
||||
vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
for (i = 0; i < totvert; i++) {
|
||||
|
|
|
@ -1018,7 +1018,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
|
|||
}
|
||||
mti->deformVerts(md, ctx, me, vertexCos, numVerts);
|
||||
if (me) {
|
||||
BKE_mesh_tag_coords_changed(me);
|
||||
BKE_mesh_tag_positions_changed(me);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
|||
/* Vertices were moved around, need to update normals after all the vertices are updated
|
||||
* Probably this is possible to do in the loop above, but this is rather tricky because
|
||||
* we don't know all needed vertices' coordinates there yet. */
|
||||
BKE_mesh_tag_coords_changed(base_mesh);
|
||||
BKE_mesh_tag_positions_changed(base_mesh);
|
||||
}
|
||||
|
||||
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)
|
||||
|
|
|
@ -735,7 +735,7 @@ static void make_duplis_verts(const DupliContext *ctx)
|
|||
vdd.params = vdd_params;
|
||||
vdd.totvert = me_eval->totvert;
|
||||
vdd.vert_positions = me_eval->vert_positions();
|
||||
vdd.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval);
|
||||
vdd.vert_normals = BKE_mesh_vert_normals_ensure(me_eval);
|
||||
vdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vdata, CD_ORCO);
|
||||
|
||||
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh);
|
||||
|
|
|
@ -2160,7 +2160,7 @@ void psys_particle_on_dm(Mesh *mesh_final,
|
|||
}
|
||||
|
||||
orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh_final->vdata, CD_ORCO));
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh_final);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh_final);
|
||||
|
||||
if (from == PART_FROM_VERT) {
|
||||
const float(*vert_positions)[3] = BKE_mesh_vert_positions(mesh_final);
|
||||
|
|
|
@ -613,18 +613,8 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
|
|||
/* experimental */
|
||||
tot = mesh->totface;
|
||||
|
||||
psys_interpolate_face(mesh,
|
||||
positions,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
mface,
|
||||
0,
|
||||
0,
|
||||
pa->fuv,
|
||||
co,
|
||||
nor,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
psys_interpolate_face(
|
||||
mesh, positions, BKE_mesh_vert_normals_ensure(mesh), mface, 0, 0, pa->fuv, co, nor, 0, 0, 0);
|
||||
|
||||
normalize_v3(nor);
|
||||
negate_v3(nor);
|
||||
|
|
|
@ -834,8 +834,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
pbvh->mloop = mloop;
|
||||
pbvh->looptri = looptri;
|
||||
pbvh->vert_positions = vert_positions;
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(mesh);
|
||||
BKE_mesh_vert_normals_ensure(mesh);
|
||||
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
||||
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
|
||||
pbvh->vert_bitmap = static_cast<bool *>(
|
||||
|
|
|
@ -672,7 +672,6 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
|
|||
uv_islands::MeshData mesh_data(
|
||||
{pbvh->looptri, pbvh->totprim},
|
||||
{pbvh->mloop, mesh->totloop},
|
||||
pbvh->totvert,
|
||||
uv_map,
|
||||
{static_cast<blender::float3 *>(static_cast<void *>(pbvh->vert_positions)), pbvh->totvert});
|
||||
uv_islands::UVIslands islands(mesh_data);
|
||||
|
|
|
@ -200,15 +200,13 @@ static void mesh_data_init(MeshData &mesh_data)
|
|||
|
||||
MeshData::MeshData(const Span<MLoopTri> looptris,
|
||||
const Span<MLoop> loops,
|
||||
const int verts_num,
|
||||
const Span<float2> uv_map,
|
||||
const Span<float3> vertex_positions)
|
||||
const Span<float3> vert_positions)
|
||||
: looptris(looptris),
|
||||
verts_num(verts_num),
|
||||
loops(loops),
|
||||
uv_map(uv_map),
|
||||
vertex_positions(vertex_positions),
|
||||
vert_to_edge_map(verts_num),
|
||||
vert_positions(vert_positions),
|
||||
vert_to_edge_map(vert_positions.size()),
|
||||
edge_to_primitive_map(0),
|
||||
primitive_to_edge_map(looptris.size())
|
||||
{
|
||||
|
@ -1085,7 +1083,7 @@ void UVIsland::print_debug(const MeshData &mesh_data) const
|
|||
ss << "import mathutils\n";
|
||||
|
||||
ss << "uvisland_vertices = [\n";
|
||||
for (const float3 &vertex_position : mesh_data.vertex_positions) {
|
||||
for (const float3 &vertex_position : mesh_data.vert_positions) {
|
||||
ss << " mathutils.Vector((" << vertex_position.x << ", " << vertex_position.y << ", "
|
||||
<< vertex_position.z << ")),\n";
|
||||
}
|
||||
|
|
|
@ -119,10 +119,9 @@ class TriangleToEdgeMap {
|
|||
struct MeshData {
|
||||
public:
|
||||
const Span<MLoopTri> looptris;
|
||||
const int64_t verts_num;
|
||||
const Span<MLoop> loops;
|
||||
const Span<float2> uv_map;
|
||||
const Span<float3> vertex_positions;
|
||||
const Span<float3> vert_positions;
|
||||
|
||||
VertToEdgeMap vert_to_edge_map;
|
||||
|
||||
|
@ -142,9 +141,8 @@ struct MeshData {
|
|||
public:
|
||||
explicit MeshData(Span<MLoopTri> looptris,
|
||||
Span<MLoop> loops,
|
||||
const int verts_num,
|
||||
const Span<float2> uv_map,
|
||||
const Span<float3> vertex_positions);
|
||||
const Span<float3> vert_positions);
|
||||
};
|
||||
|
||||
struct UVVertex {
|
||||
|
|
|
@ -115,7 +115,7 @@ bool BKE_shrinkwrap_init_tree(
|
|||
|
||||
data->mesh = mesh;
|
||||
data->polys = mesh->polys().data();
|
||||
data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
data->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
|
||||
if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
|
||||
data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2);
|
||||
|
@ -296,7 +296,7 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
|
|||
MEM_freeN(vert_status);
|
||||
|
||||
/* Finalize average direction and compute normal. */
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
int bidx = vert_boundary_id[i];
|
||||
|
||||
|
@ -1408,7 +1408,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
|||
if (mesh != nullptr && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
|
||||
/* Setup arrays to get vertex positions, normals and deform weights */
|
||||
calc.vert_positions = BKE_mesh_vert_positions_for_write(mesh);
|
||||
calc.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
calc.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
|
||||
/* Using vertices positions/normals as if a subsurface was applied */
|
||||
if (smd->subsurfLevels) {
|
||||
|
@ -1569,7 +1569,7 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
|
|||
calc.smd = &ssmd;
|
||||
calc.numVerts = src_me->totvert;
|
||||
calc.vertexCos = vertexCos;
|
||||
calc.vert_normals = BKE_mesh_vertex_normals_ensure(src_me);
|
||||
calc.vert_normals = BKE_mesh_vert_normals_ensure(src_me);
|
||||
calc.vgroup = -1;
|
||||
calc.target = target_me;
|
||||
calc.keepDist = ssmd.keepDist;
|
||||
|
|
|
@ -535,7 +535,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, num_loops, num_polygons, mask);
|
||||
subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, 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();
|
||||
|
@ -1215,13 +1215,18 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
|
|||
});
|
||||
}
|
||||
|
||||
if (subdiv->settings.is_simple) {
|
||||
/* In simple subdivision, min and max positions are not changed, avoid recomputing bounds. */
|
||||
result->runtime->bounds_cache = coarse_mesh->runtime->bounds_cache;
|
||||
}
|
||||
|
||||
// BKE_mesh_validate(result, true, true);
|
||||
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
/* Using normals from the limit surface gives different results than Blender's vertex normal
|
||||
* 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_vertex_normals_are_dirty(result) || BKE_mesh_poly_normals_are_dirty(result));
|
||||
BLI_assert(BKE_mesh_vert_normals_are_dirty(result) || BKE_mesh_poly_normals_are_dirty(result));
|
||||
/* Free used memory. */
|
||||
subdiv_mesh_context_free(&subdiv_context);
|
||||
return result;
|
||||
|
|
|
@ -302,7 +302,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
|||
|
||||
const float(*vert_normals)[3] = nullptr;
|
||||
if (params->calc_vert_normal) {
|
||||
vert_normals = BKE_mesh_vertex_normals_ensure(me);
|
||||
vert_normals = BKE_mesh_vert_normals_ensure(me);
|
||||
}
|
||||
|
||||
if (is_new) {
|
||||
|
|
|
@ -359,7 +359,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
|||
|
||||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
/* Mesh */
|
||||
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mr->me);
|
||||
mr->vert_normals = BKE_mesh_vert_normals_ensure(mr->me);
|
||||
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
|
||||
mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me);
|
||||
}
|
||||
|
|
|
@ -1625,7 +1625,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
|||
GPUVertBuf *face_adjacency_offsets,
|
||||
GPUVertBuf *face_adjacency_lists,
|
||||
GPUVertBuf *vertex_loop_map,
|
||||
GPUVertBuf *vertex_normals)
|
||||
GPUVertBuf *vert_normals)
|
||||
{
|
||||
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_NORMALS_ACCUMULATE);
|
||||
GPU_shader_bind(shader);
|
||||
|
@ -1636,7 +1636,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
|||
GPU_vertbuf_bind_as_ssbo(face_adjacency_offsets, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(face_adjacency_lists, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vertex_loop_map, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
|
||||
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
|
||||
|
||||
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_verts);
|
||||
|
@ -1651,7 +1651,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
|||
}
|
||||
|
||||
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *vertex_normals,
|
||||
GPUVertBuf *vert_normals,
|
||||
GPUVertBuf *subdiv_loop_subdiv_vert_index,
|
||||
GPUVertBuf *pos_nor)
|
||||
{
|
||||
|
@ -1659,7 +1659,7 @@ void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
|
|||
GPU_shader_bind(shader);
|
||||
|
||||
int binding_point = 0;
|
||||
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(subdiv_loop_subdiv_vert_index, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
|
||||
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
|
||||
|
|
|
@ -176,8 +176,8 @@ void DRW_globals_update(void)
|
|||
max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f);
|
||||
gb->size_vertex_gpencil = U.pixelsize * UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
|
||||
gb->size_face_dot = U.pixelsize * UI_GetThemeValuef(TH_FACEDOT_SIZE);
|
||||
gb->size_edge = U.pixelsize * (1.0f / 2.0f); /* TODO: Theme. */
|
||||
gb->size_edge_fix = U.pixelsize * (0.5f + 2.0f * (2.0f * (gb->size_edge * (float)M_SQRT1_2)));
|
||||
gb->size_edge = U.pixelsize * max_ff(1.0f, UI_GetThemeValuef(TH_EDGE_WIDTH)) / 2.0f;
|
||||
gb->size_edge_fix = U.pixelsize * (0.5f + 2.0f * (1.0f * (gb->size_edge * (float)M_SQRT1_2)));
|
||||
|
||||
gb->pixel_fac = *DRW_viewport_pixelsize_get();
|
||||
|
||||
|
|
|
@ -229,10 +229,10 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
|||
struct GPUVertBuf *face_adjacency_offsets,
|
||||
struct GPUVertBuf *face_adjacency_lists,
|
||||
struct GPUVertBuf *vertex_loop_map,
|
||||
struct GPUVertBuf *vertex_normals);
|
||||
struct GPUVertBuf *vert_normals);
|
||||
|
||||
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
|
||||
struct GPUVertBuf *vertex_normals,
|
||||
struct GPUVertBuf *vert_normals,
|
||||
struct GPUVertBuf *subdiv_loop_subdiv_vert_index,
|
||||
struct GPUVertBuf *pos_nor);
|
||||
|
||||
|
|
|
@ -291,20 +291,20 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
|
||||
subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
|
||||
|
||||
GPUVertBuf *vertex_normals = GPU_vertbuf_calloc();
|
||||
GPUVertBuf *vert_normals = GPU_vertbuf_calloc();
|
||||
GPU_vertbuf_init_build_on_device(
|
||||
vertex_normals, get_normals_format(), subdiv_cache->num_subdiv_verts);
|
||||
vert_normals, get_normals_format(), subdiv_cache->num_subdiv_verts);
|
||||
|
||||
draw_subdiv_accumulate_normals(subdiv_cache,
|
||||
vbo,
|
||||
subdiv_cache->subdiv_vertex_face_adjacency_offsets,
|
||||
subdiv_cache->subdiv_vertex_face_adjacency,
|
||||
subdiv_loop_subdiv_vert_index,
|
||||
vertex_normals);
|
||||
vert_normals);
|
||||
|
||||
draw_subdiv_finalize_normals(subdiv_cache, vertex_normals, subdiv_loop_subdiv_vert_index, vbo);
|
||||
draw_subdiv_finalize_normals(subdiv_cache, vert_normals, subdiv_loop_subdiv_vert_index, vbo);
|
||||
|
||||
GPU_vertbuf_discard(vertex_normals);
|
||||
GPU_vertbuf_discard(vert_normals);
|
||||
GPU_vertbuf_discard(subdiv_loop_subdiv_vert_index);
|
||||
}
|
||||
|
||||
|
|
|
@ -348,26 +348,6 @@ struct UVMapUDIM_Params {
|
|||
int grid_shape[2];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */
|
||||
ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */
|
||||
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
|
||||
} eUVPackIsland_MarginMethod;
|
||||
|
||||
/** See also #UnwrapOptions. */
|
||||
struct UVPackIsland_Params {
|
||||
uint rotate : 1;
|
||||
uint only_selected_uvs : 1;
|
||||
uint only_selected_faces : 1;
|
||||
uint use_seams : 1;
|
||||
uint correct_aspect : 1;
|
||||
bool ignore_pinned; /* Ignore islands which have any pinned UVs. */
|
||||
bool pin_unselected; /* Treat unselected UVs as if they were pinned. */
|
||||
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
|
||||
float margin; /* Additional space to add around each island. */
|
||||
float udim_base_offset[2]; /* Additional translation for bottom left corner. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image.
|
||||
*/
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef enum ThemeColorID {
|
|||
TH_VERTEX_ACTIVE,
|
||||
TH_VERTEX_UNREFERENCED,
|
||||
TH_VERTEX_SIZE,
|
||||
TH_EDGE_WIDTH,
|
||||
TH_OUTLINE_WIDTH,
|
||||
TH_OBCENTER_DIA,
|
||||
TH_EDGE,
|
||||
|
|
|
@ -366,6 +366,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
|||
case TH_EDGE:
|
||||
cp = ts->edge;
|
||||
break;
|
||||
case TH_EDGE_WIDTH:
|
||||
cp = &ts->edge_width;
|
||||
break;
|
||||
case TH_EDGE_SELECT:
|
||||
cp = ts->edge_select;
|
||||
break;
|
||||
|
|
|
@ -685,7 +685,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em)
|
|||
|
||||
/* Normals should not be stored in the undo mesh, so recalculate them. The edit
|
||||
* mesh is expected to have valid normals and there is no tracked dirty state. */
|
||||
BLI_assert(BKE_mesh_vertex_normals_are_dirty(&um->me));
|
||||
BLI_assert(BKE_mesh_vert_normals_are_dirty(&um->me));
|
||||
|
||||
/* Calculate face normals and tessellation at once since it's multi-threaded. */
|
||||
BKE_editmesh_looptri_and_normals_calc(em);
|
||||
|
|
|
@ -1453,7 +1453,7 @@ void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), Part
|
|||
nor = vec + 3;
|
||||
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
const MFace *mfaces = (const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE);
|
||||
for (i = 0; i < totface; i++, vec += 6, nor += 6) {
|
||||
const MFace *mface = &mfaces[i];
|
||||
|
|
|
@ -4071,7 +4071,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
|
|||
ps->mat_array[totmat - 1] = nullptr;
|
||||
|
||||
ps->vert_positions_eval = BKE_mesh_vert_positions(ps->me_eval);
|
||||
ps->vert_normals = BKE_mesh_vertex_normals_ensure(ps->me_eval);
|
||||
ps->vert_normals = BKE_mesh_vert_normals_ensure(ps->me_eval);
|
||||
ps->edges_eval = ps->me_eval->edges();
|
||||
ps->polys_eval = ps->me_eval->polys();
|
||||
ps->loops_eval = ps->me_eval->loops();
|
||||
|
|
|
@ -5547,7 +5547,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
|
|||
if (update_flags & SCULPT_UPDATE_COORDS && !ss->shapekey_active) {
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
|
||||
/* When sculpting and changing the positions of a mesh, tag them as changed and update. */
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
/* Update the mesh's bounds eagerly since the PBVH already has that information. */
|
||||
mesh->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) {
|
||||
BKE_pbvh_bounding_box(ob->sculpt->pbvh, r_bounds.min, r_bounds.max);
|
||||
|
|
|
@ -1092,7 +1092,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
|
|||
|
||||
if (tag_update) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
|
||||
BKE_sculptsession_free_deformMats(ss);
|
||||
}
|
||||
|
|
|
@ -1716,7 +1716,7 @@ static void nearest2d_data_init_mesh(const Mesh *mesh,
|
|||
r_nearest2d->get_tri_edges_index = cb_mlooptri_edges_get;
|
||||
|
||||
r_nearest2d->vert_positions = BKE_mesh_vert_positions(mesh);
|
||||
r_nearest2d->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
r_nearest2d->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
r_nearest2d->edge = mesh->edges().data();
|
||||
r_nearest2d->loop = mesh->loops().data();
|
||||
r_nearest2d->looptri = BKE_mesh_runtime_looptri_ensure(mesh);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "ED_uvedit.h" /* Own include. */
|
||||
|
||||
#include "GEO_uv_pack.hh"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
|
@ -435,199 +437,6 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
|
|||
|
||||
/** \} */
|
||||
|
||||
static float pack_islands_scale_margin(const blender::Vector<FaceIsland *> &island_vector,
|
||||
BoxPack *box_array,
|
||||
const float scale,
|
||||
const float margin)
|
||||
{
|
||||
for (const int index : island_vector.index_range()) {
|
||||
FaceIsland *island = island_vector[index];
|
||||
BoxPack *box = &box_array[index];
|
||||
box->index = index;
|
||||
box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin;
|
||||
box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin;
|
||||
}
|
||||
float max_u, max_v;
|
||||
BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v);
|
||||
return max_ff(max_u, max_v);
|
||||
}
|
||||
|
||||
static float pack_islands_margin_fraction(const blender::Vector<FaceIsland *> &island_vector,
|
||||
BoxPack *box_array,
|
||||
const float margin_fraction)
|
||||
{
|
||||
/*
|
||||
* Root finding using a combined search / modified-secant method.
|
||||
* First, use a robust search procedure to bracket the root within a factor of 10.
|
||||
* Then, use a modified-secant method to converge.
|
||||
*
|
||||
* This is a specialized solver using domain knowledge to accelerate convergence. */
|
||||
|
||||
float scale_low = 0.0f;
|
||||
float value_low = 0.0f;
|
||||
float scale_high = 0.0f;
|
||||
float value_high = 0.0f;
|
||||
float scale_last = 0.0f;
|
||||
|
||||
/* Scaling smaller than `min_scale_roundoff` is unlikely to fit and
|
||||
* will destroy information in existing UVs. */
|
||||
float min_scale_roundoff = 1e-5f;
|
||||
|
||||
/* Certain inputs might have poor convergence properties.
|
||||
* Use `max_iteration` to prevent an infinite loop. */
|
||||
int max_iteration = 25;
|
||||
for (int iteration = 0; iteration < max_iteration; iteration++) {
|
||||
float scale = 1.0f;
|
||||
|
||||
if (iteration == 0) {
|
||||
BLI_assert(iteration == 0);
|
||||
BLI_assert(scale == 1.0f);
|
||||
BLI_assert(scale_low == 0.0f);
|
||||
BLI_assert(scale_high == 0.0f);
|
||||
}
|
||||
else if (scale_low == 0.0f) {
|
||||
BLI_assert(scale_high > 0.0f);
|
||||
/* Search mode, shrink layout until we can find a scale that fits. */
|
||||
scale = scale_high * 0.1f;
|
||||
}
|
||||
else if (scale_high == 0.0f) {
|
||||
BLI_assert(scale_low > 0.0f);
|
||||
/* Search mode, grow layout until we can find a scale that doesn't fit. */
|
||||
scale = scale_low * 10.0f;
|
||||
}
|
||||
else {
|
||||
/* Bracket mode, use modified secant method to find root. */
|
||||
BLI_assert(scale_low > 0.0f);
|
||||
BLI_assert(scale_high > 0.0f);
|
||||
BLI_assert(value_low <= 0.0f);
|
||||
BLI_assert(value_high >= 0.0f);
|
||||
if (scale_high < scale_low * 1.0001f) {
|
||||
/* Convergence. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Secant method for area. */
|
||||
scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) /
|
||||
(value_high - value_low);
|
||||
scale = scale * scale;
|
||||
|
||||
if (iteration & 1) {
|
||||
/* Modified binary-search to improve robustness. */
|
||||
scale = sqrtf(scale * sqrtf(scale_low * scale_high));
|
||||
}
|
||||
}
|
||||
|
||||
scale = max_ff(scale, min_scale_roundoff);
|
||||
|
||||
/* Evaluate our `f`. */
|
||||
scale_last = scale;
|
||||
float max_uv = pack_islands_scale_margin(
|
||||
island_vector, box_array, scale_last, margin_fraction);
|
||||
float value = sqrtf(max_uv) - 1.0f;
|
||||
|
||||
if (value <= 0.0f) {
|
||||
scale_low = scale;
|
||||
value_low = value;
|
||||
}
|
||||
else {
|
||||
scale_high = scale;
|
||||
value_high = value;
|
||||
if (scale == min_scale_roundoff) {
|
||||
/* Unable to pack without damaging UVs. */
|
||||
scale_low = scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool flush = true;
|
||||
if (flush) {
|
||||
/* Write back best pack as a side-effect. First get best pack. */
|
||||
if (scale_last != scale_low) {
|
||||
scale_last = scale_low;
|
||||
float max_uv = pack_islands_scale_margin(
|
||||
island_vector, box_array, scale_last, margin_fraction);
|
||||
UNUSED_VARS(max_uv);
|
||||
/* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */
|
||||
}
|
||||
|
||||
/* Then expand FaceIslands by the correct amount. */
|
||||
for (const int index : island_vector.index_range()) {
|
||||
BoxPack *box = &box_array[index];
|
||||
box->x /= scale_last;
|
||||
box->y /= scale_last;
|
||||
FaceIsland *island = island_vector[index];
|
||||
BLI_rctf_pad(
|
||||
&island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last);
|
||||
}
|
||||
}
|
||||
return scale_last;
|
||||
}
|
||||
|
||||
static float calc_margin_from_aabb_length_sum(const blender::Vector<FaceIsland *> &island_vector,
|
||||
const struct UVPackIsland_Params ¶ms)
|
||||
{
|
||||
/* Logic matches behavior from #GEO_uv_parametrizer_pack.
|
||||
* Attempt to give predictable results not dependent on current UV scale by using
|
||||
* `aabb_length_sum` (was "`area`") to multiply the margin by the length (was "area"). */
|
||||
double aabb_length_sum = 0.0f;
|
||||
for (FaceIsland *island : island_vector) {
|
||||
float w = BLI_rctf_size_x(&island->bounds_rect);
|
||||
float h = BLI_rctf_size_y(&island->bounds_rect);
|
||||
aabb_length_sum += sqrtf(w * h);
|
||||
}
|
||||
return params.margin * aabb_length_sum * 0.1f;
|
||||
}
|
||||
|
||||
static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_vector,
|
||||
const struct UVPackIsland_Params ¶ms,
|
||||
float r_scale[2])
|
||||
{
|
||||
BoxPack *box_array = static_cast<BoxPack *>(
|
||||
MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__));
|
||||
|
||||
if (params.margin == 0.0f) {
|
||||
/* Special case for zero margin. Margin_method is ignored as all formulas give same result. */
|
||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, 0.0f);
|
||||
r_scale[0] = 1.0f / max_uv;
|
||||
r_scale[1] = r_scale[0];
|
||||
return box_array;
|
||||
}
|
||||
|
||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) {
|
||||
/* Uses a line search on scale. ~10x slower than other method. */
|
||||
const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin);
|
||||
r_scale[0] = scale;
|
||||
r_scale[1] = scale;
|
||||
/* pack_islands_margin_fraction will pad FaceIslands, return early. */
|
||||
return box_array;
|
||||
}
|
||||
|
||||
float margin = params.margin;
|
||||
switch (params.margin_method) {
|
||||
case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */
|
||||
break; /* Nothing to do. */
|
||||
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
|
||||
margin = calc_margin_from_aabb_length_sum(island_vector, params);
|
||||
break;
|
||||
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
||||
BLI_assert_unreachable(); /* Handled above. */
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin);
|
||||
r_scale[0] = 1.0f / max_uv;
|
||||
r_scale[1] = r_scale[0];
|
||||
|
||||
for (int index = 0; index < island_vector.size(); index++) {
|
||||
FaceIsland *island = island_vector[index];
|
||||
BLI_rctf_pad(&island->bounds_rect, margin, margin);
|
||||
}
|
||||
return box_array;
|
||||
}
|
||||
|
||||
static bool island_has_pins(const Scene *scene,
|
||||
FaceIsland *island,
|
||||
const UVPackIsland_Params *params)
|
||||
|
@ -664,8 +473,8 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
|
|||
Object **objects,
|
||||
const uint objects_len,
|
||||
BMesh **bmesh_override,
|
||||
const struct UVMapUDIM_Params *closest_udim,
|
||||
const struct UVPackIsland_Params *params)
|
||||
const UVMapUDIM_Params *closest_udim,
|
||||
const UVPackIsland_Params *params)
|
||||
{
|
||||
blender::Vector<FaceIsland *> island_vector;
|
||||
|
||||
|
@ -751,7 +560,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
|
|||
}
|
||||
|
||||
float scale[2] = {1.0f, 1.0f};
|
||||
BoxPack *box_array = pack_islands_params(island_vector, *params, scale);
|
||||
blender::Vector<blender::geometry::PackIsland *> pack_island_vector;
|
||||
for (int i = 0; i < island_vector.size(); i++) {
|
||||
FaceIsland *face_island = island_vector[i];
|
||||
blender::geometry::PackIsland *pack_island = new blender::geometry::PackIsland();
|
||||
pack_island->bounds_rect = face_island->bounds_rect;
|
||||
pack_island_vector.append(pack_island);
|
||||
}
|
||||
BoxPack *box_array = pack_islands(pack_island_vector, *params, scale);
|
||||
|
||||
float base_offset[2] = {0.0f, 0.0f};
|
||||
copy_v2_v2(base_offset, params->udim_base_offset);
|
||||
|
@ -818,6 +634,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
|
|||
MEM_freeN(island);
|
||||
}
|
||||
|
||||
for (int i = 0; i < pack_island_vector.size(); i++) {
|
||||
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
||||
pack_island_vector[i] = nullptr;
|
||||
delete pack_island;
|
||||
}
|
||||
|
||||
MEM_freeN(box_array);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "GEO_uv_pack.hh"
|
||||
#include "GEO_uv_parametrizer.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
|
|
@ -30,6 +30,7 @@ set(SRC
|
|||
intern/set_curve_type.cc
|
||||
intern/subdivide_curves.cc
|
||||
intern/trim_curves.cc
|
||||
intern/uv_pack.cc
|
||||
intern/uv_parametrizer.cc
|
||||
|
||||
GEO_add_curves_on_mesh.hh
|
||||
|
@ -47,6 +48,7 @@ set(SRC
|
|||
GEO_set_curve_type.hh
|
||||
GEO_subdivide_curves.hh
|
||||
GEO_trim_curves.hh
|
||||
GEO_uv_pack.hh
|
||||
GEO_uv_parametrizer.h
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_boxpack_2d.h"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "DNA_vec_types.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup geo
|
||||
*/
|
||||
|
||||
/** Workaround to forward-declare C type in C++ header. */
|
||||
extern "C" {
|
||||
|
||||
enum eUVPackIsland_MarginMethod {
|
||||
ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */
|
||||
ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */
|
||||
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
|
||||
};
|
||||
|
||||
/** See also #UnwrapOptions. */
|
||||
struct UVPackIsland_Params {
|
||||
/** Islands can be rotated to improve packing. */
|
||||
bool rotate;
|
||||
/** (In UV Editor) only pack islands which have one or more selected UVs.*/
|
||||
bool only_selected_uvs;
|
||||
/** (In 3D Viewport or UV Editor) only pack islands which have selected faces. */
|
||||
bool only_selected_faces;
|
||||
/** When determining islands, use Seams as boundary edges. */
|
||||
bool use_seams;
|
||||
/** (In 3D Viewport or UV Editor) use aspect ratio from face. */
|
||||
bool correct_aspect;
|
||||
/** Ignore islands which have any pinned UVs. */
|
||||
bool ignore_pinned;
|
||||
/** Treat unselected UVs as if they were pinned. */
|
||||
bool pin_unselected;
|
||||
/** Additional space to add around each island. */
|
||||
float margin;
|
||||
/** Which formula to use when scaling island margin. */
|
||||
eUVPackIsland_MarginMethod margin_method;
|
||||
/** Additional translation for bottom left corner. */
|
||||
float udim_base_offset[2];
|
||||
};
|
||||
}
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
class PackIsland {
|
||||
public:
|
||||
rctf bounds_rect;
|
||||
};
|
||||
|
||||
BoxPack *pack_islands(const Span<PackIsland *> &island_vector,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
float r_scale[2]);
|
||||
|
||||
} // namespace blender::geometry
|
|
@ -0,0 +1,216 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eduv
|
||||
*/
|
||||
|
||||
#include "GEO_uv_pack.hh"
|
||||
|
||||
#include "BLI_boxpack_2d.h"
|
||||
#include "BLI_convexhull_2d.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
static float pack_islands_scale_margin(const Span<PackIsland *> &island_vector,
|
||||
BoxPack *box_array,
|
||||
const float scale,
|
||||
const float margin)
|
||||
{
|
||||
for (const int64_t index : island_vector.index_range()) {
|
||||
PackIsland *island = island_vector[index];
|
||||
BoxPack *box = &box_array[index];
|
||||
box->index = (int)index;
|
||||
box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin;
|
||||
box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin;
|
||||
}
|
||||
float max_u, max_v;
|
||||
BLI_box_pack_2d(box_array, (int)island_vector.size(), &max_u, &max_v);
|
||||
return max_ff(max_u, max_v);
|
||||
}
|
||||
|
||||
static float pack_islands_margin_fraction(const Span<PackIsland *> &island_vector,
|
||||
BoxPack *box_array,
|
||||
const float margin_fraction)
|
||||
{
|
||||
/*
|
||||
* Root finding using a combined search / modified-secant method.
|
||||
* First, use a robust search procedure to bracket the root within a factor of 10.
|
||||
* Then, use a modified-secant method to converge.
|
||||
*
|
||||
* This is a specialized solver using domain knowledge to accelerate convergence. */
|
||||
|
||||
float scale_low = 0.0f;
|
||||
float value_low = 0.0f;
|
||||
float scale_high = 0.0f;
|
||||
float value_high = 0.0f;
|
||||
float scale_last = 0.0f;
|
||||
|
||||
/* Scaling smaller than `min_scale_roundoff` is unlikely to fit and
|
||||
* will destroy information in existing UVs. */
|
||||
float min_scale_roundoff = 1e-5f;
|
||||
|
||||
/* Certain inputs might have poor convergence properties.
|
||||
* Use `max_iteration` to prevent an infinite loop. */
|
||||
int max_iteration = 25;
|
||||
for (int iteration = 0; iteration < max_iteration; iteration++) {
|
||||
float scale = 1.0f;
|
||||
|
||||
if (iteration == 0) {
|
||||
BLI_assert(iteration == 0);
|
||||
BLI_assert(scale == 1.0f);
|
||||
BLI_assert(scale_low == 0.0f);
|
||||
BLI_assert(scale_high == 0.0f);
|
||||
}
|
||||
else if (scale_low == 0.0f) {
|
||||
BLI_assert(scale_high > 0.0f);
|
||||
/* Search mode, shrink layout until we can find a scale that fits. */
|
||||
scale = scale_high * 0.1f;
|
||||
}
|
||||
else if (scale_high == 0.0f) {
|
||||
BLI_assert(scale_low > 0.0f);
|
||||
/* Search mode, grow layout until we can find a scale that doesn't fit. */
|
||||
scale = scale_low * 10.0f;
|
||||
}
|
||||
else {
|
||||
/* Bracket mode, use modified secant method to find root. */
|
||||
BLI_assert(scale_low > 0.0f);
|
||||
BLI_assert(scale_high > 0.0f);
|
||||
BLI_assert(value_low <= 0.0f);
|
||||
BLI_assert(value_high >= 0.0f);
|
||||
if (scale_high < scale_low * 1.0001f) {
|
||||
/* Convergence. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Secant method for area. */
|
||||
scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) /
|
||||
(value_high - value_low);
|
||||
scale = scale * scale;
|
||||
|
||||
if (iteration & 1) {
|
||||
/* Modified binary-search to improve robustness. */
|
||||
scale = sqrtf(scale * sqrtf(scale_low * scale_high));
|
||||
}
|
||||
}
|
||||
|
||||
scale = max_ff(scale, min_scale_roundoff);
|
||||
|
||||
/* Evaluate our `f`. */
|
||||
scale_last = scale;
|
||||
float max_uv = pack_islands_scale_margin(
|
||||
island_vector, box_array, scale_last, margin_fraction);
|
||||
float value = sqrtf(max_uv) - 1.0f;
|
||||
|
||||
if (value <= 0.0f) {
|
||||
scale_low = scale;
|
||||
value_low = value;
|
||||
}
|
||||
else {
|
||||
scale_high = scale;
|
||||
value_high = value;
|
||||
if (scale == min_scale_roundoff) {
|
||||
/* Unable to pack without damaging UVs. */
|
||||
scale_low = scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool flush = true;
|
||||
if (flush) {
|
||||
/* Write back best pack as a side-effect. First get best pack. */
|
||||
if (scale_last != scale_low) {
|
||||
scale_last = scale_low;
|
||||
float max_uv = pack_islands_scale_margin(
|
||||
island_vector, box_array, scale_last, margin_fraction);
|
||||
UNUSED_VARS(max_uv);
|
||||
/* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */
|
||||
}
|
||||
|
||||
/* Then expand FaceIslands by the correct amount. */
|
||||
for (const int64_t index : island_vector.index_range()) {
|
||||
BoxPack *box = &box_array[index];
|
||||
box->x /= scale_last;
|
||||
box->y /= scale_last;
|
||||
PackIsland *island = island_vector[index];
|
||||
BLI_rctf_pad(
|
||||
&island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last);
|
||||
}
|
||||
}
|
||||
return scale_last;
|
||||
}
|
||||
|
||||
static float calc_margin_from_aabb_length_sum(const Span<PackIsland *> &island_vector,
|
||||
const UVPackIsland_Params ¶ms)
|
||||
{
|
||||
/* Logic matches behavior from #GEO_uv_parametrizer_pack.
|
||||
* Attempt to give predictable results not dependent on current UV scale by using
|
||||
* `aabb_length_sum` (was "`area`") to multiply the margin by the length (was "area"). */
|
||||
double aabb_length_sum = 0.0f;
|
||||
for (PackIsland *island : island_vector) {
|
||||
float w = BLI_rctf_size_x(&island->bounds_rect);
|
||||
float h = BLI_rctf_size_y(&island->bounds_rect);
|
||||
aabb_length_sum += sqrtf(w * h);
|
||||
}
|
||||
return params.margin * aabb_length_sum * 0.1f;
|
||||
}
|
||||
|
||||
BoxPack *pack_islands(const Span<PackIsland *> &island_vector,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
float r_scale[2])
|
||||
{
|
||||
BoxPack *box_array = static_cast<BoxPack *>(
|
||||
MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__));
|
||||
|
||||
if (params.margin == 0.0f) {
|
||||
/* Special case for zero margin. Margin_method is ignored as all formulas give same result. */
|
||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, 0.0f);
|
||||
r_scale[0] = 1.0f / max_uv;
|
||||
r_scale[1] = r_scale[0];
|
||||
return box_array;
|
||||
}
|
||||
|
||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) {
|
||||
/* Uses a line search on scale. ~10x slower than other method. */
|
||||
const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin);
|
||||
r_scale[0] = scale;
|
||||
r_scale[1] = scale;
|
||||
/* pack_islands_margin_fraction will pad FaceIslands, return early. */
|
||||
return box_array;
|
||||
}
|
||||
|
||||
float margin = params.margin;
|
||||
switch (params.margin_method) {
|
||||
case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */
|
||||
break; /* Nothing to do. */
|
||||
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
|
||||
margin = calc_margin_from_aabb_length_sum(island_vector, params);
|
||||
break;
|
||||
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
||||
BLI_assert_unreachable(); /* Handled above. */
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin);
|
||||
r_scale[0] = 1.0f / max_uv;
|
||||
r_scale[1] = r_scale[0];
|
||||
|
||||
for (int index = 0; index < island_vector.size(); index++) {
|
||||
PackIsland *island = island_vector[index];
|
||||
BLI_rctf_pad(&island->bounds_rect, margin, margin);
|
||||
}
|
||||
return box_array;
|
||||
}
|
||||
|
||||
} // namespace blender::geometry
|
|
@ -124,7 +124,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
|
|||
&mesh->fdata, CD_MTFACE, mesh->totface);
|
||||
const MFace *mface = (const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE);
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
|
||||
if ((!mtface || !mface) && !uv_warning_shown_) {
|
||||
std::fprintf(stderr,
|
||||
|
@ -249,7 +249,7 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context,
|
|||
MTFace *mtface = (MTFace *)CustomData_get_layer_for_write(
|
||||
&mesh->fdata, CD_MTFACE, mesh->totface);
|
||||
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
|
||||
ParticleSystem *psys = context.particle_system;
|
||||
ParticleSettings *part = psys->part;
|
||||
|
|
|
@ -146,7 +146,7 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
|
|||
mesh_data.ceil_positions != nullptr &&
|
||||
mesh_data.ceil_positions->size() == positions->size()) {
|
||||
read_mverts_interp(vert_positions, positions, mesh_data.ceil_positions, config.weight);
|
||||
BKE_mesh_tag_coords_changed(config.mesh);
|
||||
BKE_mesh_tag_positions_changed(config.mesh);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,15 +161,15 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa
|
|||
|
||||
copy_zup_from_yup(vert_positions[i], pos_in.getValue());
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(&mesh);
|
||||
BKE_mesh_tag_positions_changed(&mesh);
|
||||
|
||||
if (normals) {
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh);
|
||||
float(*vert_normals)[3] = BKE_mesh_vert_normals_for_write(&mesh);
|
||||
for (const int64_t i : IndexRange(normals->size())) {
|
||||
Imath::V3f nor_in = (*normals)[i];
|
||||
copy_zup_from_yup(vert_normals[i], nor_in.getValue());
|
||||
}
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh);
|
||||
BKE_mesh_vert_normals_clear_dirty(&mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -619,7 +619,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
|||
int last_normal_index = -1;
|
||||
|
||||
const Span<float3> positions = me->vert_positions();
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
|
||||
const Span<MPoly> polys = me->polys();
|
||||
const Span<MLoop> loops = me->loops();
|
||||
const float(*lnors)[3] = nullptr;
|
||||
|
@ -633,9 +633,9 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
|||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const MPoly *mpoly = &polys[poly_index];
|
||||
bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
|
||||
bool use_vert_normals = use_custom_normals || mpoly->flag & ME_SMOOTH;
|
||||
|
||||
if (!use_vertex_normals) {
|
||||
if (!use_vert_normals) {
|
||||
/* For flat faces use face normal as vertex normal: */
|
||||
|
||||
float vector[3];
|
||||
|
@ -652,7 +652,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
|||
BCPolygonNormalsIndices poly_indices;
|
||||
for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) {
|
||||
uint loop_idx = mpoly->loopstart + loop_index;
|
||||
if (use_vertex_normals) {
|
||||
if (use_vert_normals) {
|
||||
float normalized[3];
|
||||
|
||||
if (use_custom_normals) {
|
||||
|
|
|
@ -556,10 +556,10 @@ void USDMeshReader::process_normals_vertex_varying(Mesh *mesh)
|
|||
return;
|
||||
}
|
||||
|
||||
MutableSpan vert_normals{(float3 *)BKE_mesh_vertex_normals_for_write(mesh), mesh->totvert};
|
||||
MutableSpan vert_normals{(float3 *)BKE_mesh_vert_normals_for_write(mesh), mesh->totvert};
|
||||
BLI_STATIC_ASSERT(sizeof(normals_[0]) == sizeof(float3), "Expected float3 normals size");
|
||||
vert_normals.copy_from({(float3 *)normals_.data(), int64_t(normals_.size())});
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
BKE_mesh_vert_normals_clear_dirty(mesh);
|
||||
}
|
||||
|
||||
void USDMeshReader::process_normals_face_varying(Mesh *mesh)
|
||||
|
@ -651,7 +651,7 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings,
|
|||
for (int i = 0; i < positions_.size(); i++) {
|
||||
vert_positions[i] = {positions_[i][0], positions_[i][1], positions_[i][2]};
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
|
||||
read_vertex_creases(mesh, motionSampleTime);
|
||||
}
|
||||
|
|
|
@ -440,7 +440,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_
|
|||
}
|
||||
else {
|
||||
/* Compute the loop normals based on the 'smooth' flag. */
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
const float(*face_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
|
||||
for (const int i : polys.index_range()) {
|
||||
const MPoly &poly = polys[i];
|
||||
|
|
|
@ -142,7 +142,7 @@ static void geom_add_vertex_normal(const char *p,
|
|||
* making them ever-so-slightly non unit length. Make sure they are
|
||||
* normalized. */
|
||||
normalize_v3(normal);
|
||||
r_global_vertices.vertex_normals.append(normal);
|
||||
r_global_vertices.vert_normals.append(normal);
|
||||
}
|
||||
|
||||
static void geom_add_uv_vertex(const char *p, const char *end, GlobalVertices &r_global_vertices)
|
||||
|
@ -282,16 +282,16 @@ static void geom_add_polygon(Geometry *geom,
|
|||
/* Ignore corner normal index, if the geometry does not have any normals.
|
||||
* Some obj files out there do have face definitions that refer to normal indices,
|
||||
* without any normals being present (#98782). */
|
||||
if (got_normal && !global_vertices.vertex_normals.is_empty()) {
|
||||
if (got_normal && !global_vertices.vert_normals.is_empty()) {
|
||||
corner.vertex_normal_index += corner.vertex_normal_index < 0 ?
|
||||
global_vertices.vertex_normals.size() :
|
||||
global_vertices.vert_normals.size() :
|
||||
-1;
|
||||
if (corner.vertex_normal_index < 0 ||
|
||||
corner.vertex_normal_index >= global_vertices.vertex_normals.size()) {
|
||||
corner.vertex_normal_index >= global_vertices.vert_normals.size()) {
|
||||
fprintf(stderr,
|
||||
"Invalid normal index %i (valid range [0, %zu)), ignoring face\n",
|
||||
corner.vertex_normal_index,
|
||||
size_t(global_vertices.vertex_normals.size()));
|
||||
size_t(global_vertices.vert_normals.size()));
|
||||
face_valid = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ void MeshFromGeometry::create_materials(Main *bmain,
|
|||
void MeshFromGeometry::create_normals(Mesh *mesh)
|
||||
{
|
||||
/* No normal data: nothing to do. */
|
||||
if (global_vertices_.vertex_normals.is_empty()) {
|
||||
if (global_vertices_.vert_normals.is_empty()) {
|
||||
return;
|
||||
}
|
||||
/* Custom normals can only be stored on face corners. */
|
||||
|
@ -375,7 +375,7 @@ void MeshFromGeometry::create_normals(Mesh *mesh)
|
|||
int n_index = curr_corner.vertex_normal_index;
|
||||
float3 normal(0, 0, 0);
|
||||
if (n_index >= 0) {
|
||||
normal = global_vertices_.vertex_normals[n_index];
|
||||
normal = global_vertices_.vert_normals[n_index];
|
||||
}
|
||||
copy_v3_v3(loop_normals[tot_loop_idx], normal);
|
||||
tot_loop_idx++;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace blender::io::obj {
|
|||
struct GlobalVertices {
|
||||
Vector<float3> vertices;
|
||||
Vector<float2> uv_vertices;
|
||||
Vector<float3> vertex_normals;
|
||||
Vector<float3> vert_normals;
|
||||
|
||||
/**
|
||||
* Vertex colors might not be present in the file at all, or only
|
||||
|
|
|
@ -283,7 +283,7 @@ typedef struct Mesh {
|
|||
* from a vertices surrounding faces, or the normalized position of vertices connected to no
|
||||
* faces.
|
||||
*/
|
||||
blender::Span<blender::float3> vertex_normals() const;
|
||||
blender::Span<blender::float3> vert_normals() const;
|
||||
#endif
|
||||
} Mesh;
|
||||
|
||||
|
|
|
@ -309,10 +309,10 @@ typedef struct ThemeSpace {
|
|||
unsigned char console_output[4], console_input[4], console_info[4], console_error[4];
|
||||
unsigned char console_cursor[4], console_select[4];
|
||||
|
||||
unsigned char vertex_size, outline_width, obcenter_dia, facedot_size;
|
||||
unsigned char vertex_size, edge_width, outline_width, obcenter_dia, facedot_size;
|
||||
unsigned char noodle_curving;
|
||||
unsigned char grid_levels;
|
||||
char _pad5[3];
|
||||
char _pad5[2];
|
||||
float dash_alpha;
|
||||
|
||||
/* Syntax for text-window and nodes. */
|
||||
|
|
|
@ -352,7 +352,7 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
|
|||
static void rna_Mesh_update_positions_tag(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Mesh *mesh = rna_mesh(ptr);
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
rna_Mesh_update_data_legacy_deg_tag_all(bmain, scene, ptr);
|
||||
}
|
||||
|
||||
|
@ -452,7 +452,7 @@ static void rna_MeshVertex_co_set(PointerRNA *ptr, const float *value)
|
|||
static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
|
||||
{
|
||||
Mesh *mesh = rna_mesh(ptr);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
const int index = rna_MeshVertex_index_get(ptr);
|
||||
copy_v3_v3(value, vert_normals[index]);
|
||||
}
|
||||
|
@ -1994,7 +1994,7 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
|
|||
static void rna_Mesh_vertex_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
const Mesh *mesh = rna_mesh(ptr);
|
||||
const float(*normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
rna_iterator_array_begin(iter, (void *)normals, sizeof(float[3]), mesh->totvert, false, NULL);
|
||||
}
|
||||
|
||||
|
@ -2013,7 +2013,7 @@ int rna_Mesh_vertex_normals_lookup_int(PointerRNA *ptr, int index, PointerRNA *r
|
|||
/* Casting away const is okay because this RNA type doesn't allow changing the value. */
|
||||
r_ptr->owner_id = (ID *)&mesh->id;
|
||||
r_ptr->type = &RNA_MeshNormalValue;
|
||||
r_ptr->data = (float *)BKE_mesh_vertex_normals_ensure(mesh)[index];
|
||||
r_ptr->data = (float *)BKE_mesh_vert_normals_ensure(mesh)[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2205,6 +2205,11 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
|
|||
prop, "Wire Edit", "Color for wireframe when in edit mode, but edge selection is active");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "edge_width", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_range(prop, 1, 5);
|
||||
RNA_def_property_ui_text(prop, "Edge Width", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
/* Grease Pencil */
|
||||
|
||||
rna_def_userdef_theme_spaces_gpencil(srna);
|
||||
|
@ -3049,6 +3054,11 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Wire Edit", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "edge_width", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_range(prop, 1, 5);
|
||||
RNA_def_property_ui_text(prop, "Edge Width", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "edge_select", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Edge Select", "");
|
||||
|
|
|
@ -300,7 +300,7 @@ static void mesh_merge_transform(Mesh *result,
|
|||
|
||||
/* We have to correct normals too, if we do not tag them as dirty later! */
|
||||
if (!recalc_normals_later) {
|
||||
float(*dst_vert_normals)[3] = BKE_mesh_vertex_normals_for_write(result);
|
||||
float(*dst_vert_normals)[3] = BKE_mesh_vert_normals_for_write(result);
|
||||
for (i = 0; i < cap_nverts; i++) {
|
||||
mul_mat3_m4_v3(cap_offset, dst_vert_normals[cap_verts_index + i]);
|
||||
normalize_v3(dst_vert_normals[cap_verts_index + i]);
|
||||
|
@ -378,7 +378,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
|||
int tot_doubles;
|
||||
|
||||
const bool use_merge = (amd->flags & MOD_ARR_MERGE) != 0;
|
||||
const bool use_recalc_normals = BKE_mesh_vertex_normals_are_dirty(mesh) || use_merge;
|
||||
const bool use_recalc_normals = BKE_mesh_vert_normals_are_dirty(mesh) || use_merge;
|
||||
const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob != nullptr);
|
||||
|
||||
int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
|
||||
|
@ -565,9 +565,9 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
|
|||
const float(*src_vert_normals)[3] = nullptr;
|
||||
float(*dst_vert_normals)[3] = nullptr;
|
||||
if (!use_recalc_normals) {
|
||||
src_vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
dst_vert_normals = BKE_mesh_vertex_normals_for_write(result);
|
||||
BKE_mesh_vertex_normals_clear_dirty(result);
|
||||
src_vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
dst_vert_normals = BKE_mesh_vert_normals_for_write(result);
|
||||
BKE_mesh_vert_normals_clear_dirty(result);
|
||||
}
|
||||
|
||||
for (c = 1; c < count; c++) {
|
||||
|
|
|
@ -148,7 +148,7 @@ static Mesh *get_quick_mesh(
|
|||
mul_m4_v3(omat, positions[i]);
|
||||
}
|
||||
|
||||
BKE_mesh_tag_coords_changed(result);
|
||||
BKE_mesh_tag_positions_changed(result);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -336,7 +336,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
|
|||
data.vertexCos = vertexCos;
|
||||
copy_m4_m4(data.local_mat, local_mat);
|
||||
if (direction == MOD_DISP_DIR_NOR) {
|
||||
data.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
data.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
}
|
||||
data.vert_clnors = vert_clnors;
|
||||
if (tex_target != nullptr) {
|
||||
|
|
|
@ -739,13 +739,8 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
|
|||
totfsplit += add_faces[*fs];
|
||||
}
|
||||
|
||||
split_m = BKE_mesh_new_nomain_from_template(mesh, totesplit, 0, 0, 0);
|
||||
split_m->totface = totface + totfsplit;
|
||||
CustomData_copy(
|
||||
&split_m->fdata, &mesh->fdata, CD_MASK_EVERYTHING.fmask, CD_SET_DEFAULT, split_m->totface);
|
||||
if (!CustomData_get_layer(&split_m->fdata, CD_MFACE)) {
|
||||
CustomData_add_layer(&split_m->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, split_m->totface);
|
||||
}
|
||||
split_m = BKE_mesh_new_nomain_from_template_ex(
|
||||
mesh, totesplit, 0, totface + totfsplit, 0, 0, CD_MASK_EVERYTHING);
|
||||
|
||||
layers_num = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE);
|
||||
|
||||
|
@ -992,13 +987,8 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
|
|||
BLI_edgehashIterator_free(ehi);
|
||||
|
||||
/* the final duplicated vertices */
|
||||
explode = BKE_mesh_new_nomain_from_template(mesh, totdup, 0, 0, 0);
|
||||
explode->totface = totface - delface;
|
||||
CustomData_copy(
|
||||
&explode->fdata, &mesh->fdata, CD_MASK_EVERYTHING.fmask, CD_SET_DEFAULT, explode->totface);
|
||||
if (!CustomData_get_layer(&explode->fdata, CD_MFACE)) {
|
||||
CustomData_add_layer(&explode->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, explode->totface);
|
||||
}
|
||||
explode = BKE_mesh_new_nomain_from_template_ex(
|
||||
mesh, totdup, 0, totface - delface, 0, 0, CD_MASK_EVERYTHING);
|
||||
|
||||
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer_named_for_write(
|
||||
&explode->fdata, CD_MTFACE, emd->uvname, explode->totface));
|
||||
|
|
|
@ -338,7 +338,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
|
|||
}
|
||||
|
||||
BKE_mesh_normals_loop_custom_set(vert_positions,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
BKE_mesh_vert_normals_ensure(mesh),
|
||||
verts_num,
|
||||
medge,
|
||||
edges_num,
|
||||
|
@ -460,7 +460,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
|
|||
}
|
||||
|
||||
BKE_mesh_normals_loop_custom_set(positions,
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
BKE_mesh_vert_normals_ensure(mesh),
|
||||
verts_num,
|
||||
medge,
|
||||
edges_num,
|
||||
|
@ -552,7 +552,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
|
|||
|
||||
CustomData *ldata = &result->ldata;
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(result);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(result);
|
||||
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(result);
|
||||
|
||||
bke::MutableAttributeAccessor attributes = result->attributes_for_write();
|
||||
|
|
|
@ -466,7 +466,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
|
|||
}
|
||||
}
|
||||
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
|
||||
if (allocated_ocean) {
|
||||
BKE_ocean_free(omd->ocean);
|
||||
|
|
|
@ -131,7 +131,7 @@ static void mesh_calc_hq_normal(Mesh *mesh,
|
|||
}
|
||||
|
||||
/* normalize vertex normals and assign */
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
for (int i = 0; i < verts_num; i++) {
|
||||
if (normalize_v3(r_vert_nors[i]) == 0.0f) {
|
||||
copy_v3_v3(r_vert_nors[i], vert_normals[i]);
|
||||
|
@ -205,7 +205,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
|
|||
/* array size is doubled in case of using a shell */
|
||||
const uint stride = do_shell ? 2 : 1;
|
||||
|
||||
const float(*mesh_vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*mesh_vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
|
||||
MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index);
|
||||
|
||||
|
@ -972,7 +972,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
|
|||
}
|
||||
|
||||
/* must recalculate normals with vgroups since they can displace unevenly #26888. */
|
||||
if (BKE_mesh_vertex_normals_are_dirty(mesh) || do_rim || dvert) {
|
||||
if (BKE_mesh_vert_normals_are_dirty(mesh) || do_rim || dvert) {
|
||||
BKE_mesh_normals_tag_dirty(result);
|
||||
}
|
||||
else if (do_shell) {
|
||||
|
@ -1022,7 +1022,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
|
|||
#ifdef SOLIDIFY_SIDE_NORMALS
|
||||
/* NOTE(@sybren): due to the code setting normals dirty a few lines above,
|
||||
* do_side_normals is always false. */
|
||||
const bool do_side_normals = !BKE_mesh_vertex_normals_are_dirty(result);
|
||||
const bool do_side_normals = !BKE_mesh_vert_normals_are_dirty(result);
|
||||
/* annoying to allocate these since we only need the edge verts, */
|
||||
float(*edge_vert_nos)[3] = do_side_normals ? static_cast<float(*)[3]>(MEM_calloc_arrayN(
|
||||
verts_num, sizeof(float[3]), __func__)) :
|
||||
|
|
|
@ -146,7 +146,7 @@ static void waveModifier_do(WaveModifierData *md,
|
|||
|
||||
const float(*vert_normals)[3] = nullptr;
|
||||
if ((wmd->flag & MOD_WAVE_NORM) && (mesh != nullptr)) {
|
||||
vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
if (wmd->objectcenter != nullptr) {
|
||||
|
|
|
@ -610,7 +610,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
|||
wn_data.verts_num = verts_num;
|
||||
|
||||
wn_data.vert_positions = positions;
|
||||
wn_data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
|
||||
wn_data.vert_normals = BKE_mesh_vert_normals_ensure(result);
|
||||
wn_data.edges = edges;
|
||||
wn_data.sharp_edges = sharp_edges.span.data();
|
||||
|
||||
|
|
|
@ -1014,6 +1014,9 @@ static void do_mesh_separation(GeometrySet &geometry_set,
|
|||
selected_loops_num,
|
||||
selected_poly_indices,
|
||||
mesh_in);
|
||||
|
||||
/* Positions are not changed by the operation, so the bounds are the same. */
|
||||
mesh_out->runtime->bounds_cache = mesh_in.runtime->bounds_cache;
|
||||
break;
|
||||
}
|
||||
case GEO_NODE_DELETE_GEOMETRY_MODE_ONLY_FACE: {
|
||||
|
@ -1070,6 +1073,9 @@ static void do_mesh_separation(GeometrySet &geometry_set,
|
|||
selected_loops_num,
|
||||
selected_poly_indices,
|
||||
mesh_in);
|
||||
|
||||
/* Positions are not changed by the operation, so the bounds are the same. */
|
||||
mesh_out->runtime->bounds_cache = mesh_in.runtime->bounds_cache;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -674,13 +674,13 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh,
|
|||
}
|
||||
});
|
||||
|
||||
Vector<float3> vertex_positions(src_mesh.totpoly);
|
||||
for (const int i : IndexRange(src_mesh.totpoly)) {
|
||||
Vector<float3> vert_positions(src_mesh.totpoly);
|
||||
for (const int i : src_polys.index_range()) {
|
||||
const MPoly &poly = src_polys[i];
|
||||
BKE_mesh_calc_poly_center(&poly,
|
||||
&src_loops[poly.loopstart],
|
||||
reinterpret_cast<const float(*)[3]>(src_positions.data()),
|
||||
vertex_positions[i]);
|
||||
vert_positions[i]);
|
||||
}
|
||||
|
||||
Array<int> boundary_edge_midpoint_index;
|
||||
|
@ -692,8 +692,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh,
|
|||
if (edge_types[i] == EdgeType::Boundary) {
|
||||
const MEdge &edge = src_edges[i];
|
||||
const float3 mid = math::midpoint(src_positions[edge.v1], src_positions[edge.v2]);
|
||||
boundary_edge_midpoint_index[i] = vertex_positions.size();
|
||||
vertex_positions.append(mid);
|
||||
boundary_edge_midpoint_index[i] = vert_positions.size();
|
||||
vert_positions.append(mid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -837,12 +837,12 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh,
|
|||
else {
|
||||
loop_edges.append(old_to_new_edges_map[edge1]);
|
||||
}
|
||||
loop_indices.append(vertex_positions.size());
|
||||
loop_indices.append(vert_positions.size());
|
||||
/* This is sort of arbitrary, but interpolating would be a lot harder to do. */
|
||||
new_to_old_face_corners_map.append(sorted_corners.first());
|
||||
boundary_vertex_to_relevant_face_map.append(
|
||||
std::pair(loop_indices.last(), last_face_center));
|
||||
vertex_positions.append(src_positions[i]);
|
||||
vert_positions.append(src_positions[i]);
|
||||
const int boundary_vertex = loop_indices.last();
|
||||
add_edge(src_edges,
|
||||
edge1,
|
||||
|
@ -886,7 +886,7 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh,
|
|||
}
|
||||
}
|
||||
Mesh *mesh_out = BKE_mesh_new_nomain(
|
||||
vertex_positions.size(), new_edges.size(), loops.size(), loop_lengths.size());
|
||||
vert_positions.size(), new_edges.size(), loops.size(), loop_lengths.size());
|
||||
|
||||
transfer_attributes(vertex_types,
|
||||
keep_boundaries,
|
||||
|
@ -897,7 +897,7 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh,
|
|||
src_mesh.attributes(),
|
||||
mesh_out->attributes_for_write());
|
||||
|
||||
mesh_out->vert_positions_for_write().copy_from(vertex_positions);
|
||||
mesh_out->vert_positions_for_write().copy_from(vert_positions);
|
||||
MutableSpan<MEdge> dst_edges = mesh_out->edges_for_write();
|
||||
MutableSpan<MPoly> dst_polys = mesh_out->polys_for_write();
|
||||
MutableSpan<MLoop> dst_loops = mesh_out->loops_for_write();
|
||||
|
|
|
@ -319,10 +319,10 @@ static Mesh *create_uv_sphere_mesh(const float radius,
|
|||
threading::parallel_invoke(
|
||||
1024 < segments * rings,
|
||||
[&]() {
|
||||
MutableSpan vert_normals{
|
||||
reinterpret_cast<float3 *>(BKE_mesh_vertex_normals_for_write(mesh)), mesh->totvert};
|
||||
MutableSpan vert_normals{reinterpret_cast<float3 *>(BKE_mesh_vert_normals_for_write(mesh)),
|
||||
mesh->totvert};
|
||||
calculate_sphere_vertex_data(positions, vert_normals, radius, segments, rings);
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
BKE_mesh_vert_normals_clear_dirty(mesh);
|
||||
},
|
||||
[&]() { calculate_sphere_edge_indices(edges, segments, rings); },
|
||||
[&]() { calculate_sphere_faces(polys, segments); },
|
||||
|
|
|
@ -188,7 +188,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh,
|
|||
}
|
||||
});
|
||||
|
||||
BKE_mesh_tag_coords_changed(&mesh);
|
||||
BKE_mesh_tag_positions_changed(&mesh);
|
||||
}
|
||||
|
||||
static void scale_vertex_islands_on_axis(Mesh &mesh,
|
||||
|
@ -234,7 +234,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh,
|
|||
}
|
||||
});
|
||||
|
||||
BKE_mesh_tag_coords_changed(&mesh);
|
||||
BKE_mesh_tag_positions_changed(&mesh);
|
||||
}
|
||||
|
||||
static Vector<ElementIsland> prepare_face_islands(const Mesh &mesh, const IndexMask face_selection)
|
||||
|
|
|
@ -58,14 +58,14 @@ static void translate_mesh(Mesh &mesh, const float3 translation)
|
|||
{
|
||||
if (!math::is_zero(translation)) {
|
||||
translate_positions(mesh.vert_positions_for_write(), translation);
|
||||
BKE_mesh_tag_coords_changed_uniformly(&mesh);
|
||||
BKE_mesh_tag_positions_changed_uniformly(&mesh);
|
||||
}
|
||||
}
|
||||
|
||||
static void transform_mesh(Mesh &mesh, const float4x4 &transform)
|
||||
{
|
||||
transform_positions(mesh.vert_positions_for_write(), transform);
|
||||
BKE_mesh_tag_coords_changed(&mesh);
|
||||
BKE_mesh_tag_positions_changed(&mesh);
|
||||
}
|
||||
|
||||
static void translate_pointcloud(PointCloud &pointcloud, const float3 translation)
|
||||
|
|
|
@ -59,6 +59,10 @@ static Mesh *triangulate_mesh_selection(const Mesh &mesh,
|
|||
BM_mesh_triangulate(bm, quad_method, ngon_method, min_vertices, true, nullptr, nullptr, nullptr);
|
||||
Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, &mesh);
|
||||
BM_mesh_free(bm);
|
||||
|
||||
/* Positions are not changed by the triangulation operation, so the bounds are the same. */
|
||||
result->runtime->bounds_cache = mesh.runtime->bounds_cache;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -500,7 +500,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
|
|||
CustomData_get_layer(&me_eval->ldata, CD_NORMAL));
|
||||
}
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
|
||||
for (i = 0; i < tottri; i++) {
|
||||
const MLoopTri *lt = &looptri[i];
|
||||
const MPoly *mp = &polys[lt->poly];
|
||||
|
|
|
@ -491,7 +491,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
|
|||
temp_mesh->edges_for_write().copy_from({dm->getEdgeArray(dm), temp_mesh->totedge});
|
||||
temp_mesh->polys_for_write().copy_from({dm->getPolyArray(dm), temp_mesh->totpoly});
|
||||
temp_mesh->loops_for_write().copy_from({dm->getLoopArray(dm), temp_mesh->totloop});
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(temp_mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(temp_mesh);
|
||||
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(temp_mesh);
|
||||
|
||||
if (require_tangent) {
|
||||
|
|
|
@ -353,7 +353,7 @@ static void pointdensity_cache_vertex_weight(PointDensity *pd,
|
|||
static void pointdensity_cache_vertex_normal(Mesh *mesh, float *data_color)
|
||||
{
|
||||
BLI_assert(data_color);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
|
||||
memcpy(data_color, vert_normals, sizeof(float[3]) * mesh->totvert);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue