Spaces:
Running
on
Zero
Running
on
Zero
# 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 | |
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} | |
) | |
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} | |
) | |
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}, | |
) | |
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} | |
) | |
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} | |
) | |
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}, | |
) | |
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}) | |
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")}, | |
) | |
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} | |
) | |
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")}, | |
) | |
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() | |