checkpoint
This commit is contained in:
parent
f4a7739a40
commit
dbccd86622
@ -5,17 +5,18 @@
|
||||
#include "renderable.hpp"
|
||||
#include <tonc.h>
|
||||
|
||||
class ModelInstance : Renderable {
|
||||
class ModelInstance : public Renderable {
|
||||
private:
|
||||
std::shared_ptr<Mesh> 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<Mesh> m_mesh;
|
||||
|
||||
public:
|
||||
void render(std::shared_ptr<Scene> scene_context);
|
||||
ModelInstance(std::shared_ptr<Mesh> mesh, FIXED scale, VECTOR m_rotation,
|
||||
VECTOR m_pos);
|
||||
virtual void render(std::shared_ptr<Scene> scene_context);
|
||||
};
|
||||
|
||||
#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,
|
||||
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
|
||||
|
@ -7,7 +7,7 @@ class Scene;
|
||||
|
||||
class Renderable {
|
||||
public:
|
||||
virtual void render(std::shared_ptr<Scene> scene_context);
|
||||
virtual void render(std::shared_ptr<Scene> scene_context) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,13 +2,14 @@
|
||||
#define SCENE_HPP
|
||||
|
||||
#include "model_instance.hpp"
|
||||
#include "renderable.hpp"
|
||||
#include "vector.hpp"
|
||||
#include <cstdint>
|
||||
#include <tonc.h>
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
usu::vector<Renderable> renderables;
|
||||
usu::vector<std::shared_ptr<Renderable>> renderables;
|
||||
std::tuple<std::uint16_t, std::uint16_t>
|
||||
viewport_dimension; // <width, height>
|
||||
std::tuple<std::uint16_t, std::uint16_t> 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> scene_ctx) {
|
||||
for (std::shared_ptr<Renderable> renderable : scene_ctx->renderables)
|
||||
renderable->render(scene_ctx);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCENE_HPP
|
||||
|
13
src/cube.cpp
13
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});
|
||||
}
|
||||
|
30
src/main.cpp
30
src/main.cpp
@ -1,29 +1,33 @@
|
||||
#include "cube.hpp"
|
||||
#include "palette.hpp"
|
||||
#include "renderable.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "vector.hpp"
|
||||
#include <tonc.h>
|
||||
|
||||
class Box : public Renderable {
|
||||
public:
|
||||
virtual void render(std::shared_ptr<Scene> 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<Scene>();
|
||||
// auto cube = std::shared_ptr<Renderable>((Renderable *)new Cube());
|
||||
// scene->renderables.add(cube);
|
||||
auto box = std::shared_ptr<Renderable>((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();
|
||||
}
|
||||
|
@ -2,118 +2,9 @@
|
||||
#include "scene.hpp"
|
||||
#include <tuple>
|
||||
|
||||
/**
|
||||
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> 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> scene_context) {
|
||||
usu::vector<VECTOR> transformed(m_mesh->vertices.size());
|
||||
usu::vector<POINT> 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);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,13 @@
|
||||
#include "scene.hpp"
|
||||
#include <memory>
|
||||
|
||||
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<Scene>(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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user