OverviewFilesCommitsIssuesDocsReleasesPeers

proc-nodes commits / c9de802

demo: cage_graph_probe -- a real Blender cage through a real bridged graph
Feeds a cage dumped from Blender (in either frame) through a bridged graph JSON headlessly and prints the result bounding box, plus a read-back of the input with proc-nodes nowhere near it so the harness can be ruled out. It is what localised the double M conversion: an identity graph turned x 0..1 / y 0..2 / z 0..3 into x -1..0 / y 0..3 / z 0..2 while the round trip returned the input unchanged. That had been a GUI round trip per question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
c9de8023f33e09ffaca06fe2e447feb46d148d03
by plankatron <fleeky@gmail.com> · 2026-09-06T21:03:10.000Z

Changed files (1) +57 -0

demo/cage_graph_probe.gd +57 -0
……@@ -0,0 +1,57 @@
1## Feed a REAL cage (from Blender, M-converted) into a bridged graph and report
2## the bounding box, so the result can be compared against Blender's own.
3extends SceneTree
4func _init() -> void:
5 var a := OS.get_cmdline_user_args()
6 var f := FileAccess.open(a[0], FileAccess.READ)
7 var head := f.get_line().split(" ")
8 var nv := int(head[0])
9 var nt := int(head[1])
10 var pos := PackedVector3Array()
11 pos.resize(nv)
12 for i in range(nv):
13 var p := f.get_line().split(" ")
14 pos[i] = Vector3(float(p[0]), float(p[1]), float(p[2]))
15 var idx := PackedInt32Array()
16 idx.resize(nt * 3)
17 for i in range(nt):
18 var p := f.get_line().split(" ")
19 idx[i*3] = int(p[0]); idx[i*3+1] = int(p[1]); idx[i*3+2] = int(p[2])
20 f.close()
21 var arrays := []
22 arrays.resize(Mesh.ARRAY_MAX)
23 arrays[Mesh.ARRAY_VERTEX] = pos
24 arrays[Mesh.ARRAY_INDEX] = idx
25 var am := ArrayMesh.new()
26 am.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
27 print("cage in: %d verts, %d tris" % [nv, nt])
28 # ⛔ ISOLATION: read the ArrayMesh straight back, with proc-nodes nowhere
29 # near it. If the bbox is already swapped here, the harness is the liar.
30 var rt: PackedVector3Array = am.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
31 var rlo := Vector3(1e30, 1e30, 1e30)
32 var rhi := Vector3(-1e30, -1e30, -1e30)
33 for p2 in rt:
34 rlo = rlo.min(p2); rhi = rhi.max(p2)
35 print("ROUND TRIP (no graph): x %.2f..%.2f y %.2f..%.2f z %.2f..%.2f"
36 % [rlo.x, rhi.x, rlo.y, rhi.y, rlo.z, rhi.z])
37
38 var g: ProcNodeGraph = GraphImporter.import_from_json(
39 FileAccess.get_file_as_string(a[1]))
40 var host := ProcGeometryNode.new()
41 host.use_gpu = true
42 host.set_input_mesh(am)
43 host.set_graph(g)
44 get_root().add_child(host)
45 var m: ArrayMesh = host.bake_mesh()
46 if m == null or m.get_surface_count() == 0:
47 print("BAKE: no mesh")
48 quit(1)
49 return
50 var v: PackedVector3Array = m.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
51 var lo := Vector3(1e30, 1e30, 1e30)
52 var hi := Vector3(-1e30, -1e30, -1e30)
53 for p in v:
54 lo = lo.min(p); hi = hi.max(p)
55 print("GODOT result bbox: x %.2f..%.2f y %.2f..%.2f z %.2f..%.2f (%d verts)"
56 % [lo.x, hi.x, lo.y, hi.y, lo.z, hi.z, v.size()])
57 quit(0)