72 files changed, 1 insertions(+), 3907 deletions(-)
R src2/3d/{device/dither.c => er.c}
R src2/3d/{device/dither.h => er.h}
M src/moon3d.h
D src2/3d.h
D src2/3d/abstract.h
D src2/3d/abstract/aabbox.c
D src2/3d/abstract/aabbox.h
D src2/3d/abstract/color.h
D src2/3d/abstract/plane.c
D src2/3d/abstract/plane.h
D src2/3d/abstract/point.c
D src2/3d/abstract/point.h
D src2/3d/abstract/polygon.c
D src2/3d/abstract/polygon.h
D src2/3d/abstract/transform.c
D src2/3d/abstract/transform.h
D src2/3d/abstract/vertex.c
D src2/3d/abstract/vertex.h
D src2/3d/device.h
D src2/3d/device/endpoint.c
D src2/3d/device/endpoint.h
D src2/3d/device/rasterize.c
D src2/3d/device/rasterize.h
D src2/3d/device/viewport.c
D src2/3d/device/viewport.h
D src2/3d/image.h
D src2/3d/image/camera.c
D src2/3d/image/camera.h
D src2/3d/image/clip.c
D src2/3d/image/clip.h
D src2/3d/image/project.c
D src2/3d/image/project.h
D src2/3d/render.c
D src2/3d/render.h
D src2/3d/vertex_pool.c
D src2/3d/vertex_pool.h
D src2/3d/world.h
D src2/3d/world/light.c
D src2/3d/world/light.h
D src2/3d/world/mesh.c
D src2/3d/world/mesh.h
D src2/3d/world/object.c
D src2/3d/world/object.h
D src2/arraylist.h
D src2/input.c
D src2/input.h
D src2/main.c
D src2/player.c
D src2/player.h
D src2/scene.c
D src2/scene.h
D src2/scenes/cubeworld.c
D src2/scenes/cubeworld.h
D src2/scenes/moonworld.c
D src2/scenes/moonworld.h
D src2/sketch.c
D src2/sketch.h
D test2/assertions.h
D test2/assertions.test.c
D test2/clip.test.c
D test2/color.test.c
D test2/endpoint.test.c
D test2/light.test.c
D test2/main.test.c
D test2/model.test.c
D test2/performance.test.c
D test2/project.test.c
D test2/rasterize.test.c
D test2/render.test.c
D test2/tests.h
D test2/transform.test.c
D test2/vector.test.c
R src2/3d/device/dither.c => src/dither.c +0 -0
R src2/3d/device/dither.h => src/dither.h +0 -1
@@ 1,6 1,5 @@
#pragma once
-#include "../abstract.h"
#include "viewport.h"
void Dither(Viewport *frame);
M src/moon3d.h => src/moon3d.h +1 -0
@@ 2,6 2,7 @@
#include "camera.h"
#include "clip.h"
+#include "dither.h"
#include "mesh.h"
#include "model.h"
#include "obj.h"
D src2/3d.h => src2/3d.h +0 -7
@@ 1,7 0,0 @@
-#pragma once
-
-#include "3d/abstract.h"
-#include "3d/device.h"
-#include "3d/image.h"
-#include "3d/world.h"
-#include "3d/render.h"
D src2/3d/abstract.h => src2/3d/abstract.h +0 -9
@@ 1,9 0,0 @@
-#pragma once
-
-#include "abstract/aabbox.h"
-#include "abstract/color.h"
-#include "abstract/plane.h"
-#include "abstract/point.h"
-#include "abstract/polygon.h"
-#include "abstract/transform.h"
-#include "abstract/vertex.h"
D src2/3d/abstract/aabbox.c => src2/3d/abstract/aabbox.c +0 -53
@@ 1,53 0,0 @@
-#include "aabbox.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-AABBox *NewAABBox(double left, double right, double bottom, double top,
- double far, double near)
-{
- AABBox *v = malloc(sizeof(AABBox));
- v->left = left;
- v->right = right;
- v->bottom = bottom;
- v->top = top;
- v->far = far;
- v->near = near;
- return v;
-}
-
-AABBox Vol(double left, double right, double bottom, double top, double far, double near)
-{
- AABBox v = { left, right, bottom, top, near, far };
- return v;
-}
-
-AABBox *FromAABBox(AABBox *volume, Transform transform)
-{
- AABBox *newAABBox;
- Vertex rightTopNear = V(
- volume->right,
- volume->top,
- volume->near);
- Vertex leftBottomFar = V(
- volume->left,
- volume->bottom,
- volume->far);
-
- CommitTransform(transform, &rightTopNear);
- CommitTransform(transform, &leftBottomFar);
-
- newAABBox = NewAABBox(
- leftBottomFar.x,
- rightTopNear.x,
- leftBottomFar.y,
- rightTopNear.y,
- leftBottomFar.z,
- rightTopNear.z);
- return newAABBox;
-}
-
-void PrintAABBox(AABBox V)
-{
- printf(" %- 6.2f\n ┌────────┐\n ┌──┴─────┐ ─┼──%- 6.2f\n │ │ │%- 6.2f\n%- 6.2f│%- 6.2f │ │\n │ ├──┘\n └────────┘\n %- 6.2f\n\n",
- V.top, V.far, V.right, V.left, V.near, V.bottom);
-}
D src2/3d/abstract/aabbox.h => src2/3d/abstract/aabbox.h +0 -18
@@ 1,18 0,0 @@
-#pragma once
-
-#include "transform.h"
-
-// "Axis-Aligned Bounding Box"
-typedef struct AABBox {
- double left;
- double right;
- double bottom;
- double top;
- double near;
- double far;
-} AABBox;
-
-AABBox *NewAABBox(double left, double right, double bottom, double top, double far, double near);
-AABBox Vol(double left, double right, double bottom, double top, double far, double near);
-AABBox *FromAABBox(AABBox *volume, Transform transform);
-void PrintAABBox(AABBox vol);
D src2/3d/abstract/color.h => src2/3d/abstract/color.h +0 -15
@@ 1,15 0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-typedef double Color;
-typedef uint32_t Pixel;
-
-#define BLACK 0.0
-#define WHITE 1.0
-#define GRAY 0.5
-#define LT_GRAY 0.67
-#define DK_GRAY 0.33
-
-#define ColorPixel(X) (0xFF000000 | ((uint32_t)((X)*0xFF) << 16) | ((uint32_t)((X)*0xFF) << 8) | (uint32_t)((X)*0xFF))
-#define PixelColor(X) ((double)((X) & 0x000000FF) / (double)0xFF)
D src2/3d/abstract/plane.c => src2/3d/abstract/plane.c +0 -9
@@ 1,9 0,0 @@
-#include "plane.h"
-
-Plane Pl(Vertex ref, Vector normal)
-{
- Plane p;
- p.ref = ref;
- p.normal = normal;
- return p;
-}
D src2/3d/abstract/plane.h => src2/3d/abstract/plane.h +0 -10
@@ 1,10 0,0 @@
-#pragma once
-
-#include "vertex.h"
-
-typedef struct Plane {
- Vertex ref;
- Vector normal;
-} Plane;
-
-Plane Pl(Vertex ref, Vector normal);
D src2/3d/abstract/point.c => src2/3d/abstract/point.c +0 -10
@@ 1,10 0,0 @@
-#include "point.h"
-#include <stdlib.h>
-
-Point *NewPoint(Vector position, Color color)
-{
- Point *p = malloc(sizeof(Point));
- p->position = position;
- p->color = color;
- return p;
-}
D src2/3d/abstract/point.h => src2/3d/abstract/point.h +0 -11
@@ 1,11 0,0 @@
-#pragma once
-
-#include "vertex.h"
-#include "color.h"
-
-typedef struct Point {
- Vector position;
- Color color;
-} Point;
-
-Point *NewPoint(Vector position, Color color);
D src2/3d/abstract/polygon.c => src2/3d/abstract/polygon.c +0 -152
@@ 1,152 0,0 @@
-#include "polygon.h"
-#include "../../arraylist.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-Polygon *NewPolygon(void)
-{
- Polygon *p = malloc(sizeof(Polygon));
- p->vertices = NULL;
- p->vList = NULL;
- return p;
-}
-
-void AddVertex(Polygon *polygon, Vertex *vertex)
-{
- vIndex vi = FindVertex(polygon->vertices, vertex);
- if (vi == VERTEX_NOT_FOUND) {
- vi = list_count(polygon->vertices);
- list_push(polygon->vertices, vertex);
- }
- list_push(polygon->vList, vi);
-}
-
-Polygon *FromPolygon(Polygon *polygon, Transform transform)
-{
- Polygon *newPoly = NewPolygon();
- int i;
- Vertex *newVert;
-
- // transform all the polygon's vertices
- for (i = 0; i < NumVertices(polygon); i++) {
- newVert = NewVertex(0, 0, 0);
- *newVert = ApplyTransform(transform, *PolygonVertex(polygon, i));
- list_push(newPoly->vList, list_count(newPoly->vertices));
- list_push(newPoly->vertices, newVert);
- }
-
- return newPoly;
-}
-
-Polygon *CopyPolygon(Polygon *polygon)
-{
- Polygon *newPoly = NewPolygon();
- int i;
- Vertex *newVert;
-
- // transform all the polygon's vertices
- for (i = 0; i < NumVertices(polygon); i++) {
- newVert = NewVertex(0, 0, 0);
- *newVert = *PolygonVertex(polygon, i);
- list_push(newPoly->vList, list_count(newPoly->vertices));
- list_push(newPoly->vertices, newVert);
- }
-
- return newPoly;
-}
-
-Vertex *PolygonVertex(Polygon *polygon, int i)
-/* returns the ith vertex in a polygon */
-{
- int index = i % NumVertices(polygon);
- return polygon->vertices[polygon->vList[index]];
-}
-
-Vector PolygonCenter(Polygon *polygon)
-{
- double x = 0, y = 0, z = 0;
- int n = NumVertices(polygon);
- for (int i = 0; i < n; i++) {
- Vertex *v = PolygonVertex(polygon, i);
- x += v->x;
- y += v->y;
- z += v->z;
- }
-
- return V(x/n, y/n, z/n);
-}
-
-int NumVertices(Polygon *polygon)
-{
- return list_count(polygon->vList);
-}
-
-Vector PolygonNormal(Polygon *polygon)
-{
- assert(NumVertices(polygon) >= 3);
- Vertex a = Homogenize(*PolygonVertex(polygon, 0));
- Vertex b = Homogenize(*PolygonVertex(polygon, 1));
- Vertex c = Homogenize(*PolygonVertex(polygon, 2));
- Vector n = NormalizeVector(CrossProd(VecSub(b, a), VecSub(c, b)));
- return n;
-}
-
-void HomogenizePolygon(Polygon *polygon)
-{
- for (int i = 0; i < NumVertices(polygon); i++) {
- Vertex *v = PolygonVertex(polygon, i);
- *v = Homogenize(*v);
- }
-}
-
-Polygon **Triangularize(Polygon *polygon)
-{
- Polygon **triangles = NULL;
-
- if (NumVertices(polygon) < 3) {
- return NULL;
- } else if (NumVertices(polygon) == 3) {
- list_push(triangles, polygon);
- } else {
- Vertex *a = PolygonVertex(polygon, 0);
- for (int i = 1; i < NumVertices(polygon) - 1; i++) {
- Vertex *b = PolygonVertex(polygon, i);
- Vertex *c = PolygonVertex(polygon, i + 1);
- Polygon *tri = NewPolygon();
- AddVertex(tri, a);
- AddVertex(tri, b);
- AddVertex(tri, c);
- list_push(triangles, tri);
- }
- }
-
- return triangles;
-}
-
-bool IsTriangle(Polygon *polygon)
-{
- return NumVertices(polygon) == 3;
-}
-
-void FreePolygon(Polygon *p)
-{
- int i;
- for (i = 0; i < list_count(p->vertices); i++) {
- free(p->vertices[i]);
- }
- list_free(p->vertices);
- list_free(p->vList);
- free(p);
-}
-
-void PrintPolygon(Polygon *polygon)
-{
- int i;
- Vertex *v;
- printf("%d-gon:\n", NumVertices(polygon));
- for (i = 0; i < NumVertices(polygon); i++) {
- v = PolygonVertex(polygon, i);
- PrintVec(*v);
- }
-}
D src2/3d/abstract/polygon.h => src2/3d/abstract/polygon.h +0 -25
@@ 1,25 0,0 @@
-#pragma once
-
-#include "vertex.h"
-#include "transform.h"
-#include <stdbool.h>
-
-typedef struct Polygon {
- vIndex *vList; // list of indices into vertices of polygon vertices, CCW order
- Vertex **vertices; // list of possible vertices in polygon
-} Polygon;
-
-Polygon *NewPolygon();
-void AddVertex(Polygon *polygon, Vertex *vertex);
-Polygon *FromPolygon(Polygon *polygon, Transform transform);
-Polygon *CopyPolygon(Polygon *polygon);
-Vertex *PolygonVertex(Polygon *polygon, int i);
-Vector PolygonCenter(Polygon *polygon);
-int NumVertices(Polygon *polygon);
-Vector PolygonNormal(Polygon *polygon);
-void HomogenizePolygon(Polygon *polygon);
-Polygon **Triangularize(Polygon *polygon);
-bool IsTriangle(Polygon *polygon);
-void FreePolygon(Polygon *p);
-
-void PrintPolygon(Polygon *polygon);
D src2/3d/abstract/transform.c => src2/3d/abstract/transform.c +0 -251
@@ 1,251 0,0 @@
-#include "transform.h"
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdio.h>
-
-Transform Identity(void)
-{
- Transform t;
- SetIdentity(&t);
- return t;
-}
-
-void SetIdentity(Transform *m)
-{
- m->m[0][0] = 1;
- m->m[0][1] = 0;
- m->m[0][2] = 0;
- m->m[0][3] = 0;
-
- m->m[1][0] = 0;
- m->m[1][1] = 1;
- m->m[1][2] = 0;
- m->m[1][3] = 0;
-
- m->m[2][0] = 0;
- m->m[2][1] = 0;
- m->m[2][2] = 1;
- m->m[2][3] = 0;
-
- m->m[3][0] = 0;
- m->m[3][1] = 0;
- m->m[3][2] = 0;
- m->m[3][3] = 1;
-}
-
-bool IsIdentity(Transform t)
-{
- return
- t.m[0][0] == 1 && t.m[0][1] == 0 && t.m[0][2] == 0 && t.m[0][3] == 0 &&
- t.m[1][0] == 0 && t.m[1][1] == 1 && t.m[1][2] == 0 && t.m[1][3] == 0 &&
- t.m[2][0] == 0 && t.m[2][1] == 0 && t.m[2][2] == 1 && t.m[2][3] == 0 &&
- t.m[3][0] == 0 && t.m[3][1] == 0 && t.m[3][2] == 0 && t.m[3][3] == 1;
-}
-
-Transform *NewTransform(void)
-{
- Transform *t = malloc(sizeof(Transform));
- SetIdentity(t);
- return t;
-}
-
-Transform FromTransform(Transform transform)
-{
- int i, j;
- Transform newTransform = Identity();
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- newTransform.m[i][j] = transform.m[i][j];
- }
- }
- return newTransform;
-}
-
-void AddTransform(Transform A, Transform *subject)
-{
- int i, j, s;
- Transform B = FromTransform(*subject);
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- subject->m[i][j] = 0;
- for (s = 0; s < 4; s++) {
- subject->m[i][j] = subject->m[i][j] + A.m[i][s] * B.m[s][j];
- }
- }
- }
-}
-
-Transform ComposeTransform(Transform A, Transform B)
-{
- Transform C;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- C.m[i][j] = 0;
- for (int s = 0; s < 4; s++) {
- C.m[i][j] = C.m[i][j] + A.m[i][s] * B.m[s][j];
- }
- }
- }
-
- return C;
-}
-
-Vector ApplyTransform(Transform m, Vector v)
-/* Multiplies the transform matrix by the vector */
-{
- double x, y, z, W;
- Vector result;
-
- x = m.m[0][0] * v.x +
- m.m[0][1] * v.y +
- m.m[0][2] * v.z +
- m.m[0][3];
- y = m.m[1][0] * v.x +
- m.m[1][1] * v.y +
- m.m[1][2] * v.z +
- m.m[1][3];
- z = m.m[2][0] * v.x +
- m.m[2][1] * v.y +
- m.m[2][2] * v.z +
- m.m[2][3];
- W = m.m[3][0] * v.x +
- m.m[3][1] * v.y +
- m.m[3][2] * v.z +
- m.m[3][3];
-
- // printf("w: %f, %f, %f, %f\n", x, y, z, W);
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = W;
- return result;
-}
-
-void CommitTransform(Transform t, Vector *v)
-{
- *v = Homogenize(ApplyTransform(t, *v));
-}
-
-Transform RotationX(double angle)
-{
- Transform t = Identity();
- t.m[1][1] = cos(Rad(angle));
- t.m[1][2] = -sin(Rad(angle));
- t.m[2][1] = sin(Rad(angle));
- t.m[2][2] = cos(Rad(angle));
- return t;
-}
-
-Transform *RotateX(Transform *t, double angle)
-{
- Transform rotation = RotationX(angle);
- AddTransform(rotation, t);
- return t;
-}
-
-Transform RotationY(double angle)
-{
- Transform t = Identity();
- t.m[0][0] = cos(Rad(angle));
- t.m[0][2] = sin(Rad(angle));
- t.m[2][0] = -sin(Rad(angle));
- t.m[2][2] = cos(Rad(angle));
- return t;
-}
-
-Transform *RotateY(Transform *t, double angle)
-{
- Transform rotation = RotationY(angle);
- AddTransform(rotation, t);
- return t;
-}
-
-Transform RotationZ(double angle)
-{
- Transform t = Identity();
- t.m[0][0] = cos(Rad(angle));
- t.m[0][1] = -sin(Rad(angle));
- t.m[1][0] = sin(Rad(angle));
- t.m[1][1] = cos(Rad(angle));
- return t;
-}
-
-Transform *RotateZ(Transform *t, double angle)
-{
- Transform rotation = RotationZ(angle);
- AddTransform(rotation, t);
- return t;
-}
-
-Transform Translation(Vector dv)
-{
- Transform T = Identity();
- dv = Homogenize(dv);
- T.m[0][3] = dv.x;
- T.m[1][3] = dv.y;
- T.m[2][3] = dv.z;
- return T;
-}
-
-Transform *Translate(Transform *t, Vector p)
-{
- Transform translation = Translation(p);
- AddTransform(translation, t);
- return t;
-}
-
-Transform Scalation(double sx, double sy, double sz)
-{
- Transform S = Identity();
- S.m[0][0] = sx;
- S.m[1][1] = sy;
- S.m[2][2] = sz;
- return S;
-}
-
-Transform *Scale(Transform *t, double sx, double sy, double sz)
-{
- Transform scale = Scalation(sx, sy, sz);
- AddTransform(scale, t);
- return t;
-}
-
-double Determinant(Transform mat)
-{
- // Bareiss algorithm
- int i, j, k, n;
- double result;
-
- n = 4;
- Transform M = FromTransform(mat);
-
- for (i = 0; i < n-1; i++) {
- for (j = i + 1; j < n; j++)
- for (k = i + 1; k < n; k++) {
- M.m[j][k] = M.m[j][k] * M.m[i][i] - M.m[j][i] * M.m[i][k];
- if (i != 0) {
- M.m[j][k] = M.m[j][k] / M.m[i-1][i-1];
- }
- }
- }
-
- result = M.m[n-1][n-1];
- return result;
-}
-
-void PrintMat(Transform mat)
-{
- double det = Determinant(mat);
- printf("┌% 6.2f % 6.2f % 6.2f % 6.2f ┐\n",
- mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3]);
- printf("│% 6.2f % 6.2f % 6.2f % 6.2f │\n",
- mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3]);
- printf("│% 6.2f % 6.2f % 6.2f % 6.2f │\n",
- mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3]);
- printf("│% 6.2f % 6.2f % 6.2f % 6.2f │\n",
- mat.m[3][0], mat.m[3][1], mat.m[3][2], mat.m[3][3]);
- printf("└ Determinant: % 6.2f ┘\n", det);
-}
D src2/3d/abstract/transform.h => src2/3d/abstract/transform.h +0 -34
@@ 1,34 0,0 @@
-#pragma once
-
-#include "vertex.h"
-#include <stdbool.h>
-
-typedef struct Transform {
- double m[4][4];
-} Transform;
-
-#define MapRange(v, a0, a1, b0, b1) (((v)-(a0))*((b1)-(b0))/((a1)-(a0))+(b0))
-#define Rad(x) ((x)*M_PI/180)
-
-Transform Identity(void);
-void SetIdentity(Transform *m);
-bool IsIdentity(Transform t);
-Transform *NewTransform(void);
-Transform FromTransform(Transform transform);
-void AddTransform(Transform A, Transform *subject);
-Transform ComposeTransform(Transform A, Transform B);
-Vector ApplyTransform(Transform t, Vector v);
-void CommitTransform(Transform t, Vector *v);
-Transform RotationX(double angle);
-Transform *RotateX(Transform *t, double angle);
-Transform RotationY(double angle);
-Transform *RotateY(Transform *t, double angle);
-Transform RotationZ(double angle);
-Transform *RotateZ(Transform *t, double angle);
-Transform Translation(Vector dv);
-Transform *Translate(Transform *t, Vector p);
-Transform Scalation(double sx, double sy, double sz);
-Transform *Scale(Transform *t, double sx, double sy, double sz);
-double Determinant(Transform mat);
-
-void PrintMat(Transform mat);
D src2/3d/abstract/vertex.c => src2/3d/abstract/vertex.c +0 -150
@@ 1,150 0,0 @@
-#include "vertex.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "../../arraylist.h"
-#include <math.h>
-#include <assert.h>
-
-Vector *NewVector(double x, double y, double z)
-{
- Vector *v = malloc(sizeof(Vector));
- *v = V4D(x, y, z, 1);
- return v;
-}
-
-Vector *NewVector4D(double x, double y, double z, double w)
-{
- Vector *v = malloc(sizeof(Vector));
- *v = V4D(x, y, z, w);
- return v;
-}
-
-Vector V(double x, double y, double z)
-{
- Vector v = { x, y, z, 1 };
- return v;
-}
-
-Vector V4D(double x, double y, double z, double w)
-{
- Vector v = { x, y, z, w };
- return v;
-}
-
-Vector Homogenize(Vector v4d)
-{
- Vector v = {
- v4d.x / v4d.w,
- v4d.y / v4d.w,
- v4d.z / v4d.w,
- 1
- };
- return v;
-}
-
-Vector *FromVector(Vector v)
-{
- return NewVector4D(v.x, v.y, v.z, v.w);
-}
-
-bool VectorEqual(Vector a, Vector b)
-{
- return fabs(a.x - b.x) < EPSILON &&
- fabs(a.y - b.y) < EPSILON &&
- fabs(a.z - b.z) < EPSILON &&
- fabs(a.w - b.w) < EPSILON;
-}
-
-vIndex FindVertex(Vertex **vertices, Vertex *vertex)
-{
- int i;
- for (i = 0; i < list_count(vertices); i++) {
- if (VectorEqual(*vertices[i], *vertex)) {
- return i;
- }
- }
- return VERTEX_NOT_FOUND;
-}
-
-
-Vector NegVec(Vector v)
-{
- return V(-v.x, -v.y, -v.z);
-}
-
-Vector NegVec4D(Vector v)
-{
- return V4D(-v.x, -v.y, -v.z, -v.w);
-}
-
-Vector VecMul(Vector v, double s)
-{
- return V(s*v.x, s*v.y, s*v.z);
-}
-
-Vector VecMul4D(Vector v, double s)
-{
- return V4D(s*v.x, s*v.y, s*v.z, s*v.w);
-}
-
-Vector VecAdd(Vector a, Vector b)
-{
- assert(a.w == b.w);
- return V(a.x + b.x, a.y + b.y, a.z + b.z);
-}
-
-Vector VecAdd4D(Vector a, Vector b)
-{
- return V4D(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
-}
-
-Vector VecSub(Vector a, Vector b)
-{
- assert(a.w == b.w);
- return V(a.x - b.x, a.y - b.y, a.z - b.z);
-}
-
-Vector VecSub4D(Vector a, Vector b)
-{
- return V4D(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
-}
-
-double VecLen(Vector v)
-{
- return sqrt(DotProd(v, v));
-}
-
-double DotProd(Vector a, Vector b)
-{
- assert(a.w == b.w);
- return a.x*b.x + a.y*b.y + a.z*b.z;
-}
-
-double DotProd4D(Vector a, Vector b)
-{
- return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
-}
-
-Vector CrossProd(Vector a, Vector b)
-{
- assert(a.w == b.w);
- double x = a.y * b.z - a.z * b.y;
- double y = a.z * b.x - a.x * b.z;
- double z = a.x * b.y - a.y * b.x;
-
- return V(x, y, z);
-}
-
-Vector NormalizeVector(Vector v)
-{
- double len = VecLen(v);
- double x = v.x / len;
- double y = v.y / len;
- double z = v.z / len;
- return V(x, y, z);
-}
-
-void PrintVec(Vector vec)
-{
- printf("( %+.16e, %+.16e, %+.16e, %+.16e )\n", vec.x, vec.y, vec.z, vec.w);
-}
D src2/3d/abstract/vertex.h => src2/3d/abstract/vertex.h +0 -34
@@ 1,34 0,0 @@
-#pragma once
-
-#include <stdbool.h>
-
-#define EPSILON 0.0000001
-#define VERTEX_NOT_FOUND -1
-typedef int vIndex; // index into a vertex list
-
-typedef struct Vertex {
- double x, y, z, w;
-} Vector, Vertex;
-
-Vector Homogenize(Vector v4d);
-bool VectorEqual(Vector a, Vector b);
-#define VertexEqual(a, b) VectorEqual(a, b)
-Vector V(double x, double y, double z);
-Vector V4D(double x, double y, double z, double w);
-vIndex FindVertex(Vertex **vertices, Vertex *vertex);
-
-Vector NegVec(Vector vector);
-Vector NegVec4D(Vector v);
-Vector VecMul(Vector v, double s);
-Vector VecMul4D(Vector v, double s);
-Vector VecAdd(Vector a, Vector b);
-Vector VecAdd4D(Vector a, Vector b);
-Vector VecSub(Vector a, Vector b);
-Vector VecSub4D(Vector a, Vector b);
-double VecLen(Vector v);
-double DotProd(Vector a, Vector b);
-double DotProd4D(Vector a, Vector b);
-Vector CrossProd(Vector a, Vector b);
-Vector NormalizeVector(Vector v);
-
-void PrintVec(Vector vec);
D src2/3d/device.h => src2/3d/device.h +0 -6
@@ 1,6 0,0 @@
-#pragma once
-
-#include "device/dither.h"
-#include "device/endpoint.h"
-#include "device/rasterize.h"
-#include "device/viewport.h"
D src2/3d/device/endpoint.c => src2/3d/device/endpoint.c +0 -261
@@ 1,261 0,0 @@
-#include "endpoint.h"
-#include <stdlib.h>
-#include <math.h>
-#include <stdio.h>
-#include "../../arraylist.h"
-
-Endpoint *NewEndpoint(double ymax, double x, double xinc)
-{
- Endpoint *e = malloc(sizeof(Endpoint));
- e->ymax = ymax;
- e->x = x;
- e->xinc = xinc;
- e->next = NULL;
- return e;
-}
-
-Endpoint *MakeEndpoint(Vertex *upper, Vertex *lower)
-{
- double ymax, x, xinc, z, zinc;
- Endpoint *endpoint;
-
- ymax = upper->y;
- x = lower->x;
- xinc = (upper->x - lower->x) / (upper->y - lower->y);
- z = lower->z;
- zinc = (upper->z - lower->z) / (upper->y - lower->y);
- endpoint = NewEndpoint(ymax, x, xinc);
-
- /* add custom properties here */
- endpoint->z = z;
- endpoint->zinc = zinc;
-
- return endpoint;
-}
-
-void InsertEndpoint(Endpoint **list, Endpoint *endpoint)
-/* insertion sort, by x */
-{
- Endpoint *curNode;
-
- endpoint->next = NULL;
-
- if (*list == NULL) {
- *list = endpoint;
- } else if (endpoint->x < (*list)->x) {
- endpoint->next = *list;
- *list = endpoint;
- } else {
- curNode = *list;
- while (curNode->next != NULL
- && endpoint->x > curNode->next->x ) {
- curNode = curNode->next;
- }
-
- endpoint->next = curNode->next;
- curNode->next = endpoint;
- }
-}
-
-void InsertEndpoints(Endpoint **list, Endpoint *endpoint)
-{
- Endpoint *curNode, *nextNode;
-
- curNode = endpoint;
- while (curNode != NULL) {
- nextNode = curNode->next;
- InsertEndpoint(list, curNode);
- curNode = nextNode;
- }
-}
-
-void IncrementEndpoints(Endpoint **endpoints, int y)
-{
- Endpoint *curNode;
- curNode = *endpoints;
-
- while(curNode != NULL) {
- if (floor(curNode->ymax) != y + 1) {
- curNode->x += curNode->xinc;
- curNode->z += curNode->zinc;
- } else {
- curNode->x += curNode->xinc*(curNode->ymax - (y + 1));
- }
- curNode = curNode->next;
- }
-}
-
-void SortEndpoints(Endpoint **endpoints)
-/* Bubble sort, 1 pass */
-{
- Endpoint *curNode, *a, *b, *c;
-
- if (*endpoints == NULL || (*endpoints)->next == NULL)
- return;
-
- a = *endpoints;
- b = a->next;
- if (a->x > b->x) {
- c = b->next;
- *endpoints = b;
- b->next = a;
- a->next = c;
- }
-
- curNode = *endpoints;
- while(curNode != NULL &&
- curNode->next != NULL &&
- curNode->next->next != NULL) {
- a = curNode->next;
- b = a->next;
- if (a->x > b->x) {
- c = b->next;
- curNode->next = b;
- b->next = a;
- a->next = c;
- }
-
- curNode = curNode->next;
- }
-}
-
-void RemoveEndpoints(Endpoint **list, int y)
-{
- Endpoint *curNode, *oldNode;
-
- while ((*list != NULL) && floor((*list)->ymax) == y) {
- oldNode = *list;
- *list = (*list)->next;
- free(oldNode);
- }
- if (*list == NULL) {
- return;
- }
-
- curNode = *list;
- while (curNode != NULL) {
- while (curNode->next != NULL && floor(curNode->next->ymax) == y) {
- oldNode = curNode->next;
- curNode->next = curNode->next->next;
- free(oldNode);
- }
- curNode = curNode->next;
- }
-}
-
-void FreeEndpoints(Endpoint *endpoints)
-{
- Endpoint *curNode = endpoints;
- Endpoint *oldNode;
- while (curNode != NULL) {
- oldNode = curNode;
- curNode = curNode->next;
- free(oldNode);
- }
-}
-
-Endpoint **MakeEdgeTable(unsigned int numLines, Polygon *polygon)
-{
- Endpoint **buckets = malloc(sizeof(Endpoint *)*numLines);
- vIndex i;
- unsigned int bucket;
- Vertex *a, *b, *upper, *lower;
-
- for (bucket = 0; bucket < numLines; bucket++) {
- buckets[bucket] = NULL;
- }
-
- for (i = 0; i < NumVertices(polygon); i++) {
- a = PolygonVertex(polygon, i);
- b = PolygonVertex(polygon, i+1);
- lower = LowerVertex(a, b);
- upper = (a == lower) ? b : a;
-
- if (upper->y != lower->y) {
- bucket = floor(lower->y);
- InsertEndpoint(&buckets[bucket], MakeEndpoint(upper, lower));
- }
- }
-
- return buckets;
-}
-
-int FirstBucket(Endpoint **table, int length)
-/* returns first non-empty table index, or -1 if table is empty */
-{
- int bucket;
- for (bucket = 0; bucket < length; bucket++) {
- if (table[bucket] != NULL) {
- return bucket;
- }
- }
- return -1;
-}
-
-void FreeEdgeTable(Endpoint **table, int length)
-{
- int bucket;
- for (bucket = 0; bucket < length; bucket++) {
- if (table[bucket] != NULL) {
- // FreeEndpoints(table[bucket]);
- }
- }
- free(table);
-}
-
-Vertex *LowerVertex(Vertex *a, Vertex *b)
-{
- if (a->y < b->y) {
- return a;
- } else {
- return b;
- }
-}
-
-void PrintEndpoint(Endpoint *endpoint)
-{
- printf("│ymax: %.2f\n", endpoint->ymax);
- printf("│x: %.2f (%+.2f)\n", endpoint->x, endpoint->xinc);
- printf("│z: %.2f (%+.2f)\n", endpoint->z, endpoint->zinc);
- printf("├────────\n");
- if(endpoint->next == NULL) {
- printf("┴");
- }
- printf("\n");
-}
-
-void PrintEndpoints(Endpoint *endpoints)
-{
- Endpoint *curNode = endpoints;
- // printf("┌────────────\n");
- while (curNode != NULL) {
- printf("│ymax: %.2f\n", curNode->ymax);
- printf("│x: %.2f (%+.2f)\n", curNode->x, curNode->xinc);
- printf("│z: %.2f (%+.2f)\n", curNode->z, curNode->zinc);
- printf("├────────\n");
- curNode = curNode->next;
- }
- printf("┴\n");
-}
-
-void PrintTable(Endpoint **table, int numBuckets)
-{
- for(int i = 0; i < numBuckets; i++) {
- if (table[i] != NULL) {
- printf("┌─ %d ───────────\n", i);
- // printf("%d: ", i);
- PrintEndpoints(table[i]);
- }
- }
-}
-
-int ListLength(Endpoint *list)
-{
- Endpoint *curNode = list;
- int count = 0;
- while (curNode != NULL) {
- count++;
- curNode = curNode->next;
- }
- return count;
-}
D src2/3d/device/endpoint.h => src2/3d/device/endpoint.h +0 -34
@@ 1,34 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-
-typedef struct Endpoint {
- double ymax;
- double x;
- double xinc;
- double z;
- double zinc;
- int color;
- struct Endpoint *next;
-} Endpoint;
-
-Endpoint *NewEndpoint(double ymax, double x, double xinc);
-Endpoint *MakeEndpoint(Vertex *upper, Vertex *lower);
-void InsertEndpoint(Endpoint **list, Endpoint *endpoint);
-void InsertEndpoints(Endpoint **list, Endpoint *endpoint);
-void IncrementEndpoints(Endpoint **endpoints, int y);
-void SortEndpoints(Endpoint **endpoints);
-void RemoveEndpoints(Endpoint **list, int y);
-void FreeEndpoints(Endpoint *endpoints);
-
-Endpoint **MakeEdgeTable(unsigned int numLines, Polygon *polygon);
-int FirstBucket(Endpoint **table, int length);
-void FreeEdgeTable(Endpoint **table, int size);
-
-Vertex *LowerVertex(Vertex *a, Vertex *b);
-
-// debug
-void PrintEndpoint(Endpoint *endpoint);
-void PrintEndpoints(Endpoint *endpoints);
-void PrintTable(Endpoint **table, int numBuckets);
-int ListLength(Endpoint *list);
D src2/3d/device/rasterize.c => src2/3d/device/rasterize.c +0 -154
@@ 1,154 0,0 @@
-
-#include "rasterize.h"
-#include <math.h>
-#include <stddef.h>
-
-RasterSettings DefaultRasterSettings(void)
-{
- RasterSettings s;
- s.showWireframes = false;
- s.showDepthBuffer = false;
- return s;
-}
-
-void RasterPolygon(Polygon *polygon, Color color, Viewport *viewport, RasterSettings settings)
-{
- int y;
- Endpoint **ET = MakeEdgeTable(viewport->height, polygon);
- Endpoint *AET = NULL;
-
- y = FirstBucket(ET, viewport->height);
- if (y != -1) {
- do {
- InsertEndpoints(&AET, ET[y]);
- RemoveEndpoints(&AET, y);
- IncrementEndpoints(&AET, y);
- SortEndpoints(&AET);
- ColorSpans(&AET, y, color, viewport, settings);
-
- y += 1;
- } while (y < viewport->height && AET != NULL);
- }
-
- FreeEdgeTable(ET, viewport->height);
-}
-
-void ColorSpans(Endpoint **endpoints, int y, Color color, Viewport *viewport, RasterSettings settings)
-{
- Endpoint *curNode;
- int xmin, xmax, x;
- double zmin, zmax;
-
- curNode = *endpoints;
- while (curNode != NULL && curNode->next != NULL) {
- xmin = floor(curNode->x);
- xmax = floor(curNode->next->x);
- zmin = curNode->z;
- zmax = curNode->next->z;
- for (x = xmin; x < xmax; x++) {
- // TODO: refactor to use constant zxinc per polygon
- double z = MapRange(x, xmin, xmax, zmin, zmax);
-
- if (settings.showDepthBuffer) {
- color = z;
- }
-
- if (UpdateDepthBuffer(x, y, z, viewport)) {
- WritePixel(x, y, color, viewport);
- }
- }
- curNode = curNode->next->next;
- }
-}
-
-void RasterTriangle(Polygon *tri, Color color)
-{
-
-}
-
-void RasterLine(Vertex a, Vertex b, Color color, Viewport *viewport)
-{
- double dx = b.x - a.x;
- double dy = b.y - a.y;
- if (fabs(dy) < fabs(dx)) {
- if (a.x > b.x) {
- RasterLineShallow(b, a, color, viewport);
- } else {
- RasterLineShallow(a, b, color, viewport);
- }
- } else {
- if (a.y > b.y) {
- RasterLineSteep(b, a, color, viewport);
- } else {
- RasterLineSteep(a, b, color, viewport);
- }
- }
-}
-
-void RasterLineShallow(Vertex a, Vertex b, Color color, Viewport *viewport)
-{
- double dx = b.x - a.x;
- double dy = b.y - a.y;
- double yi = 1;
- if (dy < 0) {
- yi = -1;
- dy = -dy;
- }
-
- double d = 2*dy - dx;
- double x;
- double y = a.y;
-
- for (x = a.x; x <= b.x; x++) {
- double z = MapRange(x, a.x, b.x, a.z, b.z);
- if (UpdateDepthBuffer(x, y, z, viewport)) {
- WritePixel(x, y, color, viewport);
- }
- if (d > 0) {
- y += yi;
- d -= 2*dx;
- }
- d += 2*dy;
- }
-}
-
-void RasterLineSteep(Vertex a, Vertex b, Color color, Viewport *viewport)
-{
- double dx = b.x - a.x;
- double dy = b.y - a.y;
- double xi = 1;
- if (dx < 0) {
- xi = -1;
- dx = -dx;
- }
-
- double d = 2*dx - dy;
- double x = a.x;
- double y;
-
- for (y = a.y; y <= b.y; y++) {
- double z = MapRange(y, a.y, b.y, a.z, b.z);
- if (UpdateDepthBuffer(x, y, z, viewport)) {
- WritePixel(x, y, color, viewport);
- }
- if (d > 0) {
- x += xi;
- d -= 2*dy;
- }
- d += 2*dx;
- }
-}
-
-void WritePixel(int x, int y, Color color, Viewport *viewport)
-{
- Pixel p = ColorPixel(color);
- if (x >= 0 && x < viewport->width && y >= 0 && y < viewport->height) {
- viewport->pixels[(viewport->height - 1 - y)*viewport->width+x] = p;
- }
-}
-
-Color GetPixel(int x, int y, Viewport *viewport)
-{
- Pixel p = viewport->pixels[(viewport->height - 1 - y)*viewport->width+x];
- return PixelColor(p);
-}
D src2/3d/device/rasterize.h => src2/3d/device/rasterize.h +0 -26
@@ 1,26 0,0 @@
-#pragma once
-
-#include "endpoint.h"
-#include "../abstract.h"
-#include "viewport.h"
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct RasterSettings {
- bool showWireframes;
- bool showDepthBuffer;
-} RasterSettings;
-
-RasterSettings DefaultRasterSettings(void);
-
-void RasterPolygon(Polygon *polygon, Color color, Viewport *viewport, RasterSettings settings);
-void ColorSpans(Endpoint **endpoints, int y, Color color, Viewport *viewport, RasterSettings settings);
-
-void RasterTriangle(Polygon *tri, Color color);
-
-void RasterLine(Vertex a, Vertex b, Color color, Viewport *viewport);
-void RasterLineShallow(Vertex a, Vertex b, Color color, Viewport *viewport);
-void RasterLineSteep(Vertex a, Vertex b, Color color, Viewport *viewport);
-
-void WritePixel(int x, int y, Color color, Viewport *viewport);
-Color GetPixel(int x, int y, Viewport *viewport);
D src2/3d/device/viewport.c => src2/3d/device/viewport.c +0 -66
@@ 1,66 0,0 @@
-#include "viewport.h"
-#include "../image.h"
-#include "../render.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <math.h>
-
-Viewport *NewViewport(Pixel *pixels, Color bg, int width, int height)
-{
- Viewport *viewport = malloc(sizeof(Viewport));
- viewport->pixels = pixels;
- viewport->background = bg;
- viewport->width = width;
- viewport->height = height;
- viewport->depthbuffer = NULL;
- ClearViewport(viewport);
- InitDeviceTransform(width, height);
- // z buffer enabled by default
- AddDepthBuffer(viewport);
-
- return viewport;
-}
-
-void ClearViewport(Viewport *viewport)
-{
- for (int y = 0; y < viewport->height; y++) {
- for (int x = 0; x < viewport->width; x++) {
- WritePixel(x, y, viewport->background, viewport);
- if (viewport->depthbuffer != NULL)
- viewport->depthbuffer[y*viewport->width + x] = -INFINITY;
- }
- }
- // AddDepthBuffer(viewport);
-}
-
-void AddDepthBuffer(struct Viewport *viewport)
-{
- assert(viewport->pixels != NULL);
-
- DepthVal *values = malloc(sizeof(DepthVal)*viewport->width*viewport->height);
- for(int y = 0; y < viewport->height; y++) {
- for (int x = 0; x < viewport->width; x++) {
- values[y*viewport->width + x] = -INFINITY;
- }
- }
-
- viewport->depthbuffer = values;
-}
-
-bool UpdateDepthBuffer(int x, int y, double z, struct Viewport *viewport)
-{
- assert(viewport->depthbuffer != NULL);
-
- if (z > viewport->depthbuffer[y*viewport->width+x]) {
- viewport->depthbuffer[y*viewport->width+x] = z;
- return true;
- } else {
- return false;
- }
-}
-
-void DisableDepthBuffer(Viewport *viewport)
-{
- free(viewport->depthbuffer);
- viewport->depthbuffer = NULL;
-}
D src2/3d/device/viewport.h => src2/3d/device/viewport.h +0 -20
@@ 1,20 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-
-typedef double DepthVal;
-
-typedef struct Viewport {
- Color background;
- int width;
- int height;
- Pixel *pixels;
- DepthVal *depthbuffer;
-} Viewport;
-
-Viewport *NewViewport(Pixel *pixels, Color bg, int width, int height);
-Viewport *GetViewport(void);
-void ClearViewport(Viewport *viewport);
-void AddDepthBuffer(Viewport *viewport);
-bool UpdateDepthBuffer(int x, int y, double z, Viewport *viewport);
-void DisableDepthBuffer(Viewport *viewport);
D src2/3d/image.h => src2/3d/image.h +0 -5
@@ 1,5 0,0 @@
-#pragma once
-
-#include "image/camera.h"
-#include "image/clip.h"
-#include "image/project.h">
\ No newline at end of file
D src2/3d/image/camera.c => src2/3d/image/camera.c +0 -57
@@ 1,57 0,0 @@
-#include "camera.h"
-#include <stdlib.h>
-#include <assert.h>
-
-Camera *NewCamera(Vector position)
-{
- Camera *camera = malloc(sizeof(Camera));
- camera->position = position;
- camera->direction = V(0, 0, -1);
- camera->up = V(0, 1, 0);
- camera->transform = Identity();
- return camera;
-}
-
-void LookAt(Vector p, Camera *camera)
-{
- camera->direction = NormalizeVector(VecSub(p, camera->position));
-}
-
-void StandOn(Vector p, Camera *camera)
-{
- camera->up = NormalizeVector(VecSub(p, camera->position));
-}
-
-void MoveCamera(Vector dv, Camera *camera)
-{
- camera->position = VecAdd(camera->position, dv);
-}
-
-void RotateCamera(double rx, double ry, double rz, Camera *camera)
-{
- Transform t = RotationX(rx);
- AddTransform(RotationY(ry), &t);
- AddTransform(RotationZ(rz), &t);
- camera->direction = NormalizeVector(ApplyTransform(t, camera->direction));
-}
-
-Transform AlignCameraToAxis(Camera *camera)
-{
- Vector Rx, Ry, Rz;
- Transform op = Identity();
- Rz = NegVec(camera->direction);
- Rx = CrossProd(camera->up, NegVec(camera->direction));
- Ry = CrossProd(Rz, Rx);
- op.m[0][0] = Rx.x;
- op.m[0][1] = Rx.y;
- op.m[0][2] = Rx.z;
-
- op.m[1][0] = Ry.x;
- op.m[1][1] = Ry.y;
- op.m[1][2] = Ry.z;
-
- op.m[2][0] = Rz.x;
- op.m[2][1] = Rz.y;
- op.m[2][2] = Rz.z;
- return op;
-}
D src2/3d/image/camera.h => src2/3d/image/camera.h +0 -18
@@ 1,18 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-
-typedef struct Camera {
- Vector position;
- Vector direction;
- Vector up;
- Transform transform;
-} Camera;
-
-Camera *NewCamera(Vector position);
-void LookAt(Vector p, Camera *camera);
-void StandOn(Vector p, Camera *camera);
-void RotateCamera(double rx, double ry, double rz, Camera *camera);
-void MoveCamera(Vector dv, Camera *camera);
-Transform AlignCameraToAxis(Camera *camera);
-Transform CameraTransform(Camera *camera);
D src2/3d/image/clip.c => src2/3d/image/clip.c +0 -179
@@ 1,179 0,0 @@
-#include "clip.h"
-
-#include "../../arraylist.h"
-
-bool ClipLine(Vector *v0, Vector *v1)
-/* alters v0 and v1 to fit within the canonical view volume */
-{
- /* Adapted Liang-Barsky, from FvDF&H */
- double tmin = 0, tmax = 1;
- double dx = v1->x - v0->x;
- double dw = v1->w - v0->w;
- bool accept = false;
-
- if (ClipT(dx + dw, -v0->x - v0->w, &tmin, &tmax)) { /* x >= -w */
- if (ClipT(-dx + dw, v0->x - v0->w, &tmin, &tmax)) { /* x <= w */
- double dy = v1->y - v0->y;
- if (ClipT(dy + dw, -v0->y - v0->w, &tmin, &tmax)) { /* y >= -w */
- if (ClipT(-dy + dw, v0->y - v0->w, &tmin, &tmax)) { /* y <= w */
- double dz = v1->z - v0->z;
- if (ClipT(dz + dw, -v0->z - v0->w, &tmin, &tmax)) { /* z >= -w */
- if (ClipT(-dz + dw, v0->z - v0->w, &tmin, &tmax)) { /* z <= w */
- accept = true; /* part of line is visible */
- if (tmax < 1) {
- v1->x = v0->x + tmax * dx;
- v1->y = v0->y + tmax * dy;
- v1->z = v0->z + tmax * dz;
- v1->w = v0->w + tmax * dw;
- }
- if (tmin > 0) {
- v0->x += tmin * dx;
- v0->y += tmin * dy;
- v0->z += tmin * dz;
- v0->w += tmin * dw;
- }
- }
- }
- }
- }
- }
- }
-
- return accept;
-}
-
-bool ClipT(double den, double num, double *tE, double *tL)
-{
- double t;
-
- if (den > 0) {
- /* Potentially entering clip region */
- t = num / den;
- if (t > *tL) {
- return false;
- } else if (t > *tE) {
- *tE = t;
- }
- } else if (den < 0) {
- /* Potentially leaving clip region */
- t = num / den;
- if (t < *tE) {
- return false;
- } else if (t < *tL) {
- *tL = t;
- }
- } else if (num > 0) {
- return false;
- }
-
- return true;
-}
-
-bool ClipPoint(Vector p)
-{
- // planes in W-space
- Plane x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
- Plane x_pos = Pl(V4D(0, 0, 0, 0), V4D( 1, 0, 0, -1));
- Plane y_neg = Pl(V4D(0, 0, 0, 0), V4D( 0, -1, 0, -1));
- Plane y_pos = Pl(V4D(0, 0, 0, 0), V4D( 0, 1, 0, -1));
- // Plane z_neg = Pl(V4D(0, 0, 0, 0), V4D( 0, 0, -1, -1));
- // Plane z_pos = Pl(V4D(0, 0, 0, 0), V4D( 0, 0, 1, -1));
-
- return VertexInside(&p, x_neg)
- && VertexInside(&p, x_pos)
- && VertexInside(&p, y_neg)
- && VertexInside(&p, y_pos);
- // && VertexInside(&p, z_neg)
- // && VertexInside(&p, z_pos);
-}
-
-bool ClipPolygon(Polygon **polygon)
-/* alters the vertices of a polygon to fit within -w <= x, y, z <= w
- * returns whether polygon is visible after clipping */
-{
- // planes in W-space
- Plane x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
- Plane x_pos = Pl(V4D(0, 0, 0, 0), V4D( 1, 0, 0, -1));
- Plane y_neg = Pl(V4D(0, 0, 0, 0), V4D( 0, -1, 0, -1));
- Plane y_pos = Pl(V4D(0, 0, 0, 0), V4D( 0, 1, 0, -1));
- Plane z_neg = Pl(V4D(0, 0, 0, 0), V4D( 0, 0, -1, -1));
- Plane z_pos = Pl(V4D(0, 0, 0, 0), V4D( 0, 0, 1, -1));
-
- ClipPolygonPlane(polygon, x_neg);
- ClipPolygonPlane(polygon, x_pos);
- ClipPolygonPlane(polygon, y_neg);
- ClipPolygonPlane(polygon, y_pos);
- ClipPolygonPlane(polygon, z_neg);
- ClipPolygonPlane(polygon, z_pos);
-
- // floating point errors can make some vertices still be out of bounds...
- ConstrainPolygon(*polygon);
-
- return NumVertices(*polygon) > 2;
-}
-
-void ConstrainPolygon(Polygon *polygon)
-{
- for (int i = 0; i < NumVertices(polygon); i++) {
- Vertex *v = PolygonVertex(polygon, i);
- if (v->x < -v->w) v->x = -v->w;
- if (v->x > v->w) v->x = v->w;
- if (v->y < -v->w) v->y = -v->w;
- if (v->y > v->w) v->y = v->w;
- if (v->z < -v->w) v->z = -v->w;
- if (v->z > v->w) v->z = v->w;
- }
-}
-
-void ClipPolygonPlane(Polygon **polygon, Plane clipBoundary)
-/* Sutherland-Hodgeman algorithm */
-{
- Polygon *clipped = NewPolygon();
- int j;
- Vertex *s, *p, *i, *newVert;
-
- if ((*polygon)->vList == NULL) {
- return;
- }
-
- s = PolygonVertex(*polygon, list_last((*polygon)->vList));
- for (j = 0; j < NumVertices(*polygon); j++) {
- p = PolygonVertex(*polygon, j);
- if (VertexInside(p, clipBoundary)) {
- if (VertexInside(s, clipBoundary)) {
- newVert = NewVector4D(p->x, p->y, p->z, p->w);
- AddVertex(clipped, newVert);
- } else {
- i = FromVertex(ClipIntersect(s, p, clipBoundary));
- AddVertex(clipped, i);
- newVert = NewVector4D(p->x, p->y, p->z, p->w);
- AddVertex(clipped, newVert);
- }
- } else {
- if (VertexInside(s, clipBoundary)) {
- i = FromVertex(ClipIntersect(s, p, clipBoundary));
- AddVertex(clipped, i);
- }
- }
- s = p;
- }
-
- FreePolygon(*polygon);
- *polygon = clipped;
-}
-
-bool VertexInside(Vertex *v, Plane clipBoundary)
-{
- Vector n = clipBoundary.normal;
- return DotProd4D(n, *v) <= 0;
-}
-
-Vertex ClipIntersect(Vertex *s, Vertex *p, Plane clipBoundary)
-{
- Vector sp = VecSub4D(*s, *p);
- Vector n = clipBoundary.normal;
-
- // t = -n•p / n•(s-p)
- double t = DotProd4D(NegVec4D(n), *p) / DotProd4D(n, sp);
- return V4D(p->x + t*sp.x, p->y + t*sp.y, p->z + t*sp.z, p->w + t*sp.w);
-}
D src2/3d/image/clip.h => src2/3d/image/clip.h +0 -13
@@ 1,13 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-#include <stdbool.h>
-
-bool ClipT(double den, double num, double *tE, double *tL);
-bool ClipLine(Vector *v0, Vector *v1);
-bool ClipPoint(Vector p);
-bool ClipPolygon(Polygon **polygon);
-void ConstrainPolygon(Polygon *polygon);
-void ClipPolygonPlane(Polygon **polygon, Plane clipBoundary);
-bool VertexInside(Vertex *v, Plane clipBoundary);
-Vertex ClipIntersect(Vertex *a, Vertex *b, Plane clipBoundary);
D src2/3d/image/project.c => src2/3d/image/project.c +0 -138
@@ 1,138 0,0 @@
-#include "project.h"
-#include "../../arraylist.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <assert.h>
-#include "camera.h"
-
-static Transform *deviceTransform = NULL;
-
-void InitDeviceTransform(unsigned int width, unsigned int height)
-{
- // Move canonical volume to origin
- deviceTransform = malloc(sizeof(Transform));
- *deviceTransform = Translation(V(1, 1, 0));
-
- // Scale to viewport size
- Scale(deviceTransform, 0.5*(width-1), 0.5*(height-1), 1);
-}
-
-Projection *NewOrthoProjection(AABBox vol)
-{
- Projection *projection = malloc(sizeof(Projection));
-
- projection->ortho.type = ORTHO;
- projection->ortho.near = vol.near;
- projection->ortho.far = vol.far;
- projection->ortho.left = vol.left;
- projection->ortho.right = vol.right;
- projection->ortho.bottom = vol.bottom;
- projection->ortho.top = vol.top;
-
- return projection;
-}
-
-Projection *NewPerspectiveProjection(double fov, double aspect, double near, double far)
-/* field of view is in degrees */
-{
- Projection *projection = malloc(sizeof(Projection));
-
- projection->perspective.type = PERSPECTIVE;
- projection->perspective.near = near;
- projection->perspective.far = far;
- projection->perspective.fov = Rad(fov);
- projection->perspective.aspect = aspect;
-
- return projection;
-}
-
-Transform OrthoTransform(Projection *projection)
-{
- Transform t;
-
- assert(projection->ortho.type == ORTHO);
-
- t = Identity();
-
- // translate to canonical view volume
- Translate(&t, V(
- -(projection->ortho.right + projection->ortho.left) / 2,
- -(projection->ortho.top + projection->ortho.bottom) / 2,
- -projection->ortho.near));
-
- // scale to canonical view volume
- Scale(&t,
- 2 / (projection->ortho.right - projection->ortho.left),
- 2 / (projection->ortho.top - projection->ortho.bottom),
- 1 / (projection->ortho.near - projection->ortho.far));
-
- return t;
-}
-
-Transform PerspectiveTransform(Projection *projection)
-{
- Transform op, t;
-
- assert(projection->perspective.type == PERSPECTIVE);
-
- t = Identity();
-
- // perspective transform into canonical view volume
- op = Identity();
- op.m[0][0] = 1/(projection->perspective.aspect * tan(projection->perspective.fov/2));
- op.m[1][1] = 1/tan(projection->perspective.fov/2);
- op.m[2][2] = (projection->perspective.far + projection->perspective.near)
- / (projection->perspective.far - projection->perspective.near);
- op.m[3][3] = 0;
- op.m[2][3] = (2*projection->perspective.far*projection->perspective.near)
- / (projection->perspective.far - projection->perspective.near);
- op.m[3][2] = -1;
- AddTransform(op, &t);
-
- return t;
-}
-
-Transform CameraTransform(Camera *camera)
-{
- Transform t = Translation(NegVec(camera->position));
- AddTransform(AlignCameraToAxis(camera), &t);
- AddTransform(camera->transform, &t);
-
- return t;
-}
-
-Transform GetProjectionTransform(Camera *camera, Projection *projection)
-{
- Transform t = CameraTransform(camera);
- if (projection->ortho.type == ORTHO) {
- AddTransform(OrthoTransform(projection), &t);
- } else {
- AddTransform(PerspectiveTransform(projection), &t);
- }
- return t;
-}
-
-Vector ProjectPoint(Vertex p, Transform t)
-{
- return ApplyTransform(t, p);
-}
-
-Vertex ViewmapPoint(Vertex p)
-{
- assert(deviceTransform != NULL);
- return Homogenize(ApplyTransform(*deviceTransform, p));
-}
-
-Polygon *ProjectPolygon(Polygon *polygon, Transform t)
-{
- return FromPolygon(polygon, t);
-}
-
-void ViewmapPolygon(Polygon *polygon)
-{
- assert(deviceTransform != NULL);
- for (int i = 0; i < NumVertices(polygon); i++) {
- CommitTransform(*deviceTransform, PolygonVertex(polygon, i));
- }
-}
D src2/3d/image/project.h => src2/3d/image/project.h +0 -46
@@ 1,46 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-#include <stdbool.h>
-#include "camera.h"
-
-typedef enum ProjectionType {
- ORTHO, PERSPECTIVE
-} ProjectionType;
-
-typedef struct PerspectiveProjection {
- ProjectionType type;
- double near;
- double far;
- double fov;
- double aspect;
-} PerspectiveProjection;
-
-typedef struct OrthoProjection {
- ProjectionType type;
- double near;
- double far;
- double left;
- double right;
- double bottom;
- double top;
-} OrthoProjection;
-
-typedef union Projection {
- PerspectiveProjection perspective;
- OrthoProjection ortho;
-} Projection;
-
-void InitDeviceTransform(unsigned int width, unsigned int height);
-
-Projection *NewOrthoProjection(AABBox vol);
-Projection *NewPerspectiveProjection(double fov, double aspect, double near, double far);
-
-Transform OrthoTransform(Projection *projection);
-Transform PerspectiveTransform(Projection *projection);
-Transform GetProjectionTransform(Camera *camera, Projection *projection);
-
-Vertex ProjectPoint(Vertex p, Transform t);
-Vertex ViewmapPoint(Vertex p);
-Polygon *ProjectPolygon(Polygon *polygon, Transform t);
-void ViewmapPolygon(Polygon *polygon);
D src2/3d/render.c => src2/3d/render.c +0 -92
@@ 1,92 0,0 @@
-#include "render.h"
-#include "../arraylist.h"
-#include "image.h"
-#include "device.h"
-#include "abstract.h"
-
-RenderingContext MakeRenderingContext(Viewport *viewport, Camera *camera,
- Transform projectionTransform, RasterSettings settings)
-{
- RenderingContext context;
- context.viewport = viewport;
- context.camera = camera;
- context.projectionTransform = projectionTransform;
- context.settings = settings;
- return context;
-}
-
-void DrawObject(Object *object, LightSource **lights, RenderingContext context, Transform imageTransform)
-{
- Transform modelingTransform = ComposeTransform(Translation(object->position), object->transform);
- for (int i = 0; i < NumFacets(object->geometry); i++) {
- Polygon *modeled = FromPolygon(object->geometry->facets[i], modelingTransform);
- Color shade = LightPolygon(modeled, object->color, object->glow, lights);
- DrawPolygon(modeled, shade, context, imageTransform);
- FreePolygon(modeled);
- }
-}
-
-void DrawPolygon(Polygon *polygon, Color color, RenderingContext context, Transform imageTransform)
-{
- Polygon *image = ProjectPolygon(polygon, imageTransform);
- if (ClipPolygon(&image)) {
- if (!BackfaceCulled(image)) {
- HomogenizePolygon(image);
- ViewmapPolygon(image);
- RasterPolygon(image, color, context.viewport, context.settings);
- if (context.settings.showWireframes) {
- WireframePolygon(image, WHITE, context.viewport);
- }
- }
- }
- FreePolygon(image);
-}
-
-void WireframePolygon(Polygon *polygon, Color color, Viewport *viewport)
-{
- Vertex *a, *b;
- for (int i = 0; i < NumVertices(polygon); i++) {
- a = PolygonVertex(polygon, i);
- b = PolygonVertex(polygon, i+1);
- RasterLine(*a, *b, color, viewport);
- }
-}
-
-void DrawPoint(Point *p, RenderingContext context, Transform imageTransform)
-{
- Vector projected = ProjectPoint(p->position, imageTransform);
- if (ClipPoint(projected)) {
- Vector mapped = ViewmapPoint(Homogenize(projected));
- if (UpdateDepthBuffer(mapped.x, mapped.y, mapped.z, context.viewport)) {
- WritePixel(mapped.x, mapped.y, p->color, context.viewport);
- }
- }
-}
-
-void DrawLine(Vertex a, Vertex b, Color color, Viewport *viewport, Transform imageTransform)
-{
- Vector ap = ProjectPoint(a, imageTransform);
- Vector bp = ProjectPoint(b, imageTransform);
- Vector ac = ap;
- Vector bc = bp;
- if (ClipLine(&ac, &bc)) {
- Vertex av = ViewmapPoint(Homogenize(ac));
- Vertex bv = ViewmapPoint(Homogenize(bc));
- RasterLine(av, bv, color, viewport);
- }
-}
-
-void DrawAxes(RenderingContext context)
-{
- Transform imageTransform = ComposeTransform(context.projectionTransform, CameraTransform(context.camera));
- DrawLine(V(0, 0, 0), V(10, 0, 0), LT_GRAY, context.viewport, imageTransform);
- DrawLine(V(0, 0, 0), V(0, 10, 0), LT_GRAY, context.viewport, imageTransform);
- DrawLine(V(0, 0, 0), V(0, 0, 10), LT_GRAY, context.viewport, imageTransform);
-}
-
-bool BackfaceCulled(Polygon *polygon)
-{
- Vector normal = PolygonNormal(polygon);
- return normal.z <= 0;
-}
-
D src2/3d/render.h => src2/3d/render.h +0 -24
@@ 1,24 0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include "abstract.h"
-#include "world.h"
-#include "device.h"
-#include "image.h"
-
-typedef struct RenderingContext {
- Viewport *viewport;
- Camera *camera;
- Transform projectionTransform;
- RasterSettings settings;
-} RenderingContext;
-
-RenderingContext MakeRenderingContext(Viewport *viewport, Camera *camera, Transform projectionTransform, RasterSettings settings);
-void DrawObject(Object *object, LightSource **lights, RenderingContext context, Transform imageTransform);
-void DrawPolygon(Polygon *polygon, Color color, RenderingContext context, Transform imageTransform);
-void WireframePolygon(Polygon *polygon, Color color, Viewport *viewport);
-void DrawPoint(Point *p, RenderingContext context, Transform imageTransform);
-void DrawLine(Vertex a, Vertex b, Color color, Viewport *viewport, Transform imageTransform);
-void DrawAxes(RenderingContext context);
-bool BackfaceCulled(Polygon *polygon);
-
D src2/3d/vertex_pool.c => src2/3d/vertex_pool.c +0 -33
@@ 1,33 0,0 @@
-#include "vertex_pool.h"
-#include <stdlib.h>
-#include <assert.h>
-
-#define VPOOL_SIZE 1000000
-
-VPool vpool_init()
-{
- // number of used slots is in front of actual vertices
- int *raw_pool = (int *)malloc(sizeof(Vertex)*VPOOL_SIZE + sizeof(int));
- raw_pool[0] = 0;
- VPool pool = (VPool)(raw_pool + 1);
- return pool;
-}
-
-Vertex *vpool_new(VPool pool, double x, double y, double z, double w)
-{
- assert(vpool_count(pool) < VPOOL_SIZE);
- Vertex *v = &(pool[vpool_count(pool)]);
- v->x = x;
- v->y = y;
- v->z = z;
- v->w = w;
- int *raw_pool = raw_pool(pool);
- raw_pool[0]++;
- return v;
-}
-
-void vpool_destroy(VPool pool)
-{
- free(raw_pool(pool));
-}
-
D src2/3d/vertex_pool.h => src2/3d/vertex_pool.h +0 -12
@@ 1,12 0,0 @@
-#pragma once
-
-#include "abstract/vertex.h"
-
-typedef Vertex *VPool;
-
-VPool vpool_init();
-Vertex *vpool_new(VPool pool, double x, double y, double z, double w);
-void vpool_destroy(VPool pool);
-
-#define raw_pool(pool) (((int *)(pool)) - 1)
-#define vpool_count(pool) (raw_pool(pool)[0])
D src2/3d/world.h => src2/3d/world.h +0 -6
@@ 1,6 0,0 @@
-#pragma once
-
-#include "world/light.h"
-#include "world/mesh.h"
-#include "world/object.h"
-
D src2/3d/world/light.c => src2/3d/world/light.c +0 -72
@@ 1,72 0,0 @@
-#include "light.h"
-#include "../../arraylist.h"
-#include <stdlib.h>
-#include <math.h>
-#include <assert.h>
-
-static double ambient = 0.2;
-
-void AmbientLight(double amb)
-{
- ambient = amb;
-}
-
-LightSource *PointLight(Vector position, double intensity)
-{
- LightSource *l = malloc(sizeof(LightSource));
- l->position = position;
- l->intensity = intensity;
- l->type = POINT_LIGHT;
- return l;
-}
-
-SpotLightSource *SpotLight(Vector position, Vector direction, double spread, double intensity)
-{
- SpotLightSource *l = malloc(sizeof(SpotLightSource));
- l->light.position = position;
- l->light.intensity = intensity;
- l->light.type = SPOT_LIGHT;
- l->direction = direction;
- l->spread = spread;
- return l;
-}
-
-double LightPolygon(Polygon *polygon, Color color, double glow, LightSource **lights)
-{
- return fmin(glow + color * fmin((ambient + DiffuseLight(polygon, lights)), 1), 1);
-}
-
-double DiffuseLight(Polygon *polygon, LightSource **lights)
-{
- double lightAmt = 0;
- Vector n = PolygonNormal(polygon);
- for (int i = 0; i < list_count(lights); i++) {
- Vector v = PolygonCenter(polygon);
- Vector l = VecSub(lights[i]->position, v);
- Vector nl = NormalizeVector(l);
- double dist = VecLen(l);
- double attenuation = fmin(1/(0.9+0.1*dist+0.001*dist*dist), 1);
- double incidence = DotProd(n, nl);
-
- if (IsLit(lights[i], incidence, nl)) {
- lightAmt += attenuation*incidence*lights[i]->intensity;
- }
- }
- return lightAmt;
-}
-
-bool IsLit(LightSource *light, double incidence, Vector l)
-{
- if (incidence < 0) {
- return false;
- }
-
- if (light->type == SPOT_LIGHT) {
- SpotLightSource *spotlight = (SpotLightSource *)light;
- if (DotProd(spotlight->direction, NegVec(l)) < 1 - spotlight->spread) {
- return false;
- }
- }
-
- return true;
-}
D src2/3d/world/light.h => src2/3d/world/light.h +0 -27
@@ 1,27 0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include "../abstract.h"
-
-typedef enum LightType {
- POINT_LIGHT, SPOT_LIGHT
-} LightType;
-
-typedef struct LightSource {
- LightType type;
- Vertex position;
- double intensity;
-} LightSource;
-
-typedef struct SpotLightSource {
- LightSource light;
- Vector direction;
- double spread;
-} SpotLightSource;
-
-void AmbientLight(double amb);
-LightSource *PointLight(Vector position, double intensity);
-SpotLightSource *SpotLight(Vector position, Vector direction, double spread, double intensity);
-double LightPolygon(Polygon *polygon, Color color, double glow, LightSource **lights);
-double DiffuseLight(Polygon *polygon, LightSource **lights);
-bool IsLit(LightSource *light, double incidence, Vector l);
D src2/3d/world/mesh.c => src2/3d/world/mesh.c +0 -158
@@ 1,158 0,0 @@
-#include "mesh.h"
-#include "../../arraylist.h"
-#include <stdio.h>
-#include <string.h>
-
-Mesh *NewMesh(void)
-{
- Mesh *obj = malloc(sizeof(Mesh));
- obj->vertices = NULL;
- obj->facets = NULL;
- return obj;
-}
-
-void AddFacet(Mesh *mesh, Polygon *polygon)
-{
- int i;
- vIndex vi;
- Vertex *vert;
-
- /* replace facet's vList with indices into mesh's vertices;
- also make sure mesh has the same verts */
- for (i = 0; i < NumVertices(polygon); i++) {
- vert = PolygonVertex(polygon, i);
-
- vi = FindVertex(mesh->vertices, vert);
- if (vi == VERTEX_NOT_FOUND) {
- vi = list_count(mesh->vertices);
- /* this could change the vertices pointer, which won't automatically
- * be reflected in each of the mesh's facets */
- list_push(mesh->vertices, polygon->vertices[i]);
- }
- polygon->vList[i] = vi;
- }
-
- /* replace facet's vertex list with mesh's */
- list_free(polygon->vertices);
- polygon->vertices = mesh->vertices;
-
- /* also ensure facets have correct ref to vertices, since the list_push
- * may have changed the pointer */
- for (i = 0; i < list_count(mesh->facets); i++) {
- mesh->facets[i]->vertices = mesh->vertices;
- }
-
- list_push(mesh->facets, polygon);
-}
-
-int NumFacets(Mesh *mesh)
-{
- return list_count(mesh->facets);
-}
-
-Mesh *TransformMesh(Mesh *obj, Transform t)
-{
- for (int i = 0; i < list_count(obj->vertices); i++) {
- CommitTransform(t, obj->vertices[i]);
- }
-
- return obj;
-}
-
-Mesh *LoadMesh(const char *filename)
-{
- FILE *fp;
- Mesh *m = NewMesh();
- bool fileOk = true;
- int line = 0;
-
- fp = fopen(filename, "r");
- while (!feof(fp) && fileOk) {
- line++;
- fileOk = ReadObjLine(fp, m);
- }
- fclose(fp);
-
- if (!fileOk) {
- printf("Error reading \"%s\" on line %d\n", filename, line+1);
- return NULL;
- }
-
- return m;
-}
-
-bool ReadObjLine(FILE *fp, Mesh *mesh)
-{
- char itemType[8];
- if (fscanf(fp, "%8s", itemType) == 1) {
- switch (ParseLineType(itemType)) {
- case OBJ_VERTEX: return ReadObjVertex(fp, mesh);
- case OBJ_FACE: return ReadObjFace(fp, mesh);
- case OBJ_EMPTY: return true;
- case OBJ_COMMENT:
- fscanf(fp, "%*[^\n]\n"); // skip the rest of the line
- return true;
- case OBJ_UNKNOWN:
- printf("Unknown \"%s\"\n", itemType);
- return false;
- default:
- fscanf(fp, "%*[^\n]\n"); // skip the rest of the line
- return true;
- }
- }
- // no match, probably EOF
- return true;
-}
-
-bool ReadObjVertex(FILE *fp, Mesh *mesh)
-{
- float x, y, z, w;
- bool match;
-
- match = fscanf(fp, "%f", &x);
- if (!match) return false;
- match = fscanf(fp, "%f", &y);
- if (!match) return false;
- match = fscanf(fp, "%f", &z);
- if (!match) return false;
- match = fscanf(fp, "%f", &w);
- if (!match) w = 1.0;
-
- Vertex *v = NewVector4D(x, y, z, w);
- list_push(mesh->vertices, v);
- return true;
-}
-
-bool ReadObjFace(FILE *fp, Mesh *mesh)
-{
- int vIndex;
- Polygon *p = NewPolygon();
- p->vertices = mesh->vertices;
-
- while (fscanf(fp, "%d", &vIndex) == 1) {
- list_push(p->vList, vIndex-1);
- fscanf(fp, "/%*d"); // skip vt
- fscanf(fp, "/%*d"); // skip vn
- }
-
- list_push(mesh->facets, p);
- return true;
-}
-
-ObjLineType ParseLineType(const char *type)
-{
- if (0 == strcmp(type, "v")) return OBJ_VERTEX;
- if (0 == strcmp(type, "f")) return OBJ_FACE;
- if (0 == strcmp(type, "vn")) return OBJ_VNORMAL;
- if (0 == strcmp(type, "vt")) return OBJ_VTEXTURE;
- if (0 == strcmp(type, "vp")) return OBJ_VPARAM;
- if (0 == strcmp(type, "g")) return OBJ_GROUP;
- if (0 == strcmp(type, "o")) return OBJ_OBJECT;
- if (0 == strcmp(type, "s")) return OBJ_SMOOTH;
- if (0 == strcmp(type, "mtllib")) return OBJ_MTLLIB;
- if (0 == strcmp(type, "usemtl")) return OBJ_USEMTL;
- if (0 == strcmp(type, "#")) return OBJ_COMMENT;
- if (0 == strcmp(type, " ")) return OBJ_EMPTY;
- if (0 == strcmp(type, "\n")) return OBJ_EMPTY;
- return OBJ_UNKNOWN;
-}
D src2/3d/world/mesh.h => src2/3d/world/mesh.h +0 -35
@@ 1,35 0,0 @@
-#pragma once
-
-#include "../abstract.h"
-#include <stdio.h>
-
-typedef struct Mesh {
- Vertex **vertices; // list of vertices in all of the mesh's facets
- Polygon **facets;
-} Mesh;
-
-typedef enum ObjLineType {
- OBJ_VERTEX,
- OBJ_FACE,
- OBJ_VNORMAL,
- OBJ_VTEXTURE,
- OBJ_VPARAM,
- OBJ_GROUP,
- OBJ_OBJECT,
- OBJ_SMOOTH,
- OBJ_MTLLIB,
- OBJ_USEMTL,
- OBJ_COMMENT,
- OBJ_EMPTY,
- OBJ_UNKNOWN
-} ObjLineType;
-
-Mesh *NewMesh(void);
-void AddFacet(Mesh *object, Polygon *facet);
-int NumFacets(Mesh *mesh);
-Mesh *TransformMesh(Mesh *obj, Transform t);
-Mesh *LoadMesh(const char *filename);
-bool ReadObjLine(FILE *fp, Mesh *mesh);
-bool ReadObjVertex(FILE *fp, Mesh *mesh);
-bool ReadObjFace(FILE *fp, Mesh *mesh);
-ObjLineType ParseLineType(const char *type);
D src2/3d/world/object.c => src2/3d/world/object.c +0 -53
@@ 1,53 0,0 @@
-#include "object.h"
-#include <stdlib.h>
-
-Object *NewCube(Color color)
-{
- Mesh *geometry = LoadMesh("assets/cube.obj");
- return NewObject(geometry, color);
-}
-
-Object *NewGround(void)
-{
- Mesh *geom = NewMesh();
- Polygon *ground = NewPolygon();
- AddVertex(ground, NewVector(1000, -1, 1000));
- AddVertex(ground, NewVector(1000, -1, -1000));
- AddVertex(ground, NewVector(-1000, -1, -1000));
- AddVertex(ground, NewVector(-1000, -1, 1000));
- AddFacet(geom, ground);
- return NewObject(geom, GRAY);
-}
-
-Object *NewObject(Mesh *geom, Color color)
-{
- Object *o = malloc(sizeof(Object));
- o->geometry = geom;
- o->transform = Identity();
- o->position = V(0, 0, 0);
- o->color = color;
- o->glow = 0;
- return o;
-}
-
-void RotateObj(Object *obj, double rx, double ry, double rz)
-{
- RotateX(&obj->transform, rx);
- RotateY(&obj->transform, ry);
- RotateZ(&obj->transform, rz);
-}
-
-void ScaleObj(Object *obj, double sx, double sy, double sz)
-{
- Scale(&obj->transform, sx, sy, sz);
-}
-
-void TranslateObj(Object *obj, Vector dv)
-{
- Translate(&obj->transform, dv);
-}
-
-void PlaceObj(Object *obj, Vector p)
-{
- obj->position = p;
-}
D src2/3d/world/object.h => src2/3d/world/object.h +0 -20
@@ 1,20 0,0 @@
-#pragma once
-
-#include "mesh.h"
-#include "../abstract.h"
-
-typedef struct Object {
- Mesh *geometry;
- Transform transform;
- Vector position;
- double color;
- double glow;
-} Object;
-
-Object *NewObject(Mesh *geom, Color color);
-Object *NewCube(Color color);
-Object *NewGround(void);
-void RotateObj(Object *obj, double rx, double ry, double rz);
-void ScaleObj(Object *obj, double sx, double sy, double sz);
-void TranslateObj(Object *obj, Vector dv);
-void PlaceObj(Object *obj, Vector p);
D src2/arraylist.h => src2/arraylist.h +0 -35
@@ 1,35 0,0 @@
-#pragma once
-
-#define list_free(a) ((a) ? free(list__sbraw(a)),0 : 0)
-#define list_push(a,v) (list__sbmaybegrow(a,1), (a)[list__sbn(a)++] = (v))
-#define list_count(a) ((a) ? list__sbn(a) : 0)
-#define list_last(a) ((a)[list__sbn(a)-1])
-
-#define list__sbraw(a) ((int *) (void *) (a) - 2)
-#define list__sbm(a) list__sbraw(a)[0]
-#define list__sbn(a) list__sbraw(a)[1]
-
-#define list__sbneedgrow(a,n) ((a)==0 || list__sbn(a)+(n) >= list__sbm(a))
-#define list__sbmaybegrow(a,n) (list__sbneedgrow(a,(n)) ? list__sbgrow(a,n) : 0)
-#define list__sbgrow(a,n) (*((void **)&(a)) = list__sbgrowf((a), (n), sizeof(*(a))))
-
-#include <stdlib.h>
-
-static void *list__sbgrowf(void *arr, int increment, int itemsize)
-{
- int dbl_cur = arr ? 2*list__sbm(arr) : 0;
- int min_needed = list_count(arr) + increment;
- int m = dbl_cur > min_needed ? dbl_cur : min_needed;
- int *p = (int *) realloc(arr ? list__sbraw(arr) : 0, itemsize * m + sizeof(int)*2);
- if (p) {
- if (!arr)
- p[1] = 0;
- p[0] = m;
- return p+2;
- } else {
- #ifdef STRETCHY_BUFFER_OUT_OF_MEMORY
- STRETCHY_BUFFER_OUT_OF_MEMORY ;
- #endif
- return (void *) (2*sizeof(int)); // try to force a NULL pointer exception later
- }
-}
D src2/input.c => src2/input.c +0 -16
@@ 1,16 0,0 @@
-#include "input.h"
-
-InputState KeyPressed(InputState input, KeySym key)
-{
- return (input & key) == key;
-}
-
-InputState KeyDown(InputState input, KeySym key)
-{
- return input | key;
-}
-
-InputState KeyUp(InputState input, KeySym key)
-{
- return input & ~key;
-}
D src2/input.h => src2/input.h +0 -16
@@ 1,16 0,0 @@
-#pragma once
-
-#define NO_INPUT 0b00000000
-#define KEY_LEFT 0b00000001
-#define KEY_RIGHT 0b00000010
-#define KEY_FWD 0b00000100
-#define KEY_BACK 0b00001000
-#define KEY_JUMP 0b00010000
-
-typedef char KeySym;
-typedef char InputState;
-
-InputState KeyPressed(InputState input, KeySym key);
-InputState KeyDown(InputState input, KeySym key);
-InputState KeyUp(InputState input, KeySym key);
-
D src2/main.c => src2/main.c +0 -111
@@ 1,111 0,0 @@
-#include <SDL2/SDL.h>
-#include <stdio.h>
-
-#include "input.h"
-#include "sketch.h"
-
-unsigned int SCREEN_WIDTH = 400;
-unsigned int SCREEN_HEIGHT = 240;
-uint32_t *pixels;
-
-#define TICK_INTERVAL 30
-static Uint32 next_time;
-uint32_t time_left(void)
-{
- uint32_t now;
-
- now = SDL_GetTicks();
- if(next_time <= now)
- return 0;
- else
- return next_time - now;
-}
-
-InputState MapSDLInput(SDL_Keycode keyCode)
-{
- switch (keyCode) {
- case SDLK_LEFT: return KEY_LEFT;
- case SDLK_RIGHT: return KEY_RIGHT;
- case SDLK_UP: return KEY_FWD;
- case SDLK_DOWN: return KEY_BACK;
- case SDLK_SPACE: return KEY_JUMP;
- default: return NO_INPUT;
- }
-}
-
-#ifndef TEST
-int main(void)
-{
- if (SDL_Init(SDL_INIT_VIDEO) == 0) {
- SDL_Window* window = NULL;
- SDL_Renderer* renderer = NULL;
- SDL_Texture *texture = NULL;
-
- if (SDL_CreateWindowAndRenderer(SCREEN_WIDTH, SCREEN_HEIGHT, 0, &window, &renderer) == 0) {
- texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
- pixels = malloc(sizeof(uint32_t)*SCREEN_WIDTH*SCREEN_HEIGHT);
- SDL_bool done = SDL_FALSE;
- SDL_Event event;
-
- sketch_setup(pixels);
- sketch_draw(SDL_GetTicks());
-
- SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH*sizeof(uint32_t));
- SDL_RenderCopy(renderer, texture, NULL, NULL);
- SDL_RenderPresent(renderer);
-
- next_time = SDL_GetTicks() + TICK_INTERVAL;
-
- long frames = 0;
- long start = SDL_GetTicks();
- InputState input = NO_INPUT;
- while (!done) {
-
- if (time_left() == 0) {
- next_time += TICK_INTERVAL;
- frames++;
- sketch_draw(SDL_GetTicks());
- SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH*sizeof(uint32_t));
- SDL_RenderCopy(renderer, texture, NULL, NULL);
- SDL_RenderPresent(renderer);
-
- // close after 1 min
- // if (SDL_GetTicks() > 1000*60) {
- // done = SDL_TRUE;
- // }
-
- while (SDL_PollEvent(&event)) {
- if (event.type == SDL_QUIT) {
- done = SDL_TRUE;
- } else if (event.type == SDL_KEYDOWN) {
- input = KeyDown(input, MapSDLInput(event.key.keysym.sym));
-
- // sketch_draw(SDL_GetTicks());
- // SDL_UpdateTexture(texture, NULL, pixels, SCREEN_WIDTH*sizeof(uint32_t));
- // SDL_RenderCopy(renderer, texture, NULL, NULL);
- // SDL_RenderPresent(renderer);
- } else if (event.type == SDL_KEYUP) {
- input = KeyUp(input, MapSDLInput(event.key.keysym.sym));
- }
- }
-
- sketch_input(input);
- }
- }
- long time = (SDL_GetTicks() - start)/1000;
- double fps = (double)frames/(double)time;
- printf("%f fps\n", fps);
- }
-
- if (renderer) {
- SDL_DestroyRenderer(renderer);
- }
- if (window) {
- SDL_DestroyWindow(window);
- }
- }
- SDL_Quit();
- return 0;
-}
-
-#endif
D src2/player.c => src2/player.c +0 -42
@@ 1,42 0,0 @@
-#include "player.h"
-#include <stdlib.h>
-
-Player *NewPlayer(Vertex position)
-{
- Player *player = malloc(sizeof(Player));
-
- player->camera = NewCamera(position);
- LookAt(V(0, position.y, 0), player->camera);
-
- return player;
-}
-
-void PlayerTurnLeft(Player *player, double angle)
-{
- RotateCamera(0, angle, 0, player->camera);
-}
-
-void PlayerTurnRight(Player *player, double angle)
-{
- RotateCamera(0, -angle, 0, player->camera);
-}
-
-void PlayerMoveForward(Player *player, double amount)
-{
- MoveCamera(VecMul(player->camera->direction, amount), player->camera);
-}
-
-void PlayerMoveBackward(Player *player, double amount)
-{
- MoveCamera(VecMul(player->camera->direction, -amount), player->camera);
-}
-
-Vector PlayerDirection(Player *player)
-{
- return player->camera->direction;
-}
-
-Vertex PlayerPosition(Player *player)
-{
- return player->camera->position;
-}
D src2/player.h => src2/player.h +0 -15
@@ 1,15 0,0 @@
-#pragma once
-
-#include "3d.h"
-
-typedef struct Player {
- Camera *camera;
-} Player;
-
-Player *NewPlayer(Vertex position);
-void PlayerTurnLeft(Player *player, double angle);
-void PlayerTurnRight(Player *player, double angle);
-void PlayerMoveForward(Player *player, double amount);
-void PlayerMoveBackward(Player *player, double amount);
-Vector PlayerDirection(Player *player);
-Vertex PlayerPosition(Player *player);
D src2/scene.c => src2/scene.c +0 -39
@@ 1,39 0,0 @@
-#include "scene.h"
-#include "arraylist.h"
-
-Scene *NewScene(void)
-{
- Scene *s = malloc(sizeof(Scene));
- s->objects = NULL;
- s->lights = NULL;
- s->points = NULL;
- return s;
-}
-
-void AddObject(Scene *scene, Object *obj)
-{
- list_push(scene->objects, obj);
-}
-
-void AddLight(Scene *scene, LightSource *light)
-{
- list_push(scene->lights, light);
-}
-
-void AddPoint(Scene *scene, Point *point)
-{
- list_push(scene->points, point);
-}
-
-void RenderScene(Scene *scene)
-{
- Transform imageTransform = ComposeTransform(scene->context.projectionTransform, CameraTransform(scene->context.camera));
-
- for (int i = 0; i < list_count(scene->objects); i++) {
- DrawObject(scene->objects[i], scene->lights, scene->context, imageTransform);
- }
-
- for (int i = 0; i < list_count(scene->points); i++) {
- DrawPoint(scene->points[i], scene->context, imageTransform);
- }
-}
D src2/scene.h => src2/scene.h +0 -22
@@ 1,22 0,0 @@
-#pragma once
-
-#include "3d.h"
-#include "player.h"
-#include "input.h"
-
-typedef void (*SceneUpdate)(struct Scene *scene, int dt);
-
-typedef struct Scene {
- Object **objects;
- Point **points;
- LightSource **lights;
- Player *player;
- RenderingContext context;
- SceneUpdate onUpdate;
-} Scene;
-
-Scene *NewScene(void);
-void AddObject(Scene *scene, Object *obj);
-void AddLight(Scene *scene, LightSource *light);
-void AddPoint(Scene *scene, Point *point);
-void RenderScene(Scene *scene);
D src2/scenes/cubeworld.c => src2/scenes/cubeworld.c +0 -61
@@ 1,61 0,0 @@
-#include "cubeworld.h"
-
-#include "../player.h"
-#include <stdlib.h>
-#include <math.h>
-
-static Object *masterCube;
-
-Scene *CubeWorld(void)
-{
- Scene *scene = NewScene();
- scene->onUpdate = &UpdateCubeWorld;
-
- AmbientLight(0.1);
- LightSource *cubeLight = PointLight(V(0, 2, 0), 1);
- AddLight(scene, cubeLight);
-
- AddObject(scene, NewGround());
-
- for (int i = 0; i < 500; i++) {
- Object *cube = NewCube(WHITE);
- RotateObj(cube, 0, rand() % 360, 0);
- int azimuth = rand() % 360;
- int dist = rand() % 100+10;
- double x = dist*cos(Rad(azimuth));
- double z = dist*sin(Rad(azimuth));
- PlaceObj(cube, V(x, 0, z));
- AddObject(scene, cube);
- }
-
- for (int i = 0; i < 500; i++) {
- int azimuth = rand() % 360;
- int altitude = rand() % 90;
- int dist = 1000;
- double x = dist*cos(Rad(azimuth));
- double z = dist*sin(Rad(azimuth));
- double y = dist*sin(Rad(altitude));
- Point *p = NewPoint(V(x, y, z), WHITE);
- AddPoint(scene, p);
- }
-
- masterCube = NewCube(DK_GRAY);
- masterCube->glow = 1;
- PlaceObj(masterCube, V(0, 2, 0));
- AddObject(scene, masterCube);
-
- Object *ob = NewObject(LoadMesh("assets/obelisk.obj"), WHITE);
- TranslateObj(ob, V(100, -1, 0));
- RotateObj(ob, 0, rand() % 360, 0);
- AddObject(scene, ob);
-
- scene->player = NewPlayer(V(0, 0, -100));
-
- return scene;
-}
-
-void UpdateCubeWorld(Scene *scene, int dt)
-{
- RotateObj(masterCube, 0, 0.01*dt, 0);
- RotateObj(masterCube, 0.01*dt, 0, 0);
-}
D src2/scenes/cubeworld.h => src2/scenes/cubeworld.h +0 -7
@@ 1,7 0,0 @@
-#pragma once
-
-#include "../3d.h"
-#include "../scene.h"
-
-Scene *CubeWorld(void);
-void UpdateCubeWorld(Scene *scene, int dt);
D src2/scenes/moonworld.c => src2/scenes/moonworld.c +0 -65
@@ 1,65 0,0 @@
-#include "moonworld.h"
-
-#include "../player.h"
-#include <stdlib.h>
-#include <math.h>
-
-// static Object *masterCube;
-
-Scene *MoonWorld(void)
-{
- Scene *scene = NewScene();
- scene->onUpdate = &UpdateMoonWorld;
-
- AmbientLight(0.1);
- LightSource *cubeLight = PointLight(V(0, 2, 0), 1);
- AddLight(scene, cubeLight);
-
- // AddObject(scene, NewGround());
- Object *moon = NewObject(LoadMesh("assets/moon.obj"), WHITE);
- ScaleObj(moon, 10, 10, 10);
- AddObject(scene, moon);
-
- // for (int i = 0; i < 500; i++) {
- // Object *cube = NewCube(WHITE);
- // RotateObj(cube, 0, rand() % 360, 0);
- // int azimuth = rand() % 360;
- // int dist = rand() % 100+10;
- // double x = dist*cos(Rad(azimuth));
- // double z = dist*sin(Rad(azimuth));
- // PlaceObj(cube, V(x, 0, z));
- // AddObject(scene, cube);
- // }
-
- for (int i = 0; i < 500; i++) {
- int azimuth = rand() % 360;
- int altitude = rand() % 90;
- int dist = 1000;
- double x = dist*cos(Rad(azimuth));
- double z = dist*sin(Rad(azimuth));
- double y = dist*sin(Rad(altitude));
- Point *p = NewPoint(V(x, y, z), WHITE);
- AddPoint(scene, p);
- }
-
- // masterCube = NewCube(DK_GRAY);
- // masterCube->glow = 1;
- // PlaceObj(masterCube, V(0, 2, 0));
- // AddObject(scene, masterCube);
-
- // Object *ob = NewObject(LoadMesh("assets/obelisk.obj"), WHITE);
- // TranslateObj(ob, V(100, -1, 0));
- // RotateObj(ob, 0, rand() % 360, 0);
- // AddObject(scene, ob);
-
- scene->player = NewPlayer(V(0, 10, -1));
-
- return scene;
-}
-
-void UpdateMoonWorld(Scene *scene, int dt)
-{
- StandOn(scene->camera)
- // RotateObj(masterCube, 0, 0.01*dt, 0);
- // RotateObj(masterCube, 0.01*dt, 0, 0);
-}
D src2/scenes/moonworld.h => src2/scenes/moonworld.h +0 -7
@@ 1,7 0,0 @@
-#pragma once
-
-#include "../3d.h"
-#include "../scene.h"
-
-Scene *MoonWorld(void);
-void UpdateMoonWorld(Scene *scene, int dt);
D src2/sketch.c => src2/sketch.c +0 -68
@@ 1,68 0,0 @@
-#include "sketch.h"
-#include "arraylist.h"
-#include "scenes/moonworld.h"
-#include "scenes/cubeworld.h"
-#include "player.h"
-#include <assert.h>
-
-int debounce = 0;
-bool dither = false;
-Scene *scene;
-static SpotLightSource *flashlight;
-int now, lastTime;
-RenderingContext context;
-
-void sketch_setup(Pixel *pixels)
-{
- Viewport *viewport = NewViewport(pixels, BLACK, 400, 240);
- RasterSettings settings = DefaultRasterSettings();
- settings.showWireframes = true;
- scene = MoonWorld();
- Camera *camera = scene->player->camera;
- Projection *projection = NewPerspectiveProjection(60, 400/240.f, 1, 100);
- context = MakeRenderingContext(viewport, camera, PerspectiveTransform(projection), settings);
-
- flashlight = SpotLight(camera->position, camera->direction, 0.1, 0);
- AddLight(scene, (LightSource *)flashlight);
-}
-
-void sketch_draw(long ticks)
-{
- int dt = ticks - lastTime;
- lastTime = ticks;
- ClearViewport(context.viewport);
-
- (*(scene->onUpdate))(scene, dt);
- RenderScene(scene, context);
-
- if (dither) {
- Dither(context.viewport);
- }
-}
-
-void sketch_input(InputState input)
-{
- if (KeyPressed(input, KEY_LEFT)) {
- PlayerTurnLeft(scene->player, 5);
- flashlight->direction = PlayerDirection(scene->player);
- }
- if (KeyPressed(input, KEY_RIGHT)) {
- PlayerTurnRight(scene->player, 5);
- flashlight->direction = PlayerDirection(scene->player);
- }
- if (KeyPressed(input, KEY_FWD)) {
- PlayerMoveForward(scene->player, 0.5);
- ((LightSource *)flashlight)->position = PlayerPosition(scene->player);
- }
- if (KeyPressed(input, KEY_BACK)) {
- PlayerMoveBackward(scene->player, 0.5);
- ((LightSource *)flashlight)->position = PlayerPosition(scene->player);
- }
- if (debounce == 0 && KeyPressed(input, KEY_JUMP)) {
- debounce = 10;
- // dither = !dither;
- ((LightSource *)flashlight)->intensity = (((LightSource *)flashlight)->intensity) ? 0 : 0.5;
- }
-
- if (debounce > 0) debounce--;
-}
D src2/sketch.h => src2/sketch.h +0 -8
@@ 1,8 0,0 @@
-#pragma once
-
-#include "input.h"
-#include "3d.h"
-
-void sketch_setup(Pixel *pixels);
-void sketch_draw(long ticks);
-void sketch_input(InputState input);
D test2/assertions.h => test2/assertions.h +0 -27
@@ 1,27 0,0 @@
-#pragma once
-
-#include <stdbool.h>
-
-extern bool gTestPassed;
-
-void __AssertEqual(const char *a, const char *b, double aVal, double bVal,
- const char *func, const char *file, int line);
-#define AssertEqual(A, B) (void)(gTestPassed && (((A) == (B)) || (__AssertEqual(#A, #B, (double)A, (double)B, __func__, __FILE__, __LINE__),0)))
-
-void __AssertPixel(const char *x, const char *y, const char *c,
- int xVal, int yVal,
- const char *func, const char *file, int line);
-#define AssertPixel(X, Y, C, V) (void)(gTestPassed && (((GetPixel(X, Y, V)) == (C)) || (__AssertPixel(#X, #Y, #C, X, Y, __func__, __FILE__, __LINE__),0)))
-
-void __AssertTrue(const char *ex,
- const char *func, const char *file, int line);
-#define AssertTrue(A) (void)(gTestPassed && (((A)) || (__AssertTrue(#A, __func__, __FILE__, __LINE__),0)))
-
-void __AssertFalse(const char *ex,
- const char *func, const char *file, int line);
-#define AssertFalse(A) (void)(gTestPassed && ((!(A)) || (__AssertFalse(#A, __func__, __FILE__, __LINE__),0)))
-
-void __AssertWithin(const char *ex, const char *min, const char *max,
- double exVal, double minVal, double maxVal,
- const char *func, const char *file, int line);
-#define AssertWithin(EX, MIN, MAX) (void)(gTestPassed && (((EX) >= (MIN) && (EX) <= (MAX)) || (__AssertWithin(#EX, #MIN, #MAX, EX, MIN, MAX, __func__, __FILE__, __LINE__),0)))
D test2/assertions.test.c => test2/assertions.test.c +0 -48
@@ 1,48 0,0 @@
-#include "assertions.h"
-#include <stdio.h>
-
-extern bool gTestPassed;
-
-void __AssertEqual(const char *a, const char *b, double aVal, double bVal,
- const char *func, const char *file, int line)
-{
- gTestPassed = false;
- printf("*** In %s (%s:%d):\n", func, file, line);
- printf(" AssertEqual(%s, %s)\n", a, b);
- printf(" Expected %.2f to equal %.2f.\n\n", aVal, bVal);
-}
-
-void __AssertPixel(const char *x, const char *y, const char *c,
- int xVal, int yVal,
- const char *func, const char *file, int line)
-{
- gTestPassed = false;
- printf("*** In %s (%s:%d):\n", func, file, line);
- printf(" AssertPixel(%s, %s, %s)\n", x, y, c);
- printf(" Expected pixel at (%d, %d) to be %s.\n\n", xVal, yVal, c);
-}
-
-void __AssertTrue(const char *ex, const char *func, const char *file, int line)
-{
- gTestPassed = false;
- printf("*** In %s (%s:%d):\n", func, file, line);
- printf(" Expected %s to be true.\n\n", ex);
-}
-
-void __AssertFalse(const char *ex, const char *func, const char *file, int line)
-{
- gTestPassed = false;
- printf("*** In %s (%s:%d):\n", func, file, line);
- printf(" Expected %s to be false.\n\n", ex);
-}
-
-void __AssertWithin(
- const char *ex, const char *min, const char *max,
- double exVal, double minVal, double maxVal,
- const char *func, const char *file, int line)
-{
- gTestPassed = false;
- printf("*** In %s (%s:%d):\n", func, file, line);
- printf(" AssertWithin(%s, %s, %s)\n", ex, min, max);
- printf(" Expected %.2f to be within %.2f and %.2f.\n\n", exVal, minVal, maxVal);
-}>
\ No newline at end of file
D test2/clip.test.c => test2/clip.test.c +0 -193
@@ 1,193 0,0 @@
-#include "tests.h"
-
-void ClippingTests(void)
-{
- DoTest(&TestClipLine);
- DoTest(&TestVertexInside);
- DoTest(&TestClipIntersect);
- DoTest(&TestClipPolygonPlane);
- DoTest(&TestClipPolygon);
-}
-
-void TestClipLine(void)
-{
- bool visible;
- Vector a;
- Vector b;
-
- a = V4D( 0.18, 0.00, -0.97, 1);
- b = V4D( 0.18, 5.55, -0.97, 1);
- visible = ClipLine(&a, &b);
- AssertTrue(visible);
- AssertWithin(a.x, -1, 1);
- AssertWithin(a.y, -1, 1);
- AssertWithin(a.z, -1, 1);
- AssertWithin(b.x, -1, 1);
- AssertWithin(b.y, -1, 1);
- AssertWithin(b.z, -1, 1);
-
- a = V4D( 3.02, 0.00, -0.45, 1);
- b = V4D( 3.02, 95.18, -0.45, 1);
- visible = ClipLine(&a, &b);
- AssertFalse(visible);
-
- a = V4D( 0.00, 0.00, -0.99, 1);
- b = V4D( 0.00, -1.43, -0.97, 1);
- visible = ClipLine(&a, &b);
- AssertTrue(visible);
- AssertWithin(a.x, -1, 1);
- AssertWithin(a.y, -1, 1);
- AssertWithin(a.z, -1, 1);
- AssertWithin(b.x, -1, 1);
- AssertWithin(b.y, -1, 1);
- AssertWithin(b.z, -1, 1);
-
- a = V4D(10.929176, 0.000000, 0.569507, 0.431063);
- b = V4D(11.047228, 0.000000, 1.568198, -0.566630);
- visible = ClipLine(&a, &b);
- AssertFalse(visible);
-
- a = V4D( 0.00, -3.46, -5.01, 6);
- b = V4D( 0.00, -3.46, 996, -994);
- visible = ClipLine(&a, &b);
- AssertTrue(visible);
- AssertWithin(a.x, -a.w, a.w);
- AssertWithin(a.y, -a.w, a.w);
- AssertWithin(a.z, -a.w, a.w);
- AssertWithin(b.x, -b.w, b.w);
- AssertWithin(b.y, -b.w, b.w);
- AssertWithin(b.z, -b.w, b.w);
-}
-
-void TestVertexInside(void)
-{
- Vertex p = V4D(1, 0, 0, 2);
- Vertex q = V4D(2.5, 0, 0, 2);
- Vertex r = V4D(-2, 0, 0, -1);
- Vertex s = V4D(0, 0, 0, -2);
- Plane x_pos = Pl(V4D(0, 0, 0, 0), V4D(1, 0, 0, -1));
- Plane x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
- AssertTrue(VertexInside(&p, x_pos));
- AssertTrue(VertexInside(&p, x_neg));
- AssertFalse(VertexInside(&q, x_pos));
- AssertTrue(VertexInside(&q, x_neg));
- AssertTrue(VertexInside(&r, x_pos));
- AssertFalse(VertexInside(&r, x_neg));
- AssertFalse(VertexInside(&s, x_pos));
- AssertFalse(VertexInside(&s, x_neg));
-}
-
-void TestClipIntersect(void)
-{
- Vertex s = V4D(4, 0, 0, 2);
- Vertex p = V4D(1, 0, 0, 2);
- Plane x_pos = Pl(V4D(0, 0, 0, 0), V4D(1, 0, 0, -1));
- Vertex i = ClipIntersect(&s, &p, x_pos);
- AssertTrue(VectorEqual(i, V4D(2, 0, 0, 2)));
-
- s = V(-1.3, 0, 0);
- p = V( 0.1, 0, 0);
- Plane x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
- i = ClipIntersect(&s, &p, x_neg);
- AssertTrue(VectorEqual(i, V4D(-1, 0, 0, 1)));
-
- s = V4D(+8.9960098267e-02, +1.7320507765e+00, +2.6407814026e-01, +1.7344551086e+00);
- p = V4D(-3.2262287140e+00, +1.7320507765e+00, +8.4350967407e-01, +1.1561794281e+00);
- i = ClipIntersect(&s, &p, x_neg);
- Vertex v = Homogenize(i);
- AssertTrue(v.x >= -1);
-}
-
-void TestClipPolygonPlane(void)
-{
- Plane x_neg = Pl(V4D(0, 0, 0, 0), V4D(-1, 0, 0, -1));
- Plane x_pos = Pl(V4D(0, 0, 0, 0), V4D(1, 0, 0, -1));
- Polygon *p = NewPolygon();
- AddVertex(p, NewVector4D(1.2247448713915885, 1.7320508075688776, 0.77071482817625591, 1.2247448713915903));
- AddVertex(p, NewVector4D(4.5708100863428234, 1.7320508075688776, 0.24261940281555505, 1.7423829615966344));
- AddVertex(p, NewVector4D(4.5708100863428234, -1.7320508075688776, 0.24261940281555505, 1.7423829615966344));
- AddVertex(p, NewVector4D(1.2247448713915885, -1.7320508075688776, 0.77071482817625591, 1.2247448713915903));
- ClipPolygonPlane(&p, x_neg);
- ClipPolygonPlane(&p, x_pos);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex *v = PolygonVertex(p, i);
- AssertTrue(v->x <= v->w);
- AssertTrue(v->x >= -v->w);
- }
-}
-
-void TestClipPolygon(void)
-/* Clips polygons to be within -1 <= x, y <= 1; -1 <= z <= 1 */
-{
- Polygon *p = NewPolygon();
- AddVertex(p, NewVector(0.1, 0.1, 0));
- AddVertex(p, NewVector(0.1, 0.9, 0));
- AddVertex(p, NewVector(-1.3, 0.5, 0));
- AssertEqual(NumVertices(p), 3);
- bool visible = ClipPolygon(&p);
- AssertTrue(visible);
- AssertEqual(NumVertices(p), 4);
- FreePolygon(p);
-
- p = NewPolygon();
- AddVertex(p, NewVector(0.2, 0.2, 0));
- AddVertex(p, NewVector(0.3, 0.2, 0));
- AddVertex(p, NewVector(0.2, 0.3, 0));
- AssertEqual(NumVertices(p), 3);
- visible = ClipPolygon(&p);
- AssertTrue(visible);
- AssertEqual(NumVertices(p), 3);
- FreePolygon(p);
-
- p = NewPolygon();
- AddVertex(p, NewVector( -4.76, 0.75, -1.22));
- AddVertex(p, NewVector(-37.34, 3.38, -1.98));
- AddVertex(p, NewVector( 3.86, -0.42, -1.88));
- AddVertex(p, NewVector( 3.39, -0.74, -1.79));
- visible = ClipPolygon(&p);
- AssertFalse(visible);
- FreePolygon(p);
-
- p = NewPolygon();
- AddVertex(p, NewVector4D(+8.9960098267e-02, +1.7320507765e+00, +2.6407814026e-01, +1.7344551086e+00));
- AddVertex(p, NewVector4D(-3.2262287140e+00, +1.7320507765e+00, +8.4350967407e-01, +1.1561794281e+00));
- AddVertex(p, NewVector4D(-3.2262287140e+00, -1.7320507765e+00, +8.4350967407e-01, +1.1561794281e+00));
- AddVertex(p, NewVector4D(+8.9960098267e-02, -1.7320507765e+00, +2.6407814026e-01, +1.7344551086e+00));
- visible = ClipPolygon(&p);
- AssertTrue(visible);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex v = Homogenize(*PolygonVertex(p, i));
- AssertEqual(v.w, 1);
- AssertWithin(v.x, -1, 1);
- AssertWithin(v.y, -1, 1);
- AssertWithin(v.z, -1, 1);
- }
- FreePolygon(p);
-
- p = NewPolygon();
- AddVertex(p, NewVector4D( +2.1238925109378464e+00, +1.7320508075688776e+00, +9.4117255305726744e-01, +1.0587099095862040e+00 ));
- AddVertex(p, NewVector4D( -1.2739654549598711e+00, +1.7320508075688776e+00, +5.5113702891196237e-01, +1.4479661419749759e+00 ));
- AddVertex(p, NewVector4D( -1.2739654549598711e+00, -1.7320508075688776e+00, +5.5113702891196237e-01, +1.4479661419749759e+00 ));
- AddVertex(p, NewVector4D( +2.1238925109378464e+00, -1.7320508075688776e+00, +9.4117255305726744e-01, +1.0587099095862040e+00 ));
- visible = ClipPolygon(&p);
- AssertTrue(visible);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex v = Homogenize(*PolygonVertex(p, i));
- AssertEqual(v.w, 1);
- AssertWithin(v.x, -1, 1);
- AssertWithin(v.y, -1, 1);
- AssertWithin(v.z, -1, 1);
- }
- FreePolygon(p);
-
- // weird test case
- p = NewPolygon();
- AddVertex(p, NewVector4D(1.2247448713915885, 1.7320508075688776, 0.77071482817625591, 1.2247448713915903));
- AddVertex(p, NewVector4D(4.5708100863428234, 1.7320508075688776, 0.24261940281555505, 1.7423829615966344));
- AddVertex(p, NewVector4D(4.5708100863428234, -1.7320508075688776, 0.24261940281555505, 1.7423829615966344));
- AddVertex(p, NewVector4D(1.2247448713915885, -1.7320508075688776, 0.77071482817625591, 1.2247448713915903));
- visible = ClipPolygon(&p);
- AssertFalse(visible);
- // AssertTrue(NumVertices(p) >= 3);
- FreePolygon(p);
-}
D test2/color.test.c => test2/color.test.c +0 -23
@@ 1,23 0,0 @@
-#include "tests.h"
-
-void ColorTests(void)
-{
- DoTest(&TestColorPixel);
- DoTest(&TestPixelColor);
-}
-
-void TestColorPixel(void)
-{
- AssertEqual(ColorPixel(WHITE), 0xFFFFFFFF);
- AssertEqual(ColorPixel(BLACK), 0xFF000000);
- AssertEqual(ColorPixel(GRAY), 0xFF7F7F7F);
- AssertEqual(ColorPixel(DK_GRAY), 0xFF545454);
- AssertEqual(ColorPixel(LT_GRAY), 0xFFAAAAAA);
-}
-
-void TestPixelColor(void)
-{
- AssertEqual(PixelColor(0xFFFFFFFF), WHITE);
- AssertEqual(PixelColor(0x00000000), BLACK);
- AssertWithin(PixelColor(0xFF7F7F7F), GRAY-0.01, GRAY+0.01);
-}
D test2/endpoint.test.c => test2/endpoint.test.c +0 -106
@@ 1,106 0,0 @@
-#include "tests.h"
-
-void EndpointTests(void)
-{
- DoTest(&TestMakeEdgeTable);
- DoTest(&TestInsertEndpoints);
- DoTest(&TestRemoveEndpoints);
- DoTest(&TestIncrementEndpoints);
-}
-
-void TestMakeEdgeTable(void)
-{
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(84.5299454, 124.948715, 0));
- AddVertex(p, NewVertex(78.7564544, 125.196152, 0));
- AddVertex(p, NewVertex(78.7564544, 114.803848, 0));
- AddVertex(p, NewVertex(84.5299454, 115.051285, 0));
- Endpoint **table = MakeEdgeTable(240, p);
- AssertTrue(table);
- FreeEdgeTable(table, 240);
- FreePolygon(p);
-}
-
-void TestInsertEndpoints(void)
-{
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(84.5299454, 124.948715, 0));
- AddVertex(p, NewVertex(78.7564544, 125.196152, 0));
- AddVertex(p, NewVertex(78.7564544, 114.803848, 0));
- AddVertex(p, NewVertex(84.5299454, 115.051285, 0));
- Endpoint **table = MakeEdgeTable(240, p);
- Endpoint *list = NULL;
-
- for (int i = 0; i < 114; i++) {
- InsertEndpoints(&list, table[i]);
- AssertEqual(ListLength(list), 0);
- }
- InsertEndpoints(&list, table[114]);
- AssertEqual(ListLength(list), 2);
- InsertEndpoints(&list, table[115]);
- AssertEqual(ListLength(list), 3);
- for (int i = 116; i < 124; i++) {
- InsertEndpoints(&list, table[i]);
- AssertEqual(ListLength(list), 3);
- }
- InsertEndpoints(&list, table[124]);
- AssertEqual(ListLength(list), 4);
- for (int i = 125; i < 240; i++) {
- InsertEndpoints(&list, table[i]);
- AssertEqual(ListLength(list), 4);
- }
-
- FreeEdgeTable(table, 240);
- FreePolygon(p);
-}
-
-void TestRemoveEndpoints(void)
-{
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(84.5299454, 124.948715, 0));
- AddVertex(p, NewVertex(78.7564544, 125.196152, 0));
- AddVertex(p, NewVertex(78.7564544, 114.803848, 0));
- AddVertex(p, NewVertex(84.5299454, 115.051285, 0));
- Endpoint **table = MakeEdgeTable(240, p);
- Endpoint *list = NULL;
- InsertEndpoints(&list, table[114]);
- InsertEndpoints(&list, table[115]);
- InsertEndpoints(&list, table[124]);
-
- AssertEqual(ListLength(list), 4);
- RemoveEndpoints(&list, 115);
- AssertEqual(ListLength(list), 3);
- RemoveEndpoints(&list, 124);
- AssertEqual(ListLength(list), 2);
- RemoveEndpoints(&list, 125);
- AssertEqual(ListLength(list), 0);
-
- FreeEdgeTable(table, 240);
- FreePolygon(p);
-}
-
-void TestIncrementEndpoints(void)
-{
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(84.5299454, 124.948715, 0));
- AddVertex(p, NewVertex(78.7564544, 125.196152, 0));
- AddVertex(p, NewVertex(78.7564544, 114.803848, 0));
- AddVertex(p, NewVertex(84.5299454, 115.051285, 0));
- Endpoint **table = MakeEdgeTable(240, p);
- Endpoint *list = NULL;
- InsertEndpoints(&list, table[114]);
- AssertEqual(ListLength(list), 2);
- AssertWithin(list->x, 78, 79);
- AssertEqual(list->xinc, 0);
- AssertWithin(list->next->x, 78, 79);
- AssertWithin(list->next->xinc, 23, 24);
-
- AssertWithin(list->next->ymax, 115, 116);
-
- IncrementEndpoints(&list, 114);
- AssertWithin(list->x, 78, 79);
- AssertWithin(list->next->x, 78, 85);
-
- FreeEdgeTable(table, 240);
- FreePolygon(p);
-}
D test2/light.test.c => test2/light.test.c +0 -32
@@ 1,32 0,0 @@
-#include "tests.h"
-#include <math.h>
-
-void LightTests(void)
-{
- DoTest(&TestDiffuseLight);
-}
-
-void TestDiffuseLight(void)
-{
- LightSource **lights = NULL;
- LightSource *zlight = PointLight(V(0, 0, INFINITY), 1);
- list_push(lights, zlight);
-
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(1, 1, 0));
- AddVertex(p, NewVertex(-1, 1, 0));
- AddVertex(p, NewVertex(-1, -1, 0));
- AddVertex(p, NewVertex(1, -1, 0));
-
- double shade = DiffuseLight(p, lights);
- // AssertEqual(shade, 1.0);
-
- Polygon *q = FromPolygon(p, RotationY(90));
- shade = DiffuseLight(q, lights);
- // AssertEqual(shade, 0);
-
- FreePolygon(p);
- FreePolygon(q);
- free(zlight);
- list_free(lights);
-}
D test2/main.test.c => test2/main.test.c +0 -35
@@ 1,35 0,0 @@
-#include "tests.h"
-#include "assertions.h"
-#include <stdio.h>
-
-static int gTestFailures = 0;
-static int gTestSuccesses = 0;
-bool gTestPassed = true;
-
-void DoTest(TestFunc test)
-{
- (*test)();
- if (gTestPassed) {
- gTestSuccesses++;
- } else {
- gTestFailures++;
- }
- gTestPassed = true;
-}
-
-int main(void)
-{
- ColorTests();
- TransformTests();
- ProjectionTests();
- ClippingTests();
- RenderTests();
- EndpointTests();
- RasterizationTests();
- LightTests();
- ModelTests();
- PerformanceTests();
-
- printf("=================================\n");
- printf("%d passed, %d failed.\n", gTestSuccesses, gTestFailures);
-}
D test2/model.test.c => test2/model.test.c +0 -12
@@ 1,12 0,0 @@
-#include "tests.h"
-
-void ModelTests(void)
-{
- DoTest(&TestLoadMesh);
-}
-
-void TestLoadMesh(void)
-{
- Mesh *m = LoadMesh("assets/teapot.obj");
- AssertTrue(m != NULL);
-}>
\ No newline at end of file
D test2/performance.test.c => test2/performance.test.c +0 -53
@@ 1,53 0,0 @@
-#include "tests.h"
-#include <time.h>
-#include <stdio.h>
-#include <math.h>
-#include "../src/scene.h"
-
-void PerformanceTests(void)
-{
- DoTest(&TestRandomTriangles);
-}
-
-void TestRandomTriangles(void)
-{
- Scene *scene = NewScene();
- LightSource *light = PointLight(V(0, 2, 0), 1);
- AddLight(scene, light);
-
- for (int i = 0; i < 10000; ++i) {
- Polygon *tri = NewPolygon();
- AddVertex(tri, NewVector(0, 0, 0));
- AddVertex(tri, NewVector(0, 10, 0));
- AddVertex(tri, NewVector(10, 0, 0));
- Mesh *mesh = NewMesh();
- AddFacet(mesh, tri);
- Object *obj = NewObject(mesh, GRAY);
-
- RotateObj(obj, 0, rand() % 360, 0);
- int azimuth = rand() % 360;
- int dist = rand() % 100+10;
- double x = dist*cos(Rad(azimuth));
- double z = dist*sin(Rad(azimuth));
- PlaceObj(obj, V(x, 0, z));
- AddObject(scene, obj);
- }
-
- Pixel *pixels = malloc(sizeof(Pixel)*400*240);
- Viewport *viewport = NewViewport(pixels, BLACK, 400, 240);
- RasterSettings settings = DefaultRasterSettings();
- Camera *camera = NewCamera(V(0, 0, 0));
- LookAt(V(0, 0, -1), camera);
- Projection *projection = NewPerspectiveProjection(60, 400/240.f, 1, 100);
- RenderingContext context = MakeRenderingContext(viewport, camera, PerspectiveTransform(projection), settings);
-
- float clocksPerMs = CLOCKS_PER_SEC/1000;
- float startTime = (float)clock()/(clocksPerMs);
- RenderScene(scene, context);
- float endTime = (float)clock()/(clocksPerMs);
- float renderTime = (endTime - startTime);
-
- float targetTime = (1/30.f)*1000; // one frame, ~33 ms
- printf("Render time: %.2fms (target: %.2fms)\n", renderTime, targetTime);
- // AssertWithin(renderTime, 0, targetTime);
-}
D test2/project.test.c => test2/project.test.c +0 -110
@@ 1,110 0,0 @@
-#include "tests.h"
-#include <math.h>
-
-void ProjectionTests(void)
-{
- DoTest(&TestPerspectiveProjection);
- DoTest(&TestViewmapPolygon);
- DoTest(&TestCameraPosition);
-}
-
-void TestPerspectiveProjection(void)
-{
- Projection *projection = NewPerspectiveProjection(90, 1, 1, 2);
- Camera *camera = NewCamera(V(0, 0, 0));
- Transform t = GetProjectionTransform(camera, projection);
-
- Transform ct = CameraTransform(camera);
- AssertTrue(IsIdentity(ct));
-
- Vertex p = V(0, 1, -1);
- Vertex q = Homogenize(ProjectPoint(p, t));
- AssertTrue(VertexEqual(q, V(0, 1, 1)));
-
- p = V(0, -1, -1);
- q = Homogenize(ProjectPoint(p, t));
- AssertTrue(VertexEqual(q, V(0, -1, 1)));
-
- p = V(0, 2, -2);
- q = Homogenize(ProjectPoint(p, t));
- AssertTrue(VertexEqual(q, V(0, 1, -1)));
-
- p = V(0, -2, -2);
- q = Homogenize(ProjectPoint(p, t));
- AssertTrue(VertexEqual(q, V(0, -1, -1)));
-}
-
-void TestViewmapPolygon(void)
-{
- InitDeviceTransform(400, 240);
- Polygon *p = NewPolygon();
- AddVertex(p, NewVector(-0.921176, -1.000000, 1.000000));
- AddVertex(p, NewVector(1.000000, -1.000000, 0.559785));
- AddVertex(p, NewVector(1.000000, 1.000000, 0.559785));
- AddVertex(p, NewVector(-0.921176, 1.000000, 1.000000));
-
- ViewmapPolygon(p);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex *v = PolygonVertex(p, i);
- AssertTrue(v->x >= 0);
- AssertTrue(v->x < 400);
- AssertTrue(v->y >= 0);
- AssertTrue(v->y < 240);
- }
- FreePolygon(p);
-
- p = NewPolygon();
- AddVertex(p, NewVector(0.757628, -1.000000, 1.000000));
- AddVertex(p, NewVector(0.757628, 1.000000, 1.000000));
- AddVertex(p, NewVector(-1.000000, 1.000000, 0.574397));
- AddVertex(p, NewVector(-1.000000, -1.000000, 0.574397));
-
- ViewmapPolygon(p);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex *v = PolygonVertex(p, i);
- AssertTrue(v->x >= 0);
- AssertTrue(v->x < 400);
- AssertTrue(v->y >= 0);
- AssertTrue(v->y < 240);
- }
- FreePolygon(p);
-
-
- p = NewPolygon();
- AddVertex(p, NewVector(0.90350350893137943, 1.7320508075688776, 1.1582046473758254));
- AddVertex(p, NewVector(-2.0841785003064004, 1.7320508075688776, 0.14396012337173758));
- AddVertex(p, NewVector(-2.0841785003064004, -1.7320508075688776, 0.14396012337173758));
- AddVertex(p, NewVector(0.90350350893137943, -1.7320508075688776, 1.1582046473758254));
- ClipPolygon(&p);
- HomogenizePolygon(p);
- ViewmapPolygon(p);
- for (int i = 0; i < NumVertices(p); i++) {
- Vertex *v = PolygonVertex(p, i);
- AssertTrue(v->x >= 0);
- AssertTrue(v->x < 400);
- AssertTrue(v->y >= 0);
- AssertTrue(v->y < 240);
- }
- FreePolygon(p);
-}
-
-void TestCameraPosition(void)
-{
- Camera *camera = NewCamera(V(10, 20, -3));
- Vector p = camera->position;
- AssertEqual(p.x, 10);
- AssertEqual(p.y, 20);
- AssertEqual(p.z, -3);
-
- MoveCamera(V(1, 1, 1), camera);
- p = camera->position;
- AssertEqual(p.x, 11);
- AssertEqual(p.y, 21);
- AssertEqual(p.z, -2);
-
- RotateCamera(0, 130, 0, camera);
- p = camera->position;
- AssertEqual(p.x, 11);
- AssertEqual(p.y, 21);
- AssertEqual(p.z, -2);
-}
D test2/rasterize.test.c => test2/rasterize.test.c +0 -116
@@ 1,116 0,0 @@
-#include "tests.h"
-#include <stdlib.h>
-
-void RasterizationTests(void)
-{
- DoTest(&TestRasterLine);
- DoTest(&TestRasterPolygon);
- DoTest(&TestRasterTriangle);
-}
-
-void TestRasterLine(void)
-{
- Pixel *pixels = malloc(sizeof(Pixel)*100*100);
- Viewport *viewport = NewViewport(pixels, WHITE, 100, 100);
- DisableDepthBuffer(viewport);
-
- ClearViewport(viewport);
- Vertex a = V(5, 8, 0);
- Vertex b = V(9, 11, 0);
- RasterLine(a, b, BLACK, viewport);
- AssertPixel(4, 7, WHITE, viewport);
- AssertPixel(4, 8, WHITE, viewport);
- AssertPixel(5, 8, BLACK, viewport);
- AssertPixel(6, 9, BLACK, viewport);
- AssertPixel(7, 9, BLACK, viewport);
- AssertPixel(7, 8, WHITE, viewport);
- AssertPixel(8, 9, WHITE, viewport);
- AssertPixel(8, 10, BLACK, viewport);
- AssertPixel(9, 11, BLACK, viewport);
- AssertPixel(10, 11, WHITE, viewport);
- AssertPixel(10, 12, WHITE, viewport);
-
- ClearViewport(viewport);
-
- RasterLine(b, a, BLACK, viewport);
- AssertPixel(4, 7, WHITE, viewport);
- AssertPixel(4, 8, WHITE, viewport);
- AssertPixel(5, 8, BLACK, viewport);
- AssertPixel(6, 9, BLACK, viewport);
- AssertPixel(7, 9, BLACK, viewport);
- AssertPixel(7, 8, WHITE, viewport);
- AssertPixel(8, 9, WHITE, viewport);
- AssertPixel(8, 10, BLACK, viewport);
- AssertPixel(9, 11, BLACK, viewport);
- AssertPixel(10, 11, WHITE, viewport);
- AssertPixel(10, 12, WHITE, viewport);
-
- ClearViewport(viewport);
-
- b = V(7, 13, 0);
- RasterLine(a, b, BLACK, viewport);
- AssertPixel(5, 7, WHITE, viewport);
- AssertPixel(5, 8, BLACK, viewport);
- AssertPixel(5, 9, BLACK, viewport);
- AssertPixel(6, 10, BLACK, viewport);
- AssertPixel(6, 11, BLACK, viewport);
- AssertPixel(7, 12, BLACK, viewport);
- AssertPixel(7, 13, BLACK, viewport);
- AssertPixel(7, 14, WHITE, viewport);
-
- ClearViewport(viewport);
-
- RasterLine(b, a, BLACK, viewport);
- AssertPixel(5, 7, WHITE, viewport);
- AssertPixel(5, 8, BLACK, viewport);
- AssertPixel(5, 9, BLACK, viewport);
- AssertPixel(6, 10, BLACK, viewport);
- AssertPixel(6, 11, BLACK, viewport);
- AssertPixel(7, 12, BLACK, viewport);
- AssertPixel(7, 13, BLACK, viewport);
- AssertPixel(7, 14, WHITE, viewport);
-
- free(pixels);
-}
-
-void TestRasterPolygon(void)
-{
- Pixel *pixels = malloc(sizeof(Pixel)*400*240);
- Viewport *viewport = NewViewport(pixels, WHITE, 400, 240);
- RasterSettings settings = { false };
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(84.5299454, 124.948715, 0));
- AddVertex(p, NewVertex(78.7564544, 125.196152, 0));
- AddVertex(p, NewVertex(78.7564544, 114.803848, 0));
- AddVertex(p, NewVertex(84.5299454, 115.051285, 0));
- RasterPolygon(p, BLACK, viewport, settings);
-
- // bounding box should stay white
- for (int x = 78; x < 85; x++) {
- AssertPixel(x, 113, WHITE, viewport);
- AssertPixel(x, 126, WHITE, viewport);
- }
- for (int y = 114; y < 126; y++) {
- AssertPixel(77, y, WHITE, viewport);
- AssertPixel(85, y, WHITE, viewport);
- }
-
- free(pixels);
- FreePolygon(p);
-}
-
-void TestRasterTriangle(void)
-{
- Pixel *pixels = malloc(sizeof(Pixel)*400*240);
- Viewport *viewport = NewViewport(pixels, WHITE, 400, 240);
-
- Polygon *t = NewPolygon();
- AddVertex(t, NewVertex(1, 1, 0));
- AddVertex(t, NewVertex(2, 10, 0));
- AddVertex(t, NewVertex(7, 3, 0));
-
- RasterTriangle(t, BLACK);
- // TODO: assert pixels
-
- FreePolygon(t);
-}
D test2/render.test.c => test2/render.test.c +0 -57
@@ 1,57 0,0 @@
-#include "tests.h"
-
-void RenderTests(void)
-{
- // DoTest(&TestSetViewport);
- DoTest(&TestClearViewport);
- DoTest(&TestBackfaceCulled);
-}
-
-void TestSetViewport(void)
-{
- Pixel *pixels = malloc(sizeof(Pixel)*100*100);
- Viewport *viewport = NewViewport(pixels, WHITE, 100, 100);
- for (int x = 0; x < 100; x++) {
- for (int y = 0; y < 100; y++) {
- AssertPixel(x, y, WHITE, viewport);
- }
- }
- free(pixels);
-}
-
-void TestClearViewport(void)
-{
- Pixel *pixels = malloc(sizeof(Pixel)*100*100);
- Viewport *viewport = NewViewport(pixels, WHITE, 100, 100);
- WritePixel(0, 0, BLACK, viewport);
- WritePixel(50, 30, BLACK, viewport);
- WritePixel(99, 99, BLACK, viewport);
- ClearViewport(viewport);
-
- for (int x = 0; x < 100; x++) {
- for (int y = 0; y < 100; y++) {
- AssertPixel(x, y, WHITE, viewport);
- }
- }
- free(pixels);
-}
-
-void TestBackfaceCulled(void)
-/* Culls polygons defined by clockwise vertices */
-{
- /* CCW, not culled */
- Polygon *p = NewPolygon();
- AddVertex(p, NewVertex(0, 0, 0));
- AddVertex(p, NewVertex(1, 0, 0));
- AddVertex(p, NewVertex(0, 1, 0));
- AssertFalse(BackfaceCulled(p));
- FreePolygon(p);
-
- /* CW, culled */
- p = NewPolygon();
- AddVertex(p, NewVertex(0, 0, 0));
- AddVertex(p, NewVertex(0, 1, 0));
- AddVertex(p, NewVertex(1, 0, 0));
- AssertTrue(BackfaceCulled(p));
- FreePolygon(p);
-}
D test2/tests.h => test2/tests.h +0 -78
@@ 1,78 0,0 @@
-#pragma once
-
-#include "assertions.h"
-#include "../src/3d.h"
-#include "../src/arraylist.h"
-
-typedef void (*TestFunc)(void);
-void DoTest(TestFunc test);
-
-void ColorTests(void);
-void TestColorPixel(void);
-void TestPixelColor(void);
-
-void VectorTests(void);
-void TestNegVec(void);
-void TestVecMul(void);
-void TestVecAdd(void);
-void TestVecSub(void);
-void TestVecLen(void);
-void TestDotProd(void);
-void TestCrossProd(void);
-void TestNormalizeVector(void);
-
-void TransformTests(void);
-void TestSetIdentity(void);
-void TestFromTransform(void);
-void TestAddTransform(void);
-void TestApplyTransform(void);
-void TestCommitTransform(void);
-void TestRotationX(void);
-void TestRotateX(void);
-void TestRotationY(void);
-void TestRotateY(void);
-void TestRotationZ(void);
-void TestRotateZ(void);
-void TestTranslation(void);
-void TestTranslate(void);
-void TestScalation(void);
-void TestScale(void);
-void TestDeterminant(void);
-
-void RenderTests(void);
-void TestSetViewport(void);
-void TestClearViewport(void);
-void TestBackfaceCulled(void);
-void TestDrawPolygon(void);
-
-void ProjectionTests(void);
-void TestPerspectiveProjection(void);
-void TestViewmapPolygon(void);
-void TestCameraPosition(void);
-
-void ClippingTests(void);
-void TestClipLine(void);
-void TestVertexInside(void);
-void TestClipIntersect(void);
-void TestClipPolygonPlane(void);
-void TestClipPolygon(void);
-
-void EndpointTests(void);
-void TestMakeEdgeTable(void);
-void TestInsertEndpoints(void);
-void TestRemoveEndpoints(void);
-void TestIncrementEndpoints(void);
-
-void RasterizationTests(void);
-void TestRasterLine(void);
-void TestRasterPolygon(void);
-void TestRasterTriangle(void);
-
-void LightTests(void);
-void TestDiffuseLight(void);
-
-void PerformanceTests(void);
-void TestRandomTriangles(void);
-
-void ModelTests(void);
-void TestLoadMesh(void);
D test2/transform.test.c => test2/transform.test.c +0 -69
@@ 1,69 0,0 @@
-#include <stdlib.h>
-#include "tests.h"
-#include <stdio.h>
-
-void TransformTests(void)
-{
- DoTest(&TestSetIdentity);
- DoTest(&TestFromTransform);
- DoTest(&TestAddTransform);
- DoTest(&TestApplyTransform);
-}
-
-void TestSetIdentity(void)
-{
- Transform t = Identity();
- for(int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- if (i == j) AssertEqual(t.m[i][j], 1);
- else AssertEqual(t.m[i][j], 0);
- }
- }
-}
-
-void TestFromTransform(void)
-{
- Transform t = Identity();
- t.m[2][3] = 3;
- t.m[0][3] = 9;
- t.m[2][1] = 7;
- Transform u = FromTransform(t);
- t.m[2][2] = 0;
-
- AssertEqual(u.m[2][3], 3);
- AssertEqual(u.m[0][3], 9);
- AssertEqual(u.m[2][1], 7);
- AssertEqual(u.m[2][2], 1);
-}
-
-void TestAddTransform(void)
-{
- Transform t = Identity();
- t.m[0][3] = 1;
- Transform u = Identity();
- u.m[1][3] = 2;
- AddTransform(u, &t);
- AssertEqual(t.m[0][3], 1);
- AssertEqual(t.m[1][3], 2);
-}
-
-void TestApplyTransform(void)
-{
- Transform t;
- Vertex v0 = V( 0.00, 0.00, 0.00);
- Vertex v1 = V( 1.00, 0.00, 0.00);
- t.m[0][0] = 0.34; t.m[0][1] = -0.54; t.m[0][2] = -1.61; t.m[0][3] = 10.74;
- t.m[1][0] = 0.00; t.m[1][1] = 1.64; t.m[1][2] = -0.55; t.m[1][3] = 0.00;
- t.m[2][0] = 0.98; t.m[2][1] = 0.06; t.m[2][2] = 0.19; t.m[2][3] = -0.24;
- t.m[3][0] = -0.98; t.m[3][1] = -0.06; t.m[3][2] = -0.19; t.m[3][3] = 1.24;
-
- Vertex r0 = Homogenize(ApplyTransform(t, v0));
- Vertex r1 = Homogenize(ApplyTransform(t, v1));
- AssertTrue(r0.x > 1);
- AssertTrue(r1.x > r0.x);
-
- t.m[0][0] = 0.23; t.m[0][1] = -0.54; t.m[0][2] = -1.63; t.m[0][3] = 10.86;
- t.m[1][0] = 0.00; t.m[1][1] = 1.64; t.m[1][2] = -0.55; t.m[1][3] = 0.00;
- t.m[2][0] = 0.99; t.m[2][1] = 0.04; t.m[2][2] = 0.13; t.m[2][3] = 0.16;
- t.m[3][0] = -0.99; t.m[3][1] = -0.04; t.m[3][2] = -0.13; t.m[3][3] = 0.84;
-}
D test2/vector.test.c => test2/vector.test.c +0 -92
@@ 1,92 0,0 @@
-#include "tests.h"
-
-void VectorTests(void)
-{
- DoTest(&TestNegVec);
- DoTest(&TestVecMul);
- DoTest(&TestVecAdd);
- DoTest(&TestVecSub);
- DoTest(&TestVecLen);
- DoTest(&TestDotProd);
- DoTest(&TestCrossProd);
- DoTest(&TestNormalizeVector);
-}
-
-void TestNegVec(void)
-{
- Vector a = { 1, 3, 2, 1 };
- Vector b = NegVec(a);
- AssertEqual(b.x, -1);
- AssertEqual(b.y, -3);
- AssertEqual(b.z, -2);
-}
-
-void TestVecMul(void)
-{
- Vector a = { 1, 3, 2, 1 };
- Vector b = VecMul(a, 3);
- AssertEqual(b.x, 3);
- AssertEqual(b.y, 9);
- AssertEqual(b.z, 6);
- b = VecMul(a, -1.5);
- AssertEqual(b.x, -1.5);
- AssertEqual(b.y, -4.5);
- AssertEqual(b.z, -3);
-}
-
-void TestVecAdd(void)
-{
- Vector a = { 1, 3, 2, 1 };
- Vector b = { -3, 13, 1, 1 };
- Vector c = VecAdd(a, b);
- AssertEqual(c.x, -2);
- AssertEqual(c.y, 16);
- AssertEqual(c.z, 3);
-}
-
-void TestVecSub(void)
-{
- Vector a = { -23, 14, 1, 1 };
- Vector b = { 52, 3, 14, 1 };
- Vector c = VecSub(a, b);
- AssertEqual(c.x, -75);
- AssertEqual(c.y, 11);
- AssertEqual(c.z, -13);
- Vector d = VecSub(b, a);
- AssertEqual(d.x, 75);
- AssertEqual(d.y, -11);
- AssertEqual(d.z, 13);
-}
-
-void TestVecLen(void)
-{
- Vector a = { 4, 0, 0, 1 };
- double len = VecLen(a);
- AssertEqual(len, 4);
-}
-
-void TestDotProd(void)
-{
- Vector a = { 1, 2, 3, 1 };
- Vector b = { 3, 2, 4, 1 };
- AssertEqual(DotProd(a, b), 19);
-}
-
-void TestCrossProd(void)
-{
- Vector a = { 0, 0, 4, 1 };
- Vector b = { 0, -3, 0, 1 };
- Vector c = CrossProd(a, b);
- AssertEqual(c.x, 12);
- AssertEqual(c.y, 0);
- AssertEqual(c.z, 0);
-}
-
-void TestNormalizeVector(void)
-{
- Vector a = { 27, 0, 0, 1 };
- Vector b = NormalizeVector(a);
- AssertEqual(b.x, 1);
- AssertEqual(b.y, 0);
- AssertEqual(b.z, 0);
-}