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

fix #5043. Add property "apply modifiers" and "select UVMap by" for Node "Find UV Coord on Surface" #5044

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
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
Loading