DI-PCG / core /assets /flower.py
thuzhaowang's picture
init
b6a9b6d
raw
history blame
30.1 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: Alexander Raistrick, Alejandro Newell
# Code generated using version v2.0.1 of the node_transpiler
import bpy
import numpy as np
from numpy.random import normal, uniform
import infinigen
from infinigen.core import surface
from infinigen.core.nodes import node_utils
from infinigen.core.nodes.node_wrangler import Nodes
from infinigen.core.placement.factory import AssetFactory
from infinigen.core.tagging import tag_nodegroup, tag_object
from infinigen.core.util import blender as butil
from infinigen.core.util import color
from infinigen.core.util.math import FixedSeed, dict_lerp
@node_utils.to_nodegroup("nodegroup_polar_to_cart_old", singleton=True)
def nodegroup_polar_to_cart_old(nw):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketVector", "Addend", (0.0, 0.0, 0.0)),
("NodeSocketFloat", "Value", 0.5),
("NodeSocketVector", "Vector", (0.0, 0.0, 0.0)),
],
)
cosine = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Value"]},
attrs={"operation": "COSINE"},
)
sine = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Value"]},
attrs={"operation": "SINE"},
)
combine_xyz_4 = nw.new_node(Nodes.CombineXYZ, input_kwargs={"Y": cosine, "Z": sine})
multiply_add = nw.new_node(
Nodes.VectorMath,
input_kwargs={
0: group_input.outputs["Vector"],
1: combine_xyz_4,
2: group_input.outputs["Addend"],
},
attrs={"operation": "MULTIPLY_ADD"},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Vector": multiply_add.outputs["Vector"]}
)
@node_utils.to_nodegroup("nodegroup_follow_curve", singleton=True)
def nodegroup_follow_curve(nw):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Geometry", None),
("NodeSocketGeometry", "Curve", None),
("NodeSocketFloat", "Curve Min", 0.5),
("NodeSocketFloat", "Curve Max", 1.0),
],
)
position = nw.new_node(Nodes.InputPosition)
capture_attribute = nw.new_node(
Nodes.CaptureAttribute,
input_kwargs={"Geometry": group_input.outputs["Geometry"], 1: position},
attrs={"data_type": "FLOAT_VECTOR"},
)
separate_xyz = nw.new_node(
Nodes.SeparateXYZ,
input_kwargs={"Vector": capture_attribute.outputs["Attribute"]},
)
attribute_statistic = nw.new_node(
Nodes.AttributeStatistic,
input_kwargs={
"Geometry": capture_attribute.outputs["Geometry"],
2: separate_xyz.outputs["Z"],
},
)
map_range = nw.new_node(
Nodes.MapRange,
input_kwargs={
"Value": separate_xyz.outputs["Z"],
1: attribute_statistic.outputs["Min"],
2: attribute_statistic.outputs["Max"],
3: group_input.outputs["Curve Min"],
4: group_input.outputs["Curve Max"],
},
)
curve_length = nw.new_node(
Nodes.CurveLength, input_kwargs={"Curve": group_input.outputs["Curve"]}
)
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: map_range.outputs["Result"], 1: curve_length},
attrs={"operation": "MULTIPLY"},
)
sample_curve = nw.new_node(
Nodes.SampleCurve,
input_kwargs={"Curves": group_input.outputs["Curve"], "Length": multiply},
attrs={"mode": "LENGTH"},
)
cross_product = nw.new_node(
Nodes.VectorMath,
input_kwargs={
0: sample_curve.outputs["Tangent"],
1: sample_curve.outputs["Normal"],
},
attrs={"operation": "CROSS_PRODUCT"},
)
scale = nw.new_node(
Nodes.VectorMath,
input_kwargs={
0: cross_product.outputs["Vector"],
"Scale": separate_xyz.outputs["X"],
},
attrs={"operation": "SCALE"},
)
scale_1 = nw.new_node(
Nodes.VectorMath,
input_kwargs={
0: sample_curve.outputs["Normal"],
"Scale": separate_xyz.outputs["Y"],
},
attrs={"operation": "SCALE"},
)
add = nw.new_node(
Nodes.VectorMath,
input_kwargs={0: scale.outputs["Vector"], 1: scale_1.outputs["Vector"]},
)
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={
"Geometry": capture_attribute.outputs["Geometry"],
"Position": sample_curve.outputs["Position"],
"Offset": add.outputs["Vector"],
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": set_position}
)
@node_utils.to_nodegroup("nodegroup_norm_index", singleton=True)
def nodegroup_norm_index(nw):
index = nw.new_node(Nodes.Index)
group_input = nw.new_node(
Nodes.GroupInput, expose_input=[("NodeSocketInt", "Count", 0)]
)
divide = nw.new_node(
Nodes.Math,
input_kwargs={0: index, 1: group_input.outputs["Count"]},
attrs={"operation": "DIVIDE"},
)
group_output = nw.new_node(Nodes.GroupOutput, input_kwargs={"T": divide})
@node_utils.to_nodegroup("nodegroup_flower_petal", singleton=True)
def nodegroup_flower_petal(nw):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Geometry", None),
("NodeSocketFloat", "Length", 0.2),
("NodeSocketFloat", "Point", 1.0),
("NodeSocketFloat", "Point height", 0.5),
("NodeSocketFloat", "Bevel", 6.8),
("NodeSocketFloat", "Base width", 0.2),
("NodeSocketFloat", "Upper width", 0.3),
("NodeSocketInt", "Resolution H", 8),
("NodeSocketInt", "Resolution V", 4),
("NodeSocketFloat", "Wrinkle", 0.1),
("NodeSocketFloat", "Curl", 0.0),
],
)
multiply_add = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Resolution H"], 1: 2.0, 2: 1.0},
attrs={"operation": "MULTIPLY_ADD"},
)
grid = nw.new_node(
Nodes.MeshGrid,
input_kwargs={
"Vertices X": group_input.outputs["Resolution V"],
"Vertices Y": multiply_add,
},
)
position = nw.new_node(Nodes.InputPosition)
capture_attribute = nw.new_node(
Nodes.CaptureAttribute,
input_kwargs={"Geometry": grid, 1: position},
attrs={"data_type": "FLOAT_VECTOR"},
)
separate_xyz = nw.new_node(
Nodes.SeparateXYZ,
input_kwargs={"Vector": capture_attribute.outputs["Attribute"]},
)
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: separate_xyz.outputs["X"], 1: 0.05},
attrs={"operation": "MULTIPLY"},
)
combine_xyz = nw.new_node(
Nodes.CombineXYZ, input_kwargs={"X": multiply, "Y": separate_xyz.outputs["Y"]}
)
noise_texture = nw.new_node(
Nodes.NoiseTexture,
input_kwargs={
"Vector": combine_xyz,
"Scale": 7.9,
"Detail": 0.0,
"Distortion": 0.2,
},
attrs={"noise_dimensions": "2D"},
)
add = nw.new_node(
Nodes.Math, input_kwargs={0: noise_texture.outputs["Fac"], 1: -0.5}
)
multiply_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: add, 1: group_input.outputs["Wrinkle"]},
attrs={"operation": "MULTIPLY"},
)
separate_xyz_1 = nw.new_node(
Nodes.SeparateXYZ,
input_kwargs={"Vector": capture_attribute.outputs["Attribute"]},
)
add_1 = nw.new_node(Nodes.Math, input_kwargs={0: separate_xyz_1.outputs["X"]})
absolute = nw.new_node(
Nodes.Math,
input_kwargs={0: separate_xyz_1.outputs["Y"]},
attrs={"operation": "ABSOLUTE"},
)
multiply_2 = nw.new_node(
Nodes.Math, input_kwargs={0: absolute, 1: 2.0}, attrs={"operation": "MULTIPLY"}
)
power = nw.new_node(
Nodes.Math,
input_kwargs={0: multiply_2, 1: group_input.outputs["Bevel"]},
attrs={"operation": "POWER"},
)
multiply_add_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: power, 1: -1.0, 2: 1.0},
attrs={"operation": "MULTIPLY_ADD"},
)
multiply_3 = nw.new_node(
Nodes.Math,
input_kwargs={0: add_1, 1: multiply_add_1},
attrs={"operation": "MULTIPLY"},
)
multiply_add_2 = nw.new_node(
Nodes.Math,
input_kwargs={
0: multiply_3,
1: group_input.outputs["Upper width"],
2: group_input.outputs["Base width"],
},
attrs={"operation": "MULTIPLY_ADD"},
)
multiply_4 = nw.new_node(
Nodes.Math,
input_kwargs={0: separate_xyz_1.outputs["Y"], 1: multiply_add_2},
attrs={"operation": "MULTIPLY"},
)
power_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: absolute, 1: group_input.outputs["Point"]},
attrs={"operation": "POWER"},
)
multiply_add_3 = nw.new_node(
Nodes.Math,
input_kwargs={0: power_1, 1: -1.0, 2: 1.0},
attrs={"operation": "MULTIPLY_ADD"},
)
multiply_5 = nw.new_node(
Nodes.Math,
input_kwargs={0: multiply_add_3, 1: group_input.outputs["Point height"]},
attrs={"operation": "MULTIPLY"},
)
multiply_add_4 = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Point height"], 1: -1.0, 2: 1.0},
attrs={"operation": "MULTIPLY_ADD"},
)
add_2 = nw.new_node(Nodes.Math, input_kwargs={0: multiply_5, 1: multiply_add_4})
multiply_6 = nw.new_node(
Nodes.Math,
input_kwargs={0: add_2, 1: multiply_add_1},
attrs={"operation": "MULTIPLY"},
)
multiply_7 = nw.new_node(
Nodes.Math,
input_kwargs={0: add_1, 1: multiply_6},
attrs={"operation": "MULTIPLY"},
)
combine_xyz_1 = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={"X": multiply_1, "Y": multiply_4, "Z": multiply_7},
)
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={
"Geometry": capture_attribute.outputs["Geometry"],
"Position": combine_xyz_1,
},
)
multiply_8 = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Length"]},
attrs={"operation": "MULTIPLY"},
)
combine_xyz_3 = nw.new_node(Nodes.CombineXYZ, input_kwargs={"Y": multiply_8})
reroute = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Curl"]}
)
group_1 = nw.new_node(
nodegroup_polar_to_cart_old().name,
input_kwargs={"Addend": combine_xyz_3, "Value": reroute, "Vector": multiply_8},
)
quadratic_bezier = nw.new_node(
Nodes.QuadraticBezier,
input_kwargs={
"Resolution": 8,
"Start": (0.0, 0.0, 0.0),
"Middle": combine_xyz_3,
"End": group_1,
},
)
group = nw.new_node(
nodegroup_follow_curve().name,
input_kwargs={
"Geometry": set_position,
"Curve": quadratic_bezier,
"Curve Min": 0.0,
},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": tag_nodegroup(nw, group, "petal")}
)
@node_utils.to_nodegroup("nodegroup_phyllo_points", singleton=True)
def nodegroup_phyllo_points(nw):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketInt", "Count", 50),
("NodeSocketFloat", "Min Radius", 0.0),
("NodeSocketFloat", "Max Radius", 2.0),
("NodeSocketFloat", "Radius exp", 0.5),
("NodeSocketFloat", "Min angle", -0.5236),
("NodeSocketFloat", "Max angle", 0.7854),
("NodeSocketFloat", "Min z", 0.0),
("NodeSocketFloat", "Max z", 1.0),
("NodeSocketFloat", "Clamp z", 1.0),
("NodeSocketFloat", "Yaw offset", -1.5708),
],
)
mesh_line = nw.new_node(
Nodes.MeshLine, input_kwargs={"Count": group_input.outputs["Count"]}
)
mesh_to_points = nw.new_node(Nodes.MeshToPoints, input_kwargs={"Mesh": mesh_line})
position = nw.new_node(Nodes.InputPosition)
capture_attribute = nw.new_node(
Nodes.CaptureAttribute,
input_kwargs={"Geometry": mesh_to_points, 1: position},
attrs={"data_type": "FLOAT_VECTOR"},
)
index = nw.new_node(Nodes.Index)
cosine = nw.new_node(
Nodes.Math, input_kwargs={0: index}, attrs={"operation": "COSINE"}
)
sine = nw.new_node(Nodes.Math, input_kwargs={0: index}, attrs={"operation": "SINE"})
combine_xyz = nw.new_node(Nodes.CombineXYZ, input_kwargs={"X": cosine, "Y": sine})
divide = nw.new_node(
Nodes.Math,
input_kwargs={0: index, 1: group_input.outputs["Count"]},
attrs={"operation": "DIVIDE"},
)
power = nw.new_node(
Nodes.Math,
input_kwargs={0: divide, 1: group_input.outputs["Radius exp"]},
attrs={"operation": "POWER"},
)
map_range = nw.new_node(
Nodes.MapRange,
input_kwargs={
"Value": power,
3: group_input.outputs["Min Radius"],
4: group_input.outputs["Max Radius"],
},
)
multiply = nw.new_node(
Nodes.VectorMath,
input_kwargs={0: combine_xyz, 1: map_range.outputs["Result"]},
attrs={"operation": "MULTIPLY"},
)
separate_xyz = nw.new_node(
Nodes.SeparateXYZ, input_kwargs={"Vector": multiply.outputs["Vector"]}
)
map_range_2 = nw.new_node(
Nodes.MapRange,
input_kwargs={
"Value": divide,
2: group_input.outputs["Clamp z"],
3: group_input.outputs["Min z"],
4: group_input.outputs["Max z"],
},
)
combine_xyz_1 = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={
"X": separate_xyz.outputs["X"],
"Y": separate_xyz.outputs["Y"],
"Z": map_range_2.outputs["Result"],
},
)
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={
"Geometry": capture_attribute.outputs["Geometry"],
"Position": combine_xyz_1,
},
)
map_range_3 = nw.new_node(
Nodes.MapRange,
input_kwargs={
"Value": divide,
3: group_input.outputs["Min angle"],
4: group_input.outputs["Max angle"],
},
)
random_value = nw.new_node(Nodes.RandomValue, input_kwargs={2: -0.1, 3: 0.1})
add = nw.new_node(
Nodes.Math, input_kwargs={0: index, 1: group_input.outputs["Yaw offset"]}
)
combine_xyz_2 = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={
"X": map_range_3.outputs["Result"],
"Y": random_value.outputs[1],
"Z": add,
},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Points": set_position, "Rotation": combine_xyz_2},
)
@node_utils.to_nodegroup("nodegroup_plant_seed", singleton=True)
def nodegroup_plant_seed(nw):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketVector", "Dimensions", (0.0, 0.0, 0.0)),
("NodeSocketIntUnsigned", "U", 4),
("NodeSocketInt", "V", 8),
],
)
separate_xyz = nw.new_node(
Nodes.SeparateXYZ, input_kwargs={"Vector": group_input.outputs["Dimensions"]}
)
combine_xyz = nw.new_node(
Nodes.CombineXYZ, input_kwargs={"X": separate_xyz.outputs["X"]}
)
multiply_add = nw.new_node(
Nodes.VectorMath,
input_kwargs={0: combine_xyz, 1: (0.5, 0.5, 0.5)},
attrs={"operation": "MULTIPLY_ADD"},
)
quadratic_bezier_1 = nw.new_node(
Nodes.QuadraticBezier,
input_kwargs={
"Resolution": group_input.outputs["U"],
"Start": (0.0, 0.0, 0.0),
"Middle": multiply_add.outputs["Vector"],
"End": combine_xyz,
},
)
group = nw.new_node(
nodegroup_norm_index().name, input_kwargs={"Count": group_input.outputs["U"]}
)
float_curve = nw.new_node(Nodes.FloatCurve, input_kwargs={"Value": group})
node_utils.assign_curve(
float_curve.mapping.curves[0], [(0.0, 0.0), (0.3159, 0.4469), (1.0, 0.0156)]
)
map_range = nw.new_node(Nodes.MapRange, input_kwargs={"Value": float_curve, 4: 3.0})
set_curve_radius = nw.new_node(
Nodes.SetCurveRadius,
input_kwargs={
"Curve": quadratic_bezier_1,
"Radius": map_range.outputs["Result"],
},
)
curve_circle = nw.new_node(
Nodes.CurveCircle,
input_kwargs={
"Resolution": group_input.outputs["V"],
"Radius": separate_xyz.outputs["Y"],
},
)
curve_to_mesh = nw.new_node(
Nodes.CurveToMesh,
input_kwargs={
"Curve": set_curve_radius,
"Profile Curve": curve_circle.outputs["Curve"],
"Fill Caps": True,
},
)
group_output = nw.new_node(
Nodes.GroupOutput,
input_kwargs={"Mesh": tag_nodegroup(nw, curve_to_mesh, "seed")},
)
def shader_flower_center(nw):
ambient_occlusion = nw.new_node(Nodes.AmbientOcclusion)
colorramp = nw.new_node(
Nodes.ColorRamp, input_kwargs={"Fac": ambient_occlusion.outputs["Color"]}
)
colorramp.color_ramp.elements.new(1)
colorramp.color_ramp.elements[0].position = 0.4841
colorramp.color_ramp.elements[0].color = (0.0127, 0.0075, 0.0026, 1.0)
colorramp.color_ramp.elements[1].position = 0.8591
colorramp.color_ramp.elements[1].color = (0.0848, 0.0066, 0.0007, 1.0)
colorramp.color_ramp.elements[2].position = 1.0
colorramp.color_ramp.elements[2].color = (1.0, 0.6228, 0.1069, 1.0)
principled_bsdf = nw.new_node(
Nodes.PrincipledBSDF, input_kwargs={"Base Color": colorramp.outputs["Color"]}
)
material_output = nw.new_node(
Nodes.MaterialOutput, input_kwargs={"Surface": principled_bsdf}
)
def shader_petal(nw):
translucent_color_change = uniform(0.1, 0.6)
specular = normal(0.6, 0.1)
roughness = normal(0.4, 0.05)
translucent_amt = normal(0.3, 0.05)
petal_color = nw.new_node(Nodes.RGB)
petal_color.outputs[0].default_value = color.color_category("petal")
translucent_color = nw.new_node(
Nodes.MixRGB,
[translucent_color_change, petal_color, color.color_category("petal")],
)
translucent_bsdf = nw.new_node(
Nodes.TranslucentBSDF, input_kwargs={"Color": translucent_color}
)
principled_bsdf = nw.new_node(
Nodes.PrincipledBSDF,
input_kwargs={
"Base Color": petal_color,
"Specular": specular,
"Roughness": roughness,
},
)
mix_shader = nw.new_node(
Nodes.MixShader,
input_kwargs={"Fac": translucent_amt, 1: principled_bsdf, 2: translucent_bsdf},
)
material_output = nw.new_node(
Nodes.MaterialOutput, input_kwargs={"Surface": mix_shader}
)
def geo_flower(nw, petal_material, center_material):
group_input = nw.new_node(
Nodes.GroupInput,
expose_input=[
("NodeSocketGeometry", "Geometry", None),
("NodeSocketFloat", "Center Rad", 0.0),
("NodeSocketVector", "Petal Dims", (0.0, 0.0, 0.0)),
("NodeSocketFloat", "Seed Size", 0.0),
("NodeSocketFloat", "Min Petal Angle", 0.1),
("NodeSocketFloat", "Max Petal Angle", 1.36),
("NodeSocketFloat", "Wrinkle", 0.01),
("NodeSocketFloat", "Curl", 13.89),
],
)
uv_sphere = nw.new_node(
Nodes.MeshUVSphere,
input_kwargs={
"Segments": 8,
"Rings": 8,
"Radius": group_input.outputs["Center Rad"],
},
)
transform = nw.new_node(
Nodes.Transform, input_kwargs={"Geometry": uv_sphere, "Scale": (1.0, 1.0, 0.05)}
)
multiply = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Seed Size"], 1: 1.5},
attrs={"operation": "MULTIPLY"},
)
distribute_points_on_faces = nw.new_node(
Nodes.DistributePointsOnFaces,
input_kwargs={
"Mesh": transform,
"Distance Min": multiply,
"Density Max": 50000.0,
},
attrs={"distribute_method": "POISSON"},
)
multiply_1 = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Seed Size"], 1: 10.0},
attrs={"operation": "MULTIPLY"},
)
combine_xyz = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={"X": multiply_1, "Y": group_input.outputs["Seed Size"]},
)
group_3 = nw.new_node(
nodegroup_plant_seed().name,
input_kwargs={"Dimensions": combine_xyz, "U": 6, "V": 6},
)
musgrave_texture = nw.new_node(
Nodes.MusgraveTexture,
input_kwargs={"W": 13.8, "Scale": 2.41},
attrs={"musgrave_dimensions": "4D"},
)
map_range = nw.new_node(
Nodes.MapRange, input_kwargs={"Value": musgrave_texture, 3: 0.34, 4: 1.21}
)
combine_xyz_1 = nw.new_node(
Nodes.CombineXYZ,
input_kwargs={"X": map_range.outputs["Result"], "Y": 1.0, "Z": 1.0},
)
instance_on_points_1 = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": distribute_points_on_faces.outputs["Points"],
"Instance": group_3,
"Rotation": (0.0, -1.5708, 0.0541),
"Scale": combine_xyz_1,
},
)
realize_instances = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": instance_on_points_1}
)
join_geometry_1 = nw.new_node(
Nodes.JoinGeometry, input_kwargs={"Geometry": [realize_instances, transform]}
)
set_material_1 = nw.new_node(
Nodes.SetMaterial,
input_kwargs={"Geometry": join_geometry_1, "Material": center_material},
)
multiply_2 = nw.new_node(
Nodes.Math,
input_kwargs={0: group_input.outputs["Center Rad"], 1: 6.2832},
attrs={"operation": "MULTIPLY"},
)
separate_xyz = nw.new_node(
Nodes.SeparateXYZ, input_kwargs={"Vector": group_input.outputs["Petal Dims"]}
)
divide = nw.new_node(
Nodes.Math,
input_kwargs={0: multiply_2, 1: separate_xyz.outputs["Y"]},
attrs={"operation": "DIVIDE"},
)
multiply_3 = nw.new_node(
Nodes.Math, input_kwargs={0: divide, 1: 1.2}, attrs={"operation": "MULTIPLY"}
)
reroute_3 = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Center Rad"]}
)
reroute_1 = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Min Petal Angle"]}
)
reroute = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Max Petal Angle"]}
)
group_1 = nw.new_node(
nodegroup_phyllo_points().name,
input_kwargs={
"Count": multiply_3,
"Min Radius": reroute_3,
"Max Radius": reroute_3,
"Radius exp": 0.0,
"Min angle": reroute_1,
"Max angle": reroute,
"Max z": 0.0,
},
)
subtract = nw.new_node(
Nodes.Math,
input_kwargs={0: separate_xyz.outputs["Z"], 1: separate_xyz.outputs["Y"]},
attrs={"operation": "SUBTRACT", "use_clamp": True},
)
reroute_2 = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Wrinkle"]}
)
reroute_4 = nw.new_node(
Nodes.Reroute, input_kwargs={"Input": group_input.outputs["Curl"]}
)
group = nw.new_node(
nodegroup_flower_petal().name,
input_kwargs={
"Length": separate_xyz.outputs["X"],
"Point": 0.56,
"Point height": -0.1,
"Bevel": 1.83,
"Base width": separate_xyz.outputs["Y"],
"Upper width": subtract,
"Resolution H": 8,
"Resolution V": 16,
"Wrinkle": reroute_2,
"Curl": reroute_4,
},
)
instance_on_points = nw.new_node(
Nodes.InstanceOnPoints,
input_kwargs={
"Points": group_1.outputs["Points"],
"Instance": group,
"Rotation": group_1.outputs["Rotation"],
},
)
realize_instances_1 = nw.new_node(
Nodes.RealizeInstances, input_kwargs={"Geometry": instance_on_points}
)
noise_texture = nw.new_node(
Nodes.NoiseTexture,
input_kwargs={"Scale": 3.73, "Detail": 5.41, "Distortion": -1.0},
)
subtract_1 = nw.new_node(
Nodes.VectorMath,
input_kwargs={0: noise_texture.outputs["Color"], 1: (0.5, 0.5, 0.5)},
attrs={"operation": "SUBTRACT"},
)
value = nw.new_node(Nodes.Value)
value.outputs[0].default_value = 0.025
multiply_4 = nw.new_node(
Nodes.VectorMath,
input_kwargs={0: subtract_1.outputs["Vector"], 1: value},
attrs={"operation": "MULTIPLY"},
)
set_position = nw.new_node(
Nodes.SetPosition,
input_kwargs={
"Geometry": realize_instances_1,
"Offset": multiply_4.outputs["Vector"],
},
)
set_material = nw.new_node(
Nodes.SetMaterial,
input_kwargs={"Geometry": set_position, "Material": petal_material},
)
join_geometry = nw.new_node(
Nodes.JoinGeometry, input_kwargs={"Geometry": [set_material_1, set_material]}
)
set_shade_smooth = nw.new_node(
Nodes.SetShadeSmooth,
input_kwargs={"Geometry": join_geometry, "Shade Smooth": False},
)
group_output = nw.new_node(
Nodes.GroupOutput, input_kwargs={"Geometry": set_shade_smooth}
)
class FlowerFactory(AssetFactory):
def __init__(self, factory_seed, rad=0.15, diversity_fac=0.25):
super(FlowerFactory, self).__init__(factory_seed=factory_seed)
self.get_params_dict()
self.rad = rad
self.diversity_fac = diversity_fac
with FixedSeed(factory_seed):
self.petal_material = surface.shaderfunc_to_material(shader_petal)
self.center_material = surface.shaderfunc_to_material(shader_flower_center)
#self.species_params = self.get_flower_params(self.rad)
self.params = self.get_flower_params(self.rad * normal(1.0, 0.05))
def get_params_dict(self):
self.params_dict = {
"overall_rad": ['continuous', (0.7, 1.3)],
"pct_inner": ['continuous', (0.05, 0.5)],
"base_width": ['continuous', (4, 16)],
"top_width": ['continuous', (0.0, 1.6)],
"min_angle": ['continuous', (-20, 100)],
"max_angle": ['continuous', (-20, 100)],
"seed_size": ['continuous', (0.005, 0.03)],
"wrinkle": ['continuous', (0.003, 0.02)],
"curl": ['continuous', (-120, 120)],
}
@staticmethod
def get_flower_params(overall_rad=0.05):
pct_inner = uniform(0.05, 0.4)
base_width = 2 * np.pi * overall_rad * pct_inner / normal(20, 5)
top_width = overall_rad * np.clip(normal(0.7, 0.3), base_width * 1.2, 100)
min_angle, max_angle = np.deg2rad(np.sort(uniform(-20, 100, 2)))
return {
"Center Rad": overall_rad * pct_inner,
"Petal Dims": np.array(
[overall_rad * (1 - pct_inner), base_width, top_width], dtype=np.float32
),
"Seed Size": uniform(0.005, 0.01),
"Min Petal Angle": min_angle,
"Max Petal Angle": max_angle,
"Wrinkle": uniform(0.003, 0.02),
"Curl": np.deg2rad(normal(30, 50)),
}
def update_params(self, params):
overall_rad = params['overall_rad']
pct_inner = params['pct_inner']
base_width = 2 * np.pi * overall_rad * pct_inner / params['base_width']
top_width = overall_rad * np.clip(params['top_width'], base_width * 1.2, 100)
min_angle = np.deg2rad(params['min_angle'])
max_angle = np.deg2rad(params['max_angle'])
if min_angle > max_angle:
min_angle, max_angle = max_angle, min_angle
parameters = {
"Center Rad": overall_rad * pct_inner,
"Petal Dims": np.array(
[overall_rad * (1 - pct_inner), base_width, top_width], dtype=np.float32
),
"Seed Size": params['seed_size'],
"Min Petal Angle": min_angle,
"Max Petal Angle": max_angle,
"Wrinkle": params['wrinkle'],
"Curl": np.deg2rad(params['curl']),
}
self.params.update(parameters)
self.petal_material = surface.shaderfunc_to_material(shader_petal)
self.center_material = surface.shaderfunc_to_material(shader_flower_center)
def fix_unused_params(self, params):
return params
def create_asset(self, **kwargs) -> bpy.types.Object:
vert = butil.spawn_vert("flower")
mod = surface.add_geomod(
vert,
geo_flower,
input_kwargs={
"petal_material": self.petal_material,
"center_material": self.center_material,
},
)
#inst_params = self.get_flower_params(self.rad * normal(1, 0.05))
#params = dict_lerp(self.species_params, inst_params, 0.25)
butil.set_geomod_inputs(mod, self.params)
butil.apply_modifiers(vert, mod=mod)
vert.rotation_euler.z = uniform(0, 360)
tag_object(vert, "flower")
return vert