Где-то в процессе расчета преобразований в иерархии узлов преобразования не доходят до единичной матрицы.
Я уже пробовал
- проверить, не была ли какая-либо из моих матриц транспонирована
- расчет новой матрицы смещений
- различные методы вычисление средневзвешенного значения костей в вершинном шейдере
- проверка правильности поступления данных в графический процессор (проверено с помощью Nvidia NSight)
Мой код для расчета преобразований в иерархии узлов выглядит следующим образом:
< pre class="lang-java Prettyprint-override">
Код: Выделить всё
private Model model;
private Armature armature;
private final Matrix4f[] finalTransforms;
// ...
public void apply() {
recurseBones(model.scene.mRootNode(), new Matrix4f());
for(int i = 0; i < finalTransforms.length; i++)
armature.setBonePose(i, finalTransforms[i]); //updates byte buffer
//sends pose data to shader storage buffer from byte buffer
armature.updatePose();
}
protected void recurseBones(AINode node, Matrix4f parentTransform) {
var name = node.mName().dataString();
var nodeTransform = convertMatrix(node.mTransformation()); //AIMatrix4x4 to Matrix4f
var globalTransform = parentTransform.mul(nodeTransform, new Matrix4f());
var bone = armature.boneLookup.get(name);
if(bone != null) {
finalTransforms[bone.index] =
// new Matrix4f(); //expected output
globalTransform.mul(bone.offset, new Matrix4f()); //incorrect result
}
for(int childIndex = 0; childIndex < node.mNumChildren(); childIndex++) {
recurseBones(AINode.create(node.mChildren().get(childIndex)), globalTransform);
}
}
Вертексный шейдер (вес костей передается с помощью буферов хранения шейдеров) )
Код: Выделить всё
#version 450
// ...
void main() {
// ...
int vertexStartIndex = //...
int nBones = // ...
mat4 poseTransform = mat4(0);
float totalWeight = 0;
for(int b = 0; b < nBones; b++) {
totalWeight += weights[vertexStartIndex + b].weight;
}
vec4 posedPos;
if(totalWeight > 0) {
for(int b = 0; b < nBones; b++) {
Weight weightInfo = weights[vertexStartIndex + b];
int boneID = weightInfo.boneID;
float weight = weightInfo.weight;
Pose pose = poses[boneID];
poseTransform += pose.transform * (weight / totalWeight);
}
posedPos = poseTransform * vec4(aVertex, 1.0);
} else {
posedPos = vec4(aVertex.xyz, 1.0);
}
vec4 pos = uProjectionMatrix * uViewMatrix * uModelMatrix * posedPos;
gl_Position = pos;
//...
}
Я ожидал, что все FinalTransforms должны быть идентификационной матрицей и чтоbone.offset должно быть обратным родительскому преобразованию * nodeTransform.
Когда я заставляю значение быть идентификационной матрицей, моя модель использует
Код: Выделить всё
finalTransforms[bone.index] = new Matrix4f();
При выполнении расчетов по учебному коду Вместо этого я получаю искаженный беспорядок
Код: Выделить всё
finalTransforms[bone.index] = globalTransform.mul(bone.offset, new Matrix4f());


Насколько я понимаю, кумулятивные преобразования из локального пространства в костное пространство должны быть нейтрализованы матрица смещения с идеей позже заменить отдельные преобразования костей преобразованиями из данных анимации.
Редактирование: сокращенный вопрос + включенные попытки
Редактирование: форматирование
Подробнее здесь: https://stackoverflow.com/questions/792 ... inned-mesh
Мобильная версия