diff --git a/include/Orange/Core/Traits.h b/include/Orange/Core/Traits.h index 5bd9cfc..2c87511 100644 --- a/include/Orange/Core/Traits.h +++ b/include/Orange/Core/Traits.h @@ -7,6 +7,10 @@ #include #include +#ifndef offsetof2 +#define offsetof2(type, member) size_t(uintptr_t(&((type*)0)->member)) +#endif + namespace orange { template diff --git a/include/Orange/Graphics/Mesh.h b/include/Orange/Graphics/Mesh.h new file mode 100644 index 0000000..6a88cec --- /dev/null +++ b/include/Orange/Graphics/Mesh.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +namespace orange +{ + struct MeshVertexData + { + MeshVertexData(MeshVertexType type) + : vertexType(type) + { + switch(vertexType) + { + case MeshVertexType::Static: + vertices.Construct>(); + break; + case MeshVertexType::Skinned: + vertices.Construct>(); + break; + } + } + + Vector& GetStaticVertices() + { + Assert(vertexType == MeshVertexType::Static); + return vertices.Get>(); + } + + Vector& GetSkinnedVertices() + { + Assert(vertexType == MeshVertexType::Skinned); + return vertices.Get>(); + } + + BufferView View() + { + switch(vertexType) + { + case MeshVertexType::Static: + return GetStaticVertices(); + break; + case MeshVertexType::Skinned: + return GetSkinnedVertices(); + break; + default: + return BufferView{ nullptr, 0 }; + } + } + + uint32_t VertexCount() const + { + // Type doesn't matter here, just want to grab m_size. + return uint32_t(vertices.Get>().Size()); + } + + MeshVertexType vertexType; + Variant, Vector> vertices; + }; + + struct MeshData + { + MeshData(MeshVertexType type) + : vertexData{ type } {} + + MeshVertexData vertexData; + Vector indices; + AABB bounds; + }; + + Result ParseOBJ(StringView buffer); + +} diff --git a/include/Orange/Graphics/Vertex.h b/include/Orange/Graphics/Vertex.h new file mode 100644 index 0000000..d292402 --- /dev/null +++ b/include/Orange/Graphics/Vertex.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +namespace orange +{ + enum class MeshVertexType + { + Static, + Skinned, + }; + + struct StaticVertex + { + vec3 pos; + vec2 uv; + vec3 normal; + //vec3 tangent; + + static constexpr VkVertexInputAttributeDescription Attributes[] = + { + { .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, pos)) }, + { .location = 1, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, uv)) }, + { .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, normal)) }, + }; + + bool operator == (const StaticVertex& other) const + { + return + pos == other.pos && + uv == other.uv && + normal == other.normal;// && + //tangent == other.tangent; + } + }; + + struct SkinnedVertex : public StaticVertex + { + static constexpr uint32_t MaxVertexWeights = 4; + + bool operator == (const SkinnedVertex& other) const + { + return + pos == other.pos && + uv == other.uv && + normal == other.normal && + //tangent == other.tangent && + boneIndices == other.boneIndices && + boneWeights == other.boneWeights; + } + + Array boneIndices; + Array boneWeights; + }; +} diff --git a/include/Orange/Math/AABB.h b/include/Orange/Math/AABB.h new file mode 100644 index 0000000..2cda066 --- /dev/null +++ b/include/Orange/Math/AABB.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace orange +{ + struct AABB + { + vec3 min; + vec3 max; + + void Extend(vec3 pos) + { + min = Min(pos, min); + max = Max(pos, max); + } + }; +} diff --git a/include/Orange/Math/Quaternion.h b/include/Orange/Math/Quaternion.h index 4a8ec03..69a4567 100644 --- a/include/Orange/Math/Quaternion.h +++ b/include/Orange/Math/Quaternion.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/include/Orange/Math/Vector.h b/include/Orange/Math/Vector.h index 663cfbc..bf734d0 100644 --- a/include/Orange/Math/Vector.h +++ b/include/Orange/Math/Vector.h @@ -279,12 +279,12 @@ namespace orange constexpr vec4 operator"" _vec4(long double value) { return vec4{static_cast(value)}; } constexpr vec4 operator"" _vec4(unsigned long long value) { return vec4{static_cast(value)}; } - float cross(const vec2& a, const vec2& b) + constexpr float cross(const vec2& a, const vec2& b) { return a.x * b.y - b.x * a.y; } - vec3 cross(const vec3& a, const vec3& b) + constexpr vec3 cross(const vec3& a, const vec3& b) { return { diff --git a/src/Apps/Tools/CubeTest.cpp b/src/Apps/Tools/CubeTest.cpp index b97ddf7..c62c8ea 100644 --- a/src/Apps/Tools/CubeTest.cpp +++ b/src/Apps/Tools/CubeTest.cpp @@ -1,250 +1,26 @@ #include -#include -#include "Orange/Core/Span.h" -#include #include -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include - -#include +#include #include #include #include - -#include +#include #include +#include #include using namespace orange; -struct AABB -{ - vec3 min; - vec3 max; - - void Extend(vec3 pos) - { - min = Min(pos, min); - max = Max(pos, max); - } -}; - -enum class MeshVertexType -{ - Static, - Skinned, -}; - -#ifndef offsetof2 -#define offsetof2(type, member) size_t(uintptr_t(&((type*)0)->member)) -#endif - -struct StaticVertex -{ - vec3 pos; - vec2 uv; - vec3 normal; - //vec3 tangent; - - static constexpr VkVertexInputAttributeDescription Attributes[] = - { - { .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, pos)) }, - { .location = 1, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, uv)) }, - { .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, normal)) }, - }; - - bool operator == (const StaticVertex& other) const - { - return pos == other.pos && - uv == other.uv && - normal == other.normal;// && - //tangent == other.tangent; - } -}; - -struct SkinnedVertex : public StaticVertex -{ - static constexpr uint32_t MaxVertexWeights = 4; - - bool operator == (const SkinnedVertex& other) const - { - return pos == other.pos && - uv == other.uv && - normal == other.normal && - //tangent == other.tangent && - boneIndices == other.boneIndices && - boneWeights == other.boneWeights; - } - - Array boneIndices; - Array boneWeights; -}; - -struct MeshVertexData -{ - MeshVertexData(MeshVertexType type) - : vertexType(type) - { - switch(vertexType) - { - case MeshVertexType::Static: - vertices.Construct>(); - break; - case MeshVertexType::Skinned: - vertices.Construct>(); - break; - } - } - - Vector& GetStaticVertices() - { - Assert(vertexType == MeshVertexType::Static); - return vertices.Get>(); - } - - Vector& GetSkinnedVertices() - { - Assert(vertexType == MeshVertexType::Skinned); - return vertices.Get>(); - } - - BufferView View() - { - switch(vertexType) - { - case MeshVertexType::Static: - return GetStaticVertices(); - break; - case MeshVertexType::Skinned: - return GetSkinnedVertices(); - break; - default: - return BufferView{ nullptr, 0 }; - } - } - - uint32_t VertexCount() const - { - // Type doesn't matter here, just want to grab m_size. - return uint32_t(vertices.Get>().Size()); - } - - MeshVertexType vertexType; - Variant, Vector> vertices; -}; - -struct MeshData -{ - MeshData(MeshVertexType type) - : vertexData{ type } {} - - MeshVertexData vertexData; - Vector indices; - AABB bounds; -}; - -Result ParseOBJ(StringView buffer) -{ - MeshData data{ MeshVertexType::Static }; - - Vector positions; - Vector uvs; - Vector normals; - - const char* obj = buffer.data; - const char* end = buffer.data + buffer.size; - while (obj != end) - { - SmallVector element; - stream::ReadString(obj, end, " #\n", element); - - if (element == "v" || element == "vt" || element == "vn") - { - float vtx[3]{}; - for (int i = 0; i < 3; i++) - { - stream::ConsumeSpace(obj, end); - if (auto r_float = stream::Parse(obj, end)) - vtx[i] = *r_float; - } - - if (element == "v") - positions.EmplaceBack(vtx[0], vtx[1], vtx[2]); - else if (element == "vt") - uvs.EmplaceBack(vtx[0], vtx[1]); - else if (element == "vn") - normals.EmplaceBack(vtx[0], vtx[1], vtx[2]); - } - else if (element == "g" || element == "o") - { - stream::ConsumeSpace(obj, end); - SmallVector name; - stream::ReadString(obj, end, " #\n", name); - - name.PushBack('\0'); - if (element == "g") - log::info("Group name: %s", name.Data()); - else - log::info("Object name: %s", name.Data()); - } - else if (element == "f") - { - int32_t indices[3][3]{}; - for (int i = 0; i < 3; i++) - { - stream::ConsumeSpace(obj, end); - - for (int j = 0; j < 3; j++) - { - indices[i][j] = -1; - - if (j == 0 || stream::Consume(obj, end, "/")) - { - if (auto r_int = stream::Parse(obj, end)) - indices[i][j] = *r_int - 1; // OBJ indexing starts at one. - } - } - } - - for (int i = 0; i < 3; i++) - { - StaticVertex 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{}, - }; - - auto& vertices = data.vertexData.GetStaticVertices(); - - size_t vertexIdx = vertices.FindIdx(vertex); - if (vertexIdx == vertices.InvalidIdx) - { - data.bounds.Extend(vertex.pos); - vertexIdx = vertices.PushBack(vertex); - } - - Assert(vertexIdx < UINT16_MAX); - data.indices.PushBack(uint16_t(vertexIdx)); - } - } - else if (!element.Empty()) - { - element.PushBack('\0'); - log::info("Unknown element: %s", element.Data()); - } - - stream::AdvancePast(obj, end, "\n"); - }; - - return Result::Success(data); -} - int main(int argc, char** argv) { (void)argc; (void)argv; @@ -732,7 +508,7 @@ int main(int argc, char** argv) .imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = { .color = { .float32 = { 1.0f, 0.5f, 0.0f, 1.0f } } }, + .clearValue = { .color = { .float32 = { 1.0f, 1.0f, 1.0f, 1.0f } } }, }, }; diff --git a/src/Orange/Graphics/Mesh.cpp b/src/Orange/Graphics/Mesh.cpp new file mode 100644 index 0000000..50fb0f8 --- /dev/null +++ b/src/Orange/Graphics/Mesh.cpp @@ -0,0 +1,105 @@ +#pragma once + +#include + +#include + +namespace orange +{ + Result ParseOBJ(StringView buffer) + { + MeshData data{ MeshVertexType::Static }; + + Vector positions; + Vector uvs; + Vector normals; + + const char* obj = buffer.data; + const char* end = buffer.data + buffer.size; + while (obj != end) + { + SmallVector element; + stream::ReadString(obj, end, " #\n", element); + + if (element == "v" || element == "vt" || element == "vn") + { + float vtx[3]{}; + for (int i = 0; i < 3; i++) + { + stream::ConsumeSpace(obj, end); + if (auto r_float = stream::Parse(obj, end)) + vtx[i] = *r_float; + } + + if (element == "v") + positions.EmplaceBack(vtx[0], vtx[1], vtx[2]); + else if (element == "vt") + uvs.EmplaceBack(vtx[0], vtx[1]); + else if (element == "vn") + normals.EmplaceBack(vtx[0], vtx[1], vtx[2]); + } + else if (element == "g" || element == "o") + { + stream::ConsumeSpace(obj, end); + SmallVector name; + stream::ReadString(obj, end, " #\n", name); + + name.PushBack('\0'); + if (element == "g") + log::info("Group name: %s", name.Data()); + else + log::info("Object name: %s", name.Data()); + } + else if (element == "f") + { + int32_t indices[3][3]{}; + for (int i = 0; i < 3; i++) + { + stream::ConsumeSpace(obj, end); + + for (int j = 0; j < 3; j++) + { + indices[i][j] = -1; + + if (j == 0 || stream::Consume(obj, end, "/")) + { + if (auto r_int = stream::Parse(obj, end)) + indices[i][j] = *r_int - 1; // OBJ indexing starts at one. + } + } + } + + for (int i = 0; i < 3; i++) + { + StaticVertex 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{}, + }; + + auto& vertices = data.vertexData.GetStaticVertices(); + + size_t vertexIdx = vertices.FindIdx(vertex); + if (vertexIdx == vertices.InvalidIdx) + { + data.bounds.Extend(vertex.pos); + vertexIdx = vertices.PushBack(vertex); + } + + Assert(vertexIdx < UINT16_MAX); + data.indices.PushBack(uint16_t(vertexIdx)); + } + } + else if (!element.Empty()) + { + element.PushBack('\0'); + log::info("Unknown element: %s", element.Data()); + } + + stream::AdvancePast(obj, end, "\n"); + }; + + return Result::Success(data); + } +} diff --git a/src/Orange/Render/Shaders/vs_Fullscreen.vert b/src/Orange/Render/Shaders/vs_Fullscreen.vert new file mode 100644 index 0000000..5502ee3 --- /dev/null +++ b/src/Orange/Render/Shaders/vs_Fullscreen.vert @@ -0,0 +1,14 @@ +#version 450 + +layout(location = 1) out vec2 o_texcoord; + +void main() +{ + vec2 coord = vec2( + float(gl_VertexIndex & 2), + float(gl_VertexIndex & 1) * 2.0f); + + o_texcoord = coord; + gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f); +} + \ No newline at end of file diff --git a/src/Orange/Render/Shaders/vs_Triangle.vert b/src/Orange/Render/Shaders/vs_Triangle.vert deleted file mode 100644 index 1b05f5d..0000000 --- a/src/Orange/Render/Shaders/vs_Triangle.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -vec2 positions[3] = vec2[] -( - vec2( 0.0, -0.5), - vec2( 0.5, 0.5), - vec2(-0.5, 0.5) -); - -vec3 colors[3] = vec3[] -( - vec3(1.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0) -); - -layout(location = 0) out vec4 outColor; - -void main() -{ - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - outColor = vec4(colors[gl_VertexIndex], 1.0); -} \ No newline at end of file diff --git a/src/Orange/meson.build b/src/Orange/meson.build index 369d8a5..84b164c 100644 --- a/src/Orange/meson.build +++ b/src/Orange/meson.build @@ -1,6 +1,6 @@ orange_shaders = glsl_generator.process([ 'Render/Shaders/fs_DebugVertColor.frag', - 'Render/Shaders/vs_Triangle.vert', + 'Render/Shaders/vs_Fullscreen.vert', 'Render/Shaders/vs_Mesh.vert', ]) @@ -8,6 +8,8 @@ orange_src = files([ 'Core/Filesystem.cpp', 'Core/Log.cpp', + 'Graphics/Mesh.cpp', + 'Render/Input.cpp', 'Render/RenderContext_Init.cpp', 'Render/RenderContext_Util.cpp',