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_1"] = gltfModel.accessors.size() + 2;
|
||||
gltfPrimitive.attributes["NORMAL"] = gltfModel.accessors.size() + 3;
|
||||
gltfPrimitive.attributes["COLOR_0"] = gltfModel.accessors.size() + 6;
|
||||
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 7;
|
||||
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 8;
|
||||
gltfPrimitive.attributes["TANGENT"] = gltfModel.accessors.size() + 4;
|
||||
gltfPrimitive.attributes["COLOR_0"] = gltfModel.accessors.size() + 5;
|
||||
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 6;
|
||||
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 7;
|
||||
}
|
||||
|
||||
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.byteOffset = offsetof(Vertex, normal);
|
||||
|
||||
auto &tangent1Accessor = gltfModel.accessors.emplace_back();
|
||||
tangent1Accessor.bufferView = gltfModel.bufferViews.size();
|
||||
tangent1Accessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||
tangent1Accessor.count = lod.parts[i].num_vertices;
|
||||
tangent1Accessor.type = TINYGLTF_TYPE_VEC4;
|
||||
tangent1Accessor.byteOffset = offsetof(Vertex, tangent1);
|
||||
|
||||
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);
|
||||
// We're reusing this spot for tangents (see later post-processing step)
|
||||
auto &tangentAccessor = gltfModel.accessors.emplace_back();
|
||||
tangentAccessor.bufferView = gltfModel.bufferViews.size();
|
||||
tangentAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||
tangentAccessor.count = lod.parts[i].num_vertices;
|
||||
tangentAccessor.type = TINYGLTF_TYPE_VEC4;
|
||||
tangentAccessor.byteOffset = offsetof(Vertex, bitangent);
|
||||
|
||||
auto &colorAccessor = gltfModel.accessors.emplace_back();
|
||||
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[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);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,20 +84,18 @@ void importModel(physis_MDL &existingModel, const QString &filename)
|
|||
auto &mesh = model.meshes[node.mesh];
|
||||
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 &positionView = model.bufferViews[positionAccessor.bufferView];
|
||||
const auto &positionBuffer = model.buffers[positionView.buffer];
|
||||
|
||||
int elementCount = tinygltf::GetNumComponentsInType(positionAccessor.type);
|
||||
int elementSize = tinygltf::GetComponentSizeInBytes(positionAccessor.componentType);
|
||||
|
||||
return (positionBuffer.data.data() + (std::max(positionView.byteStride, (size_t)elementCount * elementSize) * index) + positionView.byteOffset
|
||||
return (positionBuffer.data.data() + (positionAccessor.ByteStride(positionView) * index) + positionView.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 &colorAccessor = model.accessors[primitive.attributes["COLOR_0"]];
|
||||
|
||||
const auto &indexAccessor = model.accessors[primitive.indices];
|
||||
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::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));
|
||||
glm::vec4 const *tangent1Data = reinterpret_cast<glm::vec4 const *>(getAccessor("TANGENT", i));
|
||||
|
||||
// Replace position data
|
||||
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[1] = positionData->y;
|
||||
|
@ -145,6 +141,34 @@ void importModel(physis_MDL &existingModel, const QString &filename)
|
|||
vertex.bone_weight[2] = weightsData->z;
|
||||
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
|
||||
// When exporting from modeling software, it's possible it sorted the nodes (Blender does this)
|
||||
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 = 2) in vec2 inUV1;
|
||||
layout(location = 3) in vec3 inNormal;
|
||||
layout(location = 4) in uvec4 inTangent1;
|
||||
layout(location = 5) in uvec4 inTangent2;
|
||||
layout(location = 6) in vec4 inColor;
|
||||
layout(location = 7) in vec4 inBoneWeights;
|
||||
layout(location = 8) in uvec4 inBoneIds;
|
||||
layout(location = 4) in vec4 inBiTangent;
|
||||
layout(location = 5) in vec4 inColor;
|
||||
layout(location = 6) in vec4 inBoneWeights;
|
||||
layout(location = 7) in uvec4 inBoneIds;
|
||||
|
||||
layout(location = 0) out vec3 outNormal;
|
||||
layout(location = 1) out vec3 outFragPos;
|
||||
|
|
Binary file not shown.
|
@ -759,40 +759,28 @@ void Renderer::initPipeline()
|
|||
normalAttribute.location = 3;
|
||||
normalAttribute.offset = offsetof(Vertex, normal);
|
||||
|
||||
VkVertexInputAttributeDescription tangent1Attribute = {};
|
||||
tangent1Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||
tangent1Attribute.location = 4;
|
||||
tangent1Attribute.offset = offsetof(Vertex, tangent1);
|
||||
|
||||
VkVertexInputAttributeDescription tangent2Attribute = {};
|
||||
tangent2Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||
tangent2Attribute.location = 5;
|
||||
tangent2Attribute.offset = offsetof(Vertex, tangent2);
|
||||
VkVertexInputAttributeDescription bitangentAttribute = {};
|
||||
bitangentAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
bitangentAttribute.location = 4;
|
||||
bitangentAttribute.offset = offsetof(Vertex, bitangent);
|
||||
|
||||
VkVertexInputAttributeDescription colorAttribute = {};
|
||||
colorAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
colorAttribute.location = 6;
|
||||
colorAttribute.location = 5;
|
||||
colorAttribute.offset = offsetof(Vertex, color);
|
||||
|
||||
VkVertexInputAttributeDescription boneWeightAttribute = {};
|
||||
boneWeightAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
boneWeightAttribute.location = 7;
|
||||
boneWeightAttribute.location = 6;
|
||||
boneWeightAttribute.offset = offsetof(Vertex, bone_weight);
|
||||
|
||||
VkVertexInputAttributeDescription boneIdAttribute = {};
|
||||
boneIdAttribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||
boneIdAttribute.location = 8;
|
||||
boneIdAttribute.location = 7;
|
||||
boneIdAttribute.offset = offsetof(Vertex, bone_id);
|
||||
|
||||
const std::array attributes = {positionAttribute,
|
||||
uv0Attribute,
|
||||
uv1Attribute,
|
||||
normalAttribute,
|
||||
tangent1Attribute,
|
||||
tangent2Attribute,
|
||||
colorAttribute,
|
||||
boneWeightAttribute,
|
||||
boneIdAttribute};
|
||||
const std::array attributes =
|
||||
{positionAttribute, uv0Attribute, uv1Attribute, normalAttribute, bitangentAttribute, colorAttribute, boneWeightAttribute, boneIdAttribute};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
|
||||
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
|
|
Loading…
Add table
Reference in a new issue