diff --git a/docs/nodes/analyzer/raycast.rst b/docs/nodes/analyzer/raycast.rst index 5cea55158ccd5f0a800e1943561c8ffbefb3f1ad..415e77c11495b093bf40ba1f128006da65d121d4 100644 --- a/docs/nodes/analyzer/raycast.rst +++ b/docs/nodes/analyzer/raycast.rst @@ -33,9 +33,6 @@ Parameters | | | | | In **world_space** mode: node works like ``bpy.types.Scene.ray_cast``. | +-----------------+--------------------------------------------------------------------------------------------------+ -| iteration modes | Method that achieve the same amount of Start and End vectors. "match short"- cuts that list that | -| | was longer, "match long repeat"- repeats the last element of the list that was shorter | -+-----------------+--------------------------------------------------------------------------------------------------+ Output sockets diff --git a/menu.py b/menu.py index a4d25b73b0e4c23d8bc50bbdce52f61a0d11cd57..1be41cdd8410787c0a153e2b2e149150dd7f6ea1 100644 --- a/menu.py +++ b/menu.py @@ -216,7 +216,8 @@ def make_node_cats(): ["SvGetPropNode", "Get property", 'FORCE_VORTEX'], ["SvSetPropNode", "Set property", 'FORCE_VORTEX'], ["SvVertexGroupNode", "Vertext group"], - ["SvRayCastNode", "Raycast"], + ["SvRayCastSceneNode", "Scene Raycast"], + ["SvRayCastObjectNode", "Object Raycast"], ["SvVertexColorNode", "Vertext color"], ] diff --git a/nodes/__init__.py b/nodes/__init__.py index 38ca813c8332ac27f9925159c69f9860ef0f850a..9727d836eb97ab5ba27d9d81a3ba7ac2ae25a71b 100644 --- a/nodes/__init__.py +++ b/nodes/__init__.py @@ -13,7 +13,8 @@ nodes_dict = { 'kd_tree', 'kd_tree_edges', 'weights', - 'raycast', + 'object_raycast', + 'scene_raycast', 'bmesh_props', 'closest_point_on_mesh', 'colors' diff --git a/nodes/analyzer/object_raycast.py b/nodes/analyzer/object_raycast.py new file mode 100644 index 0000000000000000000000000000000000000000..d4e269a564d7321c62d7233439249fcefaac357e --- /dev/null +++ b/nodes/analyzer/object_raycast.py @@ -0,0 +1,101 @@ +# ##### 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 +import mathutils +from mathutils import Vector +from bpy.props import BoolProperty +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import (updateNode, match_long_repeat) + + +class SvRayCastNode(bpy.types.Node, SverchCustomTreeNode): + ''' RayCast Object ''' + bl_idname = 'SvRayCastObjectNode' + bl_label = 'object_raycast' + bl_icon = 'OUTLINER_OB_EMPTY' + + mode = BoolProperty(name='input mode', default=False, update=updateNode) + mode2 = BoolProperty(name='output mode', default=False, update=updateNode) + + def sv_init(self, context): + si = self.inputs.new + so = self.outputs.new + si('StringsSocket', 'Objects') + si('VerticesSocket', 'start').use_prop = True + si('VerticesSocket', 'end').use_prop = True + so('VerticesSocket', "HitP") + so('VerticesSocket', "HitNorm") + so('StringsSocket', "FaceINDEX") + + def draw_buttons_ext(self, context, layout): + row = layout.row(align=True) + row.prop(self, "mode", text="In Mode") + row.prop(self, "mode2", text="Out Mode") + + def process(self): + outfin = [] + OutLoc = [] + OutNorm = [] + IND = [] + st = self.inputs['start'].sv_get()[0] + en = self.inputs['end'].sv_get()[0] + + if len(st) != len(en): + st, en = match_long_repeat([st, en]) + + obj = self.inputs['Objects'].sv_get() + for OB in obj: + out = [] + if self.mode: + i = 0 + obmat = OB.matrix_local.inverted() + while i < len(en): + out.append(OB.ray_cast(obmat*Vector(st[i]), obmat*Vector(en[i]))) + i = i+1 + else: + i = 0 + while i < len(en): + out.append(OB.ray_cast(st[i], en[i])) + i = i+1 + outfin.append(out) + + g = 0 + while g < len(obj): + omw = obj[g].matrix_world + for i in outfin[g]: + OutNorm.append(i[1][:]) + IND.append(i[2]) + OutLoc.append((omw*i[0])[:] if self.mode2 else i[0][:]) + g = g+1 + + so = self.outputs + so['HitP'].sv_set([OutLoc]) + so['HitNorm'].sv_set([OutNorm]) + so['FaceINDEX'].sv_set([IND]) + + def update_socket(self, context): + self.update() + + +def register(): + bpy.utils.register_class(SvRayCastNode) + + +def unregister(): + bpy.utils.unregister_class(SvRayCastNode) diff --git a/nodes/analyzer/raycast.py b/nodes/analyzer/raycast.py deleted file mode 100644 index 5bdd6e8fa06aa16a67f3126f621be5e1cfb9863b..0000000000000000000000000000000000000000 --- a/nodes/analyzer/raycast.py +++ /dev/null @@ -1,161 +0,0 @@ -# ##### 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 -import parser -import mathutils -from mathutils import Vector -from bpy.props import StringProperty, BoolProperty, EnumProperty -from sverchok.node_tree import SverchCustomTreeNode, StringsSocket, VerticesSocket, \ - MatrixSocket -from sverchok.data_structure import (updateNode, Vector_generate, SvSetSocketAnyType, - SvGetSocketAnyType, match_short, match_long_repeat) - - -class SvRayCastNode(bpy.types.Node, SverchCustomTreeNode): - ''' RayCast Object ''' - bl_idname = 'SvRayCastNode' - bl_label = 'raycast' - bl_icon = 'OUTLINER_OB_EMPTY' - - modes = [ - ("Object", "object_space", "", 1), - ("World", "world_space", "", 2), - ] - - Itermodes = [ - ("match_short", "match_short", "", 1), - ("match_long_repeat", "match_long_repeat", "", 2), - ] - - Modes = EnumProperty(name="Raycast modes", description="Raycast modes", - default="Object", items=modes, update=updateNode) - Iteration = EnumProperty(name="iteration modes", - description="Iteration modes", - default="match_short", items=Itermodes, - update=updateNode) - formula = StringProperty(name='formula', - description='name of object to operate on \ - ("object_space" mode only)', default='Cube', - update=updateNode) - - def draw_buttons(self, context, layout): - if self.Modes == 'Object': - layout.prop(self, "formula", text="") - row = layout.row(align=True) - layout.prop(self, "Modes", "Raycast modes") - layout.prop(self, "Iteration", "Iteration modes") - - def sv_init(self, context): - self.inputs.new('VerticesSocket', 'start', 'start') - self.inputs.new('VerticesSocket', 'end', 'end') - self.outputs.new('VerticesSocket', "HitP", "HitP") - self.outputs.new('VerticesSocket', "HitNorm", "HitNorm") - self.outputs.new('StringsSocket', "INDEX/Succes", "INDEX/Succes") - - def process(self): - start_links = self.inputs['start'].links - if not (start_links and (type(start_links[0].from_socket) == - VerticesSocket)): - return - - end_links = self.inputs['end'].links - if not (end_links and (type(end_links[0].from_socket) == - VerticesSocket)): - return - - - SSSAT = SvSetSocketAnyType - bcsrc = bpy.context.scene.ray_cast - outputs = self.outputs - out = [] - OutLoc = [] - OutNorm = [] - INDSucc = [] - OutMatrix = [] - ObjectID = [] - - st = Vector_generate(SvGetSocketAnyType(self, self.inputs['start'])) - en = Vector_generate(SvGetSocketAnyType(self, self.inputs['end'])) - start = [Vector(x) for x in st[0]] - end = [Vector(x) for x in en[0]] - if self.Iteration == 'match_short': - temp = match_short([start, end]) - start, end = temp[0], temp[1] - if self.Iteration == 'match_long_repeat': - temp = match_long_repeat([start, end]) - start, end = temp[0], temp[1] - - if self.Modes == 'Object' and (self.formula in bpy.data.objects): - - if 'data.object' in outputs: - outputs.remove(outputs['data.object']) - - if 'hited object matrix' in outputs: - outputs.remove(outputs['hited object matrix']) - - obj = bpy.data.objects[self.formula] - i = 0 - while i < len(end): - out.append(obj.ray_cast(start[i], end[i])) - i = i+1 - for i in out: - OutNorm.append(i[1][:]) - INDSucc.append(i[2]) - OutLoc.append(i[0][:]) - - if self.Modes == 'World': - - if 'data.object' not in outputs: - outputs.new("VerticesSocket", "data.object") - if 'hited object matrix' not in outputs: - outputs.new("MatrixSocket", "hited object matrix") - - for i, last in enumerate(end): - src = bcsrc(start[i], last) - OutLoc.append(src[3][:]) - OutNorm.append(src[4][:]) - INDSucc.append(src[0]) - OutMatrix.append(src[2][:]) - OutMatrix = [[a[:], b[:], c[:], d[:]] for a, b, c, d in - OutMatrix] - ObjectID.append(src[1]) - - if outputs['HitP'].links: - SSSAT(self, 'HitP', [OutLoc]) - if outputs['HitNorm'].links: - SSSAT(self, 'HitNorm', [OutNorm]) - if outputs['INDEX/Succes'].links: - SSSAT(self, 'INDEX/Succes', [INDSucc]) - if 'hited object matrix' in outputs: - if outputs['hited object matrix'].links: - SSSAT(self, 'hited object matrix', OutMatrix) - if 'data.object' in outputs: - if outputs['data.object'].links: - SSSAT(self, 'data.object', [ObjectID]) - - def update_socket(self, context): - self.update() - - -def register(): - bpy.utils.register_class(SvRayCastNode) - - -def unregister(): - bpy.utils.unregister_class(SvRayCastNode) diff --git a/nodes/analyzer/scene_raycast.py b/nodes/analyzer/scene_raycast.py new file mode 100644 index 0000000000000000000000000000000000000000..5ee624ddbc9fac81753daaeb8bf7143d3c7d52cb --- /dev/null +++ b/nodes/analyzer/scene_raycast.py @@ -0,0 +1,78 @@ +# ##### 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 sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import (updateNode, match_long_repeat) + + +class SvRayCastNode(bpy.types.Node, SverchCustomTreeNode): + ''' RayCast Scene ''' + bl_idname = 'SvRayCastSceneNode' + bl_label = 'scene_raycast' + bl_icon = 'OUTLINER_OB_EMPTY' + + def sv_init(self, context): + sin = self.inputs.new + so = self.outputs.new + sin('VerticesSocket', 'start').use_prop = True + sin('VerticesSocket', 'end').use_prop = True + so('VerticesSocket', "HitP") + so('VerticesSocket', "HitNorm") + so('StringsSocket', "Succes") + so("StringsSocket", "Objects") + so("MatrixSocket", "hited object matrix") + + def process(self): + so = self.outputs + OutLoc = [] + OutNorm = [] + Succ = [] + ObjectID = [] + OutMatrix = [] + st = self.inputs['start'].sv_get()[0] + en = self.inputs['end'].sv_get()[0] + + if len(st) != len(en): + st, en = match_long_repeat([st, en]) + + for i, last in enumerate(en): + rc = bpy.context.scene.ray_cast(st[i], last) + OutLoc.append(rc[3][:]) + OutNorm.append(rc[4][:]) + Succ.append(rc[0]) + ObjectID.append(rc[1]) + if so['hited object matrix'].is_linked: + OutMatrix.append([[a[:], b[:], c[:], d[:]] for a, b, c, d in [rc[2][:]]]) + + so['HitP'].sv_set([OutLoc]) + so['HitNorm'].sv_set([OutNorm]) + so['Succes'].sv_set([Succ]) + so['Objects'].sv_set(ObjectID) + so['hited object matrix'].sv_set(OutMatrix) + + def update_socket(self, context): + self.update() + + +def register(): + bpy.utils.register_class(SvRayCastNode) + + +def unregister(): + bpy.utils.unregister_class(SvRayCastNode)