Program Listing for File ObjLoader.ixx

Program Listing for File ObjLoader.ixx#

Return to documentation for file (Src/GraphicsEngineVulkan/scene/ObjLoader.ixx)

module;
#include <tiny_obj_loader.h>
#include <memory>
#include <string>
#include <vector>
#include <vulkan/vulkan.hpp>

export module kataglyphis.vulkan.obj_loader;

import kataglyphis.vulkan.obj_material;
import kataglyphis.vulkan.vertex;
import kataglyphis.vulkan.model;
import kataglyphis.vulkan.device;
// Re-exported: MeshRange appears in getMeshRanges()'s return type, so consumers
// (and the parse tests) that import this module see it without a second import.
export import kataglyphis.vulkan.mesh_range;

export namespace Kataglyphis {

std::string resolveObjTexturePath(const std::string &baseDir, const std::string &mapKd);

class ObjLoader
{
  public:
    ObjLoader(const std::shared_ptr<VulkanDevice> &device, vk::CommandPool command_pool);

    ObjLoader() = default;

    std::shared_ptr<Model> loadModel(const std::string &modelFile);

    bool parseCpu(const std::string &modelFile);

    std::shared_ptr<Model> uploadParsed();

    void adoptParsed(ObjLoader &&other)
    {
        vertices = std::move(other.vertices);
        indices = std::move(other.indices);
        materials = std::move(other.materials);
        materialIndex = std::move(other.materialIndex);
        textures = std::move(other.textures);
        textureSrgb = std::move(other.textureSrgb);
        meshRanges = std::move(other.meshRanges);
    }

    const std::vector<Vertex> &getVertices() const { return vertices; }
    const std::vector<unsigned int> &getIndices() const { return indices; }
    const std::vector<ObjMaterial> &getMaterials() const { return materials; }
    const std::vector<unsigned int> &getMaterialIndices() const { return materialIndex; }
    const std::vector<std::string> &getTextureNames() const { return textures; }
    const std::vector<unsigned char> &getTextureSrgbFlags() const { return textureSrgb; }

    const std::vector<MeshRange> &getMeshRanges() const { return meshRanges; }

  private:
    std::shared_ptr<VulkanDevice> device;
    vk::CommandPool command_pool;

    std::vector<Vertex> vertices;
    std::vector<unsigned int> indices;
    std::vector<ObjMaterial> materials;
    std::vector<unsigned int> materialIndex;
    std::vector<std::string> textures;
    // Parallel to textures: 1 = upload sRGB-decoded (diffuse), 0 = linear
    // (normal maps). Same convention as GltfLoader's textureSrgb.
    std::vector<unsigned char> textureSrgb;
    // One slice per OBJ shape; see MeshRange / getMeshRanges.
    std::vector<MeshRange> meshRanges;

    // Both take an ALREADY PARSED reader. The file used to be parsed once per
    // function - twice per model - which for the bundled 27 MB OBJ is around
    // 190 ms of duplicated work at the measured ~7 ms/MB (BM_ObjParse_Suzanne).
    // modelFile is still needed: texture paths resolve relative to it.
    void loadTexturesAndMaterials(const tinyobj::ObjReader &reader, const std::string &modelFile);
    void loadVertices(const tinyobj::ObjReader &reader);
};
}// namespace Kataglyphis