Program Listing for File GltfLoader.ixx

Program Listing for File GltfLoader.ixx#

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

module;

#include <memory>
#include <string>
#include <vector>

#include <vulkan/vulkan.hpp>

#include <glm/glm.hpp>

// Forward-declared cgltf types used only in the private processPrimitive
// signature. A private member must be declared in the class here, but the full
// cgltf definitions belong to the implementation unit (which includes
// <cgltf.h>); forward declarations keep them out of this module's interface.
struct cgltf_primitive;
struct cgltf_data;
struct cgltf_node;

export module kataglyphis.vulkan.gltf_loader;

import kataglyphis.vulkan.device;
import kataglyphis.vulkan.model;
import kataglyphis.vulkan.obj_material;
import kataglyphis.vulkan.vertex;
// 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;
// Re-exported: GltfSamplerDesc appears in getTextureSamplerDescs()'s return
// type, for the same reason.
export import kataglyphis.vulkan.sampler_builder;

export namespace Kataglyphis {

struct TexCoordSetInfo
{
    unsigned int set;
    bool supported;
};

TexCoordSetInfo describeTexCoordSet(int texcoord);

class GltfLoader
{
  public:
    GltfLoader(std::shared_ptr<VulkanDevice> device, vk::CommandPool command_pool);  // DEVICE_SINK_OK: moved into member
    GltfLoader() = default;

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

    std::shared_ptr<Model> uploadParsed();

    void adoptParsed(GltfLoader &&other);

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

    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::vector<unsigned char>> &getTextureImages() const { return textureImages; }

    const std::vector<GltfSamplerDesc> &getTextureSamplerDescs() const { return textureSamplerDescs; }

    const std::vector<unsigned char> &getTextureSrgbFlags() const { return textureSrgb; }

    // One entry per glTF primitive (see the shared kataglyphis.vulkan.mesh_range
    // module): its slice of the flat vertices/indices/materialIndex arrays.
    // uploadParsed builds one Mesh per range, so a multi-primitive glTF becomes a
    // multi-mesh Model (backlog #10) while parseCpu still produces the flat arrays
    // the tests assert on.
    const std::vector<MeshRange> &getMeshRanges() const { return meshRanges; }

  private:
    void processPrimitive(const cgltf_primitive *primitive,
      const glm::mat4 &world,
      const glm::mat3 &normalMatrix,
      const cgltf_data *data,
      unsigned int fallbackMaterial,
      bool mirrored);

    void visitNode(const cgltf_node *node, const cgltf_data *data, unsigned int fallbackMaterial);

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

    std::vector<Vertex> vertices;
    std::vector<unsigned int> indices;
    std::vector<ObjMaterial> materials;
    // Per-face (per-triangle) material id, exactly like the OBJ path.
    std::vector<unsigned int> materialIndex;
    // One encoded image per textured material (see getTextureImages).
    std::vector<std::vector<unsigned char>> textureImages;
    // Index-parallel with textureImages; see getTextureSamplerDescs.
    std::vector<GltfSamplerDesc> textureSamplerDescs;
    // Index-parallel with textureImages; see getTextureSrgbFlags.
    std::vector<unsigned char> textureSrgb;
    // One slice per glTF primitive; see MeshRange / getMeshRanges.
    std::vector<MeshRange> meshRanges;
};

}// namespace Kataglyphis