DI-PCG / core /assets /dandelion.py
thuzhaowang's picture
init
b6a9b6d
raw
history blame
34.4 kB
# Copyright (C) 2023, Princeton University.
# This source code is licensed under the BSD 3-Clause license found in the LICENSE file in the root directory of this source tree.
# Authors: Beining Han
# Acknowledgement: This file draws inspiration from https://www.youtube.com/watch?v=61Sk8j1Ml9c by BradleyAnimation
import bpy
import numpy as np
from numpy.random import normal, randint, uniform
import infinigen
from infinigen.assets.materials import simple_brownish, simple_greenery, simple_whitish
from infinigen.core import surface
from infinigen.core.nodes import node_utils
from infinigen.core.nodes.node_wrangler import Nodes, NodeWrangler
from infinigen.core.placement.factory import AssetFactory
from infinigen.core.tagging import tag_nodegroup, tag_object
from infinigen.core.util.math import FixedSeed
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_head_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_head_geometry(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketVectorTranslation", "Translation", (0.0, 0.0, 1.0)),
("NodeSocketFloatDistance", "Radius", 0.04),
],
)
uv_sphere_1 = nw.new_node(
Nodes.MeshUVSphere,
input_kwargs={"Segments": 64, "Radius": group_input.outputs["Radius"]},
)
transform_1 = nw.new_node(
Nodes.Transform,
input_kwargs={
"Geometry": uv_sphere_1,
"Translation": group_input.outputs["Translation"],
},
)
set_material = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": transform_1,
"Material": surface.shaderfunc_to_material(
simple_brownish.shader_simple_brown
),
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": set_material}
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_end_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_end_geometry(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketGeometry", "Points", None)]
)
endpoint_selection = nw.new_node(
"GeometryNodeCurveEndpointSelection", input_kwargs={"End Size": 0}
)
uv_sphere = nw.new_node(
Nodes.MeshUVSphere, input_kwargs={"Segments": 64, "Radius": 0.04}
)
vector = nw.new_node(Nodes.Vector)
vector.vector = (uniform(0.45, 0.7), uniform(0.45, 0.7), uniform(2, 3))
transform = nw.new_node(
Nodes.Transform, input_kwargs={"Geometry": uv_sphere, "Scale": vector}
)
cone = nw.new_node(
"GeometryNodeMeshCone", input_kwargs={"Radius Bottom": 0.0040, "Depth": 0.0040}
)
normal = nw.new_node(Nodes.InputNormal)
align_euler_to_vector_1 = nw.new_node(
Nodes.AlignEulerToVector, input_kwargs={"Vector": normal}, attrs={"axis": "Z"}
)
instance_on_points_1 = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": transform,
"Instance": cone.outputs["Mesh"],
"Rotation": align_euler_to_vector_1,
},
)
join_geometry = nw.new_node(
Nodes.JoinGeometry, input_kwargs={"Geometry": [instance_on_points_1, transform]}
)
set_material = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": join_geometry,
"Material": surface.shaderfunc_to_material(
simple_brownish.shader_simple_brown
),
},
)
geometry_to_instance = nw.new_node(
"GeometryNodeGeometryToInstance", input_kwargs={"Geometry": set_material}
)
curve_tangent = nw.new_node(Nodes.CurveTangent)
align_euler_to_vector = nw.new_node(
Nodes.AlignEulerToVector,
input_kwargs={"Vector": curve_tangent},
attrs={"axis": "Z"},
)
instance_on_points = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": group_input.outputs["Points"],
"Selection": endpoint_selection,
"Instance": geometry_to_instance,
"Rotation": align_euler_to_vector,
},
)
realize_instances = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": instance_on_points}
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": realize_instances}
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_branch_shape", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_branch_shape(nw: NodeWrangler):
# Code generated using version 2.6.4 of the node_transpiler
pedal_stem_branches_num = nw.new_node(
Nodes.Integer, label="pedal_stem_branches_num"
)
pedal_stem_branches_num.integer = 40
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketFloatDistance", "Radius", 0.0100)]
)
curve_circle_1 = nw.new_node(
Nodes.CurveCircle,
input_kwargs={
"Resolution": pedal_stem_branches_num,
"Radius": group_input.outputs["Radius"],
},
)
pedal_stem_branch_length = nw.new_node(
Nodes.Value, label="pedal_stem_branch_length"
)
pedal_stem_branch_length.outputs[0].default_value = 0.5000
combine_xyz_1 = nw.new_node(
Nodes.CombineXYZ, input_kwargs={"X": pedal_stem_branch_length}
)
curve_line_1 = nw.new_node(Nodes.CurveLine, input_kwargs={"End": combine_xyz_1})
resample_curve = nw.new_node(
Nodes.ResampleCurve, input_kwargs={"Curve": curve_line_1, "Count": 40}
)
spline_parameter = nw.new_node(Nodes.SplineParameter)
float_curve = nw.new_node(
Nodes.FloatCurve, input_kwargs={"Value": spline_parameter.outputs["Factor"]}
)
node_utils.assign_curve(
float_curve.mapping.curves[0],
[
(0.0000, 0.0000),
(0.2, 0.08 * np.random.normal(1.0, 0.15)),
(0.4, 0.22 * np.random.normal(1.0, 0.2)),
(0.6, 0.45 * np.random.normal(1.0, 0.2)),
(0.8, 0.7 * np.random.normal(1.0, 0.1)),
(1.0000, 1.0000),
],
)
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: float_curve, 1: uniform(0.15, 0.4)},
attrs={"operation": "MULTIPLY"},
)
combine_xyz = nw.new_node(Nodes.CombineXYZ, input_kwargs={"Z": multiply})
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={"Geometry": resample_curve, "Offset": combine_xyz},
)
normal = nw.new_node(Nodes.InputNormal)
align_euler_to_vector = nw.new_node(
Nodes.AlignEulerToVector, input_kwargs={"Vector": normal}
)
instance_on_points = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": curve_circle_1.outputs["Curve"],
"Instance": set_position,
"Rotation": align_euler_to_vector,
},
)
random_value_1 = nw.new_node(
Nodes.RandomValue, input_kwargs={2: -0.2000, 3: 0.2000, "Seed": 2}
)
random_value_2 = nw.new_node(
Nodes.RandomValue, input_kwargs={2: -0.2000, 3: 0.2000, "Seed": 1}
)
random_value = nw.new_node(Nodes.RandomValue, input_kwargs={2: -0.2000, 3: 0.2000})
combine_xyz_2 = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={
"X": random_value_1.outputs[1],
"Y": random_value_2.outputs[1],
"Z": random_value.outputs[1],
},
)
rotate_instances = nw.new_node(
Nodes.RotateInstances,
input_kwargs={"Instances": instance_on_points, "Rotation": combine_xyz_2},
)
random_value_3 = nw.new_node(Nodes.RandomValue, input_kwargs={2: 0.8000})
scale_instances = nw.new_node(
Nodes.ScaleInstances,
input_kwargs={
"Instances": rotate_instances,
"Scale": random_value_3.outputs[1],
},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Instances": scale_instances},
attrs={"is_active_output": True},
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_branch_contour", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_branch_contour(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketGeometry", "Geometry", None)]
)
realize_instances = nw.new_node(
Nodes.RealizeInstances,
input_kwargs={"Geometry": group_input.outputs["Geometry"]},
)
pedal_stem_branch_rsample = nw.new_node(
Nodes.Value, label="pedal_stem_branch_rsample"
)
pedal_stem_branch_rsample.outputs[0].default_value = 10.0
resample_curve = nw.new_node(
Nodes.ResampleCurve,
input_kwargs={"Curve": realize_instances, "Count": pedal_stem_branch_rsample},
)
index = nw.new_node(Nodes.Index)
capture_attribute = nw.new_node(
Nodes.CaptureAttribute,
input_kwargs={"Geometry": resample_curve, 5: index},
attrs={"domain": "CURVE", "data_type": "INT"},
)
spline_parameter = nw.new_node(Nodes.SplineParameter)
float_curve = nw.new_node(
Nodes.FloatCurve, input_kwargs={"Value": spline_parameter.outputs["Factor"]}
)
# generate pedal branch contour
dist = uniform(-0.05, -0.25)
node_utils.assign_curve(
float_curve.mapping.curves[0],
[
(0.0, 0.0),
(0.2, 0.2 + (dist + normal(0, 0.05)) / 2.0),
(0.4, 0.4 + (dist + normal(0, 0.05))),
(0.6, 0.6 + (dist + normal(0, 0.05)) / 1.2),
(0.8, 0.8 + (dist + normal(0, 0.05)) / 2.4),
(1.0, 0.95 + normal(0, 0.05)),
],
)
random_value = nw.new_node(
Nodes.RandomValue,
input_kwargs={2: 0.05, 3: 0.35, "ID": capture_attribute.outputs[5]},
)
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: float_curve, 1: random_value.outputs[1]},
attrs={"operation": "MULTIPLY"},
)
combine_xyz = nw.new_node(Nodes.CombineXYZ, input_kwargs={"Z": multiply})
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={
"Geometry": capture_attribute.outputs["Geometry"],
"Offset": combine_xyz,
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": set_position}
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_branch_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_branch_geometry(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Curve", None),
("NodeSocketVectorTranslation", "Translation", (0.0, 0.0, 1.0)),
],
)
set_curve_radius_1 = nw.new_node(
Nodes.SetCurveRadius,
input_kwargs={"Curve": group_input.outputs["Curve"], "Radius": 1.0},
)
curve_circle_2 = nw.new_node(
Nodes.CurveCircle,
input_kwargs={"Radius": uniform(0.001, 0.0025), "Resolution": 4},
)
curve_to_mesh_1 = nw.new_node(
Nodes.CurveToMesh,
input_kwargs={
"Curve": set_curve_radius_1,
"Profile Curve": curve_circle_2.outputs["Curve"],
"Fill Caps": True,
},
)
transform_2 = nw.new_node(
Nodes.Transform,
input_kwargs={
"Geometry": curve_to_mesh_1,
"Translation": group_input.outputs["Translation"],
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": transform_2}
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem_geometry(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketVectorTranslation", "End", (0.0, 0.0, 1.0)),
("NodeSocketVectorTranslation", "Middle", (0.0, 0.0, 0.5)),
("NodeSocketFloatDistance", "Radius", 0.05),
],
)
quadratic_bezier = nw.new_node(
Nodes.QuadraticBezier,
input_kwargs={
"Start": (0.0, 0.0, 0.0),
"Middle": group_input.outputs["Middle"],
"End": group_input.outputs["End"],
},
)
set_curve_radius = nw.new_node(
Nodes.SetCurveRadius,
input_kwargs={
"Curve": quadratic_bezier,
"Radius": group_input.outputs["Radius"],
},
)
curve_circle = nw.new_node(
Nodes.CurveCircle, input_kwargs={"Radius": 0.2, "Resolution": 8}
)
curve_to_mesh = nw.new_node(
Nodes.CurveToMesh,
input_kwargs={
"Curve": set_curve_radius,
"Profile Curve": curve_circle.outputs["Curve"],
"Fill Caps": True,
},
)
set_material_2 = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": curve_to_mesh,
"Material": surface.shaderfunc_to_material(
simple_whitish.shader_simple_white
),
},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Geometry": set_material_2, "Curve": quadratic_bezier},
)
@node_utils.to_nodegroup(
"nodegroup_pedal_selection", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_selection(nw: NodeWrangler, params):
# Code generated using version 2.4.3 of the node_transpiler
random_value = nw.new_node(Nodes.RandomValue, input_kwargs={5: 1})
greater_than = nw.new_node(
Nodes.Math,
input_kwargs={0: params["random_dropout"], 1: random_value.outputs[1]},
attrs={"operation": "GREATER_THAN"},
)
index_1 = nw.new_node(Nodes.Index)
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketFloat", "num_segments", 0.5)]
)
divide = nw.new_node(
Nodes.Math,
input_kwargs={0: index_1, 1: group_input.outputs["num_segments"]},
attrs={"operation": "DIVIDE"},
)
less_than = nw.new_node(
Nodes.Math,
input_kwargs={0: divide, 1: params["row_less_than"]},
attrs={"operation": "LESS_THAN"},
)
greater_than_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: divide, 1: params["row_great_than"]},
attrs={"operation": "GREATER_THAN"},
)
op_and = nw.new_node(
Nodes.BooleanMath, input_kwargs={0: less_than, 1: greater_than_1}
)
modulo = nw.new_node(
Nodes.Math,
input_kwargs={0: index_1, 1: group_input.outputs["num_segments"]},
attrs={"operation": "MODULO"},
)
less_than_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: modulo, 1: params["col_less_than"]},
attrs={"operation": "LESS_THAN"},
)
greater_than_2 = nw.new_node(
Nodes.Math,
input_kwargs={0: modulo, 1: params["col_great_than"]},
attrs={"operation": "GREATER_THAN"},
)
op_and_1 = nw.new_node(
Nodes.BooleanMath, input_kwargs={0: less_than_1, 1: greater_than_2}
)
nand = nw.new_node(
Nodes.BooleanMath,
input_kwargs={0: op_and, 1: op_and_1},
attrs={"operation": "NAND"},
)
op_and_2 = nw.new_node(Nodes.BooleanMath, input_kwargs={0: greater_than, 1: nand})
group_output = nw.new_node(Nodes.GroupOutput, input_kwargs={"Boolean": op_and_2})
@node_utils.to_nodegroup(
"nodegroup_stem_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_stem_geometry(nw: NodeWrangler, params):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Curve", None),
]
)
spline_parameter = nw.new_node(Nodes.SplineParameter)
value = nw.new_node(Nodes.Value)
value.outputs[0].default_value = params["stem_map_range"]
map_range = nw.new_node(
Nodes.MapRange,
input_kwargs={"Value": spline_parameter.outputs["Factor"], 3: 0.4, 4: value},
)
set_curve_radius_2 = nw.new_node(
Nodes.SetCurveRadius,
input_kwargs={
"Curve": group_input.outputs["Curve"],
"Radius": map_range.outputs["Result"],
},
)
stem_radius = nw.new_node(Nodes.Value, label="stem_radius")
stem_radius.outputs[0].default_value = params["stem_radius"]
curve_circle_3 = nw.new_node(
Nodes.CurveCircle, input_kwargs={"Radius": stem_radius}
)
curve_to_mesh_2 = nw.new_node(
Nodes.CurveToMesh,
input_kwargs={
"Curve": set_curve_radius_2,
"Profile Curve": curve_circle_3.outputs["Curve"],
"Fill Caps": True,
},
)
set_material = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": curve_to_mesh_2,
"Material": surface.shaderfunc_to_material(
simple_greenery.shader_simple_greenery
),
},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Mesh": tag_nodegroup(nw, set_material, "stem")},
)
@node_utils.to_nodegroup(
"nodegroup_pedal_stem", singleton=False, type="GeometryNodeTree"
)
def nodegroup_pedal_stem(nw: NodeWrangler, params):
# Code generated using version 2.4.3 of the node_transpiler
pedal_stem_top_point = nw.new_node(Nodes.Vector, label="pedal_stem_top_point")
pedal_stem_top_point.vector = (0.0, 0.0, 1.0)
pedal_stem_mid_point = nw.new_node(Nodes.Vector, label="pedal_stem_mid_point")
pedal_stem_mid_point.vector = (
params["pedal_stem_mid_point_x"],
params["pedal_stem_mid_point_y"],
0.5
)
pedal_stem_radius = nw.new_node(Nodes.Value, label="pedal_stem_radius")
pedal_stem_radius.outputs[0].default_value = params["pedal_stem_radius"]
pedal_stem_geometry = nw.new_node(
nodegroup_pedal_stem_geometry().name,
input_kwargs={
"End": pedal_stem_top_point,
"Middle": pedal_stem_mid_point,
"Radius": pedal_stem_radius,
},
)
pedal_stem_top_radius = nw.new_node(Nodes.Value, label="pedal_stem_top_radius")
pedal_stem_top_radius.outputs[0].default_value = params["pedal_stem_top_radius"]
pedal_stem_branch_shape = nw.new_node(
nodegroup_pedal_stem_branch_shape().name,
input_kwargs={"Radius": pedal_stem_top_radius},
)
pedal_stem_branch_geometry = nw.new_node(
nodegroup_pedal_stem_branch_geometry().name,
input_kwargs={
"Curve": pedal_stem_branch_shape,
"Translation": pedal_stem_top_point,
},
)
set_material_3 = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": pedal_stem_branch_geometry,
"Material": surface.shaderfunc_to_material(
simple_whitish.shader_simple_white
),
},
)
resample_curve = nw.new_node(
Nodes.ResampleCurve,
input_kwargs={"Curve": pedal_stem_geometry.outputs["Curve"]},
)
pedal_stem_end_geometry = nw.new_node(
nodegroup_pedal_stem_end_geometry().name,
input_kwargs={"Points": resample_curve},
)
pedal_stem_head_geometry = nw.new_node(
nodegroup_pedal_stem_head_geometry().name,
input_kwargs={
"Translation": pedal_stem_top_point,
"Radius": pedal_stem_top_radius,
},
)
join_geometry = nw.new_node(
Nodes.JoinGeometry,
input_kwargs={
"Geometry": [
pedal_stem_geometry.outputs["Geometry"],
set_material_3,
pedal_stem_end_geometry,
pedal_stem_head_geometry,
]
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": join_geometry}
)
@node_utils.to_nodegroup(
"nodegroup_flower_geometry", singleton=False, type="GeometryNodeTree"
)
def nodegroup_flower_geometry(nw: NodeWrangler, params):
# Code generated using version 2.4.3 of the node_transpiler
num_core_segments = nw.new_node(
Nodes.Integer, label="num_core_segments", attrs={"integer": 10}
)
num_core_segments.integer = params["flower_num_core_segments"]
num_core_rings = nw.new_node(
Nodes.Integer, label="num_core_rings", attrs={"integer": 10}
)
num_core_rings.integer = params["flower_num_core_rings"]
uv_sphere_2 = nw.new_node(
Nodes.MeshUVSphere,
input_kwargs={
"Segments": num_core_segments,
"Rings": num_core_rings,
"Radius": params["flower_radius"],
},
)
flower_core_shape = nw.new_node(Nodes.Vector, label="flower_core_shape")
flower_core_shape.vector = (params["flower_core_shape_x"], params["flower_core_shape_y"], params["flower_core_shape_z"])
transform = nw.new_node(
Nodes.Transform,
input_kwargs={"Geometry": uv_sphere_2, "Scale": flower_core_shape},
)
selection_params = {
"random_dropout": params["random_dropout"],
"row_less_than": int(params["row_less_than"] * num_core_rings.integer),
"row_great_than": int(params["row_great_than"] * num_core_rings.integer),
"col_less_than": int(params["col_less_than"] * num_core_segments.integer),
"col_great_than": int(params["col_less_than"] * num_core_segments.integer),
}
pedal_selection = nw.new_node(
nodegroup_pedal_selection(params=selection_params).name,
input_kwargs={"num_segments": num_core_segments},
)
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketGeometry", "Instance", None)]
)
normal_1 = nw.new_node(Nodes.InputNormal)
align_euler_to_vector_1 = nw.new_node(
Nodes.AlignEulerToVector, input_kwargs={"Vector": normal_1}, attrs={"axis": "Z"}
)
random_value_1 = nw.new_node(Nodes.RandomValue, input_kwargs={2: 0.4, 3: 0.7})
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: random_value_1.outputs[1]},
attrs={"operation": "MULTIPLY"},
)
instance_on_points_1 = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": transform,
"Selection": pedal_selection,
"Instance": group_input.outputs["Instance"],
"Rotation": align_euler_to_vector_1,
"Scale": multiply,
},
)
realize_instances_1 = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": instance_on_points_1}
)
set_material = nw.new_node(
Nodes.SetMaterial,
input_kwargs={
"Geometry": transform,
"Material": surface.shaderfunc_to_material(
simple_whitish.shader_simple_white
),
},
)
join_geometry_1 = nw.new_node(
Nodes.JoinGeometry,
input_kwargs={"Geometry": [realize_instances_1, set_material]},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Geometry": tag_nodegroup(nw, join_geometry_1, "flower")},
)
@node_utils.to_nodegroup(
"nodegroup_flower_on_stem", singleton=False, type="GeometryNodeTree"
)
def nodegroup_flower_on_stem(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Points", None),
("NodeSocketGeometry", "Instance", None),
],
)
endpoint_selection = nw.new_node(
"GeometryNodeCurveEndpointSelection", input_kwargs={"Start Size": 0}
)
curve_tangent = nw.new_node(Nodes.CurveTangent)
align_euler_to_vector_2 = nw.new_node(
Nodes.AlignEulerToVector,
input_kwargs={"Vector": curve_tangent},
attrs={"axis": "Z"},
)
instance_on_points_2 = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": group_input.outputs["Points"],
"Selection": endpoint_selection,
"Instance": group_input.outputs["Instance"],
"Rotation": align_euler_to_vector_2,
},
)
realize_instances_2 = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": instance_on_points_2}
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Instances": realize_instances_2}
)
def geometry_dandelion_nodes(nw: NodeWrangler, **kwargs):
# Code generated using version 2.4.3 of the node_transpiler
quadratic_bezier_1 = nw.new_node(
Nodes.QuadraticBezier,
input_kwargs={
"Start": (0.0, 0.0, 0.0),
"Middle": (kwargs["bezier_middle_x"], kwargs["bezier_middle_y"], 0.5),
"End": (kwargs["bezier_end_x"], kwargs["bezier_end_y"], 1.0),
},
)
resample_curve = nw.new_node(
Nodes.ResampleCurve, input_kwargs={"Curve": quadratic_bezier_1}
)
pedal_stem = nw.new_node(
nodegroup_pedal_stem(kwargs).name,
input_kwargs={},
)
geometry_to_instance = nw.new_node(
"GeometryNodeGeometryToInstance", input_kwargs={"Geometry": pedal_stem}
)
flower_geometry = nw.new_node(
nodegroup_flower_geometry(kwargs).name,
input_kwargs={"Instance": geometry_to_instance},
)
geometry_to_instance_1 = nw.new_node(
"GeometryNodeGeometryToInstance", input_kwargs={"Geometry": flower_geometry}
)
value_2 = nw.new_node(Nodes.Value)
value_2.outputs[0].default_value = kwargs["transform_scale"]
transform_3 = nw.new_node(
Nodes.Transform,
input_kwargs={"Geometry": geometry_to_instance_1, "Scale": value_2},
)
flower_on_stem = nw.new_node(
nodegroup_flower_on_stem().name,
input_kwargs={"Points": resample_curve, "Instance": transform_3},
)
stem_geometry = nw.new_node(
nodegroup_stem_geometry(kwargs).name,
input_kwargs={
"Curve": quadratic_bezier_1,
}
)
join_geometry_2 = nw.new_node(
Nodes.JoinGeometry, input_kwargs={"Geometry": [flower_on_stem, stem_geometry]}
)
realize_instances = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": join_geometry_2}
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": realize_instances}
)
def geometry_dandelion_seed_nodes(nw: NodeWrangler, **kwargs):
# Code generated using version 2.4.3 of the node_transpiler
pedal_stem = nw.new_node(nodegroup_pedal_stem().name)
geometry_to_instance = nw.new_node(
"GeometryNodeGeometryToInstance", input_kwargs={"Geometry": pedal_stem}
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": geometry_to_instance}
)
flower_modes_dict = {
0: "full_flower",
1: "no_flower",
2: "sparse_flower",
}
class DandelionFactory(AssetFactory):
def __init__(self, factory_seed, coarse=False):
super(DandelionFactory, self).__init__(factory_seed, coarse=coarse)
self.get_params_dict()
with FixedSeed(factory_seed):
self.sample_parameters()
def get_params_dict(self):
# list all the parameters (key:name, value: [type, range]) used in this generator
self.params_dict = {
"flower_mode": ["discrete", (0, 1, 2)],
"random_dropout": ["continuous", (0.2, 0.6)],
"row_less_than": ["continuous", (0.0, 1.0)],
"col_less_than": ["continuous", (0.0, 1.0)],
"row_great_than": ["continuous", (0.0, 1.0)],
"col_great_than": ["continuous", (0.0, 1.0)],
"bezier_middle_x": ["continuous", (-0.6, 0.6)],
"bezier_middle_y": ["continuous", (-0.6, 0.6)],
"bezier_end_x": ["continuous", (-0.6, 0.6)],
"bezier_end_y": ["continuous", (-0.6, 0.6)],
"flower_num_core_segments": ["discrete", (8, 15, 20, 25)],
"flower_num_core_rings": ["discrete", (8, 15, 20)],
"transform_scale": ["continuous", (-0.7, -0.1)],
"stem_map_range": ["continuous", (0.1, 0.6)],
"stem_radius": ["continuous", (0.01, 0.03)],
}
def sample_parameters(self):
# sample all the parameters
flower_mode = flower_modes_dict[randint(0, 2)]
if flower_mode == "full_flower":
random_dropout = 1.0
row_less_than = 0.0
row_great_than = 0.0
col_less_than = 0.0
col_great_than = 0.0
elif flower_mode == "no_flower":
random_dropout = 0.0
row_less_than = 1.0
row_great_than = 0.0
col_less_than = 1.0
col_great_than = 0.0
elif flower_mode == "sparse_flower":
random_dropout = uniform(0.2, 0.6)
row_less_than = 0.0
row_great_than = 0.0
col_less_than = 0.0
col_great_than = 0.0
else:
raise ValueError("Invalid flower mode")
self.params = {
"flower_mode": flower_mode,
"random_dropout": random_dropout,
"row_less_than": row_less_than,
"row_great_than": row_great_than,
"col_less_than": col_less_than,
"col_great_than": col_great_than,
"bezier_middle_x": normal(0.0, 0.1),
"bezier_middle_y": normal(0.0, 0.1),
"bezier_end_x": normal(0.0, 0.1),
"bezier_end_y": normal(0.0, 0.1),
"pedal_stem_mid_point_x": normal(0.0, 0.05),
"pedal_stem_mid_point_y": normal(0.0, 0.05),
"pedal_stem_radius": uniform(0.02, 0.045),
"pedal_stem_top_radius": uniform(0.005, 0.008),
"flower_num_core_segments": randint(8, 25),
"flower_num_core_rings": randint(8, 20),
"flower_radius": uniform(0.02, 0.05),
"flower_core_shape_x": uniform(0.8, 1.2),
"flower_core_shape_y": uniform(0.8, 1.2),
"flower_core_shape_z": uniform(0.5, 0.8),
"transform_scale": uniform(-0.5, -0.15),
"stem_map_range": uniform(0.2, 0.4),
"stem_radius": uniform(0.01, 0.024),
}
def fix_unused_params(self, params):
return params
def update_params(self, params):
# update the parameters in the node graph
flower_mode = flower_modes_dict[params["flower_mode"]]
if flower_mode == "full_flower":
random_dropout = uniform(0.7, 1.0)
row_less_than = 0.0
row_great_than = 0.0
col_less_than = 0.0
col_great_than = 0.0
elif flower_mode == "no_flower":
random_dropout = 0.0
row_less_than = 1.0
row_great_than = 0.0
col_less_than = 1.0
col_great_than = 0.0
elif flower_mode == "sparse_flower":
random_dropout = params["random_dropout"]
row_less_than = params["row_less_than"]
row_great_than = params["row_great_than"]
col_less_than = params["col_less_than"]
col_great_than = params["col_great_than"]
else:
raise ValueError("Invalid flower mode")
params = {
"flower_mode": flower_mode,
"random_dropout": random_dropout,
"row_less_than": row_less_than,
"row_great_than": row_great_than,
"col_less_than": col_less_than,
"col_great_than": col_great_than,
"bezier_middle_x": params["bezier_middle_x"],
"bezier_middle_y": params["bezier_middle_y"],
"bezier_end_x": params["bezier_end_x"],
"bezier_end_y": params["bezier_end_y"],
"flower_num_core_segments": int(params["flower_num_core_segments"]),
"flower_num_core_rings": int(params["flower_num_core_rings"]),
"flower_radius": uniform(0.02, 0.05),
"flower_core_shape_x": uniform(0.8, 1.2),
"flower_core_shape_y": uniform(0.8, 1.2),
"flower_core_shape_z": uniform(0.5, 0.8),
"pedal_stem_mid_point_x": normal(0.0, 0.05),
"pedal_stem_mid_point_y": normal(0.0, 0.05),
"pedal_stem_radius": uniform(0.02, 0.045),
"pedal_stem_top_radius": uniform(0.005, 0.008),
"transform_scale": params["transform_scale"],
"stem_map_range": params["stem_map_range"],
"stem_radius": params["stem_radius"],
}
self.params.update(params)
def create_asset(self, **params):
bpy.ops.mesh.primitive_plane_add(
size=1,
enter_editmode=False,
align="WORLD",
location=(0, 0, 0),
scale=(1, 1, 1),
)
obj = bpy.context.active_object
surface.add_geomod(
obj,
geometry_dandelion_nodes,
apply=True,
attributes=[],
input_kwargs=self.params,
)
tag_object(obj, "dandelion")
return obj
class DandelionSeedFactory(AssetFactory):
def __init__(self, factory_seed, coarse=False):
super(DandelionSeedFactory, self).__init__(factory_seed, coarse=coarse)
def create_asset(self, **params):
bpy.ops.mesh.primitive_plane_add(
size=1,
enter_editmode=False,
align="WORLD",
location=(0, 0, 0),
scale=(1, 1, 1),
)
obj = bpy.context.active_object
surface.add_geomod(
obj,
geometry_dandelion_seed_nodes,
apply=True,
attributes=[],
input_kwargs=params,
)
tag_object(obj, "seed")
return obj
if __name__ == "__main__":
f = DandelionSeedFactory(0)
obj = f.create_asset()