1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00
small3dlib/programs/test.c

444 lines
11 KiB
C
Raw Normal View History

2020-06-17 18:12:58 +02:00
/**
2019-06-30 17:02:43 +02:00
Some basic tests for small3dlib.
author: Miloslav Ciz
license: CC0 1.0
*/
2018-11-21 16:46:01 +01:00
#include <stdio.h>
2020-06-17 18:12:58 +02:00
#include <string.h>
#include <math.h>
2019-10-12 02:02:32 +02:00
2018-11-21 16:46:01 +01:00
#define S3L_PIXEL_FUNCTION pixelFunc
2019-10-12 02:02:32 +02:00
#define S3L_RESOLUTION_X 100
#define S3L_RESOLUTION_Y 100
2019-06-30 17:02:43 +02:00
#include "../small3dlib.h"
2018-11-21 16:46:01 +01:00
2019-05-04 23:04:13 +02:00
#define TEST_BUFFER_W 16
#define TEST_BUFFER_H 16
uint8_t testRaster[TEST_BUFFER_W * TEST_BUFFER_H];
void pixelFunc(S3L_PixelInfo *p)
{
2019-05-05 20:01:36 +02:00
testRaster[p->y * TEST_BUFFER_W + p->x] += 1;
2019-05-04 23:04:13 +02:00
}
2019-06-30 20:19:03 +02:00
int testTriangleRasterization(
2019-05-04 23:04:13 +02:00
S3L_ScreenCoord x0,
S3L_ScreenCoord y0,
S3L_ScreenCoord x1,
S3L_ScreenCoord y1,
S3L_ScreenCoord x2,
S3L_ScreenCoord y2,
uint8_t *expectedPixels
)
{
2019-05-05 20:01:36 +02:00
printf(" --- testing tringle rasterization [%d,%d] [%d,%d] [%d,%d] (|: expected, -: rasterized) ----\n",x0,y0,x1,y1,x2,y2);
2019-05-04 23:04:13 +02:00
memset(testRaster,0,TEST_BUFFER_W * TEST_BUFFER_H);
2019-06-30 17:02:43 +02:00
S3L_Vec4 p0, p1, p2;
S3L_setVec4(&p0,x0,y0,1000,0);
S3L_setVec4(&p1,x1,y1,1000,0);
S3L_setVec4(&p2,x2,y2,1000,0);
S3L_drawTriangle(p0,p1,p2,0,0);
2019-05-04 23:04:13 +02:00
printf(" 0123456789ABCDEF\n");
uint16_t numErrors = 0;
for (uint8_t y = 0; y < TEST_BUFFER_H; ++y)
{
printf(" %d",y);
if (y < 10)
printf(" ");
for (uint8_t x = 0; x < TEST_BUFFER_W; ++x)
{
uint8_t expected = expectedPixels[y * TEST_BUFFER_W + x];
uint8_t rasterized = testRaster[y * TEST_BUFFER_W + x];
char c =
expected ?
(rasterized ? '+' : '|')
:
(rasterized ? '-' : ' ');
if (c == '-' || c == '|')
numErrors++;
printf("%c",c);
}
printf("\n");
}
printf(" errors: %d\n\n",numErrors);
return numErrors;
}
2020-06-17 18:12:58 +02:00
int testRasterization(void)
2018-11-21 16:46:01 +01:00
{
2019-05-04 23:04:13 +02:00
printf("\n=== TESTING RASTERIZATION ===\n");
uint16_t numErrors = 0;
2019-05-05 02:42:16 +02:00
uint8_t pixelsEmpty[TEST_BUFFER_W * TEST_BUFFER_H];
memset(pixelsEmpty,0,TEST_BUFFER_W * TEST_BUFFER_H);
numErrors += testTriangleRasterization(5,3, 3,3, 9,3, pixelsEmpty);
numErrors += testTriangleRasterization(9,4, 9,0, 9,9, pixelsEmpty);
2019-05-05 20:55:52 +02:00
numErrors += testTriangleRasterization(9,9, 6,6, 3,3, pixelsEmpty);
numErrors += testTriangleRasterization(0,6, 3,3, 6,0, pixelsEmpty);
2019-05-05 20:01:36 +02:00
numErrors += testTriangleRasterization(7,7, 7,7, 7,7, pixelsEmpty);
2019-05-04 23:04:13 +02:00
uint8_t pixels1[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 2
0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 3
0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0, // 4
0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0, // 5
0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, // 6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
numErrors += testTriangleRasterization(4,1, 1,6, 9,7, pixels1);
uint8_t pixels2[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
2019-05-04 23:18:53 +02:00
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
2019-05-04 23:04:13 +02:00
0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0, // 2
0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, // 3
0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 4
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 5
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
numErrors += testTriangleRasterization(7,1, 1,2, 4,6, pixels2);
uint8_t pixels3[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
2019-05-04 23:18:53 +02:00
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2
0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3
0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 4
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 5
0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 6
2019-05-04 23:04:13 +02:00
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
2019-05-04 23:25:17 +02:00
numErrors += testTriangleRasterization(2,1, 1,3, 6,9, pixels3);
uint8_t pixels4[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 2
0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 3
0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 4
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 5
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
numErrors += testTriangleRasterization(4,8, 4,2, 0,0, pixels4);
2019-05-04 23:04:13 +02:00
2019-05-05 02:42:16 +02:00
uint8_t pixels5[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, // 2
0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 3
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
2019-05-04 23:04:13 +02:00
2019-05-05 02:42:16 +02:00
numErrors += testTriangleRasterization(6,2, 2,4, 0,0, pixels5);
uint8_t pixels6[TEST_BUFFER_W * TEST_BUFFER_H] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 1
1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0, // 2
0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, // 3
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
};
numErrors += testTriangleRasterization(0,2, 6,0, 4,4, pixels6);
2019-05-04 23:04:13 +02:00
2019-05-05 20:01:36 +02:00
printf("cover test (each pixel should be covered exactly once):\n\n");
S3L_ScreenCoord coords[] =
{
0,0,
6,0,
13,0,
15,0,
14,1,
11,2,
3,3,
11,4,
14,5,
0,6,
6,6,
13,8,
8,9,
3,12,
9,12,
11,13,
9,14,
0,15,
15,15
};
memset(testRaster,0,TEST_BUFFER_W * TEST_BUFFER_H);
2019-06-30 17:02:43 +02:00
#define dt(i1,i2,i3)\
{\
S3L_Vec4 p0, p1, p2;\
S3L_setVec4(&p0,coords[2*i1],coords[2*i1 + 1],1000,0);\
S3L_setVec4(&p1,coords[2*i2],coords[2*i2+1],1000,0);\
S3L_setVec4(&p2,coords[2*i3],coords[2*i3+1],1000,0);\
S3L_drawTriangle(p0,p1,p2,0,0);\
}
dt(0,1,6) // 0
dt(1,2,5) // 1
dt(2,4,5) // 2
dt(2,3,4) // 3
dt(0,6,9) // 4
dt(1,10,6) // 5
dt(1,5,10) // 6
dt(5,4,8) // 7
dt(4,3,8) // 8
dt(9,6,10) // 9
dt(10,5,12) // 10
dt(5,7,12) // 11
dt(5,7,11) // 12
dt(5,8,11) // 13
dt(8,3,18) // 14
dt(9,10,13) // 15
dt(10,12,13) // 16
dt(12,7,11) // 17
dt(11,8,18) // 18
dt(9,13,17) // 19
dt(13,12,14) // 20
dt(12,11,14) // 21
dt(11,14,15) // 22
dt(15,11,18) // 23
dt(13,14,16) // 24
dt(14,15,16) // 25
dt(17,13,16) // 26
dt(16,15,18) // 27
dt(16,17,18) // 28
2019-05-05 20:01:36 +02:00
// extra empty triangles
dt(12,12,12);
dt(9,10,10);
dt(1,10,10);
2019-05-05 22:32:52 +02:00
dt(9,6,1);
2019-05-05 20:01:36 +02:00
dt(0,6,10);
#undef dt
uint16_t numErrors2 = 0;
for (uint8_t y = 0; y < TEST_BUFFER_H - 1; ++y)
2019-05-05 20:13:07 +02:00
{ // ^ complete left and bottom aren't
printf(" "); // supposed to be rasterized
2019-05-05 20:01:36 +02:00
for (uint8_t x = 0; x < TEST_BUFFER_W - 1; ++x)
{
uint8_t count = testRaster[y * TEST_BUFFER_W + x];
printf("%d",count);
if (count != 1)
numErrors2++;
}
printf("\n");
}
printf(" errors: %d\n",numErrors2);
numErrors += numErrors2;
2019-05-04 23:04:13 +02:00
printf("total rasterization errors: %d\n",numErrors);
2019-06-30 20:19:03 +02:00
return numErrors;
}
2020-06-17 18:12:58 +02:00
static inline double absVal(double a)
2019-06-30 20:19:03 +02:00
{
return a >= 0.0 ? a : (-1 * a);
}
double vec3Len(S3L_Vec4 v)
{
return sqrt(
((double) v.x) * ((double) v.x) +
((double) v.y) * ((double) v.y) +
((double) v.z) * ((double) v.z));
}
2020-06-17 18:12:58 +02:00
int testGeneral(void)
2019-06-30 20:19:03 +02:00
{
printf("\n=== TESTING GENERAL ===\n");
printf("testing vector normalization precision...\n");
S3L_Unit m = 100 * S3L_FRACTIONS_PER_UNIT;
S3L_Unit tolerance = 0.1 * S3L_FRACTIONS_PER_UNIT;
uint32_t errors0 = 0;
uint32_t errors1 = 0;
2020-06-17 18:12:58 +02:00
for (S3L_Unit x = -1 * m; x < m; x += 3 * (absVal(x) / 64 + 1))
for (S3L_Unit y = -1 * m; y < m; y += 3 * (absVal(y) / 32 + 1))
for (S3L_Unit z = -1 * m; z < m; z += 5 * (absVal(z) / 64 + 1))
2019-06-30 20:19:03 +02:00
{
S3L_Vec4 v;
S3L_setVec4(&v,x,y,z,0);
S3L_normalizeVec3Fast(&v);
double l0 = vec3Len(v);
2020-06-17 18:12:58 +02:00
double e0 = absVal(l0 - S3L_FRACTIONS_PER_UNIT);
2019-06-30 20:19:03 +02:00
S3L_setVec4(&v,x,y,z,0);
S3L_normalizeVec3(&v);
double l1 = vec3Len(v);
2020-06-17 18:12:58 +02:00
double e1 = absVal(l1 - S3L_FRACTIONS_PER_UNIT);
2019-06-30 20:19:03 +02:00
if (e0 > tolerance)
errors0++;
if (e1 > tolerance)
{
errors1++;
printf("%f\n",l1);
S3L_logVec4(v);
}
}
printf("wrong normalization with unsafe function: %d\nwrong normalizations with safe function: %d\n",errors0,errors1);
return errors1;
2018-11-21 16:46:01 +01:00
}
2020-06-17 18:12:58 +02:00
int testRender(void)
2018-11-21 16:46:01 +01:00
{
2020-06-17 18:12:58 +02:00
printf("\n=== TESTING RENDER ===\n");
// TODO
return 0;
}
int main(void)
{
printf("testing small3dlib\n\n");
2018-11-21 16:58:26 +01:00
S3L_Mat4 m, m2;
2018-11-21 16:46:01 +01:00
S3L_Vec4 v;
S3L_initMat4(&m);
2019-06-30 17:02:43 +02:00
S3L_logMat4(m);
2018-11-21 16:46:01 +01:00
S3L_initVec4(&v);
2019-06-30 17:02:43 +02:00
S3L_logVec4(v);
2018-11-21 16:46:01 +01:00
S3L_vec4Xmat4(&v,&m);
2019-06-30 17:02:43 +02:00
S3L_logVec4(v);
2018-11-21 16:46:01 +01:00
2018-11-21 16:58:26 +01:00
S3L_makeTranslationMat(100,200,300,&m2);
2019-06-30 17:02:43 +02:00
S3L_logMat4(m2);
2018-11-21 16:46:01 +01:00
2018-11-21 16:58:26 +01:00
S3L_mat4Xmat4(&m,&m2);
2019-06-30 17:02:43 +02:00
S3L_logMat4(m);
2018-11-21 16:46:01 +01:00
2019-06-30 20:19:03 +02:00
uint32_t totalErrors = 0;
totalErrors += testGeneral();
2020-06-17 18:12:58 +02:00
totalErrors += testRasterization();
totalErrors += testRender();
2019-06-30 20:19:03 +02:00
printf("\n===== DONE =====\ntotal errors: %d\n",totalErrors);
2018-11-21 16:46:01 +01:00
return 0;
}