More progress
This commit is contained in:
parent
54ae189d86
commit
9bfd8525fc
|
@ -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 {
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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--) {
|
||||
|
|
|
@ -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]];
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue