Compare commits
10 Commits
tmp-volume
...
refactor-m
Author | SHA1 | Date | |
---|---|---|---|
55e1ef2c23 | |||
26cc225ed8 | |||
3fe03c01ac | |||
cf9f495283 | |||
30502bddc0 | |||
d6c4ef7586 | |||
ba7052caa9 | |||
a15351c338 | |||
80bd960d91 | |||
172a976273 |
@@ -372,6 +372,8 @@ const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
|
||||
*/
|
||||
const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
const float (*BKE_mesh_corner_normals_ensure(const struct Mesh *mesh))[3];
|
||||
|
||||
/**
|
||||
* Tag mesh vertex and face normals to be recalculated when/if they are needed later.
|
||||
*
|
||||
@@ -418,6 +420,8 @@ void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
|
||||
*/
|
||||
void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh);
|
||||
|
||||
void BKE_mesh_corner_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.
|
||||
@@ -430,6 +434,8 @@ bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh);
|
||||
*/
|
||||
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
bool BKE_mesh_corner_normals_are_dirty(const struct Mesh *mesh);
|
||||
|
||||
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
|
||||
const struct MLoop *loopstart,
|
||||
const struct MVert *mvarray,
|
||||
@@ -668,18 +674,6 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts,
|
||||
*/
|
||||
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
|
||||
|
||||
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
|
||||
/**
|
||||
* Compute 'split' (aka loop, or per face corner's) normals.
|
||||
*
|
||||
* \param r_lnors_spacearr: Allows to get computed loop normal space array.
|
||||
* That data, among other things, contains 'smooth fan' info, useful e.g.
|
||||
* to split geometry along sharp edges.
|
||||
*/
|
||||
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
|
||||
struct MLoopNorSpaceArray *r_lnors_spacearr,
|
||||
float (*r_corner_normals)[3]);
|
||||
|
||||
/**
|
||||
* Higher level functions hiding most of the code needed around call to
|
||||
* #BKE_mesh_normals_loop_custom_set().
|
||||
|
@@ -157,8 +157,10 @@ struct MeshRuntime {
|
||||
*/
|
||||
bool vert_normals_dirty = true;
|
||||
bool poly_normals_dirty = true;
|
||||
bool corner_normals_dirty = false;
|
||||
float (*vert_normals)[3] = nullptr;
|
||||
float (*poly_normals)[3] = nullptr;
|
||||
float (*corner_normals)[3] = nullptr;
|
||||
|
||||
/**
|
||||
* A cache of data about the loose edges. Can be shared with other data-blocks with unchanged
|
||||
|
@@ -547,7 +547,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
/* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case
|
||||
* of deferred CPU subdivision, this will be computed when the wrapper is generated. */
|
||||
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
|
||||
BKE_mesh_calc_normals_split(mesh_final);
|
||||
BKE_mesh_corner_normals_ensure(mesh_final);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -559,13 +559,6 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
||||
* which deals with drawing differently. */
|
||||
BKE_mesh_ensure_normals_for_display(mesh_final);
|
||||
}
|
||||
|
||||
/* Some modifiers, like data-transfer, may generate those data as temp layer,
|
||||
* we do not want to keep them, as they are used by display code when available
|
||||
* (i.e. even if auto-smooth is disabled). */
|
||||
if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
|
||||
CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1215,18 +1208,12 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
|
||||
/* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the
|
||||
* wrapper is generated. */
|
||||
if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
|
||||
BKE_mesh_calc_normals_split(mesh_final);
|
||||
BKE_mesh_corner_normals_ensure(mesh_final);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Same as mesh_calc_modifiers. If using loop normals, poly nors have already been computed. */
|
||||
BKE_mesh_ensure_normals_for_display(mesh_final);
|
||||
|
||||
/* Some modifiers, like data-transfer, may generate those data, we do not want to keep them,
|
||||
* as they are used by display code when available (i.e. even if autosmooth is disabled). */
|
||||
if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
|
||||
CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1564,20 +1564,6 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
|
||||
}
|
||||
}
|
||||
|
||||
/* don't update normals, caller can do this explicitly.
|
||||
* We do update loop normals though, those may not be auto-generated
|
||||
* (see e.g. STL import script)! */
|
||||
float(*lnors)[3] = (float(*)[3])CustomData_duplicate_referenced_layer(
|
||||
&me->ldata, CD_NORMAL, me->totloop);
|
||||
if (lnors) {
|
||||
float m3[3][3];
|
||||
|
||||
copy_m3_m4(m3, mat);
|
||||
normalize_m3(m3);
|
||||
for (int i = 0; i < me->totloop; i++, lnors++) {
|
||||
mul_m3_v3(m3, *lnors);
|
||||
}
|
||||
}
|
||||
BKE_mesh_tag_coords_changed(me);
|
||||
}
|
||||
|
||||
@@ -1777,65 +1763,6 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
|
||||
BKE_mesh_tag_coords_changed(mesh);
|
||||
}
|
||||
|
||||
static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
|
||||
{
|
||||
float(*r_loopnors)[3];
|
||||
if (CustomData_has_layer(&mesh.ldata, CD_NORMAL)) {
|
||||
r_loopnors = (float(*)[3])CustomData_get_layer(&mesh.ldata, CD_NORMAL);
|
||||
memset(r_loopnors, 0, sizeof(float[3]) * mesh.totloop);
|
||||
}
|
||||
else {
|
||||
r_loopnors = (float(*)[3])CustomData_add_layer(
|
||||
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, mesh.totloop);
|
||||
CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
return r_loopnors;
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
||||
MLoopNorSpaceArray *r_lnors_spacearr,
|
||||
float (*r_corner_normals)[3])
|
||||
{
|
||||
short(*clnors)[2] = nullptr;
|
||||
|
||||
/* Note that we enforce computing clnors when the clnor space array is requested by caller here.
|
||||
* However, we obviously only use the auto-smooth angle threshold
|
||||
* only in case auto-smooth is enabled. */
|
||||
const bool use_split_normals = (r_lnors_spacearr != nullptr) ||
|
||||
((mesh->flag & ME_AUTOSMOOTH) != 0);
|
||||
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
|
||||
|
||||
/* may be nullptr */
|
||||
clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
|
||||
const Span<MVert> verts = mesh->verts();
|
||||
const Span<MEdge> edges = mesh->edges();
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
const Span<MLoop> loops = mesh->loops();
|
||||
|
||||
BKE_mesh_normals_loop_split(verts.data(),
|
||||
BKE_mesh_vertex_normals_ensure(mesh),
|
||||
verts.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
loops.data(),
|
||||
r_corner_normals,
|
||||
loops.size(),
|
||||
polys.data(),
|
||||
BKE_mesh_poly_normals_ensure(mesh),
|
||||
polys.size(),
|
||||
use_split_normals,
|
||||
split_angle,
|
||||
nullptr,
|
||||
r_lnors_spacearr,
|
||||
clnors);
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_normals_split(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh));
|
||||
}
|
||||
|
||||
/* **** Depsgraph evaluation **** */
|
||||
|
||||
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
|
||||
|
@@ -164,8 +164,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
||||
|
||||
/* XXX: investigate using EditMesh data. */
|
||||
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
|
||||
BKE_mesh_corner_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
|
||||
int f_idx;
|
||||
@@ -186,8 +185,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
||||
}
|
||||
else {
|
||||
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
|
||||
BKE_mesh_corner_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
|
||||
const MVert *mv = BKE_mesh_verts(mesh);
|
||||
|
@@ -101,6 +101,7 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
mesh->runtime->corner_normals_dirty = true;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
|
||||
@@ -139,6 +140,18 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
|
||||
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
|
||||
}
|
||||
|
||||
void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->corner_normals_dirty = false;
|
||||
BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0);
|
||||
}
|
||||
|
||||
void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime->corner_normals_dirty = false;
|
||||
BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0);
|
||||
}
|
||||
|
||||
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime->vert_normals_dirty;
|
||||
@@ -499,6 +512,65 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
||||
return poly_normals;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_corner_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totloop == 0);
|
||||
return mesh->runtime->corner_normals;
|
||||
}
|
||||
|
||||
if (mesh->totpoly == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
|
||||
const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
|
||||
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_corner_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime->corner_normals != nullptr);
|
||||
return mesh->runtime->corner_normals;
|
||||
}
|
||||
|
||||
float(*corner_normals)[3];
|
||||
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
const Span<MVert> verts = mesh_mutable.verts();
|
||||
const Span<MEdge> edges = mesh_mutable.edges();
|
||||
const Span<MPoly> polys = mesh_mutable.polys();
|
||||
const Span<MLoop> loops = mesh_mutable.loops();
|
||||
|
||||
if (mesh_mutable.runtime->corner_normals == nullptr) {
|
||||
mesh_mutable.runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
mesh_mutable.totloop, sizeof(float[3]), __func__);
|
||||
}
|
||||
|
||||
const short(*custom_normals)[2] = (const short(*)[2])CustomData_get_layer(&mesh->ldata,
|
||||
CD_CUSTOMLOOPNORMAL);
|
||||
|
||||
BKE_mesh_normals_loop_split(verts.data(),
|
||||
vert_normals,
|
||||
verts.size(),
|
||||
edges.data(),
|
||||
edges.size(),
|
||||
loops.data(),
|
||||
corner_normals,
|
||||
loops.size(),
|
||||
polys.data(),
|
||||
poly_normals,
|
||||
polys.size(),
|
||||
true,
|
||||
mesh->smoothresh,
|
||||
nullptr,
|
||||
custom_normals,
|
||||
nullptr);
|
||||
|
||||
BKE_mesh_corner_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
}
|
||||
|
||||
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
|
@@ -1291,7 +1291,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
const float(*poly_nors_src)[3] = nullptr;
|
||||
const float(*loop_nors_src)[3] = nullptr;
|
||||
const float(*poly_nors_dst)[3] = nullptr;
|
||||
float(*loop_nors_dst)[3] = nullptr;
|
||||
const float(*loop_nors_dst)[3] = nullptr;
|
||||
|
||||
float(*poly_cents_src)[3] = nullptr;
|
||||
|
||||
@@ -1355,45 +1355,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst);
|
||||
}
|
||||
if (need_lnors_dst) {
|
||||
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
|
||||
CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL));
|
||||
|
||||
/* Cache loop normals into a temporary custom data layer. */
|
||||
loop_nors_dst = static_cast<float(*)[3]>(CustomData_get_layer(ldata_dst, CD_NORMAL));
|
||||
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
|
||||
if (!loop_nors_dst) {
|
||||
loop_nors_dst = static_cast<float(*)[3]>(
|
||||
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, numloops_dst));
|
||||
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
BKE_mesh_normals_loop_split(verts_dst,
|
||||
BKE_mesh_vertex_normals_ensure(mesh_dst),
|
||||
numverts_dst,
|
||||
edges_dst,
|
||||
numedges_dst,
|
||||
loops_dst,
|
||||
loop_nors_dst,
|
||||
numloops_dst,
|
||||
polys_dst,
|
||||
poly_nors_dst,
|
||||
numpolys_dst,
|
||||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
nullptr,
|
||||
nullptr,
|
||||
custom_nors_dst);
|
||||
}
|
||||
loop_nors_dst = BKE_mesh_corner_normals_ensure(mesh_dst);
|
||||
}
|
||||
if (need_pnors_src || need_lnors_src) {
|
||||
if (need_pnors_src) {
|
||||
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
|
||||
}
|
||||
if (need_lnors_src) {
|
||||
loop_nors_src = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&me_src->ldata, CD_NORMAL));
|
||||
BLI_assert(loop_nors_src != nullptr);
|
||||
}
|
||||
if (need_pnors_src) {
|
||||
poly_nors_src = BKE_mesh_poly_normals_ensure(me_src);
|
||||
}
|
||||
if (need_lnors_src) {
|
||||
loop_nors_src = BKE_mesh_corner_normals_ensure(me_src);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -133,19 +133,11 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
|
||||
return;
|
||||
}
|
||||
|
||||
const float(*loopnors)[3] = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
if (!loopnors) {
|
||||
BKE_report(
|
||||
reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_verts(mesh),
|
||||
mesh->totvert,
|
||||
BKE_mesh_loops(mesh),
|
||||
r_looptangents,
|
||||
loopnors,
|
||||
BKE_mesh_corner_normals_ensure(mesh),
|
||||
loopuvs,
|
||||
mesh->totloop,
|
||||
BKE_mesh_polys(mesh),
|
||||
@@ -585,7 +577,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
||||
tangent_names_len,
|
||||
BKE_mesh_vertex_normals_ensure(me_eval),
|
||||
BKE_mesh_poly_normals_ensure(me_eval),
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
|
||||
BKE_mesh_corner_normals_ensure(me_eval),
|
||||
/* may be nullptr */
|
||||
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->vdata, CD_ORCO)),
|
||||
/* result */
|
||||
|
@@ -331,22 +331,14 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
|
||||
if (use_clnors) {
|
||||
/* If custom normals are present and the option is turned on calculate the split
|
||||
* normals and clear flag so the normals get interpolated to the result mesh. */
|
||||
BKE_mesh_calc_normals_split(me);
|
||||
CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
|
||||
Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me);
|
||||
|
||||
if (use_clnors) {
|
||||
float(*lnors)[3] = static_cast<float(*)[3]>(
|
||||
CustomData_get_layer(&subdiv_mesh->ldata, CD_NORMAL));
|
||||
BLI_assert(lnors != nullptr);
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh);
|
||||
BKE_mesh_set_custom_normals(subdiv_mesh, lnors);
|
||||
CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
else if (runtime_data->calc_loop_normals) {
|
||||
BKE_mesh_calc_normals_split(subdiv_mesh);
|
||||
}
|
||||
|
||||
if (subdiv != runtime_data->subdiv) {
|
||||
|
@@ -136,7 +136,7 @@ bool BKE_shrinkwrap_init_tree(
|
||||
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
|
||||
data->pnors = BKE_mesh_poly_normals_ensure(mesh);
|
||||
if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
|
||||
data->clnors = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
data->clnors = BKE_mesh_corner_normals_ensure(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -364,26 +364,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me);
|
||||
}
|
||||
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
|
||||
mr->loop_normals = static_cast<float(*)[3]>(
|
||||
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
|
||||
short(*clnors)[2] = static_cast<short(*)[2]>(
|
||||
CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL));
|
||||
BKE_mesh_normals_loop_split(mr->mvert,
|
||||
mr->vert_normals,
|
||||
mr->vert_len,
|
||||
mr->medge,
|
||||
mr->edge_len,
|
||||
mr->mloop,
|
||||
mr->loop_normals,
|
||||
mr->loop_len,
|
||||
mr->mpoly,
|
||||
mr->poly_normals,
|
||||
mr->poly_len,
|
||||
is_auto_smooth,
|
||||
split_angle,
|
||||
nullptr,
|
||||
nullptr,
|
||||
clnors);
|
||||
mr->loop_normals = BKE_mesh_corner_normals_ensure(mr->me);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -403,8 +384,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
poly_normals = mr->bm_poly_normals;
|
||||
}
|
||||
|
||||
mr->loop_normals = static_cast<float(*)[3]>(
|
||||
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
|
||||
mr->bm_loop_normals = static_cast<float(*)[3]>(
|
||||
MEM_mallocN(sizeof(*mr->bm_loop_normals) * mr->loop_len, __func__));
|
||||
const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
BM_loops_calc_normal_vcos(mr->bm,
|
||||
vert_coords,
|
||||
@@ -412,11 +393,12 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
||||
poly_normals,
|
||||
is_auto_smooth,
|
||||
split_angle,
|
||||
mr->loop_normals,
|
||||
mr->bm_loop_normals,
|
||||
nullptr,
|
||||
nullptr,
|
||||
clnors_offset,
|
||||
false);
|
||||
mr->loop_normals = mr->bm_loop_normals;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -601,7 +583,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
||||
|
||||
void mesh_render_data_free(MeshRenderData *mr)
|
||||
{
|
||||
MEM_SAFE_FREE(mr->loop_normals);
|
||||
MEM_SAFE_FREE(mr->bm_loop_normals);
|
||||
|
||||
/* Loose geometry are owned by #MeshBufferCache. */
|
||||
mr->ledges = nullptr;
|
||||
|
@@ -91,7 +91,8 @@ struct MeshRenderData {
|
||||
const bool *select_vert;
|
||||
const bool *select_edge;
|
||||
const bool *select_poly;
|
||||
float (*loop_normals)[3];
|
||||
const float (*loop_normals)[3];
|
||||
float (*bm_loop_normals)[3];
|
||||
int *lverts, *ledges;
|
||||
|
||||
const char *active_color_name;
|
||||
|
@@ -264,9 +264,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
|
||||
if (subdiv_cache->use_custom_loop_normals) {
|
||||
Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const float(*lnors)[3] = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&coarse_mesh->ldata, CD_NORMAL));
|
||||
BLI_assert(lnors != nullptr);
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(coarse_mesh);
|
||||
|
||||
GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc();
|
||||
GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format());
|
||||
|
@@ -127,7 +127,7 @@ struct AddOperationExecutor {
|
||||
transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
|
||||
|
||||
Object &surface_ob_orig = *curves_id_orig_->surface;
|
||||
Mesh &surface_orig = *static_cast<Mesh *>(surface_ob_orig.data);
|
||||
const Mesh &surface_orig = *static_cast<Mesh *>(surface_ob_orig.data);
|
||||
if (surface_orig.totpoly == 0) {
|
||||
report_empty_original_surface(stroke_extension.reports);
|
||||
return;
|
||||
@@ -206,13 +206,8 @@ struct AddOperationExecutor {
|
||||
}
|
||||
|
||||
const Span<MLoopTri> surface_looptris_orig = surface_orig.looptris();
|
||||
|
||||
/* Find normals. */
|
||||
if (!CustomData_has_layer(&surface_orig.ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(&surface_orig);
|
||||
}
|
||||
const Span<float3> corner_normals_su = {
|
||||
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig.ldata, CD_NORMAL)),
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(&surface_orig)),
|
||||
surface_orig.totloop};
|
||||
|
||||
const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig};
|
||||
|
@@ -256,12 +256,8 @@ struct DensityAddOperationExecutor {
|
||||
}
|
||||
self_->new_deformed_root_positions_.extend(new_positions_cu);
|
||||
|
||||
/* Find normals. */
|
||||
if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(surface_orig_);
|
||||
}
|
||||
const Span<float3> corner_normals_su = {
|
||||
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)),
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_orig_)),
|
||||
surface_orig_->totloop};
|
||||
|
||||
const Span<MLoopTri> surface_looptris_orig = surface_orig_->looptris();
|
||||
|
@@ -112,11 +112,8 @@ struct PuffOperationExecutor {
|
||||
|
||||
transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_);
|
||||
|
||||
if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(surface_);
|
||||
}
|
||||
corner_normals_su_ = {
|
||||
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)),
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_)),
|
||||
surface_->totloop};
|
||||
|
||||
surface_verts_ = surface_->verts();
|
||||
|
@@ -177,11 +177,8 @@ struct SlideOperationExecutor {
|
||||
report_missing_uv_map_on_original_surface(stroke_extension.reports);
|
||||
return;
|
||||
}
|
||||
if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(surface_orig_);
|
||||
}
|
||||
corner_normals_orig_su_ = {
|
||||
reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)),
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_orig_)),
|
||||
surface_orig_->totloop};
|
||||
|
||||
surface_ob_eval_ = DEG_get_evaluated_object(ctx_.depsgraph, surface_ob_orig_);
|
||||
|
@@ -412,12 +412,8 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
|
||||
mesh_loops.data(), mesh_polys.data(), mesh_verts.data(), me->totloop, me->totpoly, mlooptri);
|
||||
|
||||
// Compute loop normals
|
||||
BKE_mesh_calc_normals_split(me);
|
||||
const float(*lnors)[3] = nullptr;
|
||||
|
||||
if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
|
||||
lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
|
||||
}
|
||||
/* TODO: Only retrieve loop normals when necessary. */
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
|
||||
|
||||
// Get other mesh data
|
||||
const FreestyleEdge *fed = (FreestyleEdge *)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE);
|
||||
|
@@ -534,9 +534,7 @@ static void get_loop_normals(struct Mesh *mesh,
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
BLI_assert_msg(lnors != nullptr, "BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh);
|
||||
|
||||
normals.resize(mesh->totloop);
|
||||
|
||||
|
@@ -621,14 +621,9 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
const Span<MPoly> polys = me->polys();
|
||||
const Span<MLoop> loops = me->loops();
|
||||
const float(*lnors)[3] = nullptr;
|
||||
bool use_custom_normals = false;
|
||||
|
||||
BKE_mesh_calc_normals_split(me);
|
||||
if (CustomData_has_layer(&me->ldata, CD_NORMAL)) {
|
||||
lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL);
|
||||
use_custom_normals = true;
|
||||
}
|
||||
/* TODO: Only retrieve when necessary. */
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me);
|
||||
bool use_custom_normals = true;
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const MPoly *mpoly = &polys[poly_index];
|
||||
|
@@ -398,7 +398,8 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context,
|
||||
void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh)
|
||||
{
|
||||
pxr::UsdTimeCode timecode = get_export_time_code();
|
||||
const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
|
||||
/* TODO: Only when necessary. */
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh);
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
const Span<MLoop> loops = mesh->loops();
|
||||
|
||||
|
@@ -181,12 +181,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
|
||||
return poly_smooth_groups_[poly_index];
|
||||
}
|
||||
|
||||
void OBJMesh::ensure_mesh_normals() const
|
||||
{
|
||||
/* Const cast can be removed when calculating face corner normals lazily is possible. */
|
||||
BKE_mesh_calc_normals_split(const_cast<Mesh *>(export_mesh_));
|
||||
}
|
||||
|
||||
void OBJMesh::calc_smooth_groups(const bool use_bitflags)
|
||||
{
|
||||
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(),
|
||||
@@ -385,8 +379,8 @@ void OBJMesh::store_normal_coords_and_indices()
|
||||
normal_to_index.reserve(export_mesh_->totpoly);
|
||||
loop_to_normal_index_.resize(export_mesh_->totloop);
|
||||
loop_to_normal_index_.fill(-1);
|
||||
const float(*lnors)[3] = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&export_mesh_->ldata, CD_NORMAL));
|
||||
/* TODO: Only retrieve when necessary. */
|
||||
const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_);
|
||||
for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) {
|
||||
const MPoly &mpoly = mesh_polys_[poly_index];
|
||||
bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH);
|
||||
|
@@ -121,8 +121,6 @@ class OBJMesh : NonCopyable {
|
||||
*/
|
||||
const Material *get_object_material(int16_t mat_nr) const;
|
||||
|
||||
void ensure_mesh_normals() const;
|
||||
|
||||
/**
|
||||
* Calculate smooth groups of a smooth-shaded object.
|
||||
* \return A polygon aligned array of smooth group numbers.
|
||||
|
@@ -157,9 +157,6 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me
|
||||
if (mtl_writer) {
|
||||
mtlindices.append(mtl_writer->add_materials(obj));
|
||||
}
|
||||
if (export_params.export_normals) {
|
||||
obj.ensure_mesh_normals();
|
||||
}
|
||||
}
|
||||
|
||||
/* Parallel over meshes: store normal coords & indices, uv coords and indices. */
|
||||
|
@@ -104,7 +104,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest {
|
||||
const Span<MVert> verts = mesh->verts();
|
||||
EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f);
|
||||
EXPECT_V3_NEAR(verts.last().co, exp.vert_last, 0.0001f);
|
||||
const float3 *lnors = (const float3 *)CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
||||
const float3 *lnors = (const float3 *)BKE_mesh_corner_normals_ensure(mesh);
|
||||
float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0);
|
||||
EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f);
|
||||
const MLoopUV *mloopuv = static_cast<const MLoopUV *>(
|
||||
|
@@ -554,25 +554,8 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
const int index = rna_MeshLoop_index_get(ptr);
|
||||
const float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
|
||||
|
||||
if (!vec) {
|
||||
zero_v3(values);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(values, (const float *)vec);
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_MeshLoop_normal_set(PointerRNA *ptr, const float *values)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
const int index = rna_MeshLoop_index_get(ptr);
|
||||
float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
|
||||
|
||||
if (vec) {
|
||||
normalize_v3_v3(*vec, values);
|
||||
}
|
||||
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
|
||||
copy_v3_v3(values, loop_normals[index]);
|
||||
}
|
||||
|
||||
static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values)
|
||||
@@ -602,7 +585,8 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
const int index = rna_MeshLoop_index_get(ptr);
|
||||
const float(*nor)[3] = CustomData_get(&me->ldata, index, CD_NORMAL);
|
||||
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
|
||||
const float(*nor)[3] = loop_normals[index];
|
||||
const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT);
|
||||
|
||||
if (nor && vec) {
|
||||
@@ -744,19 +728,11 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values)
|
||||
static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values)
|
||||
{
|
||||
Mesh *me = rna_mesh(ptr);
|
||||
const float(*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
|
||||
|
||||
if (!lnors) {
|
||||
zero_v3(values + 0);
|
||||
zero_v3(values + 3);
|
||||
zero_v3(values + 6);
|
||||
}
|
||||
else {
|
||||
MLoopTri *lt = (MLoopTri *)ptr->data;
|
||||
copy_v3_v3(values + 0, lnors[lt->tri[0]]);
|
||||
copy_v3_v3(values + 3, lnors[lt->tri[1]]);
|
||||
copy_v3_v3(values + 6, lnors[lt->tri[2]]);
|
||||
}
|
||||
const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me);
|
||||
const MLoopTri *lt = (const MLoopTri *)ptr->data;
|
||||
copy_v3_v3(values + 0, loop_normals[lt->tri[0]]);
|
||||
copy_v3_v3(values + 3, loop_normals[lt->tri[1]]);
|
||||
copy_v3_v3(values + 6, loop_normals[lt->tri[2]]);
|
||||
}
|
||||
|
||||
static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr)
|
||||
@@ -2458,9 +2434,10 @@ static void rna_def_mloop(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Index", "Index of this loop");
|
||||
|
||||
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_range(prop, -1.0f, 1.0f);
|
||||
RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", "rna_MeshLoop_normal_set", NULL);
|
||||
RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Normal",
|
||||
|
@@ -44,15 +44,14 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh,
|
||||
|
||||
static void rna_Mesh_create_normals_split(Mesh *mesh)
|
||||
{
|
||||
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
|
||||
CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, NULL, mesh->totloop);
|
||||
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
/* TODO: Deprecation? */
|
||||
BKE_mesh_corner_normals_ensure(mesh);
|
||||
}
|
||||
|
||||
static void rna_Mesh_free_normals_split(Mesh *mesh)
|
||||
{
|
||||
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
|
||||
/* TODO: Deprecation? */
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
}
|
||||
|
||||
static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap)
|
||||
@@ -69,11 +68,6 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
|
||||
CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY);
|
||||
}
|
||||
|
||||
/* Compute loop normals if needed. */
|
||||
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
}
|
||||
|
||||
BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
|
||||
}
|
||||
|
||||
@@ -225,7 +219,7 @@ void RNA_api_mesh(StructRNA *srna)
|
||||
func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split");
|
||||
RNA_def_function_ui_description(func, "Empty split vertex normals");
|
||||
|
||||
func = RNA_def_function(srna, "calc_normals_split", "BKE_mesh_calc_normals_split");
|
||||
func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_create_normals_split");
|
||||
RNA_def_function_ui_description(func,
|
||||
"Calculate split vertex normals, which preserve sharp edges");
|
||||
|
||||
|
@@ -305,18 +305,14 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
|
||||
}
|
||||
|
||||
if (direction == MOD_DISP_DIR_CLNOR) {
|
||||
CustomData *ldata = &mesh->ldata;
|
||||
|
||||
if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
|
||||
if (!CustomData_has_layer(ldata, CD_NORMAL)) {
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
}
|
||||
|
||||
float(*clnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(ldata, CD_NORMAL));
|
||||
if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) {
|
||||
vert_clnors = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__));
|
||||
BKE_mesh_normals_loop_to_vertex(
|
||||
verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors);
|
||||
BKE_mesh_normals_loop_to_vertex(verts_num,
|
||||
BKE_mesh_loops(mesh),
|
||||
mesh->totloop,
|
||||
BKE_mesh_corner_normals_ensure(mesh),
|
||||
vert_clnors);
|
||||
}
|
||||
else {
|
||||
direction = MOD_DISP_DIR_NOR;
|
||||
|
@@ -252,20 +252,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
||||
}
|
||||
else {
|
||||
if (use_clnors) {
|
||||
/* If custom normals are present and the option is turned on calculate the split
|
||||
* normals and clear flag so the normals get interpolated to the result mesh. */
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_add_layer(&mesh->ldata,
|
||||
CD_NORMAL,
|
||||
CD_DUPLICATE,
|
||||
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
|
||||
mesh->totloop);
|
||||
}
|
||||
|
||||
result = multires_as_mesh(mmd, ctx, mesh, subdiv);
|
||||
|
||||
if (use_clnors) {
|
||||
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL));
|
||||
BLI_assert(lnors != nullptr);
|
||||
BKE_mesh_set_custom_normals(result, lnors);
|
||||
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
|
||||
}
|
||||
// BKE_subdiv_stats_print(&subdiv->stats);
|
||||
if (subdiv != runtime_data->subdiv) {
|
||||
|
@@ -250,10 +250,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
||||
}
|
||||
const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
|
||||
if (use_clnors) {
|
||||
/* If custom normals are present and the option is turned on calculate the split
|
||||
* normals and clear flag so the normals get interpolated to the result mesh. */
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_add_layer(&mesh->ldata,
|
||||
CD_NORMAL,
|
||||
CD_DUPLICATE,
|
||||
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
|
||||
mesh->totloop);
|
||||
}
|
||||
/* TODO(sergey): Decide whether we ever want to use CCG for subsurf,
|
||||
* maybe when it is a last modifier in the stack? */
|
||||
@@ -266,10 +267,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
||||
|
||||
if (use_clnors) {
|
||||
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL));
|
||||
BLI_assert(lnors != nullptr);
|
||||
BKE_mesh_set_custom_normals(result, lnors);
|
||||
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
|
||||
}
|
||||
// BKE_subdiv_stats_print(&subdiv->stats);
|
||||
if (subdiv != runtime_data->subdiv) {
|
||||
|
@@ -53,10 +53,11 @@ static Mesh *triangulate_mesh(Mesh *mesh,
|
||||
bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0;
|
||||
|
||||
if (keep_clnors) {
|
||||
BKE_mesh_calc_normals_split(mesh);
|
||||
/* We need that one to 'survive' to/from BMesh conversions. */
|
||||
CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
cd_mask_extra.lmask |= CD_MASK_NORMAL;
|
||||
CustomData_add_layer(&mesh->ldata,
|
||||
CD_NORMAL,
|
||||
CD_DUPLICATE,
|
||||
const_cast<float(*)[3]>(BKE_mesh_corner_normals_ensure(mesh)),
|
||||
mesh->totloop);
|
||||
}
|
||||
|
||||
BMeshCreateParams bmesh_create_params{};
|
||||
@@ -75,13 +76,8 @@ static Mesh *triangulate_mesh(Mesh *mesh,
|
||||
|
||||
if (keep_clnors) {
|
||||
float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&result->ldata, CD_NORMAL));
|
||||
BLI_assert(lnors != nullptr);
|
||||
|
||||
BKE_mesh_set_custom_normals(result, lnors);
|
||||
|
||||
/* Do some cleanup, we do not want those temp data to stay around. */
|
||||
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
|
||||
CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop);
|
||||
}
|
||||
|
||||
edges_num = result->totedge;
|
||||
|
@@ -322,14 +322,13 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
|
||||
/* Retrieve face corner normals from each mesh. It's necessary to use face corner normals
|
||||
* because face normals or vertex normals may lose information (custom normals, auto smooth) in
|
||||
* some cases. It isn't yet possible to retrieve lazily calculated face corner normals from a
|
||||
* const mesh, so they are calculated here every time. */
|
||||
Array<float3> corner_normals_orig(surface_mesh_orig->totloop);
|
||||
Array<float3> corner_normals_eval(surface_mesh_eval->totloop);
|
||||
BKE_mesh_calc_normals_split_ex(
|
||||
surface_mesh_orig, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_orig.data()));
|
||||
BKE_mesh_calc_normals_split_ex(
|
||||
surface_mesh_eval, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_eval.data()));
|
||||
* some cases. */
|
||||
const Span<float3> corner_normals_orig(
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_orig)),
|
||||
surface_mesh_orig->totloop);
|
||||
const Span<float3> corner_normals_eval(
|
||||
reinterpret_cast<const float3 *>(BKE_mesh_corner_normals_ensure(surface_mesh_eval)),
|
||||
surface_mesh_eval->totloop);
|
||||
|
||||
std::atomic<int> invalid_uv_count = 0;
|
||||
|
||||
|
@@ -483,15 +483,12 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
|
||||
const TSpace *tspace = nullptr;
|
||||
const float(*loop_normals)[3] = nullptr;
|
||||
if (tangent) {
|
||||
BKE_mesh_ensure_normals_for_display(me_eval);
|
||||
BKE_mesh_calc_normals_split(me_eval);
|
||||
BKE_mesh_calc_loop_tangents(me_eval, true, nullptr, 0);
|
||||
BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0);
|
||||
|
||||
tspace = static_cast<const TSpace *>(CustomData_get_layer(&me_eval->ldata, CD_TANGENT));
|
||||
BLI_assert(tspace);
|
||||
|
||||
loop_normals = static_cast<const float(*)[3]>(
|
||||
CustomData_get_layer(&me_eval->ldata, CD_NORMAL));
|
||||
loop_normals = BKE_mesh_corner_normals_ensure(me_eval);
|
||||
}
|
||||
|
||||
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
|
||||
|
@@ -515,7 +515,7 @@ static void do_multires_bake(MultiresBakeRender *bkr,
|
||||
0,
|
||||
vert_normals,
|
||||
poly_normals,
|
||||
(const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
|
||||
BKE_mesh_corner_normals_ensure(temp_mesh),
|
||||
(const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* May be nullptr. */
|
||||
/* result */
|
||||
&dm->loopData,
|
||||
|
Reference in New Issue
Block a user