Skip to content

Commit

Permalink
Merge pull request #5044 from nortikin/fix_5043_Add_property_apply_mo…
Browse files Browse the repository at this point in the history
…difiers_and_select_UVMap_of_Node_Find_UV_Coord_on_Surface

fix #5043. Add property "apply modifiers" and "select UVMap by" for Node "Find UV Coord on Surface"
  • Loading branch information
satabol authored Nov 8, 2023
2 parents c8582c1 + a56a732 commit 418a4bf
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 28 deletions.
33 changes: 33 additions & 0 deletions docs/nodes/object_nodes/points_from_uv_to_mesh.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Find UV Coord on Surface
========================

.. image:: https://github.com/nortikin/sverchok/assets/14288520/bc7f7630-6e01-4356-a214-af4546a8b04b
:target: https://github.com/nortikin/sverchok/assets/14288520/bc7f7630-6e01-4356-a214-af4546a8b04b

Description
-----------

.. image:: https://github.com/nortikin/sverchok/assets/14288520/63b0de53-4ba2-4097-9389-9ecf9c09a665
:target: https://github.com/nortikin/sverchok/assets/14288520/63b0de53-4ba2-4097-9389-9ecf9c09a665

.. image:: https://github.com/nortikin/sverchok/assets/14288520/248f59bf-d468-415b-a7ec-0ef04d4f014e
:target: https://github.com/nortikin/sverchok/assets/14288520/248f59bf-d468-415b-a7ec-0ef04d4f014e

.. image:: https://github.com/nortikin/sverchok/assets/14288520/445fde34-d6a1-4365-80dd-0b0e6fb32501
:target: https://github.com/nortikin/sverchok/assets/14288520/445fde34-d6a1-4365-80dd-0b0e6fb32501

If you see this exception then check UV Map property. Here must at least one element:

.. image:: https://github.com/nortikin/sverchok/assets/14288520/630537e2-65b5-4501-aba9-ff27c6d16e88
:target: https://github.com/nortikin/sverchok/assets/14288520/630537e2-65b5-4501-aba9-ff27c6d16e88

Property
--------

Examples
--------

Nodes of description:

.. image:: https://github.com/nortikin/sverchok/assets/14288520/9cbd1034-111c-40f0-8680-b5cbe53b9347
:target: https://github.com/nortikin/sverchok/assets/14288520/9cbd1034-111c-40f0-8680-b5cbe53b9347
2 changes: 1 addition & 1 deletion index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@
- SvSetCustomUVMap
- SvUVtextureNode
- SvMeshUVColorNode
- SvUVPointonMeshNode
- SvUVPointonMeshNodeMK2
- SvSampleUVColorNode
- SvArmaturePropsNode
- SvLatticePropsNode
Expand Down
2 changes: 1 addition & 1 deletion menus/full_by_data_type.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@
- SvSetCustomUVMap
- SvUVtextureNode
- SvMeshUVColorNode
- SvUVPointonMeshNode
- SvUVPointonMeshNodeMK2
- SvSampleUVColorNode
- SvArmaturePropsNode
- SvLatticePropsNode
Expand Down
2 changes: 1 addition & 1 deletion menus/full_nortikin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@
- SvSetCustomUVMap
- SvUVtextureNode
- SvMeshUVColorNode
- SvUVPointonMeshNode
- SvUVPointonMeshNodeMK2
- SvSampleUVColorNode
- SvArmaturePropsNode
- SvLatticePropsNode
Expand Down
105 changes: 82 additions & 23 deletions nodes/object_nodes/points_from_uv_to_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,14 @@
from mathutils.bvhtree import BVHTree
from mathutils.geometry import barycentric_transform
import numpy as np
from bpy.props import BoolProperty, StringProperty, FloatVectorProperty
from bpy.props import BoolProperty, StringProperty, FloatVectorProperty, EnumProperty
from sverchok.node_tree import SverchCustomTreeNode

from sverchok.data_structure import (updateNode)


def UV(self, object):
def UV(self, bm, uv_layer):
# makes UV from layout texture area to sverchok vertices and polygons.
bm = bmesh.new()
bm.from_mesh(object.data)
uv_layer = bm.loops.layers.uv[0]
bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()
vertices_dict = {}
polygons_new = []
polygons_new_append = polygons_new.append
Expand All @@ -49,20 +44,48 @@ def UV(self, object):
polygons_new_append(polygons_new_pol)

vertices_new = list( vertices_dict.values() )
bm.clear()
return [vertices_new, polygons_new]


class SvUVPointonMeshNode(SverchCustomTreeNode, bpy.types.Node):
class SvUVPointonMeshNodeMK2(SverchCustomTreeNode, bpy.types.Node):
''' Transform vectors from UV space to Object space '''
bl_idname = 'SvUVPointonMeshNode'
bl_idname = 'SvUVPointonMeshNodeMK2'
bl_label = 'Find UV Coord on Surface'
bl_icon = 'GROUP_UVS'
is_scene_dependent = True
is_animation_dependent = True

object_ref: StringProperty(default='', update=updateNode)

apply_modifiers: BoolProperty(
name="Apply Modifiers", description="Off: use original object from scene\nOn: Apply modifiers before select UV Map",
default=False, update=updateNode)

uv_select_modes = [
('active_item', "Active Selected", "UV Map selected by an active elem in the list of UV Maps of object data", 0),
('active_render', "Active Render", "UV Map selected by property active_render in the list of UV Maps of object data (actived photo icon)", 1)
]

uv_select_mode : EnumProperty(
name = "Select UV Map by",
description = "UV Map select from object data property by",
items = uv_select_modes,
default = 'active_item',
update = updateNode)

def sv_draw_buttons(self, context, layout):
row = layout.row()
col = row.column()
col.label(text='Apply midifiers:')
col = row.column()
col.alignment = 'LEFT'
col.prop(self, 'apply_modifiers', expand=True, text='')
row = layout.row()
row.column().label(text="Select UV Map by:")
row.column().prop(self, 'uv_select_mode', expand=True ) #, text='')



def sv_init(self, context):
si, so = self.inputs.new, self.outputs.new
si('SvObjectSocket', 'Mesh Object')
Expand All @@ -75,31 +98,67 @@ def process(self):
Object, PointsUV = self.inputs
Pom, uvV, uvP = self.outputs
obj = Object.sv_get()[0] # triangulate faces
UVMAPV, UVMAPP = UV(self,obj)
if not obj.data.uv_layers:
raise Exception(f"Object '{obj.data.name}' has no UV Maps. Open Properties->Data->UV Maps and check list of UV Maps.")

# get all UV Maps name in object UV Maps list
uv_layer_active_render_name = obj.data.uv_layers[0].name
for uv in obj.data.uv_layers:
if uv.active_render==True:
uv_layer_active_render_name = uv.name # get UV Map name active render (photo mark)
break

bm = bmesh.new()
if self.apply_modifiers:
# apply modifiers and build mesh after it
sv_depsgraph = bpy.context.evaluated_depsgraph_get()
scene_object = sv_depsgraph.objects[ obj.name ]
object_to_mesh = scene_object.to_mesh(preserve_all_data_layers=True, depsgraph=sv_depsgraph)
bm.from_mesh(object_to_mesh)
scene_object.to_mesh_clear()
else:
# get mesh of original object from scene
bm.from_mesh(obj.data)

uv_layer_active = bm.loops.layers.uv.active
uv_layer_active_render = obj.data.uv_layers[0]
for uv in bm.loops.layers.uv:
if uv.name==uv_layer_active_render_name:
uv_layer_active_render = uv
break

if self.uv_select_mode=='active_item':
uv_layer = uv_layer_active
else: #if self.uv_select_mode=='active_render':
uv_layer = uv_layer_active_render

bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()
UVMAPV, UVMAPP = UV(self, bm, uv_layer)
if Pom.is_linked:
# resore UV to 3D
pointuv = PointsUV.sv_get()[0]
bvh = BVHTree.FromPolygons(UVMAPV, UVMAPP, all_triangles=False, epsilon=0.0)
ran = range(3)
out = []
uvMap = obj.data.uv_layers[0].data
out = [] # result in 3D
for Puv in pointuv:
loc, norm, ind, dist = bvh.find_nearest(Puv)
found_poly = obj.data.polygons[ind]
verticesIndices = found_poly.vertices
p1, p2, p3 = [obj.data.vertices[verticesIndices[i]].co for i in ran]
uvMapIndices = found_poly.loop_indices
uv1, uv2, uv3 = [uvMap[uvMapIndices[i]].uv.to_3d() for i in ran]
V = barycentric_transform(Puv, uv1, uv2, uv3, p1, p2, p3)
out.append(V[:])
_found_poly = bm.faces[ind]
_p1, _p2, _p3 = [v.co for v in bm.faces[ind].verts[0:3] ]
_uv1, _uv2, _uv3 = [l[uv_layer].uv.to_3d() for l in _found_poly.loops[0:3] ]
_V = barycentric_transform(Puv, _uv1, _uv2, _uv3, _p1, _p2, _p3)
out.append(_V[:])

Pom.sv_set([out])
bm.clear()

if uvV.is_linked:
uvV.sv_set([UVMAPV])
uvP.sv_set([UVMAPP])


def register():
bpy.utils.register_class(SvUVPointonMeshNode)
bpy.utils.register_class(SvUVPointonMeshNodeMK2)


def unregister():
bpy.utils.unregister_class(SvUVPointonMeshNode)
bpy.utils.unregister_class(SvUVPointonMeshNodeMK2)
105 changes: 105 additions & 0 deletions old_nodes/points_from_uv_to_mesh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# ##### 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 bmesh
from mathutils.bvhtree import BVHTree
from mathutils.geometry import barycentric_transform
import numpy as np
from bpy.props import BoolProperty, StringProperty, FloatVectorProperty
from sverchok.node_tree import SverchCustomTreeNode

from sverchok.data_structure import (updateNode)


def UV(self, object):
# makes UV from layout texture area to sverchok vertices and polygons.
bm = bmesh.new()
bm.from_mesh(object.data)
uv_layer = bm.loops.layers.uv[0]
bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()
vertices_dict = {}
polygons_new = []
polygons_new_append = polygons_new.append
for fi in bm.faces:
polygons_new_pol = []
polygons_new_pol_append = polygons_new_pol.append
for loop in fi.loops:
li = loop.index
polygons_new_pol_append(li)
uv = loop[uv_layer].uv
vertices_dict[li] = [ uv.x, uv.y, 0.0]

polygons_new_append(polygons_new_pol)

vertices_new = list( vertices_dict.values() )
bm.clear()
return [vertices_new, polygons_new]


class SvUVPointonMeshNode(SverchCustomTreeNode, bpy.types.Node):
''' Transform vectors from UV space to Object space '''
bl_idname = 'SvUVPointonMeshNode'
bl_label = 'Find UV Coord on Surface'
bl_icon = 'GROUP_UVS'
is_scene_dependent = True
is_animation_dependent = True

object_ref: StringProperty(default='', update=updateNode)

def sv_init(self, context):
si, so = self.inputs.new, self.outputs.new
si('SvObjectSocket', 'Mesh Object')
si('SvVerticesSocket', 'Point on UV')
so('SvVerticesSocket', 'Point on mesh')
so('SvVerticesSocket', 'UVMapVert')
so('SvStringsSocket', 'UVMapPoly')

def process(self):
Object, PointsUV = self.inputs
Pom, uvV, uvP = self.outputs
obj = Object.sv_get()[0] # triangulate faces
UVMAPV, UVMAPP = UV(self,obj)
if Pom.is_linked:
pointuv = PointsUV.sv_get()[0]
bvh = BVHTree.FromPolygons(UVMAPV, UVMAPP, all_triangles=False, epsilon=0.0)
ran = range(3)
out = []
uvMap = obj.data.uv_layers[0].data
for Puv in pointuv:
loc, norm, ind, dist = bvh.find_nearest(Puv)
found_poly = obj.data.polygons[ind]
verticesIndices = found_poly.vertices
p1, p2, p3 = [obj.data.vertices[verticesIndices[i]].co for i in ran]
uvMapIndices = found_poly.loop_indices
uv1, uv2, uv3 = [uvMap[uvMapIndices[i]].uv.to_3d() for i in ran]
V = barycentric_transform(Puv, uv1, uv2, uv3, p1, p2, p3)
out.append(V[:])
Pom.sv_set([out])
if uvV.is_linked:
uvV.sv_set([UVMAPV])
uvP.sv_set([UVMAPP])


def register():
bpy.utils.register_class(SvUVPointonMeshNode)


def unregister():
bpy.utils.unregister_class(SvUVPointonMeshNode)
3 changes: 1 addition & 2 deletions tests/docs_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_uniq_node_modules(self):
continue
with self.subTest(node_module=f"{file_name}.py"):
if file_name in modules:
self.fail(f'There are tow modules with the same name "{file_name}" \n'
self.fail(f'There are two modules with the same name "{file_name}" \n'
f'File 1: {Path(modules[file_name]).relative_to(sv_root)} \n'
f'file 2: {Path(path).relative_to(sv_root)}')
else:
Expand All @@ -59,7 +59,6 @@ def test_node_docs_existance(self):
scene_raycast2.py
sculpt_mask.py
set_blenddata2.py
points_from_uv_to_mesh.py
custom_mesh_normals.py
color_uv_texture.py
filter_blenddata.py
Expand Down

0 comments on commit 418a4bf

Please sign in to comment.