| … | … | @@ -52,13 +52,23 @@ func _init() -> void: |
| 52 | 52 | # Moments as well as bounds: two surfaces can share a bounding box and be |
| 53 | 53 | # different shapes. Reported in BLENDER's axes -- M maps our y back to |
| 54 | 54 | # Blender's z -- so the two are directly comparable. |
| 55 | | var s1 := Vector3() |
| 56 | | var s2 := Vector3() |
| 55 | # |
| 56 | # ⛔ ACCUMULATE IN PLAIN FLOATS, NOT A Vector3. Vector3's components are |
| 57 | # real_t = float32, and summing 2.58M heights into one reaches ~2.8e7 where |
| 58 | # a float32 ulp is ~2. Measured on the voronoi mountain: the Vector3 form |
| 59 | # reported sum(z)=1792324.375 and sumsq(z)=28291398 where the true values |
| 60 | # are 1792386.704 and 28382639 -- an instrument error of 62 and 91241, |
| 61 | # against a real disagreement with Blender of 7.05 and 90.9. The accumulator |
| 62 | # was an order of magnitude noisier than the signal it exists to detect, so |
| 63 | # it read as a failing comparison on a mesh that matches. GDScript's own |
| 64 | # float IS a double; the sum belongs in one. |
| 65 | var s1z := 0.0 |
| 66 | var s2z := 0.0 |
| 57 | 67 | for p in v: |
| 58 | | var b := Vector3(-p.x, p.z, p.y) # M is self-inverse |
| 59 | | s1 += b |
| 60 | | s2 += Vector3(b.x * b.x, b.y * b.y, b.z * b.z) |
| 61 | | print("MOMENTS sum(z)=%.4f sumsq(z)=%.4f" % [s1.z, s2.z]) |
| 68 | var bz := float(p.y) # M is self-inverse; Blender z is our y |
| 69 | s1z += bz |
| 70 | s2z += bz * bz |
| 71 | print("MOMENTS sum(z)=%.4f sumsq(z)=%.4f" % [s1z, s2z]) |
| 62 | 72 | |
| 63 | 73 | # The graph as a Godot resource, so it opens in the proc-nodes editor, and |
| 64 | 74 | # the baked mesh, so it can be dropped into a scene. |