From 4558a2a704bf75266f7262f8dd41bb1c9b094e1d Mon Sep 17 00:00:00 2001 From: vimene Date: Wed, 22 Nov 2023 20:32:48 +0100 Subject: code refactoring --- src/chfb.cpp | 152 ----------------------- src/chfb.h | 28 ----- src/engine.cpp | 14 +-- src/fb/chfb.cpp | 152 +++++++++++++++++++++++ src/fb/chfb.h | 28 +++++ src/fb/pixfb.cpp | 153 +++++++++++++++++++++++ src/fb/pixfb.h | 29 +++++ src/math/math_vector.cpp | 173 ++++++++++++++++++++++++++ src/math/math_vector.h | 69 +++++++++++ src/math_vector.cpp | 173 -------------------------- src/math_vector.h | 69 ----------- src/o3d/obj3d.cpp | 46 +++++++ src/o3d/obj3d.h | 42 +++++++ src/o3d/tri_vertex.cpp | 314 +++++++++++++++++++++++++++++++++++++++++++++++ src/o3d/tri_vertex.h | 29 +++++ src/o3d/vertex.cpp | 16 +++ src/o3d/vertex.h | 25 ++++ src/o3d/vertex_data.cpp | 12 ++ src/o3d/vertex_data.h | 12 ++ src/obj3d.cpp | 46 ------- src/obj3d.h | 42 ------- src/pixfb.cpp | 153 ----------------------- src/pixfb.h | 29 ----- src/tri_vertex.cpp | 314 ----------------------------------------------- src/tri_vertex.h | 29 ----- src/vertex.cpp | 16 --- src/vertex.h | 25 ---- src/vertex_data.cpp | 12 -- src/vertex_data.h | 12 -- 29 files changed, 1107 insertions(+), 1107 deletions(-) delete mode 100644 src/chfb.cpp delete mode 100644 src/chfb.h create mode 100644 src/fb/chfb.cpp create mode 100644 src/fb/chfb.h create mode 100644 src/fb/pixfb.cpp create mode 100644 src/fb/pixfb.h create mode 100644 src/math/math_vector.cpp create mode 100644 src/math/math_vector.h delete mode 100644 src/math_vector.cpp delete mode 100644 src/math_vector.h create mode 100644 src/o3d/obj3d.cpp create mode 100644 src/o3d/obj3d.h create mode 100644 src/o3d/tri_vertex.cpp create mode 100644 src/o3d/tri_vertex.h create mode 100644 src/o3d/vertex.cpp create mode 100644 src/o3d/vertex.h create mode 100644 src/o3d/vertex_data.cpp create mode 100644 src/o3d/vertex_data.h delete mode 100644 src/obj3d.cpp delete mode 100644 src/obj3d.h delete mode 100644 src/pixfb.cpp delete mode 100644 src/pixfb.h delete mode 100644 src/tri_vertex.cpp delete mode 100644 src/tri_vertex.h delete mode 100644 src/vertex.cpp delete mode 100644 src/vertex.h delete mode 100644 src/vertex_data.cpp delete mode 100644 src/vertex_data.h (limited to 'src') diff --git a/src/chfb.cpp b/src/chfb.cpp deleted file mode 100644 index 249fb16..0000000 --- a/src/chfb.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "chfb.h" -#include -#include -#include -#include "math_vector.h" -#include "vertex.h" -#include "tri_vertex.h" -#include "vertex_data.h" - -CharacterFrameBuffer::CharacterFrameBuffer(unsigned int w, unsigned int h) { - resize(w, h); -} - -void CharacterFrameBuffer::resize(unsigned int w, unsigned int h) { - this->w = w; - this->h = h; - chars_vector.resize(w * h); - depth_buf.resize(w * h); - clear(); -} - -unsigned int CharacterFrameBuffer::width() const { - return w; -} - -unsigned int CharacterFrameBuffer::height() const { - return h; -} - -const char* CharacterFrameBuffer::chars() const { - return chars_vector.data(); -} - -void CharacterFrameBuffer::clear() { - std::fill(chars_vector.begin(), chars_vector.end(), ' '); - std::fill(depth_buf.begin(), depth_buf.end(), 1.f); - face_ind = -1; -} - -void CharacterFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { - std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; - -#define SWAP_IF_LT(X,Y) ({\ - if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ - Vertex3* 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 - - Vertex3 middle_vl = *sorted_vs[1]; - float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); - Vertex3 middle_vr{ - { - sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), - sorted_vs[1]->point.y, - sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) - }, - VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) - }; - if (middle_vr.point.x < middle_vl.point.x) { - Vertex3 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 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); - // depth and vd don't take into account perspective - float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); - // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); - if (depth < depth_buf[x + y * w]) { - depth_buf[x + y * w] = depth; - chars_vector[x + y * w] = face_char(); - } - } - } - } - } - - // 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 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); - // depth and vd don't take into account perspective - float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); - // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); - if (depth < depth_buf[x + y * w]) { - depth_buf[x + y * w] = depth; - chars_vector[x + y * w] = face_char(); - } - } - } - } - } -} - -void CharacterFrameBuffer::draw_triangle(TriangleVertex4 triangle) { - face_ind++; - for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { - for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { - MathVector2 pp1 = t2.vertex1.point.xy(), - pp2 = t2.vertex2.point.xy(), - pp3 = t2.vertex3.point.xy(); - if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; - t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - float fw = static_cast(w), fh = static_cast(h); - t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; - t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; - t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; - t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; - t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; - t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; - _draw_cropped_triangle(t2); - } - } -} - -char CharacterFrameBuffer::face_char() const { - int n = 1 + face_ind / 2; - return (n < 10 ? '0' : 'A' - 10) + n; -} diff --git a/src/chfb.h b/src/chfb.h deleted file mode 100644 index 66fd79c..0000000 --- a/src/chfb.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef CHFB_H -#define CHFB_H - -#include -#include "math_vector.h" -#include "tri_vertex.h" - -class CharacterFrameBuffer { - public: - CharacterFrameBuffer(unsigned int w, unsigned int h); - void resize(unsigned int w, unsigned int h); - unsigned int width() const; - unsigned int height() const; - const char* chars() const; - void clear(); - void draw_triangle(TriangleVertex4 triangle); - - private: - unsigned int w, h; - std::vector chars_vector; - std::vector depth_buf; - int face_ind; - - void _draw_cropped_triangle(TriangleVertex3 triangle); - char face_char() const; -}; - -#endif // CHFB_H diff --git a/src/engine.cpp b/src/engine.cpp index 840d2f9..292f167 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -13,13 +13,13 @@ #include #include #include -#include "chfb.h" -#include "pixfb.h" -#include "obj3d.h" -#include "math_vector.h" -#include "vertex.h" -#include "vertex_data.h" -#include "tri_vertex.h" +#include "fb/chfb.h" +#include "fb/pixfb.h" +#include "o3d/obj3d.h" +#include "o3d/vertex.h" +#include "o3d/vertex_data.h" +#include "o3d/tri_vertex.h" +#include "math/math_vector.h" #define MKEY_Z 122 #define MKEY_Q 113 diff --git a/src/fb/chfb.cpp b/src/fb/chfb.cpp new file mode 100644 index 0000000..7ac1626 --- /dev/null +++ b/src/fb/chfb.cpp @@ -0,0 +1,152 @@ +#include "fb/chfb.h" +#include +#include +#include +#include "math/math_vector.h" +#include "o3d/vertex.h" +#include "o3d/tri_vertex.h" +#include "o3d/vertex_data.h" + +CharacterFrameBuffer::CharacterFrameBuffer(unsigned int w, unsigned int h) { + resize(w, h); +} + +void CharacterFrameBuffer::resize(unsigned int w, unsigned int h) { + this->w = w; + this->h = h; + chars_vector.resize(w * h); + depth_buf.resize(w * h); + clear(); +} + +unsigned int CharacterFrameBuffer::width() const { + return w; +} + +unsigned int CharacterFrameBuffer::height() const { + return h; +} + +const char* CharacterFrameBuffer::chars() const { + return chars_vector.data(); +} + +void CharacterFrameBuffer::clear() { + std::fill(chars_vector.begin(), chars_vector.end(), ' '); + std::fill(depth_buf.begin(), depth_buf.end(), 1.f); + face_ind = -1; +} + +void CharacterFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { + std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; + +#define SWAP_IF_LT(X,Y) ({\ + if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ + Vertex3* 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 + + Vertex3 middle_vl = *sorted_vs[1]; + float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); + Vertex3 middle_vr{ + { + sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), + sorted_vs[1]->point.y, + sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) + }, + VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) + }; + if (middle_vr.point.x < middle_vl.point.x) { + Vertex3 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 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); + // depth and vd don't take into account perspective + float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + chars_vector[x + y * w] = face_char(); + } + } + } + } + } + + // 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 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); + // depth and vd don't take into account perspective + float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + chars_vector[x + y * w] = face_char(); + } + } + } + } + } +} + +void CharacterFrameBuffer::draw_triangle(TriangleVertex4 triangle) { + face_ind++; + for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { + for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { + MathVector2 pp1 = t2.vertex1.point.xy(), + pp2 = t2.vertex2.point.xy(), + pp3 = t2.vertex3.point.xy(); + if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; + t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + float fw = static_cast(w), fh = static_cast(h); + t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; + t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; + t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; + t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; + t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; + t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; + _draw_cropped_triangle(t2); + } + } +} + +char CharacterFrameBuffer::face_char() const { + int n = 1 + face_ind / 2; + return (n < 10 ? '0' : 'A' - 10) + n; +} diff --git a/src/fb/chfb.h b/src/fb/chfb.h new file mode 100644 index 0000000..a3d2ed5 --- /dev/null +++ b/src/fb/chfb.h @@ -0,0 +1,28 @@ +#ifndef FB_CHFB_H +#define FB_CHFB_H + +#include +#include "math/math_vector.h" +#include "o3d/tri_vertex.h" + +class CharacterFrameBuffer { + public: + CharacterFrameBuffer(unsigned int w, unsigned int h); + void resize(unsigned int w, unsigned int h); + unsigned int width() const; + unsigned int height() const; + const char* chars() const; + void clear(); + void draw_triangle(TriangleVertex4 triangle); + + private: + unsigned int w, h; + std::vector chars_vector; + std::vector depth_buf; + int face_ind; + + void _draw_cropped_triangle(TriangleVertex3 triangle); + char face_char() const; +}; + +#endif // FB_CHFB_H diff --git a/src/fb/pixfb.cpp b/src/fb/pixfb.cpp new file mode 100644 index 0000000..d4563ca --- /dev/null +++ b/src/fb/pixfb.cpp @@ -0,0 +1,153 @@ +#include "fb/pixfb.h" +#include +#include +#include +#include +#include "math/math_vector.h" +#include "o3d/vertex.h" +#include "o3d/tri_vertex.h" +#include "o3d/vertex_data.h" + +PixelFrameBuffer::PixelFrameBuffer(unsigned int w, unsigned int h) { + resize(w, h); +} + +void PixelFrameBuffer::resize(unsigned int w, unsigned int h) { + this->w = w; + this->h = h; + pixels_vector.resize(w * h); + depth_buf.resize(w * h); + clear(); +} + +unsigned int PixelFrameBuffer::width() const { + return w; +} + +unsigned int PixelFrameBuffer::height() const { + return h; +} + +const uint32_t* PixelFrameBuffer::pixels() const { + return pixels_vector.data(); +} + +void PixelFrameBuffer::clear() { + std::fill(pixels_vector.begin(), pixels_vector.end(), 0x000000FF); + std::fill(depth_buf.begin(), depth_buf.end(), 1.f); + face_ind = -1; +} + +void PixelFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { + std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; + +#define SWAP_IF_LT(X,Y) ({\ + if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ + Vertex3* 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 + + Vertex3 middle_vl = *sorted_vs[1]; + float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); + Vertex3 middle_vr{ + { + sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), + sorted_vs[1]->point.y, + sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) + }, + VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) + }; + if (middle_vr.point.x < middle_vl.point.x) { + Vertex3 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 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); + // depth and vd don't take into account perspective + float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + pixels_vector[x + y * w] = face_color(); + } + } + } + } + } + + // 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 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); + // depth and vd don't take into account perspective + float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + pixels_vector[x + y * w] = face_color(); + } + } + } + } + } +} + +void PixelFrameBuffer::draw_triangle(TriangleVertex4 triangle) { + face_ind++; + for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { + for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { + MathVector2 pp1 = t2.vertex1.point.xy(), + pp2 = t2.vertex2.point.xy(), + pp3 = t2.vertex3.point.xy(); + if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; + t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + float fw = static_cast(w), fh = static_cast(h); + t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; + t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; + t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; + t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; + t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; + t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; + _draw_cropped_triangle(t2); + } + } +} + +uint32_t PixelFrameBuffer::face_color() const { + int n = face_ind / 2; + return ((n % 2 ? 0xFF000000 : 0x55000000) >> ((n % 6) / 2 * 8)) | 0xFF; +} diff --git a/src/fb/pixfb.h b/src/fb/pixfb.h new file mode 100644 index 0000000..f5f8bde --- /dev/null +++ b/src/fb/pixfb.h @@ -0,0 +1,29 @@ +#ifndef FB_PIXFB_H +#define FB_PIXFB_H + +#include +#include +#include "math/math_vector.h" +#include "o3d/tri_vertex.h" + +class PixelFrameBuffer { + public: + PixelFrameBuffer(unsigned int w, unsigned int h); + void resize(unsigned int w, unsigned int h); + unsigned int width() const; + unsigned int height() const; + const uint32_t* pixels() const; + void clear(); + void draw_triangle(TriangleVertex4 triangle); + + private: + unsigned int w, h; + std::vector pixels_vector; + std::vector depth_buf; + int face_ind; + + void _draw_cropped_triangle(TriangleVertex3 triangle); + uint32_t face_color() const; +}; + +#endif // FB_PIXFB_H diff --git a/src/math/math_vector.cpp b/src/math/math_vector.cpp new file mode 100644 index 0000000..baa2448 --- /dev/null +++ b/src/math/math_vector.cpp @@ -0,0 +1,173 @@ +#include "math/math_vector.h" +#include + +MathVector2::MathVector2() { +} + +MathVector2::MathVector2(float x, float y) : x{x}, y{y} { +} + +bool MathVector2::operator==(MathVector2 other) const { + return x == other.x && y == other.y; +} + +bool MathVector2::operator!=(MathVector2 other) const { + return !(*this == other); +} + +MathVector2 MathVector2::operator+() const { + return *this; +} + +MathVector2 MathVector2::operator-() const { + return { -x, -y }; +} + +MathVector2 MathVector2::operator+(MathVector2 other) const { + return { x + other.x, y + other.y }; +} + +MathVector2 MathVector2::operator-(MathVector2 other) const { + return *this + (-other); +} + +float MathVector2::det(MathVector2 other) const { + return this->x * other.y - other.x * this->y; +} + +MathVector2 MathVector2::round() const { + return { std::round(x), std::round(y) }; +} + +MathVector2 operator*(float n, MathVector2 other) { + return { n * other.x, n * other.y }; +} + +MathVector2 operator*(MathVector2 other, float n) { + return n * other; +} + +MathVector2 operator/(MathVector2 other, float n) { + return { other.x / n, other.y / n }; +} + +MathVector3::MathVector3() { +} + +MathVector3::MathVector3(float x, float y, float z) : x{x}, y{y}, z{z} { +} + +bool MathVector3::operator==(MathVector3 other) const { + return x == other.x && y == other.y && z == other.z; +} + +bool MathVector3::operator!=(MathVector3 other) const { + return !(*this == other); +} + +MathVector3 MathVector3::operator+() const { + return *this; +} + +MathVector3 MathVector3::operator-() const { + return { -x, -y, -z }; +} + +MathVector3 MathVector3::operator+(MathVector3 other) const { + return { x + other.x, y + other.y, z + other.z }; +} + +MathVector3 MathVector3::operator-(MathVector3 other) const { + return *this + (-other); +} + +MathVector3 MathVector3::round() const { + return { std::round(x), std::round(y), std::round(z) }; +} + +MathVector2 MathVector3::xy() const { + return { x, y }; +} + +MathVector3 MathVector3::cross(MathVector3 other) const { + return { + y * other.z - z * other.y, + z * other.x - x * other.z, + x * other.y - y * other.x + }; +} + +MathVector3 operator*(float n, MathVector3 other) { + return { n * other.x, n * other.y, n * other.z }; +} + +MathVector3 operator*(MathVector3 other, float n) { + return n * other; +} + +MathVector3 operator/(MathVector3 other, float n) { + return { other.x / n, other.y / n, other.z / n }; +} + +MathVector4::MathVector4() { +} + +MathVector4::MathVector4(float x, float y, float z, float w) : x{x}, y{y}, z{z}, w{w} { +} + +MathVector4::MathVector4(float x, float y, float z) : x{x}, y{y}, z{z}, w{1.f} { +} + +MathVector4::MathVector4(MathVector3 v, float w) : x{v.x}, y{v.y}, z{v.z}, w{w} { +} + +MathVector4::MathVector4(MathVector3 v) : x{v.x}, y{v.y}, z{v.z}, w{1.f} { +} + +bool MathVector4::operator==(MathVector4 other) const { + return x == other.x && y == other.y && z == other.z && w == other.w; +} + +bool MathVector4::operator!=(MathVector4 other) const { + return !(*this == other); +} + +MathVector4 MathVector4::operator+() const { + return *this; +} + +MathVector4 MathVector4::operator-() const { + return { -x, -y, -z, -w }; +} + +MathVector4 MathVector4::operator+(MathVector4 other) const { + return { x + other.x, y + other.y, z + other.z, w + other.w }; +} + +MathVector4 MathVector4::operator-(MathVector4 other) const { + return *this + (-other); +} + +MathVector4 MathVector4::round() const { + return { std::round(x), std::round(y), std::round(z), std::round(w) }; +} + +MathVector3 MathVector4::xyz() const { + return { x, y, z }; +} + +MathVector3 MathVector4::div_by_w() const { + return xyz() / w; +} + +MathVector4 operator*(float n, MathVector4 other) { + return { n * other.x, n * other.y, n * other.z, n * other.w }; +} + +MathVector4 operator*(MathVector4 other, float n) { + return n * other; +} + +MathVector4 operator/(MathVector4 other, float n) { + return { other.x / n, other.y / n, other.z / n, other.w / n }; +} diff --git a/src/math/math_vector.h b/src/math/math_vector.h new file mode 100644 index 0000000..668a3f3 --- /dev/null +++ b/src/math/math_vector.h @@ -0,0 +1,69 @@ +#ifndef MATH_MATH_VECTOR_H +#define MATH_MATH_VECTOR_H + +class MathVector2 { + public: + float x, y; + + MathVector2(); + MathVector2(float x, float y); + bool operator==(MathVector2 other) const; + bool operator!=(MathVector2 other) const; + MathVector2 operator+() const; + MathVector2 operator-() const; + MathVector2 operator+(MathVector2 other) const; + MathVector2 operator-(MathVector2 other) const; + float det(MathVector2 other) const; + MathVector2 round() const; +}; + +MathVector2 operator*(float n, MathVector2 other); +MathVector2 operator*(MathVector2 other, float n); +MathVector2 operator/(MathVector2 other, float n); + +class MathVector3 { + public: + float x, y, z; + + MathVector3(); + MathVector3(float x, float y, float z); + bool operator==(MathVector3 other) const; + bool operator!=(MathVector3 other) const; + MathVector3 operator+() const; + MathVector3 operator-() const; + MathVector3 operator+(MathVector3 other) const; + MathVector3 operator-(MathVector3 other) const; + MathVector3 round() const; + MathVector2 xy() const; + MathVector3 cross(MathVector3 other) const; +}; + +MathVector3 operator*(float n, MathVector3 other); +MathVector3 operator*(MathVector3 other, float n); +MathVector3 operator/(MathVector3 other, float n); + +class MathVector4 { + public: + float x, y, z, w; + + MathVector4(); + MathVector4(float x, float y, float z, float w); + MathVector4(float x, float y, float z); + MathVector4(MathVector3 v, float w); + MathVector4(MathVector3 v); + bool operator==(MathVector4 other) const; + bool operator!=(MathVector4 other) const; + MathVector4 operator+() const; + MathVector4 operator-() const; + MathVector4 operator+(MathVector4 other) const; + MathVector4 operator-(MathVector4 other) const; + MathVector4 round() const; + MathVector3 xyz() const; + MathVector3 div_by_w() const; +}; + +MathVector4 operator*(float n, MathVector4 other); +MathVector4 operator*(MathVector4 other, float n); +MathVector4 operator/(MathVector4 other, float n); + +#endif // MATH_MATH_VECTOR_H diff --git a/src/math_vector.cpp b/src/math_vector.cpp deleted file mode 100644 index 60081bf..0000000 --- a/src/math_vector.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "math_vector.h" -#include - -MathVector2::MathVector2() { -} - -MathVector2::MathVector2(float x, float y) : x{x}, y{y} { -} - -bool MathVector2::operator==(MathVector2 other) const { - return x == other.x && y == other.y; -} - -bool MathVector2::operator!=(MathVector2 other) const { - return !(*this == other); -} - -MathVector2 MathVector2::operator+() const { - return *this; -} - -MathVector2 MathVector2::operator-() const { - return { -x, -y }; -} - -MathVector2 MathVector2::operator+(MathVector2 other) const { - return { x + other.x, y + other.y }; -} - -MathVector2 MathVector2::operator-(MathVector2 other) const { - return *this + (-other); -} - -float MathVector2::det(MathVector2 other) const { - return this->x * other.y - other.x * this->y; -} - -MathVector2 MathVector2::round() const { - return { std::round(x), std::round(y) }; -} - -MathVector2 operator*(float n, MathVector2 other) { - return { n * other.x, n * other.y }; -} - -MathVector2 operator*(MathVector2 other, float n) { - return n * other; -} - -MathVector2 operator/(MathVector2 other, float n) { - return { other.x / n, other.y / n }; -} - -MathVector3::MathVector3() { -} - -MathVector3::MathVector3(float x, float y, float z) : x{x}, y{y}, z{z} { -} - -bool MathVector3::operator==(MathVector3 other) const { - return x == other.x && y == other.y && z == other.z; -} - -bool MathVector3::operator!=(MathVector3 other) const { - return !(*this == other); -} - -MathVector3 MathVector3::operator+() const { - return *this; -} - -MathVector3 MathVector3::operator-() const { - return { -x, -y, -z }; -} - -MathVector3 MathVector3::operator+(MathVector3 other) const { - return { x + other.x, y + other.y, z + other.z }; -} - -MathVector3 MathVector3::operator-(MathVector3 other) const { - return *this + (-other); -} - -MathVector3 MathVector3::round() const { - return { std::round(x), std::round(y), std::round(z) }; -} - -MathVector2 MathVector3::xy() const { - return { x, y }; -} - -MathVector3 MathVector3::cross(MathVector3 other) const { - return { - y * other.z - z * other.y, - z * other.x - x * other.z, - x * other.y - y * other.x - }; -} - -MathVector3 operator*(float n, MathVector3 other) { - return { n * other.x, n * other.y, n * other.z }; -} - -MathVector3 operator*(MathVector3 other, float n) { - return n * other; -} - -MathVector3 operator/(MathVector3 other, float n) { - return { other.x / n, other.y / n, other.z / n }; -} - -MathVector4::MathVector4() { -} - -MathVector4::MathVector4(float x, float y, float z, float w) : x{x}, y{y}, z{z}, w{w} { -} - -MathVector4::MathVector4(float x, float y, float z) : x{x}, y{y}, z{z}, w{1.f} { -} - -MathVector4::MathVector4(MathVector3 v, float w) : x{v.x}, y{v.y}, z{v.z}, w{w} { -} - -MathVector4::MathVector4(MathVector3 v) : x{v.x}, y{v.y}, z{v.z}, w{1.f} { -} - -bool MathVector4::operator==(MathVector4 other) const { - return x == other.x && y == other.y && z == other.z && w == other.w; -} - -bool MathVector4::operator!=(MathVector4 other) const { - return !(*this == other); -} - -MathVector4 MathVector4::operator+() const { - return *this; -} - -MathVector4 MathVector4::operator-() const { - return { -x, -y, -z, -w }; -} - -MathVector4 MathVector4::operator+(MathVector4 other) const { - return { x + other.x, y + other.y, z + other.z, w + other.w }; -} - -MathVector4 MathVector4::operator-(MathVector4 other) const { - return *this + (-other); -} - -MathVector4 MathVector4::round() const { - return { std::round(x), std::round(y), std::round(z), std::round(w) }; -} - -MathVector3 MathVector4::xyz() const { - return { x, y, z }; -} - -MathVector3 MathVector4::div_by_w() const { - return xyz() / w; -} - -MathVector4 operator*(float n, MathVector4 other) { - return { n * other.x, n * other.y, n * other.z, n * other.w }; -} - -MathVector4 operator*(MathVector4 other, float n) { - return n * other; -} - -MathVector4 operator/(MathVector4 other, float n) { - return { other.x / n, other.y / n, other.z / n, other.w / n }; -} diff --git a/src/math_vector.h b/src/math_vector.h deleted file mode 100644 index 336c3fe..0000000 --- a/src/math_vector.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef MATH_VECTOR_H -#define MATH_VECTOR_H - -class MathVector2 { - public: - float x, y; - - MathVector2(); - MathVector2(float x, float y); - bool operator==(MathVector2 other) const; - bool operator!=(MathVector2 other) const; - MathVector2 operator+() const; - MathVector2 operator-() const; - MathVector2 operator+(MathVector2 other) const; - MathVector2 operator-(MathVector2 other) const; - float det(MathVector2 other) const; - MathVector2 round() const; -}; - -MathVector2 operator*(float n, MathVector2 other); -MathVector2 operator*(MathVector2 other, float n); -MathVector2 operator/(MathVector2 other, float n); - -class MathVector3 { - public: - float x, y, z; - - MathVector3(); - MathVector3(float x, float y, float z); - bool operator==(MathVector3 other) const; - bool operator!=(MathVector3 other) const; - MathVector3 operator+() const; - MathVector3 operator-() const; - MathVector3 operator+(MathVector3 other) const; - MathVector3 operator-(MathVector3 other) const; - MathVector3 round() const; - MathVector2 xy() const; - MathVector3 cross(MathVector3 other) const; -}; - -MathVector3 operator*(float n, MathVector3 other); -MathVector3 operator*(MathVector3 other, float n); -MathVector3 operator/(MathVector3 other, float n); - -class MathVector4 { - public: - float x, y, z, w; - - MathVector4(); - MathVector4(float x, float y, float z, float w); - MathVector4(float x, float y, float z); - MathVector4(MathVector3 v, float w); - MathVector4(MathVector3 v); - bool operator==(MathVector4 other) const; - bool operator!=(MathVector4 other) const; - MathVector4 operator+() const; - MathVector4 operator-() const; - MathVector4 operator+(MathVector4 other) const; - MathVector4 operator-(MathVector4 other) const; - MathVector4 round() const; - MathVector3 xyz() const; - MathVector3 div_by_w() const; -}; - -MathVector4 operator*(float n, MathVector4 other); -MathVector4 operator*(MathVector4 other, float n); -MathVector4 operator/(MathVector4 other, float n); - -#endif // MATH_VECTOR_H diff --git a/src/o3d/obj3d.cpp b/src/o3d/obj3d.cpp new file mode 100644 index 0000000..46f4db6 --- /dev/null +++ b/src/o3d/obj3d.cpp @@ -0,0 +1,46 @@ +#include "o3d/obj3d.h" +#include +#include +#include "o3d/vertex.h" +#include "o3d/tri_vertex.h" + +Object3D::TriangleVertex3Iterator::TriangleVertex3Iterator(const Object3D* obj, int face_ind) : obj{obj}, face_ind{face_ind} { +} + +Object3D::TriangleVertex3Iterator& Object3D::TriangleVertex3Iterator::operator++() { + face_ind++; + return *this; +} + +Object3D::TriangleVertex3Iterator Object3D::TriangleVertex3Iterator::operator++(int) { + TriangleVertex3Iterator retval = *this; + ++(*this); + return retval; +} + +bool Object3D::TriangleVertex3Iterator::operator==(TriangleVertex3Iterator other) const { + return obj == other.obj && face_ind == other.face_ind; +} + +bool Object3D::TriangleVertex3Iterator::operator!=(TriangleVertex3Iterator other) const { + return !(*this == other); +} + +Object3D::TriangleVertex3Iterator::reference Object3D::TriangleVertex3Iterator::operator*() const { + return { + obj->pts[obj->faces[face_ind][0]], + obj->pts[obj->faces[face_ind][1]], + obj->pts[obj->faces[face_ind][2]] + }; +} + +Object3D::Object3D(std::vector pts, std::vector> faces) : pts{pts}, faces{faces} { +} + +Object3D::TriangleVertex3Iterator Object3D::begin() { + return Object3D::TriangleVertex3Iterator{this}; +} + +Object3D::TriangleVertex3Iterator Object3D::end() { + return Object3D::TriangleVertex3Iterator{this, static_cast(faces.size())}; +} diff --git a/src/o3d/obj3d.h b/src/o3d/obj3d.h new file mode 100644 index 0000000..559ed63 --- /dev/null +++ b/src/o3d/obj3d.h @@ -0,0 +1,42 @@ +#ifndef O3D_OBJ3D_H +#define O3D_OBJ3D_H + +#include +#include +#include +#include "o3d/vertex.h" +#include "o3d/tri_vertex.h" + +class Object3D { + public: + class TriangleVertex3Iterator { + public: + using iterator_category = std::input_iterator_tag; + using value_type = TriangleVertex3; + using difference_type = TriangleVertex3; + using pointer = const TriangleVertex3*; + using reference = TriangleVertex3; + + explicit TriangleVertex3Iterator(const Object3D* obj, int face_ind = 0); + TriangleVertex3Iterator& operator++(); + TriangleVertex3Iterator operator++(int); + bool operator==(TriangleVertex3Iterator other) const; + bool operator!=(TriangleVertex3Iterator other) const; + reference operator*() const; + + private: + const Object3D* obj; + int face_ind; + + }; + + Object3D(std::vector pts, std::vector> faces); + TriangleVertex3Iterator begin(); + TriangleVertex3Iterator end(); + + private: + std::vector pts; + std::vector> faces; +}; + +#endif // O3D_OBJ3D_H diff --git a/src/o3d/tri_vertex.cpp b/src/o3d/tri_vertex.cpp new file mode 100644 index 0000000..7b6b379 --- /dev/null +++ b/src/o3d/tri_vertex.cpp @@ -0,0 +1,314 @@ +#include "o3d/tri_vertex.h" +#include +#include "math/math_vector.h" +#include "o3d/vertex_data.h" +#include "o3d/vertex.h" +#include "o3d/tri_vertex.h" + +TriangleVertex3::TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { +} + +#define P1_OUT 1 +#define P2_OUT 2 +#define P3_OUT 4 +static void _crop_x(std::vector& tris, TriangleVertex3 t, int n, float x) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex3* q1; + Vertex3* q2; + Vertex3* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector3 dq2 = q1->point - q2->point; + float fac2 = (x - q2->point.x) / dq2.x; + Vertex3 r2{ + { + x, + q2->point.y + fac2 * dq2.y, + q2->point.z + fac2 * dq2.z + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector3 dq3 = q1->point - q3->point; + float fac3 = (x - q3->point.x) / dq3.x; + Vertex3 r3{ + { + x, + q3->point.y + fac3 * dq3.y, + q3->point.z + fac3 * dq3.z + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +static void _crop_y(std::vector& tris, TriangleVertex3 t, int n, float y) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex3* q1; + Vertex3* q2; + Vertex3* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector3 dq2 = q1->point - q2->point; + float fac2 = (y - q2->point.y) / dq2.y; + Vertex3 r2{ + { + q2->point.x + fac2 * dq2.x, + y, + q2->point.z + fac2 * dq2.z + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector3 dq3 = q1->point - q3->point; + float fac3 = (y - q3->point.y) / dq3.y; + Vertex3 r3{ + { + q3->point.x + fac3 * dq3.x, + y, + q3->point.z + fac3 * dq3.z + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +std::vector TriangleVertex3::crop_xy_out(float x1, float x2, float y1, float y2) const { + std::vector tris_final; + std::vector tris1; + _crop_x(tris1, *this, (vertex1.point.x < x1) | ((vertex2.point.x < x1) << 1) | ((vertex3.point.x < x1) << 2), x1); + for (auto t1 : tris1) { + std::vector tris2; + _crop_x(tris2, t1, (t1.vertex1.point.x > x2) | ((t1.vertex2.point.x > x2) << 1) | ((t1.vertex3.point.x > x2) << 2), x2); + for (auto t2 : tris2) { + std::vector tris3; + _crop_y(tris3, t2, (t2.vertex1.point.y < y1) | ((t2.vertex2.point.y < y1) << 1) | ((t2.vertex3.point.y < y1) << 2), y1); + for (auto t3 : tris3) + _crop_y(tris_final, t3, (t3.vertex1.point.y > y2) | ((t3.vertex2.point.y > y2) << 1) | ((t3.vertex3.point.y > y2) << 2), y2); + } + } + return tris_final; +} +#undef P1_OUT +#undef P2_OUT +#undef P3_OUT + +TriangleVertex4::TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { +} + +TriangleVertex4::TriangleVertex4(TriangleVertex3 triangle) : vertex1{triangle.vertex1}, vertex2{triangle.vertex2}, vertex3{triangle.vertex3} { +} + +#define P1_OUT 1 +#define P2_OUT 2 +#define P3_OUT 4 +static void _crop_z(std::vector& tris, TriangleVertex4 t, int n, float z) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex4* q1; + Vertex4* q2; + Vertex4* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector4 dq2 = q1->point - q2->point; + float fac2 = (z - q2->point.z) / dq2.z; + Vertex4 r2{ + { + q2->point.x + fac2 * dq2.x, + q2->point.y + fac2 * dq2.y, + z, + q2->point.w + fac2 * dq2.w + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector4 dq3 = q1->point - q3->point; + float fac3 = (z - q3->point.z) / dq3.z; + Vertex4 r3{ + { + q3->point.x + fac3 * dq3.x, + q3->point.y + fac3 * dq3.y, + z, + q3->point.w + fac3 * dq3.w + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +std::vector TriangleVertex4::crop_z_out(float z1, float z2) const { + std::vector tris; + _crop_z(tris, *this, (vertex1.point.z < z1) | ((vertex2.point.z < z1) << 1) | ((vertex3.point.z < z1) << 2), z1); + std::vector tris2; + for (auto t : tris) + _crop_z(tris2, t, (t.vertex1.point.z > z2) | ((t.vertex2.point.z > z2) << 1) | ((t.vertex3.point.z > z2) << 2), z2); + return tris2; +} +#undef P1_OUT +#undef P2_OUT +#undef P3_OUT + +TriangleVertex3 TriangleVertex4::div_by_w() const { + return {vertex1.div_by_w(), vertex2.div_by_w(), vertex3.div_by_w()}; +} diff --git a/src/o3d/tri_vertex.h b/src/o3d/tri_vertex.h new file mode 100644 index 0000000..91e20f5 --- /dev/null +++ b/src/o3d/tri_vertex.h @@ -0,0 +1,29 @@ +#ifndef O3D_TRI_VERTEX_H +#define O3D_TRI_VERTEX_H + +#include "o3d/vertex.h" +#include + +class TriangleVertex3 { + public: + Vertex3 vertex1; + Vertex3 vertex2; + Vertex3 vertex3; + + TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3); + std::vector crop_xy_out(float x1, float x2, float y1, float y2) const; +}; + +class TriangleVertex4 { + public: + Vertex4 vertex1; + Vertex4 vertex2; + Vertex4 vertex3; + + TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3); + TriangleVertex4(TriangleVertex3 triangle); + std::vector crop_z_out(float z1, float z2) const; + TriangleVertex3 div_by_w() const; +}; + +#endif // O3D_TRI_VERTEX_H diff --git a/src/o3d/vertex.cpp b/src/o3d/vertex.cpp new file mode 100644 index 0000000..c3bddef --- /dev/null +++ b/src/o3d/vertex.cpp @@ -0,0 +1,16 @@ +#include "o3d/vertex.h" +#include "math/math_vector.h" +#include "o3d/vertex_data.h" + +Vertex3::Vertex3(MathVector3 point, VertexData data) : point{point}, data{data} { +} + +Vertex4::Vertex4(MathVector4 point, VertexData data) : point{point}, data{data} { +} + +Vertex4::Vertex4(Vertex3 vertex) : point{vertex.point}, data{vertex.data} { +} + +Vertex3 Vertex4::div_by_w() const { + return {point.div_by_w(), data}; +} diff --git a/src/o3d/vertex.h b/src/o3d/vertex.h new file mode 100644 index 0000000..27ca56a --- /dev/null +++ b/src/o3d/vertex.h @@ -0,0 +1,25 @@ +#ifndef O3D_VERTEX_H +#define O3D_VERTEX_H + +#include "math/math_vector.h" +#include "o3d/vertex_data.h" + +class Vertex3 { + public: + MathVector3 point; + VertexData data; + + Vertex3(MathVector3 point, VertexData data); +}; + +class Vertex4 { + public: + MathVector4 point; + VertexData data; + + Vertex4(MathVector4 point, VertexData data); + Vertex4(Vertex3 vertex); + Vertex3 div_by_w() const; +}; + +#endif // O3D_VERTEX_H diff --git a/src/o3d/vertex_data.cpp b/src/o3d/vertex_data.cpp new file mode 100644 index 0000000..8d6f77b --- /dev/null +++ b/src/o3d/vertex_data.cpp @@ -0,0 +1,12 @@ +#include "o3d/vertex_data.h" + +VertexData VertexData::lerp(VertexData& vd1, VertexData& vd2, float s) { + return {}; +} + +VertexData VertexData::bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t) { + return {}; +} + +VertexData::VertexData() { +} diff --git a/src/o3d/vertex_data.h b/src/o3d/vertex_data.h new file mode 100644 index 0000000..0000dda --- /dev/null +++ b/src/o3d/vertex_data.h @@ -0,0 +1,12 @@ +#ifndef O3D_VERTEX_DATA_H +#define O3D_VERTEX_DATA_H + +class VertexData { + public: + static VertexData lerp(VertexData& vd1, VertexData& vd2, float s); + static VertexData bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t); + + VertexData(); +}; + +#endif // O3D_VERTEX_DATA_H diff --git a/src/obj3d.cpp b/src/obj3d.cpp deleted file mode 100644 index 3902d30..0000000 --- a/src/obj3d.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "obj3d.h" -#include -#include -#include "vertex.h" -#include "tri_vertex.h" - -Object3D::TriangleVertex3Iterator::TriangleVertex3Iterator(const Object3D* obj, int face_ind) : obj{obj}, face_ind{face_ind} { -} - -Object3D::TriangleVertex3Iterator& Object3D::TriangleVertex3Iterator::operator++() { - face_ind++; - return *this; -} - -Object3D::TriangleVertex3Iterator Object3D::TriangleVertex3Iterator::operator++(int) { - TriangleVertex3Iterator retval = *this; - ++(*this); - return retval; -} - -bool Object3D::TriangleVertex3Iterator::operator==(TriangleVertex3Iterator other) const { - return obj == other.obj && face_ind == other.face_ind; -} - -bool Object3D::TriangleVertex3Iterator::operator!=(TriangleVertex3Iterator other) const { - return !(*this == other); -} - -Object3D::TriangleVertex3Iterator::reference Object3D::TriangleVertex3Iterator::operator*() const { - return { - obj->pts[obj->faces[face_ind][0]], - obj->pts[obj->faces[face_ind][1]], - obj->pts[obj->faces[face_ind][2]] - }; -} - -Object3D::Object3D(std::vector pts, std::vector> faces) : pts{pts}, faces{faces} { -} - -Object3D::TriangleVertex3Iterator Object3D::begin() { - return Object3D::TriangleVertex3Iterator{this}; -} - -Object3D::TriangleVertex3Iterator Object3D::end() { - return Object3D::TriangleVertex3Iterator{this, static_cast(faces.size())}; -} diff --git a/src/obj3d.h b/src/obj3d.h deleted file mode 100644 index b76f06d..0000000 --- a/src/obj3d.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef OBJ3D_H -#define OBJ3D_H - -#include -#include -#include -#include "vertex.h" -#include "tri_vertex.h" - -class Object3D { - public: - class TriangleVertex3Iterator { - public: - using iterator_category = std::input_iterator_tag; - using value_type = TriangleVertex3; - using difference_type = TriangleVertex3; - using pointer = const TriangleVertex3*; - using reference = TriangleVertex3; - - explicit TriangleVertex3Iterator(const Object3D* obj, int face_ind = 0); - TriangleVertex3Iterator& operator++(); - TriangleVertex3Iterator operator++(int); - bool operator==(TriangleVertex3Iterator other) const; - bool operator!=(TriangleVertex3Iterator other) const; - reference operator*() const; - - private: - const Object3D* obj; - int face_ind; - - }; - - Object3D(std::vector pts, std::vector> faces); - TriangleVertex3Iterator begin(); - TriangleVertex3Iterator end(); - - private: - std::vector pts; - std::vector> faces; -}; - -#endif // OBJ3D_H diff --git a/src/pixfb.cpp b/src/pixfb.cpp deleted file mode 100644 index f84bf2f..0000000 --- a/src/pixfb.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "pixfb.h" -#include -#include -#include -#include -#include "math_vector.h" -#include "vertex.h" -#include "tri_vertex.h" -#include "vertex_data.h" - -PixelFrameBuffer::PixelFrameBuffer(unsigned int w, unsigned int h) { - resize(w, h); -} - -void PixelFrameBuffer::resize(unsigned int w, unsigned int h) { - this->w = w; - this->h = h; - pixels_vector.resize(w * h); - depth_buf.resize(w * h); - clear(); -} - -unsigned int PixelFrameBuffer::width() const { - return w; -} - -unsigned int PixelFrameBuffer::height() const { - return h; -} - -const uint32_t* PixelFrameBuffer::pixels() const { - return pixels_vector.data(); -} - -void PixelFrameBuffer::clear() { - std::fill(pixels_vector.begin(), pixels_vector.end(), 0x000000FF); - std::fill(depth_buf.begin(), depth_buf.end(), 1.f); - face_ind = -1; -} - -void PixelFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { - std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; - -#define SWAP_IF_LT(X,Y) ({\ - if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ - Vertex3* 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 - - Vertex3 middle_vl = *sorted_vs[1]; - float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); - Vertex3 middle_vr{ - { - sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), - sorted_vs[1]->point.y, - sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) - }, - VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) - }; - if (middle_vr.point.x < middle_vl.point.x) { - Vertex3 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 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); - // depth and vd don't take into account perspective - float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); - // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); - if (depth < depth_buf[x + y * w]) { - depth_buf[x + y * w] = depth; - pixels_vector[x + y * w] = face_color(); - } - } - } - } - } - - // 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 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); - // depth and vd don't take into account perspective - float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); - // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); - if (depth < depth_buf[x + y * w]) { - depth_buf[x + y * w] = depth; - pixels_vector[x + y * w] = face_color(); - } - } - } - } - } -} - -void PixelFrameBuffer::draw_triangle(TriangleVertex4 triangle) { - face_ind++; - for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { - for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { - MathVector2 pp1 = t2.vertex1.point.xy(), - pp2 = t2.vertex2.point.xy(), - pp3 = t2.vertex3.point.xy(); - if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; - t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; - float fw = static_cast(w), fh = static_cast(h); - t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; - t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; - t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; - t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; - t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; - t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; - _draw_cropped_triangle(t2); - } - } -} - -uint32_t PixelFrameBuffer::face_color() const { - int n = face_ind / 2; - return ((n % 2 ? 0xFF000000 : 0x55000000) >> ((n % 6) / 2 * 8)) | 0xFF; -} diff --git a/src/pixfb.h b/src/pixfb.h deleted file mode 100644 index c54b5fb..0000000 --- a/src/pixfb.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef PIXFB_H -#define PIXFB_H - -#include -#include -#include "math_vector.h" -#include "tri_vertex.h" - -class PixelFrameBuffer { - public: - PixelFrameBuffer(unsigned int w, unsigned int h); - void resize(unsigned int w, unsigned int h); - unsigned int width() const; - unsigned int height() const; - const uint32_t* pixels() const; - void clear(); - void draw_triangle(TriangleVertex4 triangle); - - private: - unsigned int w, h; - std::vector pixels_vector; - std::vector depth_buf; - int face_ind; - - void _draw_cropped_triangle(TriangleVertex3 triangle); - uint32_t face_color() const; -}; - -#endif // PIXFB_H diff --git a/src/tri_vertex.cpp b/src/tri_vertex.cpp deleted file mode 100644 index cd07770..0000000 --- a/src/tri_vertex.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "tri_vertex.h" -#include -#include "math_vector.h" -#include "vertex_data.h" -#include "vertex.h" -#include "tri_vertex.h" - -TriangleVertex3::TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { -} - -#define P1_OUT 1 -#define P2_OUT 2 -#define P3_OUT 4 -static void _crop_x(std::vector& tris, TriangleVertex3 t, int n, float x) { - switch (n) { - case 0: - tris.push_back(t); - break; - case P1_OUT: - case P2_OUT: - case P3_OUT: - case P2_OUT | P3_OUT: - case P1_OUT | P3_OUT: - case P1_OUT | P2_OUT: - { - Vertex3* q1; - Vertex3* q2; - Vertex3* q3; - switch (n) { - case P1_OUT: - case P2_OUT | P3_OUT: - q1 = &t.vertex1; - q2 = &t.vertex2; - q3 = &t.vertex3; - break; - case P2_OUT: - case P1_OUT | P3_OUT: - q1 = &t.vertex2; - q2 = &t.vertex1; - q3 = &t.vertex3; - break; - case P3_OUT: - case P1_OUT | P2_OUT: - q1 = &t.vertex3; - q2 = &t.vertex2; - q3 = &t.vertex1; - break; - } - MathVector3 dq2 = q1->point - q2->point; - float fac2 = (x - q2->point.x) / dq2.x; - Vertex3 r2{ - { - x, - q2->point.y + fac2 * dq2.y, - q2->point.z + fac2 * dq2.z - }, - VertexData::lerp(q2->data, q1->data, fac2) - }; - MathVector3 dq3 = q1->point - q3->point; - float fac3 = (x - q3->point.x) / dq3.x; - Vertex3 r3{ - { - x, - q3->point.y + fac3 * dq3.y, - q3->point.z + fac3 * dq3.z - }, - VertexData::lerp(q3->data, q1->data, fac3) - }; - switch (n) { - case P1_OUT: - tris.push_back({r3, *q2, *q3}); - tris.push_back({r3, r2, *q2}); - break; - case P2_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P3_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P2_OUT | P3_OUT: - tris.push_back({*q1, r2, r3}); - break; - case P1_OUT | P3_OUT: - tris.push_back({*q1, r3, r2}); - break; - case P1_OUT | P2_OUT: - tris.push_back({*q1, r3, r2}); - break; - } - } - break; - case P1_OUT | P2_OUT | P3_OUT: - break; - } -} - -static void _crop_y(std::vector& tris, TriangleVertex3 t, int n, float y) { - switch (n) { - case 0: - tris.push_back(t); - break; - case P1_OUT: - case P2_OUT: - case P3_OUT: - case P2_OUT | P3_OUT: - case P1_OUT | P3_OUT: - case P1_OUT | P2_OUT: - { - Vertex3* q1; - Vertex3* q2; - Vertex3* q3; - switch (n) { - case P1_OUT: - case P2_OUT | P3_OUT: - q1 = &t.vertex1; - q2 = &t.vertex2; - q3 = &t.vertex3; - break; - case P2_OUT: - case P1_OUT | P3_OUT: - q1 = &t.vertex2; - q2 = &t.vertex1; - q3 = &t.vertex3; - break; - case P3_OUT: - case P1_OUT | P2_OUT: - q1 = &t.vertex3; - q2 = &t.vertex2; - q3 = &t.vertex1; - break; - } - MathVector3 dq2 = q1->point - q2->point; - float fac2 = (y - q2->point.y) / dq2.y; - Vertex3 r2{ - { - q2->point.x + fac2 * dq2.x, - y, - q2->point.z + fac2 * dq2.z - }, - VertexData::lerp(q2->data, q1->data, fac2) - }; - MathVector3 dq3 = q1->point - q3->point; - float fac3 = (y - q3->point.y) / dq3.y; - Vertex3 r3{ - { - q3->point.x + fac3 * dq3.x, - y, - q3->point.z + fac3 * dq3.z - }, - VertexData::lerp(q3->data, q1->data, fac3) - }; - switch (n) { - case P1_OUT: - tris.push_back({r3, *q2, *q3}); - tris.push_back({r3, r2, *q2}); - break; - case P2_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P3_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P2_OUT | P3_OUT: - tris.push_back({*q1, r2, r3}); - break; - case P1_OUT | P3_OUT: - tris.push_back({*q1, r3, r2}); - break; - case P1_OUT | P2_OUT: - tris.push_back({*q1, r3, r2}); - break; - } - } - break; - case P1_OUT | P2_OUT | P3_OUT: - break; - } -} - -std::vector TriangleVertex3::crop_xy_out(float x1, float x2, float y1, float y2) const { - std::vector tris_final; - std::vector tris1; - _crop_x(tris1, *this, (vertex1.point.x < x1) | ((vertex2.point.x < x1) << 1) | ((vertex3.point.x < x1) << 2), x1); - for (auto t1 : tris1) { - std::vector tris2; - _crop_x(tris2, t1, (t1.vertex1.point.x > x2) | ((t1.vertex2.point.x > x2) << 1) | ((t1.vertex3.point.x > x2) << 2), x2); - for (auto t2 : tris2) { - std::vector tris3; - _crop_y(tris3, t2, (t2.vertex1.point.y < y1) | ((t2.vertex2.point.y < y1) << 1) | ((t2.vertex3.point.y < y1) << 2), y1); - for (auto t3 : tris3) - _crop_y(tris_final, t3, (t3.vertex1.point.y > y2) | ((t3.vertex2.point.y > y2) << 1) | ((t3.vertex3.point.y > y2) << 2), y2); - } - } - return tris_final; -} -#undef P1_OUT -#undef P2_OUT -#undef P3_OUT - -TriangleVertex4::TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { -} - -TriangleVertex4::TriangleVertex4(TriangleVertex3 triangle) : vertex1{triangle.vertex1}, vertex2{triangle.vertex2}, vertex3{triangle.vertex3} { -} - -#define P1_OUT 1 -#define P2_OUT 2 -#define P3_OUT 4 -static void _crop_z(std::vector& tris, TriangleVertex4 t, int n, float z) { - switch (n) { - case 0: - tris.push_back(t); - break; - case P1_OUT: - case P2_OUT: - case P3_OUT: - case P2_OUT | P3_OUT: - case P1_OUT | P3_OUT: - case P1_OUT | P2_OUT: - { - Vertex4* q1; - Vertex4* q2; - Vertex4* q3; - switch (n) { - case P1_OUT: - case P2_OUT | P3_OUT: - q1 = &t.vertex1; - q2 = &t.vertex2; - q3 = &t.vertex3; - break; - case P2_OUT: - case P1_OUT | P3_OUT: - q1 = &t.vertex2; - q2 = &t.vertex1; - q3 = &t.vertex3; - break; - case P3_OUT: - case P1_OUT | P2_OUT: - q1 = &t.vertex3; - q2 = &t.vertex2; - q3 = &t.vertex1; - break; - } - MathVector4 dq2 = q1->point - q2->point; - float fac2 = (z - q2->point.z) / dq2.z; - Vertex4 r2{ - { - q2->point.x + fac2 * dq2.x, - q2->point.y + fac2 * dq2.y, - z, - q2->point.w + fac2 * dq2.w - }, - VertexData::lerp(q2->data, q1->data, fac2) - }; - MathVector4 dq3 = q1->point - q3->point; - float fac3 = (z - q3->point.z) / dq3.z; - Vertex4 r3{ - { - q3->point.x + fac3 * dq3.x, - q3->point.y + fac3 * dq3.y, - z, - q3->point.w + fac3 * dq3.w - }, - VertexData::lerp(q3->data, q1->data, fac3) - }; - switch (n) { - case P1_OUT: - tris.push_back({r3, *q2, *q3}); - tris.push_back({r3, r2, *q2}); - break; - case P2_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P3_OUT: - tris.push_back({r2, *q3, *q2}); - tris.push_back({r2, r3, *q3}); - break; - case P2_OUT | P3_OUT: - tris.push_back({*q1, r2, r3}); - break; - case P1_OUT | P3_OUT: - tris.push_back({*q1, r3, r2}); - break; - case P1_OUT | P2_OUT: - tris.push_back({*q1, r3, r2}); - break; - } - } - break; - case P1_OUT | P2_OUT | P3_OUT: - break; - } -} - -std::vector TriangleVertex4::crop_z_out(float z1, float z2) const { - std::vector tris; - _crop_z(tris, *this, (vertex1.point.z < z1) | ((vertex2.point.z < z1) << 1) | ((vertex3.point.z < z1) << 2), z1); - std::vector tris2; - for (auto t : tris) - _crop_z(tris2, t, (t.vertex1.point.z > z2) | ((t.vertex2.point.z > z2) << 1) | ((t.vertex3.point.z > z2) << 2), z2); - return tris2; -} -#undef P1_OUT -#undef P2_OUT -#undef P3_OUT - -TriangleVertex3 TriangleVertex4::div_by_w() const { - return {vertex1.div_by_w(), vertex2.div_by_w(), vertex3.div_by_w()}; -} diff --git a/src/tri_vertex.h b/src/tri_vertex.h deleted file mode 100644 index 5bbdd40..0000000 --- a/src/tri_vertex.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef TRI_VERTEX_H -#define TRI_VERTEX_H - -#include "vertex.h" -#include - -class TriangleVertex3 { - public: - Vertex3 vertex1; - Vertex3 vertex2; - Vertex3 vertex3; - - TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3); - std::vector crop_xy_out(float x1, float x2, float y1, float y2) const; -}; - -class TriangleVertex4 { - public: - Vertex4 vertex1; - Vertex4 vertex2; - Vertex4 vertex3; - - TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3); - TriangleVertex4(TriangleVertex3 triangle); - std::vector crop_z_out(float z1, float z2) const; - TriangleVertex3 div_by_w() const; -}; - -#endif // TRI_VERTEX_H diff --git a/src/vertex.cpp b/src/vertex.cpp deleted file mode 100644 index d136754..0000000 --- a/src/vertex.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "vertex.h" -#include "math_vector.h" -#include "vertex_data.h" - -Vertex3::Vertex3(MathVector3 point, VertexData data) : point{point}, data{data} { -} - -Vertex4::Vertex4(MathVector4 point, VertexData data) : point{point}, data{data} { -} - -Vertex4::Vertex4(Vertex3 vertex) : point{vertex.point}, data{vertex.data} { -} - -Vertex3 Vertex4::div_by_w() const { - return {point.div_by_w(), data}; -} diff --git a/src/vertex.h b/src/vertex.h deleted file mode 100644 index 92b7dcb..0000000 --- a/src/vertex.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef VERTEX_H -#define VERTEX_H - -#include "math_vector.h" -#include "vertex_data.h" - -class Vertex3 { - public: - MathVector3 point; - VertexData data; - - Vertex3(MathVector3 point, VertexData data); -}; - -class Vertex4 { - public: - MathVector4 point; - VertexData data; - - Vertex4(MathVector4 point, VertexData data); - Vertex4(Vertex3 vertex); - Vertex3 div_by_w() const; -}; - -#endif // VERTEX_H diff --git a/src/vertex_data.cpp b/src/vertex_data.cpp deleted file mode 100644 index 23c8b03..0000000 --- a/src/vertex_data.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "vertex_data.h" - -VertexData VertexData::lerp(VertexData& vd1, VertexData& vd2, float s) { - return {}; -} - -VertexData VertexData::bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t) { - return {}; -} - -VertexData::VertexData() { -} diff --git a/src/vertex_data.h b/src/vertex_data.h deleted file mode 100644 index e35d65a..0000000 --- a/src/vertex_data.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef VERTEX_DATA_H -#define VERTEX_DATA_H - -class VertexData { - public: - static VertexData lerp(VertexData& vd1, VertexData& vd2, float s); - static VertexData bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t); - - VertexData(); -}; - -#endif // VERTEX_DATA_H -- cgit v1.2.3