From 7e25d7d5f161826e6a0d76763ae6b71cb6e92810 Mon Sep 17 00:00:00 2001 From: Tom Marks Date: Wed, 1 Sep 2021 21:37:57 +1000 Subject: [PATCH] Working 3D Math (I think) (#7) * update makefiles to clean src and handle dist better * nuke dist folder on clean * reworked matrices for proper MVP with cam pos and rotation(y) * add primitive fustrum test * fix formatter in Makefile, format Co-authored-by: Tom Marks --- Makefile | 10 +++++-- src/draw.c | 79 +++++++++++++++++++++++++++++++++++---------------- src/main.c | 30 +++++++++++-------- src/math.c | 33 ++++++++++----------- src/ps2draw.h | 9 ++++-- src/ps2math.h | 1 + 6 files changed, 103 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index 341ccf0..b7fd655 100644 --- a/Makefile +++ b/Makefile @@ -18,11 +18,15 @@ assets: cp asset/*.bin dist/ cp distfiles/* dist/ -$(BIN): +$(BIN): src/test.elf if ! [ -d dist ]; then mkdir dist; fi - $(MAKE) PLATFORM=ps2 -C src test.elf cp src/test.elf dist/test.elf +.PHONY: src/test.elf +src/test.elf: + $(MAKE) PLATFORM=ps2 -C src test.elf + + # TODO(phy1um): update ISO building to include everything in dist/ $(ISO_TGT): $(EE_BIN) mkisofs -l -o $(ISO_TGT) $(BIN) dist/SYSTEM.CNF @@ -57,6 +61,6 @@ lint: .PHONY: format format: - $(DOCKER) run $(DOCKERFLAGS) -v $(shell pwd):/workdir unibeautify/clang-format -i -sort-includes *.c *.h + $(DOCKER) run $(DOCKERFLAGS) -v $(shell pwd):/workdir unibeautify/clang-format -i -sort-includes **/*.c **/*.h diff --git a/src/draw.c b/src/draw.c index 054bfde..01c18c6 100644 --- a/src/draw.c +++ b/src/draw.c @@ -4,9 +4,9 @@ #include -#include "ps2draw.h" #include "log.h" #include "mesh.h" +#include "ps2draw.h" #include "ps2math.h" #define ZMAX (1024 * 1024) @@ -15,10 +15,17 @@ static int cc = 0; void log_matrix(MATRIX m) { printf("Matrix = \n"); - for (int i = 0; i < 4; i++) { - int b = i * 4; - printf("%.2f %.2f %.2f %.2f\n", m[b], m[b + 1], m[b + 2], m[b + 3]); - } + printf("%.2f %.2f %.2f %.2f\n", m[0], m[4], m[8], m[12]); + printf("%.2f %.2f %.2f %.2f\n", m[1], m[5], m[9], m[13]); + printf("%.2f %.2f %.2f %.2f\n", m[2], m[6], m[10], m[14]); + printf("%.2f %.2f %.2f %.2f\n", m[3], m[7], m[11], m[15]); +} + +int mesh_is_visible(struct model_instance *inst, struct render_state *d) { + VECTOR v; + vector_sub(v, d->camera_pos, inst->translate); + float dot = v[0] * d->fwd[0] + v[1] * d->fwd[1] + v[2] * d->fwd[2]; + return (dot > 0); } void mesh_transform(char *b, struct model_instance *inst, @@ -28,12 +35,22 @@ void mesh_transform(char *b, struct model_instance *inst, matrix_unit(model); create_model_matrix(model, inst->translate, inst->scale, inst->rotate); matrix_unit(tmp); - matrix_multiply(tmp, model, d->world_to_screen); - if (cc % 100 == 0) { - info("Matrix info"); - log_matrix(d->world_to_screen); - log_matrix(model); + matrix_multiply(tmp, tmp, model); + matrix_multiply(tmp, tmp, d->v); + matrix_multiply(tmp, tmp, d->p); + + if (cc == 0) { + info("PROJECTION == "); + log_matrix(d->p); + } + + if (cc % 200 == 0) { + info("###### Matrix info ######"); + info("rotate=%f", d->camera_rotate_y); + info(" view="); + log_matrix(d->v); + info(" mvp="); log_matrix(tmp); } int stride = inst->m->vertex_size * 16; @@ -42,14 +59,18 @@ void mesh_transform(char *b, struct model_instance *inst, // get address of current vertex data float *pos = (float *)(b + (stride * i) + (inst->m->vertex_position_offset * 16)); - VECTOR *v = pos; + float *v = pos; + pos[3] = 1.f; vector_apply(v, v, tmp); pos[0] = pos[0] / pos[3]; pos[1] = pos[1] / pos[3]; - pos[2] = pos[2] / pos[3]; + pos[2] = pos[2]; d_avg += pos[2]; + pos[0] = (pos[0] * 200); + pos[1] = (pos[1] * 200); + *((uint32_t *)pos) = ftoi4(pos[0] + d->offset_x); *((uint32_t *)(pos + 1)) = ftoi4(pos[1] + d->offset_y); uint32_t zv = (uint32_t)(ZMAX * (pos[2] / 100.f)); @@ -69,7 +90,9 @@ void mesh_transform(char *b, struct model_instance *inst, pos[3] = 0; } - // info("avg depth = %f", d_avg / (1.0f * inst->m->vertex_count)); + if (cc % 100 == 0) { + info("avg depth = %f", d_avg / (1.0f * inst->m->vertex_count)); + } cc++; } @@ -87,16 +110,22 @@ void update_draw_matrix(struct render_state *d) { d->up[2] = 0; d->up[3] = 0; - VECTOR camfwd = {0, 0, -1, 0}; - vector_rotate_y(camfwd, d->camera_rotate_y); - // d->camera_tgt[0] = d->camera_pos[0] + camfwd[0]; - // d->camera_tgt[1] = d->camera_pos[1] + camfwd[1]; - d->camera_tgt[2] = d->camera_pos[2] - 1; - - MATRIX viewport, proj, cam; - matrix_viewport(viewport, 640.f, 480.f); - matrix_proj(proj, 1.2f, 3.f / 4.f, 1.f, 100.f); - matrix_lookat(cam, d->camera_pos, d->camera_tgt, d->up); - matrix_multiply(d->world_to_screen, viewport, proj); - matrix_multiply(d->world_to_screen, d->world_to_screen, cam); + d->fwd[0] = 0; + d->fwd[1] = 0; + d->fwd[2] = -1.f; + d->fwd[3] = 1.f; + vector_rotate_y(d->fwd, d->camera_rotate_y); + + d->camera_tgt[0] = d->camera_pos[0] + d->fwd[0]; + d->camera_tgt[1] = d->camera_pos[1] + d->fwd[1]; + d->camera_tgt[2] = d->camera_pos[2] + d->fwd[2]; + /* + d->camera_tgt[0] = 0; + d->camera_tgt[1] = 0; + d->camera_tgt[2] = 0; + */ + d->camera_tgt[3] = 1; + + matrix_proj(d->p, 1.2f, 0.7f, .1f, 100.f); + matrix_lookat(d->v, d->camera_pos, d->camera_tgt, d->up); } diff --git a/src/main.c b/src/main.c index 06fdbee..880f8df 100644 --- a/src/main.c +++ b/src/main.c @@ -13,11 +13,11 @@ #include -#include "ps2draw.h" #include "gs.h" #include "log.h" #include "mesh.h" #include "pad.h" +#include "ps2draw.h" #define OFFSET_X 2048 #define OFFSET_Y 2048 @@ -77,7 +77,7 @@ int main() { struct render_state r = {0}; r.camera_pos[0] = 0.0f; - r.camera_pos[2] = 10.0f; + r.camera_pos[2] = 1.0f; r.camera_pos[3] = 1.0f; r.clear_col[0] = 0xb1; @@ -89,10 +89,11 @@ int main() { struct model_instance inst = {0}; inst.m = &m; - inst.scale[0] = .8f; - inst.scale[1] = .8f; - inst.scale[2] = .8f; + inst.scale[0] = 1.f; + inst.scale[1] = 1.f; + inst.scale[2] = 1.f; inst.scale[3] = 1.0f; + inst.translate[2] = 10.f; pad_init(); @@ -108,12 +109,14 @@ int main() { q = draw_clear(q, 0, 2048.0f - 320, 2048.0f - 244, VID_W, VID_H, r.clear_col[0], r.clear_col[1], r.clear_col[2]); q = draw_enable_tests(q, 0, &st.zb); - qword_t *model_verts_start = q; - memcpy(q, m.buffer, m.buffer_len); - // info("copied mesh buffer with len=%d", m.buffer_len); - q += (m.buffer_len / 16); + if (mesh_is_visible(&inst, &r)) { + qword_t *model_verts_start = q; + memcpy(q, m.buffer, m.buffer_len); + // info("copied mesh buffer with len=%d", m.buffer_len); + mesh_transform((char *)(model_verts_start + MESH_HEADER_SIZE), &inst, &r); + q += (m.buffer_len / 16); + } q = draw_finish(q); - mesh_transform((char *)(model_verts_start + MESH_HEADER_SIZE), &inst, &r); dma_channel_send_normal(DMA_CHANNEL_GIF, buf, q - buf, 0, 0); // print_buffer(buf, q-buf); // info("draw from buffer with length %d", q-buf); @@ -133,10 +136,13 @@ int main() { #else int dx = button_held(DPAD_RIGHT) - button_held(DPAD_LEFT); int dz = button_held(DPAD_DOWN) - button_held(DPAD_UP); + int dy = button_held(BUTTON_L1) - button_held(BUTTON_L2); #endif - r.camera_pos[0] += 0.02f * dx; - r.camera_pos[2] += 0.02f * dz; + r.camera_pos[0] += 0.2f * dx; + r.camera_pos[2] += 0.2f * dz; + // r.camera_pos[1] += 0.1f * dy; + r.camera_rotate_y += 0.01f * dy; } } diff --git a/src/math.c b/src/math.c index 6217029..80d1920 100644 --- a/src/math.c +++ b/src/math.c @@ -27,12 +27,12 @@ void vector_sub(VECTOR out, VECTOR a, VECTOR b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; - out[3] = a[3] - b[3]; + // out[3] = a[3] - b[3]; } void matrix_lookat(MATRIX out, VECTOR eye, VECTOR c, VECTOR up) { - VECTOR z, x, y; - vector_sub(z, eye, c); + VECTOR z, x, y, nd; + vector_sub(z, c, eye); vector_normalize(z, z); vector_cross(x, up, z); @@ -42,17 +42,18 @@ void matrix_lookat(MATRIX out, VECTOR eye, VECTOR c, VECTOR up) { vector_normalize(y, y); matrix_unit(out); - MATRIX t; - matrix_unit(t); + + nd[0] = -1 * (x[0] * eye[0] + x[1] * eye[1] + x[2] * eye[2]); + nd[1] = -1 * (y[0] * eye[0] + y[1] * eye[1] + y[2] * eye[2]); + nd[2] = -1 * (z[0] * eye[0] + z[1] * eye[1] + z[2] * eye[2]); for (int i = 0; i < 3; i++) { - out[i] = x[i]; - out[4 + i] = y[i]; - out[8 + i] = z[i]; - t[12 + i] = c[i]; + out[4 * i] = x[i]; + out[4 * i + 1] = y[i]; + out[4 * i + 2] = z[i]; + out[4 * i + 3] = nd[i]; } - matrix_multiply(out, out, t); matrix_tsp(out); } @@ -64,13 +65,13 @@ void matrix_zero(MATRIX out) { void matrix_proj(MATRIX out, float fov, float ar, float near, float far) { matrix_zero(out); - float angle = 1 / (tanf(fov / 2)); - out[0] = ar * angle; + float angle = 1.f / (tanf(fov * 0.5f)); + float fn = 1.f / (near - far); + out[0] = angle / ar; out[5] = angle; - out[10] = far / (far - near); - out[11] = 1; - out[14] = (-far * near) / (far - near); - matrix_tsp(out); + out[10] = -1 * far * fn; + out[14] = near * far * fn; + out[11] = 1.0f; } void matrix_viewport(MATRIX out, float w, float h) { diff --git a/src/ps2draw.h b/src/ps2draw.h index 19560af..c4ee26d 100644 --- a/src/ps2draw.h +++ b/src/ps2draw.h @@ -9,13 +9,14 @@ struct render_state { float offset_x; float offset_y; char clear_col[3]; - MATRIX world_view; - MATRIX view_screen; MATRIX world_to_screen; + MATRIX v; + MATRIX p; VECTOR camera_pos; VECTOR camera_tgt; - float camera_rotate_y; + VECTOR fwd; VECTOR up; + float camera_rotate_y; }; struct model_instance { @@ -31,4 +32,6 @@ void create_model_matrix(MATRIX tgt, VECTOR translate, VECTOR scale, VECTOR rotate); void update_draw_matrix(struct render_state *d); +int mesh_is_visible(struct model_instance *inst, struct render_state *d); + #endif diff --git a/src/ps2math.h b/src/ps2math.h index e7f01da..bac9911 100644 --- a/src/ps2math.h +++ b/src/ps2math.h @@ -11,5 +11,6 @@ void matrix_proj(MATRIX out, float fov, float ar, float near, float far); void matrix_tsp(MATRIX t); void vector_rotate_y(VECTOR out, float r); +void vector_sub(VECTOR out, VECTOR a, VECTOR b); #endif