procedural-3d-engine/examples/gltfskinning/gltfskinning.h

236 lines
5.8 KiB
C
Raw Normal View History

/*
* Vulkan Example - glTF skinned animation
*
2024-05-01 18:29:52 +02:00
* Copyright (C) 2020-2024 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/
/*
* Shows how to load and display an animated scene from a glTF file using vertex skinning
* See the accompanying README.md for a short tutorial on the data structures and functions required for vertex skinning
*
* For details on how glTF 2.0 works, see the official spec at https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
*
* If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/
*/
2020-06-06 11:05:56 +02:00
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define TINYGLTF_NO_STB_IMAGE_WRITE
#ifdef VK_USE_PLATFORM_ANDROID_KHR
2020-06-06 11:05:56 +02:00
# define TINYGLTF_ANDROID_LOAD_FROM_ASSETS
#endif
#include "tiny_gltf.h"
2020-06-06 11:05:56 +02:00
#include "vulkanexamplebase.h"
#include <vulkan/vulkan.h>
// 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
2020-06-06 11:05:56 +02:00
class VulkanglTFModel
{
2020-06-06 11:05:56 +02:00
public:
vks::VulkanDevice *vulkanDevice;
VkQueue copyQueue;
2020-05-23 20:38:28 +02:00
/*
Base glTF structures, see gltfscene sample for details
*/
2020-06-06 11:05:56 +02:00
struct Vertices
{
VkBuffer buffer;
VkDeviceMemory memory;
} vertices;
2020-06-06 11:05:56 +02:00
struct Indices
{
int count;
VkBuffer buffer;
VkDeviceMemory memory;
} indices;
struct Node;
2020-06-06 11:05:56 +02:00
struct Material
{
glm::vec4 baseColorFactor = glm::vec4(1.0f);
2020-06-06 11:05:56 +02:00
uint32_t baseColorTextureIndex;
};
2020-06-06 11:05:56 +02:00
struct Image
{
vks::Texture2D texture;
VkDescriptorSet descriptorSet;
};
2020-06-06 11:05:56 +02:00
struct Texture
{
int32_t imageIndex;
};
2020-06-06 11:05:56 +02:00
struct Primitive
{
uint32_t firstIndex;
uint32_t indexCount;
2020-06-06 11:05:56 +02:00
int32_t materialIndex;
};
2020-06-06 11:05:56 +02:00
struct Mesh
{
std::vector<Primitive> primitives;
};
2020-06-06 11:05:56 +02:00
struct Node
{
Node * parent;
uint32_t index;
std::vector<Node *> children;
Mesh mesh;
glm::vec3 translation{};
glm::vec3 scale{1.0f};
glm::quat rotation{};
int32_t skin = -1;
glm::mat4 matrix;
glm::mat4 getLocalMatrix();
};
2020-06-06 11:05:56 +02:00
struct Vertex
{
2020-05-23 20:38:28 +02:00
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;
glm::vec3 color;
glm::vec4 jointIndices;
glm::vec4 jointWeights;
};
/*
Skin structure
*/
2020-06-06 11:05:56 +02:00
struct Skin
{
std::string name;
Node * skeletonRoot = nullptr;
std::vector<glm::mat4> inverseBindMatrices;
2020-06-06 11:05:56 +02:00
std::vector<Node *> joints;
vks::Buffer ssbo;
VkDescriptorSet descriptorSet;
};
/*
2020-05-23 20:38:28 +02:00
Animation related structures
*/
2020-05-23 20:38:28 +02:00
2020-06-06 11:05:56 +02:00
struct AnimationSampler
{
std::string interpolation;
std::vector<float> inputs;
std::vector<glm::vec4> outputsVec4;
};
2020-06-06 11:05:56 +02:00
struct AnimationChannel
{
std::string path;
2020-06-06 11:05:56 +02:00
Node * node;
uint32_t samplerIndex;
};
2020-06-06 11:05:56 +02:00
struct Animation
{
std::string name;
std::vector<AnimationSampler> samplers;
std::vector<AnimationChannel> channels;
2020-06-06 11:05:56 +02:00
float start = std::numeric_limits<float>::max();
float end = std::numeric_limits<float>::min();
float currentTime = 0.0f;
};
2020-06-06 11:05:56 +02:00
std::vector<Image> images;
std::vector<Texture> textures;
std::vector<Material> materials;
std::vector<Node *> nodes;
std::vector<Skin> skins;
std::vector<Animation> animations;
uint32_t activeAnimation = 0;
~VulkanglTFModel();
2020-06-06 11:05:56 +02:00
void loadImages(tinygltf::Model &input);
void loadTextures(tinygltf::Model &input);
void loadMaterials(tinygltf::Model &input);
Node * findNode(Node *parent, uint32_t index);
Node * nodeFromIndex(uint32_t index);
void loadSkins(tinygltf::Model &input);
void loadAnimations(tinygltf::Model &input);
void loadNode(const tinygltf::Node &inputNode, const tinygltf::Model &input, VulkanglTFModel::Node *parent, uint32_t nodeIndex, std::vector<uint32_t> &indexBuffer, std::vector<VulkanglTFModel::Vertex> &vertexBuffer);
glm::mat4 getNodeMatrix(VulkanglTFModel::Node *node);
void updateJoints(VulkanglTFModel::Node *node);
void updateAnimation(float deltaTime);
void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node);
void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout);
};
class VulkanExample : public VulkanExampleBase
{
2020-06-06 11:05:56 +02:00
public:
bool wireframe = false;
2020-06-06 11:05:56 +02:00
struct ShaderData
{
vks::Buffer buffer;
2020-06-06 11:05:56 +02:00
struct Values
{
glm::mat4 projection;
glm::mat4 model;
glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, 5.0f, 1.0f);
} values;
} shaderData;
2024-05-01 18:29:52 +02:00
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
2020-06-06 11:05:56 +02:00
struct Pipelines
{
2024-01-06 18:00:43 +01:00
VkPipeline solid{ VK_NULL_HANDLE };
VkPipeline wireframe{ VK_NULL_HANDLE };
} pipelines;
2020-06-06 11:05:56 +02:00
struct DescriptorSetLayouts
{
2024-01-06 18:00:43 +01:00
VkDescriptorSetLayout matrices{ VK_NULL_HANDLE };
VkDescriptorSetLayout textures{ VK_NULL_HANDLE };
VkDescriptorSetLayout jointMatrices{ VK_NULL_HANDLE };
} descriptorSetLayouts;
2024-01-06 18:00:43 +01:00
VkDescriptorSet descriptorSet{ VK_NULL_HANDLE };
VulkanglTFModel glTFModel;
VulkanExample();
~VulkanExample();
2020-06-06 11:05:56 +02:00
void loadglTFFile(std::string filename);
virtual void getEnabledFeatures();
2020-06-06 11:05:56 +02:00
void buildCommandBuffers();
void loadAssets();
void setupDescriptors();
void preparePipelines();
void prepareUniformBuffers();
void updateUniformBuffers();
void prepare();
virtual void render();
2020-06-06 11:05:56 +02:00
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay);
};