commit
4dcdd32bf7
@ -14,9 +14,9 @@ typedef struct TRIANGLE {
|
|||||||
} TRIANGLE;
|
} TRIANGLE;
|
||||||
|
|
||||||
class Mesh {
|
class Mesh {
|
||||||
protected:
|
public:
|
||||||
usu::vector<VECTOR> m_vertices;
|
usu::vector<VECTOR> vertices;
|
||||||
usu::vector<TRIANGLE> m_triangles;
|
usu::vector<TRIANGLE> triangles;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESH_HPP
|
#endif // MESH_HPP
|
||||||
|
@ -5,13 +5,19 @@
|
|||||||
#include "renderable.hpp"
|
#include "renderable.hpp"
|
||||||
#include <tonc.h>
|
#include <tonc.h>
|
||||||
|
|
||||||
class ModelInstance : Renderable {
|
class ModelInstance : public Renderable {
|
||||||
private:
|
private:
|
||||||
|
std::shared_ptr<Mesh> m_mesh;
|
||||||
FIXED m_scale;
|
FIXED m_scale;
|
||||||
VECTOR m_rotation;
|
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;
|
VECTOR m_pos;
|
||||||
|
|
||||||
std::shared_ptr<Mesh> m_mesh;
|
public:
|
||||||
|
ModelInstance(std::shared_ptr<Mesh> mesh, FIXED scale, VECTOR m_rotation,
|
||||||
|
VECTOR m_pos);
|
||||||
|
void add_pos(VECTOR d_pos);
|
||||||
|
virtual void render(std::shared_ptr<Scene> scene_context);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MODEL_INSTANCE_HPP
|
#endif // MODEL_INSTANCE_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,
|
constexpr std::uint16_t cube_colors[6] = {CLR_WHITE, CLR_YELLOW, CLR_RED,
|
||||||
CLR_ORANGE, CLR_BLUE, CLR_GREEN};
|
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, 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
|
}; // namespace palette
|
||||||
|
|
||||||
#endif // PALETTE_HPP
|
#endif // PALETTE_HPP
|
||||||
|
@ -7,7 +7,7 @@ class Scene;
|
|||||||
|
|
||||||
class Renderable {
|
class Renderable {
|
||||||
public:
|
public:
|
||||||
virtual void render(std::shared_ptr<Scene> scene_context);
|
virtual void render(std::shared_ptr<Scene> scene_context) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
#ifndef CANVAS_HPP
|
#ifndef SCENE_HPP
|
||||||
#define CANVAS_HPP
|
#define SCENE_HPP
|
||||||
|
|
||||||
#include "mesh.hpp"
|
#include "model_instance.hpp"
|
||||||
|
#include "renderable.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <tonc.h>
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
private:
|
|
||||||
usu::vector<Mesh> meshes;
|
|
||||||
std::uint32_t width;
|
|
||||||
std::uint32_t height;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Scene();
|
usu::vector<std::shared_ptr<Renderable>> renderables;
|
||||||
|
std::tuple<std::uint32_t, std::uint32_t>
|
||||||
|
viewport_dimension; // <width, height>
|
||||||
|
std::tuple<std::uint32_t, std::uint32_t> scene_dimension;
|
||||||
|
VECTOR directional_light;
|
||||||
|
FIXED z_plane;
|
||||||
|
|
||||||
void render();
|
Scene();
|
||||||
|
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> scene_ctx) {
|
||||||
|
for (std::shared_ptr<Renderable> renderable : scene_ctx->renderables)
|
||||||
|
renderable->render(scene_ctx);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SCENE_HPP
|
#endif // SCENE_HPP
|
||||||
|
21
src/cube.cpp
21
src/cube.cpp
@ -1,6 +1,23 @@
|
|||||||
#include "cube.hpp"
|
#include "cube.hpp"
|
||||||
|
|
||||||
Cube::Cube() {
|
Cube::Cube() {
|
||||||
for (std::uint8_t i = 0; i < 8; ++i)
|
for (std::uint8_t i = 0; i < 8; ++i) {
|
||||||
m_vertices.add({(i >> 2) & 1, (i >> 1) & 1, i & 1});
|
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});
|
||||||
|
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});
|
||||||
}
|
}
|
||||||
|
27
src/main.cpp
27
src/main.cpp
@ -1,4 +1,7 @@
|
|||||||
|
#include "cube.hpp"
|
||||||
#include "palette.hpp"
|
#include "palette.hpp"
|
||||||
|
#include "renderable.hpp"
|
||||||
|
#include "scene.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include <tonc.h>
|
#include <tonc.h>
|
||||||
|
|
||||||
@ -7,23 +10,27 @@ int main() {
|
|||||||
irq_init(NULL);
|
irq_init(NULL);
|
||||||
irq_enable(II_VBLANK);
|
irq_enable(II_VBLANK);
|
||||||
REG_DISPCNT = DCNT_MODE4 | DCNT_BG2;
|
REG_DISPCNT = DCNT_MODE4 | DCNT_BG2;
|
||||||
|
|
||||||
// initialize our palette
|
|
||||||
palette::put_palette((std::uint16_t *)MEM_PAL);
|
palette::put_palette((std::uint16_t *)MEM_PAL);
|
||||||
|
|
||||||
// begin
|
auto scene = std::make_shared<Scene>();
|
||||||
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);
|
|
||||||
|
|
||||||
std::uint32_t frame = 0;
|
auto cube = std::shared_ptr<Mesh>((Mesh *)new Cube);
|
||||||
|
|
||||||
|
ModelInstance model_instance(cube, float2fx(0.25), {0, 0x0C00, 0},
|
||||||
|
{int2fx(3), int2fx(3), int2fx(3)});
|
||||||
|
|
||||||
|
auto model_instance_ptr = std::shared_ptr<Renderable>(&model_instance);
|
||||||
|
scene->renderables.add(model_instance_ptr);
|
||||||
|
|
||||||
|
std::uint8_t frame = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
frame = (frame + 1) % 60;
|
|
||||||
if (frame == 0) {
|
if (frame == 0) {
|
||||||
|
model_instance.add_pos({0, 0, float2fx(0.2)});
|
||||||
|
M4_CLEAR();
|
||||||
|
Scene::render(scene);
|
||||||
vid_flip();
|
vid_flip();
|
||||||
}
|
}
|
||||||
|
frame = (frame + 1) % 10;
|
||||||
|
|
||||||
VBlankIntrWait();
|
VBlankIntrWait();
|
||||||
}
|
}
|
||||||
|
11
src/mesh.hpp
11
src/mesh.hpp
@ -1,11 +0,0 @@
|
|||||||
#include "mesh.hpp"
|
|
||||||
#include "scene.hpp"
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
void Mesh::render(std::shared_ptr<Scene> 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)];
|
|
||||||
}
|
|
||||||
}
|
|
60
src/model_instance.cpp
Normal file
60
src/model_instance.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "model_instance.hpp"
|
||||||
|
#include "scene.hpp"
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
ModelInstance::ModelInstance(std::shared_ptr<Mesh> 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;
|
||||||
|
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 = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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> scene_context) {
|
||||||
|
usu::vector<POINT> projected(m_mesh->vertices.size());
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < projected.size(); i++) {
|
||||||
|
VECTOR transformed = rotate(m_mesh->vertices[i], m_rot);
|
||||||
|
vec_add(&transformed, &transformed, &m_pos);
|
||||||
|
|
||||||
|
projected[i] = scene_context->project_2d(transformed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const TRIANGLE triangle : m_mesh->triangles) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelInstance::add_pos(VECTOR d_pos) { vec_add(&m_pos, &m_pos, &d_pos); }
|
@ -0,0 +1,38 @@
|
|||||||
|
#include "scene.hpp"
|
||||||
|
|
||||||
|
Scene::Scene() {
|
||||||
|
directional_light = {0, 0, -1};
|
||||||
|
viewport_dimension = {3, 2};
|
||||||
|
scene_dimension = {SCREEN_WIDTH / 2, SCREEN_HEIGHT};
|
||||||
|
|
||||||
|
z_plane = int2fx(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
POINT Scene::viewport_to_scene(POINT p) {
|
||||||
|
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) {
|
||||||
|
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,
|
||||||
|
SCREEN_WIDTH);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user