extends SceneTree
## Does the terrain mesh wind the same way Godot's own meshes do?
##
## Godot's front-face convention is not something to remember: PlaneMesh faces
## +Y, its stored normal is (0,1,0), and cross(b-a, c-a) over its index order is
## (0,-1,0). So the geometric cross of a front-facing triangle points AGAINST
## its shading normal. Getting that backwards renders the terrain inside out,
## which is exactly what the first version did.
##
## This asks PlaneMesh for the convention each run rather than hard-coding it,
## so it stays correct if the engine ever changes, and compares our first
## triangle against it.
##
## "$HYPER_TPS_GODOT" --headless --path . --script res://scenes/test/gate_winding.gd
var _m: Node = null
func _tri_cross(v: PackedVector3Array, i: PackedInt32Array, t: int) -> Vector3:
var a := v[i[t * 3]]
var b := v[i[t * 3 + 1]]
var c := v[i[t * 3 + 2]]
return (b - a).cross(c - a).normalized()
func _init() -> void:
var packed := load("res://scenes/maps/map_heightmap.tscn") as PackedScene
if packed == null:
print("FAIL — map_heightmap.tscn did not load"); quit(2); return
_m = packed.instantiate()
root.add_child(_m)
func _process(_dt: float) -> bool:
var pm := PlaneMesh.new()
pm.size = Vector2(10, 10)
var pa: Array = pm.get_mesh_arrays()
var ref_cross := _tri_cross(pa[Mesh.ARRAY_VERTEX], pa[Mesh.ARRAY_INDEX], 0)
var ref_normal: Vector3 = (pa[Mesh.ARRAY_NORMAL] as PackedVector3Array)[0]
print(" REFERENCE PlaneMesh (faces +Y): cross %s, stored normal %s"
% [str(ref_cross), str(ref_normal.round())])
var mi = _m.get_node_or_null("TerrainMesh")
if mi == null:
print("FAIL — no TerrainMesh"); quit(1); return true
var arrs: Array = mi.mesh.surface_get_arrays(0)
var our_cross := _tri_cross(arrs[Mesh.ARRAY_VERTEX], arrs[Mesh.ARRAY_INDEX], 0)
var our_normal: Vector3 = (arrs[Mesh.ARRAY_NORMAL] as PackedVector3Array)[0]
print(" TERRAIN tri0: cross %s, stored normal %s"
% [str(our_cross.round()), str(our_normal.round())])
var fails := 0
# Both surfaces face up, so both must have the same cross sign.
if signf(our_cross.y) != signf(ref_cross.y):
print(" FAIL — winding is flipped relative to PlaneMesh: renders inside out")
fails += 1
# And the shading normal must still point up, or lighting is wrong even when
# the winding is right. These are two different mistakes.
if our_normal.y <= 0.0:
print(" FAIL — shading normal points down")
fails += 1
print("")
if fails == 0:
print("VERDICT: the terrain winds the same way Godot's own meshes do,")
print(" and its normals point up.")
else:
print("VERDICT: ", fails, " check(s) failed.")
quit(0 if fails == 0 else 1)
return true