From dfa16befec98166eca8590fc26c6a52e43677c73 Mon Sep 17 00:00:00 2001 From: Luca Wresch Date: Fri, 21 Jun 2024 19:26:06 +0200 Subject: [PATCH] test functions --- src/matrixMath.c | 39 +++- src/test.c | 564 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 584 insertions(+), 19 deletions(-) diff --git a/src/matrixMath.c b/src/matrixMath.c index f9acc51..7c1343e 100644 --- a/src/matrixMath.c +++ b/src/matrixMath.c @@ -8,6 +8,10 @@ // MATRICES IN COLUMN MAJOR +/* + vec3 functions (tested) +*/ + void vec3Zero(vec3* out) { for (int i = 0; i < 3; i++) { ((GLfloat*)out)[i] = 0; @@ -51,6 +55,12 @@ GLfloat vec3Dot(vec3* a, vec3* b) { void vec3Normalise(vec3* out, vec3* a) { vec3Multiply(out, a, 1 / vec3Length(a)); } + +/* + mat4 functions +*/ + +//tested // CREATE 4x4 IDENTITY MATRIX void identity(mat4* out) { for (int i = 0; i < 16; i++) { @@ -58,6 +68,7 @@ void identity(mat4* out) { } } +//tested // CREATE 4x4 TRANSLATION MATRIX void translation(mat4* out, vec3* v) { identity(out); @@ -66,6 +77,7 @@ void translation(mat4* out, vec3* v) { out->m23 = v->z; } +//tested // CREATE 4x4 SCALING MATRIX void scaling(mat4* out, vec3* v) { identity(out); @@ -126,11 +138,13 @@ void multiplyAny(GLfloat* out, GLfloat* A, GLfloat* B, int wA, int hA, int wB) { result = NULL; } +//tested // MULTIPLY TWO 4x4 MATRICES void multiply(mat4* out, mat4* A, mat4* B) { multiplyAny((GLfloat*)out, (GLfloat*)A, (GLfloat*)B, 4, 4, 4); } +//! // MULTIPLY in WITH TRANSLATION MATRIX OF v void translate(mat4* out, mat4* in, vec3* v) { mat4 translationMatrix; @@ -138,6 +152,7 @@ void translate(mat4* out, mat4* in, vec3* v) { multiply(out, &translationMatrix, in); } +//! // MULTIPLY in WITH SCALING MATRIX OF v void scale(mat4* out, mat4* in, vec3* v) { mat4 scalingMatrix; @@ -145,18 +160,23 @@ void scale(mat4* out, mat4* in, vec3* v) { multiply(out, &scalingMatrix, in); } +//! // MULTIPLY in WITH ROTATION MATRIX OF angle AROUND Z AXIS void rotateZ(mat4* out, mat4* in, GLfloat angle) { mat4 rotationMatrix; rotationZ(&rotationMatrix, angle); multiply(out, &rotationMatrix, in); } + +//! // MULTIPLY in WITH ROTATION MATRIX OF angle AROUND Y AXIS void rotateY(mat4* out, mat4* in, GLfloat angle) { mat4 rotationMatrix; rotationY(&rotationMatrix, angle); multiply(out, &rotationMatrix, in); } + +//! // MULTIPLY in WITH ROTATION MATRIX OF angle AROUND X AXIS void rotateX(mat4* out, mat4* in, GLfloat angle) { mat4 rotationMatrix; @@ -164,6 +184,7 @@ void rotateX(mat4* out, mat4* in, GLfloat angle) { multiply(out, &rotationMatrix, in); } +//tested // TRANSPOSE MATRIX OF ANY SIZE void transposeAny(GLfloat* out, GLfloat* in, int w, int h) { int size = w * h; @@ -178,7 +199,7 @@ void transposeAny(GLfloat* out, GLfloat* in, int w, int h) { result = NULL; } - +//tested, da transpose any schon getestet ist // TRANSPOSE 4x4 MATRIX void transpose(mat4* out, mat4* in) { transposeAny((GLfloat*)out, (GLfloat*)in, 4, 4); @@ -211,6 +232,10 @@ void mat3Print(mat3* m) { printAny((GLfloat*)m, 3, 3); } +/* + mat3 functions +*/ + // TURN mat4 INTO mat3 BY CUTTING LAST COLUMN AND ROW void mat3From4(mat3* out, mat4* in) { memcpy(&out->m00, &in->m00, sizeof(vec3)); @@ -218,11 +243,13 @@ void mat3From4(mat3* out, mat4* in) { memcpy(&out->m02, &in->m02, sizeof(vec3)); } +//tested // TRANSPOSE 3x3 MATRIX void mat3Transpose(mat3* out, mat3* in) { transposeAny((GLfloat*)out, (GLfloat*)in, 3, 3); } +//tested /** * a - m00 b - m01 c - m02 * d - m10 e - m11 f - m12 @@ -247,6 +274,7 @@ void mat3Minor(mat3* out, mat3* in) { memcpy(out, &result, sizeof(mat3)); } +//tested // GET THE COFACTOR MATRIX OF A 3x3 MATRIX void mat3Cofactor(mat3* out, mat3* in) { mat3 result; @@ -258,6 +286,7 @@ void mat3Cofactor(mat3* out, mat3* in) { out->m12 *= -1; } +//tested // GET ADJOING MATRRIX OF 3x3 MATRIX void mat3Adjoint(mat3* out, mat3* in) { mat3Cofactor(out, in); @@ -271,6 +300,7 @@ void mat3MultiplyScalar(mat3* out, mat3* in, GLfloat x) { } } +//tested // CALCULATE DETERMINANT OF 3x3 MATRIX GLfloat mat3Determinant(mat3* M) { return @@ -284,6 +314,7 @@ GLfloat mat3Determinant(mat3* M) { ; } +//tested // GET INVERSE OF 3x3 MATRIX void mat3Inverse(mat3* out, mat3* in) { mat3 result; @@ -293,6 +324,7 @@ void mat3Inverse(mat3* out, mat3* in) { memcpy(out, &result, sizeof(mat3)); } +//tested // GET THE SUM OF DIFFERENCES BETWEEON TWO MATRICES GLfloat sumDiffAny(GLfloat* A, GLfloat* B, int w, int h) { GLfloat result = 0; @@ -302,11 +334,16 @@ GLfloat sumDiffAny(GLfloat* A, GLfloat* B, int w, int h) { return result; } +//tested // GET THE SUM OF DIFFERENCES BETWEEN TWO 3x3 MATRICES GLfloat mat3SumDiff(mat3* A, mat3* B) { return sumDiffAny((GLfloat*)A, (GLfloat*)B, 3, 3); } +/* + vec2 functions (tested) +*/ + // COMPONENTWISE SUBTRACT vec2 b FROM vec2 a void vec2Subtract(vec2* out, vec2* a, vec2* b) { out->x = a->x - b->x; diff --git a/src/test.c b/src/test.c index b317647..79c1d36 100644 --- a/src/test.c +++ b/src/test.c @@ -2,8 +2,11 @@ #include #include #include +#include +#include #include "matrixMath.h" +#include "transformation.h" #define KRED "\x1B[31m" @@ -23,7 +26,19 @@ void printTest(char* name, bool result) { } } -void testSumDiff() { +bool vec3Equals(vec3* a, vec3* b) { + return (fabs(a->x - b->x) < EPSILON) && + (fabs(a->y - b->y) < EPSILON) && + (fabs(a->z - b->z) < EPSILON); +} + +bool vec2Equals(vec2* a, vec2* b) { + return (fabs(a->x - b->x) < EPSILON) && + (fabs(a->y - b->y) < EPSILON); +} + + +void testMat3SumDiff() { mat3 A = {1, 0, 0, -1, 0, -1, 1, -1, 9}; mat3 B = {0, 1, -1, 0, 0, 1, 1, -1, 8}; GLfloat target = 7; @@ -97,12 +112,6 @@ void testMat3Inverse() { bool result = mat3SumDiff(&M, &target) < EPSILON; - if (!result) { - printf("\nM:\n"); - mat3Print(&M); - printf("\ntarget:\n"); - mat3Print(&target); - } printTest("mat3Inverse", result); } @@ -116,15 +125,534 @@ void testMat3Transpose() { printTest("mat3Transpose", mat3SumDiff(&M, &target) < EPSILON); } -int main(void) { - testSumDiff(); - testMat3Minor(); - testMat3Cofactor(); - testMat3Adjoint(); - testMat3MultiplyScalar(); - testMat3Determinant(); - testMat3Inverse(); - testMat3Transpose(); +void testVec3Zero() { + vec3 result = {0, 0, 0}; + vec3 test = {1, 2, 3}; - return exitCode; -} \ No newline at end of file + vec3Zero(&test); + + printTest("vec3Zero", vec3Equals(&result, &test)); +} + +void testVec3Add() { + vec3 first = {1, 2, 3}; + vec3 second = {4, 5, 6}; + + vec3 expectedResult = {5, 7, 9}; + + vec3 result = {0, 0, 0}; + + vec3Add(&result, &first, &second); + + printTest("vec3Add", vec3Equals(&result, &expectedResult)); +} + +void testVec3Multiply() { + vec3 test = {1, 2, 3}; + GLfloat multiplyBy = 2; + + vec3 result = {0, 0, 0}; + + vec3 expectedResult = {2, 4, 6}; + + vec3Multiply(&result, &test, multiplyBy); + + printTest("vec3Multiply", vec3Equals(&result, &expectedResult)); +} + +void testVec3Subtract() { + vec3 first = {1, 2, 3}; + vec3 second = {4, 5, 6}; + + vec3 expectedResult = {-3, -3, -3}; + + vec3 result = {0, 0, 0}; + + vec3Subtract(&result, &first, &second); + + printTest("vec3Substract", vec3Equals(&result, &expectedResult)); +} + +void testVec3Cross() { + vec3 first = {1, 2, 3}; + vec3 second = {4, 5, 6}; + + vec3 expectedResult = {-3, 6, -3}; + + vec3 result = {0, 0, 0}; + + vec3Cross(&result, &first, &second); + + printTest("vec3Cross", vec3Equals(&result, &expectedResult)); +} + +void testVec3Length() { + vec3 test = {3, 4, 0}; + + GLfloat expectedResult = 5; + + GLfloat result = vec3Length(&test); + + printTest("vec3Length", fabs(result - expectedResult) < EPSILON); +} + +void testVec3Dot() { + vec3 first = {1, 2, 3}; + vec3 second = {4, 5, 6}; + + GLfloat expectedResult = 32; + + GLfloat result = vec3Dot(&first, &second); + + printTest("vec3Dot", fabs(result - expectedResult) < EPSILON); +} + +void testVec3Normalise() { + vec3 first = {1, 2, 3}; + + vec3 expectedResult = {sqrt(14)/14, sqrt(14)*2/14, sqrt(14)*3/14}; + vec3 result = {0, 0, 0}; + + vec3Normalise(&result, &first); + + printTest("vec3Normalise", vec3Equals(&result, &expectedResult)); +} + +void testVec2Subtract() { + vec2 first = {1, 2}; + vec2 second = {4, 5}; + + vec2 expectedResult = {-3, -3}; + + vec2 result = {0, 0}; + + vec2Subtract(&result, &first, &second); + + printTest("vec2Substract", vec2Equals(&result, &expectedResult)); +} + +void testMat4Identity() { + mat4 expectedResult = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + mat4 randomMat4 = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + + identity(&randomMat4); + + printTest("Mat4Identity", sumDiffAny((GLfloat*) &expectedResult, (GLfloat*) &randomMat4, 4, 4) < EPSILON); + +} + +void testMat4Multiply() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + mat4 matrix2 = {1, 1, 3, 3, + 8, 8, 5, 3, + 9, 5, 7, 7, + 2, 1, 5, 6}; + + mat4 result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + mat4 expectedResult = { + 52, 56, 27, 45, + 134, 189, 98, 101, + 156, 212, 103, 137, + 90, 97, 45, 81 + }; + + + + multiply(&result, &matrix1, &matrix2); + + printTest("Mat4Multiply", sumDiffAny((GLfloat*) &expectedResult, (GLfloat*) &result, 4, 4) < EPSILON); +} + +void testTranslation() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + + mat4 result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + vec3 test = {1, 2, 3}; + + mat4 expectedResult = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 1, 2, 3, 1}; + + translation(&result, &test); + + printTest("Translation", sumDiffAny((GLfloat*) &expectedResult, (GLfloat*) &result, 4, 4) < EPSILON); +} + +void testScaling() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + + mat4 result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + vec3 test = {1, 2, 3}; + + mat4 expectedResult = {1, 0, 0, 0, + 0, 2, 0, 0, + 0, 0, 3, 0, + 0, 0, 0, 1}; + + scaling(&result, &test); + + printTest("Scaling", (sumDiffAny(&expectedResult, &result, 4, 4) < EPSILON)); +} + +void testRotationZ() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + GLfloat a = 4; + + mat4 result = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + + + mat4 expectedResult = {cos(a), sin(a), 0, 0, + -sin(a), cos(a), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + rotationZ(&result, a); + + printTest("RotationZ", (sumDiffAny(&expectedResult, &result, 4, 4) < EPSILON)); + +} + +void testRotationY() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + GLfloat a = 4; + + mat4 result = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + + + mat4 expectedResult = {cos(a), 0, -sin(a), 0, + 0, 1, 0, 0, + sin(a), 0, cos(a), 0, + 0, 0, 0, 1}; + + rotationY(&result, a); + + printTest("RotationY", (sumDiffAny(&expectedResult, &result, 4, 4) < EPSILON)); +} + +void testRotationX() { + mat4 matrix1 = {2, 9, 4, 4, + 8, 8, 5, 2, + 6, 7, 4, 7, + 8, 6, 2, 6}; + + GLfloat a = 4; + + mat4 result = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + + + mat4 expectedResult = {1, 0, 0, 0, + 0, cos(a), sin(a), 0, + 0, -sin(a), cos(a), 0, + 0, 0, 0, 1}; + + rotationX(&result, a); + + printTest("RotationX", (sumDiffAny(&expectedResult, &result, 4, 4) < EPSILON)); +} + +void testMultiplyAny() { + GLfloat matrix1[6] = {1, 2, 3, + 4, 5, 6}; // 2x3 matrix + + GLfloat matrix2[6] = {7, 8, + 9, 10, + 11, 12}; // 3x2 matrix + + GLfloat result[4] = {0, 0, + 0, 0}; // 2x2 result matrix + + GLfloat expectedResult[4] = {39, 54, + 69, 49}; + + multiplyAny(&result, &matrix1, &matrix2, 2, 3, 2); + + printTest("Multiply Any", sumDiffAny(result, expectedResult, 2, 2) < EPSILON); +} + + +void testAnyTranspose() { + mat3 M = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + mat3 target = {1, 4, 7, 2, 5, 8, 3, 6, 9}; + + transposeAny(&M, &M, 3, 3); + + printTest("Transpose Any", mat3SumDiff(&M, &target) < EPSILON); +} + +void testTranslate() { + mat4 in = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + vec3 translationVec = {1, 2, 3}; + + mat4 expectedResult = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 1, 2, 3, 1}; + + mat4 result; + translate(&result, &in, &translationVec); + + printTest("translate", sumDiffAny((GLfloat*)&result, (GLfloat*)&expectedResult, 4, 4) < EPSILON); +} + +void testScale() { + mat4 in = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + vec3 scaleVec = {2, 3, 4}; + + mat4 expectedResult = {2, 0, 0, 0, + 0, 3, 0, 0, + 0, 0, 4, 0, + 0, 0, 0, 1}; + + mat4 result; + scale(&result, &in, &scaleVec); + + printTest("scale", sumDiffAny((GLfloat*)&result, (GLfloat*)&expectedResult, 4, 4) < EPSILON); +} + + +void testRotateZ() { + mat4 in = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + GLfloat angle = M_PI / 4; // 45 degrees + + mat4 expectedResult = {cos(angle), sin(angle), 0, 0, + -sin(angle), cos(angle), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + mat4 result; + rotateZ(&result, &in, angle); + + printTest("rotateZ", sumDiffAny((GLfloat*)&result, (GLfloat*)&expectedResult, 4, 4) < EPSILON); +} + +void testRotateY() { + mat4 in = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + GLfloat angle = M_PI / 4; // 45 degrees + + mat4 expectedResult = {cos(angle), 0, -sin(angle), 0, + 0, 1, 0, 0, + sin(angle), 0, cos(angle), 0, + 0, 0, 0, 1}; + + mat4 result; + rotateY(&result, &in, angle); + + printTest("rotateY", sumDiffAny((GLfloat*)&result, (GLfloat*)&expectedResult, 4, 4) < EPSILON); +} + +void testRotateX() { + mat4 in = {1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1}; + + GLfloat angle = M_PI / 4; // 45 degrees + + mat4 expectedResult = {1, 0, 0, 0, + 0, cos(angle), sin(angle), 0, + 0, -sin(angle), cos(angle), 0, + 0, 0, 0, 1}; + + mat4 result; + rotateX(&result, &in, angle); + + printTest("rotateX", sumDiffAny((GLfloat*)&result, (GLfloat*)&expectedResult, 4, 4) < EPSILON); +} + +void testLookAt() { + mat4 result; + mat4 expected = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, -2, 1 + }; + + vec3 eye = {0, 0, 2}; + vec3 look = {0, 0, 0}; + vec3 up = {0, 1, 0}; + + lookAt(&result, &eye, &look, &up); + + bool isEqual = sumDiffAny((GLfloat*)&expected, (GLfloat*)&result, 4, 4) < EPSILON; + printTest("lookAt", isEqual); +} + + +void testPerspectiveProjection() { + mat4 result; + mat4 expected = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 4, -1, + 0, 0, 3, 0 + }; + + + GLfloat near = 1.0f; + GLfloat far = 3.0f; + + perspectiveProjection(&result, near, far); + + bool isEqual = sumDiffAny((GLfloat*)&expected, (GLfloat*)&result, 4, 4) < EPSILON; + printTest("perspectiveProjection", isEqual); +} + + +void testNormalisedDeviceCoordinates() { + mat4 result; + mat4 expected = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, -1, 0, + -0, -0, -2, 1 + }; + + + GLfloat r = 1.0f; + GLfloat l = -1.0f; + GLfloat t = 1.0f; + GLfloat b = -1.0f; + GLfloat n = 1.0f; + GLfloat f = 3.0f; + + normalisedDeviceCoordinates(&result, r, l, t, b, n, f); + + bool isEqual = sumDiffAny((GLfloat*)&expected, (GLfloat*)&result, 4, 4) < EPSILON; + printTest("normalisedDeviceCoordinates", isEqual); +} + + +void testNormalisedDeviceCoordinatesFov() { + mat4 result; + mat4 expected = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, -1, 0, + -0, -0, -2, 1 + }; + + GLfloat fovy = 90.0f * (3.14159f / 180.0f); // Convert degrees to radians + GLfloat aspectRatio = 1.0f; + GLfloat near = 1.0f; + GLfloat far = 3.0f; + + normalisedDeviceCoordinatesFov(&result, fovy, aspectRatio, near, far); + + bool isEqual = sumDiffAny((GLfloat*)&expected, (GLfloat*)&result, 4, 4) < EPSILON; + printTest("normalisedDeviceCoordinatesFov", isEqual); +} + + +int main(void) { + + // mat3 functions + printf("==========\n mat3 functions\n==========\n"); + testMat3SumDiff(); + testMat3Minor(); + testMat3Cofactor(); + testMat3Adjoint(); + testMat3MultiplyScalar(); + testMat3Determinant(); + testMat3Inverse(); + testMat3Transpose(); + + // mat4 functions + printf("==========\n mat4 functions\n==========\n"); + testMat4Identity(); + testMat4Multiply(); + testTranslation(); + testScaling(); + testRotationZ(); + testRotationY(); + testRotationX(); + testMultiplyAny(); + testAnyTranspose(); + + // mat4 transform functions + printf("==========\n mat4 transform functions\n==========\n"); + testTranslate(); + testScale(); + testRotateZ(); + testRotateY(); + testRotateX(); + + // vec2 functions + printf("==========\n vec2 functions\n==========\n"); + testVec2Subtract(); + + // vec3 functions + printf("==========\n vec3 functions\n==========\n"); + testVec3Zero(); + testVec3Add(); + testVec3Multiply(); + testVec3Subtract(); + testVec3Cross(); + testVec3Length(); + testVec3Dot(); + testVec3Normalise(); + + // transformation functions + printf("==========\n vec3 functions\n==========\n"); + testLookAt(); + testPerspectiveProjection(); + testNormalisedDeviceCoordinates(); + testNormalisedDeviceCoordinatesFov(); + return exitCode; +}