diff --git a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp index 6ddaf136ae96eadd0bf219dfb2d614a606d0cb0f..c677f600e0a0304f26835c685d9ab10545433ad5 100644 --- a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp +++ b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp @@ -47,6 +47,8 @@ namespace vkcv::asset { enum PrimitiveMode { POINTS=0, LINES, LINELOOP, LINESTRIP, TRIANGLES, TRIANGLESTRIP, TRIANGLEFAN }; /* With these enums, 0 is reserved to signal uninitialized or invalid data. */ enum PrimitiveType { POSITION=1, NORMAL, TEXCOORD_0 }; +/* The indices in the index buffer can be of different bit width. */ +enum IndexType { UINT32=0, UINT16=1, UINT8=2 }; typedef struct { // TODO not yet needed for the first (unlit) triangle @@ -64,26 +66,18 @@ typedef struct { /* This struct represents one (possibly the only) part of a mesh. There is * always one vertexBuffer and zero or one indexBuffer (indexed rendering is - * common but not always used). If there is no indexBuffer, this is indicated - * by indexBuffer.data being NULL. - * Each vertex buffer can have one or more vertex attributes. - * Note that the indexBuffer and vertexBuffer might be pointing to the same - * block of memory. - * - * TODO For now, the caller of loadMesh() has to free this memory when they are - * done, but since this is not generally good practice in C++, this behaviour - * will likely be changed later. */ + * common but not always used). If there is no index buffer, this is indicated + * by indexBuffer.data being empty. Each vertex buffer can have one or more + * vertex attributes. */ typedef struct { enum PrimitiveMode mode; // draw as points, lines or triangle? size_t numIndices, numVertices; struct { - void *data; // binary data of the index buffer - size_t byteLength; // length of the index buffer - uint32_t byteOffset; // offset into the buffer in bytes + enum IndexType type; // data type of the indices + std::vector<uint8_t> data; // binary data of the index buffer } indexBuffer; struct { - void *data; // the binary data of the buffer - size_t byteLength; // the length of the entire buffer in bytes + std::vector<uint8_t> data; // binary data of the vertex buffer std::vector<VertexAttribute> attributes; } vertexBuffer; struct { float x, y, z; } min; // bounding box lower left diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp index 9e55ff0104c162e40d4584c387f28a8413d62648..3bdc45449d66d8a41e64ac2b5b9f14ed18636651 100644 --- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp +++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp @@ -146,58 +146,60 @@ namespace vkcv::asset { const fx::gltf::Accessor &indexAccessor = object.accessors[objectPrimitive.indices]; const fx::gltf::BufferView &indexBufferView = object.bufferViews[indexAccessor.bufferView]; const fx::gltf::Buffer &indexBuffer = object.buffers[indexBufferView.buffer]; - void *indexBufferData = calloc(1, indexBuffer.byteLength); - if (memcpy(indexBufferData, indexBuffer.data.data(), indexBuffer.byteLength) == NULL) { - fprintf(stderr, "ERROR copying buffer data.\n"); - return 0; + std::vector<uint8_t> indexBufferData; + indexBufferData.resize(indexBufferView.byteLength); + { + const size_t off = indexBufferView.byteOffset; + const void *const ptr = ((char*)indexBuffer.data.data()) + off; + if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) { + std::cerr << "ERROR copying index buffer data.\n"; + return 0; + } } // vertexBuffer fx::gltf::BufferView& vertexBufferView = object.bufferViews[posAccessor.bufferView]; fx::gltf::Buffer& vertexBuffer = object.buffers[vertexBufferView.buffer]; - void *vertexBufferData; - - // check whether only one buffer is used - if (indexBufferView.buffer == vertexBufferView.buffer){ - std::cout << "It's just one Buffer, let's be efficient!" << std::endl; - vertexBufferData = indexBufferData; - } else { - std::cout << "No luck, different Buffers :(" << std::endl; - vertexBufferData = calloc(1, vertexBuffer.byteLength); - if (memcpy(vertexBufferData, vertexBuffer.data.data(), vertexBuffer.byteLength) == NULL) { - fprintf(stderr, "ERROR copying buffer data.\n"); - return 0; - } - } + std::vector<uint8_t> vertexBufferData; + vertexBufferData.resize(vertexBufferView.byteLength); + { + const size_t off = vertexBufferView.byteOffset; + const void *const ptr = ((char*)vertexBuffer.data.data()) + off; + if (!memcpy(vertexBufferData.data(), ptr, vertexBufferView.byteLength)) { + fprintf(stderr, "ERROR copying vertex buffer data.\n"); + return 0; + } + } - // fill vertex groups vector - const size_t numVertexGroups = 1; // TODO get value from fx-gltf + IndexType indexType; + switch(indexAccessor.componentType) { + case fx::gltf::Accessor::ComponentType::UnsignedByte: + indexType = UINT8; break; + case fx::gltf::Accessor::ComponentType::UnsignedShort: + indexType = UINT16; break; + case fx::gltf::Accessor::ComponentType::UnsignedInt: + indexType = UINT32; break; + default: + std::cerr << "ERROR: Index type not supported: " << + static_cast<uint16_t>(indexAccessor.componentType) << + std::endl; + return 0; + } + + const size_t numVertexGroups = objectMesh.primitives.size(); vertexGroups.resize(numVertexGroups); - vertexGroups.back() = { - static_cast<PrimitiveMode>(objectPrimitive.mode), // mode - object.accessors[objectPrimitive.indices].count, // num indices - posAccessor.count, // num vertices - { //index buffer - indexBufferData, - indexBufferView.byteLength, - indexBufferView.byteOffset - }, - { //vertex buffer - vertexBufferData, - vertexBufferView.byteLength, - vertexAttributes - }, + vertexGroups[0] = { + static_cast<PrimitiveMode>(objectPrimitive.mode),// mode + object.accessors[objectPrimitive.indices].count, // numIndices + posAccessor.count, // numVertices + { indexType, indexBufferData }, + { vertexBufferData, vertexAttributes }, {posAccessor.min[0], posAccessor.min[1], posAccessor.min[2]}, // bounding box min {posAccessor.max[0], posAccessor.max[1], posAccessor.max[2]}, // bounding box max static_cast<uint8_t>(objectPrimitive.material) // material index }; - // fill mesh struct - mesh = { - object.meshes[0].name, - vertexGroups, - materials - }; + mesh = { object.meshes[0].name, vertexGroups, materials }; // Finally return 1 to signal that all is fine return 1; diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 769fe9f36a7ebcdbb8027f5548e826ef6c4a8ea1..3a1b5d1af8b3d5e354594086385360854052a105 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -30,11 +30,10 @@ int main(int argc, const char** argv) { const auto &vg = mesh.vertexGroups[i]; printf("primitive mode: %d (%s)\n", vg.mode, primitive_modes[vg.mode]); - printf("index buffer: %lu bytes for %lu indices (offset into " - "%p is %u)\n", vg.indexBuffer.byteLength, - vg.numIndices, vg.indexBuffer.data, - vg.indexBuffer.byteOffset); - buf = (char*)vg.indexBuffer.data + vg.indexBuffer.byteOffset; + printf("index buffer: %lu bytes for %lu indices (%p)\n", + vg.indexBuffer.data.size(), vg.numIndices, + vg.indexBuffer.data.data()); + buf = (char*)vg.indexBuffer.data.data(); uint16_t *indices = (uint16_t*)buf; printf("\tindices: "); for (size_t j = 0; j < vg.numIndices; j++) { @@ -43,9 +42,9 @@ int main(int argc, const char** argv) { printf("\n"); printf("vertex buffer: %lu bytes for %lu vertices with %lu " "attributes (starting at %p)\n", - vg.vertexBuffer.byteLength, vg.numVertices, + vg.vertexBuffer.data.size(), vg.numVertices, vg.vertexBuffer.attributes.size(), - vg.vertexBuffer.data); + vg.vertexBuffer.data.data()); } return 0;