From 1c1f5471fbeaad1a9c583f759beece2e8cae95f5 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 18 Jan 2015 12:31:59 +0500 Subject: [PATCH 1/9] Implementation of Mk2 of Matrix Apply node. refs portnov#9 --- menu.py | 1 + nodes/__init__.py | 1 + nodes/matrix/apply_and_join.py | 89 ++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 nodes/matrix/apply_and_join.py diff --git a/menu.py b/menu.py index adda70bea..f0a76fcdb 100644 --- a/menu.py +++ b/menu.py @@ -237,6 +237,7 @@ def make_node_cats(): ['SvBricksNode', 'Bricks grid'], ["SvRandomizeVerticesNode", "Randomize input vertices"], ["SvDuplicateAlongEdgeNode", "Duplicate objects along edge"], + ["MatrixApplyJoinNode", "Apply matrix to mesh"], ["SvIterateNode", "Iterate matrix transformation"], ] diff --git a/nodes/__init__.py b/nodes/__init__.py index 7a398b8d1..bb26b6318 100644 --- a/nodes/__init__.py +++ b/nodes/__init__.py @@ -100,6 +100,7 @@ nodes_dict = { 'matrix': [ 'apply', + 'apply_and_join', 'deform', 'destructor', 'generator', diff --git a/nodes/matrix/apply_and_join.py b/nodes/matrix/apply_and_join.py new file mode 100644 index 000000000..ae44a681f --- /dev/null +++ b/nodes/matrix/apply_and_join.py @@ -0,0 +1,89 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy +from mathutils import Matrix, Vector + +from sverchok.node_tree import SverchCustomTreeNode, VerticesSocket, MatrixSocket +from sverchok.data_structure import (Vector_generate, Vector_degenerate, + Matrix_generate, updateNode, + SvGetSocketAnyType, SvSetSocketAnyType) + + +class MatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): + ''' Multiply vectors on matrices with several objects in output, + and process edges & faces too ''' + bl_idname = 'MatrixApplyJoinNode' + bl_label = 'Apply matrix to mesh' + bl_icon = 'OUTLINER_OB_EMPTY' + + def sv_init(self, context): + self.inputs.new('VerticesSocket', "Vertices") + self.inputs.new('StringsSocket', "Edges") + self.inputs.new('StringsSocket', "Faces") + self.inputs.new('MatrixSocket', "Matrices") + + self.outputs.new('VerticesSocket', "Vertices") + self.outputs.new('StringsSocket', "Edges") + self.outputs.new('StringsSocket', "Faces") + + def process(self): + if not self.outputs['Vertices'].is_linked: + return + + vertices = self.inputs['Vertices'].sv_get() + vertices = Vector_generate(vertices) + edges = self.inputs['Edges'].sv_get(default=[[]]) + faces = self.inputs['Faces'].sv_get(default=[[]]) + + matrices = self.inputs['Matrices'].sv_get() + matrices = Matrix_generate(matrices) + n = len(matrices) + + result_vertices = self.apply(vertices, matrices) + result_vertices = Vector_degenerate(result_vertices) + + result_edges = edges * n + result_faces = faces * n + + self.outputs['Vertices'].sv_set(result_vertices) + if self.outputs['Edges'].is_linked: + self.outputs['Edges'].sv_set(result_edges) + if self.outputs['Faces'].is_linked: + self.outputs['Faces'].sv_set(result_faces) + + def apply(self, vecs, mats): + out = [] + lengthve = len(vecs)-1 + for i, m in enumerate(mats): + out_ = [] + k = i + if k > lengthve: + k = lengthve + for v in vecs[k]: + out_.append(m*v) + out.append(out_) + return out + +def register(): + bpy.utils.register_class(MatrixApplyJoinNode) + + +def unregister(): + bpy.utils.unregister_class(MatrixApplyJoinNode) + -- GitLab From 8f47bf829ef84ef69c07db3912b136afca5d85e0 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 18:05:38 +0500 Subject: [PATCH 2/9] Rename MatrixApplyJoinNode to SvMatrixApplyJoinNode. refs #563 --- menu.py | 2 +- nodes/matrix/apply_and_join.py | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/menu.py b/menu.py index f0a76fcdb..773044962 100644 --- a/menu.py +++ b/menu.py @@ -237,7 +237,7 @@ def make_node_cats(): ['SvBricksNode', 'Bricks grid'], ["SvRandomizeVerticesNode", "Randomize input vertices"], ["SvDuplicateAlongEdgeNode", "Duplicate objects along edge"], - ["MatrixApplyJoinNode", "Apply matrix to mesh"], + ["SvMatrixApplyJoinNode", "Apply matrix to mesh"], ["SvIterateNode", "Iterate matrix transformation"], ] diff --git a/nodes/matrix/apply_and_join.py b/nodes/matrix/apply_and_join.py index ae44a681f..ce2688648 100644 --- a/nodes/matrix/apply_and_join.py +++ b/nodes/matrix/apply_and_join.py @@ -21,14 +21,13 @@ from mathutils import Matrix, Vector from sverchok.node_tree import SverchCustomTreeNode, VerticesSocket, MatrixSocket from sverchok.data_structure import (Vector_generate, Vector_degenerate, - Matrix_generate, updateNode, - SvGetSocketAnyType, SvSetSocketAnyType) + Matrix_generate, updateNode) -class MatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): +class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): ''' Multiply vectors on matrices with several objects in output, and process edges & faces too ''' - bl_idname = 'MatrixApplyJoinNode' + bl_idname = 'SvMatrixApplyJoinNode' bl_label = 'Apply matrix to mesh' bl_icon = 'OUTLINER_OB_EMPTY' @@ -81,9 +80,9 @@ class MatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): return out def register(): - bpy.utils.register_class(MatrixApplyJoinNode) + bpy.utils.register_class(SvMatrixApplyJoinNode) def unregister(): - bpy.utils.unregister_class(MatrixApplyJoinNode) + bpy.utils.unregister_class(SvMatrixApplyJoinNode) -- GitLab From a47273cdcae30d61cca96a3212095ab32fd4761b Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 18:34:12 +0500 Subject: [PATCH 3/9] Documentation for `Apply matrix to mesh` node. refs #563. --- docs/nodes/beta/beta.rst | 1 + docs/nodes/beta/matrix_apply_and_join.rst | 37 +++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/nodes/beta/matrix_apply_and_join.rst diff --git a/docs/nodes/beta/beta.rst b/docs/nodes/beta/beta.rst index e001caa60..774646a49 100644 --- a/docs/nodes/beta/beta.rst +++ b/docs/nodes/beta/beta.rst @@ -16,6 +16,7 @@ Beta ngon bricks randomize + matrix_apply_and_join objects_along_edge extrude_separate iterate diff --git a/docs/nodes/beta/matrix_apply_and_join.rst b/docs/nodes/beta/matrix_apply_and_join.rst new file mode 100644 index 000000000..6832f511f --- /dev/null +++ b/docs/nodes/beta/matrix_apply_and_join.rst @@ -0,0 +1,37 @@ +Apply Matrix to Mesh +==================== + +Functionality +------------- + +Applies a Transform Matrix to a list or nested lists of vertices, edges and faces. If several matrices are provided on the input, then this node will produce several meshes. + + +Inputs +------ + +This node has the following inputs: + +- **Vertices**. Represents vertices or intermediate vectors used for further vector math. +- **Edges** +- **Faces** +- **Matrices**. One or more, never empty. + +Outputs +------- + +This node has the following outputs: + +- **Vertices**. Nested list of vectors / vertices, matching the number nested incoming *matrices*. +- **Edges**. Input edges list, repeated the number of incoming matrices. Empty if corresponding input is empty. +- **Faces**. Input faces list, repeated the number of incoming matrices. Empty if corresponding input is empty. + +So if N matrices are provided at the input, then this node will produce N lists of vertices, N lists of edges and N lists of faces. + +Examples +-------- + +.. image:: https://cloud.githubusercontent.com/assets/284644/6096652/ac13659e-afbf-11e4-83c9-e13b75c0e346.png + +.. image:: https://cloud.githubusercontent.com/assets/284644/6096654/b300fbfa-afbf-11e4-901b-1361a44238c2.png + -- GitLab From 6427cfff996bdf49200bf1aab5d7ab3b16db83b6 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 18:41:21 +0500 Subject: [PATCH 4/9] Update documentation. refs #563 --- docs/nodes/beta/matrix_apply_and_join.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/nodes/beta/matrix_apply_and_join.rst b/docs/nodes/beta/matrix_apply_and_join.rst index 6832f511f..e40f90fb0 100644 --- a/docs/nodes/beta/matrix_apply_and_join.rst +++ b/docs/nodes/beta/matrix_apply_and_join.rst @@ -6,6 +6,8 @@ Functionality Applies a Transform Matrix to a list or nested lists of vertices, edges and faces. If several matrices are provided on the input, then this node will produce several meshes. +**Note**. Unless there is further processing going on which explicitly require the duplicated topology, then letting the ``Viewer Draw`` or ``BMesh Viewer`` nodes automatically repeat the index lists for the edges and faces is slightly more efficient than use of this node. + Inputs ------ -- GitLab From 5202dc496c8bb839d2cbe206fb6c6ce4116376c6 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 21:58:08 +0500 Subject: [PATCH 5/9] Factor internal functionality of MeshJoin node out to sv_mesh_utils module. refs #566 --- nodes/modifier_change/mesh_join.py | 22 ++++++----------- utils/sv_mesh_utils.py | 38 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 utils/sv_mesh_utils.py diff --git a/nodes/modifier_change/mesh_join.py b/nodes/modifier_change/mesh_join.py index 95ff43ac0..2a9d3e409 100644 --- a/nodes/modifier_change/mesh_join.py +++ b/nodes/modifier_change/mesh_join.py @@ -22,6 +22,7 @@ import bpy from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import SvSetSocketAnyType, SvGetSocketAnyType +from sverchok.utils.sv_mesh_utils import mesh_join class SvMeshJoinNode(bpy.types.Node, SverchCustomTreeNode): @@ -42,25 +43,16 @@ class SvMeshJoinNode(bpy.types.Node, SverchCustomTreeNode): if 'Vertices' in self.inputs and self.inputs['Vertices'].is_linked and \ 'PolyEdge' in self.inputs and self.inputs['PolyEdge'].is_linked: - verts = SvGetSocketAnyType(self, self.inputs['Vertices']) - poly_edge = SvGetSocketAnyType(self, self.inputs['PolyEdge']) - verts_out = [] - poly_edge_out = [] - offset = 0 - for obj in zip(verts, poly_edge): - verts_out.extend(obj[0]) - if offset: - res = [list(map(lambda x:operator.add(offset, x), ep)) for ep in obj[1]] - poly_edge_out.extend(res) - else: - poly_edge_out.extend(obj[1]) - offset += len(obj[0]) + verts = self.inputs['Vertices'].sv_get() + poly_edge = self.inputs['PolyEdge'].sv_get() + + verts_out, dummy, poly_edge_out = mesh_join(verts, [], poly_edge) if 'Vertices' in self.outputs and self.outputs['Vertices'].is_linked: - SvSetSocketAnyType(self, 'Vertices', [verts_out]) + self.outputs['Vertices'].sv_set([verts_out]) if 'PolyEdge' in self.outputs and self.outputs['PolyEdge'].is_linked: - SvSetSocketAnyType(self, 'PolyEdge', [poly_edge_out]) + self.outputs['PolyEdge'].sv_set([poly_edge_out]) def update_socket(self, context): self.update() diff --git a/utils/sv_mesh_utils.py b/utils/sv_mesh_utils.py new file mode 100644 index 000000000..3325ffb7c --- /dev/null +++ b/utils/sv_mesh_utils.py @@ -0,0 +1,38 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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. +# +# ##### END GPL LICENSE BLOCK ##### + +def mesh_join(vertices_s, edges_s, faces_s): + '''Given list of meshes represented by lists of vertices, edges and faces, + produce one joined mesh.''' + + print("Mesh_join") + + offset = 0 + result_vertices = [] + result_edges = [] + result_faces = [] + if len(edges_s) == 0: + edges_s = [[]] * len(faces_s) + for vertices, edges, faces in zip(vertices_s, edges_s, faces_s): + result_vertices.extend(vertices) + new_edges = [tuple(i + offset for i in edge) for edge in edges] + new_faces = [[i + offset for i in face] for face in faces] + result_edges.extend(new_edges) + result_faces.extend(new_faces) + offset += len(vertices) + return result_vertices, result_edges, result_faces -- GitLab From 98d947119518d30b4d22e329ee1da6139d4ac2e3 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 22:03:41 +0500 Subject: [PATCH 6/9] Add an option to join resulting meshes into one. refs #566 --- nodes/matrix/apply_and_join.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nodes/matrix/apply_and_join.py b/nodes/matrix/apply_and_join.py index ce2688648..073860feb 100644 --- a/nodes/matrix/apply_and_join.py +++ b/nodes/matrix/apply_and_join.py @@ -17,11 +17,13 @@ # ##### END GPL LICENSE BLOCK ##### import bpy +from bpy.props import BoolProperty from mathutils import Matrix, Vector from sverchok.node_tree import SverchCustomTreeNode, VerticesSocket, MatrixSocket from sverchok.data_structure import (Vector_generate, Vector_degenerate, Matrix_generate, updateNode) +from sverchok.utils.sv_mesh_utils import mesh_join class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): @@ -31,6 +33,11 @@ class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): bl_label = 'Apply matrix to mesh' bl_icon = 'OUTLINER_OB_EMPTY' + do_join = BoolProperty(name='Join', + description = 'Join resulting meshes to one mesh', + default=True, + update=updateNode) + def sv_init(self, context): self.inputs.new('VerticesSocket', "Vertices") self.inputs.new('StringsSocket', "Edges") @@ -41,6 +48,9 @@ class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): self.outputs.new('StringsSocket', "Edges") self.outputs.new('StringsSocket', "Faces") + def draw_buttons(self, context, layout): + layout.prop(self, "do_join") + def process(self): if not self.outputs['Vertices'].is_linked: return @@ -60,6 +70,9 @@ class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): result_edges = edges * n result_faces = faces * n + if self.do_join: + result_vertices, result_edges, result_faces = mesh_join(result_vertices, result_edges, result_faces) + self.outputs['Vertices'].sv_set(result_vertices) if self.outputs['Edges'].is_linked: self.outputs['Edges'].sv_set(result_edges) -- GitLab From 84c668cd34b191e47d0aad8b70222289c46b5b1d Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 22:06:22 +0500 Subject: [PATCH 7/9] Remove debug output. --- utils/sv_mesh_utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/utils/sv_mesh_utils.py b/utils/sv_mesh_utils.py index 3325ffb7c..61a97955d 100644 --- a/utils/sv_mesh_utils.py +++ b/utils/sv_mesh_utils.py @@ -20,8 +20,6 @@ def mesh_join(vertices_s, edges_s, faces_s): '''Given list of meshes represented by lists of vertices, edges and faces, produce one joined mesh.''' - print("Mesh_join") - offset = 0 result_vertices = [] result_edges = [] -- GitLab From a0f2f2efc0581e37b4e884979743166352be1e00 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 22:25:09 +0500 Subject: [PATCH 8/9] Don't do unnesessary computations if outputs are not linked. refs #566 --- nodes/matrix/apply_and_join.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/nodes/matrix/apply_and_join.py b/nodes/matrix/apply_and_join.py index 073860feb..4bd2c4802 100644 --- a/nodes/matrix/apply_and_join.py +++ b/nodes/matrix/apply_and_join.py @@ -67,17 +67,19 @@ class SvMatrixApplyJoinNode(bpy.types.Node, SverchCustomTreeNode): result_vertices = self.apply(vertices, matrices) result_vertices = Vector_degenerate(result_vertices) - result_edges = edges * n - result_faces = faces * n + self.outputs['Vertices'].sv_set(result_vertices) - if self.do_join: - result_vertices, result_edges, result_faces = mesh_join(result_vertices, result_edges, result_faces) + if self.outputs['Edges'].is_linked or self.outputs['Faces'].is_linked: + result_edges = edges * n + result_faces = faces * n - self.outputs['Vertices'].sv_set(result_vertices) - if self.outputs['Edges'].is_linked: - self.outputs['Edges'].sv_set(result_edges) - if self.outputs['Faces'].is_linked: - self.outputs['Faces'].sv_set(result_faces) + if self.do_join: + result_vertices, result_edges, result_faces = mesh_join(result_vertices, result_edges, result_faces) + + if self.outputs['Edges'].is_linked: + self.outputs['Edges'].sv_set(result_edges) + if self.outputs['Faces'].is_linked: + self.outputs['Faces'].sv_set(result_faces) def apply(self, vecs, mats): out = [] -- GitLab From fbbd33f28e9b35fe38d2f89da40abea6b8459cfb Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Sun, 8 Feb 2015 22:28:34 +0500 Subject: [PATCH 9/9] Update documentation. refs #566 --- docs/nodes/beta/matrix_apply_and_join.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/nodes/beta/matrix_apply_and_join.rst b/docs/nodes/beta/matrix_apply_and_join.rst index e40f90fb0..3cb6e7bd3 100644 --- a/docs/nodes/beta/matrix_apply_and_join.rst +++ b/docs/nodes/beta/matrix_apply_and_join.rst @@ -19,6 +19,14 @@ This node has the following inputs: - **Faces** - **Matrices**. One or more, never empty. +Parameters +---------- + +This node has the following parameter: + +**Join**. If set, then this node will join output meshes into one mesh, the same way as ``Mesh Join`` node does. +Otherwise, if N matrices are provided at the input, this node will produce N lists of vertices, N lists of edges and N lists of faces. + Outputs ------- @@ -28,8 +36,6 @@ This node has the following outputs: - **Edges**. Input edges list, repeated the number of incoming matrices. Empty if corresponding input is empty. - **Faces**. Input faces list, repeated the number of incoming matrices. Empty if corresponding input is empty. -So if N matrices are provided at the input, then this node will produce N lists of vertices, N lists of edges and N lists of faces. - Examples -------- -- GitLab