mirror of
https://github.com/redstrate/Novus.git
synced 2025-06-07 13:47:45 +00:00
Fix tangent reading/writing
Updates to latest physis changes, and fixing tangent reading/writing.
This commit is contained in:
parent
9f6be07254
commit
693a47cf4e
6 changed files with 70 additions and 52 deletions
2
extern/libphysis
vendored
2
extern/libphysis
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit b439934f816fef2f07a62cf04cf892d46e1c4080
|
Subproject commit be79c3c9e7dedcdf7494f2ed849ce257d5421230
|
|
@ -175,9 +175,10 @@ void exportModel(const QString &name, const physis_MDL &model, const physis_Skel
|
||||||
gltfPrimitive.attributes["TEXCOORD_0"] = gltfModel.accessors.size() + 1;
|
gltfPrimitive.attributes["TEXCOORD_0"] = gltfModel.accessors.size() + 1;
|
||||||
gltfPrimitive.attributes["TEXCOORD_1"] = gltfModel.accessors.size() + 2;
|
gltfPrimitive.attributes["TEXCOORD_1"] = gltfModel.accessors.size() + 2;
|
||||||
gltfPrimitive.attributes["NORMAL"] = gltfModel.accessors.size() + 3;
|
gltfPrimitive.attributes["NORMAL"] = gltfModel.accessors.size() + 3;
|
||||||
gltfPrimitive.attributes["COLOR_0"] = gltfModel.accessors.size() + 6;
|
gltfPrimitive.attributes["TANGENT"] = gltfModel.accessors.size() + 4;
|
||||||
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 7;
|
gltfPrimitive.attributes["COLOR_0"] = gltfModel.accessors.size() + 5;
|
||||||
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 8;
|
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 6;
|
||||||
|
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh_offset += part.num_submeshes;
|
mesh_offset += part.num_submeshes;
|
||||||
|
@ -211,19 +212,13 @@ void exportModel(const QString &name, const physis_MDL &model, const physis_Skel
|
||||||
normalAccessor.type = TINYGLTF_TYPE_VEC3;
|
normalAccessor.type = TINYGLTF_TYPE_VEC3;
|
||||||
normalAccessor.byteOffset = offsetof(Vertex, normal);
|
normalAccessor.byteOffset = offsetof(Vertex, normal);
|
||||||
|
|
||||||
auto &tangent1Accessor = gltfModel.accessors.emplace_back();
|
// We're reusing this spot for tangents (see later post-processing step)
|
||||||
tangent1Accessor.bufferView = gltfModel.bufferViews.size();
|
auto &tangentAccessor = gltfModel.accessors.emplace_back();
|
||||||
tangent1Accessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
tangentAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
tangent1Accessor.count = lod.parts[i].num_vertices;
|
tangentAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
tangent1Accessor.type = TINYGLTF_TYPE_VEC4;
|
tangentAccessor.count = lod.parts[i].num_vertices;
|
||||||
tangent1Accessor.byteOffset = offsetof(Vertex, tangent1);
|
tangentAccessor.type = TINYGLTF_TYPE_VEC4;
|
||||||
|
tangentAccessor.byteOffset = offsetof(Vertex, bitangent);
|
||||||
auto &tangent2Accessor = gltfModel.accessors.emplace_back();
|
|
||||||
tangent2Accessor.bufferView = gltfModel.bufferViews.size();
|
|
||||||
tangent2Accessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
|
||||||
tangent2Accessor.count = lod.parts[i].num_vertices;
|
|
||||||
tangent2Accessor.type = TINYGLTF_TYPE_VEC4;
|
|
||||||
tangent2Accessor.byteOffset = offsetof(Vertex, tangent2);
|
|
||||||
|
|
||||||
auto &colorAccessor = gltfModel.accessors.emplace_back();
|
auto &colorAccessor = gltfModel.accessors.emplace_back();
|
||||||
colorAccessor.bufferView = gltfModel.bufferViews.size();
|
colorAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
@ -261,6 +256,18 @@ void exportModel(const QString &name, const physis_MDL &model, const physis_Skel
|
||||||
vertex.bone_id[2]++;
|
vertex.bone_id[2]++;
|
||||||
vertex.bone_id[3]++;
|
vertex.bone_id[3]++;
|
||||||
|
|
||||||
|
// Do the reverse of what we do in importing, because we need to get the tangent from the binormal.
|
||||||
|
const glm::vec3 normal = glm::vec3(vertex.normal[0], vertex.normal[1], vertex.normal[2]);
|
||||||
|
const glm::vec4 tangent = glm::vec4(vertex.bitangent[0], vertex.bitangent[1], vertex.bitangent[2], vertex.bitangent[3]);
|
||||||
|
const glm::vec3 bitangent = glm::cross(glm::vec3(tangent), normal) * tangent.w;
|
||||||
|
|
||||||
|
const float handedness = glm::dot(glm::cross(bitangent, glm::vec3(tangent)), normal) > 0 ? 1 : -1;
|
||||||
|
|
||||||
|
vertex.bitangent[0] = bitangent.x;
|
||||||
|
vertex.bitangent[1] = bitangent.y;
|
||||||
|
vertex.bitangent[2] = bitangent.z;
|
||||||
|
vertex.bitangent[3] = handedness;
|
||||||
|
|
||||||
newVertices.push_back(vertex);
|
newVertices.push_back(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,20 +84,18 @@ void importModel(physis_MDL &existingModel, const QString &filename)
|
||||||
auto &mesh = model.meshes[node.mesh];
|
auto &mesh = model.meshes[node.mesh];
|
||||||
auto &primitive = mesh.primitives[0];
|
auto &primitive = mesh.primitives[0];
|
||||||
|
|
||||||
const auto getAccessor = [&model, &primitive](const std::string &name, const int index) -> unsigned char const * {
|
const auto getAccessor = [&model, &primitive](const std::string &name, const size_t index) -> unsigned char const * {
|
||||||
const auto &positionAccessor = model.accessors[primitive.attributes[name]];
|
const auto &positionAccessor = model.accessors[primitive.attributes[name]];
|
||||||
const auto &positionView = model.bufferViews[positionAccessor.bufferView];
|
const auto &positionView = model.bufferViews[positionAccessor.bufferView];
|
||||||
const auto &positionBuffer = model.buffers[positionView.buffer];
|
const auto &positionBuffer = model.buffers[positionView.buffer];
|
||||||
|
|
||||||
int elementCount = tinygltf::GetNumComponentsInType(positionAccessor.type);
|
return (positionBuffer.data.data() + (positionAccessor.ByteStride(positionView) * index) + positionView.byteOffset
|
||||||
int elementSize = tinygltf::GetComponentSizeInBytes(positionAccessor.componentType);
|
|
||||||
|
|
||||||
return (positionBuffer.data.data() + (std::max(positionView.byteStride, (size_t)elementCount * elementSize) * index) + positionView.byteOffset
|
|
||||||
+ positionAccessor.byteOffset);
|
+ positionAccessor.byteOffset);
|
||||||
};
|
};
|
||||||
|
|
||||||
// All of the accessors are mapped to the same buffer vertex view
|
// All the accessors are mapped to the same buffer vertex view
|
||||||
const auto &positionAccessor = model.accessors[primitive.attributes["POSITION"]];
|
const auto &positionAccessor = model.accessors[primitive.attributes["POSITION"]];
|
||||||
|
const auto &colorAccessor = model.accessors[primitive.attributes["COLOR_0"]];
|
||||||
|
|
||||||
const auto &indexAccessor = model.accessors[primitive.indices];
|
const auto &indexAccessor = model.accessors[primitive.indices];
|
||||||
const auto &indexView = model.bufferViews[indexAccessor.bufferView];
|
const auto &indexView = model.bufferViews[indexAccessor.bufferView];
|
||||||
|
@ -119,12 +117,10 @@ void importModel(physis_MDL &existingModel, const QString &filename)
|
||||||
glm::vec2 const *uv1Data = reinterpret_cast<glm::vec2 const *>(getAccessor("TEXCOORD_1", i));
|
glm::vec2 const *uv1Data = reinterpret_cast<glm::vec2 const *>(getAccessor("TEXCOORD_1", i));
|
||||||
glm::vec4 const *weightsData = reinterpret_cast<glm::vec4 const *>(getAccessor("WEIGHTS_0", i));
|
glm::vec4 const *weightsData = reinterpret_cast<glm::vec4 const *>(getAccessor("WEIGHTS_0", i));
|
||||||
uint8_t const *jointsData = reinterpret_cast<uint8_t const *>(getAccessor("JOINTS_0", i));
|
uint8_t const *jointsData = reinterpret_cast<uint8_t const *>(getAccessor("JOINTS_0", i));
|
||||||
|
glm::vec4 const *tangent1Data = reinterpret_cast<glm::vec4 const *>(getAccessor("TANGENT", i));
|
||||||
|
|
||||||
// Replace position data
|
// Replace position data
|
||||||
Vertex vertex{};
|
Vertex vertex{};
|
||||||
if (i < existingModel.lods[lodNumber].parts[partNumber].num_vertices) {
|
|
||||||
vertex = existingModel.lods[lodNumber].parts[partNumber].vertices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex.position[0] = positionData->x;
|
vertex.position[0] = positionData->x;
|
||||||
vertex.position[1] = positionData->y;
|
vertex.position[1] = positionData->y;
|
||||||
|
@ -145,6 +141,34 @@ void importModel(physis_MDL &existingModel, const QString &filename)
|
||||||
vertex.bone_weight[2] = weightsData->z;
|
vertex.bone_weight[2] = weightsData->z;
|
||||||
vertex.bone_weight[3] = weightsData->w;
|
vertex.bone_weight[3] = weightsData->w;
|
||||||
|
|
||||||
|
// calculate binormal, because glTF won't give us those!!
|
||||||
|
const glm::vec3 normal = glm::vec3(vertex.normal[0], vertex.normal[1], vertex.normal[2]);
|
||||||
|
const glm::vec4 tangent = *tangent1Data;
|
||||||
|
const glm::vec3 bitangent = glm::cross(normal, glm::vec3(tangent)) * tangent.w;
|
||||||
|
|
||||||
|
const float handedness = glm::dot(glm::cross(glm::vec3(tangent), bitangent), normal) > 0 ? 1 : -1;
|
||||||
|
|
||||||
|
// In a cruel twist of fate, Tangent1 is actually the **BINORMAL** and not the tangent data. Square Enix is AMAZING.
|
||||||
|
vertex.bitangent[0] = bitangent.x;
|
||||||
|
vertex.bitangent[1] = bitangent.y;
|
||||||
|
vertex.bitangent[2] = bitangent.z;
|
||||||
|
vertex.bitangent[3] = handedness;
|
||||||
|
|
||||||
|
if (colorAccessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
|
||||||
|
unsigned short const *colorData = reinterpret_cast<unsigned short const *>(getAccessor("COLOR_0", i));
|
||||||
|
|
||||||
|
vertex.color[0] = static_cast<float>(*colorData) / std::numeric_limits<unsigned short>::max();
|
||||||
|
vertex.color[1] = static_cast<float>(*(colorData + 1)) / std::numeric_limits<unsigned short>::max();
|
||||||
|
vertex.color[2] = static_cast<float>(*(colorData + 2)) / std::numeric_limits<unsigned short>::max();
|
||||||
|
vertex.color[3] = static_cast<float>(*(colorData + 3)) / std::numeric_limits<unsigned short>::max();
|
||||||
|
} else {
|
||||||
|
glm::vec4 const *colorData = reinterpret_cast<glm::vec4 const *>(getAccessor("COLOR_0", i));
|
||||||
|
vertex.color[0] = colorData->x;
|
||||||
|
vertex.color[1] = colorData->y;
|
||||||
|
vertex.color[2] = colorData->z;
|
||||||
|
vertex.color[3] = colorData->w;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to ensure the bones are mapped correctly
|
// We need to ensure the bones are mapped correctly
|
||||||
// When exporting from modeling software, it's possible it sorted the nodes (Blender does this)
|
// When exporting from modeling software, it's possible it sorted the nodes (Blender does this)
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
|
|
@ -7,11 +7,10 @@ layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec2 inUV0;
|
layout(location = 1) in vec2 inUV0;
|
||||||
layout(location = 2) in vec2 inUV1;
|
layout(location = 2) in vec2 inUV1;
|
||||||
layout(location = 3) in vec3 inNormal;
|
layout(location = 3) in vec3 inNormal;
|
||||||
layout(location = 4) in uvec4 inTangent1;
|
layout(location = 4) in vec4 inBiTangent;
|
||||||
layout(location = 5) in uvec4 inTangent2;
|
layout(location = 5) in vec4 inColor;
|
||||||
layout(location = 6) in vec4 inColor;
|
layout(location = 6) in vec4 inBoneWeights;
|
||||||
layout(location = 7) in vec4 inBoneWeights;
|
layout(location = 7) in uvec4 inBoneIds;
|
||||||
layout(location = 8) in uvec4 inBoneIds;
|
|
||||||
|
|
||||||
layout(location = 0) out vec3 outNormal;
|
layout(location = 0) out vec3 outNormal;
|
||||||
layout(location = 1) out vec3 outFragPos;
|
layout(location = 1) out vec3 outFragPos;
|
||||||
|
|
Binary file not shown.
|
@ -759,40 +759,28 @@ void Renderer::initPipeline()
|
||||||
normalAttribute.location = 3;
|
normalAttribute.location = 3;
|
||||||
normalAttribute.offset = offsetof(Vertex, normal);
|
normalAttribute.offset = offsetof(Vertex, normal);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription tangent1Attribute = {};
|
VkVertexInputAttributeDescription bitangentAttribute = {};
|
||||||
tangent1Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
bitangentAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
tangent1Attribute.location = 4;
|
bitangentAttribute.location = 4;
|
||||||
tangent1Attribute.offset = offsetof(Vertex, tangent1);
|
bitangentAttribute.offset = offsetof(Vertex, bitangent);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription tangent2Attribute = {};
|
|
||||||
tangent2Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
|
||||||
tangent2Attribute.location = 5;
|
|
||||||
tangent2Attribute.offset = offsetof(Vertex, tangent2);
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription colorAttribute = {};
|
VkVertexInputAttributeDescription colorAttribute = {};
|
||||||
colorAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
colorAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
colorAttribute.location = 6;
|
colorAttribute.location = 5;
|
||||||
colorAttribute.offset = offsetof(Vertex, color);
|
colorAttribute.offset = offsetof(Vertex, color);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription boneWeightAttribute = {};
|
VkVertexInputAttributeDescription boneWeightAttribute = {};
|
||||||
boneWeightAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
boneWeightAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
boneWeightAttribute.location = 7;
|
boneWeightAttribute.location = 6;
|
||||||
boneWeightAttribute.offset = offsetof(Vertex, bone_weight);
|
boneWeightAttribute.offset = offsetof(Vertex, bone_weight);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription boneIdAttribute = {};
|
VkVertexInputAttributeDescription boneIdAttribute = {};
|
||||||
boneIdAttribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
boneIdAttribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||||
boneIdAttribute.location = 8;
|
boneIdAttribute.location = 7;
|
||||||
boneIdAttribute.offset = offsetof(Vertex, bone_id);
|
boneIdAttribute.offset = offsetof(Vertex, bone_id);
|
||||||
|
|
||||||
const std::array attributes = {positionAttribute,
|
const std::array attributes =
|
||||||
uv0Attribute,
|
{positionAttribute, uv0Attribute, uv1Attribute, normalAttribute, bitangentAttribute, colorAttribute, boneWeightAttribute, boneIdAttribute};
|
||||||
uv1Attribute,
|
|
||||||
normalAttribute,
|
|
||||||
tangent1Attribute,
|
|
||||||
tangent2Attribute,
|
|
||||||
colorAttribute,
|
|
||||||
boneWeightAttribute,
|
|
||||||
boneIdAttribute};
|
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
|
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
|
||||||
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
|
Loading…
Add table
Reference in a new issue