Load animations
This commit is contained in:
parent
988df583c5
commit
23010275ce
1 changed files with 122 additions and 27 deletions
|
|
@ -159,6 +159,38 @@ public:
|
||||||
int32_t imageIndex;
|
int32_t imageIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
glTF animation channel
|
||||||
|
// @todo: Comment
|
||||||
|
*/
|
||||||
|
struct AnimationChannel {
|
||||||
|
std::string path;
|
||||||
|
Node* node;
|
||||||
|
uint32_t samplerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
glTF animation sampler
|
||||||
|
// @todo: Comment
|
||||||
|
*/
|
||||||
|
struct AnimationSampler {
|
||||||
|
std::string interpolation;
|
||||||
|
std::vector<float> inputs;
|
||||||
|
std::vector<glm::vec4> outputsVec4;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
glTF animation
|
||||||
|
// @todo: Comment
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Model data
|
Model data
|
||||||
*/
|
*/
|
||||||
|
|
@ -167,6 +199,7 @@ public:
|
||||||
std::vector<Material> materials;
|
std::vector<Material> materials;
|
||||||
std::vector<Node*> nodes;
|
std::vector<Node*> nodes;
|
||||||
std::vector<Skin> skins;
|
std::vector<Skin> skins;
|
||||||
|
std::vector<Animation> animations;
|
||||||
|
|
||||||
// POI: @todo: document
|
// POI: @todo: document
|
||||||
struct MeshData {
|
struct MeshData {
|
||||||
|
|
@ -331,6 +364,89 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo: Helper for getting buffer
|
||||||
|
|
||||||
|
// @todo: comment
|
||||||
|
void loadAnimations(tinygltf::Model& input)
|
||||||
|
{
|
||||||
|
animations.resize(input.animations.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < input.animations.size(); i++) {
|
||||||
|
// @todo; source...Animation etc.?
|
||||||
|
tinygltf::Animation srcAnimation = input.animations[i];
|
||||||
|
animations[i].name = srcAnimation.name;
|
||||||
|
|
||||||
|
// Samplers
|
||||||
|
// @todo: Link to specs
|
||||||
|
animations[i].samplers.resize(srcAnimation.samplers.size());
|
||||||
|
for (size_t j = 0; j < srcAnimation.samplers.size(); j++) {
|
||||||
|
tinygltf::AnimationSampler srcSampler = srcAnimation.samplers[j];
|
||||||
|
AnimationSampler& dstSampler = animations[i].samplers[j];
|
||||||
|
// Interpolation type
|
||||||
|
dstSampler.interpolation = srcSampler.interpolation;
|
||||||
|
|
||||||
|
// Read sampler input time values
|
||||||
|
{
|
||||||
|
const tinygltf::Accessor& accessor = input.accessors[srcSampler.input];
|
||||||
|
const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView];
|
||||||
|
const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer];
|
||||||
|
const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||||
|
const float* buf = static_cast<const float*>(dataPtr);
|
||||||
|
for (size_t index = 0; index < accessor.count; index++) {
|
||||||
|
dstSampler.inputs.push_back(buf[index]);
|
||||||
|
}
|
||||||
|
for (auto input : animations[i].samplers[j].inputs) {
|
||||||
|
if (input < animations[i].start) {
|
||||||
|
animations[i].start = input;
|
||||||
|
};
|
||||||
|
if (input > animations[i].end) {
|
||||||
|
animations[i].end = input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read sampler output Translate/rotate/scale values
|
||||||
|
{
|
||||||
|
const tinygltf::Accessor& accessor = input.accessors[srcSampler.output];
|
||||||
|
const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView];
|
||||||
|
const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer];
|
||||||
|
const void* dataPtr = &buffer.data[accessor.byteOffset + bufferView.byteOffset];
|
||||||
|
switch (accessor.type) {
|
||||||
|
case TINYGLTF_TYPE_VEC3: {
|
||||||
|
const glm::vec3* buf = static_cast<const glm::vec3*>(dataPtr);
|
||||||
|
for (size_t index = 0; index < accessor.count; index++) {
|
||||||
|
dstSampler.outputsVec4.push_back(glm::vec4(buf[index], 0.0f));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TINYGLTF_TYPE_VEC4: {
|
||||||
|
const glm::vec4* buf = static_cast<const glm::vec4*>(dataPtr);
|
||||||
|
for (size_t index = 0; index < accessor.count; index++) {
|
||||||
|
dstSampler.outputsVec4.push_back(buf[index]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
std::cout << "unknown type" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channels
|
||||||
|
animations[i].channels.resize(srcAnimation.channels.size());
|
||||||
|
for (size_t j = 0; j < srcAnimation.channels.size(); j++) {
|
||||||
|
tinygltf::AnimationChannel srcChannel = srcAnimation.channels[j];
|
||||||
|
AnimationChannel& dstChannel = animations[i].channels[j];
|
||||||
|
// Target channel is either rotation, translation or scale
|
||||||
|
dstChannel.path = srcChannel.target_path;
|
||||||
|
dstChannel.samplerIndex = srcChannel.sampler;
|
||||||
|
dstChannel.node = nodeFromIndex(srcChannel.target_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
VulkanglTFModel::Node* node = new VulkanglTFModel::Node{};
|
VulkanglTFModel::Node* node = new VulkanglTFModel::Node{};
|
||||||
|
|
@ -628,8 +744,8 @@ public:
|
||||||
title = "glTF vertex skinning";
|
title = "glTF vertex skinning";
|
||||||
camera.type = Camera::CameraType::lookat;
|
camera.type = Camera::CameraType::lookat;
|
||||||
camera.flipY = true;
|
camera.flipY = true;
|
||||||
camera.setPosition(glm::vec3(0.0f, -0.1f, -1.0f));
|
camera.setPosition(glm::vec3(0.0f, 0.75f, -2.0f));
|
||||||
camera.setRotation(glm::vec3(0.0f, -135.0f, 0.0f));
|
camera.setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
|
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
|
||||||
settings.overlay = true;
|
settings.overlay = true;
|
||||||
}
|
}
|
||||||
|
|
@ -728,6 +844,7 @@ public:
|
||||||
glTFModel.loadNode(node, glTFInput, nullptr, scene.nodes[i], indexBuffer, vertexBuffer);
|
glTFModel.loadNode(node, glTFInput, nullptr, scene.nodes[i], indexBuffer, vertexBuffer);
|
||||||
}
|
}
|
||||||
glTFModel.loadSkins(glTFInput);
|
glTFModel.loadSkins(glTFInput);
|
||||||
|
glTFModel.loadAnimations(glTFInput);
|
||||||
// Calculate initial pose
|
// Calculate initial pose
|
||||||
// @todo: Ugly code
|
// @todo: Ugly code
|
||||||
// @todo: Linear nodes?
|
// @todo: Linear nodes?
|
||||||
|
|
@ -787,23 +904,10 @@ public:
|
||||||
// Copy data from staging buffers (host) do device local buffer (gpu)
|
// Copy data from staging buffers (host) do device local buffer (gpu)
|
||||||
VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||||
VkBufferCopy copyRegion = {};
|
VkBufferCopy copyRegion = {};
|
||||||
|
|
||||||
copyRegion.size = vertexBufferSize;
|
copyRegion.size = vertexBufferSize;
|
||||||
vkCmdCopyBuffer(
|
vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, glTFModel.vertices.buffer, 1, ©Region);
|
||||||
copyCmd,
|
|
||||||
vertexStaging.buffer,
|
|
||||||
glTFModel.vertices.buffer,
|
|
||||||
1,
|
|
||||||
©Region);
|
|
||||||
|
|
||||||
copyRegion.size = indexBufferSize;
|
copyRegion.size = indexBufferSize;
|
||||||
vkCmdCopyBuffer(
|
vkCmdCopyBuffer(copyCmd, indexStaging.buffer, glTFModel.indices.buffer, 1, ©Region);
|
||||||
copyCmd,
|
|
||||||
indexStaging.buffer,
|
|
||||||
glTFModel.indices.buffer,
|
|
||||||
1,
|
|
||||||
©Region);
|
|
||||||
|
|
||||||
vulkanDevice->flushCommandBuffer(copyCmd, queue, true);
|
vulkanDevice->flushCommandBuffer(copyCmd, queue, true);
|
||||||
|
|
||||||
// Free staging resources
|
// Free staging resources
|
||||||
|
|
@ -950,19 +1054,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and initialize uniform buffer containing shader uniforms
|
|
||||||
void prepareUniformBuffers()
|
void prepareUniformBuffers()
|
||||||
{
|
{
|
||||||
// Vertex shader uniform buffer block
|
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.buffer, sizeof(shaderData.values)));
|
||||||
VK_CHECK_RESULT(vulkanDevice->createBuffer(
|
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
||||||
&shaderData.buffer,
|
|
||||||
sizeof(shaderData.values)));
|
|
||||||
|
|
||||||
// Map persistent
|
|
||||||
VK_CHECK_RESULT(shaderData.buffer.map());
|
VK_CHECK_RESULT(shaderData.buffer.map());
|
||||||
|
|
||||||
updateUniformBuffers();
|
updateUniformBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue