Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component Analyzer Vertex normal modes #4039

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/nodes/analyzer/component_analyzer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ This node has the following parameters:

* For **Vertices** supported criteria are:

* **Normal**. Vertices normal vector.
* **Normal**. Vertices normal vector. Offers different calculation methods:
Bmesh (standard Blender),Mean Weighted Equally (Faster), Mean Weighted Based on Triangle Area
Mean Weighted Edge Length Reciprocal and Mean Weighted by Sine
* **Matrix ZY**: Matrix aligned with normal.
* **Sharpness**: Curvature of mesh in vertex.
* **Adjacent Edges**: Adjacent edges.
Expand Down
16 changes: 15 additions & 1 deletion nodes/analyzer/component_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
'n': ('matrix_normal', 'e'),
't': ('tangent_mode', 'e'),
'a': ('output_numpy', 'b'),
'v': ('vertex_normal_mode', 'e'),
}


Expand Down Expand Up @@ -99,7 +100,13 @@ class SvComponentAnalyzerNode(bpy.types.Node, SverchCustomTreeNode, SvRecursiveN
("X", "X", "Aligned with X", 0),
("Z", "Z", "Aligned with Z", 2),
]

vertex_normal_modes = [
('BMESH', 'Bmesh', 'Slower (Legacy)', 0),
('MWE', 'Mean Weighted Equally', 'Faster', 1),
('MWELR','Mean Weighted Edge Length Reciprocal', '', 2),
('MWAT', 'Mean Weighted Area Triangle', '', 3),
('MWS', 'Mean Weighted by Sine', '', 4)
]

@throttle_and_update_node
def update_mode(self, context):
Expand Down Expand Up @@ -194,6 +201,12 @@ def update_mode(self, context):
default="Median_Center",
update=update_mode)

vertex_normal_mode: EnumProperty(
name="Method",
items=vertex_normal_modes,
default="MWE",
update=update_mode)

matrix_track: EnumProperty(
name="Normal",
items=matrix_track_modes,
Expand Down Expand Up @@ -362,6 +375,7 @@ def process_data(self, params):
'u': self.matrix_normal_up,
'n': self.matrix_normal,
't': self.tangent_mode,
'v': self.vertex_normal_mode,
'a': self.output_numpy
}
special_op = []
Expand Down
41 changes: 28 additions & 13 deletions utils/modules/vertex_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ def adjacent_edg_pol_idx(verts, edgs_pols):
faces: list as [polygon, polygon,..], being each polygon [int, int, ...].
returns value of each vertex as [value, value,...]
'''
def vertex_normal(vertices, edges, faces, output_numpy=True):
if len(faces) == 0:
bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
def vertex_normal(vertices, faces, algorithm='MWE', output_numpy=True):
if len(faces) == 0 or algorithm == 'BMESH':
bm = bmesh_from_pydata(vertices, [], faces, normal_update=True)
vals = [tuple(v.normal) for v in bm.verts]
bm.free()
return vals

return np_vertex_normals(vertices, faces, output_numpy=output_numpy)
return np_vertex_normals(vertices, faces, algorithm, output_numpy=output_numpy)

def np_faces_normals(v_pols):
pol_sides = v_pols.shape[1]
Expand All @@ -108,8 +108,27 @@ def np_faces_normals(v_pols):
np_normalize_vectors(f_normals)

return f_normals
# based in this article https://www.researchgate.net/publication/220067106_A_comparison_of_algorithms_for_vertex_normal_computation
def add_faces_normals(v_pols, np_faces_g, algorithm, pol_sides, v_normals):
if algorithm in ('MWE', 'MWAT'):
if algorithm == 'MWE': #weighted equally
f_normal_g = np_normalize_vectors(np_faces_normals(v_pols))
else: #weighted by area of triangle
f_normal_g = np_faces_normals(v_pols)
for i in range(pol_sides):
np.add.at(v_normals, np_faces_g[:, i], f_normal_g)
else:
if algorithm == 'MWELR': #weighted edge length reciprocal
f_normal_g = np_normalize_vectors(np_faces_normals(v_pols))
else: # algorithm == 'MWS': #weighted by sine
f_normal_g = np_faces_normals(v_pols)
edges_length = np.linalg.norm(v_pols - np.roll(v_pols, 1, axis=1), axis=2)
factor = edges_length * np.roll(edges_length, -1, axis=1)

for i in range(pol_sides):
np.add.at(v_normals, np_faces_g[:, i], f_normal_g * factor[:, i, np.newaxis])

def np_vertex_normals(vertices, faces, output_numpy=False):
def np_vertex_normals(vertices, faces, algorithm='MWE', output_numpy=False):

if isinstance(vertices, np.ndarray):
np_verts = vertices
Expand All @@ -131,17 +150,13 @@ def np_vertex_normals(vertices, faces, output_numpy=False):
mask = lens == pol_sides
np_faces_g = np.array(np_faces[mask].tolist())
v_pols = np_verts[np_faces_g]
f_normal_g = np_normalize_vectors(np_faces_normals(v_pols))

for i in range(pol_sides):
np.add.at(v_normals, np_faces_g[:, i], f_normal_g)
add_faces_normals(v_pols, np_faces_g, algorithm, pol_sides, v_normals)

else:
pol_sides = np_faces.shape[1]
v_pols = np_verts[np_faces]
f_normal_g = np_normalize_vectors(np_faces_normals(v_pols))
for i in range(pol_sides):
np.add.at(v_normals, np_faces[:, i], f_normal_g)
add_faces_normals(v_pols, np_faces, algorithm, pol_sides, v_normals)


if output_numpy:
return np_normalize_vectors(v_normals)
Expand Down Expand Up @@ -205,7 +220,7 @@ def vertex_matrix(vertices, edges, faces, track, up):

# Name: (index, input_sockets, func_options, output_options, function, output_sockets, output_sockets_names, description)
vertex_modes_dict = {
'Normal': (0, 'vep', 'a', '', vertex_normal, 'v', 'Normal', 'Vertex normal'),
'Normal': (0, 'vp', 'va', '', vertex_normal, 'v', 'Normal', 'Vertex normal'),
'Matrix': (10, 'vep', 'mu', 'u', vertex_matrix, 'm', 'Matrix', 'Matrix aligned with normal'),
'Sharpness': (20, 'vep', '', '', vertex_shell_factor, 's', 'Sharpness', 'Curvature of mesh in vertex'),
'Adjacent edges': (30, 've', '', 'u', adjacent_edg_pol, 's', 'Edges', 'Adjacent edges'),
Expand Down