Advertisement
cybereality

Vulkan TinyOBJ Model Loading

Mar 12th, 2018
374
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.04 KB | None | 0 0
  1. void loadModel(const std::string& fileName) {
  2.     tinyobj::attrib_t attrib;
  3.     std::vector<tinyobj::shape_t> shapes;
  4.     std::vector<tinyobj::material_t> materials;
  5.     std::string err;
  6.  
  7.     std::string baseDir = getBaseDir(fileName);
  8.  
  9.     if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, fileName.c_str(), baseDir.c_str())) {
  10.         throw std::runtime_error(err);
  11.     }
  12.  
  13.     auto textureStart = textureIndex; // first free slot in texture array
  14.     uint32_t indexCount = 0; // the number of indices to be drawn in one bundle
  15.     auto indexStart = static_cast<uint32_t>(indices.size()); // index offset for drawing
  16.     int currentMat = 0; // the current OBJ material being used in face loop
  17.  
  18.     for (const auto& mat : materials) {
  19.         // loads a texture and adds it to the global array. also increments textureIndex.
  20.         // note: if you are loading multiple textures per material (i.e. diffuse + normal textures),
  21.         // you'll need to track this better than just a single index variable. Also, this
  22.         // method here does not account for materials with no textures, it's work in progress.
  23.         loadTexture(baseDir + mat.diffuse_texname, textureIndex);
  24.     }
  25.  
  26.     std::unordered_map<Vertex, uint32_t> uniqueVertices = {};
  27.  
  28.     for (size_t shape = 0; shape < shapes.size(); shape++) {
  29.         size_t index_offset = 0;
  30.         for (size_t face = 0; face < shapes[shape].mesh.num_face_vertices.size(); face++) {
  31.             // check if the material of this face is different than previous
  32.             auto thisMat = shapes[shape].mesh.material_ids[face];
  33.             if (thisMat != currentMat) {
  34.                 // save the index data for this sub-object bundle for drawing later
  35.                 // what is saved is the indexCount: the number of indices to be drawn
  36.                 // in one draw call, as well as the indexStart: the offset into the
  37.                 // main indices array. the last parameter is the index into the
  38.                 // global texture array. this index is passed to the fragment shader.
  39.                 recordIndexInfo(indexCount, indexStart, textureStart + currentMat);
  40.                 currentMat = thisMat;
  41.                 indexCount = 0;
  42.                 indexStart = static_cast<uint32_t>(indices.size());
  43.             }
  44.  
  45.             int faceVerts = shapes[shape].mesh.num_face_vertices[face];
  46.             for (size_t vert = 0; vert < faceVerts; vert++) {
  47.                 tinyobj::index_t idx = shapes[shape].mesh.indices[index_offset + vert];
  48.  
  49.                 tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
  50.                 tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
  51.                 tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
  52.  
  53.                 tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
  54.                 tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
  55.                 tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
  56.  
  57.                 tinyobj::real_t tx = attrib.texcoords[2*idx.texcoord_index+0];
  58.                 tinyobj::real_t ty = 1.0f - attrib.texcoords[2*idx.texcoord_index+1];
  59.  
  60.                 tinyobj::real_t r = attrib.colors[3*idx.vertex_index+0];
  61.                 tinyobj::real_t g = attrib.colors[3*idx.vertex_index+1];
  62.                 tinyobj::real_t b = attrib.colors[3*idx.vertex_index+2];
  63.  
  64.                 Vertex vertex = {};
  65.  
  66.                 vertex.position = {vx, vy, vz};
  67.                 vertex.uv = {tx, ty};
  68.                 vertex.color = {r, g, b};
  69.  
  70.                 if (uniqueVertices.count(vertex) == 0) {
  71.                     uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size());
  72.                     vertices.push_back(vertex);
  73.                 }
  74.  
  75.                 indices.push_back(uniqueVertices[vertex]);
  76.                 // increment the index counter for this sub-object
  77.                 ++indexCount;
  78.             }
  79.             index_offset += faceVerts;
  80.         }
  81.         // don't forget to save the last sub-object bundle when leaving the loop
  82.         recordIndexInfo(indexCount, indexStart, textureStart + currentMat);
  83.     }
  84. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement