Tree Generator v1.8.0: Profilaufloesung je Ast-Ebene (Branch Sides / Sub Sides)
Stamm rund (8 Seiten), Aeste 4, Zweige 3 - wie im TreeIt-Referenzbaum. Runderer Stamm bei gleichzeitig ~25% weniger Tris (baum 1368 -> 1032). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
|
|
||||||
id = "stylized_tree_generator"
|
id = "stylized_tree_generator"
|
||||||
version = "1.7.0"
|
version = "1.8.0"
|
||||||
name = "Stylized Tree Generator"
|
name = "Stylized Tree Generator"
|
||||||
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
|
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
|
||||||
maintainer = "D4rkst3r"
|
maintainer = "D4rkst3r"
|
||||||
|
|||||||
Vendored
+4
-4
@@ -32,7 +32,7 @@
|
|||||||
"id": "stylized_tree_generator",
|
"id": "stylized_tree_generator",
|
||||||
"name": "Stylized Tree Generator",
|
"name": "Stylized Tree Generator",
|
||||||
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
|
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
|
||||||
"version": "1.7.0",
|
"version": "1.8.0",
|
||||||
"type": "add-on",
|
"type": "add-on",
|
||||||
"maintainer": "D4rkst3r",
|
"maintainer": "D4rkst3r",
|
||||||
"license": [
|
"license": [
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
"Mesh",
|
"Mesh",
|
||||||
"Modeling"
|
"Modeling"
|
||||||
],
|
],
|
||||||
"archive_url": "./stylized_tree_generator-1.7.0.zip",
|
"archive_url": "./stylized_tree_generator-1.8.0.zip",
|
||||||
"archive_size": 13398,
|
"archive_size": 13440,
|
||||||
"archive_hash": "sha256:3817ce7433ef63918ddf75a827591b3bb712c8659141ae85f73f4f1fd19e20fb"
|
"archive_hash": "sha256:e96e6ec6f8009708ce0611dea6ea50e3271b6603d60bce84ebeab2e365bba983"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+97
-99
@@ -1,7 +1,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Stylized Tree Generator",
|
"name": "Stylized Tree Generator",
|
||||||
"author": "D4rkst3r",
|
"author": "D4rkst3r",
|
||||||
"version": (1, 7, 0),
|
"version": (1, 8, 0),
|
||||||
"blender": (4, 2, 0),
|
"blender": (4, 2, 0),
|
||||||
"location": "View3D > Sidebar > Tree Gen",
|
"location": "View3D > Sidebar > Tree Gen",
|
||||||
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
|
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
|
||||||
@@ -43,7 +43,9 @@ DEFAULTS = {
|
|||||||
"Sub Count": 2, # Sub-Aeste je Hauptast (0 = aus)
|
"Sub Count": 2, # Sub-Aeste je Hauptast (0 = aus)
|
||||||
"Sub Length": 0.55,
|
"Sub Length": 0.55,
|
||||||
"Sub Up": 1.4,
|
"Sub Up": 1.4,
|
||||||
"Sides": 5,
|
"Sides": 8, # Stamm rund (Referenz TreeIt: ~9)
|
||||||
|
"Branch Sides": 4, # Aeste sparsamer
|
||||||
|
"Sub Sides": 3, # Zweige nur Dreiecke - sieht man nicht
|
||||||
"UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m)
|
"UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m)
|
||||||
"Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus)
|
"Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus)
|
||||||
"Root Flare": 1.1, # Wurzelanlauf: Stamm verbreitert sich am Fuss
|
"Root Flare": 1.1, # Wurzelanlauf: Stamm verbreitert sich am Fuss
|
||||||
@@ -86,7 +88,7 @@ PRESETS = {
|
|||||||
"Branch Taper": 0.12, # Arme bleiben dick statt spitz zuzulaufen
|
"Branch Taper": 0.12, # Arme bleiben dick statt spitz zuzulaufen
|
||||||
"Sub Count": 0,
|
"Sub Count": 0,
|
||||||
"Tip Blunt": 0.45,
|
"Tip Blunt": 0.45,
|
||||||
"Sides": 18, "Ribs": 9.0, "Rib Depth": 0.09,
|
"Sides": 16, "Branch Sides": 12, "Ribs": 9.0, "Rib Depth": 0.09,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
@@ -166,6 +168,8 @@ def build_group():
|
|||||||
add_in("Sub Length", 'NodeSocketFloat', DEFAULTS["Sub Length"], 0.05, 5.0)
|
add_in("Sub Length", 'NodeSocketFloat', DEFAULTS["Sub Length"], 0.05, 5.0)
|
||||||
add_in("Sub Up", 'NodeSocketFloat', DEFAULTS["Sub Up"], -3.0, 3.0)
|
add_in("Sub Up", 'NodeSocketFloat', DEFAULTS["Sub Up"], -3.0, 3.0)
|
||||||
add_in("Sides", 'NodeSocketInt', DEFAULTS["Sides"], 3, 32)
|
add_in("Sides", 'NodeSocketInt', DEFAULTS["Sides"], 3, 32)
|
||||||
|
add_in("Branch Sides", 'NodeSocketInt', DEFAULTS["Branch Sides"], 3, 16)
|
||||||
|
add_in("Sub Sides", 'NodeSocketInt', DEFAULTS["Sub Sides"], 3, 12)
|
||||||
add_in("Tip Blunt", 'NodeSocketFloat', DEFAULTS["Tip Blunt"], 0.0, 0.9)
|
add_in("Tip Blunt", 'NodeSocketFloat', DEFAULTS["Tip Blunt"], 0.0, 0.9)
|
||||||
add_in("UV Scale", 'NodeSocketFloat', DEFAULTS["UV Scale"], 0.01, 20.0)
|
add_in("UV Scale", 'NodeSocketFloat', DEFAULTS["UV Scale"], 0.01, 20.0)
|
||||||
add_in("Detail", 'NodeSocketFloat', DEFAULTS["Detail"], 0.2, 2.0)
|
add_in("Detail", 'NodeSocketFloat', DEFAULTS["Detail"], 0.2, 2.0)
|
||||||
@@ -573,108 +577,102 @@ def build_group():
|
|||||||
L(_out(sreal, "Geometry"), _sock(sbset, "Geometry"))
|
L(_out(sreal, "Geometry"), _sock(sbset, "Geometry"))
|
||||||
L(sboff.outputs[0], _sock(sbset, "Offset"))
|
L(sboff.outputs[0], _sock(sbset, "Offset"))
|
||||||
|
|
||||||
join = N("GeometryNodeJoinGeometry"); join.location = (3150, 200)
|
# ---------- Curve -> Mesh, PRO EBENE mit eigener Profilaufloesung ----------
|
||||||
L(_out(sbset, "Geometry"), join.inputs[0])
|
# Referenz (TreeIt): Stamm ~9 Segmente, duenne Zweige nur Dreiecke. Ein
|
||||||
L(_out(rsetp, "Geometry"), join.inputs[0])
|
# "Curve to Mesh" kennt aber nur EIN Profil -> deshalb wird jede Ebene
|
||||||
L(_out(setrad, "Curve"), join.inputs[0])
|
# einzeln gewandelt und erst danach zusammengefuegt. Spart massiv Tris,
|
||||||
|
# weil die vielen duennen Zweige nicht die Rundung des Stammes brauchen.
|
||||||
|
def _profile(sides_socket, x, y):
|
||||||
|
c = N("GeometryNodeCurvePrimitiveCircle"); c.location = (x, y)
|
||||||
|
L(sides_socket, _sock(c, "Resolution"))
|
||||||
|
_sock(c, "Radius").default_value = 1.0
|
||||||
|
# Rippen (Kaktus-Kanneluren): radiale Welle auf dem Profil
|
||||||
|
sp = N("GeometryNodeSplineParameter"); sp.location = (x, y - 200)
|
||||||
|
ang = N("ShaderNodeMath"); ang.location = (x + 150, y - 200); ang.operation = 'MULTIPLY'
|
||||||
|
ang.inputs[1].default_value = 6.283185
|
||||||
|
L(sp.outputs["Factor"], ang.inputs[0])
|
||||||
|
rb = N("ShaderNodeMath"); rb.location = (x + 300, y - 200); rb.operation = 'MULTIPLY'
|
||||||
|
L(ang.outputs[0], rb.inputs[0]); L(V["Ribs"], rb.inputs[1])
|
||||||
|
co = N("ShaderNodeMath"); co.location = (x + 450, y - 200); co.operation = 'COSINE'
|
||||||
|
L(rb.outputs[0], co.inputs[0])
|
||||||
|
am = N("ShaderNodeMath"); am.location = (x + 600, y - 200); am.operation = 'MULTIPLY'
|
||||||
|
L(co.outputs[0], am.inputs[0]); L(V["Rib Depth"], am.inputs[1])
|
||||||
|
po = N("GeometryNodeInputPosition"); po.location = (x + 300, y - 340)
|
||||||
|
dn = N("ShaderNodeVectorMath"); dn.location = (x + 450, y - 340); dn.operation = 'NORMALIZE'
|
||||||
|
L(po.outputs[0], dn.inputs[0])
|
||||||
|
of = N("ShaderNodeVectorMath"); of.location = (x + 750, y - 300); of.operation = 'SCALE'
|
||||||
|
L(dn.outputs[0], of.inputs[0]); L(am.outputs[0], _sock(of, "Scale"))
|
||||||
|
st = N("GeometryNodeSetPosition"); st.location = (x + 900, y)
|
||||||
|
L(_out(c, "Curve"), _sock(st, "Geometry")); L(of.outputs[0], _sock(st, "Offset"))
|
||||||
|
# uv_u = Bogenlaenge um das Profil
|
||||||
|
sp2 = N("GeometryNodeSplineParameter"); sp2.location = (x + 900, y - 200)
|
||||||
|
su = N("GeometryNodeStoreNamedAttribute"); su.location = (x + 1050, y)
|
||||||
|
su.domain = 'POINT'; su.data_type = 'FLOAT'
|
||||||
|
L(_out(st, "Geometry"), _sock(su, "Geometry"))
|
||||||
|
_sock(su, "Name").default_value = "uv_u"
|
||||||
|
L(sp2.outputs["Length"], _sock(su, "Value"))
|
||||||
|
return su
|
||||||
|
|
||||||
# ---------- Curve -> Mesh ----------
|
def _to_mesh(curve_node, curve_out_name, sides_socket, x, y):
|
||||||
# Falle 6: Der Profil-Radius wird mit dem Curve-Radius MULTIPLIZIERT.
|
"""Kurven -> Mesh inkl. world-space UVs. Pro Ast-Ebene einmal."""
|
||||||
# Profil deshalb auf 1.0 lassen waere richtig -- aber nur, wenn der
|
cs = N("GeometryNodeSplineParameter"); cs.location = (x, y - 140)
|
||||||
# Curve-Radius bereits die echte Staerke ist. Hier ist er das, also 1.0.
|
sv = N("GeometryNodeStoreNamedAttribute"); sv.location = (x + 150, y)
|
||||||
circ = N("GeometryNodeCurvePrimitiveCircle"); circ.location = (1350, -100)
|
sv.domain = 'POINT'; sv.data_type = 'FLOAT'
|
||||||
L(V["Sides"], _sock(circ, "Resolution"))
|
L(_out(curve_node, curve_out_name), _sock(sv, "Geometry"))
|
||||||
_sock(circ, "Radius").default_value = 1.0
|
_sock(sv, "Name").default_value = "uv_v"
|
||||||
|
L(cs.outputs["Length"], _sock(sv, "Value"))
|
||||||
|
rd = N("GeometryNodeInputRadius"); rd.location = (x, y - 280)
|
||||||
|
sw = N("GeometryNodeStoreNamedAttribute"); sw.location = (x + 300, y)
|
||||||
|
sw.domain = 'POINT'; sw.data_type = 'FLOAT'
|
||||||
|
L(_out(sv, "Geometry"), _sock(sw, "Geometry"))
|
||||||
|
_sock(sw, "Name").default_value = "uv_r"
|
||||||
|
L(rd.outputs[0], _sock(sw, "Value"))
|
||||||
|
|
||||||
# ---------- Rippen (senkrechte Kanneluren, Kaktus-Signatur) ----------
|
prof = _profile(sides_socket, x - 1100, y - 500)
|
||||||
# Das Profil bekommt eine radiale Welle: Offset entlang der Punktrichtung,
|
|
||||||
# moduliert mit cos(Rippen * Winkel). Rib Depth = 0 -> glatter Kreis.
|
|
||||||
pspar = N("GeometryNodeSplineParameter"); pspar.location = (1350, -420)
|
|
||||||
pang = N("ShaderNodeMath"); pang.location = (1500, -420); pang.operation = 'MULTIPLY'
|
|
||||||
pang.inputs[1].default_value = 6.283185
|
|
||||||
L(pspar.outputs["Factor"], pang.inputs[0])
|
|
||||||
pribs = N("ShaderNodeMath"); pribs.location = (1650, -420); pribs.operation = 'MULTIPLY'
|
|
||||||
L(pang.outputs[0], pribs.inputs[0])
|
|
||||||
L(V["Ribs"], pribs.inputs[1])
|
|
||||||
pcos = N("ShaderNodeMath"); pcos.location = (1800, -420); pcos.operation = 'COSINE'
|
|
||||||
L(pribs.outputs[0], pcos.inputs[0])
|
|
||||||
pamp = N("ShaderNodeMath"); pamp.location = (1950, -420); pamp.operation = 'MULTIPLY'
|
|
||||||
L(pcos.outputs[0], pamp.inputs[0])
|
|
||||||
L(V["Rib Depth"], pamp.inputs[1])
|
|
||||||
ppos = N("GeometryNodeInputPosition"); ppos.location = (1650, -560)
|
|
||||||
pdir = N("ShaderNodeVectorMath"); pdir.location = (1800, -560)
|
|
||||||
pdir.operation = 'NORMALIZE'
|
|
||||||
L(ppos.outputs[0], pdir.inputs[0])
|
|
||||||
poff = N("ShaderNodeVectorMath"); poff.location = (2100, -520)
|
|
||||||
poff.operation = 'SCALE'
|
|
||||||
L(pdir.outputs[0], poff.inputs[0])
|
|
||||||
L(pamp.outputs[0], _sock(poff, "Scale"))
|
|
||||||
pset = N("GeometryNodeSetPosition"); pset.location = (2250, -100)
|
|
||||||
L(_out(circ, "Curve"), _sock(pset, "Geometry"))
|
|
||||||
L(poff.outputs[0], _sock(pset, "Offset"))
|
|
||||||
|
|
||||||
# ---------- UVs (Curve to Mesh erzeugt KEINE - gemessen!) ----------
|
cm = N("GeometryNodeCurveToMesh"); cm.location = (x + 500, y)
|
||||||
# V = echte Bogenlaenge entlang Stamm/Ast, U = Bogenlaenge um das Profil mal
|
L(_out(sw, "Geometry"), _sock(cm, "Curve"))
|
||||||
# Radius => world-space UVs: Rinde sitzt auf dickem Stamm und duennem Zweig
|
L(_out(prof, "Geometry"), _sock(cm, "Profile Curve"))
|
||||||
# gleich dicht. Attribute VOR Curve to Mesh ablegen, danach kombinieren.
|
# Falle 7 (Blender 5.x): Radius-Attribut wird NICHT mehr implizit
|
||||||
cspar = N("GeometryNodeSplineParameter"); cspar.location = (2250, 60)
|
# ausgewertet -> muss an den "Scale"-Eingang.
|
||||||
stv = N("GeometryNodeStoreNamedAttribute"); stv.location = (2400, 200)
|
if "Scale" in cm.inputs:
|
||||||
stv.domain = 'POINT'; stv.data_type = 'FLOAT'
|
ra = N("GeometryNodeInputRadius"); ra.location = (x + 350, y - 420)
|
||||||
L(_out(join, "Geometry"), _sock(stv, "Geometry"))
|
L(ra.outputs[0], _sock(cm, "Scale"))
|
||||||
_sock(stv, "Name").default_value = "uv_v"
|
try:
|
||||||
L(cspar.outputs["Length"], _sock(stv, "Value"))
|
_sock(cm, "Fill Caps").default_value = True
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
crad = N("GeometryNodeInputRadius"); crad.location = (2250, -80)
|
nu = N("GeometryNodeInputNamedAttribute"); nu.location = (x + 500, y - 200)
|
||||||
stw = N("GeometryNodeStoreNamedAttribute"); stw.location = (2550, 200)
|
nu.data_type = 'FLOAT'; _sock(nu, "Name").default_value = "uv_u"
|
||||||
stw.domain = 'POINT'; stw.data_type = 'FLOAT'
|
nv = N("GeometryNodeInputNamedAttribute"); nv.location = (x + 500, y - 320)
|
||||||
L(_out(stv, "Geometry"), _sock(stw, "Geometry"))
|
nv.data_type = 'FLOAT'; _sock(nv, "Name").default_value = "uv_v"
|
||||||
_sock(stw, "Name").default_value = "uv_r"
|
nr = N("GeometryNodeInputNamedAttribute"); nr.location = (x + 500, y - 440)
|
||||||
L(crad.outputs[0], _sock(stw, "Value"))
|
nr.data_type = 'FLOAT'; _sock(nr, "Name").default_value = "uv_r"
|
||||||
|
um = N("ShaderNodeMath"); um.location = (x + 650, y - 200); um.operation = 'MULTIPLY'
|
||||||
|
L(_out(nu, "Attribute"), um.inputs[0]); L(_out(nr, "Attribute"), um.inputs[1])
|
||||||
|
us_ = N("ShaderNodeMath"); us_.location = (x + 800, y - 200); us_.operation = 'MULTIPLY'
|
||||||
|
L(um.outputs[0], us_.inputs[0]); L(V["UV Scale"], us_.inputs[1])
|
||||||
|
vs_ = N("ShaderNodeMath"); vs_.location = (x + 800, y - 320); vs_.operation = 'MULTIPLY'
|
||||||
|
L(_out(nv, "Attribute"), vs_.inputs[0]); L(V["UV Scale"], vs_.inputs[1])
|
||||||
|
uv = N("ShaderNodeCombineXYZ"); uv.location = (x + 950, y - 260)
|
||||||
|
L(us_.outputs[0], uv.inputs["X"]); L(vs_.outputs[0], uv.inputs["Y"])
|
||||||
|
sm = N("GeometryNodeStoreNamedAttribute"); sm.location = (x + 1100, y)
|
||||||
|
sm.domain = 'CORNER'; sm.data_type = 'FLOAT2'
|
||||||
|
L(_out(cm, "Mesh", "Geometry"), _sock(sm, "Geometry"))
|
||||||
|
_sock(sm, "Name").default_value = "UVMap"
|
||||||
|
L(uv.outputs[0], _sock(sm, "Value"))
|
||||||
|
return sm
|
||||||
|
|
||||||
pspar2 = N("GeometryNodeSplineParameter"); pspar2.location = (2250, -700)
|
mesh_trunk = _to_mesh(setrad, "Curve", V["Sides"], 3400, 900)
|
||||||
stu = N("GeometryNodeStoreNamedAttribute"); stu.location = (2400, -100)
|
mesh_branch = _to_mesh(rsetp, "Geometry", V["Branch Sides"], 3400, 200)
|
||||||
stu.domain = 'POINT'; stu.data_type = 'FLOAT'
|
mesh_sub = _to_mesh(sbset, "Geometry", V["Sub Sides"], 3400, -500)
|
||||||
L(_out(pset, "Geometry"), _sock(stu, "Geometry"))
|
|
||||||
_sock(stu, "Name").default_value = "uv_u"
|
|
||||||
L(pspar2.outputs["Length"], _sock(stu, "Value"))
|
|
||||||
|
|
||||||
c2m = N("GeometryNodeCurveToMesh"); c2m.location = (1500, 200)
|
join = N("GeometryNodeJoinGeometry"); join.location = (4700, 300)
|
||||||
L(_out(stw, "Geometry"), _sock(c2m, "Curve"))
|
L(_out(mesh_sub, "Geometry"), join.inputs[0])
|
||||||
L(_out(stu, "Geometry"), _sock(c2m, "Profile Curve"))
|
L(_out(mesh_branch, "Geometry"), join.inputs[0])
|
||||||
# Falle 7 (Blender 5.x!): "Curve to Mesh" wertet das Radius-Attribut NICHT
|
L(_out(mesh_trunk, "Geometry"), join.inputs[0])
|
||||||
# mehr implizit aus, sondern hat einen eigenen "Scale"-Eingang. Ohne diese
|
stuv = join # Name beibehalten fuer den nachfolgenden Merge-Zweig
|
||||||
# Verbindung bleibt der Stamm immer bei Profil-Radius 1.0 (= 2 m dick),
|
|
||||||
# egal was "Trunk Radius" sagt. Gemessen: Stammbreite konstant 1.995.
|
|
||||||
if "Scale" in c2m.inputs:
|
|
||||||
radattr = N("GeometryNodeInputRadius"); radattr.location = (1350, -260)
|
|
||||||
L(radattr.outputs[0], _sock(c2m, "Scale"))
|
|
||||||
try:
|
|
||||||
_sock(c2m, "Fill Caps").default_value = True
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# UVMap aus den drei Attributen zusammensetzen (FACE_CORNER, sonst kein UV)
|
|
||||||
na_u = N("GeometryNodeInputNamedAttribute"); na_u.location = (2700, -300)
|
|
||||||
na_u.data_type = 'FLOAT'; _sock(na_u, "Name").default_value = "uv_u"
|
|
||||||
na_v = N("GeometryNodeInputNamedAttribute"); na_v.location = (2700, -420)
|
|
||||||
na_v.data_type = 'FLOAT'; _sock(na_v, "Name").default_value = "uv_v"
|
|
||||||
na_r = N("GeometryNodeInputNamedAttribute"); na_r.location = (2700, -540)
|
|
||||||
na_r.data_type = 'FLOAT'; _sock(na_r, "Name").default_value = "uv_r"
|
|
||||||
|
|
||||||
umul = N("ShaderNodeMath"); umul.location = (2880, -300); umul.operation = 'MULTIPLY'
|
|
||||||
L(_out(na_u, "Attribute"), umul.inputs[0]); L(_out(na_r, "Attribute"), umul.inputs[1])
|
|
||||||
us = N("ShaderNodeMath"); us.location = (3030, -300); us.operation = 'MULTIPLY'
|
|
||||||
L(umul.outputs[0], us.inputs[0]); L(V["UV Scale"], us.inputs[1])
|
|
||||||
vs = N("ShaderNodeMath"); vs.location = (3030, -420); vs.operation = 'MULTIPLY'
|
|
||||||
L(_out(na_v, "Attribute"), vs.inputs[0]); L(V["UV Scale"], vs.inputs[1])
|
|
||||||
uvvec = N("ShaderNodeCombineXYZ"); uvvec.location = (3180, -360)
|
|
||||||
L(us.outputs[0], uvvec.inputs["X"]); L(vs.outputs[0], uvvec.inputs["Y"])
|
|
||||||
|
|
||||||
stuv = N("GeometryNodeStoreNamedAttribute"); stuv.location = (1650, 60)
|
|
||||||
stuv.domain = 'CORNER'; stuv.data_type = 'FLOAT2'
|
|
||||||
L(_out(c2m, "Mesh", "Geometry"), _sock(stuv, "Geometry"))
|
|
||||||
_sock(stuv, "Name").default_value = "UVMap"
|
|
||||||
L(uvvec.outputs[0], _sock(stuv, "Value"))
|
|
||||||
|
|
||||||
# ---------- optional: Aeste mit dem Stamm VERSCHMELZEN ----------
|
# ---------- optional: Aeste mit dem Stamm VERSCHMELZEN ----------
|
||||||
# Voxel-Remesh (Mesh to Volume -> Volume to Mesh) macht aus den sich
|
# Voxel-Remesh (Mesh to Volume -> Volume to Mesh) macht aus den sich
|
||||||
|
|||||||
Reference in New Issue
Block a user