diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | src/engine.cpp | 18 | ||||
-rw-r--r-- | src/fb/chfb.cpp | 1 | ||||
-rw-r--r-- | src/o3d/deriv_vertex.cpp | 6 | ||||
-rw-r--r-- | src/o3d/deriv_vertex.h | 8 | ||||
-rw-r--r-- | src/o3d/mesh.cpp | 28 | ||||
-rw-r--r-- | src/o3d/mesh.h | 15 | ||||
-rw-r--r-- | src/o3d/tri.cpp | 10 | ||||
-rw-r--r-- | src/o3d/tri.h | 21 | ||||
-rw-r--r-- | src/o3d/tri_deriv.cpp | 138 | ||||
-rw-r--r-- | src/o3d/tri_deriv.h | 22 | ||||
-rw-r--r-- | src/o3d/vertex.cpp | 9 | ||||
-rw-r--r-- | src/o3d/vertex.h | 16 | ||||
-rw-r--r-- | src/renderer.cpp | 178 | ||||
-rw-r--r-- | src/renderer.h | 7 |
15 files changed, 237 insertions, 244 deletions
diff --git a/Makefile.am b/Makefile.am index 91513f7..ac2c3b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,8 +17,8 @@ engine_SOURCES = \ src/o3d/vertex_data.h src/o3d/vertex_data.cpp \ src/o3d/vertex.h src/o3d/vertex.cpp \ src/o3d/deriv_vertex.h src/o3d/deriv_vertex.cpp \ - src/o3d/tri_vertex.h src/o3d/tri_vertex.cpp \ - src/o3d/tri_deriv_vertex.h src/o3d/tri_deriv_vertex.cpp \ + src/o3d/tri.h src/o3d/tri.cpp \ + src/o3d/tri_deriv.h src/o3d/tri_deriv.cpp \ src/o3d/camera.h src/o3d/camera.cpp \ src/o3d/scene.h src/o3d/scene.cpp engine_CPPFLAGS = -Wall -Wextra $(DEPS_CPPFLAGS) diff --git a/src/engine.cpp b/src/engine.cpp index 96dfd7b..e8cde92 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -23,9 +23,8 @@ #include "o3d/scene.h" #include "o3d/mesh.h" #include "o3d/obj3d.h" -#include "o3d/vertex.h" #include "o3d/vertex_data.h" -#include "o3d/tri_vertex.h" +#include "o3d/tri.h" #include "o3d/camera.h" #include "math/vector.h" #include "math/mat4.h" @@ -87,11 +86,16 @@ static void scene_main(engine::Renderer& renderer, engine::math::Matrix4 final_t for (int i = 0; i < 1; i++) { auto final_mat = pre_final_mat * mats[i]; const auto& mesh = scene.objs[i].mesh; - std::vector<engine::o3d::Vertex4> pts; - for (const auto& vert : mesh.pts) - pts.push_back({ final_mat * engine::math::Vector4{vert.point}, vert.data }); - for (auto face : mesh.faces) - renderer.draw_triangle({pts[face[0]], pts[face[1]], pts[face[2]]}); + std::vector<engine::math::Vector4> vertices; + for (const auto& vertex : mesh.vertices) + vertices.push_back(final_mat * vertex); + for (auto triangle_indices : mesh.indices) { + renderer.draw_triangle({ + {vertices[triangle_indices[0][0]], mesh.normals[triangle_indices[0][1]], mesh.vertices_data[triangle_indices[0][2]]}, + {vertices[triangle_indices[1][0]], mesh.normals[triangle_indices[1][1]], mesh.vertices_data[triangle_indices[1][2]]}, + {vertices[triangle_indices[2][0]], mesh.normals[triangle_indices[2][1]], mesh.vertices_data[triangle_indices[2][2]]}, + }); + } } cont = update_frame(); } diff --git a/src/fb/chfb.cpp b/src/fb/chfb.cpp index e3c0cf1..029d619 100644 --- a/src/fb/chfb.cpp +++ b/src/fb/chfb.cpp @@ -33,6 +33,7 @@ void CharacterFrameBuffer::clear() { } void CharacterFrameBuffer::draw_point(int x, int y, engine::math::Vector3 loc, const engine::o3d::VertexData& vd) { + (void) loc; (void) vd; chars_vector[x + y * w] = face_char(0); } diff --git a/src/o3d/deriv_vertex.cpp b/src/o3d/deriv_vertex.cpp index dcb2bff..7123b1c 100644 --- a/src/o3d/deriv_vertex.cpp +++ b/src/o3d/deriv_vertex.cpp @@ -3,9 +3,9 @@ using namespace engine::o3d; -DerivedVertex4::DerivedVertex4(engine::math::Vector4 point, float b0, float b1) : point{point}, b0{b0}, b1{b1} { +DerivedVertex::DerivedVertex(engine::math::Vector4 vertex, float b0, float b1) : vertex{vertex}, b0{b0}, b1{b1} { } -DerivedVertex4 DerivedVertex4::div_by_w() const { - return {point.div_by_w(), b0, b1}; +DerivedVertex DerivedVertex::div_by_w() const { + return {vertex.div_by_w(), b0, b1}; } diff --git a/src/o3d/deriv_vertex.h b/src/o3d/deriv_vertex.h index 8945696..7524f9b 100644 --- a/src/o3d/deriv_vertex.h +++ b/src/o3d/deriv_vertex.h @@ -5,13 +5,13 @@ namespace engine::o3d { -class DerivedVertex4 { +class DerivedVertex { public: - engine::math::Vector4 point; + engine::math::Vector4 vertex; float b0, b1; - DerivedVertex4(engine::math::Vector4 point, float b0, float b1); - DerivedVertex4 div_by_w() const; + DerivedVertex(engine::math::Vector4 vertex, float b0, float b1); + DerivedVertex div_by_w() const; }; } diff --git a/src/o3d/mesh.cpp b/src/o3d/mesh.cpp index bf60cc8..2dba328 100644 --- a/src/o3d/mesh.cpp +++ b/src/o3d/mesh.cpp @@ -1,8 +1,8 @@ #include "o3d/mesh.h" #include <vector> #include <array> +#include <cstddef> #include "math/vector.h" -#include "o3d/vertex.h" using namespace engine::o3d; @@ -32,16 +32,30 @@ using namespace engine::o3d; Mesh Mesh::plane() { return { { - { engine::math::Vector3(-1.f, 0.f, -1.f), {0.f, 0.f} }, - { engine::math::Vector3(+1.f, 0.f, -1.f), {1.f, 0.f} }, - { engine::math::Vector3(+1.f, 0.f, +1.f), {1.f, 1.f} }, - { engine::math::Vector3(-1.f, 0.f, +1.f), {0.f, 1.f} }, + {-1.f, 0.f, -1.f, 1.f}, + {+1.f, 0.f, -1.f, 1.f}, + {+1.f, 0.f, +1.f, 1.f}, + {-1.f, 0.f, +1.f, 1.f}, }, + { {0.f, 0.f, -1.f} }, { - { 0, 1, 2 }, { 2, 3, 0 }, + {0.f, 0.f}, + {1.f, 0.f}, + {1.f, 1.f}, + {0.f, 1.f}, + }, + { + {{ {{0, 0, 0}}, {{1, 0, 1}}, {{2, 0, 2}} }}, + {{ {{2, 0, 2}}, {{3, 0, 3}}, {{0, 0, 0}} }}, + {{ {{0, 0, 0}}, {{3, 0, 3}}, {{2, 0, 2}} }}, + {{ {{2, 0, 2}}, {{1, 0, 1}}, {{0, 0, 0}} }}, } }; } -Mesh::Mesh(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces) : pts{pts}, faces{faces} { +Mesh::Mesh(std::vector<engine::math::Vector4> vertices, + std::vector<engine::math::Vector3> normals, + std::vector<VertexData> vertices_data, + std::vector<std::array<std::array<std::size_t, 3>, 3>> indices) + : vertices{vertices}, normals{normals}, vertices_data{vertices_data}, indices{indices} { } diff --git a/src/o3d/mesh.h b/src/o3d/mesh.h index 34d1e09..4aad0e4 100644 --- a/src/o3d/mesh.h +++ b/src/o3d/mesh.h @@ -4,7 +4,9 @@ #include <vector> #include <array> #include <iterator> -#include "o3d/vertex.h" +#include <cstddef> +#include "math/vector.h" +#include "o3d/vertex_data.h" namespace engine::o3d { @@ -13,10 +15,15 @@ class Mesh { // static Mesh cube(); // this function should not be in this file static Mesh plane(); // this function should not be in this file - std::vector<Vertex3> pts; - std::vector<std::array<int, 3>> faces; + std::vector<engine::math::Vector4> vertices; + std::vector<engine::math::Vector3> normals; + std::vector<VertexData> vertices_data; + std::vector<std::array<std::array<std::size_t, 3>, 3>> indices; - Mesh(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces); + Mesh(std::vector<engine::math::Vector4> vertices, + std::vector<engine::math::Vector3> normals, + std::vector<VertexData> vertices_data, + std::vector<std::array<std::array<std::size_t, 3>, 3>> indices); }; } diff --git a/src/o3d/tri.cpp b/src/o3d/tri.cpp index 08f5e7e..73410bf 100644 --- a/src/o3d/tri.cpp +++ b/src/o3d/tri.cpp @@ -1,16 +1,16 @@ -#include "o3d/tri_vertex.h" +#include "o3d/tri.h" #include <vector> #include "math/vector.h" #include "o3d/vertex_data.h" #include "o3d/deriv_vertex.h" #include "o3d/vertex.h" -#include "o3d/tri_deriv_vertex.h" +#include "o3d/tri_deriv.h" using namespace engine::o3d; -TriangleVertex4::TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { +Triangle::Triangle(Vertex vertex1, Vertex vertex2, Vertex vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { } -TriangleDerivedVertex4 TriangleVertex4::to_derived() const { - return {{vertex1.point, 1.f, 0.f}, {vertex2.point, 0.f, 1.f}, {vertex3.point, 0.f, 0.f}}; +TriangleDerived Triangle::to_derived() const { + return {{vertex1.vertex, 1.f, 0.f}, {vertex2.vertex, 0.f, 1.f}, {vertex3.vertex, 0.f, 0.f}}; } diff --git a/src/o3d/tri.h b/src/o3d/tri.h index 715f649..7fa37fe 100644 --- a/src/o3d/tri.h +++ b/src/o3d/tri.h @@ -1,22 +1,23 @@ -#ifndef O3D_TRI_VERTEX_H -#define O3D_TRI_VERTEX_H +#ifndef O3D_TRI_H +#define O3D_TRI_H #include <vector> #include "o3d/vertex.h" -#include "o3d/tri_deriv_vertex.h" +#include "o3d/tri.h" +#include "o3d/tri_deriv.h" namespace engine::o3d { -class TriangleVertex4 { +class Triangle { public: - Vertex4 vertex1; - Vertex4 vertex2; - Vertex4 vertex3; + Vertex vertex1; + Vertex vertex2; + Vertex vertex3; - TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3); - TriangleDerivedVertex4 to_derived() const; + Triangle(Vertex vertex1, Vertex vertex2, Vertex vertex3); + TriangleDerived to_derived() const; }; } -#endif // O3D_TRI_VERTEX_H +#endif // O3D_TRI_H diff --git a/src/o3d/tri_deriv.cpp b/src/o3d/tri_deriv.cpp index 3605b51..81f60a0 100644 --- a/src/o3d/tri_deriv.cpp +++ b/src/o3d/tri_deriv.cpp @@ -1,18 +1,18 @@ -#include "o3d/tri_deriv_vertex.h" +#include "o3d/tri_deriv.h" #include <vector> #include "math/vector.h" #include "o3d/deriv_vertex.h" using namespace engine::o3d; -TriangleDerivedVertex4::TriangleDerivedVertex4(DerivedVertex4 derived_vertex1, DerivedVertex4 derived_vertex2, DerivedVertex4 derived_vertex3) +TriangleDerived::TriangleDerived(DerivedVertex derived_vertex1, DerivedVertex derived_vertex2, DerivedVertex derived_vertex3) : derived_vertex1{derived_vertex1}, derived_vertex2{derived_vertex2}, derived_vertex3{derived_vertex3} { } #define P1_OUT 1 #define P2_OUT 2 #define P3_OUT 4 -static void _perspective_crop_x(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVertex4 t, int n, float x) { +static void _perspective_crop_x(std::vector<TriangleDerived>& tris, TriangleDerived t, int n, float x) { switch (n) { case 0: tris.push_back(t); @@ -24,9 +24,9 @@ static void _perspective_crop_x(std::vector<TriangleDerivedVertex4>& tris, Trian case P1_OUT | P3_OUT: case P1_OUT | P2_OUT: { - DerivedVertex4* q1; - DerivedVertex4* q2; - DerivedVertex4* q3; + DerivedVertex* q1; + DerivedVertex* q2; + DerivedVertex* q3; switch (n) { case P1_OUT: case P2_OUT | P3_OUT: @@ -47,29 +47,29 @@ static void _perspective_crop_x(std::vector<TriangleDerivedVertex4>& tris, Trian q3 = &t.derived_vertex1; break; } - engine::math::Vector4 dq2 = q1->point - q2->point; - float fac2 = (x - q2->point.x) / dq2.x; - float r2w = 1.f / (fac2 / q1->point.w + (1.f - fac2) / q2->point.w); - float fac2_b = r2w * fac2 / q1->point.w; - DerivedVertex4 r2{ + engine::math::Vector4 dq2 = q1->vertex - q2->vertex; + float fac2 = (x - q2->vertex.x) / dq2.x; + float r2w = 1.f / (fac2 / q1->vertex.w + (1.f - fac2) / q2->vertex.w); + float fac2_b = r2w * fac2 / q1->vertex.w; + DerivedVertex r2{ { x, - q2->point.y + fac2 * dq2.y, - fac2_b * q1->point.z + (1.f - fac2_b) * q2->point.z, + q2->vertex.y + fac2 * dq2.y, + fac2_b * q1->vertex.z + (1.f - fac2_b) * q2->vertex.z, r2w }, fac2_b * q1->b0 + (1.f - fac2_b) * q2->b0, fac2_b * q1->b1 + (1.f - fac2_b) * q2->b1 }; - engine::math::Vector4 dq3 = q1->point - q3->point; - float fac3 = (x - q3->point.x) / dq3.x; - float r3w = 1.f / (fac3 / q1->point.w + (1.f - fac3) / q3->point.w); - float fac3_b = r3w * fac3 / q1->point.w; - DerivedVertex4 r3{ + engine::math::Vector4 dq3 = q1->vertex - q3->vertex; + float fac3 = (x - q3->vertex.x) / dq3.x; + float r3w = 1.f / (fac3 / q1->vertex.w + (1.f - fac3) / q3->vertex.w); + float fac3_b = r3w * fac3 / q1->vertex.w; + DerivedVertex r3{ { x, - q3->point.y + fac3 * dq3.y, - fac3_b * q1->point.z + (1.f - fac3_b) * q3->point.z, + q3->vertex.y + fac3 * dq3.y, + fac3_b * q1->vertex.z + (1.f - fac3_b) * q3->vertex.z, r3w }, fac3_b * q1->b0 + (1.f - fac3_b) * q3->b0, @@ -105,7 +105,7 @@ static void _perspective_crop_x(std::vector<TriangleDerivedVertex4>& tris, Trian } } -static void _perspective_crop_y(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVertex4 t, int n, float y) { +static void _perspective_crop_y(std::vector<TriangleDerived>& tris, TriangleDerived t, int n, float y) { switch (n) { case 0: tris.push_back(t); @@ -117,9 +117,9 @@ static void _perspective_crop_y(std::vector<TriangleDerivedVertex4>& tris, Trian case P1_OUT | P3_OUT: case P1_OUT | P2_OUT: { - DerivedVertex4* q1; - DerivedVertex4* q2; - DerivedVertex4* q3; + DerivedVertex* q1; + DerivedVertex* q2; + DerivedVertex* q3; switch (n) { case P1_OUT: case P2_OUT | P3_OUT: @@ -140,29 +140,29 @@ static void _perspective_crop_y(std::vector<TriangleDerivedVertex4>& tris, Trian q3 = &t.derived_vertex1; break; } - engine::math::Vector4 dq2 = q1->point - q2->point; - float fac2 = (y - q2->point.y) / dq2.y; - float r2w = 1.f / (fac2 / q1->point.w + (1.f - fac2) / q2->point.w); - float fac2_b = r2w * fac2 / q1->point.w; - DerivedVertex4 r2{ + engine::math::Vector4 dq2 = q1->vertex - q2->vertex; + float fac2 = (y - q2->vertex.y) / dq2.y; + float r2w = 1.f / (fac2 / q1->vertex.w + (1.f - fac2) / q2->vertex.w); + float fac2_b = r2w * fac2 / q1->vertex.w; + DerivedVertex r2{ { - q2->point.x + fac2 * dq2.x, + q2->vertex.x + fac2 * dq2.x, y, - fac2_b * q1->point.z + (1.f - fac2_b) * q2->point.z, + fac2_b * q1->vertex.z + (1.f - fac2_b) * q2->vertex.z, r2w }, fac2_b * q1->b0 + (1.f - fac2_b) * q2->b0, fac2_b * q1->b1 + (1.f - fac2_b) * q2->b1 }; - engine::math::Vector4 dq3 = q1->point - q3->point; - float fac3 = (y - q3->point.y) / dq3.y; - float r3w = 1.f / (fac3 / q1->point.w + (1.f - fac3) / q3->point.w); - float fac3_b = r3w * fac3 / q1->point.w; - DerivedVertex4 r3{ + engine::math::Vector4 dq3 = q1->vertex - q3->vertex; + float fac3 = (y - q3->vertex.y) / dq3.y; + float r3w = 1.f / (fac3 / q1->vertex.w + (1.f - fac3) / q3->vertex.w); + float fac3_b = r3w * fac3 / q1->vertex.w; + DerivedVertex r3{ { - q3->point.x + fac3 * dq3.x, + q3->vertex.x + fac3 * dq3.x, y, - fac3_b * q1->point.z + (1.f - fac3_b) * q3->point.z, + fac3_b * q1->vertex.z + (1.f - fac3_b) * q3->vertex.z, r3w }, fac3_b * q1->b0 + (1.f - fac3_b) * q3->b0, @@ -198,24 +198,24 @@ static void _perspective_crop_y(std::vector<TriangleDerivedVertex4>& tris, Trian } } -std::vector<TriangleDerivedVertex4> TriangleDerivedVertex4::perspective_crop_xy_out(float x1, float x2, float y1, float y2) const { - std::vector<TriangleDerivedVertex4> tris_final; - std::vector<TriangleDerivedVertex4> tris1; - _perspective_crop_x(tris1, *this, (derived_vertex1.point.x < x1) | ((derived_vertex2.point.x < x1) << 1) | ((derived_vertex3.point.x < x1) << 2), x1); +std::vector<TriangleDerived> TriangleDerived::perspective_crop_xy_out(float x1, float x2, float y1, float y2) const { + std::vector<TriangleDerived> tris_final; + std::vector<TriangleDerived> tris1; + _perspective_crop_x(tris1, *this, (derived_vertex1.vertex.x < x1) | ((derived_vertex2.vertex.x < x1) << 1) | ((derived_vertex3.vertex.x < x1) << 2), x1); for (auto t1 : tris1) { - std::vector<TriangleDerivedVertex4> tris2; - _perspective_crop_x(tris2, t1, (t1.derived_vertex1.point.x > x2) | ((t1.derived_vertex2.point.x > x2) << 1) | ((t1.derived_vertex3.point.x > x2) << 2), x2); + std::vector<TriangleDerived> tris2; + _perspective_crop_x(tris2, t1, (t1.derived_vertex1.vertex.x > x2) | ((t1.derived_vertex2.vertex.x > x2) << 1) | ((t1.derived_vertex3.vertex.x > x2) << 2), x2); for (auto t2 : tris2) { - std::vector<TriangleDerivedVertex4> tris3; - _perspective_crop_y(tris3, t2, (t2.derived_vertex1.point.y < y1) | ((t2.derived_vertex2.point.y < y1) << 1) | ((t2.derived_vertex3.point.y < y1) << 2), y1); + std::vector<TriangleDerived> tris3; + _perspective_crop_y(tris3, t2, (t2.derived_vertex1.vertex.y < y1) | ((t2.derived_vertex2.vertex.y < y1) << 1) | ((t2.derived_vertex3.vertex.y < y1) << 2), y1); for (auto t3 : tris3) - _perspective_crop_y(tris_final, t3, (t3.derived_vertex1.point.y > y2) | ((t3.derived_vertex2.point.y > y2) << 1) | ((t3.derived_vertex3.point.y > y2) << 2), y2); + _perspective_crop_y(tris_final, t3, (t3.derived_vertex1.vertex.y > y2) | ((t3.derived_vertex2.vertex.y > y2) << 1) | ((t3.derived_vertex3.vertex.y > y2) << 2), y2); } } return tris_final; } -static void _crop_z(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVertex4 t, int n, float z) { +static void _crop_z(std::vector<TriangleDerived>& tris, TriangleDerived t, int n, float z) { switch (n) { case 0: tris.push_back(t); @@ -227,9 +227,9 @@ static void _crop_z(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVe case P1_OUT | P3_OUT: case P1_OUT | P2_OUT: { - DerivedVertex4* q1; - DerivedVertex4* q2; - DerivedVertex4* q3; + DerivedVertex* q1; + DerivedVertex* q2; + DerivedVertex* q3; switch (n) { case P1_OUT: case P2_OUT | P3_OUT: @@ -250,26 +250,26 @@ static void _crop_z(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVe q3 = &t.derived_vertex1; break; } - engine::math::Vector4 dq2 = q1->point - q2->point; - float fac2 = (z - q2->point.z) / dq2.z; - DerivedVertex4 r2{ + engine::math::Vector4 dq2 = q1->vertex - q2->vertex; + float fac2 = (z - q2->vertex.z) / dq2.z; + DerivedVertex r2{ { - q2->point.x + fac2 * dq2.x, - q2->point.y + fac2 * dq2.y, + q2->vertex.x + fac2 * dq2.x, + q2->vertex.y + fac2 * dq2.y, z, - q2->point.w + fac2 * dq2.w + q2->vertex.w + fac2 * dq2.w }, fac2 * q1->b0 + (1.f - fac2) * q2->b0, fac2 * q1->b1 + (1.f - fac2) * q2->b1 }; - engine::math::Vector4 dq3 = q1->point - q3->point; - float fac3 = (z - q3->point.z) / dq3.z; - DerivedVertex4 r3{ + engine::math::Vector4 dq3 = q1->vertex - q3->vertex; + float fac3 = (z - q3->vertex.z) / dq3.z; + DerivedVertex r3{ { - q3->point.x + fac3 * dq3.x, - q3->point.y + fac3 * dq3.y, + q3->vertex.x + fac3 * dq3.x, + q3->vertex.y + fac3 * dq3.y, z, - q3->point.w + fac3 * dq3.w + q3->vertex.w + fac3 * dq3.w }, fac3 * q1->b0 + (1.f - fac3) * q3->b0, fac3 * q1->b1 + (1.f - fac3) * q3->b1 @@ -304,18 +304,18 @@ static void _crop_z(std::vector<TriangleDerivedVertex4>& tris, TriangleDerivedVe } } -std::vector<TriangleDerivedVertex4> TriangleDerivedVertex4::crop_z_out(float z1, float z2) const { - std::vector<TriangleDerivedVertex4> tris; - _crop_z(tris, *this, (derived_vertex1.point.z < z1) | ((derived_vertex2.point.z < z1) << 1) | ((derived_vertex3.point.z < z1) << 2), z1); - std::vector<TriangleDerivedVertex4> tris2; +std::vector<TriangleDerived> TriangleDerived::crop_z_out(float z1, float z2) const { + std::vector<TriangleDerived> tris; + _crop_z(tris, *this, (derived_vertex1.vertex.z < z1) | ((derived_vertex2.vertex.z < z1) << 1) | ((derived_vertex3.vertex.z < z1) << 2), z1); + std::vector<TriangleDerived> tris2; for (auto t : tris) - _crop_z(tris2, t, (t.derived_vertex1.point.z > z2) | ((t.derived_vertex2.point.z > z2) << 1) | ((t.derived_vertex3.point.z > z2) << 2), z2); + _crop_z(tris2, t, (t.derived_vertex1.vertex.z > z2) | ((t.derived_vertex2.vertex.z > z2) << 1) | ((t.derived_vertex3.vertex.z > z2) << 2), z2); return tris2; } #undef P1_OUT #undef P2_OUT #undef P3_OUT -TriangleDerivedVertex4 TriangleDerivedVertex4::div_by_w() const { +TriangleDerived TriangleDerived::div_by_w() const { return {derived_vertex1.div_by_w(), derived_vertex2.div_by_w(), derived_vertex3.div_by_w()}; } diff --git a/src/o3d/tri_deriv.h b/src/o3d/tri_deriv.h index 41ed4dc..201539b 100644 --- a/src/o3d/tri_deriv.h +++ b/src/o3d/tri_deriv.h @@ -1,5 +1,5 @@ -#ifndef O3D_TRI_DERIV_VERTEX_H -#define O3D_TRI_DERIV_VERTEX_H +#ifndef O3D_TRI_VERTEX_H +#define O3D_TRI_VERTEX_H #include <vector> #include "o3d/vertex.h" @@ -7,18 +7,18 @@ namespace engine::o3d { -class TriangleDerivedVertex4 { +class TriangleDerived { public: - DerivedVertex4 derived_vertex1; - DerivedVertex4 derived_vertex2; - DerivedVertex4 derived_vertex3; + DerivedVertex derived_vertex1; + DerivedVertex derived_vertex2; + DerivedVertex derived_vertex3; - TriangleDerivedVertex4(DerivedVertex4 derived_vertex1, DerivedVertex4 derived_vertex2, DerivedVertex4 derived_vertex3); - std::vector<TriangleDerivedVertex4> perspective_crop_xy_out(float x1, float x2, float y1, float y2) const; - std::vector<TriangleDerivedVertex4> crop_z_out(float z1, float z2) const; - TriangleDerivedVertex4 div_by_w() const; + TriangleDerived(DerivedVertex derived_vertex1, DerivedVertex derived_vertex2, DerivedVertex derived_vertex3); + std::vector<TriangleDerived> perspective_crop_xy_out(float x1, float x2, float y1, float y2) const; + std::vector<TriangleDerived> crop_z_out(float z1, float z2) const; + TriangleDerived div_by_w() const; }; } -#endif // O3D_TRI_DERIV_VERTEX_H +#endif // O3D_TRI_VERTEX_H diff --git a/src/o3d/vertex.cpp b/src/o3d/vertex.cpp index ec9c05f..5845e27 100644 --- a/src/o3d/vertex.cpp +++ b/src/o3d/vertex.cpp @@ -4,11 +4,6 @@ using namespace engine::o3d; -Vertex3::Vertex3(engine::math::Vector3 point, VertexData data) : point{point}, data{data} { -} - -Vertex4::Vertex4(engine::math::Vector4 point, VertexData data) : point{point}, data{data} { -} - -Vertex4::Vertex4(Vertex3 vertex) : point{vertex.point}, data{vertex.data} { +Vertex::Vertex(engine::math::Vector4 vertex, engine::math::Vector3 normal, VertexData data) + : vertex{vertex}, normal{normal}, data{data} { } diff --git a/src/o3d/vertex.h b/src/o3d/vertex.h index b0dd195..1247fc8 100644 --- a/src/o3d/vertex.h +++ b/src/o3d/vertex.h @@ -6,21 +6,13 @@ namespace engine::o3d { -class Vertex3 { +class Vertex { public: - engine::math::Vector3 point; + engine::math::Vector4 vertex; + engine::math::Vector3 normal; VertexData data; - Vertex3(engine::math::Vector3 point, VertexData data); -}; - -class Vertex4 { - public: - engine::math::Vector4 point; - VertexData data; - - Vertex4(engine::math::Vector4 point, VertexData data); - Vertex4(Vertex3 vertex); + Vertex(engine::math::Vector4 vertex, engine::math::Vector3 normal, VertexData data); }; } diff --git a/src/renderer.cpp b/src/renderer.cpp index 7a32807..1fa8799 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -6,8 +6,8 @@ #include "math/vector.h" #include "o3d/vertex.h" #include "o3d/deriv_vertex.h" -#include "o3d/tri_vertex.h" -#include "o3d/tri_deriv_vertex.h" +#include "o3d/tri.h" +#include "o3d/tri_deriv.h" #include "o3d/vertex_data.h" using namespace engine; @@ -34,127 +34,105 @@ void Renderer::clear() { fb->clear(); } -void Renderer::_draw_cropped_triangle(o3d::TriangleVertex4 root, o3d::TriangleDerivedVertex4 triangle) { - std::array<o3d::DerivedVertex4*, 3> sorted_vs = { &triangle.derived_vertex1, &triangle.derived_vertex2, &triangle.derived_vertex3 }; +enum TriangleSide { top, bottom }; -#define SWAP_IF_LT(X,Y) ({ \ - if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) { \ - auto temp = sorted_vs[X]; \ - sorted_vs[X] = sorted_vs[Y]; \ - sorted_vs[Y] = temp; \ - } \ - }) - SWAP_IF_LT(1, 0); - SWAP_IF_LT(2, 1); - SWAP_IF_LT(1, 0); -#undef SWAP_IF_LT +void Renderer::_draw_cropped_triangle(const o3d::Triangle& root, const o3d::TriangleDerived& triangle) { + std::array<const o3d::DerivedVertex*, 3> sorted_vs = { &triangle.derived_vertex1, &triangle.derived_vertex2, &triangle.derived_vertex3 }; + + { + const auto swap_if_lt = [&](auto x, auto y) { + if (sorted_vs[x]->vertex.y < sorted_vs[y]->vertex.y) { + auto temp = sorted_vs[x]; + sorted_vs[x] = sorted_vs[y]; + sorted_vs[y] = temp; + } + }; + + swap_if_lt(1, 0); + swap_if_lt(2, 1); + swap_if_lt(1, 0); + } auto middle_vl = *sorted_vs[1]; - const float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); - const float fac_b0 = (1.f - fac) / sorted_vs[0]->point.w / ((1.f - fac) / sorted_vs[0]->point.w + fac / sorted_vs[2]->point.w); - o3d::DerivedVertex4 middle_vr{ + const float fac = (sorted_vs[1]->vertex.y - sorted_vs[0]->vertex.y) / (sorted_vs[2]->vertex.y - sorted_vs[0]->vertex.y); + const float fac_b0 = (1.f - fac) / sorted_vs[0]->vertex.w / ((1.f - fac) / sorted_vs[0]->vertex.w + fac / sorted_vs[2]->vertex.w); + o3d::DerivedVertex middle_vr{ { - sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), - sorted_vs[1]->point.y, - fac_b0 * sorted_vs[0]->point.z + (1.f - fac_b0) * sorted_vs[2]->point.z, - 1.f / (1.f / sorted_vs[0]->point.w + fac * (1.f / sorted_vs[2]->point.w - 1.f / sorted_vs[0]->point.w)) + sorted_vs[0]->vertex.x + fac * (sorted_vs[2]->vertex.x - sorted_vs[0]->vertex.x), + sorted_vs[1]->vertex.y, + fac_b0 * sorted_vs[0]->vertex.z + (1.f - fac_b0) * sorted_vs[2]->vertex.z, + 1.f / (1.f / sorted_vs[0]->vertex.w + fac * (1.f / sorted_vs[2]->vertex.w - 1.f / sorted_vs[0]->vertex.w)) }, fac_b0 * sorted_vs[0]->b0 + (1.f - fac_b0) * sorted_vs[2]->b0, fac_b0 * sorted_vs[0]->b1 + (1.f - fac_b0) * sorted_vs[2]->b1 }; - if (middle_vr.point.x < middle_vl.point.x) { + if (middle_vr.vertex.x < middle_vl.vertex.x) { auto temp = middle_vr; middle_vr = middle_vl; middle_vl = temp; } - // top triangle - { - if (sorted_vs[0]->point.y != sorted_vs[1]->point.y) { - int top_y = static_cast<int>(std::floor(sorted_vs[0]->point.y + 1.f)); - int bottom_y = static_cast<int>(std::ceil(sorted_vs[1]->point.y - 1.f)); - for (int y = top_y; y <= bottom_y; y++) { - float iy = static_cast<float>(y); - float s = (iy - sorted_vs[0]->point.y) / (sorted_vs[1]->point.y - sorted_vs[0]->point.y); - float sub_bb0 = 1.f - s; - float xl = sorted_vs[0]->point.x + s * (middle_vl.point.x - sorted_vs[0]->point.x); - float xr = sorted_vs[0]->point.x + s * (middle_vr.point.x - sorted_vs[0]->point.x); - int left_x = static_cast<int>(std::ceil(xl)); - int right_x = static_cast<int>(std::ceil(xr - 1.f)); - for (int x = left_x; x <= right_x; x++) { - float ix = static_cast<float>(x); - float t = (ix - xl) / (xr - xl); - float sub_bb1 = s * (1.f - t); - float b_fac = 1.f / (sub_bb0 / sorted_vs[0]->point.w + sub_bb1 / middle_vl.point.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.point.w); - float sub_b0 = b_fac * sub_bb0 / sorted_vs[0]->point.w; - float sub_b1 = b_fac * sub_bb1 / middle_vl.point.w; - float b0 = sub_b0 * sorted_vs[0]->b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0; - float b1 = sub_b0 * sorted_vs[0]->b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1; - math::Vector3 loc{ - b0 * root.vertex1.point.x + b1 * root.vertex2.point.x + (1.f - b0 - b1) * root.vertex3.point.x, - b0 * root.vertex1.point.y + b1 * root.vertex2.point.y + (1.f - b0 - b1) * root.vertex3.point.y, - b0 * root.vertex1.point.z + b1 * root.vertex2.point.z + (1.f - b0 - b1) * root.vertex3.point.z - }; - if (loc.z < depth_buf[x + y * fb->width()]) { - depth_buf[x + y * fb->width()] = loc.z; - fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1)); - } - } - } + const auto _draw_cropped_triangle_side = [&]<TriangleSide side>() { + const int vertex_end_index = ([&]() { if constexpr (side == TriangleSide::top) return 0; else return 2; })(); + const o3d::DerivedVertex& vertex_end = *sorted_vs[vertex_end_index]; + if (vertex_end.vertex.y == sorted_vs[1]->vertex.y) + return; + int top_y; + int bottom_y; + if constexpr (side == TriangleSide::top) { + top_y = static_cast<int>(std::floor(vertex_end.vertex.y + 1.f)); + bottom_y = static_cast<int>(std::ceil(sorted_vs[1]->vertex.y - 1.f)); + } else { + bottom_y = static_cast<int>(std::floor(vertex_end.vertex.y)); + top_y = static_cast<int>(std::ceil(sorted_vs[1]->vertex.y)); } - } - - // bottom triangle - { - if (sorted_vs[1]->point.y != sorted_vs[2]->point.y) { - int bottom_y = static_cast<int>(std::floor(sorted_vs[2]->point.y)); - int top_y = static_cast<int>(std::ceil(sorted_vs[1]->point.y)); - for (int y = top_y; y <= bottom_y; y++) { - float iy = static_cast<float>(y); - float s = (iy - sorted_vs[2]->point.y) / (sorted_vs[1]->point.y - sorted_vs[2]->point.y); - float sub_bb0 = 1.f - s; - float xl = sorted_vs[2]->point.x + s * (middle_vl.point.x - sorted_vs[2]->point.x); - float xr = sorted_vs[2]->point.x + s * (middle_vr.point.x - sorted_vs[2]->point.x); - int left_x = static_cast<int>(std::ceil(xl)); - int right_x = static_cast<int>(std::ceil(xr - 1.f)); - for (int x = left_x; x <= right_x; x++) { - float ix = static_cast<float>(x); - float t = (ix - xl) / (xr - xl); - float sub_bb1 = s * (1.f - t); - float b_fac = 1.f / (sub_bb0 / sorted_vs[2]->point.w + sub_bb1 / middle_vl.point.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.point.w); - float sub_b0 = b_fac * sub_bb0 / sorted_vs[2]->point.w; - float sub_b1 = b_fac * sub_bb1 / middle_vl.point.w; - float b0 = sub_b0 * sorted_vs[2]->b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0; - float b1 = sub_b0 * sorted_vs[2]->b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1; - math::Vector3 loc{ - b0 * root.vertex1.point.x + b1 * root.vertex2.point.x + (1.f - b0 - b1) * root.vertex3.point.x, - b0 * root.vertex1.point.y + b1 * root.vertex2.point.y + (1.f - b0 - b1) * root.vertex3.point.y, - b0 * root.vertex1.point.z + b1 * root.vertex2.point.z + (1.f - b0 - b1) * root.vertex3.point.z - }; - if (loc.z < depth_buf[x + y * fb->width()]) { - depth_buf[x + y * fb->width()] = loc.z; - fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1)); - } + for (int y = top_y; y <= bottom_y; y++) { + float iy = static_cast<float>(y); + float s = (iy - vertex_end.vertex.y) / (sorted_vs[1]->vertex.y - vertex_end.vertex.y); + float sub_bb0 = 1.f - s; + float xl = vertex_end.vertex.x + s * (middle_vl.vertex.x - vertex_end.vertex.x); + float xr = vertex_end.vertex.x + s * (middle_vr.vertex.x - vertex_end.vertex.x); + int left_x = static_cast<int>(std::ceil(xl)); + int right_x = static_cast<int>(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast<float>(x); + float t = (ix - xl) / (xr - xl); + float sub_bb1 = s * (1.f - t); + float b_fac = 1.f / (sub_bb0 / vertex_end.vertex.w + sub_bb1 / middle_vl.vertex.w + (1.f - sub_bb0 - sub_bb1) / middle_vr.vertex.w); + float sub_b0 = b_fac * sub_bb0 / vertex_end.vertex.w; + float sub_b1 = b_fac * sub_bb1 / middle_vl.vertex.w; + float b0 = sub_b0 * vertex_end.b0 + sub_b1 * middle_vl.b0 + (1.f - sub_b0 - sub_b1) * middle_vr.b0; + float b1 = sub_b0 * vertex_end.b1 + sub_b1 * middle_vl.b1 + (1.f - sub_b0 - sub_b1) * middle_vr.b1; + math::Vector3 loc{ + b0 * root.vertex1.vertex.x + b1 * root.vertex2.vertex.x + (1.f - b0 - b1) * root.vertex3.vertex.x, + b0 * root.vertex1.vertex.y + b1 * root.vertex2.vertex.y + (1.f - b0 - b1) * root.vertex3.vertex.y, + b0 * root.vertex1.vertex.z + b1 * root.vertex2.vertex.z + (1.f - b0 - b1) * root.vertex3.vertex.z + }; + if (loc.z < depth_buf[x + y * fb->width()]) { + depth_buf[x + y * fb->width()] = loc.z; + fb->draw_point(x, y, loc, o3d::VertexData::bilerp(root.vertex1.data, root.vertex2.data, root.vertex3.data, b0, b1)); } } } - } + }; + _draw_cropped_triangle_side.operator()<TriangleSide::top>(); + _draw_cropped_triangle_side.operator()<TriangleSide::bottom>(); } -void Renderer::draw_triangle(o3d::TriangleVertex4 triangle) { +void Renderer::draw_triangle(o3d::Triangle triangle) { for (auto t1 : triangle.to_derived().crop_z_out(-1.f, 1.f)) { for (auto t2 : t1.div_by_w().perspective_crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { - auto pp1 = t2.derived_vertex1.point.xy(); - auto pp2 = t2.derived_vertex2.point.xy(); - auto pp3 = t2.derived_vertex3.point.xy(); + auto pp1 = t2.derived_vertex1.vertex.xy(); + auto pp2 = t2.derived_vertex2.vertex.xy(); + auto pp3 = t2.derived_vertex3.vertex.xy(); if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; float fw_over_2 = static_cast<float>(fb->width()) / 2.f, fh_over_2 = static_cast<float>(fb->height()) / 2.f; - t2.derived_vertex1.point.x = (t2.derived_vertex1.point.x + 1.f) * fw_over_2 - .5f; - t2.derived_vertex1.point.y = (t2.derived_vertex1.point.y + 1.f) * fh_over_2 - .5f; - t2.derived_vertex2.point.x = (t2.derived_vertex2.point.x + 1.f) * fw_over_2 - .5f; - t2.derived_vertex2.point.y = (t2.derived_vertex2.point.y + 1.f) * fh_over_2 - .5f; - t2.derived_vertex3.point.x = (t2.derived_vertex3.point.x + 1.f) * fw_over_2 - .5f; - t2.derived_vertex3.point.y = (t2.derived_vertex3.point.y + 1.f) * fh_over_2 - .5f; + t2.derived_vertex1.vertex.x = (t2.derived_vertex1.vertex.x + 1.f) * fw_over_2 - .5f; + t2.derived_vertex1.vertex.y = (t2.derived_vertex1.vertex.y + 1.f) * fh_over_2 - .5f; + t2.derived_vertex2.vertex.x = (t2.derived_vertex2.vertex.x + 1.f) * fw_over_2 - .5f; + t2.derived_vertex2.vertex.y = (t2.derived_vertex2.vertex.y + 1.f) * fh_over_2 - .5f; + t2.derived_vertex3.vertex.x = (t2.derived_vertex3.vertex.x + 1.f) * fw_over_2 - .5f; + t2.derived_vertex3.vertex.y = (t2.derived_vertex3.vertex.y + 1.f) * fh_over_2 - .5f; _draw_cropped_triangle(triangle, t2); } } diff --git a/src/renderer.h b/src/renderer.h index 046a4ef..457099d 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -3,7 +3,8 @@ #include <memory> #include "fb/fb.h" -#include "o3d/tri_vertex.h" +#include "o3d/tri.h" +#include "o3d/tri_deriv.h" namespace engine { @@ -16,12 +17,12 @@ class Renderer { unsigned int width() const; unsigned int height() const; void clear(); - void draw_triangle(o3d::TriangleVertex4 triangle); + void draw_triangle(o3d::Triangle triangle); private: std::vector<float> depth_buf; - void _draw_cropped_triangle(o3d::TriangleVertex4 root, o3d::TriangleDerivedVertex4 triangle); + void _draw_cropped_triangle(const o3d::Triangle& root, const o3d::TriangleDerived& triangle); }; } |