270 lines
6.9 KiB
C++
270 lines
6.9 KiB
C++
#pragma once
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <vector>
|
|
|
|
#include <ktx.h>
|
|
#include <ktxvulkan.h>
|
|
|
|
#ifndef GLM_FORCE_RADIANS
|
|
#define GLM_FORCE_RADIANS
|
|
#endif
|
|
|
|
#ifndef GLM_FORCE_DEPTH_ZERO_TO_ONE
|
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
|
#endif
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
|
|
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
|
#define TINYGLTF_NO_STB_IMAGE_WRITE
|
|
#endif //
|
|
|
|
|
|
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS
|
|
#endif
|
|
|
|
|
|
#include "tiny_gltf.h"
|
|
#include "VulkanDevice.hpp"
|
|
//#include "VulkanUtils.hpp"
|
|
#include "vulkan/vulkan.h"
|
|
|
|
#define ENABLE_VALIDATION false
|
|
#define MAX_NUM_JOINTS 128u
|
|
|
|
// Contains everything required to render a glTF model in Vulkan
|
|
// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure
|
|
namespace glTFModel
|
|
{
|
|
|
|
struct Node;
|
|
|
|
struct BoundingBox {
|
|
glm::vec3 min;
|
|
glm::vec3 max;
|
|
bool valid = false;
|
|
BoundingBox();
|
|
BoundingBox(glm::vec3 min, glm::vec3 max);
|
|
BoundingBox getAABB(glm::mat4 m);
|
|
};
|
|
|
|
struct TextureSampler {
|
|
VkFilter magFilter;
|
|
VkFilter minFilter;
|
|
VkSamplerAddressMode addressModeU;
|
|
VkSamplerAddressMode addressModeV;
|
|
VkSamplerAddressMode addressModeW;
|
|
};
|
|
|
|
struct Texture {
|
|
vks::VulkanDevice* device;
|
|
VkImage image;
|
|
VkImageLayout imageLayout;
|
|
VkDeviceMemory deviceMemory;
|
|
VkImageView view;
|
|
uint32_t width, height;
|
|
uint32_t mipLevels;
|
|
uint32_t layerCount;
|
|
VkDescriptorImageInfo descriptor;
|
|
VkSampler sampler;
|
|
void updateDescriptor();
|
|
void destroy();
|
|
// Load a texture from a glTF image (stored as vector of chars loaded via stb_image) and generate a full mip chaing for it
|
|
void fromglTfImage(tinygltf::Image& gltfimage, glTFModel::TextureSampler textureSampler, vks::VulkanDevice* device, VkQueue copyQueue);
|
|
};
|
|
|
|
struct Material {
|
|
enum AlphaMode { ALPHAMODE_OPAQUE, ALPHAMODE_MASK, ALPHAMODE_BLEND };
|
|
AlphaMode alphaMode = ALPHAMODE_OPAQUE;
|
|
float alphaCutoff = 1.0f;
|
|
float metallicFactor = 1.0f;
|
|
float roughnessFactor = 1.0f;
|
|
glm::vec4 baseColorFactor = glm::vec4(1.0f);
|
|
glm::vec4 emissiveFactor = glm::vec4(1.0f);
|
|
glTFModel::Texture* baseColorTexture;
|
|
glTFModel::Texture* metallicRoughnessTexture;
|
|
glTFModel::Texture* normalTexture;
|
|
glTFModel::Texture* occlusionTexture;
|
|
glTFModel::Texture* emissiveTexture;
|
|
bool doubleSided = false;
|
|
struct TexCoordSets {
|
|
uint8_t baseColor = 0;
|
|
uint8_t metallicRoughness = 0;
|
|
uint8_t specularGlossiness = 0;
|
|
uint8_t normal = 0;
|
|
uint8_t occlusion = 0;
|
|
uint8_t emissive = 0;
|
|
} texCoordSets;
|
|
struct Extension {
|
|
glTFModel::Texture* specularGlossinessTexture;
|
|
glTFModel::Texture* diffuseTexture;
|
|
glm::vec4 diffuseFactor = glm::vec4(1.0f);
|
|
glm::vec3 specularFactor = glm::vec3(0.0f);
|
|
} extension;
|
|
struct PbrWorkflows {
|
|
bool metallicRoughness = true;
|
|
bool specularGlossiness = false;
|
|
} pbrWorkflows;
|
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
|
};
|
|
|
|
struct Primitive {
|
|
uint32_t firstIndex;
|
|
uint32_t indexCount;
|
|
uint32_t vertexCount;
|
|
Material& material;
|
|
bool hasIndices;
|
|
BoundingBox bb;
|
|
Primitive(uint32_t firstIndex, uint32_t indexCount, uint32_t vertexCount, Material& material);
|
|
void setBoundingBox(glm::vec3 min, glm::vec3 max);
|
|
};
|
|
|
|
struct Mesh {
|
|
vks::VulkanDevice* device;
|
|
std::vector<Primitive*> primitives;
|
|
BoundingBox bb;
|
|
BoundingBox aabb;
|
|
struct UniformBuffer {
|
|
VkBuffer buffer;
|
|
VkDeviceMemory memory;
|
|
VkDescriptorBufferInfo descriptor;
|
|
VkDescriptorSet descriptorSet;
|
|
void* mapped;
|
|
} uniformBuffer;
|
|
struct UniformBlock {
|
|
glm::mat4 matrix;
|
|
glm::mat4 jointMatrix[128]{};
|
|
float jointcount{ 0 };
|
|
} uniformBlock;
|
|
Mesh(vks::VulkanDevice* device, glm::mat4 matrix);
|
|
~Mesh();
|
|
void setBoundingBox(glm::vec3 min, glm::vec3 max);
|
|
};
|
|
|
|
struct Skin {
|
|
std::string name;
|
|
Node* skeletonRoot = nullptr;
|
|
std::vector<glm::mat4> inverseBindMatrices;
|
|
std::vector<Node*> joints;
|
|
};
|
|
|
|
struct Node {
|
|
Node* parent;
|
|
uint32_t index;
|
|
std::vector<Node*> children;
|
|
glm::mat4 matrix;
|
|
std::string name;
|
|
Mesh* mesh;
|
|
Skin* skin;
|
|
int32_t skinIndex = -1;
|
|
glm::vec3 translation{};
|
|
glm::vec3 scale{ 1.0f };
|
|
glm::quat rotation{};
|
|
BoundingBox bvh;
|
|
BoundingBox aabb;
|
|
glm::mat4 localMatrix();
|
|
glm::mat4 getMatrix();
|
|
void update();
|
|
~Node();
|
|
};
|
|
|
|
struct AnimationChannel {
|
|
enum PathType { TRANSLATION, ROTATION, SCALE };
|
|
PathType path;
|
|
Node* node;
|
|
uint32_t samplerIndex;
|
|
};
|
|
|
|
struct AnimationSampler {
|
|
enum InterpolationType { LINEAR, STEP, CUBICSPLINE };
|
|
InterpolationType interpolation;
|
|
std::vector<float> inputs;
|
|
std::vector<glm::vec4> outputsVec4;
|
|
};
|
|
|
|
struct Animation {
|
|
std::string name;
|
|
std::vector<AnimationSampler> samplers;
|
|
std::vector<AnimationChannel> channels;
|
|
float start = std::numeric_limits<float>::max();
|
|
float end = std::numeric_limits<float>::min();
|
|
};
|
|
|
|
struct Model {
|
|
|
|
vks::VulkanDevice* device;
|
|
|
|
struct Vertex {
|
|
glm::vec3 pos;
|
|
glm::vec3 normal;
|
|
glm::vec2 uv0;
|
|
glm::vec2 uv1;
|
|
glm::vec4 joint0;
|
|
glm::vec4 weight0;
|
|
glm::vec4 color;
|
|
};
|
|
|
|
struct Vertices {
|
|
VkBuffer buffer = VK_NULL_HANDLE;
|
|
VkDeviceMemory memory;
|
|
} vertices;
|
|
struct Indices {
|
|
VkBuffer buffer = VK_NULL_HANDLE;
|
|
VkDeviceMemory memory;
|
|
} indices;
|
|
|
|
glm::mat4 aabb;
|
|
|
|
std::vector<Node*> nodes;
|
|
std::vector<Node*> linearNodes;
|
|
|
|
std::vector<Skin*> skins;
|
|
|
|
std::vector<Texture> textures;
|
|
std::vector<TextureSampler> textureSamplers;
|
|
std::vector<Material> materials;
|
|
std::vector<Animation> animations;
|
|
std::vector<std::string> extensions;
|
|
|
|
struct Dimensions {
|
|
glm::vec3 min = glm::vec3(FLT_MAX);
|
|
glm::vec3 max = glm::vec3(-FLT_MAX);
|
|
} dimensions;
|
|
|
|
struct LoaderInfo {
|
|
uint32_t* indexBuffer;
|
|
Vertex* vertexBuffer;
|
|
size_t indexPos = 0;
|
|
size_t vertexPos = 0;
|
|
};
|
|
|
|
void destroy(VkDevice device);
|
|
void loadNode(glTFModel::Node* parent, const tinygltf::Node& node, uint32_t nodeIndex, const tinygltf::Model& model, LoaderInfo& loaderInfo, float globalscale);
|
|
void getNodeProps(const tinygltf::Node& node, const tinygltf::Model& model, size_t& vertexCount, size_t& indexCount);
|
|
void loadSkins(tinygltf::Model& gltfModel);
|
|
void loadTextures(tinygltf::Model& gltfModel, vks::VulkanDevice* device, VkQueue transferQueue);
|
|
VkSamplerAddressMode getVkWrapMode(int32_t wrapMode);
|
|
VkFilter getVkFilterMode(int32_t filterMode);
|
|
void loadTextureSamplers(tinygltf::Model& gltfModel);
|
|
void loadMaterials(tinygltf::Model& gltfModel);
|
|
void loadAnimations(tinygltf::Model& gltfModel);
|
|
void loadFromFile(std::string filename, vks::VulkanDevice* device, VkQueue transferQueue, float scale = 1.0f);
|
|
void drawNode(Node* node, VkCommandBuffer commandBuffer);
|
|
void draw(VkCommandBuffer commandBuffer);
|
|
void calculateBoundingBox(Node* node, Node* parent);
|
|
void getSceneDimensions();
|
|
void updateAnimation(uint32_t index, float time);
|
|
Node* findNode(Node* parent, uint32_t index);
|
|
Node* nodeFromIndex(uint32_t index);
|
|
};
|
|
|
|
|
|
|
|
} |