Коммит cf613267 создал по автору Ilya Portnov's avatar Ilya Portnov
Просмотр файлов

Possibility to bake curves & surfaces.

владелец 68368684
......@@ -18,6 +18,8 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, get_data_nesting_level, ensure_nesting_level, zip_long_repeat, node_id
from sverchok.utils.curve.core import SvCurve
from sverchok.utils.curve.nurbs import SvNurbsCurve
from sverchok.utils.curve.bakery import CurveData
from sverchok.utils.sv_operator_mixins import SvGenericNodeLocator
from sverchok.ui.bgl_callback_3dview import callback_disable, callback_enable
def draw_edges(shader, points, edges, line_width, color):
......@@ -36,35 +38,6 @@ def draw_points(shader, points, size, color):
batch.draw(shader)
bgl.glPointSize(1)
class CurveData(object):
def __init__(self, node, curve, resolution):
self.node = node
self.curve = curve
self.resolution = resolution
if node.draw_line or node.draw_verts:
t_min, t_max = curve.get_u_bounds()
ts = np.linspace(t_min, t_max, num=resolution)
self.points = curve.evaluate_array(ts).tolist()
if node.draw_line:
n = len(ts)
self.edges = [(i,i+1) for i in range(n-1)]
if (node.draw_control_polygon or node.draw_control_points) and hasattr(curve, 'get_control_points'):
self.control_points = curve.get_control_points().tolist()
else:
self.control_points = None
if node.draw_control_polygon:
n = len(self.control_points)
self.control_polygon_edges = [(i,i+1) for i in range(n-1)]
if node.draw_nodes and hasattr(curve, 'calc_greville_points'):
self.node_points = curve.calc_greville_points().tolist()
else:
self.node_points = None
def draw_curves(context, args):
node, draw_inputs, v_shader, e_shader = args
......@@ -89,6 +62,18 @@ def draw_curves(context, args):
bgl.glEnable(bgl.GL_BLEND)
class SvBakeCurveOp(bpy.types.Operator, SvGenericNodeLocator):
"""B A K E CURVES"""
bl_idname = "node.sverchok_curve_baker"
bl_label = "Bake Curves"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
def sv_execute(self, context, node):
curve_data = node.get_curve_data()
for i, item in enumerate(curve_data):
item.bake(f"Sv_Curve_{i}")
return {'FINISHED'}
class SvCurveViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
"""
Triggers: preview curve
......@@ -215,6 +200,12 @@ class SvCurveViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
row.prop(self, 'nodes_color', text="")
row.prop(self, 'nodes_size', text="px")
row = layout.row(align=True)
row.scale_y = 4.0 if self.prefs_over_sized_buttons else 1
self.wrapper_tracked_ui_draw_op(row, SvBakeCurveOp.bl_idname, icon='OUTLINER_OB_MESH', text="B A K E")
row.separator()
self.wrapper_tracked_ui_draw_op(row, "node.view3d_align_from", icon='CURSOR', text='')
def sv_init(self, context):
self.inputs.new('SvCurveSocket', 'Curve')
self.inputs.new('SvStringsSocket', 'Resolution').prop_name = 'resolution'
......@@ -232,6 +223,21 @@ class SvCurveViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
callback_enable(node_id(self), draw_data)
def get_curve_data(self):
curves_s = self.inputs['Curve'].sv_get()
resolution_s = self.inputs['Resolution'].sv_get()
curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve,))
resolution_s = ensure_nesting_level(resolution_s, 2)
draw_inputs = []
for params in zip_long_repeat(curves_s, resolution_s):
for curve, resolution in zip_long_repeat(*params):
t_curve = SvNurbsCurve.to_nurbs(curve)
if t_curve is None:
t_curve = curve
draw_inputs.append(CurveData(self, t_curve, resolution))
return draw_inputs
def process(self):
if bpy.app.background:
return
......@@ -248,18 +254,7 @@ class SvCurveViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
if not self.inputs['Curve'].is_linked:
return
curves_s = self.inputs['Curve'].sv_get()
resolution_s = self.inputs['Resolution'].sv_get()
curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve,))
resolution_s = ensure_nesting_level(resolution_s, 2)
draw_inputs = []
for params in zip_long_repeat(curves_s, resolution_s):
for curve, resolution in zip_long_repeat(*params):
t_curve = SvNurbsCurve.to_nurbs(curve)
if t_curve is None:
t_curve = curve
draw_inputs.append(CurveData(self, t_curve, resolution))
draw_inputs = self.get_curve_data()
self.draw_all(draw_inputs)
def show_viewport(self, is_show: bool):
......@@ -276,6 +271,6 @@ class SvCurveViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
def sv_free(self):
callback_disable(node_id(self))
classes = [SvCurveViewerDrawNode]
classes = [SvCurveViewerDrawNode, SvBakeCurveOp]
register, unregister = bpy.utils.register_classes_factory(classes)
......@@ -18,9 +18,8 @@ from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, get_data_nesting_level, ensure_nesting_level, zip_long_repeat, node_id
from sverchok.utils.surface.core import SvSurface
from sverchok.utils.surface.nurbs import SvNurbsSurface
from sverchok.utils.modules.polygon_utils import pols_normals
from sverchok.utils.modules.vertex_utils import np_vertex_normals
from sverchok.utils.math import np_dot
from sverchok.utils.surface.bakery import SurfaceData
from sverchok.utils.sv_operator_mixins import SvGenericNodeLocator
from sverchok.ui.bgl_callback_3dview import callback_disable, callback_enable
def draw_edges(shader, points, edges, line_width, color):
......@@ -44,75 +43,6 @@ def draw_polygons(shader, points, tris, vertex_colors):
shader.bind()
batch.draw(shader)
def make_quad_edges(n_u, n_v):
edges = []
for row in range(n_v):
e_row = [(i + n_u * row, (i+1) + n_u * row) for i in range(n_u-1)]
edges.extend(e_row)
if row < n_v - 1:
e_col = [(i + n_u * row, i + n_u * (row+1)) for i in range(n_u)]
edges.extend(e_col)
return edges
def make_tris(n_u, n_v):
def calc_idx(row_idx, column_idx):
return n_u * row_idx + column_idx
tris = []
for row_idx in range(n_v-1):
for column_idx in range(n_u-1):
pt1 = calc_idx(row_idx, column_idx)
pt2 = calc_idx(row_idx, column_idx+1)
pt3 = calc_idx(row_idx+1, column_idx+1)
pt4 = calc_idx(row_idx+1, column_idx)
#tri1 = [pt1, pt2, pt3]
#tri2 = [pt1, pt3, pt4]
tri1 = [pt1, pt3, pt2]
tri2 = [pt1, pt4, pt3]
tris.append(tri1)
tris.append(tri2)
return tris
def vert_light_factor(vecs, polygons, light):
return (np_dot(np_vertex_normals(vecs, polygons, output_numpy=True), light)*0.5+0.5).tolist()
def calc_surface_data(light_vector, surface_color, n_u, n_v, points):
#points = points.reshape((n_u*n_v, 3))
tris = make_tris(n_u, n_v)
n_tris = len(tris)
light_factor = vert_light_factor(points, tris, light_vector)
colors = []
col = surface_color
for l_factor in light_factor:
colors.append([col[0]*l_factor, col[1]*l_factor, col[2]*l_factor, col[3]])
return tris, colors
class SurfaceData(object):
def __init__(self, node, surface, resolution_u, resolution_v):
self.node = node
self.surface = surface
self.resolution_u = resolution_u
self.resolution_v = resolution_v
u_min, u_max = surface.get_u_bounds()
v_min, v_max = surface.get_v_bounds()
us = np.linspace(u_min, u_max, num=resolution_u)
vs = np.linspace(v_min, v_max, num=resolution_v)
us, vs = np.meshgrid(us, vs)
us = us.flatten()
vs = vs.flatten()
self.points = surface.evaluate_array(us, vs)#.tolist()
self.points_list = self.points.reshape((resolution_u*resolution_v, 3)).tolist()
if hasattr(surface, 'get_control_points'):
self.cpts = surface.get_control_points()
n_v, n_u, _ = self.cpts.shape
self.cpts_list = self.cpts.reshape((n_u*n_v, 3)).tolist()
self.control_net = make_quad_edges(n_u, n_v)
self.edges = make_quad_edges(resolution_u, resolution_v)
self.tris, self.tri_colors = calc_surface_data(node.light_vector, node.surface_color, resolution_u, resolution_v, self.points)
def draw_surfaces(context, args):
node, draw_inputs, v_shader, e_shader, p_shader = args
......@@ -137,6 +67,18 @@ def draw_surfaces(context, args):
bgl.glEnable(bgl.GL_BLEND)
class SvBakeSurfaceOp(bpy.types.Operator, SvGenericNodeLocator):
"""B A K E SURFACES"""
bl_idname = "node.sverchok_surface_baker"
bl_label = "Bake Surfaces"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
def sv_execute(self, context, node):
surface_data = node.get_surface_data()
for i, item in enumerate(surface_data):
item.bake(f"Sv_Surface_{i}")
return {'FINISHED'}
class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
"""
Triggers: preview surface
......@@ -278,6 +220,12 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
row.prop(self, 'control_net_color', text="")
row.prop(self, 'control_net_line_width', text="px")
row = layout.row(align=True)
row.scale_y = 4.0 if self.prefs_over_sized_buttons else 1
self.wrapper_tracked_ui_draw_op(row, SvBakeSurfaceOp.bl_idname, icon='OUTLINER_OB_MESH', text="B A K E")
row.separator()
self.wrapper_tracked_ui_draw_op(row, "node.view3d_align_from", icon='CURSOR', text='')
def draw_buttons_ext(self, context, layout):
layout.prop(self, 'light_vector')
self.draw_buttons(context, layout)
......@@ -296,6 +244,24 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
callback_enable(node_id(self), draw_data)
def get_surface_data(self):
surfaces_s = self.inputs['Surface'].sv_get()
resolution_u_s = self.inputs['ResolutionU'].sv_get()
resolution_v_s = self.inputs['ResolutionV'].sv_get()
surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface,))
resolution_u_s = ensure_nesting_level(resolution_u_s, 2)
resolution_v_s = ensure_nesting_level(resolution_v_s, 2)
draw_inputs = []
for params in zip_long_repeat(surfaces_s, resolution_u_s, resolution_v_s):
for surface, resolution_u, resolution_v in zip_long_repeat(*params):
t_surface = SvNurbsSurface.get(surface)
if t_surface is None:
t_surface = surface
draw_inputs.append(SurfaceData(self, t_surface, resolution_u, resolution_v))
return draw_inputs
def process(self):
if bpy.app.background:
return
......@@ -312,21 +278,7 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
if not self.inputs['Surface'].is_linked:
return
surfaces_s = self.inputs['Surface'].sv_get()
resolution_u_s = self.inputs['ResolutionU'].sv_get()
resolution_v_s = self.inputs['ResolutionV'].sv_get()
surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface,))
resolution_u_s = ensure_nesting_level(resolution_u_s, 2)
resolution_v_s = ensure_nesting_level(resolution_v_s, 2)
draw_inputs = []
for params in zip_long_repeat(surfaces_s, resolution_u_s, resolution_v_s):
for surface, resolution_u, resolution_v in zip_long_repeat(*params):
t_surface = SvNurbsSurface.get(surface)
if t_surface is None:
t_surface = surface
draw_inputs.append(SurfaceData(self, t_surface, resolution_u, resolution_v))
draw_inputs = self.get_surface_data()
self.draw_all(draw_inputs)
def show_viewport(self, is_show: bool):
......@@ -344,6 +296,6 @@ class SvSurfaceViewerDrawNode(bpy.types.Node, SverchCustomTreeNode):
callback_disable(node_id(self))
classes = [SvSurfaceViewerDrawNode]
classes = [SvSurfaceViewerDrawNode, SvBakeSurfaceOp]
register, unregister = bpy.utils.register_classes_factory(classes)
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import numpy as np
import bpy
def curve_to_meshdata(curve, resolution):
t_min, t_max = curve.get_u_bounds()
ts = np.linspace(t_min, t_max, num=resolution)
points = curve.evaluate_array(ts).tolist()
edges = [(i,i+1) for i in range(resolution-1)]
return points, edges
def bake_curve(curve, resolution, object_name):
points, edges = curve_to_meshdata(curve, resolution)
me = bpy.data.meshes.new(object_name)
me.from_pydata(points, edges, [])
ob = bpy.data.objects.new(object_name, me)
bpy.context.scene.collection.objects.link(ob)
return ob
class CurveData(object):
def __init__(self, node, curve, resolution):
self.node = node
self.curve = curve
self.resolution = resolution
if node.draw_line or node.draw_verts:
t_min, t_max = curve.get_u_bounds()
ts = np.linspace(t_min, t_max, num=resolution)
self.points = curve.evaluate_array(ts).tolist()
if node.draw_line:
n = len(ts)
self.edges = [(i,i+1) for i in range(n-1)]
if (node.draw_control_polygon or node.draw_control_points) and hasattr(curve, 'get_control_points'):
self.control_points = curve.get_control_points().tolist()
else:
self.control_points = None
if node.draw_control_polygon:
n = len(self.control_points)
self.control_polygon_edges = [(i,i+1) for i in range(n-1)]
if node.draw_nodes and hasattr(curve, 'calc_greville_points'):
self.node_points = curve.calc_greville_points().tolist()
else:
self.node_points = None
def bake(self, object_name):
me = bpy.data.meshes.new(object_name)
me.from_pydata(self.points, self.edges, [])
ob = bpy.data.objects.new(object_name, me)
bpy.context.scene.collection.objects.link(ob)
return ob
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import numpy as np
import bpy
from sverchok.utils.modules.polygon_utils import pols_normals
from sverchok.utils.modules.vertex_utils import np_vertex_normals
from sverchok.utils.math import np_dot
def make_quad_edges(n_u, n_v):
edges = []
for row in range(n_v):
e_row = [(i + n_u * row, (i+1) + n_u * row) for i in range(n_u-1)]
edges.extend(e_row)
if row < n_v - 1:
e_col = [(i + n_u * row, i + n_u * (row+1)) for i in range(n_u)]
edges.extend(e_col)
return edges
def make_quad_faces(samples_u, samples_v):
faces = []
for row in range(samples_v - 1):
for col in range(samples_u - 1):
i = row * samples_u + col
face = (i, i+samples_u, i+samples_u+1, i+1)
faces.append(face)
return faces
def surface_to_meshdata(surface, resolution_u, resolution_v):
u_min, u_max = surface.get_u_bounds()
v_min, v_max = surface.get_v_bounds()
us = np.linspace(u_min, u_max, num=resolution_u)
vs = np.linspace(v_min, v_max, num=resolution_v)
us, vs = np.meshgrid(us, vs)
us = us.flatten()
vs = vs.flatten()
points = surface.evaluate_array(us, vs).tolist()
edges = make_quad_edges(resolution_u, resolution_v)
faces = make_quad_faces(resolution_u, resolution_v)
return points, edges, faces
def bake_surface(surface, resolution_u, resolution_v, object_name):
verts, edges, faces = surface_to_meshdata(surface, resolution_u, resolution_v)
me = bpy.data.meshes.new(object_name)
me.from_pydata(points, edges, faces)
ob = bpy.data.objects.new(object_name, me)
bpy.context.scene.collection.objects.link(ob)
return ob
def make_tris(n_u, n_v):
def calc_idx(row_idx, column_idx):
return n_u * row_idx + column_idx
tris = []
for row_idx in range(n_v-1):
for column_idx in range(n_u-1):
pt1 = calc_idx(row_idx, column_idx)
pt2 = calc_idx(row_idx, column_idx+1)
pt3 = calc_idx(row_idx+1, column_idx+1)
pt4 = calc_idx(row_idx+1, column_idx)
#tri1 = [pt1, pt2, pt3]
#tri2 = [pt1, pt3, pt4]
tri1 = [pt1, pt3, pt2]
tri2 = [pt1, pt4, pt3]
tris.append(tri1)
tris.append(tri2)
return tris
def vert_light_factor(vecs, polygons, light):
return (np_dot(np_vertex_normals(vecs, polygons, output_numpy=True), light)*0.5+0.5).tolist()
def calc_surface_data(light_vector, surface_color, n_u, n_v, points):
#points = points.reshape((n_u*n_v, 3))
tris = make_tris(n_u, n_v)
n_tris = len(tris)
light_factor = vert_light_factor(points, tris, light_vector)
colors = []
col = surface_color
for l_factor in light_factor:
colors.append([col[0]*l_factor, col[1]*l_factor, col[2]*l_factor, col[3]])
return tris, colors
class SurfaceData(object):
def __init__(self, node, surface, resolution_u, resolution_v):
self.node = node
self.surface = surface
self.resolution_u = resolution_u
self.resolution_v = resolution_v
u_min, u_max = surface.get_u_bounds()
v_min, v_max = surface.get_v_bounds()
us = np.linspace(u_min, u_max, num=resolution_u)
vs = np.linspace(v_min, v_max, num=resolution_v)
us, vs = np.meshgrid(us, vs)
us = us.flatten()
vs = vs.flatten()
self.points = surface.evaluate_array(us, vs)#.tolist()
self.points_list = self.points.reshape((resolution_u*resolution_v, 3)).tolist()
if hasattr(surface, 'get_control_points'):
self.cpts = surface.get_control_points()
n_v, n_u, _ = self.cpts.shape
self.cpts_list = self.cpts.reshape((n_u*n_v, 3)).tolist()
self.control_net = make_quad_edges(n_u, n_v)
self.edges = make_quad_edges(resolution_u, resolution_v)
self.tris, self.tri_colors = calc_surface_data(node.light_vector, node.surface_color, resolution_u, resolution_v, self.points)
def bake(self, object_name):
me = bpy.data.meshes.new(object_name)
faces = make_quad_faces(self.resolution_u, self.resolution_v)
me.from_pydata(self.points_list, self.edges, faces)
is_smooth = np.ones(len(faces), dtype=bool)
me.polygons.foreach_set('use_smooth', is_smooth)
ob = bpy.data.objects.new(object_name, me)
bpy.context.scene.collection.objects.link(ob)
return ob
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать