#include "Mesh.hpp" #include int Tags::SizeOf(VertexElementType type) { switch (type) { case VET_Float1: return sizeof(float); case VET_Float2: return sizeof(float) * 2; case VET_Float3: return sizeof(float) * 3; case VET_Float4: return sizeof(float) * 4; case VET_Double1: return sizeof(double); case VET_Double2: return sizeof(double) * 2; case VET_Double3: return sizeof(double) * 3; case VET_Double4: return sizeof(double) * 4; case VET_Short2: case VET_Short2Norm: case VET_Ushort2: case VET_Ushort2Norm: return sizeof(short) * 2; case VET_Short4: case VET_Short4Norm: case VET_Ushort4: case VET_Ushort4Norm: return sizeof(short) * 4; case VET_Int1: case VET_Uint1: return sizeof(int); case VET_Int2: case VET_Uint2: return sizeof(int) * 2; case VET_Int3: case VET_Uint3: return sizeof(int) * 3; case VET_Int4: case VET_Uint4: return sizeof(int) * 4; case VET_Byte4: case VET_Byte4Norm: case VET_Ubyte4: case VET_Ubyte4Norm: return sizeof(char) * 4; } return 0; } bool Tags::IsNormalized(VertexElementType type) { return type >= VET_NORM_BEGIN && type <= VET_NORM_END; } int Tags::SizeOf(IndexType type) { switch (type) { case IT_16Bit: return sizeof(uint16_t); case IT_32Bit: return sizeof(uint32_t); } return 0; } GpuVertexBuffer::GpuVertexBuffer() { glGenBuffers(1, &handle); } GpuVertexBuffer::~GpuVertexBuffer() { glDeleteBuffers(1, &handle); } void GpuVertexBuffer::Upload(const std::byte* data, size_t sizeInBytes) { glBindBuffer(GL_ARRAY_BUFFER, handle); glBufferData(GL_ARRAY_BUFFER, sizeInBytes, data, GL_DYNAMIC_DRAW); } GpuIndexBuffer::GpuIndexBuffer() { glGenBuffers(1, &handle); } GpuIndexBuffer::~GpuIndexBuffer() { glDeleteBuffers(1, &handle); } void GpuIndexBuffer::Upload(const std::byte* data, size_t count) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * Tags::SizeOf(indexType), data, GL_DYNAMIC_DRAW); } void GpuIndexBuffer::Upload(const std::byte* data, Tags::IndexType type, size_t count) { indexType = type; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * Tags::SizeOf(type), data, GL_DYNAMIC_DRAW); } int BufferBindings::GetMaxBindingIndex() const { return bindings.size() - 1; } GpuVertexBuffer* BufferBindings::GetBinding(int index) const { if (index >= 0 && index < bindings.size()) { return bindings[index].Get(); } else { return nullptr; } } void BufferBindings::SetBinding(int index, GpuVertexBuffer* buffer) { int maxBindingIndex = GetMaxBindingIndex(); if (index > maxBindingIndex) { int countDelta = index - maxBindingIndex; bindings.resize(bindings.size() + countDelta); } bindings[index].Attach(buffer); if (index == maxBindingIndex && buffer == nullptr) { bindings.pop_back(); } } void BufferBindings::Clear() { bindings.clear(); } int VertexElementFormat::GetStride() const { return Tags::SizeOf(type); } void VertexFormat::AddElement(VertexElementFormat element) { vertexSize += element.GetStride(); elements.push_back(std::move(element)); } void VertexFormat::RemoveElement(int index) { auto& element = elements[index]; vertexSize -= element.GetStride(); elements.erase(elements.begin() + index); } void VertexFormat::Sort() { std::sort(elements.begin(), elements.end()); } void VertexFormat::CompactBindingIndex() { if (elements.empty()) { return; } Sort(); int targetIdx = 0; int lastIdx = elements[0].bindingIndex; int c = 0; for (auto& elm : elements) { if (lastIdx != elm.bindingIndex) { targetIdx++; lastIdx = elm.bindingIndex; } if (targetIdx != elm.bindingIndex) { elements[c] = elm; elements[c].bindingIndex = targetIdx; } ++c; } } GpuMesh::GpuMesh(VertexFormat* vertexFormat, BufferBindings* bindings, GpuIndexBuffer* indexBuffer) : vertFormat(vertexFormat) , vertBufBindings(bindings) , indexBuf(indexBuffer) { } bool GpuMesh::IsEmpty() const { return vertFormat != nullptr; } void GpuMesh::SetVertex(VertexFormat* vertexFormat, BufferBindings* bindings) { vertFormat.Attach(vertexFormat); vertBufBindings.Attach(bindings); } VertexFormat* GpuMesh::GetVertexFormat() const { return vertFormat.Get(); } BufferBindings* GpuMesh::GetVertexBufferBindings() const { return vertBufBindings.Get(); } GpuIndexBuffer* GpuMesh::GetIndexBuffer() const { return indexBuf.Get(); }