diff options
author | tylermurphy534 <tylermurphy534@gmail.com> | 2022-09-18 21:20:51 -0400 |
---|---|---|
committer | tylermurphy534 <tylermurphy534@gmail.com> | 2022-09-18 21:20:51 -0400 |
commit | 8045b8ba04aae39a4cf9733e72413f648b6ebe2b (patch) | |
tree | f90a9bd50a2316d5077df99c9e8584afc76ed656 /engine/xe_model.cpp | |
download | minecraftvulkan-8045b8ba04aae39a4cf9733e72413f648b6ebe2b.tar.gz minecraftvulkan-8045b8ba04aae39a4cf9733e72413f648b6ebe2b.tar.bz2 minecraftvulkan-8045b8ba04aae39a4cf9733e72413f648b6ebe2b.zip |
stanford dragon rendering
Diffstat (limited to 'engine/xe_model.cpp')
-rw-r--r-- | engine/xe_model.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/engine/xe_model.cpp b/engine/xe_model.cpp new file mode 100644 index 0000000..e6835a6 --- /dev/null +++ b/engine/xe_model.cpp @@ -0,0 +1,193 @@ +#include "xe_model.hpp" +#include "xe_utils.hpp" + +#define TINYOBJLOADER_IMPLEMENTATION +#include "xe_obj_loader.hpp" + +#define GLM_ENABLE_EXPERIMENTAL +#include <glm/gtx/hash.hpp> + +#include <cassert> +#include <cstring> +#include <unordered_map> + +namespace std { +template<> +struct hash<xe::XeModel::Vertex> { + size_t operator()(xe::XeModel::Vertex const &vertex) const { + size_t seed = 0; + xe::hashCombine(seed, vertex.position, vertex.normal, vertex.uv); + return seed; + } +}; +} + +namespace xe { + +XeModel::XeModel(XeDevice &device, const XeModel::Builder &builder) : xeDevice{device} { + createVertexBuffers(builder.vertices); + createIndexBuffers(builder.indices); +} + +XeModel::~XeModel() {} + +std::unique_ptr<XeModel> XeModel::createModelFromFile(XeDevice &device, const std::string &filepath) { + Builder builder{}; + builder.loadModel(filepath); + return std::make_unique<XeModel>(device, builder); +} + +void XeModel::createVertexBuffers(const std::vector<Vertex> &vertices) { + vertexCount = static_cast<uint32_t>(vertices.size()); + assert(vertexCount >= 3 && "Vertex count must be atleast 3"); + VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount; + uint32_t vertexSize = sizeof(vertices[0]); + + XeBuffer stagingBuffer { + xeDevice, + vertexSize, + vertexCount, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + }; + + stagingBuffer.map(); + stagingBuffer.writeToBuffer((void *)vertices.data()); + + vertexBuffer = std::make_unique<XeBuffer>( + xeDevice, + vertexSize, + vertexCount, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + + xeDevice.copyBuffer(stagingBuffer.getBuffer(), vertexBuffer->getBuffer(), bufferSize); +} + +void XeModel::createIndexBuffers(const std::vector<uint32_t> &indices) { + indexCount = static_cast<uint32_t>(indices.size()); + hasIndexBuffer = indexCount > 0; + + if (!hasIndexBuffer) { + return; + } + + VkDeviceSize bufferSize = sizeof(indices[0]) * indexCount; + uint32_t indexSize = sizeof(indices[0]); + + XeBuffer stagingBuffer { + xeDevice, + indexSize, + indexCount, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + }; + + stagingBuffer.map(); + stagingBuffer.writeToBuffer((void *)indices.data()); + + indexBuffer = std::make_unique<XeBuffer>( + xeDevice, + indexSize, + indexCount, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + ); + + xeDevice.copyBuffer(stagingBuffer.getBuffer(), indexBuffer->getBuffer(), bufferSize); +} + +void XeModel::bind(VkCommandBuffer commandBuffer) { + VkBuffer buffers[] = {vertexBuffer->getBuffer()}; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets); + + if (hasIndexBuffer) { + vkCmdBindIndexBuffer(commandBuffer, indexBuffer->getBuffer(), 0, VK_INDEX_TYPE_UINT32); + } +} + +void XeModel::draw(VkCommandBuffer commandBuffer) { + if (hasIndexBuffer) { + vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); + } else { + vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0); + } +} + +std::vector<VkVertexInputBindingDescription> XeModel::Vertex::getBindingDescriptions() { + std::vector<VkVertexInputBindingDescription> bindingDescriptions(1); + bindingDescriptions[0].binding = 0; + bindingDescriptions[0].stride = sizeof(Vertex); + bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + return bindingDescriptions; +} + +std::vector<VkVertexInputAttributeDescription> XeModel::Vertex::getAttributeDescriptions() { + std::vector<VkVertexInputAttributeDescription> attributeDescptions{}; + + attributeDescptions.push_back({0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position)}); + attributeDescptions.push_back({1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)}); + attributeDescptions.push_back({2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)}); + attributeDescptions.push_back({3, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)}); + + return attributeDescptions; +} + +void XeModel::Builder::loadModel(const std::string &filepath) { + tinyobj::attrib_t attrib; + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> materials; + std::string warn, err; + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { + throw std::runtime_error(warn + err); + } + + vertices.clear(); + indices.clear(); + + std::unordered_map<Vertex, uint32_t> uniqueVertices{}; + for (const auto &shape : shapes) { + for (const auto &index : shape.mesh.indices) { + Vertex vertex{}; + + if(index.vertex_index >= 0) { + vertex.position = { + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2] + }; + + vertex.color = { + attrib.colors[3 * index.vertex_index + 0], + attrib.colors[3 * index.vertex_index + 1], + attrib.colors[3 * index.vertex_index + 2] + }; + } + + if(index.normal_index >= 0) { + vertex.normal = { + attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2] + }; + } + + if(index.texcoord_index >= 0) { + vertex.uv = { + attrib.texcoords[2 * index.texcoord_index + 0], + attrib.texcoords[2 * index.texcoord_index + 1], + }; + } + + if (uniqueVertices.count(vertex) == 0) { + uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); + vertices.push_back(vertex); + } + indices.push_back(uniqueVertices[vertex]); + } + } +} + +}
\ No newline at end of file |