diff options
Diffstat (limited to 'src/o3d')
-rw-r--r-- | src/o3d/obj3d.cpp | 46 | ||||
-rw-r--r-- | src/o3d/obj3d.h | 42 | ||||
-rw-r--r-- | src/o3d/tri_vertex.cpp | 314 | ||||
-rw-r--r-- | src/o3d/tri_vertex.h | 29 | ||||
-rw-r--r-- | src/o3d/vertex.cpp | 16 | ||||
-rw-r--r-- | src/o3d/vertex.h | 25 | ||||
-rw-r--r-- | src/o3d/vertex_data.cpp | 12 | ||||
-rw-r--r-- | src/o3d/vertex_data.h | 12 |
8 files changed, 496 insertions, 0 deletions
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 <vector> +#include <array> +#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<Vertex3> pts, std::vector<std::array<int, 3>> faces) : pts{pts}, faces{faces} { +} + +Object3D::TriangleVertex3Iterator Object3D::begin() { + return Object3D::TriangleVertex3Iterator{this}; +} + +Object3D::TriangleVertex3Iterator Object3D::end() { + return Object3D::TriangleVertex3Iterator{this, static_cast<int>(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 <vector> +#include <array> +#include <iterator> +#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<Vertex3> pts, std::vector<std::array<int, 3>> faces); + TriangleVertex3Iterator begin(); + TriangleVertex3Iterator end(); + + private: + std::vector<Vertex3> pts; + std::vector<std::array<int, 3>> 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 <vector> +#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<TriangleVertex3>& 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<TriangleVertex3>& 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> TriangleVertex3::crop_xy_out(float x1, float x2, float y1, float y2) const { + std::vector<TriangleVertex3> tris_final; + std::vector<TriangleVertex3> 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<TriangleVertex3> 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<TriangleVertex3> 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<TriangleVertex4>& 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> TriangleVertex4::crop_z_out(float z1, float z2) const { + std::vector<TriangleVertex4> tris; + _crop_z(tris, *this, (vertex1.point.z < z1) | ((vertex2.point.z < z1) << 1) | ((vertex3.point.z < z1) << 2), z1); + std::vector<TriangleVertex4> 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 <vector> + +class TriangleVertex3 { + public: + Vertex3 vertex1; + Vertex3 vertex2; + Vertex3 vertex3; + + TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3); + std::vector<TriangleVertex3> 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<TriangleVertex4> 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 |