reconstruct gltf loader (not complete yet)
							parent
							
								
									e7d9f78252
								
							
						
					
					
						commit
						f5096914ae
					
				| 
						 | 
					@ -532,46 +532,6 @@ void VulkanglTFModel::loadAnimations(tinygltf::Model& input)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
	glTF material
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
void glTFModel::Material::createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout, uint32_t descriptorBindingFlags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	VkDescriptorSetAllocateInfo descriptorSetAllocInfo{};
 | 
					 | 
				
			||||||
	descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
 | 
					 | 
				
			||||||
	descriptorSetAllocInfo.descriptorPool = descriptorPool;
 | 
					 | 
				
			||||||
	descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
 | 
					 | 
				
			||||||
	descriptorSetAllocInfo.descriptorSetCount = 1;
 | 
					 | 
				
			||||||
	VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &descriptorSetAllocInfo, &descriptorSet));
 | 
					 | 
				
			||||||
	std::vector<VkDescriptorImageInfo> imageDescriptors{};
 | 
					 | 
				
			||||||
	std::vector<VkWriteDescriptorSet> writeDescriptorSets{};
 | 
					 | 
				
			||||||
	if (descriptorBindingFlags & DescriptorBindingFlags::ImageBaseColor) {
 | 
					 | 
				
			||||||
		imageDescriptors.push_back(baseColorTexture->descriptor);
 | 
					 | 
				
			||||||
		VkWriteDescriptorSet writeDescriptorSet{};
 | 
					 | 
				
			||||||
		writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
					 | 
				
			||||||
		writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
					 | 
				
			||||||
		writeDescriptorSet.descriptorCount = 1;
 | 
					 | 
				
			||||||
		writeDescriptorSet.dstSet = descriptorSet;
 | 
					 | 
				
			||||||
		writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
					 | 
				
			||||||
		writeDescriptorSet.pImageInfo = &baseColorTexture->descriptor;
 | 
					 | 
				
			||||||
		writeDescriptorSets.push_back(writeDescriptorSet);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (normalTexture && descriptorBindingFlags & DescriptorBindingFlags::ImageNormalMap) {
 | 
					 | 
				
			||||||
		imageDescriptors.push_back(normalTexture->descriptor);
 | 
					 | 
				
			||||||
		VkWriteDescriptorSet writeDescriptorSet{};
 | 
					 | 
				
			||||||
		writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
					 | 
				
			||||||
		writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
					 | 
				
			||||||
		writeDescriptorSet.descriptorCount = 1;
 | 
					 | 
				
			||||||
		writeDescriptorSet.dstSet = descriptorSet;
 | 
					 | 
				
			||||||
		writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
					 | 
				
			||||||
		writeDescriptorSet.pImageInfo = &normalTexture->descriptor;
 | 
					 | 
				
			||||||
		writeDescriptorSets.push_back(writeDescriptorSet);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	vkUpdateDescriptorSets(device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
					void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -610,81 +570,459 @@ void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
void VulkanglTFModel::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)
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF material
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void glTFModel::Material::createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout, uint32_t descriptorBindingFlags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	VulkanglTFModel::Node* node = new VulkanglTFModel::Node{};
 | 
						VkDescriptorSetAllocateInfo descriptorSetAllocInfo{};
 | 
				
			||||||
	node->matrix = glm::mat4(1.0f);
 | 
						descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
 | 
				
			||||||
	node->parent = parent;
 | 
						descriptorSetAllocInfo.descriptorPool = descriptorPool;
 | 
				
			||||||
	node->index = nodeIndex;
 | 
						descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
 | 
				
			||||||
 | 
						descriptorSetAllocInfo.descriptorSetCount = 1;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &descriptorSetAllocInfo, &descriptorSet));
 | 
				
			||||||
 | 
						std::vector<VkDescriptorImageInfo> imageDescriptors{};
 | 
				
			||||||
 | 
						std::vector<VkWriteDescriptorSet> writeDescriptorSets{};
 | 
				
			||||||
 | 
						if (descriptorBindingFlags & DescriptorBindingFlags::ImageBaseColor) {
 | 
				
			||||||
 | 
							imageDescriptors.push_back(baseColorTexture->descriptor);
 | 
				
			||||||
 | 
							VkWriteDescriptorSet writeDescriptorSet{};
 | 
				
			||||||
 | 
							writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorCount = 1;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstSet = descriptorSet;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
				
			||||||
 | 
							writeDescriptorSet.pImageInfo = &baseColorTexture->descriptor;
 | 
				
			||||||
 | 
							writeDescriptorSets.push_back(writeDescriptorSet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (normalTexture && descriptorBindingFlags & DescriptorBindingFlags::ImageNormalMap) {
 | 
				
			||||||
 | 
							imageDescriptors.push_back(normalTexture->descriptor);
 | 
				
			||||||
 | 
							VkWriteDescriptorSet writeDescriptorSet{};
 | 
				
			||||||
 | 
							writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorCount = 1;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstSet = descriptorSet;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
				
			||||||
 | 
							writeDescriptorSet.pImageInfo = &normalTexture->descriptor;
 | 
				
			||||||
 | 
							writeDescriptorSets.push_back(writeDescriptorSet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vkUpdateDescriptorSets(device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF primitive
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void glTFModel::Primitive::setDimensions(glm::vec3 min, glm::vec3 max) {
 | 
				
			||||||
 | 
						dimensions.min = min;
 | 
				
			||||||
 | 
						dimensions.max = max;
 | 
				
			||||||
 | 
						dimensions.size = max - min;
 | 
				
			||||||
 | 
						dimensions.center = (min + max) / 2.0f;
 | 
				
			||||||
 | 
						dimensions.radius = glm::distance(min, max) / 2.0f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF mesh
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					glTFModel::Mesh::Mesh(vks::VulkanDevice* device, glm::mat4 matrix) {
 | 
				
			||||||
 | 
						this->device = device;
 | 
				
			||||||
 | 
						this->uniformBlock.matrix = matrix;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(device->createBuffer(
 | 
				
			||||||
 | 
							VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
 | 
				
			||||||
 | 
							VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
 | 
				
			||||||
 | 
							sizeof(uniformBlock),
 | 
				
			||||||
 | 
							&uniformBuffer.buffer,
 | 
				
			||||||
 | 
							&uniformBuffer.memory,
 | 
				
			||||||
 | 
							&uniformBlock));
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, uniformBuffer.memory, 0, sizeof(uniformBlock), 0, &uniformBuffer.mapped));
 | 
				
			||||||
 | 
						uniformBuffer.descriptor = { uniformBuffer.buffer, 0, sizeof(uniformBlock) };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					glTFModel::Mesh::~Mesh() {
 | 
				
			||||||
 | 
						vkDestroyBuffer(device->logicalDevice, uniformBuffer.buffer, nullptr);
 | 
				
			||||||
 | 
						vkFreeMemory(device->logicalDevice, uniformBuffer.memory, nullptr);
 | 
				
			||||||
 | 
						for (auto primitive : primitives)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							delete primitive;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF node
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					glm::mat4 glTFModel::Node::localMatrix() {
 | 
				
			||||||
 | 
						return glm::translate(glm::mat4(1.0f), translation) * glm::mat4(rotation) * glm::scale(glm::mat4(1.0f), scale) * matrix;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					glm::mat4 glTFModel::Node::getMatrix() {
 | 
				
			||||||
 | 
						glm::mat4 m = localMatrix();
 | 
				
			||||||
 | 
						glTFModel::Node* p = parent;
 | 
				
			||||||
 | 
						while (p) {
 | 
				
			||||||
 | 
							m = p->localMatrix() * m;
 | 
				
			||||||
 | 
							p = p->parent;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Node::update() {
 | 
				
			||||||
 | 
						if (mesh) {
 | 
				
			||||||
 | 
							glm::mat4 m = getMatrix();
 | 
				
			||||||
 | 
							if (skin) {
 | 
				
			||||||
 | 
								mesh->uniformBlock.matrix = m;
 | 
				
			||||||
 | 
								// Update join matrices
 | 
				
			||||||
 | 
								glm::mat4 inverseTransform = glm::inverse(m);
 | 
				
			||||||
 | 
								for (size_t i = 0; i < skin->joints.size(); i++) {
 | 
				
			||||||
 | 
									glTFModel::Node* jointNode = skin->joints[i];
 | 
				
			||||||
 | 
									glm::mat4 jointMat = jointNode->getMatrix() * skin->inverseBindMatrices[i];
 | 
				
			||||||
 | 
									jointMat = inverseTransform * jointMat;
 | 
				
			||||||
 | 
									mesh->uniformBlock.jointMatrix[i] = jointMat;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								mesh->uniformBlock.jointCount = (float)skin->joints.size();
 | 
				
			||||||
 | 
								memcpy(mesh->uniformBuffer.mapped, &mesh->uniformBlock, sizeof(mesh->uniformBlock));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								memcpy(mesh->uniformBuffer.mapped, &m, sizeof(glm::mat4));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (auto& child : children) {
 | 
				
			||||||
 | 
							child->update();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					glTFModel::Node::~Node() {
 | 
				
			||||||
 | 
						if (mesh) {
 | 
				
			||||||
 | 
							delete mesh;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (auto& child : children) {
 | 
				
			||||||
 | 
							delete child;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF default vertex layout with easy Vulkan mapping functions
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkVertexInputBindingDescription glTFModel::Vertex::vertexInputBindingDescription;
 | 
				
			||||||
 | 
					std::vector<VkVertexInputAttributeDescription> glTFModel::Vertex::vertexInputAttributeDescriptions;
 | 
				
			||||||
 | 
					VkPipelineVertexInputStateCreateInfo glTFModel::Vertex::pipelineVertexInputStateCreateInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkVertexInputBindingDescription glTFModel::Vertex::inputBindingDescription(uint32_t binding) {
 | 
				
			||||||
 | 
						return VkVertexInputBindingDescription({ binding, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkVertexInputAttributeDescription glTFModel::Vertex::inputAttributeDescription(uint32_t binding, uint32_t location, VertexComponent component) {
 | 
				
			||||||
 | 
						switch (component) {
 | 
				
			||||||
 | 
						case VertexComponent::Position:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) });
 | 
				
			||||||
 | 
						case VertexComponent::Normal:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) });
 | 
				
			||||||
 | 
						case VertexComponent::UV:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) });
 | 
				
			||||||
 | 
						case VertexComponent::Color:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, color) });
 | 
				
			||||||
 | 
						case VertexComponent::Tangent:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, tangent) });
 | 
				
			||||||
 | 
						case VertexComponent::Joint0:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, joint0) });
 | 
				
			||||||
 | 
						case VertexComponent::Weight0:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, weight0) });
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return VkVertexInputAttributeDescription({});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<VkVertexInputAttributeDescription> glTFModel::Vertex::inputAttributeDescriptions(uint32_t binding, const std::vector<VertexComponent> components) {
 | 
				
			||||||
 | 
						std::vector<VkVertexInputAttributeDescription> result;
 | 
				
			||||||
 | 
						uint32_t location = 0;
 | 
				
			||||||
 | 
						for (VertexComponent component : components) {
 | 
				
			||||||
 | 
							result.push_back(Vertex::inputAttributeDescription(binding, location, component));
 | 
				
			||||||
 | 
							location++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @brief Returns the default pipeline vertex input state create info structure for the requested vertex components */
 | 
				
			||||||
 | 
					VkPipelineVertexInputStateCreateInfo* glTFModel::Vertex::getPipelineVertexInputState(const std::vector<VertexComponent> components) {
 | 
				
			||||||
 | 
						vertexInputBindingDescription = Vertex::inputBindingDescription(0);
 | 
				
			||||||
 | 
						Vertex::vertexInputAttributeDescriptions = Vertex::inputAttributeDescriptions(0, components);
 | 
				
			||||||
 | 
						pipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
 | 
				
			||||||
 | 
						pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
 | 
				
			||||||
 | 
						pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &Vertex::vertexInputBindingDescription;
 | 
				
			||||||
 | 
						pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(Vertex::vertexInputAttributeDescriptions.size());
 | 
				
			||||||
 | 
						pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = Vertex::vertexInputAttributeDescriptions.data();
 | 
				
			||||||
 | 
						return &pipelineVertexInputStateCreateInfo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					glTFModel::Texture* glTFModel::Model::getTexture(uint32_t index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (index < textures.size()) {
 | 
				
			||||||
 | 
							return &textures[index];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Model::createEmptyTexture(VkQueue transferQueue)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						emptyTexture.device = device;
 | 
				
			||||||
 | 
						emptyTexture.width = 1;
 | 
				
			||||||
 | 
						emptyTexture.height = 1;
 | 
				
			||||||
 | 
						emptyTexture.layerCount = 1;
 | 
				
			||||||
 | 
						emptyTexture.mipLevels = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t bufferSize = emptyTexture.width * emptyTexture.height * 4;
 | 
				
			||||||
 | 
						unsigned char* buffer = new unsigned char[bufferSize];
 | 
				
			||||||
 | 
						memset(buffer, 0, bufferSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkBuffer stagingBuffer;
 | 
				
			||||||
 | 
						VkDeviceMemory stagingMemory;
 | 
				
			||||||
 | 
						VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
 | 
				
			||||||
 | 
						bufferCreateInfo.size = bufferSize;
 | 
				
			||||||
 | 
						// This buffer is used as a transfer source for the buffer copy
 | 
				
			||||||
 | 
						bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
 | 
				
			||||||
 | 
						bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateBuffer(device->logicalDevice, &bufferCreateInfo, nullptr, &stagingBuffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
 | 
				
			||||||
 | 
						VkMemoryRequirements memReqs;
 | 
				
			||||||
 | 
						vkGetBufferMemoryRequirements(device->logicalDevice, stagingBuffer, &memReqs);
 | 
				
			||||||
 | 
						memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
						memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &stagingMemory));
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkBindBufferMemory(device->logicalDevice, stagingBuffer, stagingMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Copy texture data into staging buffer
 | 
				
			||||||
 | 
						uint8_t* data;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void**)&data));
 | 
				
			||||||
 | 
						memcpy(data, buffer, bufferSize);
 | 
				
			||||||
 | 
						vkUnmapMemory(device->logicalDevice, stagingMemory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkBufferImageCopy bufferCopyRegion = {};
 | 
				
			||||||
 | 
						bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
						bufferCopyRegion.imageSubresource.layerCount = 1;
 | 
				
			||||||
 | 
						bufferCopyRegion.imageExtent.width = emptyTexture.width;
 | 
				
			||||||
 | 
						bufferCopyRegion.imageExtent.height = emptyTexture.height;
 | 
				
			||||||
 | 
						bufferCopyRegion.imageExtent.depth = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create optimal tiled target image
 | 
				
			||||||
 | 
						VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo();
 | 
				
			||||||
 | 
						imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
 | 
				
			||||||
 | 
						imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
				
			||||||
 | 
						imageCreateInfo.mipLevels = 1;
 | 
				
			||||||
 | 
						imageCreateInfo.arrayLayers = 1;
 | 
				
			||||||
 | 
						imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
 | 
						imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
				
			||||||
 | 
						imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
						imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
 | 
						imageCreateInfo.extent = { emptyTexture.width, emptyTexture.height, 1 };
 | 
				
			||||||
 | 
						imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageCreateInfo, nullptr, &emptyTexture.image));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vkGetImageMemoryRequirements(device->logicalDevice, emptyTexture.image, &memReqs);
 | 
				
			||||||
 | 
						memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
						memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &emptyTexture.deviceMemory));
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, emptyTexture.image, emptyTexture.deviceMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkImageSubresourceRange subresourceRange{};
 | 
				
			||||||
 | 
						subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
						subresourceRange.baseMipLevel = 0;
 | 
				
			||||||
 | 
						subresourceRange.levelCount = 1;
 | 
				
			||||||
 | 
						subresourceRange.layerCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
 | 
				
			||||||
 | 
						vks::tools::setImageLayout(copyCmd, emptyTexture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
 | 
				
			||||||
 | 
						vkCmdCopyBufferToImage(copyCmd, stagingBuffer, emptyTexture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
 | 
				
			||||||
 | 
						vks::tools::setImageLayout(copyCmd, emptyTexture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
 | 
				
			||||||
 | 
						device->flushCommandBuffer(copyCmd, transferQueue);
 | 
				
			||||||
 | 
						emptyTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Clean up staging resources
 | 
				
			||||||
 | 
						vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
 | 
				
			||||||
 | 
						vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkSamplerCreateInfo samplerCreateInfo = vks::initializers::samplerCreateInfo();
 | 
				
			||||||
 | 
						samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
 | 
				
			||||||
 | 
						samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
 | 
				
			||||||
 | 
						samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
 | 
				
			||||||
 | 
						samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
 | 
				
			||||||
 | 
						samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
 | 
				
			||||||
 | 
						samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
 | 
				
			||||||
 | 
						samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
 | 
				
			||||||
 | 
						samplerCreateInfo.maxAnisotropy = 1.0f;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerCreateInfo, nullptr, &emptyTexture.sampler));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkImageViewCreateInfo viewCreateInfo = vks::initializers::imageViewCreateInfo();
 | 
				
			||||||
 | 
						viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
				
			||||||
 | 
						viewCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
				
			||||||
 | 
						viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
 | 
				
			||||||
 | 
						viewCreateInfo.subresourceRange.levelCount = 1;
 | 
				
			||||||
 | 
						viewCreateInfo.image = emptyTexture.image;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &emptyTexture.view));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						emptyTexture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
				
			||||||
 | 
						emptyTexture.descriptor.imageView = emptyTexture.view;
 | 
				
			||||||
 | 
						emptyTexture.descriptor.sampler = emptyTexture.sampler;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF model loading and rendering class
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					glTFModel::Model::~Model()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						vkDestroyBuffer(device->logicalDevice, vertices.buffer, nullptr);
 | 
				
			||||||
 | 
						vkFreeMemory(device->logicalDevice, vertices.memory, nullptr);
 | 
				
			||||||
 | 
						vkDestroyBuffer(device->logicalDevice, indices.buffer, nullptr);
 | 
				
			||||||
 | 
						vkFreeMemory(device->logicalDevice, indices.memory, nullptr);
 | 
				
			||||||
 | 
						for (auto texture : textures) {
 | 
				
			||||||
 | 
							texture.destroy();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (auto node : nodes) {
 | 
				
			||||||
 | 
							delete node;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (auto skin : skins) {
 | 
				
			||||||
 | 
							delete skin;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (descriptorSetLayoutUbo != VK_NULL_HANDLE) {
 | 
				
			||||||
 | 
							vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayoutUbo, nullptr);
 | 
				
			||||||
 | 
							descriptorSetLayoutUbo = VK_NULL_HANDLE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (descriptorSetLayoutImage != VK_NULL_HANDLE) {
 | 
				
			||||||
 | 
							vkDestroyDescriptorSetLayout(device->logicalDevice, descriptorSetLayoutImage, nullptr);
 | 
				
			||||||
 | 
							descriptorSetLayoutImage = VK_NULL_HANDLE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr);
 | 
				
			||||||
 | 
						emptyTexture.destroy();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Model::loadNode(glTFModel::Node* parent, const tinygltf::Node& node, uint32_t nodeIndex, const tinygltf::Model& model, std::vector<uint32_t>& indexBuffer, std::vector<Vertex>& vertexBuffer, float globalscale)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						glTFModel::Node* newNode = new Node{};
 | 
				
			||||||
 | 
						newNode->index = nodeIndex;
 | 
				
			||||||
 | 
						newNode->name = node.name;
 | 
				
			||||||
 | 
						newNode->skinIndex = node.skin;
 | 
				
			||||||
 | 
						newNode->matrix = glm::mat4(1.0f);
 | 
				
			||||||
 | 
						newNode->parent = parent;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the local node matrix
 | 
						// Get the local node matrix
 | 
				
			||||||
	// It's either made up from translation, rotation, scale or a 4x4 matrix
 | 
						// It's either made up from translation, rotation, scale or a 4x4 matrix
 | 
				
			||||||
	if (inputNode.translation.size() == 3) {
 | 
						glm::vec3 translation = glm::vec3(0.0f);
 | 
				
			||||||
		node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data())));
 | 
						if (node.translation.size() == 3) {
 | 
				
			||||||
 | 
							translation = glm::make_vec3(node.translation.data());
 | 
				
			||||||
 | 
							newNode->translation = translation;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (inputNode.rotation.size() == 4) {
 | 
						glm::mat4 rotation = glm::mat4(1.0f);
 | 
				
			||||||
		glm::quat q = glm::make_quat(inputNode.rotation.data());
 | 
						if (node.rotation.size() == 4) {
 | 
				
			||||||
		node->matrix *= glm::mat4(q);
 | 
							glm::quat q = glm::make_quat(node.rotation.data());
 | 
				
			||||||
 | 
							newNode->rotation = glm::mat4(q);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (inputNode.scale.size() == 3) {
 | 
						glm::vec3 scale = glm::vec3(1.0f);
 | 
				
			||||||
		node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data())));
 | 
						if (node.scale.size() == 3) {
 | 
				
			||||||
 | 
							scale = glm::make_vec3(node.scale.data());
 | 
				
			||||||
 | 
							newNode->scale = scale;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (node.matrix.size() == 16) {
 | 
				
			||||||
 | 
							newNode->matrix = glm::make_mat4x4(node.matrix.data());
 | 
				
			||||||
 | 
							if (globalscale != 1.0f) {
 | 
				
			||||||
 | 
								//newNode->matrix = glm::scale(newNode->matrix, glm::vec3(globalscale));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if (inputNode.matrix.size() == 16) {
 | 
					 | 
				
			||||||
		node->matrix = glm::make_mat4x4(inputNode.matrix.data());
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load node's children
 | 
						// Load node's children
 | 
				
			||||||
	if (inputNode.children.size() > 0) {
 | 
						if (node.children.size() > 0) {
 | 
				
			||||||
		for (size_t i = 0; i < inputNode.children.size(); i++) {
 | 
							for (size_t i = 0; i < node.children.size(); i++) {
 | 
				
			||||||
			loadNode(input.nodes[inputNode.children[i]], input, node, inputNode.children[i], indexBuffer, vertexBuffer);
 | 
								loadNode(newNode, model.nodes[node.children[i]],node.children[i],model,indexBuffer,vertexBuffer,globalscale);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If the node contains mesh data, we load vertices and indices from the buffers
 | 
						// If the node contains mesh data, we load vertices and indices from the buffers
 | 
				
			||||||
	// In glTF this is done via accessors and buffer views
 | 
						// In glTF this is done via accessors and buffer views
 | 
				
			||||||
	if (inputNode.mesh > -1) {
 | 
						if (node.mesh > -1) {
 | 
				
			||||||
		const tinygltf::Mesh mesh = input.meshes[inputNode.mesh];
 | 
							const tinygltf::Mesh mesh = model.meshes[node.mesh];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Mesh* newMesh = new Mesh(device, newNode->matrix);
 | 
				
			||||||
 | 
							newMesh->name = mesh.name;
 | 
				
			||||||
		// Iterate through all primitives of this node's mesh
 | 
							// Iterate through all primitives of this node's mesh
 | 
				
			||||||
		for (size_t i = 0; i < mesh.primitives.size(); i++) {
 | 
							for (size_t i = 0; i < mesh.primitives.size(); i++) {
 | 
				
			||||||
			const tinygltf::Primitive& glTFPrimitive = mesh.primitives[i];
 | 
								const tinygltf::Primitive& primitive = mesh.primitives[i];
 | 
				
			||||||
 | 
								if (primitive.indices < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			uint32_t firstIndex = static_cast<uint32_t>(indexBuffer.size());
 | 
								uint32_t firstIndex = static_cast<uint32_t>(indexBuffer.size());
 | 
				
			||||||
			uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
 | 
								uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
 | 
				
			||||||
			uint32_t indexCount = 0;
 | 
								uint32_t indexCount = 0;
 | 
				
			||||||
 | 
								uint32_t vertexCount = 0;
 | 
				
			||||||
 | 
								glm::vec3 posMin{};
 | 
				
			||||||
 | 
								glm::vec3 posMax{};
 | 
				
			||||||
 | 
								bool hasSkin = false;
 | 
				
			||||||
			// Vertices
 | 
								// Vertices
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				const float* positionBuffer = nullptr;
 | 
									const float* positionBuffer = nullptr;
 | 
				
			||||||
				const float* normalsBuffer = nullptr;
 | 
									const float* normalsBuffer = nullptr;
 | 
				
			||||||
				const float* texCoordsBuffer = nullptr;
 | 
									const float* texCoordsBuffer = nullptr;
 | 
				
			||||||
 | 
									const float* colorBuffer = nullptr;
 | 
				
			||||||
				const float* tangentsBuffer = nullptr;
 | 
									const float* tangentsBuffer = nullptr;
 | 
				
			||||||
				size_t vertexCount = 0;
 | 
									uint32_t colorComponentsNum;
 | 
				
			||||||
 | 
									const uint16_t* jointsBuffer = nullptr;
 | 
				
			||||||
 | 
									const float* weightsBuffer = nullptr;
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Get buffer data for vertex positions
 | 
									// Get buffer data for vertex positions
 | 
				
			||||||
				if (glTFPrimitive.attributes.find("POSITION") != glTFPrimitive.attributes.end()) {
 | 
									if (primitive.attributes.find("POSITION") != primitive.attributes.end()) {
 | 
				
			||||||
					const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("POSITION")->second];
 | 
										const tinygltf::Accessor& positionAccessor = model.accessors[primitive.attributes.find("POSITION")->second];
 | 
				
			||||||
					const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView];
 | 
										const tinygltf::BufferView& view = model.bufferViews[positionAccessor.bufferView];
 | 
				
			||||||
					positionBuffer = reinterpret_cast<const float*>(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
 | 
										positionBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[positionAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
					vertexCount = accessor.count;
 | 
										posMin = glm::vec3(positionAccessor.minValues[0], positionAccessor.minValues[1], positionAccessor.minValues[2]);
 | 
				
			||||||
 | 
										posMax = glm::vec3(positionAccessor.maxValues[0], positionAccessor.maxValues[1], positionAccessor.maxValues[2]);
 | 
				
			||||||
 | 
										vertexCount = static_cast<uint32_t>(positionAccessor.count);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Get buffer data for vertex normals
 | 
									// Get buffer data for vertex normals
 | 
				
			||||||
				if (glTFPrimitive.attributes.find("NORMAL") != glTFPrimitive.attributes.end()) {
 | 
									if (primitive.attributes.find("NORMAL") != primitive.attributes.end()) {
 | 
				
			||||||
					const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("NORMAL")->second];
 | 
										const tinygltf::Accessor& normalAccessor = model.accessors[primitive.attributes.find("NORMAL")->second];
 | 
				
			||||||
					const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView];
 | 
										const tinygltf::BufferView& view = model.bufferViews[normalAccessor.bufferView];
 | 
				
			||||||
					normalsBuffer = reinterpret_cast<const float*>(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
 | 
										normalsBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[normalAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Get buffer data for vertex texture coordinates
 | 
									// Get buffer data for vertex texture coordinates
 | 
				
			||||||
				// glTF supports multiple sets, we only load the first one
 | 
									// glTF supports multiple sets, we only load the first one
 | 
				
			||||||
				if (glTFPrimitive.attributes.find("TEXCOORD_0") != glTFPrimitive.attributes.end()) {
 | 
									if (primitive.attributes.find("TEXCOORD_0") != primitive.attributes.end()) {
 | 
				
			||||||
					const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TEXCOORD_0")->second];
 | 
										const tinygltf::Accessor& texcoordAccessor = model.accessors[primitive.attributes.find("TEXCOORD_0")->second];
 | 
				
			||||||
					const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView];
 | 
										const tinygltf::BufferView& view = model.bufferViews[texcoordAccessor.bufferView];
 | 
				
			||||||
					texCoordsBuffer = reinterpret_cast<const float*>(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
 | 
										texCoordsBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[texcoordAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// material tangent
 | 
				
			||||||
 | 
									if (primitive.attributes.find("TANGENT") != primitive.attributes.end())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										const tinygltf::Accessor& tangentAccessor = model.accessors[primitive.attributes.find("TANGENT")->second];
 | 
				
			||||||
 | 
										const tinygltf::BufferView& view = model.bufferViews[tangentAccessor.bufferView];
 | 
				
			||||||
 | 
										tangentsBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[tangentAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									//color
 | 
				
			||||||
 | 
									if (primitive.attributes.find("COLOR_0") != primitive.attributes.end())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										const tinygltf::Accessor& colorAccessor = model.accessors[primitive.attributes.find("COLOR_0")->second];
 | 
				
			||||||
 | 
										const tinygltf::BufferView& view = model.bufferViews[colorAccessor.bufferView];
 | 
				
			||||||
 | 
										colorBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[colorAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// skin joints
 | 
				
			||||||
 | 
									if (primitive.attributes.find("JOINTS_0") != primitive.attributes.end())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										const tinygltf::Accessor& jointsAccessor = model.accessors[primitive.attributes.find("JOINTS_0")->second];
 | 
				
			||||||
 | 
										const tinygltf::BufferView& view = model.bufferViews[jointsAccessor.bufferView];
 | 
				
			||||||
 | 
										jointsBuffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[jointsAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									// skin weights
 | 
				
			||||||
 | 
									if (primitive.attributes.find("WEIGHTS_0") != primitive.attributes.end())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										const tinygltf::Accessor& weightsAccessor = model.accessors[primitive.attributes.find("WEIGHTSS_0")->second];
 | 
				
			||||||
 | 
										const tinygltf::BufferView& view = model.bufferViews[weightsAccessor.bufferView];
 | 
				
			||||||
 | 
										weightsBuffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[weightsAccessor.byteOffset + view.byteOffset]));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (glTFPrimitive.attributes.find("TANGENT") != glTFPrimitive.attributes.end())
 | 
									hasSkin = (jointsBuffer && weightsBuffer);
 | 
				
			||||||
				{
 | 
					
 | 
				
			||||||
					const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.attributes.find("TANGENT")->second];
 | 
									
 | 
				
			||||||
					const tinygltf::BufferView& view = input.bufferViews[accessor.bufferView];
 | 
					 | 
				
			||||||
					tangentsBuffer = reinterpret_cast<const float*>(&(input.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Append data to model's vertex buffer
 | 
									// Append data to model's vertex buffer
 | 
				
			||||||
				for (size_t v = 0; v < vertexCount; v++) {
 | 
									for (size_t v = 0; v < vertexCount; v++) {
 | 
				
			||||||
| 
						 | 
					@ -692,40 +1030,63 @@ void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::
 | 
				
			||||||
					vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f);
 | 
										vert.pos = glm::vec4(glm::make_vec3(&positionBuffer[v * 3]), 1.0f);
 | 
				
			||||||
					vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f)));
 | 
										vert.normal = glm::normalize(glm::vec3(normalsBuffer ? glm::make_vec3(&normalsBuffer[v * 3]) : glm::vec3(0.0f)));
 | 
				
			||||||
					vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f);
 | 
										vert.uv = texCoordsBuffer ? glm::make_vec2(&texCoordsBuffer[v * 2]) : glm::vec3(0.0f);
 | 
				
			||||||
					vert.tangent = tangentsBuffer ? glm::normalize(glm::make_vec3(&tangentsBuffer[v * 4])) : glm::vec3(0.0f);
 | 
										if (colorBuffer)
 | 
				
			||||||
					vert.color = glm::vec3(1.0f, 1.0f, nodeIndex);//Temp set index in color attribute
 | 
										{
 | 
				
			||||||
 | 
											switch (colorComponentsNum)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
											case 3 :
 | 
				
			||||||
 | 
												vert.color = glm::vec4(glm::make_vec3(&colorBuffer[v * 3]), 1.0f);
 | 
				
			||||||
 | 
											case 4 :
 | 
				
			||||||
 | 
												vert.color = glm::make_vec4(&colorBuffer[v * 4]);
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											vert.color = glm::vec4(1.0f);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										vert.tangent = tangentsBuffer ? glm::vec4(glm::make_vec4(&tangentsBuffer[v * 4])) : glm::vec4(0.0f);
 | 
				
			||||||
 | 
										vert.joint0 = hasSkin ? glm::vec4(glm::make_vec4(&jointsBuffer[v * 4])) : glm::vec4(0.0f);
 | 
				
			||||||
 | 
										vert.weight0 = hasSkin ? glm::make_vec4(&weightsBuffer[v * 4]) : glm::vec4(0.0f);
 | 
				
			||||||
 | 
										
 | 
				
			||||||
					vertexBuffer.push_back(vert);
 | 
										vertexBuffer.push_back(vert);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Indices
 | 
								// Indices
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				const tinygltf::Accessor& accessor = input.accessors[glTFPrimitive.indices];
 | 
									const tinygltf::Accessor& accessor = model.accessors[primitive.indices];
 | 
				
			||||||
				const tinygltf::BufferView& bufferView = input.bufferViews[accessor.bufferView];
 | 
									const tinygltf::BufferView& bufferView = model.bufferViews[accessor.bufferView];
 | 
				
			||||||
				const tinygltf::Buffer& buffer = input.buffers[bufferView.buffer];
 | 
									const tinygltf::Buffer& buffer = model.buffers[bufferView.buffer];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				indexCount += static_cast<uint32_t>(accessor.count);
 | 
									indexCount += static_cast<uint32_t>(accessor.count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// glTF supports different component types of indices
 | 
									// glTF supports different component types of indices
 | 
				
			||||||
				switch (accessor.componentType) {
 | 
									switch (accessor.componentType) {
 | 
				
			||||||
				case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
 | 
									case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
 | 
				
			||||||
					const uint32_t* buf = reinterpret_cast<const uint32_t*>(&buffer.data[accessor.byteOffset + bufferView.byteOffset]);
 | 
										uint32_t* buf = new uint32_t[accessor.count];
 | 
				
			||||||
 | 
										memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count * sizeof(uint32_t));
 | 
				
			||||||
					for (size_t index = 0; index < accessor.count; index++) {
 | 
										for (size_t index = 0; index < accessor.count; index++) {
 | 
				
			||||||
						indexBuffer.push_back(buf[index] + vertexStart);
 | 
											indexBuffer.push_back(buf[index] + vertexStart);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										delete[] buf;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
 | 
									case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
 | 
				
			||||||
					const uint16_t* buf = reinterpret_cast<const uint16_t*>(&buffer.data[accessor.byteOffset + bufferView.byteOffset]);
 | 
										uint16_t* buf = new uint16_t[accessor.count];
 | 
				
			||||||
 | 
										memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count * sizeof(uint16_t));
 | 
				
			||||||
					for (size_t index = 0; index < accessor.count; index++) {
 | 
										for (size_t index = 0; index < accessor.count; index++) {
 | 
				
			||||||
						indexBuffer.push_back(buf[index] + vertexStart);
 | 
											indexBuffer.push_back(buf[index] + vertexStart);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										delete[] buf;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
 | 
									case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
 | 
				
			||||||
					const uint8_t* buf = reinterpret_cast<const uint8_t*>(&buffer.data[accessor.byteOffset + bufferView.byteOffset]);
 | 
										uint8_t* buf = new uint8_t[accessor.count];
 | 
				
			||||||
 | 
										memcpy(buf, &buffer.data[accessor.byteOffset + bufferView.byteOffset], accessor.count * sizeof(uint8_t));
 | 
				
			||||||
					for (size_t index = 0; index < accessor.count; index++) {
 | 
										for (size_t index = 0; index < accessor.count; index++) {
 | 
				
			||||||
						indexBuffer.push_back(buf[index] + vertexStart);
 | 
											indexBuffer.push_back(buf[index] + vertexStart);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										delete[] buf;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
| 
						 | 
					@ -733,20 +1094,22 @@ void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			Primitive primitive{};
 | 
								Primitive* newPrimitive = new Primitive(firstIndex, indexCount, primitive.material > -1 ? materials[primitive.material] : materials.back());
 | 
				
			||||||
			primitive.firstIndex = firstIndex;
 | 
								newPrimitive->firstVertex = vertexStart;
 | 
				
			||||||
			primitive.indexCount = indexCount;
 | 
								newPrimitive->vertexCount = vertexCount;
 | 
				
			||||||
			primitive.materialIndex = glTFPrimitive.material;
 | 
								newPrimitive->setDimensions(posMin, posMax);
 | 
				
			||||||
			node->mesh.primitives.push_back(primitive);
 | 
								newMesh->primitives.push_back(newPrimitive);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							newNode -> mesh = newMesh;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (parent) {
 | 
						if (parent) {
 | 
				
			||||||
		parent->children.push_back(node);
 | 
							parent->children.push_back(newNode);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		nodes.push_back(node);
 | 
							nodes.push_back(newNode);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						linearNodes.push_back(newNode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index)
 | 
					VulkanglTFModel::Node* VulkanglTFModel::findNode(Node* parent, uint32_t index)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue