| 141 | } |
| 142 | |
| 143 | void LveModel::Builder::loadModel(const std::string &filepath) { |
| 144 | tinyobj::attrib_t attrib; |
| 145 | std::vector<tinyobj::shape_t> shapes; |
| 146 | std::vector<tinyobj::material_t> materials; |
| 147 | std::string warn, err; |
| 148 | |
| 149 | if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { |
| 150 | throw std::runtime_error(warn + err); |
| 151 | } |
| 152 | |
| 153 | vertices.clear(); |
| 154 | indices.clear(); |
| 155 | |
| 156 | std::unordered_map<Vertex, uint32_t> uniqueVertices{}; |
| 157 | for (const auto &shape : shapes) { |
| 158 | for (const auto &index : shape.mesh.indices) { |
| 159 | Vertex vertex{}; |
| 160 | |
| 161 | if (index.vertex_index >= 0) { |
| 162 | vertex.position = { |
| 163 | attrib.vertices[3 * index.vertex_index + 0], |
| 164 | attrib.vertices[3 * index.vertex_index + 1], |
| 165 | attrib.vertices[3 * index.vertex_index + 2], |
| 166 | }; |
| 167 | |
| 168 | vertex.color = { |
| 169 | attrib.colors[3 * index.vertex_index + 0], |
| 170 | attrib.colors[3 * index.vertex_index + 1], |
| 171 | attrib.colors[3 * index.vertex_index + 2], |
| 172 | }; |
| 173 | } |
| 174 | |
| 175 | if (index.normal_index >= 0) { |
| 176 | vertex.normal = { |
| 177 | attrib.normals[3 * index.normal_index + 0], |
| 178 | attrib.normals[3 * index.normal_index + 1], |
| 179 | attrib.normals[3 * index.normal_index + 2], |
| 180 | }; |
| 181 | } |
| 182 | |
| 183 | if (index.texcoord_index >= 0) { |
| 184 | vertex.uv = { |
| 185 | attrib.texcoords[2 * index.texcoord_index + 0], |
| 186 | attrib.texcoords[2 * index.texcoord_index + 1], |
| 187 | }; |
| 188 | } |
| 189 | |
| 190 | if (uniqueVertices.count(vertex) == 0) { |
| 191 | uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); |
| 192 | vertices.push_back(vertex); |
| 193 | } |
| 194 | indices.push_back(uniqueVertices[vertex]); |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | } // namespace lve |
no test coverage detected