diff --git a/include/Orange/Core/Array.h b/include/Orange/Core/Array.h index e8f3995..343b9d8 100644 --- a/include/Orange/Core/Array.h +++ b/include/Orange/Core/Array.h @@ -13,7 +13,12 @@ namespace orange constexpr Array(const T components[Size]) { - Copy(&components[0], &components[Size], m_data.begin()); + Copy(&components[0], &components[Size], begin()); + } + + constexpr Array(std::initializer_list list) + { + Copy(list.begin(), list.end(), begin()); } template diff --git a/include/Orange/Core/Traits.h b/include/Orange/Core/Traits.h index d154ba3..ec5019c 100644 --- a/include/Orange/Core/Traits.h +++ b/include/Orange/Core/Traits.h @@ -4,6 +4,7 @@ // Needed for placement new/delete. #include +#include namespace orange { diff --git a/include/Orange/Core/Vector.h b/include/Orange/Core/Vector.h index 775fe22..d0abc74 100644 --- a/include/Orange/Core/Vector.h +++ b/include/Orange/Core/Vector.h @@ -19,9 +19,26 @@ namespace orange for (const auto& val : span) PushBack(val); } + constexpr SmallVector(std::initializer_list list) + { + Reserve(list.size()); + for (const auto& val : list) + PushBack(val); + } - SmallVector (const SmallVector&) = delete; - SmallVector& operator = (const SmallVector&) = delete; + SmallVector (const SmallVector& x) + { + Reserve(x.Size()); + for (const auto& val : x) + PushBack(val); + } + SmallVector& operator = (const SmallVector& x) + { + Clear(); + Reserve(x.Size()); + for (const auto& val : x) + PushBack(val); + } ~SmallVector() { @@ -70,6 +87,11 @@ namespace orange const T* Data() const { return Ptr(0); } T* Data() { return Ptr(0); } + void Clear() + { + Resize(0); + } + void Resize(size_t n) { Reserve(n); @@ -83,23 +105,26 @@ namespace orange m_size = n; } - void PushBack(const T& object) + size_t PushBack(const T& object) { Reserve(m_size + 1); new (Ptr(m_size++)) T(object); + return m_size - 1; } - void PushBack(T&& object) + size_t PushBack(T&& object) { Reserve(m_size + 1); new (Ptr(m_size++)) T(Move(object)); + return m_size - 1; } template - void EmplaceBack(Args... args) + size_t EmplaceBack(Args... args) { Reserve(m_size + 1); new (Ptr(m_size++)) T(Forward(args)...); + return m_size - 1; } void Erase(size_t idx) @@ -123,6 +148,24 @@ namespace orange return Size() == 0; } + constexpr static size_t InvalidIdx = ~(0zu); + + size_t FindIdx(const T& x) const + { + for (size_t i = 0; i < m_size; i++) + { + if (*Ptr(i) == x) + return i; + } + + return InvalidIdx; + } + + bool Contains(const T& x) const + { + return FindIdx(x) != InvalidIdx; + } + T& operator [] (size_t idx) { return *Ptr(idx); } const T& operator [] (size_t idx) const { return *Ptr(idx); } diff --git a/include/Orange/Math/Vector.h b/include/Orange/Math/Vector.h index 7174e62..c8b81d2 100644 --- a/include/Orange/Math/Vector.h +++ b/include/Orange/Math/Vector.h @@ -267,9 +267,21 @@ namespace orange return a == Vec::Identity; } - using Vec1 = Vec; - using Vec2 = Vec; - using Vec3 = Vec; - using Vec4 = Vec; + template + constexpr Vec Min(const Vec& a, const Vec& b) + { + return TransformResult>(a.begin(), a.end(), b.begin(), [](T val_a, T val_b){ return Min(val_a, val_b); }); + } + + template + constexpr Vec Max(const Vec& a, const Vec& b) + { + return TransformResult>(a.begin(), a.end(), b.begin(), [](T val_a, T val_b){ return Max(val_a, val_b); }); + } + + using vec1 = Vec; + using vec2 = Vec; + using vec3 = Vec; + using vec4 = Vec; } diff --git a/src/Apps/Tools/CubeTest.cpp b/src/Apps/Tools/CubeTest.cpp index c08025c..bf6ba18 100644 --- a/src/Apps/Tools/CubeTest.cpp +++ b/src/Apps/Tools/CubeTest.cpp @@ -12,8 +12,45 @@ using namespace orange; -Result ParseOBJ(StringView buffer) +struct AABB { + vec3 min; + vec3 max; + + void Extend(vec3 pos) + { + min = Min(pos, min); + max = Max(pos, max); + } +}; + +struct Vertex +{ + vec3 pos; + vec2 uv; + vec3 normal; + + bool operator == (const Vertex& other) const + { + return pos == other.pos && uv == other.uv && normal == other.normal; + } +}; + +struct MeshData +{ + Vector vertices; + Vector indices; + AABB bounds; +}; + +Result ParseOBJ(StringView buffer) +{ + MeshData data; + + Vector positions; + Vector uvs; + Vector normals; + const char* obj = buffer.data; const char* end = buffer.data + buffer.size; while (obj != end) @@ -21,7 +58,7 @@ Result ParseOBJ(StringView buffer) SmallVector element; stream::ReadString(obj, end, " #\n", element); - if (element == "v" || element == "vn" || element == "vt") + if (element == "v" || element == "vt" || element == "vn") { float vtx[3]{}; for (int i = 0; i < 3; i++) @@ -30,11 +67,15 @@ Result ParseOBJ(StringView buffer) if (auto r_float = stream::Parse(obj, end)) vtx[i] = *r_float; else - return Result::Error(); + return Result::Error(); } - element.PushBack('\0'); - log::info("Found: %s %f %f %f", element.Data(), vtx[0], vtx[1], vtx[2]); + if (element == "v") + positions.EmplaceBack(vtx[0], vtx[1], vtx[2]); + else if (element == "vt") + normals.EmplaceBack(vtx[0], vtx[1], vtx[2]); + else if (element == "vn") + uvs.EmplaceBack(vtx[0], vtx[1]); } else if (element == "g" || element == "o") { @@ -66,10 +107,26 @@ Result ParseOBJ(StringView buffer) } } } - log::info("Found: f %d/%d/%d %d/%d/%d %d/%d/%d", - indices[0][0], indices[0][1], indices[0][2], - indices[1][0], indices[1][1], indices[1][2], - indices[2][0], indices[2][1], indices[2][2]); + + for (int i = 0; i < 3; i++) + { + Vertex vertex = + { + .pos = indices[i][0] != -1 ? positions[indices[i][0]] : vec3{}, + .uv = indices[i][1] != -1 ? uvs [indices[i][1]] : vec2{}, + .normal = indices[i][2] != -1 ? normals [indices[i][2]] : vec3{}, + }; + + size_t vertexIdx = data.vertices.FindIdx(vertex); + if (vertexIdx == Vector::InvalidIdx) + { + data.bounds.Extend(vertex.pos); + vertexIdx = data.vertices.PushBack(vertex); + } + + Assert(vertexIdx < UINT16_MAX); + data.indices.PushBack(uint16_t(vertexIdx)); + } } else if (!element.Empty()) { @@ -80,7 +137,7 @@ Result ParseOBJ(StringView buffer) stream::AdvancePast(obj, end, "\n"); }; - return Result::Success(); + return Result::Success(data); } int main(int argc, char** argv) @@ -107,9 +164,7 @@ int main(int argc, char** argv) if (!r_objData) return 1; - ParseOBJ(*r_objData); - - return 0; + auto r_mesh = ParseOBJ(*r_objData); while (r_window->Update()) {