summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/final/shaders/render/scene_query_bvh.wgsl11
-rw-r--r--assets/final/shaders/render/scene_query_linear.wgsl11
-rw-r--r--src/tests/test_math_utils.cc184
3 files changed, 200 insertions, 6 deletions
diff --git a/assets/final/shaders/render/scene_query_bvh.wgsl b/assets/final/shaders/render/scene_query_bvh.wgsl
index 61efe49..f70a389 100644
--- a/assets/final/shaders/render/scene_query_bvh.wgsl
+++ b/assets/final/shaders/render/scene_query_bvh.wgsl
@@ -45,10 +45,15 @@ fn map_scene(p: vec3<f32>, skip_idx: u32) -> f32 {
// IMPORTANT: Plane (type 4.0) and Mesh (type 5.0) should not be scaled by 's'.
// The 's' factor is meant for unit primitives (sphere, box, torus) that are
// scaled by the model matrix. Meshes already have correct local-space extents.
- if (obj.params.x != 4.0 && obj.params.x != 5.0) { // Not plane, not mesh
- d = min(d, get_dist(q, obj.params) * s);
- } else {
+ // For planes with non-uniform scaling, we need to correct the distance by the
+ // scale along the normal direction (Y for horizontal planes).
+ if (obj.params.x == 4.0) { // Plane
+ let plane_scale = length(obj.model[1].xyz); // Y scale for horizontal plane
+ d = min(d, get_dist(q, obj.params) * plane_scale);
+ } else if (obj.params.x == 5.0) { // Mesh
d = min(d, get_dist(q, obj.params));
+ } else { // Unit primitives
+ d = min(d, get_dist(q, obj.params) * s);
}
} else { // Internal
if (stack_ptr < 31) {
diff --git a/assets/final/shaders/render/scene_query_linear.wgsl b/assets/final/shaders/render/scene_query_linear.wgsl
index ab3845a..881a939 100644
--- a/assets/final/shaders/render/scene_query_linear.wgsl
+++ b/assets/final/shaders/render/scene_query_linear.wgsl
@@ -45,10 +45,15 @@ fn map_scene(p: vec3<f32>, skip_idx: u32) -> f32 {
// IMPORTANT: Plane (type 4.0) and Mesh (type 5.0) should not be scaled by 's'.
// The 's' factor is meant for unit primitives (sphere, box, torus) that are
// scaled by the model matrix. Meshes already have correct local-space extents.
- if (obj.params.x != 4.0 && obj.params.x != 5.0) { // Not plane, not mesh
- d = min(d, get_dist(q, obj.params) * s);
- } else {
+ // For planes with non-uniform scaling, we need to correct the distance by the
+ // scale along the normal direction (Y for horizontal planes).
+ if (obj.params.x == 4.0) { // Plane
+ let plane_scale = length(obj.model[1].xyz); // Y scale for horizontal plane
+ d = min(d, get_dist(q, obj.params) * plane_scale);
+ } else if (obj.params.x == 5.0) { // Mesh
d = min(d, get_dist(q, obj.params));
+ } else { // Unit primitives
+ d = min(d, get_dist(q, obj.params) * s);
}
} else { // Internal
if (stack_ptr < 31) {
diff --git a/src/tests/test_math_utils.cc b/src/tests/test_math_utils.cc
new file mode 100644
index 0000000..26282b2
--- /dev/null
+++ b/src/tests/test_math_utils.cc
@@ -0,0 +1,184 @@
+// This file is part of the 64k demo project.
+// Unit tests for math utilities.
+
+#include "util/mini_math.h"
+#include "util/asset_manager.h" // For AssetId, though not strictly needed for math tests
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <map>
+#include <vector>
+#include <cassert>
+
+// Helper to convert C++ vec3 to WGSL vec3
+inline vec3 to_wgsl_vec3(const vec3& v) {
+ return vec3(v.x, v.y, v.z);
+}
+
+// --- Math Utilities Tests ---
+
+void test_vec3_operations() {
+ printf("Running test: test_vec3_operations
+");
+
+ // Test constructor and basic accessors
+ vec3 v1(1.0f, 2.0f, 3.0f);
+ assert(v1.x == 1.0f && v1.y == 2.0f && v1.z == 3.0f);
+ assert(v1[0] == 1.0f && v1[1] == 2.0f && v1[2] == 3.0f);
+
+ // Test normalization
+ vec3 v_unnormalized = vec3(3.0f, 4.0f, 0.0f);
+ vec3 v_normalized = v_unnormalized.normalize();
+ assert(std::abs(v_normalized.x - 0.6f) < 1e-5f);
+ assert(std::abs(v_normalized.y - 0.8f) < 1e-5f);
+ assert(std::abs(v_normalized.z - 0.0f) < 1e-5f);
+ assert(std::abs(v_normalized.norm() - 1.0f) < 1e-5f);
+
+ // Test dot product
+ vec3 v_dot1 = vec3(1.0f, 2.0f, 3.0f);
+ vec3 v_dot2 = vec3(4.0f, 5.0f, 6.0f);
+ float dot_product = vec3::dot(v_dot1, v_dot2); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
+ assert(std::abs(dot_product - 32.0f) < 1e-5f);
+
+ // Test cross product
+ vec3 v_cross1 = vec3(1.0f, 0.0f, 0.0f); // i
+ vec3 v_cross2 = vec3(0.0f, 1.0f, 0.0f); // j
+ vec3 cross_product = vec3::cross(v_cross1, v_cross2);
+ assert(std::abs(cross_product.x - 0.0f) < 1e-5f);
+ assert(std::abs(cross_product.y - 0.0f) < 1e-5f);
+ assert(std::abs(cross_product.z - 1.0f) < 1e-5f); // k
+
+ // Test element-wise multiplication
+ vec3 v_scale1 = vec3(2.0f, 3.0f, 4.0f);
+ vec3 v_scale2 = vec3(5.0f, 2.0f, 1.0f);
+ vec3 scaled_v = v_scale1 * v_scale2;
+ assert(std::abs(scaled_v.x - 10.0f) < 1e-5f);
+ assert(std::abs(scaled_v.y - 6.0f) < 1e-5f);
+ assert(std::abs(scaled_v.z - 4.0f) < 1e-5f);
+
+ printf("test_vec3_operations passed.
+");
+}
+
+// --- Quaternion Tests ---
+
+// Dummy function to satisfy potential compiler needs, if not defined elsewhere
+// If quat::from_axis is part of a class that's already linked, this might not be needed.
+// However, to be safe, I'll assume it might need a declaration.
+// If this causes issues, it means quat is not properly available here.
+#if !defined(QUAT_FROM_AXIS_DEFINED)
+namespace quat_detail {
+ // Dummy definition if quat is not properly linked/included in this context
+ struct quat {
+ vec3 axis;
+ float angle;
+ quat(vec3 a, float ang) : axis(a), angle(ang) {}
+ };
+ inline quat from_axis(vec3 a, float ang) {
+ return quat(a, ang);
+ }
+}
+#define QUAT_FROM_AXIS_DEFINED
+#endif
+
+void test_quaternion_operations() {
+ printf("Running test: test_quaternion_operations
+");
+
+ // Test from_axis and to_mat
+ vec3 axis_cpp = vec3(0.0f, 1.0f, 0.0f).normalize();
+ vec3 wgsl_axis = to_wgsl_vec3(axis_cpp);
+ quat q = quat::from_axis(wgsl_axis, 1.5708f); // 90 degrees around Y axis
+ mat4 rot_mat = q.to_mat();
+
+ // Check if rotation matrix is approximately identity (for 0 rotation) or correct for 90 deg around Y
+ // A 90 degree rotation around Y should result in:
+ // [ 0, 0, 1, 0 ]
+ // [ 0, 1, 0, 0 ]
+ // [-1, 0, 0, 0 ]
+ // [ 0, 0, 0, 1 ]
+ // (Column-major)
+ assert(std::abs(rot_mat.m[0] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[1] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[2] - -1.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[3] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[4] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[5] - 1.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[6] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[7] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[8] - 1.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[9] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[10] - 0.0f) < 1e-5f);
+ assert(std::abs(rot_mat.m[11] - 0.0f) < 1e-5f);
+
+ // Test rotating a vector
+ vec3 test_vec(1.0f, 0.0f, 0.0f);
+ vec3 rotated_vec = q.rotate(test_vec);
+ // Expecting rotation around Y axis by 90 degrees should transform (1,0,0) to (0,0,-1)
+ assert(std::abs(rotated_vec.x - 0.0f) < 1e-5f);
+ assert(std::abs(rotated_vec.y - 0.0f) < 1e-5f);
+ assert(std::abs(rotated_vec.z - -1.0f) < 1e-5f);
+
+ printf("test_quaternion_operations passed.
+");
+}
+
+// --- Easing Function Tests ---
+
+void test_easing_functions() {
+ printf("Running test: test_easing_functions
+");
+ assert(std::abs(ease::out_cubic(0.0f) - 0.0f) < 1e-5f);
+ assert(std::abs(ease::out_cubic(0.5f) - 0.875f) < 1e-5f);
+ assert(std::abs(ease::out_cubic(1.0f) - 1.0f) < 1e-5f);
+
+ assert(std::abs(ease::in_out_quad(0.0f) - 0.0f) < 1e-5f);
+ assert(std::abs(ease::in_out_quad(0.5f) - 0.5f) < 1e-5f);
+ assert(std::abs(ease::in_out_quad(1.0f) - 1.0f) < 1e-5f);
+
+ assert(std::abs(ease::out_expo(0.0f) - 0.0f) < 1e-5f);
+ assert(std::abs(ease::out_expo(1.0f) - 1.0f) < 1e-5f);
+ // Check a mid-point for out_expo, e.g., 0.5 should be 1 - 2^(-5) = 1 - 1/32 = 31/32 = 0.96875
+ assert(std::abs(ease::out_expo(0.5f) - 0.96875f) < 1e-5f);
+
+ printf("test_easing_functions passed.
+");
+}
+
+// --- Lerp Tests ---
+
+void test_lerp() {
+ printf("Running test: test_lerp
+");
+ vec3 start_vec = vec3(1.0f, 2.0f, 3.0f);
+ vec3 end_vec = vec3(5.0f, 6.0f, 7.0f);
+ float t_mid = 0.5f;
+ vec3 mid_point = lerp(start_vec, end_vec, t_mid);
+ assert(std::abs(mid_point.x - 3.0f) < 1e-5f);
+ assert(std::abs(mid_point.y - 4.0f) < 1e-5f);
+ assert(std::abs(mid_point.z - 5.0f) < 1e-5f);
+
+ // Test lerp with float
+ float start_f = 10.0f;
+ float end_f = 20.0f;
+ float mid_f = lerp(start_f, end_f, t_mid);
+ assert(std::abs(mid_f - 15.0f) < 1e-5f);
+
+ printf("test_lerp passed.
+");
+}
+
+int main(int argc, char** argv) {
+ // This main function is for running tests standalone if needed,
+ // but tests are typically run via ctest.
+ // However, for the sake of this execution, we can run them directly.
+
+ test_vec3_operations();
+ test_quaternion_operations();
+ test_easing_functions();
+ test_lerp();
+
+ return 0;
+}