Compare commits
83 Commits
temp-legac
...
gsoc-2021-
Author | SHA1 | Date | |
---|---|---|---|
06dadc78a7 | |||
c1ae3b850c | |||
bcb7f4c172 | |||
745ff852f5 | |||
c21f9930bc | |||
906347042d | |||
0d8bb5f898 | |||
bcd1a5af89 | |||
de9dda76ab | |||
f0f26b3fcb | |||
28ee6ef31a | |||
6afd66c2eb | |||
5379633e59 | |||
051ce30390 | |||
1f70e8b748 | |||
ecc67c10e1 | |||
75df5d34d3 | |||
aedf0f3efa | |||
97aab4245e | |||
897838a2cc | |||
0766941f8f | |||
bfbeabeb39 | |||
efcab1bc1b | |||
4a4445124e | |||
a58a4cfc14 | |||
c71b4ee3f6 | |||
496e3b2b1a | |||
fa06eb9b97 | |||
7d2b039942 | |||
a13e9edfbb | |||
00a3241095 | |||
171a1feeb3 | |||
c17b1601b7 | |||
931b1ed7c7 | |||
b51602996e | |||
1cc5ab539b | |||
f12f0f0cd9 | |||
2869ee328c | |||
84ecc6c3e1 | |||
0176d404f1 | |||
821b17be25 | |||
751679edc2 | |||
fd9932d380 | |||
da94c057fd | |||
a44785c4dc | |||
ef51c65775 | |||
b4ff2ce85d | |||
1640c3536f | |||
08fc5f1d8e | |||
339b7a7b03 | |||
5af6c35dd1 | |||
a33076f769 | |||
7026eca6e3 | |||
0291553d70 | |||
48fc1bde95 | |||
48dc0c6fd6 | |||
95bd8e494c | |||
328406cf60 | |||
3ecf0753e8 | |||
dbeb2a7724 | |||
f07aa393bf | |||
68a28e1982 | |||
f23bb03cbb | |||
1fcbade10c | |||
cbe359bbf2 | |||
3493fefb74 | |||
8f600e8256 | |||
607eef0ae7 | |||
035ee22a50 | |||
e39543a64d | |||
a97bfc4e31 | |||
30ea058694 | |||
6fad4ce981 | |||
c718d169a9 | |||
0a96b035cf | |||
39f1908ba9 | |||
1f38c1f3b2 | |||
5444335e44 | |||
531c65fd93 | |||
1e07e070fc | |||
29c0528eb6 | |||
174052e1de | |||
caac062b55 |
@@ -147,6 +147,7 @@ def mesh_node_items(context):
|
||||
yield NodeItem("GeometryNodeMeshBoolean")
|
||||
yield NodeItem("GeometryNodeMeshToCurve")
|
||||
yield NodeItem("GeometryNodeMeshToPoints")
|
||||
yield NodeItem("GeometryNodeSolidify")
|
||||
yield NodeItem("GeometryNodeSplitEdges")
|
||||
yield NodeItem("GeometryNodeSubdivideMesh")
|
||||
yield NodeItem("GeometryNodeSubdivisionSurface")
|
||||
|
@@ -1526,6 +1526,7 @@ struct TexResult;
|
||||
#define GEO_NODE_SCALE_ELEMENTS 1151
|
||||
#define GEO_NODE_EXTRUDE_MESH 1152
|
||||
#define GEO_NODE_MERGE_BY_DISTANCE 1153
|
||||
#define GEO_NODE_SOLIDIFY 1154
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@@ -4845,6 +4845,7 @@ static void registerGeometryNodes()
|
||||
register_node_type_geo_set_shade_smooth();
|
||||
register_node_type_geo_set_spline_cyclic();
|
||||
register_node_type_geo_set_spline_resolution();
|
||||
register_node_type_geo_solidify();
|
||||
register_node_type_geo_string_join();
|
||||
register_node_type_geo_string_to_curves();
|
||||
register_node_type_geo_subdivision_surface();
|
||||
|
@@ -34,11 +34,13 @@ set(SRC
|
||||
intern/mesh_to_curve_convert.cc
|
||||
intern/point_merge_by_distance.cc
|
||||
intern/realize_instances.cc
|
||||
intern/solidify_nonmanifold.c
|
||||
|
||||
GEO_mesh_merge_by_distance.hh
|
||||
GEO_mesh_to_curve.hh
|
||||
GEO_point_merge_by_distance.hh
|
||||
GEO_realize_instances.hh
|
||||
GEO_solidifiy.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
43
source/blender/geometry/GEO_solidifiy.h
Normal file
43
source/blender/geometry/GEO_solidifiy.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Mesh;
|
||||
|
||||
typedef struct SolidifyData {
|
||||
const Object *object;
|
||||
/** New surface offset level. (Thickness) */
|
||||
float offset;
|
||||
/** Midpoint of the offset. */
|
||||
float offset_fac;
|
||||
/**
|
||||
* Factor for the minimum weight to use when vertex-groups are used,
|
||||
* avoids 0.0 weights giving duplicate geometry.
|
||||
*/
|
||||
float offset_fac_vg;
|
||||
/** Clamp offset based on surrounding geometry. */
|
||||
float offset_clamp;
|
||||
|
||||
/** Variables for #MOD_SOLIDIFY_MODE_NONMANIFOLD. */
|
||||
char nonmanifold_offset_mode;
|
||||
char nonmanifold_boundary_mode;
|
||||
|
||||
int flag;
|
||||
|
||||
float merge_tolerance;
|
||||
float bevel_convex;
|
||||
const float *distance;
|
||||
} SolidifyData;
|
||||
|
||||
struct Mesh *solidify_nonmanifold(const SolidifyData *solidify_data,
|
||||
struct Mesh *mesh,
|
||||
bool **r_shell_verts,
|
||||
bool **r_rim_verts,
|
||||
bool **r_shell_faces,
|
||||
bool **r_rim_faces);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -18,24 +18,20 @@
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "GEO_solidifiy.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
#include "MOD_solidify_util.h" /* Own include. */
|
||||
#include "MOD_util.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic error "-Wsign-conversion"
|
||||
#endif
|
||||
@@ -144,12 +140,14 @@ static int comp_float_int_pair(const void *a, const void *b)
|
||||
}
|
||||
|
||||
/* NOLINTNEXTLINE: readability-function-size */
|
||||
Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
Mesh *mesh)
|
||||
Mesh *solidify_nonmanifold(const SolidifyData *solidify_data,
|
||||
Mesh *mesh,
|
||||
bool **r_shell_verts,
|
||||
bool **r_rim_verts,
|
||||
bool **r_shell_faces,
|
||||
bool **r_rim_faces)
|
||||
{
|
||||
Mesh *result;
|
||||
const SolidifyModifierData *smd = (SolidifyModifierData *)md;
|
||||
|
||||
MVert *mv, *mvert, *orig_mvert;
|
||||
MEdge *ed, *medge, *orig_medge;
|
||||
@@ -158,49 +156,32 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
const uint numVerts = (uint)mesh->totvert;
|
||||
const uint numEdges = (uint)mesh->totedge;
|
||||
const uint numPolys = (uint)mesh->totpoly;
|
||||
const uint numLoops = (uint)mesh->totloop;
|
||||
|
||||
if (numPolys == 0 && numVerts != 0) {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
/* Only use material offsets if we have 2 or more materials. */
|
||||
const short mat_nrs = ctx->object->totcol > 1 ? ctx->object->totcol : 1;
|
||||
const short mat_nr_max = mat_nrs - 1;
|
||||
const short mat_ofs = mat_nrs > 1 ? smd->mat_ofs : 0;
|
||||
const short mat_ofs_rim = mat_nrs > 1 ? smd->mat_ofs_rim : 0;
|
||||
float(*poly_nors)[3] = NULL;
|
||||
|
||||
/* #ofs_front and #ofs_back are the offset from the original
|
||||
* surface along the normal, where #oft_front is along the positive
|
||||
* and #oft_back is along the negative normal. */
|
||||
const float ofs_front = (smd->offset_fac + 1.0f) * 0.5f * smd->offset;
|
||||
const float ofs_back = ofs_front - smd->offset * smd->offset_fac;
|
||||
/* #ofs_front_clamped and #ofs_back_clamped are the same as
|
||||
* #ofs_front and #ofs_back, but never zero. */
|
||||
const float ofs_front_clamped = clamp_nonzero(ofs_front, 1e-5f);
|
||||
const float ofs_back_clamped = clamp_nonzero(ofs_back, 1e-5f);
|
||||
const float offset_fac_vg = smd->offset_fac_vg;
|
||||
const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
|
||||
const float offset = fabsf(smd->offset) * smd->offset_clamp;
|
||||
const bool do_angle_clamp = smd->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP;
|
||||
/* #do_flip, flips the normals of the result. This is inverted if negative thickness
|
||||
* is used, since simple solidify with negative thickness keeps the faces facing outside. */
|
||||
const bool do_flip = ((smd->flag & MOD_SOLIDIFY_FLIP) != 0) == (smd->offset > 0);
|
||||
const bool do_rim = smd->flag & MOD_SOLIDIFY_RIM;
|
||||
const bool do_shell = ((smd->flag & MOD_SOLIDIFY_RIM) && (smd->flag & MOD_SOLIDIFY_NOSHELL)) ==
|
||||
0;
|
||||
const bool do_clamp = (smd->offset_clamp != 0.0f);
|
||||
const float ofs_front = (solidify_data->offset_fac + 1.0f) * 0.5f * solidify_data->offset;
|
||||
const float ofs_back = ofs_front - solidify_data->offset * solidify_data->offset_fac;
|
||||
const float ofs_front_clamped = max_ff(1e-5f,
|
||||
fabsf(solidify_data->offset > 0 ? ofs_front : ofs_back));
|
||||
const float ofs_back_clamped = max_ff(1e-5f,
|
||||
fabsf(solidify_data->offset > 0 ? ofs_back : ofs_front));
|
||||
const float offset_fac_vg = solidify_data->offset_fac_vg;
|
||||
const float offset_fac_vg_inv = 1.0f - solidify_data->offset_fac_vg;
|
||||
const float offset = fabsf(solidify_data->offset) * solidify_data->offset_clamp;
|
||||
const bool do_angle_clamp = solidify_data->flag & MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP;
|
||||
const bool do_flip = (solidify_data->flag & MOD_SOLIDIFY_FLIP) != 0;
|
||||
const bool do_rim = solidify_data->flag & MOD_SOLIDIFY_RIM;
|
||||
const bool do_shell = solidify_data->flag & MOD_SOLIDIFY_SHELL;
|
||||
const bool do_clamp = (solidify_data->offset_clamp != 0.0f);
|
||||
|
||||
const float bevel_convex = smd->bevel_convex;
|
||||
const float bevel_convex = solidify_data->bevel_convex;
|
||||
|
||||
MDeformVert *dvert;
|
||||
const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
|
||||
int defgrp_index;
|
||||
const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name);
|
||||
const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name);
|
||||
|
||||
MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index);
|
||||
|
||||
const bool do_flat_faces = dvert && (smd->flag & MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES);
|
||||
const bool do_flat_faces = solidify_data->flag & MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES;
|
||||
|
||||
orig_mvert = mesh->mvert;
|
||||
orig_medge = mesh->medge;
|
||||
@@ -214,16 +195,18 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
|
||||
#define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1)
|
||||
|
||||
/* Calculate only face normals. Copied because they are modified directly below. */
|
||||
float(*poly_nors)[3] = MEM_malloc_arrayN(numPolys, sizeof(float[3]), __func__);
|
||||
memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * numPolys);
|
||||
/* Calculate only face normals. */
|
||||
poly_nors = MEM_malloc_arrayN(numPolys, sizeof(*poly_nors), __func__);
|
||||
BKE_mesh_calc_normals_poly(
|
||||
orig_mvert, (int)numVerts, orig_mloop, (int)numLoops, orig_mpoly, (int)numPolys, poly_nors);
|
||||
|
||||
NewFaceRef *face_sides_arr = MEM_malloc_arrayN(
|
||||
numPolys * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify");
|
||||
bool *null_faces =
|
||||
(smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) ?
|
||||
MEM_calloc_arrayN(numPolys, sizeof(*null_faces), "null_faces in solidify") :
|
||||
NULL;
|
||||
bool *null_faces = (solidify_data->nonmanifold_offset_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) ?
|
||||
MEM_calloc_arrayN(
|
||||
numPolys, sizeof(*null_faces), "null_faces in solidify") :
|
||||
NULL;
|
||||
uint largest_ngon = 3;
|
||||
/* Calculate face to #NewFaceRef map. */
|
||||
{
|
||||
@@ -363,7 +346,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
bool *face_singularity = MEM_calloc_arrayN(
|
||||
numPolys, sizeof(*face_singularity), "face_sides_arr in solidify");
|
||||
|
||||
const float merge_tolerance_sqr = smd->merge_tolerance * smd->merge_tolerance;
|
||||
const float merge_tolerance_sqr = solidify_data->merge_tolerance *
|
||||
solidify_data->merge_tolerance;
|
||||
uint *combined_verts = MEM_calloc_arrayN(
|
||||
numVerts, sizeof(*combined_verts), "combined_verts in solidify");
|
||||
|
||||
@@ -1397,14 +1381,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
int loopend = mp->loopstart + mp->totloop;
|
||||
ml = orig_mloop + mp->loopstart;
|
||||
for (int j = mp->loopstart; j < loopend; j++, ml++) {
|
||||
MDeformVert *dv = &dvert[ml->v];
|
||||
if (defgrp_invert) {
|
||||
scalar_vgroup = min_ff(1.0f - BKE_defvert_find_weight(dv, defgrp_index),
|
||||
scalar_vgroup);
|
||||
}
|
||||
else {
|
||||
scalar_vgroup = min_ff(BKE_defvert_find_weight(dv, defgrp_index), scalar_vgroup);
|
||||
}
|
||||
scalar_vgroup = min_ff(solidify_data->distance[i], scalar_vgroup);
|
||||
}
|
||||
scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
|
||||
face_weight[i] = scalar_vgroup;
|
||||
@@ -1420,11 +1397,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
if (!g->is_singularity) {
|
||||
float *nor = g->no;
|
||||
float move_nor[3] = {0, 0, 0};
|
||||
bool disable_boundary_fix = (smd->nonmanifold_boundary_mode ==
|
||||
bool disable_boundary_fix = (solidify_data->nonmanifold_boundary_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE ||
|
||||
(g->is_orig_closed || g->split));
|
||||
/* Constraints Method. */
|
||||
if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) {
|
||||
if (solidify_data->nonmanifold_offset_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) {
|
||||
NewEdgeRef *first_edge = NULL;
|
||||
NewEdgeRef **edge_ptr = g->edges;
|
||||
/* Contains normal and offset [nx, ny, nz, ofs]. */
|
||||
@@ -1470,7 +1448,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
}
|
||||
}
|
||||
uint face_nors_len = 0;
|
||||
const float stop_explosion = 0.999f - fabsf(smd->offset_fac) * 0.05f;
|
||||
const float stop_explosion = 0.999f - fabsf(solidify_data->offset_fac) * 0.05f;
|
||||
while (queue_index > 0) {
|
||||
if (face_nors_len == 0) {
|
||||
if (queue_index <= 2) {
|
||||
@@ -1620,7 +1598,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
ofs *= face_weight[face->index];
|
||||
}
|
||||
|
||||
if (smd->nonmanifold_offset_mode ==
|
||||
if (solidify_data->nonmanifold_offset_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) {
|
||||
MLoop *ml_next = orig_mloop + face->face->loopstart;
|
||||
ml = ml_next + (face->face->totloop - 1);
|
||||
@@ -1666,7 +1644,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
}
|
||||
|
||||
/* Set normal length with selected method. */
|
||||
if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) {
|
||||
if (solidify_data->nonmanifold_offset_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) {
|
||||
if (has_front) {
|
||||
float length_sq = len_squared_v3(nor);
|
||||
if (LIKELY(length_sq > FLT_EPSILON)) {
|
||||
@@ -1755,7 +1734,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
sub_v3_v3v3(e1,
|
||||
orig_mvert_co[vm[e1_edge->v1] == i ? e1_edge->v2 : e1_edge->v1],
|
||||
orig_mvert_co[i]);
|
||||
if (smd->nonmanifold_boundary_mode == MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) {
|
||||
if (solidify_data->nonmanifold_boundary_mode ==
|
||||
MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) {
|
||||
cross_v3_v3v3(constr_nor, e0, e1);
|
||||
}
|
||||
else {
|
||||
@@ -1789,14 +1769,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
}
|
||||
float scalar_vgroup = 1;
|
||||
/* Use vertex group. */
|
||||
if (dvert && !do_flat_faces) {
|
||||
MDeformVert *dv = &dvert[i];
|
||||
if (defgrp_invert) {
|
||||
scalar_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
|
||||
}
|
||||
else {
|
||||
scalar_vgroup = BKE_defvert_find_weight(dv, defgrp_index);
|
||||
}
|
||||
if (!do_flat_faces) {
|
||||
scalar_vgroup = solidify_data->distance[i];
|
||||
scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
|
||||
}
|
||||
/* Do clamping. */
|
||||
@@ -1929,16 +1903,32 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
|
||||
}
|
||||
|
||||
/* Checks that result has dvert data. */
|
||||
if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
|
||||
dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert);
|
||||
/* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
|
||||
if (dvert == NULL) {
|
||||
/* Add a valid data layer! */
|
||||
dvert = CustomData_add_layer(
|
||||
&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert);
|
||||
}
|
||||
result->dvert = dvert;
|
||||
*r_shell_verts = MEM_malloc_arrayN(
|
||||
(size_t)result->totvert, sizeof(bool), "shell verts selection in solidify");
|
||||
|
||||
for (int i = 0; i < result->totvert; i++) {
|
||||
(*r_shell_verts)[i] = false;
|
||||
}
|
||||
|
||||
*r_rim_verts = MEM_malloc_arrayN(
|
||||
(size_t)result->totvert, sizeof(bool), "rim verts selection in solidify");
|
||||
|
||||
for (int i = 0; i < result->totvert; i++) {
|
||||
(*r_rim_verts)[i] = false;
|
||||
}
|
||||
|
||||
*r_shell_faces = MEM_malloc_arrayN(
|
||||
(size_t)result->totpoly, sizeof(bool), "shell faces selection in solidify");
|
||||
|
||||
for (int i = 0; i < result->totpoly; i++) {
|
||||
(*r_shell_faces)[i] = false;
|
||||
}
|
||||
|
||||
*r_rim_faces = MEM_malloc_arrayN(
|
||||
(size_t)result->totpoly, sizeof(bool), "rim faces selection in solidify");
|
||||
|
||||
for (int i = 0; i < result->totpoly; i++) {
|
||||
(*r_rim_faces)[i] = false;
|
||||
}
|
||||
|
||||
/* Make_new_verts. */
|
||||
@@ -2167,50 +2157,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
|
||||
/* Loop data. */
|
||||
int *loops = MEM_malloc_arrayN(j, sizeof(*loops), "loops in solidify");
|
||||
/* The #mat_nr is from consensus. */
|
||||
short most_mat_nr = 0;
|
||||
uint most_mat_nr_face = 0;
|
||||
uint most_mat_nr_count = 0;
|
||||
for (short l = 0; l < mat_nrs; l++) {
|
||||
uint count = 0;
|
||||
uint face = 0;
|
||||
uint k = 0;
|
||||
for (EdgeGroup *g3 = g2; g3->valid && k < j; g3++) {
|
||||
if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) {
|
||||
/* Check both far ends in terms of faces of an edge group. */
|
||||
if (g3->edges[0]->faces[0]->face->mat_nr == l) {
|
||||
face = g3->edges[0]->faces[0]->index;
|
||||
count++;
|
||||
}
|
||||
NewEdgeRef *le = g3->edges[g3->edges_len - 1];
|
||||
if (le->faces[1] && le->faces[1]->face->mat_nr == l) {
|
||||
face = le->faces[1]->index;
|
||||
count++;
|
||||
}
|
||||
else if (!le->faces[1] && le->faces[0]->face->mat_nr == l) {
|
||||
face = le->faces[0]->index;
|
||||
count++;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
if (count > most_mat_nr_count) {
|
||||
most_mat_nr = l;
|
||||
most_mat_nr_face = face;
|
||||
most_mat_nr_count = count;
|
||||
}
|
||||
}
|
||||
CustomData_copy_data(
|
||||
&mesh->pdata, &result->pdata, (int)most_mat_nr_face, (int)poly_index, 1);
|
||||
|
||||
if (origindex_poly) {
|
||||
origindex_poly[poly_index] = ORIGINDEX_NONE;
|
||||
}
|
||||
mpoly[poly_index].loopstart = (int)loop_index;
|
||||
mpoly[poly_index].totloop = (int)j;
|
||||
mpoly[poly_index].mat_nr = most_mat_nr +
|
||||
(g->is_orig_closed || !do_rim ? 0 : mat_ofs_rim);
|
||||
CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
|
||||
mpoly[poly_index].flag = orig_mpoly[most_mat_nr_face].flag;
|
||||
|
||||
if (g->is_orig_closed || !do_rim) {
|
||||
(*r_rim_faces)[poly_index] = true;
|
||||
}
|
||||
|
||||
poly_index++;
|
||||
|
||||
for (uint k = 0; g2->valid && k < j; g2++) {
|
||||
@@ -2282,8 +2239,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
&mesh->pdata, &result->pdata, (int)(*new_edges)->faces[0]->index, (int)poly_index, 1);
|
||||
mpoly[poly_index].loopstart = (int)loop_index;
|
||||
mpoly[poly_index].totloop = 4 - (int)(v1_singularity || v2_singularity);
|
||||
mpoly[poly_index].mat_nr = face->mat_nr + mat_ofs_rim;
|
||||
CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
|
||||
|
||||
(*r_rim_faces)[poly_index] = true;
|
||||
mpoly[poly_index].flag = face->flag;
|
||||
poly_index++;
|
||||
|
||||
@@ -2304,20 +2261,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
MEdge *open_face_edge;
|
||||
uint open_face_edge_index;
|
||||
if (!do_flip) {
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
(*r_rim_verts)[medge[edge1->new_edge].v1] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge1->new_edge].v1;
|
||||
mloop[loop_index++].e = edge1->new_edge;
|
||||
|
||||
if (!v2_singularity) {
|
||||
open_face_edge_index = edge1->link_edge_groups[1]->open_face_edge;
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
|
||||
(*r_rim_verts)[medge[edge1->new_edge].v2] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge1->new_edge].v2;
|
||||
open_face_edge = medge + open_face_edge_index;
|
||||
@@ -2328,21 +2282,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
mloop[loop_index++].e = edge2->link_edge_groups[1]->open_face_edge;
|
||||
}
|
||||
}
|
||||
(*r_rim_verts)[medge[edge2->new_edge].v2] = true;
|
||||
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge2->new_edge].v2;
|
||||
mloop[loop_index++].e = edge2->new_edge;
|
||||
|
||||
if (!v1_singularity) {
|
||||
open_face_edge_index = edge2->link_edge_groups[0]->open_face_edge;
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
|
||||
(*r_rim_verts)[medge[edge2->new_edge].v1] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge2->new_edge].v1;
|
||||
open_face_edge = medge + open_face_edge_index;
|
||||
@@ -2357,10 +2307,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
else {
|
||||
if (!v1_singularity) {
|
||||
open_face_edge_index = edge1->link_edge_groups[0]->open_face_edge;
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
|
||||
(*r_rim_verts)[medge[edge1->new_edge].v1] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge1->new_edge].v1;
|
||||
open_face_edge = medge + open_face_edge_index;
|
||||
@@ -2372,20 +2321,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
}
|
||||
}
|
||||
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
(*r_rim_verts)[medge[edge2->new_edge].v1] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge2->new_edge].v1;
|
||||
mloop[loop_index++].e = edge2->new_edge;
|
||||
|
||||
if (!v2_singularity) {
|
||||
open_face_edge_index = edge2->link_edge_groups[1]->open_face_edge;
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
|
||||
(*r_rim_verts)[medge[edge2->new_edge].v2] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge2->new_edge].v2;
|
||||
open_face_edge = medge + open_face_edge_index;
|
||||
@@ -2397,10 +2343,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
}
|
||||
}
|
||||
|
||||
if (rim_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
(*r_rim_verts)[medge[edge1->new_edge].v2] = true;
|
||||
|
||||
CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1);
|
||||
mloop[loop_index].v = medge[edge1->new_edge].v2;
|
||||
mloop[loop_index++].e = edge1->new_edge;
|
||||
@@ -2414,10 +2358,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
NewFaceRef *fr = face_sides_arr;
|
||||
uint *face_loops = MEM_malloc_arrayN(
|
||||
largest_ngon * 2, sizeof(*face_loops), "face_loops in solidify");
|
||||
|
||||
uint *face_verts = MEM_malloc_arrayN(
|
||||
largest_ngon * 2, sizeof(*face_verts), "face_verts in solidify");
|
||||
|
||||
uint *face_edges = MEM_malloc_arrayN(
|
||||
largest_ngon * 2, sizeof(*face_edges), "face_edges in solidify");
|
||||
|
||||
for (uint i = 0; i < numPolys * 2; i++, fr++) {
|
||||
const uint loopstart = (uint)fr->face->loopstart;
|
||||
uint totloop = (uint)fr->face->totloop;
|
||||
@@ -2473,15 +2420,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
CustomData_copy_data(&mesh->pdata, &result->pdata, (int)(i / 2), (int)poly_index, 1);
|
||||
mpoly[poly_index].loopstart = (int)loop_index;
|
||||
mpoly[poly_index].totloop = (int)k;
|
||||
mpoly[poly_index].mat_nr = fr->face->mat_nr + (fr->reversed != do_flip ? mat_ofs : 0);
|
||||
CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
|
||||
|
||||
if (fr->reversed != do_flip) {
|
||||
(*r_shell_faces)[poly_index] = true;
|
||||
}
|
||||
mpoly[poly_index].flag = fr->face->flag;
|
||||
if (fr->reversed != do_flip) {
|
||||
for (int l = (int)k - 1; l >= 0; l--) {
|
||||
if (shell_defgrp_index != -1) {
|
||||
BKE_defvert_ensure_index(&result->dvert[face_verts[l]], shell_defgrp_index)
|
||||
->weight = 1.0f;
|
||||
}
|
||||
(*r_shell_verts)[face_verts[l]] = true;
|
||||
|
||||
CustomData_copy_data(
|
||||
&mesh->ldata, &result->ldata, (int)face_loops[l], (int)loop_index, 1);
|
||||
mloop[loop_index].v = face_verts[l];
|
||||
@@ -2506,27 +2453,28 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
MEM_freeN(face_verts);
|
||||
MEM_freeN(face_edges);
|
||||
}
|
||||
if (edge_index != numNewEdges) {
|
||||
BKE_modifier_set_error(ctx->object,
|
||||
md,
|
||||
"Internal Error: edges array wrong size: %u instead of %u",
|
||||
numNewEdges,
|
||||
edge_index);
|
||||
}
|
||||
if (poly_index != numNewPolys) {
|
||||
BKE_modifier_set_error(ctx->object,
|
||||
md,
|
||||
"Internal Error: polys array wrong size: %u instead of %u",
|
||||
numNewPolys,
|
||||
poly_index);
|
||||
}
|
||||
if (loop_index != numNewLoops) {
|
||||
BKE_modifier_set_error(ctx->object,
|
||||
md,
|
||||
"Internal Error: loops array wrong size: %u instead of %u",
|
||||
numNewLoops,
|
||||
loop_index);
|
||||
}
|
||||
/* Haven't found a good way to generalize this. */
|
||||
// if (edge_index != numNewEdges) {
|
||||
/*BKE_modifier_set_error(ctx->object,
|
||||
md,A
|
||||
"Internal Error: edges array wrong size: %u instead of %u",
|
||||
numNewEdges,
|
||||
edge_index);*/
|
||||
//}
|
||||
// if (poly_index != numNewPolys) {
|
||||
/*BKE_modifier_set_error(ctx->object,
|
||||
md,
|
||||
"Internal Error: polys array wrong size: %u instead of %u",
|
||||
numNewPolys,f
|
||||
poly_index);*/
|
||||
//}
|
||||
// if (loop_index != numNewLoops) {
|
||||
/*BKE_modifier_set_error(ctx->object,
|
||||
md,
|
||||
"Internal Error: loops array wrong size: %u instead of %u",
|
||||
numNewLoops,
|
||||
loop_index);*/
|
||||
//}
|
||||
BLI_assert(edge_index == numNewEdges);
|
||||
BLI_assert(poly_index == numNewPolys);
|
||||
BLI_assert(loop_index == numNewLoops);
|
@@ -399,9 +399,9 @@ enum {
|
||||
/* We can't have both flags enabled at once,
|
||||
* flags defined in DNA_scene_types.h */
|
||||
#define ME_EDIT_PAINT_SEL_MODE(_me) \
|
||||
(((_me)->editflag & ME_EDIT_PAINT_FACE_SEL) ? SCE_SELECT_FACE : \
|
||||
((_me)->editflag & ME_EDIT_PAINT_VERT_SEL) ? SCE_SELECT_VERTEX : \
|
||||
0)
|
||||
(((_me)->editflag & ME_EDIT_PAINT_FACE_SEL) ? \
|
||||
SCE_SELECT_FACE : \
|
||||
((_me)->editflag & ME_EDIT_PAINT_VERT_SEL) ? SCE_SELECT_VERTEX : 0)
|
||||
|
||||
/** #Mesh.flag */
|
||||
enum {
|
||||
|
@@ -1314,9 +1314,11 @@ enum {
|
||||
MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */
|
||||
#endif
|
||||
MOD_SOLIDIFY_FLIP = (1 << 5),
|
||||
MOD_SOLIDIFY_NOSHELL = (1 << 6),
|
||||
MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP = (1 << 7),
|
||||
MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES = (1 << 8),
|
||||
MOD_SOLIDIFY_SHELL = (1 << 6),
|
||||
MOD_SOLIDIFY_NOSHELL = (1 << 7), /* MOD_SOLIDIFY_SHELL should be used. instead This is kept as
|
||||
long as the Modifier uses it. */
|
||||
MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP = (1 << 8),
|
||||
MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES = (1 << 9),
|
||||
};
|
||||
|
||||
/** #SolidifyModifierData.mode */
|
||||
|
@@ -1347,6 +1347,14 @@ typedef struct NodeInputColor {
|
||||
float color[4];
|
||||
} NodeInputColor;
|
||||
|
||||
typedef struct NodeGeometrySolidify {
|
||||
/* GeometryNodeAttributeInputMode */
|
||||
uint8_t thickness_mode;
|
||||
uint8_t nonmanifold_offset_mode;
|
||||
uint8_t nonmanifold_boundary_mode;
|
||||
char _pad[5];
|
||||
} NodeGeometrySolidify;
|
||||
|
||||
typedef struct NodeInputString {
|
||||
char *string;
|
||||
} NodeInputString;
|
||||
|
@@ -4522,6 +4522,36 @@ static void rna_def_modifier_surface(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS);
|
||||
}
|
||||
|
||||
const EnumPropertyItem nonmanifold_thickness_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_FIXED,
|
||||
"FIXED",
|
||||
0,
|
||||
"Fixed",
|
||||
"Most basic thickness calculation"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN,
|
||||
"EVEN",
|
||||
0,
|
||||
"Even",
|
||||
"Even thickness calculation which takes the angle between faces into account"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS,
|
||||
"CONSTRAINTS",
|
||||
0,
|
||||
"Constraints",
|
||||
"Thickness calculation using constraints, most advanced"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem nonmanifold_boundary_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE, "NONE", 0, "None", "No shape correction"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND,
|
||||
"ROUND",
|
||||
0,
|
||||
"Round",
|
||||
"Round open perimeter shape"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT, "FLAT", 0, "Flat", "Flat open perimeter shape"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void rna_def_modifier_solidify(BlenderRNA *brna)
|
||||
{
|
||||
static const EnumPropertyItem mode_items[] = {
|
||||
@@ -4540,40 +4570,6 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem nonmanifold_thickness_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_FIXED,
|
||||
"FIXED",
|
||||
0,
|
||||
"Fixed",
|
||||
"Most basic thickness calculation"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN,
|
||||
"EVEN",
|
||||
0,
|
||||
"Even",
|
||||
"Even thickness calculation which takes the angle between faces into account"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS,
|
||||
"CONSTRAINTS",
|
||||
0,
|
||||
"Constraints",
|
||||
"Thickness calculation using constraints, most advanced"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem nonmanifold_boundary_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE, "NONE", 0, "None", "No shape correction"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND,
|
||||
"ROUND",
|
||||
0,
|
||||
"Round",
|
||||
"Round open perimeter shape"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT,
|
||||
"FLAT",
|
||||
0,
|
||||
"Flat",
|
||||
"Flat open perimeter shape"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
|
@@ -10485,6 +10485,59 @@ static void def_geo_point_scale(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static const EnumPropertyItem nonmanifold_thickness_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_FIXED,
|
||||
"FIXED",
|
||||
0,
|
||||
"Fixed",
|
||||
"Most basic thickness calculation"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN,
|
||||
"EVEN",
|
||||
0,
|
||||
"Even",
|
||||
"Even thickness calculation which takes the angle between faces into account"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS,
|
||||
"CONSTRAINTS",
|
||||
0,
|
||||
"Constraints",
|
||||
"Thickness calculation using constraints, most advanced"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem nonmanifold_boundary_mode_items[] = {
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE, "NONE", 0, "None", "No shape correction"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND,
|
||||
"ROUND",
|
||||
0,
|
||||
"Round",
|
||||
"Round open perimeter shape"},
|
||||
{MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT, "FLAT", 0, "Flat", "Flat open perimeter shape"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static void def_geo_solidify(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeGeometrySolidify", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "thickness_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Thickness", "Changes the Thickness input between Float and Attribute");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "nonmanifold_offset_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, nonmanifold_thickness_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Selects the used thickness algorithm");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "nonmanifold_boundary_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, nonmanifold_boundary_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Boundary", "Selects the boundary adjustment algorithm");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_geo_point_translate(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
@@ -96,8 +96,7 @@ set(SRC
|
||||
intern/MOD_softbody.c
|
||||
intern/MOD_solidify.c
|
||||
intern/MOD_solidify_extrude.c
|
||||
intern/MOD_solidify_nonmanifold.c
|
||||
intern/MOD_subsurf.c
|
||||
intern/MOD_subsurf.c
|
||||
intern/MOD_surface.c
|
||||
intern/MOD_surfacedeform.c
|
||||
intern/MOD_triangulate.c
|
||||
@@ -130,7 +129,8 @@ set(SRC
|
||||
set(LIB
|
||||
bf_blenkernel
|
||||
bf_blenlib
|
||||
)
|
||||
bf_geometry
|
||||
)
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
|
@@ -29,22 +29,26 @@
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "GEO_solidifiy.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
#include "MOD_ui_common.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
#include "MOD_solidify_util.h"
|
||||
#include "MOD_ui_common.h"
|
||||
|
||||
static bool dependsOnNormals(ModifierData *md)
|
||||
{
|
||||
@@ -81,14 +85,154 @@ static void requiredDataMask(Object *UNUSED(ob),
|
||||
}
|
||||
}
|
||||
|
||||
static void get_distance_factor(
|
||||
Mesh *mesh, Object *ob, const char *name, bool invert, float *r_selection)
|
||||
{
|
||||
int defgrp_index = BKE_object_defgroup_name_index(ob, name);
|
||||
|
||||
if (mesh && defgrp_index != -1) {
|
||||
MDeformVert *dvert = mesh->dvert;
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
MDeformVert *dv = &dvert[i];
|
||||
r_selection[i] = BKE_defvert_find_weight(dv, defgrp_index);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
r_selection[i] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
r_selection[i] = 1.0f - r_selection[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SolidifyData solidify_data_from_modifier_data(ModifierData *md,
|
||||
const ModifierEvalContext *ctx)
|
||||
{
|
||||
const SolidifyModifierData *smd = (SolidifyModifierData *)md;
|
||||
SolidifyData solidify_data = {
|
||||
ctx->object,
|
||||
smd->offset,
|
||||
smd->offset_fac,
|
||||
smd->offset_fac_vg,
|
||||
smd->offset_clamp,
|
||||
smd->nonmanifold_offset_mode,
|
||||
smd->nonmanifold_boundary_mode,
|
||||
smd->flag,
|
||||
smd->merge_tolerance,
|
||||
smd->bevel_convex,
|
||||
NULL,
|
||||
};
|
||||
|
||||
if (!(smd->flag & MOD_SOLIDIFY_NOSHELL)) {
|
||||
solidify_data.flag |= MOD_SOLIDIFY_SHELL;
|
||||
}
|
||||
|
||||
return solidify_data;
|
||||
}
|
||||
|
||||
static Mesh *solidify_nonmanifold_modify_mesh(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
Mesh *mesh,
|
||||
const SolidifyModifierData *smd)
|
||||
{
|
||||
SolidifyData solidify_data = solidify_data_from_modifier_data(md, ctx);
|
||||
|
||||
const bool defgrp_invert = (solidify_data.flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
|
||||
float *selection = MEM_callocN(sizeof(float) * (uint64_t)mesh->totvert, __func__);
|
||||
get_distance_factor(mesh, ctx->object, smd->defgrp_name, defgrp_invert, selection);
|
||||
solidify_data.distance = selection;
|
||||
|
||||
bool *shell_verts = NULL;
|
||||
bool *rim_verts = NULL;
|
||||
bool *shell_faces = NULL;
|
||||
bool *rim_faces = NULL;
|
||||
|
||||
Mesh *output_mesh = solidify_nonmanifold(
|
||||
&solidify_data, mesh, &shell_verts, &rim_verts, &shell_faces, &rim_faces);
|
||||
|
||||
const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object,
|
||||
smd->shell_defgrp_name);
|
||||
const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name);
|
||||
|
||||
MDeformVert *dvert;
|
||||
if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
|
||||
dvert = CustomData_duplicate_referenced_layer(
|
||||
&output_mesh->vdata, CD_MDEFORMVERT, output_mesh->totvert);
|
||||
/* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
|
||||
if (dvert == NULL) {
|
||||
/* Add a valid data layer! */
|
||||
dvert = CustomData_add_layer(
|
||||
&output_mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, output_mesh->totvert);
|
||||
}
|
||||
output_mesh->dvert = dvert;
|
||||
if ((solidify_data.flag & MOD_SOLIDIFY_SHELL) && shell_defgrp_index != -1) {
|
||||
for (int i = 0; i < output_mesh->totvert; i++) {
|
||||
BKE_defvert_ensure_index(&output_mesh->dvert[i], shell_defgrp_index)->weight =
|
||||
shell_verts[i];
|
||||
}
|
||||
}
|
||||
if ((solidify_data.flag & MOD_SOLIDIFY_RIM) && rim_defgrp_index != -1) {
|
||||
for (int i = 0; i < output_mesh->totvert; i++) {
|
||||
BKE_defvert_ensure_index(&output_mesh->dvert[i], rim_defgrp_index)->weight = rim_verts[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only use material offsets if we have 2 or more materials. */
|
||||
const short mat_nrs = ctx->object->totcol > 1 ? ctx->object->totcol : 1;
|
||||
const short mat_nr_max = mat_nrs - 1;
|
||||
const short mat_ofs = mat_nrs > 1 ? smd->mat_ofs : 0;
|
||||
const short mat_ofs_rim = mat_nrs > 1 ? smd->mat_ofs_rim : 0;
|
||||
|
||||
short most_mat_nr = 0;
|
||||
uint most_mat_nr_count = 0;
|
||||
for (int mat_nr = 0; mat_nr < mat_nrs; mat_nr++) {
|
||||
uint count = 0;
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
if (mesh->mpoly[i].mat_nr == mat_nr) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > most_mat_nr_count) {
|
||||
most_mat_nr = mat_nr;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < output_mesh->totpoly; i++) {
|
||||
output_mesh->mpoly[i].mat_nr = most_mat_nr;
|
||||
if (mat_ofs > 0 && shell_faces && shell_faces[i]) {
|
||||
output_mesh->mpoly[i].mat_nr += mat_ofs;
|
||||
CLAMP(output_mesh->mpoly[i].mat_nr, 0, mat_nr_max);
|
||||
}
|
||||
else if (mat_ofs_rim > 0 && rim_faces && rim_faces[i]) {
|
||||
output_mesh->mpoly[i].mat_nr += mat_ofs_rim;
|
||||
CLAMP(output_mesh->mpoly[i].mat_nr, 0, mat_nr_max);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(selection);
|
||||
MEM_freeN(shell_verts);
|
||||
MEM_freeN(rim_verts);
|
||||
MEM_freeN(shell_faces);
|
||||
MEM_freeN(rim_faces);
|
||||
return output_mesh;
|
||||
}
|
||||
|
||||
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
|
||||
{
|
||||
const SolidifyModifierData *smd = (SolidifyModifierData *)md;
|
||||
|
||||
switch (smd->mode) {
|
||||
case MOD_SOLIDIFY_MODE_EXTRUDE:
|
||||
return MOD_solidify_extrude_modifyMesh(md, ctx, mesh);
|
||||
case MOD_SOLIDIFY_MODE_NONMANIFOLD:
|
||||
return MOD_solidify_nonmanifold_modifyMesh(md, ctx, mesh);
|
||||
case MOD_SOLIDIFY_MODE_NONMANIFOLD: {
|
||||
return solidify_nonmanifold_modify_mesh(md, ctx, mesh, smd);
|
||||
}
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
|
@@ -24,8 +24,3 @@
|
||||
Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
Mesh *mesh);
|
||||
|
||||
/* MOD_solidify_nonmanifold.c */
|
||||
Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
Mesh *mesh);
|
||||
|
@@ -174,6 +174,7 @@ void register_node_type_geo_set_position(void);
|
||||
void register_node_type_geo_set_shade_smooth(void);
|
||||
void register_node_type_geo_set_spline_cyclic(void);
|
||||
void register_node_type_geo_set_spline_resolution(void);
|
||||
void register_node_type_geo_solidify(void);
|
||||
void register_node_type_geo_string_join(void);
|
||||
void register_node_type_geo_string_to_curves(void);
|
||||
void register_node_type_geo_subdivision_surface(void);
|
||||
|
@@ -427,6 +427,7 @@ DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Se
|
||||
DefNode(GeometryNode, GEO_NODE_SET_SHADE_SMOOTH, 0, "SET_SHADE_SMOOTH", SetShadeSmooth, "Set Shade Smooth", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SET_SPLINE_CYCLIC, 0, "SET_SPLINE_CYCLIC", SetSplineCyclic, "Set Spline Cyclic", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SET_SPLINE_RESOLUTION, 0, "SET_SPLINE_RESOLUTION", SetSplineResolution, "Set Spline Resolution", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SOLIDIFY, def_geo_solidify, "SOLIDIFY", Solidify, "Solidify", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SPLIT_EDGES, 0, "SPLIT_EDGES", SplitEdges, "Split Edges", "")
|
||||
DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "Join Strings", "")
|
||||
DefNode(GeometryNode, GEO_NODE_STRING_TO_CURVES, def_geo_string_to_curves, "STRING_TO_CURVES", StringToCurves, "String to Curves", "")
|
||||
|
@@ -184,6 +184,7 @@ set(SRC
|
||||
nodes/node_geo_set_shade_smooth.cc
|
||||
nodes/node_geo_set_spline_cyclic.cc
|
||||
nodes/node_geo_set_spline_resolution.cc
|
||||
nodes/node_geo_solidify.cc
|
||||
nodes/node_geo_string_join.cc
|
||||
nodes/node_geo_string_to_curves.cc
|
||||
nodes/node_geo_subdivision_surface.cc
|
||||
|
198
source/blender/nodes/geometry/nodes/node_geo_solidify.cc
Normal file
198
source/blender/nodes/geometry/nodes/node_geo_solidify.cc
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "GEO_solidifiy.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_solidify {
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
|
||||
b.add_input<decl::Float>(N_("Thickness"))
|
||||
.default_value(0.0f)
|
||||
.subtype(PROP_DISTANCE)
|
||||
.supports_field();
|
||||
b.add_input<decl::Float>(N_("Clamp"))
|
||||
.default_value(0.0f)
|
||||
.min(0.0f)
|
||||
.max(2.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
b.add_input<decl::Float>(N_("Offset"))
|
||||
.default_value(0.0f)
|
||||
.min(-1.0f)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR);
|
||||
b.add_input<decl::Bool>(N_("Fill")).default_value(true);
|
||||
b.add_input<decl::Bool>(N_("Rim")).default_value(true);
|
||||
|
||||
b.add_output<decl::Geometry>(N_("Mesh"));
|
||||
b.add_output<decl::Bool>(N_("Fill Faces")).field_source();
|
||||
b.add_output<decl::Bool>(N_("Rim Faces")).field_source();
|
||||
}
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
uiItemR(layout, ptr, "nonmanifold_offset_mode", 0, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "nonmanifold_boundary_mode", 0, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void geo_node_solidify_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodeGeometrySolidify *node_storage = (NodeGeometrySolidify *)MEM_callocN(
|
||||
sizeof(NodeGeometrySolidify), __func__);
|
||||
|
||||
node->storage = node_storage;
|
||||
}
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
const bNode &node = params.node();
|
||||
NodeGeometrySolidify &node_storage = *(NodeGeometrySolidify *)node.storage;
|
||||
const Object *self_object = params.self_object();
|
||||
|
||||
bool add_fill = params.extract_input<bool>("Fill");
|
||||
bool add_rim = params.extract_input<bool>("Rim");
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
|
||||
|
||||
float offset = params.extract_input<float>("Offset");
|
||||
float offset_clamp = params.extract_input<float>("Clamp");
|
||||
|
||||
bke::StrongAnonymousAttributeID fill_id;
|
||||
bke::StrongAnonymousAttributeID rim_id;
|
||||
|
||||
if (geometry_set.has<MeshComponent>()) {
|
||||
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
|
||||
MeshComponent &component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
Mesh *input_mesh = component.get_for_write();
|
||||
|
||||
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
|
||||
GeometryComponentFieldContext context{component, ATTR_DOMAIN_POINT};
|
||||
|
||||
Field<float> thickness_field = params.extract_input<Field<float>>("Thickness");
|
||||
FieldEvaluator thickness_evaluator{context, domain_size};
|
||||
thickness_evaluator.add(thickness_field);
|
||||
thickness_evaluator.evaluate();
|
||||
Array<float> thickness(domain_size);
|
||||
thickness_evaluator.get_evaluated<float>(0).materialize(thickness);
|
||||
|
||||
char flag = 0;
|
||||
|
||||
if (add_fill) {
|
||||
flag |= MOD_SOLIDIFY_SHELL;
|
||||
}
|
||||
|
||||
if (add_rim) {
|
||||
flag |= MOD_SOLIDIFY_RIM;
|
||||
}
|
||||
|
||||
SolidifyData solidify_node_data = {
|
||||
self_object,
|
||||
1,
|
||||
offset,
|
||||
0.0f,
|
||||
offset_clamp,
|
||||
node_storage.nonmanifold_offset_mode,
|
||||
node_storage.nonmanifold_boundary_mode,
|
||||
flag,
|
||||
0.01f,
|
||||
0.0f,
|
||||
thickness.begin(),
|
||||
};
|
||||
|
||||
bool *shell_verts = nullptr;
|
||||
bool *rim_verts = nullptr;
|
||||
bool *shell_faces = nullptr;
|
||||
bool *rim_faces = nullptr;
|
||||
|
||||
Mesh *output_mesh = solidify_nonmanifold(
|
||||
&solidify_node_data, input_mesh, &shell_verts, &rim_verts, &shell_faces, &rim_faces);
|
||||
|
||||
if (output_mesh != input_mesh) {
|
||||
component.replace(output_mesh, GeometryOwnershipType::Editable);
|
||||
|
||||
if (params.output_is_required("Fill Faces")) {
|
||||
fill_id = StrongAnonymousAttributeID("fill_faces");
|
||||
if (add_fill) {
|
||||
OutputAttribute_Typed<bool> shell_faces_attribute =
|
||||
component.attribute_try_get_for_output_only<bool>(fill_id.get(), ATTR_DOMAIN_FACE);
|
||||
Span<bool> shell_faces_span(shell_faces, shell_faces_attribute->size());
|
||||
shell_faces_attribute->set_all(shell_faces_span);
|
||||
shell_faces_attribute.save();
|
||||
}
|
||||
}
|
||||
|
||||
if (params.output_is_required("Rim Faces")) {
|
||||
rim_id = StrongAnonymousAttributeID("rim_faces");
|
||||
if (add_rim) {
|
||||
OutputAttribute_Typed<bool> rim_faces_attribute =
|
||||
component.attribute_try_get_for_output_only<bool>(rim_id.get(), ATTR_DOMAIN_FACE);
|
||||
Span<bool> rim_faces_span(rim_faces, rim_faces_attribute->size());
|
||||
rim_faces_attribute->set_all(rim_faces_span);
|
||||
rim_faces_attribute.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(shell_verts);
|
||||
MEM_freeN(rim_verts);
|
||||
MEM_freeN(shell_faces);
|
||||
MEM_freeN(rim_faces);
|
||||
});
|
||||
}
|
||||
if (fill_id) {
|
||||
params.set_output("Fill Faces",
|
||||
AnonymousAttributeFieldInput::Create<bool>(
|
||||
std::move(fill_id), params.attribute_producer_name()));
|
||||
}
|
||||
if (rim_id) {
|
||||
params.set_output("Rim Faces",
|
||||
AnonymousAttributeFieldInput::Create<bool>(
|
||||
std::move(rim_id), params.attribute_producer_name()));
|
||||
}
|
||||
|
||||
params.set_output("Mesh", geometry_set);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_geo_solidify
|
||||
|
||||
void register_node_type_geo_solidify()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_geo_solidify;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, GEO_NODE_SOLIDIFY, "Solidify", NODE_CLASS_GEOMETRY);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
node_type_storage(
|
||||
&ntype, "NodeGeometrySolidify", node_free_standard_storage, node_copy_standard_storage);
|
||||
node_type_init(&ntype, file_ns::geo_node_solidify_init);
|
||||
node_type_size(&ntype, 172, 100, 600);
|
||||
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Reference in New Issue
Block a user