More progress

This commit is contained in:
Hans Goudey 2023-01-05 11:32:05 -05:00
parent 54ae189d86
commit 9bfd8525fc
13 changed files with 136 additions and 64 deletions

View File

@ -75,7 +75,7 @@ struct Scene;
/* keep in sync with MFace/MPoly types */
typedef struct DMFlagMat {
short mat_nr;
char flag;
bool sharp;
} DMFlagMat;
typedef enum DerivedMeshType {

View File

@ -475,6 +475,8 @@ void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
*
* Used when defining an empty custom loop normals data layer,
* to keep same shading as with auto-smooth!
*
* \param sharp_faces: Optional array used to mark specific faces as sharp.
*/
void BKE_edges_sharp_from_angle_set(struct MEdge *medges,
int numEdges,
@ -482,6 +484,7 @@ void BKE_edges_sharp_from_angle_set(struct MEdge *medges,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
float split_angle);
@ -596,6 +599,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
* (splitting edges).
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
* \param sharp_faces: Optional array used to mark specific faces as sharp.
*/
void BKE_mesh_normals_loop_split(const struct MVert *mverts,
const float (*vert_normals)[3],
@ -607,6 +611,7 @@ void BKE_mesh_normals_loop_split(const struct MVert *mverts,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
bool use_split_normals,
float split_angle,
@ -624,6 +629,7 @@ void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_verts_set(const struct MVert *mverts,
@ -636,6 +642,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const struct MVert *mverts,
int numLoops,
const struct MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
short (*r_clnors_data)[2]);

View File

@ -297,6 +297,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
num_loops_dst,
polys_dst,
BKE_mesh_poly_normals_ensure(me_dst),
static_cast<const bool *>(CustomData_get_layer_named(
&me_dst->pdata, CD_PROP_BOOL, "sharp_face")),
num_polys_dst,
use_split_nors_dst,
split_angle_dst,
@ -352,6 +354,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
num_loops_dst,
polys_dst,
poly_nors_dst,
static_cast<const bool *>(CustomData_get_layer_named(
&me_dst->pdata, CD_PROP_BOOL, "sharp_face")),
num_polys_dst,
custom_nors_dst);
}
@ -1056,26 +1060,20 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
return true;
}
if (r_map && cddata_type == CD_FAKE_SHARP) {
const size_t elem_size = sizeof(*((MPoly *)nullptr));
const size_t data_size = sizeof(((MPoly *)nullptr)->flag);
const size_t data_offset = offsetof(MPoly, flag);
const uint64_t data_flag = ME_SMOOTH;
data_transfer_layersmapping_add_item(r_map,
cddata_type,
mix_mode,
mix_factor,
mix_weights,
BKE_mesh_polys(me_src),
BKE_mesh_polys_for_write(me_dst),
me_src->totpoly,
me_dst->totpoly,
elem_size,
data_size,
data_offset,
data_flag,
nullptr,
interp_data);
if (!CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")) {
CustomData_add_layer_named(
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totpoly, "sharp_face");
}
data_transfer_layersmapping_add_item_cd(
r_map,
CD_PROP_BOOL,
mix_mode,
mix_factor,
mix_weights,
CustomData_get_layer_named(&me_src->pdata, CD_PROP_BOOL, "sharp_face"),
CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face"),
interp,
interp_data);
return true;
}

View File

@ -838,6 +838,7 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
const Span<MLoop> loops,
const Span<int> loop_to_poly_map,
const Span<float3> poly_normals,
const Span<bool> sharp_faces,
const bool check_angle,
const float split_angle,
MutableSpan<int2> edge_to_loops,
@ -845,6 +846,9 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
{
using namespace blender;
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
auto face_is_smooth = [&](const int poly_i) {
return sharp_faces.is_empty() || !sharp_faces[poly_i];
};
for (const int poly_i : polys.index_range()) {
const MPoly &poly = polys[poly_i];
@ -859,7 +863,7 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
/* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
e2l[0] = loop_index;
/* We have to check this here too, else we might miss some flat faces!!! */
e2l[1] = (poly.flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
e2l[1] = (face_is_smooth(poly_i)) ? INDEX_UNSET : INDEX_INVALID;
}
else if (e2l[1] == INDEX_UNSET) {
const bool is_angle_sharp = (check_angle &&
@ -871,7 +875,7 @@ static void mesh_edges_sharp_tag(const Span<MEdge> edges,
* or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the
* same vertex, or angle between both its polys' normals is above split_angle value.
*/
if (!(poly.flag & ME_SMOOTH) || (edges[edge_i].flag & ME_SHARP) ||
if (!face_is_smooth(poly_i) || (edges[edge_i].flag & ME_SHARP) ||
vert_i == loops[e2l[0]].v || is_angle_sharp) {
/* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
@ -907,6 +911,7 @@ void BKE_edges_sharp_from_angle_set(MEdge *medges,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
const int numPolys,
const float split_angle)
{
@ -930,6 +935,7 @@ void BKE_edges_sharp_from_angle_set(MEdge *medges,
{mloops, numLoops},
loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
Span(sharp_faces, sharp_faces ? numPolys : 0),
true,
split_angle,
edge_to_loops,
@ -1501,6 +1507,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
const int numPolys,
const bool use_split_normals,
const float split_angle,
@ -1527,7 +1534,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
const MPoly *mp = &mpolys[mp_index];
int ml_index = mp->loopstart;
const int ml_index_end = ml_index + mp->totloop;
const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0);
const bool is_poly_flat = sharp_faces && sharp_faces[mp_index];
for (; ml_index < ml_index_end; ml_index++) {
if (is_poly_flat) {
@ -1619,6 +1626,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
loops,
loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
Span(sharp_faces, sharp_faces ? numPolys : 0),
check_angle,
split_angle,
edge_to_loops,
@ -1668,6 +1676,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
const int numPolys,
short (*r_clnors_data)[2],
const bool use_vertices)
@ -1704,6 +1713,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
numLoops,
mpolys,
poly_normals,
sharp_faces,
numPolys,
use_split_normals,
split_angle,
@ -1831,6 +1841,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
numLoops,
mpolys,
poly_normals,
sharp_faces,
numPolys,
use_split_normals,
split_angle,
@ -1908,6 +1919,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
const int numPolys,
short (*r_clnors_data)[2])
{
@ -1921,6 +1933,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
numLoops,
mpolys,
poly_normals,
sharp_faces,
numPolys,
r_clnors_data,
false);
@ -1936,6 +1949,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const MVert *mverts,
const int numLoops,
const MPoly *mpolys,
const float (*poly_normals)[3],
const bool *sharp_faces,
const int numPolys,
short (*r_clnors_data)[2])
{
@ -1949,6 +1963,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const MVert *mverts,
numLoops,
mpolys,
poly_normals,
sharp_faces,
numPolys,
r_clnors_data,
true);
@ -1982,6 +1997,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
static_cast<const bool *>(CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, "sharp_face")),
polys.size(),
clnors,
use_vertices);

View File

@ -152,14 +152,22 @@ static void update_node_vb(PBVH *pbvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
static bool face_materials_match(const PBVH *pbvh, const int a, const int b)
static bool face_materials_match(const PBVH *pbvh,
const bool *sharp_faces,
const int a,
const int b)
{
if (pbvh->material_indices) {
if (pbvh->material_indices[a] != pbvh->material_indices[b]) {
return false;
}
}
return (pbvh->mpoly[a].flag & ME_SMOOTH) == (pbvh->mpoly[b].flag & ME_SMOOTH);
if (sharp_faces) {
if (sharp_faces[a] != sharp_faces[b]) {
return false;
}
}
return true;
}
static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
@ -230,7 +238,7 @@ static int partition_indices_grids(int *prim_indices,
}
/* Returns the index of the first element on the right of the partition */
static int partition_indices_material(PBVH *pbvh, int lo, int hi)
static int partition_indices_material(PBVH *pbvh, const bool *sharp_faces, int lo, int hi)
{
const MLoopTri *looptri = pbvh->looptri;
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
@ -240,10 +248,10 @@ static int partition_indices_material(PBVH *pbvh, int lo, int hi)
for (;;) {
if (pbvh->looptri) {
const int first = looptri[pbvh->prim_indices[lo]].poly;
for (; face_materials_match(pbvh, first, looptri[indices[i]].poly); i++) {
for (; face_materials_match(pbvh, sharp_faces, first, looptri[indices[i]].poly); i++) {
/* pass */
}
for (; !face_materials_match(pbvh, first, looptri[indices[j]].poly); j--) {
for (; !face_materials_match(pbvh, sharp_faces, first, looptri[indices[j]].poly); j--) {
/* pass */
}
}
@ -449,7 +457,7 @@ static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, in
/* Return zero if all primitives in the node can be drawn with the
* same material (including flat/smooth shading), non-zero otherwise */
static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
static bool leaf_needs_material_split(PBVH *pbvh, const bool *sharp_faces, int offset, int count)
{
if (count <= 1) {
return false;
@ -459,7 +467,7 @@ static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
for (int i = offset + count - 1; i > offset; i--) {
int prim = pbvh->prim_indices[i];
if (!face_materials_match(pbvh, first->poly, pbvh->looptri[prim].poly)) {
if (!face_materials_match(pbvh, sharp_faces, first->poly, pbvh->looptri[prim].poly)) {
return true;
}
}
@ -538,6 +546,7 @@ static void test_face_boundaries(PBVH *pbvh)
*/
static void build_sub(PBVH *pbvh,
const bool *sharp_faces,
int node_index,
BB *cb,
BBC *prim_bbc,
@ -556,7 +565,7 @@ static void build_sub(PBVH *pbvh,
/* Decide whether this is a leaf or not */
const bool below_leaf_limit = count <= pbvh->leaf_limit || depth == STACK_FIXED_DEPTH - 1;
if (below_leaf_limit) {
if (!leaf_needs_material_split(pbvh, offset, count)) {
if (!leaf_needs_material_split(pbvh, sharp_faces, offset, count)) {
build_leaf(pbvh, node_index, prim_bbc, offset, count);
if (node_index == 0) {
@ -609,11 +618,12 @@ static void build_sub(PBVH *pbvh,
}
else {
/* Partition primitives by material */
end = partition_indices_material(pbvh, offset, offset + count - 1);
end = partition_indices_material(pbvh, sharp_faces, offset, offset + count - 1);
}
/* Build children */
build_sub(pbvh,
sharp_faces,
pbvh->nodes[node_index].children_offset,
NULL,
prim_bbc,
@ -622,6 +632,7 @@ static void build_sub(PBVH *pbvh,
prim_scratch,
depth + 1);
build_sub(pbvh,
sharp_faces,
pbvh->nodes[node_index].children_offset + 1,
NULL,
prim_bbc,
@ -635,7 +646,7 @@ static void build_sub(PBVH *pbvh,
}
}
static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
static void pbvh_build(PBVH *pbvh, const bool *sharp_faces, BB *cb, BBC *prim_bbc, int totprim)
{
if (totprim != pbvh->totprim) {
pbvh->totprim = totprim;
@ -657,7 +668,7 @@ static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
}
pbvh->totnode = 1;
build_sub(pbvh, 0, cb, prim_bbc, 0, totprim, NULL, 0);
build_sub(pbvh, sharp_faces, 0, cb, prim_bbc, 0, totprim, NULL, 0);
}
static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
@ -876,7 +887,9 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
}
if (looptri_num) {
pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, "sharp_face");
pbvh_build(pbvh, sharp_faces, &cb, prim_bbc, looptri_num);
#ifdef TEST_PBVH_FACE_SPLIT
test_face_boundaries(pbvh);
@ -964,7 +977,9 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
}
if (totgrid) {
pbvh_build(pbvh, &cb, prim_bbc, totgrid);
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&me->pdata, CD_PROP_BOOL, "sharp_face");
pbvh_build(pbvh, sharp_faces, &cb, prim_bbc, totgrid);
#ifdef TEST_PBVH_FACE_SPLIT
test_face_boundaries(pbvh);

View File

@ -721,10 +721,6 @@ char BM_edge_flag_from_mflag(const short mflag)
return (((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0));
}
char BM_face_flag_from_mflag(const char mflag)
{
return ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0);
}
short BM_edge_flag_to_mflag(BMEdge *e)
{
@ -733,9 +729,3 @@ short BM_edge_flag_to_mflag(BMEdge *e)
return (((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0));
}
char BM_face_flag_to_mflag(BMFace *f)
{
const char hflag = f->head.hflag;
return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0);
}

View File

@ -170,10 +170,8 @@ void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
const struct BMAllocTemplate *allocsize);
BMesh *BM_mesh_copy(BMesh *bm_old);
char BM_face_flag_from_mflag(char mflag);
char BM_edge_flag_from_mflag(short mflag);
/* ME -> BM */
char BM_face_flag_to_mflag(BMFace *f);
short BM_edge_flag_to_mflag(BMEdge *e);
#ifdef __cplusplus

View File

@ -302,6 +302,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
&me->pdata, CD_PROP_BOOL, ".hide_poly");
const int *material_indices = (const int *)CustomData_get_layer_named(
&me->pdata, CD_PROP_INT32, "material_index");
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&me->pdata, CD_PROP_BOOL, "sharp_face");
Span<MVert> mvert = me->verts();
Array<BMVert *> vtable(me->totvert);
@ -396,10 +398,12 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
BM_elem_index_set(f, bm->totface - 1); /* set_ok */
/* Transfer flag. */
f->head.hflag = BM_face_flag_from_mflag(mpoly[i].flag);
if (hide_poly && hide_poly[i]) {
BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
}
if (!(sharp_faces && sharp_faces[i])) {
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
}
if (select_poly && select_poly[i]) {
BM_face_select_set(bm, f, true);
}
@ -978,6 +982,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
bool need_hide_edge = false;
bool need_hide_poly = false;
bool need_material_index = false;
bool need_sharp_face = false;
i = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@ -1033,7 +1038,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
if (f->mat_nr != 0) {
need_material_index = true;
}
mpoly[i].flag = BM_face_flag_to_mflag(f);
if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
need_sharp_face = true;
}
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
need_hide_poly = true;
}
@ -1073,6 +1080,13 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
ATTR_DOMAIN_FACE,
[&](const int i) { return int(BM_face_at_index(bm, i)->mat_nr); });
}
if (need_sharp_face) {
BM_mesh_elem_table_ensure(bm, BM_FACE);
write_fn_to_attribute<int>(
me->attributes_for_write(), "sharp_face", ATTR_DOMAIN_FACE, [&](const int i) {
return !BM_elem_flag_test(BM_face_at_index(bm, i), BM_ELEM_SMOOTH);
});
}
/* Patch hook indices and vertex parents. */
if (params->calc_object_remap && (ototvert > 0)) {
@ -1296,6 +1310,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
j = 0;
bke::SpanAttributeWriter<int> material_index_attribute;
bke::SpanAttributeWriter<bool> sharp_face_attribute;
bke::SpanAttributeWriter<bool> hide_poly_attribute;
bke::SpanAttributeWriter<bool> select_poly_attribute;
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
@ -1306,7 +1321,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
BM_elem_index_set(efa, i); /* set_inline */
mp->totloop = efa->len;
mp->flag = BM_face_flag_to_mflag(efa);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
if (!hide_poly_attribute) {
hide_poly_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>(".hide_poly",
@ -1328,7 +1342,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
material_index_attribute = mesh_attributes.lookup_or_add_for_write_span<int>(
"material_index", ATTR_DOMAIN_FACE);
}
material_index_attribute.span[i] = efa->mat_nr;
}
if (!BM_elem_flag_test(efa, BM_ELEM_SMOOTH)) {
if (!sharp_face_attribute) {
sharp_face_attribute = mesh_attributes.lookup_or_add_for_write_span<bool>(
"sharp_face", ATTR_DOMAIN_FACE);
}
sharp_face_attribute.span[i] = true;
}
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);

View File

@ -336,16 +336,17 @@ struct PBVHBatches {
float fno[3];
short no[3];
int last_poly = -1;
bool smooth = false;
const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(args->pdata, CD_PROP_BOOL, "sharp_face"));
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const MLoopTri *tri) {
const MPoly *mp = args->mpoly + tri->poly;
bool smooth = false;
if (tri->poly != last_poly) {
last_poly = tri->poly;
if (!(mp->flag & ME_SMOOTH)) {
if (sharp_faces && sharp_faces[tri->poly]) {
smooth = true;
const MPoly *mp = args->mpoly + tri->poly;
BKE_mesh_calc_poly_normal(mp, args->mloop + mp->loopstart, args->mvert, fno);
normal_float_to_short_v3(no, fno);
}
@ -371,6 +372,8 @@ struct PBVHBatches {
{
uint vert_per_grid = square_i(args->ccg_key.grid_size - 1) * 4;
uint vert_count = args->totprim * vert_per_grid;
const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(args->pdata, CD_PROP_BOOL, "sharp_face"));
int existing_num = GPU_vertbuf_get_vertex_len(vbo.vert_buf);
void *existing_data = GPU_vertbuf_get_data(vbo.vert_buf);
@ -1066,6 +1069,8 @@ struct PBVHBatches {
{
int *mat_index = static_cast<int *>(
CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(args->pdata, CD_PROP_BOOL, "sharp_face"));
if (mat_index && args->totprim) {
int poly_index = BKE_subdiv_ccg_grid_to_face_index(args->subdiv_ccg, args->grid_indices[0]);

View File

@ -17,6 +17,7 @@
#include "PIL_time.h"
#include "BKE_attribute.hh"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_customdata.h"
@ -1474,6 +1475,7 @@ struct EdgeFeatData {
Object *ob_eval; /* For evaluated materials. */
const MLoopTri *mlooptri;
const int *material_indices;
blender::VArray<bool> sharp_faces;
blender::Span<MEdge> edges;
blender::Span<MLoop> loops;
blender::Span<MPoly> polys;
@ -1645,8 +1647,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
if (ld->conf.use_crease) {
bool do_crease = true;
if (!ld->conf.force_crease && !e_feat_data->use_auto_smooth &&
(e_feat_data->polys[mlooptri[f1].poly].flag & ME_SMOOTH) &&
(e_feat_data->polys[mlooptri[f2].poly].flag & ME_SMOOTH)) {
(!e_feat_data->sharp_faces[mlooptri[f1].poly]) &&
(!e_feat_data->sharp_faces[mlooptri[f2].poly])) {
do_crease = false;
}
if (do_crease && (dot_v3v3_db(tri1->gn, tri2->gn) < e_feat_data->crease_threshold)) {
@ -1936,6 +1938,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me);
const int tot_tri = BKE_mesh_runtime_looptri_len(me);
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const int *material_indices = (const int *)CustomData_get_layer_named(
&me->pdata, CD_PROP_INT32, "material_index");
@ -2075,6 +2080,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_data.ob_eval = ob_info->original_ob_eval;
edge_feat_data.mlooptri = mlooptri;
edge_feat_data.material_indices = material_indices;
edge_feat_data.sharp_faces = sharp_faces;
edge_feat_data.edges = me->edges();
edge_feat_data.polys = me->polys();
edge_feat_data.loops = me->loops();

View File

@ -449,7 +449,15 @@ static void get_topology(struct Mesh *mesh,
{
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
r_has_flat_shaded_poly = false;
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
for (const int i : sharp_faces.index_range()) {
if (sharp_faces[i]) {
r_has_flat_shaded_poly = true;
break;
}
}
poly_verts.clear();
loop_counts.clear();
@ -461,8 +469,6 @@ static void get_topology(struct Mesh *mesh,
const MPoly &poly = polys[i];
loop_counts.push_back(poly.totloop);
r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
const MLoop *loop = &loops[poly.loopstart + (poly.totloop - 1)];
for (int j = 0; j < poly.totloop; j++, loop--) {

View File

@ -56,6 +56,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_attribute.hh"
#include "BKE_bvhutils.h"
#include "BKE_customdata.h"
#include "BKE_image.h"
@ -450,6 +451,7 @@ static bool cast_ray_highpoly(BVHTreeFromMesh *treeData,
*/
static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval)
{
using namespace blender;
int i;
const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
@ -463,6 +465,9 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
const MVert *verts = BKE_mesh_verts(me);
const MPoly *polys = BKE_mesh_polys(me);
const MLoop *loops = BKE_mesh_loops(me);
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
looptri = static_cast<MLoopTri *>(MEM_mallocN(sizeof(*looptri) * tottri, __func__));
triangles = static_cast<TriTessFace *>(MEM_callocN(sizeof(TriTessFace) * tottri, __func__));
@ -505,7 +510,7 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
triangles[i].vert_normals[0] = vert_normals[loops[lt->tri[0]].v];
triangles[i].vert_normals[1] = vert_normals[loops[lt->tri[1]].v];
triangles[i].vert_normals[2] = vert_normals[loops[lt->tri[2]].v];
triangles[i].is_smooth = (mp->flag & ME_SMOOTH) != 0;
triangles[i].is_smooth = !sharp_faces[lt->poly];
if (tangent) {
triangles[i].tspace[0] = &tspace[lt->tri[0]];

View File

@ -64,6 +64,7 @@ struct MResolvePixelData {
const float (*vert_normals)[3];
MPoly *mpoly;
const int *material_indices;
const bool *sharp_faces;
MLoop *mloop;
MLoopUV *mloopuv;
float uv_offset[2];
@ -114,7 +115,7 @@ static void multiresbake_get_normal(const MResolvePixelData *data,
{
const int poly_index = data->mlooptri[tri_num].poly;
const MPoly *mp = &data->mpoly[poly_index];
const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0;
const bool smoothnormal = !(data->sharp_faces && data->sharp_faces[poly_index]);
if (smoothnormal) {
const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v;
@ -509,6 +510,8 @@ static void do_multires_bake(MultiresBakeRender *bkr,
dm->getLoopArray(dm),
dm->getLoopTriArray(dm),
dm->getNumLoopTri(dm),
static_cast<const bool *>(
CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face")),
&dm->loopData,
true,
nullptr,
@ -555,6 +558,8 @@ static void do_multires_bake(MultiresBakeRender *bkr,
handle->data.mpoly = mpoly;
handle->data.material_indices = static_cast<const int *>(
CustomData_get_layer_named(&dm->polyData, CD_PROP_INT32, "material_index"));
handle->data.sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face"));
handle->data.mvert = mvert;
handle->data.vert_normals = vert_normals;
handle->data.mloopuv = mloopuv;