OpenGL/Assimp — Как вычислить иерархию преобразований для сетки со шкуройJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 OpenGL/Assimp — Как вычислить иерархию преобразований для сетки со шкурой

Сообщение Anonymous »

Я пытаюсь настроить рендеринг для скелетной/скелетной анимации (преобразований поз пока нет). Модель импортируется с помощью Assimp и отображается с помощью OpenGL.
Где-то в процессе расчета преобразований в иерархии узлов преобразования не доходят до единичной матрицы.
Я уже пробовал
  • проверить, не была ли какая-либо из моих матриц транспонирована
  • расчет новой матрицы смещений
  • различные методы вычисление средневзвешенного значения костей в вершинном шейдере
  • проверка правильности поступления данных в графический процессор (проверено с помощью 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»