Add cutout shell and volume node assets for depth volume processing
- Implemented `cutout_shell.py` to build front normals and shell positions for balloon geometry. - Created `cutout_volume.py` to establish smooth center fields and manage balloon surface attributes. - Introduced `pisa_sr_export.py` for exporting PiSA-SR components with dependencies and asset finalization.
This commit is contained in:
88
tools/node_assets/cutout_volume.py
Normal file
88
tools/node_assets/cutout_volume.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""Build the smooth center field for depth volume."""
|
||||
from node_graph import edge_boundary_field
|
||||
|
||||
|
||||
def node(group, kind, location):
|
||||
result = group.nodes.new(kind)
|
||||
result.location = location
|
||||
return result
|
||||
|
||||
|
||||
def shift_stage(group, previous, offset):
|
||||
for item in group.nodes:
|
||||
if item not in previous:
|
||||
item.location.x += offset[0]
|
||||
item.location.y += offset[1]
|
||||
|
||||
|
||||
def build_volume_fields(group, geometry, offset=(0, 0)):
|
||||
previous = set(group.nodes)
|
||||
boundary = edge_boundary_field(group.nodes, group.links, (0, -400))
|
||||
store = node(group, "GeometryNodeStoreNamedAttribute", (860, 0))
|
||||
store.domain, store.data_type = "POINT", "FLOAT"
|
||||
store.inputs["Name"].default_value = "o_balloon_surface_rim"
|
||||
group.links.new(geometry, store.inputs["Geometry"])
|
||||
group.links.new(boundary, store.inputs["Value"])
|
||||
profile = node(group, "GeometryNodeInputNamedAttribute", (860, 700))
|
||||
profile.data_type = "FLOAT"
|
||||
profile.inputs["Name"].default_value = "o_balloon"
|
||||
links = group.links
|
||||
def math(operation, a, b, location):
|
||||
result = node(group, "ShaderNodeMath", location)
|
||||
result.operation = operation
|
||||
for index, value in enumerate((a, b)):
|
||||
if isinstance(value, (int, float)):
|
||||
result.inputs[index].default_value = value
|
||||
else:
|
||||
links.new(value, result.inputs[index])
|
||||
return result.outputs[0]
|
||||
position = node(group, "GeometryNodeInputPosition", (860, 1100))
|
||||
axes = node(group, "ShaderNodeSeparateXYZ", (1100, 1100))
|
||||
links.new(position.outputs[0], axes.inputs[0])
|
||||
seed = math("SUBTRACT", axes.outputs["Z"], profile.outputs["Attribute"], (1340, 900))
|
||||
center = node(group, "GeometryNodeStoreNamedAttribute", (1340, 0))
|
||||
center.domain, center.data_type = "POINT", "FLOAT"
|
||||
center.inputs["Name"].default_value = "o_balloon_surface_center"
|
||||
links.new(store.outputs["Geometry"], center.inputs["Geometry"])
|
||||
links.new(seed, center.inputs["Value"])
|
||||
current = node(group, "GeometryNodeInputNamedAttribute", (1660, -330))
|
||||
current.data_type = "FLOAT"
|
||||
current.inputs["Name"].default_value = "o_balloon_surface_center"
|
||||
rim = node(group, "GeometryNodeInputNamedAttribute", (1660, -660))
|
||||
rim.data_type = "FLOAT"
|
||||
rim.inputs["Name"].default_value = "o_balloon_surface_rim"
|
||||
interior = math("SUBTRACT", 1, rim.outputs["Attribute"], (1890, -660))
|
||||
blur = node(group, "GeometryNodeBlurAttribute", (2120, -330))
|
||||
blur.data_type = "FLOAT"
|
||||
blur.inputs["Iterations"].default_value = 256
|
||||
links.new(current.outputs["Attribute"], blur.inputs["Value"])
|
||||
links.new(interior, blur.inputs["Weight"])
|
||||
update = node(group, "GeometryNodeStoreNamedAttribute", (2370, 0))
|
||||
update.domain, update.data_type = "POINT", "FLOAT"
|
||||
update.inputs["Name"].default_value = "o_balloon_surface_center"
|
||||
links.new(center.outputs["Geometry"], update.inputs["Geometry"])
|
||||
links.new(blur.outputs[0], update.inputs["Value"])
|
||||
baseline = node(group, "GeometryNodeInputNamedAttribute", (2940, 1000))
|
||||
baseline.data_type = "FLOAT"
|
||||
baseline.inputs["Name"].default_value = "o_balloon_surface_center"
|
||||
profile_end = node(group, "GeometryNodeInputNamedAttribute", (2940, 700))
|
||||
profile_end.data_type = "FLOAT"
|
||||
profile_end.inputs["Name"].default_value = "o_balloon"
|
||||
position_end = node(group, "GeometryNodeInputPosition", (2940, 1360))
|
||||
axes_end = node(group, "ShaderNodeSeparateXYZ", (3180, 1360))
|
||||
links.new(position_end.outputs[0], axes_end.inputs[0])
|
||||
residual = math("SUBTRACT", axes_end.outputs["Z"], baseline.outputs["Attribute"], (3420, 1000))
|
||||
full = math("ADD", residual, profile_end.outputs["Attribute"], (3660, 1000))
|
||||
minimum = math("MULTIPLY", profile_end.outputs["Attribute"], 0.05, (3420, 700))
|
||||
positive = math("MAXIMUM", full, minimum, (3900, 1000))
|
||||
control = node(group, "NodeGroupInput", (3900, 700))
|
||||
scaled = math("MULTIPLY", positive, control.outputs["Thickness"], (4140, 1000))
|
||||
thickness = node(group, "GeometryNodeStoreNamedAttribute", (4140, 0))
|
||||
thickness.domain, thickness.data_type = "POINT", "FLOAT"
|
||||
thickness.inputs["Name"].default_value = "o_balloon_surface_thickness"
|
||||
group.links.new(update.outputs["Geometry"], thickness.inputs["Geometry"])
|
||||
group.links.new(scaled, thickness.inputs["Value"])
|
||||
shift_stage(group, previous, offset)
|
||||
return thickness.outputs["Geometry"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user