2020-05-15 07:13:51 +02:00
|
|
|
/*
|
|
|
|
|
* Vulkan Example - glTF skinned animation
|
|
|
|
|
*
|
2024-05-01 18:29:52 +02:00
|
|
|
* Copyright (C) 2020-2024 by Sascha Willems - www.saschawillems.de
|
2020-05-15 07:13:51 +02:00
|
|
|
*
|
|
|
|
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
2020-05-26 08:13:47 +02:00
|
|
|
* 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
|
|
|
|
|
*
|
2020-05-15 07:13:51 +02:00
|
|
|
* 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>
|
2020-05-15 07:13:51 +02:00
|
|
|
#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>
|
|
|
|
|
|
2022-05-09 14:09:47 -04:00
|
|
|
#define TINYGLTF_IMPLEMENTATION
|
2020-05-15 07:13:51 +02:00
|
|
|
#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
|
2020-05-15 07:13:51 +02:00
|
|
|
#endif
|
|
|
|
|
#include "tiny_gltf.h"
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
#include "vulkanexamplebase.h"
|
|
|
|
|
#include <vulkan/vulkan.h>
|
2020-05-15 07:13:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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-05-15 07:13:51 +02:00
|
|
|
{
|
2020-06-06 11:05:56 +02:00
|
|
|
public:
|
|
|
|
|
vks::VulkanDevice *vulkanDevice;
|
|
|
|
|
VkQueue copyQueue;
|
2020-05-15 07:13:51 +02:00
|
|
|
|
2020-05-23 20:38:28 +02:00
|
|
|
/*
|
|
|
|
|
Base glTF structures, see gltfscene sample for details
|
|
|
|
|
*/
|
2020-05-15 07:13:51 +02:00
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Vertices
|
|
|
|
|
{
|
|
|
|
|
VkBuffer buffer;
|
2020-05-15 07:13:51 +02:00
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
} vertices;
|
2020-06-06 11:05:56 +02:00
|
|
|
|
|
|
|
|
struct Indices
|
|
|
|
|
{
|
|
|
|
|
int count;
|
|
|
|
|
VkBuffer buffer;
|
2020-05-15 07:13:51 +02:00
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
} indices;
|
|
|
|
|
|
|
|
|
|
struct Node;
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Material
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
glm::vec4 baseColorFactor = glm::vec4(1.0f);
|
2020-06-06 11:05:56 +02:00
|
|
|
uint32_t baseColorTextureIndex;
|
2020-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Image
|
|
|
|
|
{
|
|
|
|
|
vks::Texture2D texture;
|
2020-05-15 07:13:51 +02:00
|
|
|
VkDescriptorSet descriptorSet;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Texture
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
int32_t imageIndex;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Primitive
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
uint32_t firstIndex;
|
|
|
|
|
uint32_t indexCount;
|
2020-06-06 11:05:56 +02:00
|
|
|
int32_t materialIndex;
|
2020-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Mesh
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
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-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
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;
|
2020-05-15 07:13:51 +02:00
|
|
|
std::vector<glm::mat4> inverseBindMatrices;
|
2020-06-06 11:05:56 +02:00
|
|
|
std::vector<Node *> joints;
|
|
|
|
|
vks::Buffer ssbo;
|
|
|
|
|
VkDescriptorSet descriptorSet;
|
2020-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
2020-05-23 20:38:28 +02:00
|
|
|
Animation related structures
|
2020-05-15 07:13:51 +02:00
|
|
|
*/
|
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;
|
2020-05-15 07:13:51 +02:00
|
|
|
std::vector<glm::vec4> outputsVec4;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct AnimationChannel
|
|
|
|
|
{
|
2020-05-26 08:13:47 +02:00
|
|
|
std::string path;
|
2020-06-06 11:05:56 +02:00
|
|
|
Node * node;
|
|
|
|
|
uint32_t samplerIndex;
|
2020-05-26 08:13:47 +02:00
|
|
|
};
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Animation
|
|
|
|
|
{
|
|
|
|
|
std::string name;
|
2020-05-15 07:13:51 +02:00
|
|
|
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-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
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;
|
2020-05-15 07:13:51 +02:00
|
|
|
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);
|
2020-05-15 07:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class VulkanExample : public VulkanExampleBase
|
|
|
|
|
{
|
2020-06-06 11:05:56 +02:00
|
|
|
public:
|
2020-05-15 07:13:51 +02:00
|
|
|
bool wireframe = false;
|
|
|
|
|
|
2020-06-06 11:05:56 +02:00
|
|
|
struct ShaderData
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
vks::Buffer buffer;
|
2020-06-06 11:05:56 +02:00
|
|
|
struct Values
|
|
|
|
|
{
|
2020-05-15 07:13:51 +02:00
|
|
|
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 };
|
2020-05-15 07:13:51 +02:00
|
|
|
} 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 };
|
2020-05-15 07:13:51 +02:00
|
|
|
} descriptorSetLayouts;
|
2024-01-06 18:00:43 +01:00
|
|
|
VkDescriptorSet descriptorSet{ VK_NULL_HANDLE };
|
2020-05-15 07:13:51 +02:00
|
|
|
|
|
|
|
|
VulkanglTFModel glTFModel;
|
|
|
|
|
|
|
|
|
|
VulkanExample();
|
|
|
|
|
~VulkanExample();
|
2020-06-06 11:05:56 +02:00
|
|
|
void loadglTFFile(std::string filename);
|
2020-05-15 07:13:51 +02:00
|
|
|
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();
|
2020-05-15 07:13:51 +02:00
|
|
|
virtual void render();
|
2020-06-06 11:05:56 +02:00
|
|
|
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay);
|
2020-05-15 07:13:51 +02:00
|
|
|
};
|