From 6b765a85cf81bf4b7162e4c9280dd4054581c611 Mon Sep 17 00:00:00 2001 From: vimene Date: Mon, 11 Dec 2023 12:42:46 +0100 Subject: improved mesh definition - In the context of mesh definition, splited indices into vertex index, normal index and vertex data index to be able to specify different normals and vertex data for different faces using the same vertex --- Makefile.am | 4 +- src/engine.cpp | 18 +++-- src/fb/chfb.cpp | 1 + src/o3d/deriv_vertex.cpp | 6 +- src/o3d/deriv_vertex.h | 8 +-- src/o3d/mesh.cpp | 28 ++++++-- src/o3d/mesh.h | 15 ++-- src/o3d/tri.cpp | 10 +-- src/o3d/tri.h | 21 +++--- src/o3d/tri_deriv.cpp | 138 ++++++++++++++++++------------------ src/o3d/tri_deriv.h | 22 +++--- src/o3d/vertex.cpp | 9 +-- src/o3d/vertex.h | 16 ++--- src/renderer.cpp | 178 +++++++++++++++++++++-------------------------- 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 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 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 #include +#include #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 pts, std::vector> faces) : pts{pts}, faces{faces} { +Mesh::Mesh(std::vector vertices, + std::vector normals, + std::vector vertices_data, + std::vector, 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 #include #include -#include "o3d/vertex.h" +#include +#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 pts; - std::vector> faces; + std::vector vertices; + std::vector normals; + std::vector vertices_data; + std::vector, 3>> indices; - Mesh(std::vector pts, std::vector> faces); + Mesh(std::vector vertices, + std::vector normals, + std::vector vertices_data, + std::vector, 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 #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 #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 #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& tris, TriangleDerivedVertex4 t, int n, float x) { +static void _perspective_crop_x(std::vector& 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& 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& 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& tris, Trian } } -static void _perspective_crop_y(std::vector& tris, TriangleDerivedVertex4 t, int n, float y) { +static void _perspective_crop_y(std::vector& 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& 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& 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& tris, Trian } } -std::vector TriangleDerivedVertex4::perspective_crop_xy_out(float x1, float x2, float y1, float y2) const { - std::vector tris_final; - std::vector 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::perspective_crop_xy_out(float x1, float x2, float y1, float y2) const { + std::vector tris_final; + std::vector 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 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 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 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 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& tris, TriangleDerivedVertex4 t, int n, float z) { +static void _crop_z(std::vector& 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& 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& 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& tris, TriangleDerivedVe } } -std::vector TriangleDerivedVertex4::crop_z_out(float z1, float z2) const { - std::vector 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 tris2; +std::vector TriangleDerived::crop_z_out(float z1, float z2) const { + std::vector 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 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 #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 perspective_crop_xy_out(float x1, float x2, float y1, float y2) const; - std::vector 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 perspective_crop_xy_out(float x1, float x2, float y1, float y2) const; + std::vector 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 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 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(std::floor(sorted_vs[0]->point.y + 1.f)); - int bottom_y = static_cast(std::ceil(sorted_vs[1]->point.y - 1.f)); - for (int y = top_y; y <= bottom_y; y++) { - float iy = static_cast(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(std::ceil(xl)); - int right_x = static_cast(std::ceil(xr - 1.f)); - for (int x = left_x; x <= right_x; x++) { - float ix = static_cast(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 = [&]() { + 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(std::floor(vertex_end.vertex.y + 1.f)); + bottom_y = static_cast(std::ceil(sorted_vs[1]->vertex.y - 1.f)); + } else { + bottom_y = static_cast(std::floor(vertex_end.vertex.y)); + top_y = static_cast(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(std::floor(sorted_vs[2]->point.y)); - int top_y = static_cast(std::ceil(sorted_vs[1]->point.y)); - for (int y = top_y; y <= bottom_y; y++) { - float iy = static_cast(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(std::ceil(xl)); - int right_x = static_cast(std::ceil(xr - 1.f)); - for (int x = left_x; x <= right_x; x++) { - float ix = static_cast(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(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(std::ceil(xl)); + int right_x = static_cast(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast(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()(); + _draw_cropped_triangle_side.operator()(); } -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(fb->width()) / 2.f, fh_over_2 = static_cast(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 #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 depth_buf; - void _draw_cropped_triangle(o3d::TriangleVertex4 root, o3d::TriangleDerivedVertex4 triangle); + void _draw_cropped_triangle(const o3d::Triangle& root, const o3d::TriangleDerived& triangle); }; } -- cgit v1.2.3