#define WINDOW_WIDTH 1024
#define WINDOW_HEIGHT 768
+#define EPSILON 1e-6f
+
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Surface *window_surface;
+void print_vec30(struct array *array) {
+ for (int i = 0; i < 3; ++i) {
+ float v;
+ array_get1(array, &v, i);
+ printf("%s%7.3f", i ? ", " : "[", v);
+ }
+ printf("]");
+}
+
+void print_vec31(struct array *array, size_t i0) {
+ for (int i = 0; i < 3; ++i) {
+ float v;
+ array_get2(array, &v, i0, i);
+ printf("%s%7.3f", i ? ", " : "[", v);
+ }
+ printf("]");
+}
+
+void print_vec40(struct array *array) {
+ for (int i = 0; i < 4; ++i) {
+ float v;
+ array_get1(array, &v, i);
+ printf("%s%7.3f", i ? ", " : "[", v);
+ }
+ printf("]");
+}
+
+void print_vec41(struct array *array, size_t i0) {
+ for (int i = 0; i < 4; ++i) {
+ float v;
+ array_get2(array, &v, i0, i);
+ printf("%s%7.3f", i ? ", " : "[", v);
+ }
+ printf("]");
+}
+
+void print_mat330(struct array *array) {
+ for (int i = 0; i < 3; ++i) {
+ printf("%s", i ? " " : "[");
+ print_vec31(array, i);
+ printf("%s", i < 2 ? "\n" : "]");
+ }
+}
+
+void print_mat340(struct array *array) {
+ for (int i = 0; i < 3; ++i) {
+ printf("%s", i ? " " : "[");
+ print_vec41(array, i);
+ printf("%s", i < 2 ? "\n" : "]");
+ }
+}
+
+void print_mat440(struct array *array) {
+ for (int i = 0; i < 4; ++i) {
+ printf("%s", i ? " " : "[");
+ print_vec41(array, i);
+ printf("%s", i < 3 ? "\n" : "]");
+ }
+}
+
+// compute C = A B
+void mul_mat33_mat34(struct array *A, struct array *B, struct array *C) {
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 4; ++j) {
+ float c = 0.f;
+ for (int k = 0; k < 3; ++k) {
+ float a, b;
+ array_get2(A, &a, i, k);
+ array_get2(B, &b, k, j);
+ c += a * b;
+ }
+ array_set2(C, &c, i, j);
+ }
+}
+void mul_mat34_mat44(struct array *A, struct array *B, struct array *C) {
+ for (int i = 0; i < 3; ++i)
+ for (int j = 0; j < 4; ++j) {
+ float c = 0.f;
+ for (int k = 0; k < 4; ++k) {
+ float a, b;
+ array_get2(A, &a, i, k);
+ array_get2(B, &b, k, j);
+ c += a * b;
+ }
+ array_set2(C, &c, i, j);
+ }
+}
+void mul_mat34_vec4(struct array *A, struct array *B, struct array *C) {
+ for (int i = 0; i < 3; ++i) {
+ float c = 0.f;
+ for (int j = 0; j < 4; ++j) {
+ float a, b;
+ array_get2(A, &a, i, j);
+ array_get1(B, &b, j);
+ c += a * b;
+ }
+ array_set1(C, &c, i);
+ }
+}
+
int main(void) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
exit(EXIT_FAILURE);
}
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xff);
+ // device
+ struct array *device_transform = array_new3(3, 3, sizeof(float));
+ {
+ float v[3][3] = {
+ {WINDOW_WIDTH, 0.f, .5f * WINDOW_WIDTH},
+ {0.f, WINDOW_WIDTH, .5f * WINDOW_HEIGHT},
+ {0.f, 0.f, 1.f},
+ };
+ array_set0(device_transform, v);
+ }
+ printf("device_transform\n");
+ print_mat330(device_transform);
+ printf("\n");
- struct array *a = array_new3(4, 4, sizeof(float));
- array_clear0(a);
- for (int i = 0; i < 4; ++i)
- for (int j = 0; j < i; ++j) {
- float v = i + j;
- array_set2(a, &v, i, j);
- }
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 4; ++j) {
- float v;
- array_get2(a, &v, i, j);
- printf("%s%7.3f", j ? ", " : i ? " [" : "[[", v);
- }
- printf("%s\n", i < 3 ? "]" : "]]");
+ // perspective
+ struct array *perspective_transform = array_new3(3, 4, sizeof(float));
+ {
+ float v[3][4] = {
+ {1.f, 0.f, 0.f, 0.f},
+ {0.f, 0.f, 1.f, 0.f},
+ {0.f, 1.f, 0.f, 0.f},
+ };
+ array_set0(perspective_transform, v);
}
+ printf("perspective_transform\n");
+ print_mat340(perspective_transform);
+ printf("\n");
+
+ // camera
+ struct array *camera_transform = array_new3(4, 4, sizeof(float));
+ {
+ float v[4][4] = {
+ {1.f, 0.f, 0.f, 0.f},
+ {0.f, 1.f, 0.f, 10.f},
+ {0.f, 0.f, 1.f, 0.f},
+ {0.f, 0.f, 0.f, 1.f}
+ };
+ array_set0(camera_transform, v);
+ }
+ printf("camera_transform\n");
+ print_mat440(camera_transform);
+ printf("\n");
+
+ // model
+ struct array *model_vertices = array_new3(8, 4, sizeof(float));
+ for (int i = 0; i < 2; ++i)
+ for (int j = 0; j < 2; ++j)
+ for (int k = 0; k < 2; ++k) {
+ float v[4] = {i * 2 - 1, j * 2 - 1, k * 2 - 1, 1.f};
+ array_set1(model_vertices, v, i * 4 + j * 2 + k);
+ }
+ printf("model_vertices\n");
+ for (int i = 0; i < 8; ++i) {
+ print_vec41(model_vertices, i);
+ printf("\n");
+ }
+ int model_lines[12][2] = {
+ {0, 1}, // 0, 0, 0 -> 0, 0, 1
+ {0, 2}, // 0, 0, 0 -> 0, 1, 0
+ {0, 4}, // 0, 0, 0 -> 1, 0, 0
+
+ //{1, 0}, // 0, 0, 1 -> 0, 0, 0
+ {1, 3}, // 0, 0, 1 -> 0, 1, 1
+ {1, 5}, // 0, 0, 1 -> 1, 0, 1
+
+ {2, 3}, // 0, 1, 0 -> 0, 1, 1
+ //{2, 0}, // 0, 1, 0 -> 0, 0, 0
+ {2, 6}, // 0, 1, 0 -> 1, 1, 0
+
+ //{3, 2}, // 0, 1, 1 -> 0, 1, 0
+ //{3, 1}, // 0, 1, 1 -> 0, 0, 1
+ {3, 7}, // 0, 1, 1 -> 1, 1, 1
+ {4, 5}, // 1, 0, 0 -> 1, 0, 1
+ {4, 6}, // 1, 0, 0 -> 1, 1, 0
+ //{4, 0}, // 1, 0, 0 -> 0, 0, 0
+
+ //{5, 4}, // 1, 0, 1 -> 1, 0, 0
+ {5, 7}, // 1, 0, 1 -> 1, 1, 1
+ //{5, 1}, // 1, 0, 1 -> 0, 0, 1
+
+ {6, 7}, // 1, 1, 0 -> 1, 1, 1
+ //{6, 4}, // 1, 1, 0 -> 1, 0, 0
+ //{6, 2}, // 1, 1, 0 -> 0, 1, 0
+
+ //{7, 6}, // 1, 1, 1 -> 1, 1, 0
+ //{7, 5}, // 1, 1, 1 -> 1, 0, 1
+ //{7, 3}, // 1, 1, 1 -> 0, 1, 1
+ };
+
+ struct array *model_transform = array_new3(4, 4, sizeof(float));
+ {
+ float v[4][4] = {
+ {1.f, 0.f, 0.f, 0.f},
+ {0.f, 1.f, 0.f, 0.f},
+ {0.f, 0.f, 1.f, 0.f},
+ {0.f, 0.f, 0.f, 1.f}
+ };
+ array_set0(model_transform, v);
+ }
+ printf("model_transform\n");
+ print_mat440(model_transform);
+ printf("\n");
+
+ // main loop
while (true) {
SDL_Event event;
while (SDL_PollEvent(&event))
goto quit;
}
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xff);
SDL_RenderClear(renderer);
+
+ // compose device, perspective, camera and model transforms for speed
+ struct array *t0 = array_new3(3, 4, sizeof(float));
+ mul_mat33_mat34(device_transform, perspective_transform, t0);
+ struct array *t1 = array_new3(3, 4, sizeof(float));
+ mul_mat34_mat44(t0, camera_transform, t1);
+ struct array *t2 = array_new3(3, 4, sizeof(float));
+ mul_mat34_mat44(t1, model_transform, t2);
+
+ // transform model points
+ struct array *p = array_new3(8, 3, sizeof(float));
+ for (int i = 0; i < 8; ++i)
+ // taken from mul_mat34_vec4():
+ for (int j = 0; j < 3; ++j) {
+ float c = 0.f;
+ for (int k = 0; k < 4; ++k) {
+ float a, b;
+ array_get2(t2, &a, j, k);
+ array_get2(model_vertices, &b, i, k);
+ c += a * b;
+ }
+ array_set2(p, &c, i, j);
+ }
+
+ // unproject
+ for (int i = 0; i < 8; ++i) {
+ float v[3];
+ array_get1(p, v, i);
+ if (v[2] >= EPSILON) {
+ v[0] /= v[2];
+ v[1] /= v[2];
+ array_set1(p, v, i);
+ }
+ }
+
+ // draw
+ SDL_SetRenderDrawColor(renderer, 0, 0xff, 0, 0xff);
+ for (int i = 0; i < 12; ++i) {
+ float p0[3];
+ float p1[3];
+ array_get1(p, p0, model_lines[i][0]);
+ array_get1(p, p1, model_lines[i][1]);
+ if (p0[2] >= EPSILON && p1[2] >= EPSILON)
+ SDL_RenderDrawLine(renderer, p0[0], p0[1], p1[0], p1[1]);
+ }
+
+ array_free(p);
+ array_free(t2);
+ array_free(t1);
+ array_free(t0);
+
SDL_RenderPresent(renderer);
SDL_Delay(1);
}