std::string LoadObj( std::vector<shape_t>& shapes, std::vector<material_t>& materials, // [output] const char* filename, const char* mtl_basepath) { shapes.clear(); std::stringstream err; std::ifstream ifs(filename); if (!ifs) { err << "Cannot open file [" << filename << "]" << std::endl; return err.str(); } std::string basePath; if (mtl_basepath) { basePath = mtl_basepath; } MaterialFileReader matFileReader( basePath ); return LoadObj(shapes, materials, ifs, matFileReader); }
void prepareVertices() { // Load mesh from compressed asset AAsset* asset = AAssetManager_open(app->activity->assetManager, "models/vulkanlogo.obj", AASSET_MODE_STREAMING); assert(asset); size_t size = AAsset_getLength(asset); assert(size > 0); char *assetData = new char[size]; AAsset_read(asset, assetData, size); AAsset_close(asset); std::stringstream assetStream(assetData); std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; std::string objerr; tinyobj::MaterialFileReader matFileReader(""); bool ret = tinyobj::LoadObj(shapes, materials, objerr, assetStream, matFileReader, true); LOGW("shapes %d", shapes.size()); // Setup vertices float scale = 0.025f; std::vector<Vertex> vertexBuffer; std::vector<uint32_t> indexBuffer; for (auto& shape : shapes) { // Vertices for (size_t i = 0; i < shape.mesh.positions.size() / 3; i++) { Vertex v; v.pos[0] = shape.mesh.positions[3 * i + 0] * scale; v.pos[1] = -shape.mesh.positions[3 * i + 1] * scale; v.pos[2] = shape.mesh.positions[3 * i + 2] * scale; v.normal[0] = shape.mesh.normals[3 * i + 0]; v.normal[1] = shape.mesh.normals[3 * i + 1]; v.normal[2] = shape.mesh.normals[3 * i + 2]; v.color = glm::vec3(1.0f, 0.0f, 0.0f); vertexBuffer.push_back(v); } // Indices for (size_t i = 0; i < shape.mesh.indices.size() / 3; i++) { indexBuffer.push_back(shape.mesh.indices[3 * i + 0]); indexBuffer.push_back(shape.mesh.indices[3 * i + 1]); indexBuffer.push_back(shape.mesh.indices[3 * i + 2]); } } uint32_t vertexBufferSize = vertexBuffer.size() * sizeof(Vertex); uint32_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t); VkMemoryAllocateInfo memAlloc = {}; memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; memAlloc.pNext = NULL; memAlloc.allocationSize = 0; memAlloc.memoryTypeIndex = 0; VkMemoryRequirements memReqs; VkResult err; void *data; // Generate vertex buffer // Setup VkBufferCreateInfo bufInfo = {}; bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufInfo.pNext = NULL; bufInfo.size = vertexBufferSize; bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; bufInfo.flags = 0; // Copy vertex data to VRAM memset(&vertices, 0, sizeof(vertices)); err = vkCreateBuffer(device, &bufInfo, nullptr, &vertices.buf); assert(!err); vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem); assert(!err); err = vkMapMemory(device, vertices.mem, 0, memAlloc.allocationSize, 0, &data); assert(!err); memcpy(data, vertexBuffer.data(), vertexBufferSize); vkUnmapMemory(device, vertices.mem); assert(!err); err = vkBindBufferMemory(device, vertices.buf, vertices.mem, 0); assert(!err); // Generate index buffer // Setup VkBufferCreateInfo indexbufferInfo = {}; indexbufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; indexbufferInfo.pNext = NULL; indexbufferInfo.size = indexBufferSize; indexbufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; indexbufferInfo.flags = 0; // Copy index data to VRAM memset(&indices, 0, sizeof(indices)); err = vkCreateBuffer(device, &bufInfo, nullptr, &indices.buf); assert(!err); vkGetBufferMemoryRequirements(device, indices.buf, &memReqs); memAlloc.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); err = vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem); assert(!err); err = vkMapMemory(device, indices.mem, 0, indexBufferSize, 0, &data); assert(!err); memcpy(data, indexBuffer.data(), indexBufferSize); vkUnmapMemory(device, indices.mem); err = vkBindBufferMemory(device, indices.buf, indices.mem, 0); assert(!err); indices.count = indexBuffer.size(); // Binding description vertices.bindingDescriptions.resize(1); vertices.bindingDescriptions[0] = vkTools::initializers::vertexInputBindingDescription( VERTEX_BUFFER_BIND_ID, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX); // Attribute descriptions // Describes memory layout and shader positions vertices.attributeDescriptions.resize(3); // Location 0 : Position vertices.attributeDescriptions[0] = vkTools::initializers::vertexInputAttributeDescription( VERTEX_BUFFER_BIND_ID, 0, VK_FORMAT_R32G32B32_SFLOAT, 0); // Location 1 : Normal vertices.attributeDescriptions[1] = vkTools::initializers::vertexInputAttributeDescription( VERTEX_BUFFER_BIND_ID, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3); // Location 2 : Color vertices.attributeDescriptions[2] = vkTools::initializers::vertexInputAttributeDescription( VERTEX_BUFFER_BIND_ID, 2, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 6); // Assign to vertex buffer vertices.inputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertices.inputState.pNext = NULL; vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size(); vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data(); vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size(); vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data(); }