-
Notifications
You must be signed in to change notification settings - Fork 131
/
VulkanglTFModel.h
282 lines (248 loc) · 7.6 KB
/
VulkanglTFModel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/**
* Vulkan glTF model and texture loading class based on tinyglTF (https://github.com/syoyo/tinygltf)
*
* Copyright (C) 2018-2024 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/
#pragma once
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <vector>
#include "vulkan/vulkan.h"
#include "VulkanDevice.hpp"
#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>
#include <gli/gli.hpp>
#include <glm/gtx/string_cast.hpp>
#include "basisu_transcoder.h"
// ERROR is already defined in wingdi.h and collides with a define in the Draco headers
#if defined(_WIN32) && defined(ERROR) && defined(TINYGLTF_ENABLE_DRACO)
#undef ERROR
#pragma message ("ERROR constant already defined, undefining")
#endif
#define TINYGLTF_NO_STB_IMAGE_WRITE
#if defined(__ANDROID__)
#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS
#include <android/asset_manager.h>
#endif
#include "tiny_gltf.h"
// Changing this value here also requires changing it in the vertex shader
#define MAX_NUM_JOINTS 128u
namespace vkglTF
{
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();
void fromglTfImage(tinygltf::Image& gltfimage, std::string path, 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(0.0f);
vkglTF::Texture *baseColorTexture;
vkglTF::Texture *metallicRoughnessTexture;
vkglTF::Texture *normalTexture;
vkglTF::Texture *occlusionTexture;
vkglTF::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 {
vkglTF::Texture *specularGlossinessTexture;
vkglTF::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;
int index = 0;
bool unlit = false;
float emissiveStrength = 1.0f;
};
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[MAX_NUM_JOINTS]{};
uint32_t 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;
bool useCachedMatrix{ false };
glm::mat4 cachedLocalMatrix{ glm::mat4(1.0f) };
glm::mat4 cachedMatrix{ glm::mat4(1.0f) };
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;
std::vector<float> outputs;
glm::vec4 cubicSplineInterpolation(size_t index, float time, uint32_t stride);
void translate(size_t index, float time, vkglTF::Node* node);
void scale(size_t index, float time, vkglTF::Node* node);
void rotate(size_t index, float time, vkglTF::Node* node);
};
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::uvec4 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;
};
std::string filePath;
void destroy(VkDevice device);
void loadNode(vkglTF::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);
};
}