#include #include #include #include #include namespace object_loader = ::basalt::shared::object_loader; using object_loader::IObjectLoader; using object_loader::Object; using object_loader::ObjectLoaderConfig; namespace math = ::basalt::shared::math; using math::FloatPoint; using math::Index; using math::Triangle; using math::Vector3; class ObjObjectLoader : public IObjectLoader { public: ObjObjectLoader() {} virtual ~ObjObjectLoader() {} public: virtual void load(ObjectLoaderConfig&& config) override { IObjectLoader::load(std::move(config)); // Load the OBJ file using tinyobjloader tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string err; // Load the OBJ file if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, this->config.filename.c_str())) { throw std::runtime_error("fail to load obj file"); } // Create one object from all shapes in the OBJ file std::vector vertices; std::vector triangles; // Extract all vertices from the OBJ file // In tinyobjloader, vertices are stored in a flat array [x,y,z,x,y,z,...] size_t num_vertices = attrib.vertices.size() / 3; vertices.reserve(num_vertices); for (size_t i = 0; i < attrib.vertices.size(); i += 3) { Vector3 vertex; vertex.x = attrib.vertices[i + 0]; // x coordinate vertex.y = attrib.vertices[i + 1]; // y coordinate vertex.z = attrib.vertices[i + 2]; // z coordinate vertices.emplace_back(vertex); } // Process each shape and add its triangles for (const auto& shape : shapes) { // Add triangles from this shape to our collection // Each face in the shape has been triangulated by tinyobjloader for (size_t i = 0; i < shape.mesh.indices.size(); i += 3) { if (i + 2 < shape.mesh.indices.size()) { Triangle triangle; // Get the three indices that form the triangle // vertex_index is the index into the attrib.vertices array int idx0 = shape.mesh.indices[i + 0].vertex_index; int idx1 = shape.mesh.indices[i + 1].vertex_index; int idx2 = shape.mesh.indices[i + 2].vertex_index; // Make sure indices are valid if (idx0 >= 0 && idx1 >= 0 && idx2 >= 0) { triangle.i = static_cast(idx0); triangle.j = static_cast(idx1); triangle.k = static_cast(idx2); triangles.emplace_back(triangle); } } } } // Create an Object and add it to our objects vector if (vertices.empty() || triangles.empty()) { throw std::runtime_error("empty scene is not allowed"); } else { this->objects.emplace_back(std::move(vertices), std::move(triangles)); } } }; BS_EXPORT void* BSCreateInstance() { return static_cast(new ObjObjectLoader()); } BS_EXPORT void BSDestroyInstance(void* instance) { delete dynamic_cast(static_cast(instance)); }