OverviewFilesCommitsIssuesDocsReleasesPeers

proc-nodes / demo / sdf_grid_probe.gd

58 lines · gd ref:
## Diagnostic for the SDF-grid chain: what the field looks like and where the
## extracted vertices actually sit. Not a gate -- it prints, it does not judge.
extends SceneTree

func _init() -> void:
	var g := ProcNodeGraph.new()
	var sphere := g.add_node(MeshUVSphereNode.new())
	g.get_node(sphere).set_input_default(2, 1.0)
	var to_grid := g.add_node(MeshToSDFGridNode.new())
	g.get_node(to_grid).set_input_default(1, 0.25)
	g.connect_sockets(sphere, 0, to_grid, 0)
	var to_mesh := g.add_node(GridToMeshNode.new())
	g.connect_sockets(to_grid, 0, to_mesh, 0)

	var sm = g.evaluate_socket(sphere, 0).get_mesh()
	var sv: PackedVector3Array = sm.to_array_mesh().surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
	var smin := 1e30
	var smax := -1e30
	for v in sv:
		smin = min(smin, v.length()); smax = max(smax, v.length())
	print("sphere: %d verts, |r| in [%.4f, %.4f]" % [sv.size(), smin, smax])

	var vol = g.evaluate_socket(to_grid, 0).get_volume()
	var d: PackedFloat32Array = vol.get_density_grid()
	var r: Vector3i = vol.get_grid_resolution()
	var dmin := 1e30
	var dmax := -1e30
	var npos := 0
	for x in d:
		dmin = min(dmin, x); dmax = max(dmax, x)
		if x > 0.0: npos += 1
	print("grid: res %v origin %v size %v" % [r, vol.get_grid_origin(), vol.get_grid_size()])
	print("grid: value in [%.4f, %.4f], %d/%d positive (inside)" % [dmin, dmax, npos, d.size()])
	# The boundary shell: is the field already negative all around the border?
	var bmax := -1e30
	for z in range(r.z):
		for y in range(r.y):
			for x in range(r.x):
				if x == 0 or y == 0 or z == 0 or x == r.x-1 or y == r.y-1 or z == r.z-1:
					bmax = max(bmax, d[(z*r.y + y)*r.x + x])
	print("grid: max value on the border = %.4f" % bmax)

	var m = g.evaluate_socket(to_mesh, 0).get_mesh()
	var mv: PackedVector3Array = m.to_array_mesh().surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
	var near := 0
	var far := 0
	var fmin := Vector3(1e30,1e30,1e30)
	var fmax := Vector3(-1e30,-1e30,-1e30)
	for v in mv:
		if abs(v.length() - 1.0) < 0.25: near += 1
		else:
			far += 1
			fmin = fmin.min(v); fmax = fmax.max(v)
	print("mesh: %d verts, %d near the unit sphere, %d elsewhere" % [mv.size(), near, far])
	if far > 0:
		print("mesh: the stray vertices span %v .. %v" % [fmin, fmax])
	quit(0)