Orange/src/Apps/Tools/CubeTest.cpp

200 lines
5.6 KiB
C++

#include <Orange/Core/Array.h>
#include <Orange/Core/Vector.h>
#include "Orange/Core/Span.h"
#include <Orange/Core/Result.h>
#include <Orange/Core/FileSystem.h>
#include <Orange/Math/Vector.h>
#include <Orange/Core/Parse.h>
#include <Orange/Render/Window.h>
#include <Orange/Render/RenderContext.h>
#include <Orange/Render/Swapchain.h>
using namespace orange;
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<Vertex> vertices;
Vector<uint16_t> indices;
AABB bounds;
};
Result<MeshData> ParseOBJ(StringView buffer)
{
MeshData data;
Vector<vec3> positions;
Vector<vec2> uvs;
Vector<vec3> normals;
const char* obj = buffer.data;
const char* end = buffer.data + buffer.size;
while (obj != end)
{
SmallVector<char, 8> 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<float>(obj, end))
vtx[i] = *r_float;
else
return Result<MeshData>::Error();
}
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")
{
stream::ConsumeSpace(obj, end);
SmallVector<char, 32> 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<uint32_t>(obj, end))
indices[i][j] = *r_int;
}
}
}
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<Vertex>::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())
{
element.PushBack('\0');
log::info("Unknown element: %s", element.Data());
}
stream::AdvancePast(obj, end, "\n");
};
return Result<MeshData>::Success(data);
}
int main(int argc, char** argv)
{
(void)argc; (void)argv;
auto r_window = Window::Create();
if (!r_window)
return 1;
auto r_renderContext = RenderContext::Create("Cube Test");
if (!r_renderContext)
return 1;
auto r_surface = r_window->CreateSurface(r_renderContext->Instance());
if (!r_surface)
return 1;
auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface);
if (!r_swapchain)
return 1;
auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj");
if (!r_objData)
return 1;
auto r_mesh = ParseOBJ(*r_objData);
while (r_window->Update())
{
r_renderContext->BeginCommandBuffer(r_swapchain->CommandBuffer());
{
const VkRenderingAttachmentInfoKHR attachmentInfo =
{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,
.imageView = r_swapchain->ImageView(),
.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 } } },
};
const VkRenderingInfo renderInfo =
{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = { {}, r_swapchain->Extent() },
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo,
};
vkCmdBeginRendering(r_swapchain->CommandBuffer(), &renderInfo);
vkCmdEndRendering(r_swapchain->CommandBuffer());
}
r_renderContext->EndCommandBuffer(r_swapchain->CommandBuffer());
r_swapchain->Present();
}
return 0;
}