feat(node_assets): add image plane geometry nodes and validation scripts
- Implemented `image_plane.py` to build the Image Plane Geometry Nodes group with customizable parameters for geometry, subdivide, and thickness. - Created `image_plane_validation.py` to validate the functionality of the image plane, ensuring correct geometry generation and material assignment. - Developed `material_layers.py` to construct shader node groups for image materials, including depth and normal handling. - Authored `plane_layouts.py` to define node arrangements for image geometry assets. - Introduced `shadeless.py` to create a shadeless shader node group that displays color without scene lighting while preserving shadows and reflections.
This commit is contained in:
145
tools/node_assets/depth_cutout_layout.py
Normal file
145
tools/node_assets/depth_cutout_layout.py
Normal file
@@ -0,0 +1,145 @@
|
||||
"""Arrange staggered calculation branches on both sides of the geometry path."""
|
||||
|
||||
from cutout_layout import route_geometry
|
||||
|
||||
# Main geometry advances left to right. Local fields grow to either side of it;
|
||||
# a long calculation may start before the geometry input or span several stages.
|
||||
POSITIONS = {
|
||||
"Position": (-240, 110),
|
||||
"Store Named Attribute": (0, 0),
|
||||
"Store Named Attribute.001": (260, 0),
|
||||
"Store Named Attribute.002": (520, 0),
|
||||
"Store Named Attribute.003": (780, 0),
|
||||
"Split Edges": (1060, 0),
|
||||
"Switch": (1360, 0),
|
||||
# Face sampling stays near its stores; selection forms a dense field cluster.
|
||||
"Named Attribute": (-440, 380),
|
||||
"Evaluate on Domain": (-220, 380),
|
||||
"Image Texture": (20, 380),
|
||||
"Named Attribute.003": (260, 260),
|
||||
"Named Attribute.001": (-1090, 1060),
|
||||
"Separate XYZ": (-870, 1060),
|
||||
"Named Attribute.002": (-390, 590),
|
||||
"Corners of Edge": (-1090, 910),
|
||||
"Face of Corner": (-910, 910),
|
||||
"Corners of Edge.001": (-1090, 770),
|
||||
"Face of Corner.001": (-910, 770),
|
||||
"Evaluate at Index": (-170, 750),
|
||||
"Evaluate at Index.002": (-170, 610),
|
||||
"Evaluate at Index.001": (-710, 1060),
|
||||
"Evaluate at Index.003": (-710, 920),
|
||||
"Vector Math": (10, 710),
|
||||
"Math": (-530, 1040),
|
||||
"Math.001": (-350, 1040),
|
||||
"Math.002": (-170, 1040),
|
||||
"Math.003": (190, 1040),
|
||||
"Math.004": (190, 790),
|
||||
"Math.005": (370, 980),
|
||||
"Math.006": (190, 620),
|
||||
"Math.007": (550, 910),
|
||||
"Edge Neighbors": (370, 590),
|
||||
"Math.008": (550, 590),
|
||||
"Math.009": (730, 810),
|
||||
"Evaluate on Domain.001": (730, 670),
|
||||
"Evaluate on Domain.002": (910, 670),
|
||||
"Math.010": (1090, 670),
|
||||
"Math.011": (1360, 280),
|
||||
# Camera-ray reconstruction runs below; scene projection runs above.
|
||||
"Named Attribute.004": (1290, -440),
|
||||
"Image Texture.001": (1510, -440),
|
||||
"Separate XYZ.001": (1740, -440),
|
||||
"Named Attribute.005": (1510, -710),
|
||||
"Separate XYZ.002": (1740, -710),
|
||||
"Math.014": (1960, -440),
|
||||
"Vector Math.001": (2180, -440),
|
||||
"Named Attribute.006": (1740, -940),
|
||||
"Math.012": (1510, -940),
|
||||
"Math.013": (1960, -940),
|
||||
"Switch.001": (2600, -240),
|
||||
"Store Named Attribute.004": (2920, 0),
|
||||
"Named Attribute.007": (2340, 1080),
|
||||
"Vector Math.002": (2560, 1080),
|
||||
"Separate XYZ.003": (2740, 1080),
|
||||
"Math.015": (3100, 730),
|
||||
"Math.016": (3280, 730),
|
||||
"Math.017": (2740, 910),
|
||||
"Combine XYZ": (2920, 1040),
|
||||
"Position.001": (2920, 790),
|
||||
"Mix": (3100, 950),
|
||||
"Separate XYZ.004": (3280, 950),
|
||||
"Combine XYZ.001": (3460, 850),
|
||||
"Set Position": (3870, 0),
|
||||
# Front and rear caps share a single extrusion along the geometry axis.
|
||||
"Position.002": (4560, 340),
|
||||
"Store Named Attribute.005": (4560, 0),
|
||||
"Vector Math.003": (4780, 340),
|
||||
"Set Position.001": (4780, 0),
|
||||
"Index": (5010, 340),
|
||||
"Store Named Attribute.006": (5010, 0),
|
||||
"Extrude Mesh": (5500, 0),
|
||||
"Combine XYZ.003": (5260, 350),
|
||||
"Separate Geometry": (5780, 0),
|
||||
"Flip Faces.001": (6300, 0),
|
||||
"Join Geometry": (6970, 0),
|
||||
"Combine XYZ.004": (6070, -530),
|
||||
"Set Position.002": (6300, -320),
|
||||
"Flip Faces": (6740, -320),
|
||||
# Identity decoding above and position restoration below have independent,
|
||||
# horizontally spread readers rather than equally tall vertical stacks.
|
||||
"Named Attribute.008": (6240, 880),
|
||||
"Integer Math": (6470, 880),
|
||||
"Named Attribute.009": (6240, 650),
|
||||
"Integer Math.001": (6470, 650),
|
||||
"Position.004": (6240, 410),
|
||||
"Separate XYZ.006": (6470, 410),
|
||||
"Combine XYZ.002": (6670, 650),
|
||||
"Set Position.003": (7410, 0),
|
||||
"Merge by Distance": (7640, 0),
|
||||
"Position.003": (6910, -950),
|
||||
"Separate XYZ.005": (7160, -950),
|
||||
"Math.018": (7380, -750),
|
||||
"Combine XYZ.005": (7600, -680),
|
||||
"Named Attribute.010": (7600, -370),
|
||||
"Vector Math.004": (7830, -340),
|
||||
"Set Position.004": (8080, 0),
|
||||
"Math.019": (8310, 260),
|
||||
"Switch.002": (8310, 0),
|
||||
"Remove Named Attribute": (9000, 0),
|
||||
"Set Shade Smooth": (9220, 0),
|
||||
"Group Output": (9440, 0),
|
||||
}
|
||||
|
||||
INPUT_REGIONS = (
|
||||
(("Store Named Attribute",), (-240, 0)),
|
||||
(("Switch",), (1100, -300)),
|
||||
(("Image Texture",), (30, 520)),
|
||||
(("Math.002",), (-350, 1140)),
|
||||
(("Math.003",), (10, 1140)),
|
||||
(("Math.011",), (1100, 320)),
|
||||
(("Image Texture.001",), (1290, -270)),
|
||||
(("Math.012",), (1290, -940)),
|
||||
(("Vector Math.002",), (2340, 1200)),
|
||||
(("Math.015", "Math.016"), (2920, 680)),
|
||||
(("Mix",), (2920, 900)),
|
||||
(("Math.019",), (8080, 300)),
|
||||
)
|
||||
|
||||
|
||||
def layout_geometry_references(group, stage):
|
||||
"""Separate the split bypass and long projection references from fields."""
|
||||
links = group.links
|
||||
entry = stage["Store Named Attribute"].inputs["Geometry"]
|
||||
source = entry.links[0].from_socket
|
||||
fork = route_geometry(group, source, [(-3250, -40), (-1450, -40), (-290, -40)])
|
||||
links.new(fork, entry)
|
||||
bypass = route_geometry(group, fork, [(-210, -280), (500, -280), (1100, -280)])
|
||||
links.new(bypass, stage["Switch"].inputs["False"])
|
||||
|
||||
projection = next(n.outputs["Geometry"] for n in group.nodes if n.bl_idname == "GeometryNodeStoreNamedAttribute" and n.inputs["Name"].default_value == "o_balloon_surface_front_normal")
|
||||
shared = next(n.outputs["Geometry"] for n in group.nodes if n.bl_idname == "GeometryNodeStoreNamedAttribute" and n.inputs["Name"].default_value == "o_balloon_surface_inflation_normal")
|
||||
uniform = next(link.to_socket for link in shared.links if link.to_node.bl_idname == "GeometryNodeStoreNamedAttribute" and link.to_node.inputs["Name"].default_value == "o_balloon_surface_thickness")
|
||||
fork = route_geometry(group, projection, [(4360, -40), (4650, -1700), (8500, -1700), (11400, -1700)])
|
||||
uniform_route = route_geometry(group, shared, [(8250, -40), (8460, -1450), (11400, -1450), (11420, -370)])
|
||||
links.new(uniform_route, uniform)
|
||||
surface_route = route_geometry(group, fork, [(13500, -1700), (16800, -1700)])
|
||||
links.new(surface_route, stage["Switch.002"].inputs["True"])
|
||||
Reference in New Issue
Block a user