# 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