2022-08-07 00:15:47 +01:00
|
|
|
#include <Orange/Core/Array.h>
|
|
|
|
#include <Orange/Core/Vector.h>
|
2022-08-05 01:01:41 +01:00
|
|
|
#include "Orange/Core/Span.h"
|
2022-06-19 04:33:41 +01:00
|
|
|
#include <Orange/Core/Result.h>
|
2022-08-05 01:01:41 +01:00
|
|
|
#include <Orange/Core/FileSystem.h>
|
2022-08-07 00:15:47 +01:00
|
|
|
#include <Orange/Math/Vector.h>
|
2022-08-12 10:05:58 +01:00
|
|
|
#include <Orange/Math/Matrix.h>
|
2022-08-05 01:01:41 +01:00
|
|
|
#include <Orange/Core/Parse.h>
|
2022-06-19 04:33:41 +01:00
|
|
|
|
|
|
|
#include <Orange/Render/Window.h>
|
2022-08-04 03:00:54 +01:00
|
|
|
#include <Orange/Render/RenderContext.h>
|
|
|
|
#include <Orange/Render/Swapchain.h>
|
2022-06-19 04:33:41 +01:00
|
|
|
|
2022-08-07 06:09:59 +01:00
|
|
|
#include <vs_Triangle.h>
|
|
|
|
#include <fs_DebugVertColor.h>
|
|
|
|
|
2022-06-19 04:33:41 +01:00
|
|
|
using namespace orange;
|
|
|
|
|
2022-08-07 00:59:25 +01:00
|
|
|
struct AABB
|
2022-08-05 01:01:41 +01:00
|
|
|
{
|
2022-08-07 00:59:25 +01:00
|
|
|
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;
|
|
|
|
|
2022-08-05 03:26:36 +01:00
|
|
|
const char* obj = buffer.data;
|
|
|
|
const char* end = buffer.data + buffer.size;
|
|
|
|
while (obj != end)
|
2022-08-05 01:01:41 +01:00
|
|
|
{
|
2022-08-07 00:15:47 +01:00
|
|
|
SmallVector<char, 8> element;
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::ReadString(obj, end, " #\n", element);
|
2022-08-05 01:01:41 +01:00
|
|
|
|
2022-08-07 00:59:25 +01:00
|
|
|
if (element == "v" || element == "vt" || element == "vn")
|
2022-08-05 01:01:41 +01:00
|
|
|
{
|
|
|
|
float vtx[3]{};
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::ConsumeSpace(obj, end);
|
|
|
|
if (auto r_float = stream::Parse<float>(obj, end))
|
|
|
|
vtx[i] = *r_float;
|
|
|
|
else
|
2022-08-07 00:59:25 +01:00
|
|
|
return Result<MeshData>::Error();
|
2022-08-05 01:01:41 +01:00
|
|
|
}
|
|
|
|
|
2022-08-07 00:59:25 +01:00
|
|
|
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]);
|
2022-08-05 01:01:41 +01:00
|
|
|
}
|
|
|
|
else if (element == "g" || element == "o")
|
|
|
|
{
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::ConsumeSpace(obj, end);
|
2022-08-07 00:15:47 +01:00
|
|
|
SmallVector<char, 32> name;
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::ReadString(obj, end, " #\n", name);
|
2022-08-05 01:01:41 +01:00
|
|
|
|
|
|
|
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++)
|
|
|
|
{
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::ConsumeSpace(obj, end);
|
2022-08-05 01:01:41 +01:00
|
|
|
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
|
|
{
|
|
|
|
indices[i][j] = -1;
|
|
|
|
|
2022-08-05 03:26:36 +01:00
|
|
|
if (j == 0 || stream::Consume(obj, end, "/"))
|
2022-08-05 01:01:41 +01:00
|
|
|
{
|
2022-08-05 03:26:36 +01:00
|
|
|
if (auto r_int = stream::Parse<uint32_t>(obj, end))
|
|
|
|
indices[i][j] = *r_int;
|
2022-08-05 01:01:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-07 00:59:25 +01:00
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
2022-08-05 01:01:41 +01:00
|
|
|
}
|
2022-08-05 03:26:36 +01:00
|
|
|
else if (!element.Empty())
|
2022-08-05 01:01:41 +01:00
|
|
|
{
|
|
|
|
element.PushBack('\0');
|
|
|
|
log::info("Unknown element: %s", element.Data());
|
|
|
|
}
|
|
|
|
|
2022-08-05 03:26:36 +01:00
|
|
|
stream::AdvancePast(obj, end, "\n");
|
|
|
|
};
|
2022-08-05 01:01:41 +01:00
|
|
|
|
2022-08-07 00:59:25 +01:00
|
|
|
return Result<MeshData>::Success(data);
|
2022-08-05 01:01:41 +01:00
|
|
|
}
|
|
|
|
|
2022-06-19 04:33:41 +01:00
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
|
|
|
(void)argc; (void)argv;
|
|
|
|
|
2022-08-04 18:23:08 +01:00
|
|
|
auto r_window = Window::Create();
|
2022-06-19 04:33:41 +01:00
|
|
|
if (!r_window)
|
|
|
|
return 1;
|
|
|
|
|
2022-08-04 18:23:08 +01:00
|
|
|
auto r_renderContext = RenderContext::Create("Cube Test");
|
2022-08-04 03:00:54 +01:00
|
|
|
if (!r_renderContext)
|
2022-08-02 22:27:01 +01:00
|
|
|
return 1;
|
|
|
|
|
2022-08-04 18:23:08 +01:00
|
|
|
auto r_surface = r_window->CreateSurface(r_renderContext->Instance());
|
2022-08-04 03:00:54 +01:00
|
|
|
if (!r_surface)
|
|
|
|
return 1;
|
2022-08-03 05:33:52 +01:00
|
|
|
|
2022-08-04 18:23:08 +01:00
|
|
|
auto r_swapchain = Swapchain::Create(*r_renderContext, *r_surface);
|
2022-08-04 03:00:54 +01:00
|
|
|
if (!r_swapchain)
|
2022-08-02 22:27:01 +01:00
|
|
|
return 1;
|
2022-06-19 04:33:41 +01:00
|
|
|
|
2022-08-05 03:26:36 +01:00
|
|
|
auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj");
|
2022-08-05 01:01:41 +01:00
|
|
|
if (!r_objData)
|
|
|
|
return 1;
|
|
|
|
|
2022-08-07 00:59:25 +01:00
|
|
|
auto r_mesh = ParseOBJ(*r_objData);
|
2022-08-05 01:01:41 +01:00
|
|
|
|
2022-08-07 06:09:59 +01:00
|
|
|
auto r_vs = r_renderContext->CreateShader(vs_Triangle);
|
|
|
|
if (!r_vs) return 1;
|
|
|
|
auto r_fs = r_renderContext->CreateShader(fs_DebugVertColor);
|
|
|
|
if (!r_fs) return 1;
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo stages[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
.module = *r_vs,
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
.module = *r_fs,
|
|
|
|
.pName = "main",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
Array<VkDynamicState, 2> dynamicStates =
|
|
|
|
{
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineDynamicStateCreateInfo dynamicStateInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
|
|
.dynamicStateCount = uint32_t(dynamicStates.Size()),
|
|
|
|
.pDynamicStates = dynamicStates.Data(),
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
.vertexBindingDescriptionCount = 0u,
|
|
|
|
.pVertexBindingDescriptions = nullptr,
|
|
|
|
.vertexAttributeDescriptionCount = 0u,
|
|
|
|
.pVertexAttributeDescriptions = nullptr,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
|
.primitiveRestartEnable = VK_FALSE,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo viewportStateInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
|
|
.viewportCount = 1,
|
|
|
|
.scissorCount = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterizationInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
|
|
.cullMode = VK_CULL_MODE_NONE, //VK_CULL_MODE_BACK_BIT,
|
|
|
|
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisampleInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
|
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineColorBlendAttachmentState attachmentBlendState =
|
|
|
|
{
|
|
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
|
|
|
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
.attachmentCount = 1,
|
|
|
|
.pAttachments = &attachmentBlendState,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
};
|
|
|
|
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
|
|
|
vkCreatePipelineLayout(r_renderContext->Device(), &pipelineLayoutInfo, nullptr, &pipelineLayout);
|
|
|
|
|
|
|
|
VkFormat format = r_swapchain->Format();
|
|
|
|
VkPipelineRenderingCreateInfo renderingInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
|
|
|
.viewMask = 0u,
|
|
|
|
.colorAttachmentCount = 1u,
|
|
|
|
.pColorAttachmentFormats = &format,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkGraphicsPipelineCreateInfo pipelineInfo =
|
|
|
|
{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
.pNext = &renderingInfo,
|
|
|
|
.stageCount = Size(stages),
|
|
|
|
.pStages = stages,
|
|
|
|
.pVertexInputState = &vertexInputInfo,
|
|
|
|
.pInputAssemblyState = &inputAssemblyInfo,
|
|
|
|
.pViewportState = &viewportStateInfo,
|
|
|
|
.pRasterizationState = &rasterizationInfo,
|
|
|
|
.pMultisampleState = &multisampleInfo,
|
|
|
|
.pDepthStencilState = nullptr,
|
|
|
|
.pColorBlendState = &colorBlendStateInfo,
|
|
|
|
.pDynamicState = &dynamicStateInfo,
|
|
|
|
.layout = pipelineLayout,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
|
|
|
if (vkCreateGraphicsPipelines(r_renderContext->Device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline) != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
log::err("Blah");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-08-04 22:18:11 +01:00
|
|
|
while (r_window->Update())
|
|
|
|
{
|
|
|
|
r_renderContext->BeginCommandBuffer(r_swapchain->CommandBuffer());
|
|
|
|
{
|
2022-08-07 06:09:59 +01:00
|
|
|
VkViewport viewport =
|
|
|
|
{
|
|
|
|
.x = 0.0f,
|
|
|
|
.y = 0.0f,
|
|
|
|
.width = float(r_swapchain->Extent().width),
|
|
|
|
.height = float(r_swapchain->Extent().height),
|
|
|
|
.minDepth = 0.0f,
|
|
|
|
.maxDepth = 1.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
VkRect2D scissor =
|
|
|
|
{
|
|
|
|
.offset = {0u, 0u},
|
|
|
|
.extent = r_swapchain->Extent(),
|
|
|
|
};
|
|
|
|
|
|
|
|
vkCmdSetViewport(r_swapchain->CommandBuffer(), 0, 1, &viewport);
|
|
|
|
vkCmdSetScissor(r_swapchain->CommandBuffer(), 0, 1, &scissor);
|
|
|
|
|
2022-08-04 22:18:11 +01:00
|
|
|
const VkRenderingAttachmentInfoKHR attachmentInfo =
|
|
|
|
{
|
2022-08-07 01:07:56 +01:00
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,
|
|
|
|
.imageView = r_swapchain->ImageView(),
|
2022-08-04 22:18:11 +01:00
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,
|
2022-08-07 01:07:56 +01:00
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
.clearValue = { .color = { .float32 = { 1.0f, 0.5f, 0.0f, 1.0f } } },
|
2022-08-04 22:18:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2022-06-19 04:33:41 +01:00
|
|
|
return 0;
|
|
|
|
}
|