From f4a7739a40c095e0c837d78d00f13a1ef47d3a11 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sat, 25 Nov 2023 17:05:01 -0700 Subject: [PATCH 1/4] cube foo init --- inc/mesh.hpp | 6 +- inc/model_instance.hpp | 6 +- inc/scene.hpp | 21 +++--- src/cube.cpp | 2 +- src/mesh.hpp | 11 --- src/model_instance.cpp | 161 +++++++++++++++++++++++++++++++++++++++++ src/scene.cpp | 29 ++++++++ 7 files changed, 211 insertions(+), 25 deletions(-) delete mode 100644 src/mesh.hpp create mode 100644 src/model_instance.cpp diff --git a/inc/mesh.hpp b/inc/mesh.hpp index db465fb..91fa500 100644 --- a/inc/mesh.hpp +++ b/inc/mesh.hpp @@ -14,9 +14,9 @@ typedef struct TRIANGLE { } TRIANGLE; class Mesh { -protected: - usu::vector m_vertices; - usu::vector m_triangles; +public: + usu::vector vertices; + usu::vector triangles; }; #endif // MESH_HPP diff --git a/inc/model_instance.hpp b/inc/model_instance.hpp index a8bbee0..059d3a5 100644 --- a/inc/model_instance.hpp +++ b/inc/model_instance.hpp @@ -8,10 +8,14 @@ class ModelInstance : Renderable { private: FIXED m_scale; - VECTOR m_rotation; + VECTOR m_rotation; // though technically "FIXED"'s, these are simply s32's + // where [0, 2pi] -> [0, 0xFFFF] in the x,y,z axes VECTOR m_pos; std::shared_ptr m_mesh; + +public: + void render(std::shared_ptr scene_context); }; #endif // MODEL_INSTANCE_HPP diff --git a/inc/scene.hpp b/inc/scene.hpp index f84bcd7..8e286db 100644 --- a/inc/scene.hpp +++ b/inc/scene.hpp @@ -1,20 +1,23 @@ -#ifndef CANVAS_HPP -#define CANVAS_HPP +#ifndef SCENE_HPP +#define SCENE_HPP -#include "mesh.hpp" +#include "model_instance.hpp" #include "vector.hpp" #include +#include class Scene { -private: - usu::vector meshes; - std::uint32_t width; - std::uint32_t height; - public: - Scene(); + usu::vector renderables; + std::tuple + viewport_dimension; // + std::tuple scene_dimension; + VECTOR directional_light; + FIXED z_plane; + Scene(); void render(); + POINT project_2d(VECTOR vertex); }; #endif // SCENE_HPP diff --git a/src/cube.cpp b/src/cube.cpp index fddc601..2fe855a 100644 --- a/src/cube.cpp +++ b/src/cube.cpp @@ -2,5 +2,5 @@ Cube::Cube() { for (std::uint8_t i = 0; i < 8; ++i) - m_vertices.add({(i >> 2) & 1, (i >> 1) & 1, i & 1}); + vertices.add({(i >> 2) & 1, (i >> 1) & 1, i & 1}); } diff --git a/src/mesh.hpp b/src/mesh.hpp deleted file mode 100644 index 55b414a..0000000 --- a/src/mesh.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "mesh.hpp" -#include "scene.hpp" -#include - -void Mesh::render(std::shared_ptr scene_context) { - for (const TRIANGLE triangle : m_triangles) { - VECTOR v0 = m_vertices[std::get<0>(triangle.vertex_indices)]; - VECTOR v1 = m_vertices[std::get<1>(triangle.vertex_indices)]; - VECTOR v2 = m_vertices[std::get<2>(triangle.vertex_indices)]; - } -} diff --git a/src/model_instance.cpp b/src/model_instance.cpp new file mode 100644 index 0000000..48703a5 --- /dev/null +++ b/src/model_instance.cpp @@ -0,0 +1,161 @@ +#include "model_instance.hpp" +#include "scene.hpp" +#include + +/** +static inline POINT viewportToScreen (POINT *point) { + // Convert a viewport coordinate to screen x, y + return createPoint(fixed_multiply(point->x, fixed_divide(WINDOW_WIDTH << +FIX_SHIFT, viewport_width << FIX_SHIFT)), fixed_multiply(point->y, +fixed_divide(WINDOW_HEIGHT << FIX_SHIFT, viewport_height << FIX_SHIFT)) + ); +} + +static inline POINT projectVertex(VERTEX *vertex) { + // Project a vertex to a point + POINT temp; + if (vertex->z != 0) { + // Make sure we don't divide by zero + temp = createPoint(fixed_multiply(vertex->x, fixed_divide(ZPlane << +FIX_SHIFT, vertex->z)), fixed_multiply(vertex->y, fixed_divide(ZPlane << +FIX_SHIFT, vertex->z)) + ); + } + else { + temp = createPoint(0, 0); + } + temp = viewportToScreen(&temp); + return temp; +} + +void renderInstance(INSTANCE *instance, SDL_Renderer *renderer) { + // Render an instance + // Array for projected points + POINT projected[instance->model->vertices_length]; + // Pointers for transformed vertices + VERTEX *transformed = malloc(sizeof(VERTEX) * +instance->model->vertices_length); + + for (int i = 0; i < instance->model->vertices_length; i++) { + // Apply translation and rotation + *(transformed + i) = *(instance->model->vertices + i); + applyXRotation((transformed + i), *instance->xRotation); + applyYRotation((transformed + i), *instance->yRotation); + applyZRotation((transformed + i), *instance->zRotation); + *(transformed + i) = addVertices((transformed + i), +instance->position); + // Project vertices + projected[i] = projectVertex(transformed + i); + } + VERTEX n, copyV; + // A directional light source + VERTEX playerLight = createVertex(0, 0, -1 << FIX_SHIFT); + normalizeVertex(&playerLight); + TRIANGLE *addr; + FIXED intensity; + COLOR clr; + for (int i = 0; i < instance->model->triangles_length; i++) { + // Render the triangle + addr = (instance->model->triangles + i); + n = computeNormal(transformed, addr); + normalizeVertex(&n); + // Intensity of light on the triangle + intensity = fixed_multiply(dotProduct(&n, &playerLight) + (1 << +FIX_SHIFT), 127 << FIX_SHIFT); copyV = *(transformed + addr->v2); + normalizeVertex(©V); + + // Grayscale color of the triangle from light intensity + clr = createColor(intensity >> FIX_SHIFT, intensity >> FIX_SHIFT, +intensity >> FIX_SHIFT); + + if (dotProduct(&n, ©V) < 0) { + // The triangle is viewable by the camera + drawFilledTriangle( + &(projected[addr->v0]), + &(projected[addr->v1]), + &(projected[addr->v2]), + &clr, + renderer + ); + + } + } + transformed = NULL; + free(transformed); + + + + + static inline void applyXRotation(VERTEX *vertex, FIXED xRotation) { + // Apply rotation to vertex on x-axis + FIXED sinTheta = float_to_fixed(sin(fixed_to_float(xRotation) * (3.14159 / +180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(xRotation) * (3.14159 +/ 180))); FIXED y = vertex->y; FIXED z = vertex->z; vertex->y = +fixed_multiply(y, cosTheta) - fixed_multiply(z, sinTheta); vertex->z = +fixed_multiply(z, cosTheta) + fixed_multiply(y, sinTheta); +} + +static inline void applyYRotation(VERTEX *vertex, FIXED yRotation) { + // Apply rotation to vertex on y-axis + FIXED sinTheta = float_to_fixed(sin(fixed_to_float(yRotation) * (3.14159 / +180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(yRotation) * (3.14159 +/ 180))); FIXED x = vertex->x; FIXED z = vertex->z; vertex->x = +fixed_multiply(x, cosTheta) + fixed_multiply(z, sinTheta); vertex->z = +fixed_multiply(z, cosTheta) - fixed_multiply(x, sinTheta); +} + +static inline void applyZRotation(VERTEX *vertex, FIXED zRotation) { + // Apply rotation to vertex on z-axis + FIXED sinTheta = float_to_fixed(sin(fixed_to_float(zRotation) * (3.14159 / +180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(zRotation) * (3.14159 +/ 180))); FIXED x = vertex->x; FIXED y = vertex->y; vertex->x = +fixed_multiply(x, cosTheta) - fixed_multiply(y, sinTheta); vertex->y = +fixed_multiply(y, cosTheta) + fixed_multiply(x, sinTheta); +} +} + */ + +VECTOR rotate(VECTOR v, VECTOR rot) { + FIXED sin_theta_x, sin_theta_y, sin_theta_z; + FIXED cos_theta_x, cos_theta_y, cos_theta_z; + VECTOR res = {v.x, v.y, v.z}; + + if (rot.x != 0) { + sin_theta_x = lu_sin(rot.x) >> 4; + cos_theta_x = lu_cos(rot.x) >> 4; + res.y = fxmul(res.y, cos_theta_x) - fxmul(res.z, sin_theta_x); + res.z = fxmul(res.z, cos_theta_x) + fxmul(res.y, sin_theta_x); + } + + if (rot.y != 0) { + sin_theta_y = lu_sin(rot.y) >> 4; + cos_theta_y = lu_cos(rot.y) >> 4; + res.x = fxmul(res.x, cos_theta_y) + fxmul(res.z, sin_theta_y); + res.z = fxmul(res.z, cos_theta_y) - fxmul(res.x, sin_theta_y); + } + + if (rot.z != 0) { + sin_theta_z = lu_sin(rot.z) >> 4; + cos_theta_z = lu_cos(rot.z) >> 4; + res.x = fxmul(res.x, cos_theta_z) - fxmul(res.y, sin_theta_z); + res.y = fxmul(res.z, cos_theta_z) + fxmul(res.x, sin_theta_z); + } + + return res; +}; + +void ModelInstance::render(std::shared_ptr scene_context) { + usu::vector transformed(m_mesh->vertices.size()); + usu::vector projected(transformed.size()); + + for (std::uint32_t i = 0; i < transformed.size(); i++) { + transformed[i] = rotate(m_mesh->vertices[i], m_rotation); + projected[i] = scene_context->project_2d(m_mesh->vertices[i]); + } + + for (const TRIANGLE triangle : m_mesh->triangles) { + VECTOR v0 = transformed[std::get<0>(triangle.vertex_indices)]; + VECTOR v1 = transformed[std::get<1>(triangle.vertex_indices)]; + VECTOR v2 = transformed[std::get<2>(triangle.vertex_indices)]; + } +} diff --git a/src/scene.cpp b/src/scene.cpp index e69de29..b52553a 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -0,0 +1,29 @@ +#include "scene.hpp" +#include + +Scene::Scene() { + directional_light = {0, 0, -1}; + viewport_dimension = {2, 3}; + scene_dimension = {SCREEN_WIDTH, SCREEN_HEIGHT}; + + z_plane = int2fx(1); +} + +void Scene::render() { + auto this_ptr = std::make_shared(this); + for (auto renderable : renderables) { + renderable.render(this_ptr); + } +} + +POINT Scene::project_2d(VECTOR vertex) { + POINT pt = {0, 0}; + + if (vertex.z != 0) { + pt.x = fxdiv(z_plane, vertex.z); + pt.y = fxmul(vertex.y, pt.x); + pt.x = fxmul(vertex.x, pt.x); + } + + return pt; +} From dbccd866229a4b06d10fbafc3eb3343015caedba Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 26 Nov 2023 16:09:41 -0700 Subject: [PATCH 2/4] checkpoint --- inc/model_instance.hpp | 13 ++-- inc/palette.hpp | 7 ++- inc/renderable.hpp | 2 +- inc/scene.hpp | 10 +++- src/cube.cpp | 13 ++++ src/main.cpp | 30 ++++++---- src/model_instance.cpp | 131 +++++------------------------------------ src/scene.cpp | 29 ++++++--- 8 files changed, 84 insertions(+), 151 deletions(-) diff --git a/inc/model_instance.hpp b/inc/model_instance.hpp index 059d3a5..997e9a6 100644 --- a/inc/model_instance.hpp +++ b/inc/model_instance.hpp @@ -5,17 +5,18 @@ #include "renderable.hpp" #include -class ModelInstance : Renderable { +class ModelInstance : public Renderable { private: + std::shared_ptr m_mesh; FIXED m_scale; - VECTOR m_rotation; // though technically "FIXED"'s, these are simply s32's - // where [0, 2pi] -> [0, 0xFFFF] in the x,y,z axes + VECTOR m_rot; // though technically "FIXED"'s, these are simply s32's + // where [0, 2pi] -> [0, 0xFFFF] in the x,y,z axes VECTOR m_pos; - std::shared_ptr m_mesh; - public: - void render(std::shared_ptr scene_context); + ModelInstance(std::shared_ptr mesh, FIXED scale, VECTOR m_rotation, + VECTOR m_pos); + virtual void render(std::shared_ptr scene_context); }; #endif // MODEL_INSTANCE_HPP diff --git a/inc/palette.hpp b/inc/palette.hpp index 1850835..e45e9cf 100644 --- a/inc/palette.hpp +++ b/inc/palette.hpp @@ -10,11 +10,12 @@ constexpr std::uint8_t pal_len = 255; constexpr std::uint16_t cube_colors[6] = {CLR_WHITE, CLR_YELLOW, CLR_RED, CLR_ORANGE, CLR_BLUE, CLR_GREEN}; -constexpr void put_palette(std::uint16_t *palette_address) { +void put_palette(std::uint16_t *palette_address) { toncset16(palette_address, CLR_BLACK, 1); - toncset16(palette_address + 1, CLR_WHITE, 1); + for (std::uint32_t i = 0; i < 6; ++i) + toncset16(palette_address + i + 1, cube_colors[i], 1); + // TODO: PALETTE GRADIENT IN ALPHA DIMENSION (BRIGHTNESS) } - }; // namespace palette #endif // PALETTE_HPP diff --git a/inc/renderable.hpp b/inc/renderable.hpp index 7f72e51..83b7596 100644 --- a/inc/renderable.hpp +++ b/inc/renderable.hpp @@ -7,7 +7,7 @@ class Scene; class Renderable { public: - virtual void render(std::shared_ptr scene_context); + virtual void render(std::shared_ptr scene_context) = 0; }; #endif diff --git a/inc/scene.hpp b/inc/scene.hpp index 8e286db..05cdac0 100644 --- a/inc/scene.hpp +++ b/inc/scene.hpp @@ -2,13 +2,14 @@ #define SCENE_HPP #include "model_instance.hpp" +#include "renderable.hpp" #include "vector.hpp" #include #include class Scene { public: - usu::vector renderables; + usu::vector> renderables; std::tuple viewport_dimension; // std::tuple scene_dimension; @@ -16,8 +17,13 @@ public: FIXED z_plane; Scene(); - void render(); POINT project_2d(VECTOR vertex); + POINT viewport_to_scene(POINT p); + void draw_line(POINT p0, POINT p1, std::uint8_t pal_idx); + static inline void render(std::shared_ptr scene_ctx) { + for (std::shared_ptr renderable : scene_ctx->renderables) + renderable->render(scene_ctx); + } }; #endif // SCENE_HPP diff --git a/src/cube.cpp b/src/cube.cpp index 2fe855a..c181794 100644 --- a/src/cube.cpp +++ b/src/cube.cpp @@ -3,4 +3,17 @@ Cube::Cube() { for (std::uint8_t i = 0; i < 8; ++i) vertices.add({(i >> 2) & 1, (i >> 1) & 1, i & 1}); + + triangles.add({{0, 4, 5}, 1}); + triangles.add({{0, 1, 5}, 1}); + triangles.add({{4, 6, 7}, 1}); + triangles.add({{4, 5, 7}, 1}); + triangles.add({{1, 5, 7}, 1}); + triangles.add({{1, 3, 7}, 1}); + triangles.add({{0, 4, 6}, 1}); + triangles.add({{0, 2, 6}, 1}); + triangles.add({{0, 2, 1}, 1}); + triangles.add({{1, 2, 3}, 1}); + triangles.add({{2, 7, 3}, 1}); + triangles.add({{2, 5, 7}, 1}); } diff --git a/src/main.cpp b/src/main.cpp index f147f2f..0c91536 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,29 +1,33 @@ +#include "cube.hpp" #include "palette.hpp" +#include "renderable.hpp" +#include "scene.hpp" #include "vector.hpp" #include +class Box : public Renderable { +public: + virtual void render(std::shared_ptr scene) { + scene->draw_line({0, 0}, {2 << FIX_SHIFT, 3 << FIX_SHIFT}, 1); + } +}; + int main() { // interrupt & mode 4 foo irq_init(NULL); irq_enable(II_VBLANK); REG_DISPCNT = DCNT_MODE4 | DCNT_BG2; - - // initialize our palette palette::put_palette((std::uint16_t *)MEM_PAL); - // begin - bmp16_line(1, 3, 1 + SCREEN_WIDTH / 2 - 2, SCREEN_HEIGHT, 0x0101, vid_page, - SCREEN_WIDTH); - vid_flip(); - bmp16_line(2, 3, 2 + SCREEN_WIDTH / 2 - 2, SCREEN_HEIGHT, 0x0101, vid_page, - SCREEN_WIDTH); + auto scene = std::make_shared(); + // auto cube = std::shared_ptr((Renderable *)new Cube()); + // scene->renderables.add(cube); + auto box = std::shared_ptr((Renderable *)new Box()); + + scene->renderables.add(box); - std::uint32_t frame = 0; while (1) { - frame = (frame + 1) % 60; - if (frame == 0) { - vid_flip(); - } + Scene::render(scene); VBlankIntrWait(); } diff --git a/src/model_instance.cpp b/src/model_instance.cpp index 48703a5..65ed6a8 100644 --- a/src/model_instance.cpp +++ b/src/model_instance.cpp @@ -2,118 +2,9 @@ #include "scene.hpp" #include -/** -static inline POINT viewportToScreen (POINT *point) { - // Convert a viewport coordinate to screen x, y - return createPoint(fixed_multiply(point->x, fixed_divide(WINDOW_WIDTH << -FIX_SHIFT, viewport_width << FIX_SHIFT)), fixed_multiply(point->y, -fixed_divide(WINDOW_HEIGHT << FIX_SHIFT, viewport_height << FIX_SHIFT)) - ); -} - -static inline POINT projectVertex(VERTEX *vertex) { - // Project a vertex to a point - POINT temp; - if (vertex->z != 0) { - // Make sure we don't divide by zero - temp = createPoint(fixed_multiply(vertex->x, fixed_divide(ZPlane << -FIX_SHIFT, vertex->z)), fixed_multiply(vertex->y, fixed_divide(ZPlane << -FIX_SHIFT, vertex->z)) - ); - } - else { - temp = createPoint(0, 0); - } - temp = viewportToScreen(&temp); - return temp; -} - -void renderInstance(INSTANCE *instance, SDL_Renderer *renderer) { - // Render an instance - // Array for projected points - POINT projected[instance->model->vertices_length]; - // Pointers for transformed vertices - VERTEX *transformed = malloc(sizeof(VERTEX) * -instance->model->vertices_length); - - for (int i = 0; i < instance->model->vertices_length; i++) { - // Apply translation and rotation - *(transformed + i) = *(instance->model->vertices + i); - applyXRotation((transformed + i), *instance->xRotation); - applyYRotation((transformed + i), *instance->yRotation); - applyZRotation((transformed + i), *instance->zRotation); - *(transformed + i) = addVertices((transformed + i), -instance->position); - // Project vertices - projected[i] = projectVertex(transformed + i); - } - VERTEX n, copyV; - // A directional light source - VERTEX playerLight = createVertex(0, 0, -1 << FIX_SHIFT); - normalizeVertex(&playerLight); - TRIANGLE *addr; - FIXED intensity; - COLOR clr; - for (int i = 0; i < instance->model->triangles_length; i++) { - // Render the triangle - addr = (instance->model->triangles + i); - n = computeNormal(transformed, addr); - normalizeVertex(&n); - // Intensity of light on the triangle - intensity = fixed_multiply(dotProduct(&n, &playerLight) + (1 << -FIX_SHIFT), 127 << FIX_SHIFT); copyV = *(transformed + addr->v2); - normalizeVertex(©V); - - // Grayscale color of the triangle from light intensity - clr = createColor(intensity >> FIX_SHIFT, intensity >> FIX_SHIFT, -intensity >> FIX_SHIFT); - - if (dotProduct(&n, ©V) < 0) { - // The triangle is viewable by the camera - drawFilledTriangle( - &(projected[addr->v0]), - &(projected[addr->v1]), - &(projected[addr->v2]), - &clr, - renderer - ); - - } - } - transformed = NULL; - free(transformed); - - - - - static inline void applyXRotation(VERTEX *vertex, FIXED xRotation) { - // Apply rotation to vertex on x-axis - FIXED sinTheta = float_to_fixed(sin(fixed_to_float(xRotation) * (3.14159 / -180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(xRotation) * (3.14159 -/ 180))); FIXED y = vertex->y; FIXED z = vertex->z; vertex->y = -fixed_multiply(y, cosTheta) - fixed_multiply(z, sinTheta); vertex->z = -fixed_multiply(z, cosTheta) + fixed_multiply(y, sinTheta); -} - -static inline void applyYRotation(VERTEX *vertex, FIXED yRotation) { - // Apply rotation to vertex on y-axis - FIXED sinTheta = float_to_fixed(sin(fixed_to_float(yRotation) * (3.14159 / -180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(yRotation) * (3.14159 -/ 180))); FIXED x = vertex->x; FIXED z = vertex->z; vertex->x = -fixed_multiply(x, cosTheta) + fixed_multiply(z, sinTheta); vertex->z = -fixed_multiply(z, cosTheta) - fixed_multiply(x, sinTheta); -} - -static inline void applyZRotation(VERTEX *vertex, FIXED zRotation) { - // Apply rotation to vertex on z-axis - FIXED sinTheta = float_to_fixed(sin(fixed_to_float(zRotation) * (3.14159 / -180))); FIXED cosTheta = float_to_fixed(cos(fixed_to_float(zRotation) * (3.14159 -/ 180))); FIXED x = vertex->x; FIXED y = vertex->y; vertex->x = -fixed_multiply(x, cosTheta) - fixed_multiply(y, sinTheta); vertex->y = -fixed_multiply(y, cosTheta) + fixed_multiply(x, sinTheta); -} -} - */ +ModelInstance::ModelInstance(std::shared_ptr mesh, FIXED scale, + VECTOR rotation, VECTOR position) + : m_mesh(mesh), m_scale(scale), m_rot(rotation), m_pos(position) {} VECTOR rotate(VECTOR v, VECTOR rot) { FIXED sin_theta_x, sin_theta_y, sin_theta_z; @@ -142,20 +33,26 @@ VECTOR rotate(VECTOR v, VECTOR rot) { } return res; -}; +} void ModelInstance::render(std::shared_ptr scene_context) { usu::vector transformed(m_mesh->vertices.size()); usu::vector projected(transformed.size()); for (std::uint32_t i = 0; i < transformed.size(); i++) { - transformed[i] = rotate(m_mesh->vertices[i], m_rotation); + VECTOR rotated = rotate(m_mesh->vertices[i], m_rot); + vec_add(&transformed[i], &rotated, &m_pos); + projected[i] = scene_context->project_2d(m_mesh->vertices[i]); } for (const TRIANGLE triangle : m_mesh->triangles) { - VECTOR v0 = transformed[std::get<0>(triangle.vertex_indices)]; - VECTOR v1 = transformed[std::get<1>(triangle.vertex_indices)]; - VECTOR v2 = transformed[std::get<2>(triangle.vertex_indices)]; + POINT v0 = projected[std::get<0>(triangle.vertex_indices)]; + POINT v1 = projected[std::get<1>(triangle.vertex_indices)]; + POINT v2 = projected[std::get<2>(triangle.vertex_indices)]; + + scene_context->draw_line(v0, v1, triangle.color_idx); + scene_context->draw_line(v1, v2, triangle.color_idx); + scene_context->draw_line(v2, v0, triangle.color_idx); } } diff --git a/src/scene.cpp b/src/scene.cpp index b52553a..f69398d 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -1,21 +1,13 @@ #include "scene.hpp" -#include Scene::Scene() { directional_light = {0, 0, -1}; viewport_dimension = {2, 3}; - scene_dimension = {SCREEN_WIDTH, SCREEN_HEIGHT}; + scene_dimension = {SCREEN_WIDTH / 2, SCREEN_HEIGHT}; z_plane = int2fx(1); } -void Scene::render() { - auto this_ptr = std::make_shared(this); - for (auto renderable : renderables) { - renderable.render(this_ptr); - } -} - POINT Scene::project_2d(VECTOR vertex) { POINT pt = {0, 0}; @@ -27,3 +19,22 @@ POINT Scene::project_2d(VECTOR vertex) { return pt; } + +POINT Scene::viewport_to_scene(POINT p) { + FIXED x = fxmul( + p.x, (std::get<0>(scene_dimension) / std::get<0>(viewport_dimension)) + << FIX_SHIFT); + FIXED y = fxmul( + p.y, (std::get<1>(scene_dimension) / std::get<1>(viewport_dimension)) + << FIX_SHIFT); + return {x, y}; +} + +void Scene::draw_line(POINT p0, POINT p1, std::uint8_t pal_idx) { + POINT scene_p0 = viewport_to_scene(p0); + POINT scene_p1 = viewport_to_scene(p1); + + std::uint16_t pixels = (pal_idx << 8) | pal_idx; + bmp16_line(scene_p0.x, scene_p0.y, scene_p1.x, scene_p1.y, pixels, vid_page, + M4_WIDTH); +} From 1b96b0211ed98afba515f0ac9880116f79ead2e5 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Tue, 28 Nov 2023 13:58:18 -0700 Subject: [PATCH 3/4] render the front face of a cube --- inc/scene.hpp | 4 ++-- src/main.cpp | 20 +++++++++----------- src/model_instance.cpp | 17 +++++++++-------- src/scene.cpp | 16 +++++++--------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/inc/scene.hpp b/inc/scene.hpp index 05cdac0..6dd4c35 100644 --- a/inc/scene.hpp +++ b/inc/scene.hpp @@ -10,9 +10,9 @@ class Scene { public: usu::vector> renderables; - std::tuple + std::tuple viewport_dimension; // - std::tuple scene_dimension; + std::tuple scene_dimension; VECTOR directional_light; FIXED z_plane; diff --git a/src/main.cpp b/src/main.cpp index 0c91536..c08b584 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,13 +5,6 @@ #include "vector.hpp" #include -class Box : public Renderable { -public: - virtual void render(std::shared_ptr scene) { - scene->draw_line({0, 0}, {2 << FIX_SHIFT, 3 << FIX_SHIFT}, 1); - } -}; - int main() { // interrupt & mode 4 foo irq_init(NULL); @@ -20,14 +13,19 @@ int main() { palette::put_palette((std::uint16_t *)MEM_PAL); auto scene = std::make_shared(); - // auto cube = std::shared_ptr((Renderable *)new Cube()); - // scene->renderables.add(cube); - auto box = std::shared_ptr((Renderable *)new Box()); - scene->renderables.add(box); + auto cube = std::shared_ptr((Mesh *)new Cube); + + ModelInstance modelInstance(cube, int2fx(2), {0x0C7F, 0x0000, 0}, + {int2fx(0), 0, int2fx(0)}); + + auto modelInstancePtr = std::shared_ptr(&modelInstance); + scene->renderables.add(modelInstancePtr); while (1) { + Scene::render(scene); + vid_flip(); VBlankIntrWait(); } diff --git a/src/model_instance.cpp b/src/model_instance.cpp index 65ed6a8..61204ff 100644 --- a/src/model_instance.cpp +++ b/src/model_instance.cpp @@ -9,11 +9,12 @@ ModelInstance::ModelInstance(std::shared_ptr mesh, FIXED scale, VECTOR rotate(VECTOR v, VECTOR rot) { FIXED sin_theta_x, sin_theta_y, sin_theta_z; FIXED cos_theta_x, cos_theta_y, cos_theta_z; + VECTOR res = {v.x, v.y, v.z}; if (rot.x != 0) { - sin_theta_x = lu_sin(rot.x) >> 4; - cos_theta_x = lu_cos(rot.x) >> 4; + sin_theta_x = float2fx(0.707); // lu_sin(rot.x) >> 4; + cos_theta_x = float2fx(0.707); // lu_cos(rot.x) >> 4; res.y = fxmul(res.y, cos_theta_x) - fxmul(res.z, sin_theta_x); res.z = fxmul(res.z, cos_theta_x) + fxmul(res.y, sin_theta_x); } @@ -36,14 +37,14 @@ VECTOR rotate(VECTOR v, VECTOR rot) { } void ModelInstance::render(std::shared_ptr scene_context) { - usu::vector transformed(m_mesh->vertices.size()); - usu::vector projected(transformed.size()); + usu::vector projected(m_mesh->vertices.size()); - for (std::uint32_t i = 0; i < transformed.size(); i++) { - VECTOR rotated = rotate(m_mesh->vertices[i], m_rot); - vec_add(&transformed[i], &rotated, &m_pos); + for (std::uint32_t i = 0; i < projected.size(); i++) { + VECTOR transformed = + m_mesh->vertices[i]; // rotate(m_mesh->vertices[i], m_rot); + // vec_add(&transformed, &transformed, &m_pos); - projected[i] = scene_context->project_2d(m_mesh->vertices[i]); + projected[i] = scene_context->project_2d(transformed); } for (const TRIANGLE triangle : m_mesh->triangles) { diff --git a/src/scene.cpp b/src/scene.cpp index f69398d..44e7028 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -2,7 +2,7 @@ Scene::Scene() { directional_light = {0, 0, -1}; - viewport_dimension = {2, 3}; + viewport_dimension = {3, 2}; scene_dimension = {SCREEN_WIDTH / 2, SCREEN_HEIGHT}; z_plane = int2fx(1); @@ -21,13 +21,11 @@ POINT Scene::project_2d(VECTOR vertex) { } POINT Scene::viewport_to_scene(POINT p) { - FIXED x = fxmul( - p.x, (std::get<0>(scene_dimension) / std::get<0>(viewport_dimension)) - << FIX_SHIFT); - FIXED y = fxmul( - p.y, (std::get<1>(scene_dimension) / std::get<1>(viewport_dimension)) - << FIX_SHIFT); - return {x, y}; + FIXED x = fxmul(p.x, int2fx(std::get<0>(scene_dimension) / + std::get<0>(viewport_dimension))); + FIXED y = fxmul(p.y, int2fx(std::get<1>(scene_dimension) / + std::get<1>(viewport_dimension))); + return {x >> FIX_SHIFT, y >> FIX_SHIFT}; } void Scene::draw_line(POINT p0, POINT p1, std::uint8_t pal_idx) { @@ -36,5 +34,5 @@ void Scene::draw_line(POINT p0, POINT p1, std::uint8_t pal_idx) { std::uint16_t pixels = (pal_idx << 8) | pal_idx; bmp16_line(scene_p0.x, scene_p0.y, scene_p1.x, scene_p1.y, pixels, vid_page, - M4_WIDTH); + SCREEN_WIDTH); } From 3197f9e40cd7079e19990c64c98de667e2457d75 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Tue, 28 Nov 2023 14:39:20 -0700 Subject: [PATCH 4/4] draw the whole cube --- inc/model_instance.hpp | 1 + src/cube.cpp | 8 ++++++-- src/main.cpp | 19 ++++++++++++------- src/model_instance.cpp | 7 ++++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/inc/model_instance.hpp b/inc/model_instance.hpp index 997e9a6..8126278 100644 --- a/inc/model_instance.hpp +++ b/inc/model_instance.hpp @@ -16,6 +16,7 @@ private: public: ModelInstance(std::shared_ptr mesh, FIXED scale, VECTOR m_rotation, VECTOR m_pos); + void add_pos(VECTOR d_pos); virtual void render(std::shared_ptr scene_context); }; diff --git a/src/cube.cpp b/src/cube.cpp index c181794..60422a2 100644 --- a/src/cube.cpp +++ b/src/cube.cpp @@ -1,8 +1,12 @@ #include "cube.hpp" Cube::Cube() { - for (std::uint8_t i = 0; i < 8; ++i) - vertices.add({(i >> 2) & 1, (i >> 1) & 1, i & 1}); + for (std::uint8_t i = 0; i < 8; ++i) { + VECTOR vertex = {int2fx((((i >> 2) & 1) << 1) - 1), + int2fx((((i >> 1) & 1) << 1) - 1), + int2fx(((i & 1) << 1) - 1)}; + vertices.add(vertex); + } triangles.add({{0, 4, 5}, 1}); triangles.add({{0, 1, 5}, 1}); diff --git a/src/main.cpp b/src/main.cpp index c08b584..cc21223 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,16 +16,21 @@ int main() { auto cube = std::shared_ptr((Mesh *)new Cube); - ModelInstance modelInstance(cube, int2fx(2), {0x0C7F, 0x0000, 0}, - {int2fx(0), 0, int2fx(0)}); + ModelInstance model_instance(cube, float2fx(0.25), {0, 0x0C00, 0}, + {int2fx(3), int2fx(3), int2fx(3)}); - auto modelInstancePtr = std::shared_ptr(&modelInstance); - scene->renderables.add(modelInstancePtr); + auto model_instance_ptr = std::shared_ptr(&model_instance); + scene->renderables.add(model_instance_ptr); + std::uint8_t frame = 0; while (1) { - - Scene::render(scene); - vid_flip(); + if (frame == 0) { + model_instance.add_pos({0, 0, float2fx(0.2)}); + M4_CLEAR(); + Scene::render(scene); + vid_flip(); + } + frame = (frame + 1) % 10; VBlankIntrWait(); } diff --git a/src/model_instance.cpp b/src/model_instance.cpp index 61204ff..db28243 100644 --- a/src/model_instance.cpp +++ b/src/model_instance.cpp @@ -40,9 +40,8 @@ void ModelInstance::render(std::shared_ptr scene_context) { usu::vector projected(m_mesh->vertices.size()); for (std::uint32_t i = 0; i < projected.size(); i++) { - VECTOR transformed = - m_mesh->vertices[i]; // rotate(m_mesh->vertices[i], m_rot); - // vec_add(&transformed, &transformed, &m_pos); + VECTOR transformed = rotate(m_mesh->vertices[i], m_rot); + vec_add(&transformed, &transformed, &m_pos); projected[i] = scene_context->project_2d(transformed); } @@ -57,3 +56,5 @@ void ModelInstance::render(std::shared_ptr scene_context) { scene_context->draw_line(v2, v0, triangle.color_idx); } } + +void ModelInstance::add_pos(VECTOR d_pos) { vec_add(&m_pos, &m_pos, &d_pos); }