Kürzlich arbeite ich an Knochenanimation Import, also habe ich ein 3D-Minecraft-like-Modell mit einigen IK-Technik, Assimp Animation Import zu testen. Das Ausgabeformat ist COLLADA (*. Dae), und das Werkzeug, das ich verwendete, ist Blender. Auf der Programmierseite ist meine Umgebung opengl/glm/assimp. Ich denke, dass diese Informationen für mein Problem genug sind. Eine Sache, die Animation des Modells, ich notiere gerade 7 unmoove keyframe für das Testen von assimp Animation.Assimp Animation Knochen Transformation
Zuerst denke ich, dass meine Transformation außer lokalen Transformationsteil korrekt ist, also lassen Sie die Funktion nur glm::mat4(1.0f)
zurückgeben, und das Ergebnis zeigt das Bind Pose (nicht sicher) Modell. (Siehe Bild unten)
Zweitens den Wert glm::mat4(1.0f)
-bone->localTransform = transform * scaling * glm::mat4(1.0f);
Kehre, dann das Modell deformieren. (Siehe Bild unten)
Testbild und das Modell in Blender: (bone->localTransform = glm::mat4(1.0f) * scaling * rotate;
: Dieses Bild ist unter der Erde :()
Der Code hier:
void MeshModel::UpdateAnimations(float time, std::vector<Bone*>& bones)
{
for each (Bone* bone in bones)
{
glm::mat4 rotate = GetInterpolateRotation(time, bone->rotationKeys);
glm::mat4 transform = GetInterpolateTransform(time, bone->transformKeys);
glm::mat4 scaling = GetInterpolateScaling(time, bone->scalingKeys);
//bone->localTransform = transform * scaling * glm::mat4(1.0f);
//bone->localTransform = glm::mat4(1.0f) * scaling * rotate;
//bone->localTransform = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f));
bone->localTransform = glm::mat4(1.0f);
}
}
void MeshModel::UpdateBone(Bone * bone)
{
glm::mat4 parentTransform = bone->getParentTransform();
bone->nodeTransform = parentTransform
* bone->transform // assimp_node->mTransformation
* bone->localTransform; // T S R matrix
bone->finalTransform = globalInverse
* bone->nodeTransform
* bone->inverseBindPoseMatrix; // ai_mesh->mBones[i]->mOffsetMatrix
for (int i = 0; i < (int)bone->children.size(); i++) {
UpdateBone(bone->children[i]);
}
}
glm::mat4 Bone::getParentTransform()
{
if (this->parent != nullptr)
return parent->nodeTransform;
else
return glm::mat4(1.0f);
}
glm::mat4 MeshModel::GetInterpolateRotation(float time, std::vector<BoneKey>& keys)
{
// we need at least two values to interpolate...
if ((int)keys.size() == 0) {
return glm::mat4(1.0f);
}
if ((int)keys.size() == 1) {
return glm::mat4_cast(keys[0].rotation);
}
int rotationIndex = FindBestTimeIndex(time, keys);
int nextRotationIndex = (rotationIndex + 1);
assert(nextRotationIndex < (int)keys.size());
float DeltaTime = (float)(keys[nextRotationIndex].time - keys[rotationIndex].time);
float Factor = (time - (float)keys[rotationIndex].time)/DeltaTime;
if (Factor < 0.0f)
Factor = 0.0f;
if (Factor > 1.0f)
Factor = 1.0f;
assert(Factor >= 0.0f && Factor <= 1.0f);
const glm::quat& startRotationQ = keys[rotationIndex].rotation;
const glm::quat& endRotationQ = keys[nextRotationIndex].rotation;
glm::quat interpolateQ = glm::lerp(endRotationQ, startRotationQ, Factor);
interpolateQ = glm::normalize(interpolateQ);
return glm::mat4_cast(interpolateQ);
}
glm::mat4 MeshModel::GetInterpolateTransform(float time, std::vector<BoneKey>& keys)
{
// we need at least two values to interpolate...
if ((int)keys.size() == 0) {
return glm::mat4(1.0f);
}
if ((int)keys.size() == 1) {
return glm::translate(glm::mat4(1.0f), keys[0].vector);
}
int translateIndex = FindBestTimeIndex(time, keys);
int nextTranslateIndex = (translateIndex + 1);
assert(nextTranslateIndex < (int)keys.size());
float DeltaTime = (float)(keys[nextTranslateIndex].time - keys[translateIndex].time);
float Factor = (time - (float)keys[translateIndex].time)/DeltaTime;
if (Factor < 0.0f)
Factor = 0.0f;
if (Factor > 1.0f)
Factor = 1.0f;
assert(Factor >= 0.0f && Factor <= 1.0f);
const glm::vec3& startTranslate = keys[translateIndex].vector;
const glm::vec3& endTrabslate = keys[nextTranslateIndex].vector;
glm::vec3 delta = endTrabslate - startTranslate;
glm::vec3 resultVec = startTranslate + delta * Factor;
return glm::translate(glm::mat4(1.0f), resultVec);
}
Der Code Idee verwiesen wird Matrix calculations for gpu skinning und Skeletal Animation With Assimp
Insgesamt fekt ich alle Informationen von Assimp zu MeshModel und speichern Sie es in der Knochenstruktur, also denke ich, dass die Information in Ordnung ist?
Das letzte, was, mein Vertex-Shader-Code:
#version 330 core
#define MAX_BONES_PER_VERTEX 4
in vec3 position;
in vec2 texCoord;
in vec3 normal;
in ivec4 boneID;
in vec4 boneWeight;
const int MAX_BONES = 100;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 boneTransform[MAX_BONES];
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
out float Visibility;
const float density = 0.007f;
const float gradient = 1.5f;
void main()
{
mat4 boneTransformation = boneTransform[boneID[0]] * boneWeight[0];
boneTransformation += boneTransform[boneID[1]] * boneWeight[1];
boneTransformation += boneTransform[boneID[2]] * boneWeight[2];
boneTransformation += boneTransform[boneID[3]] * boneWeight[3];
vec3 usingPosition = (boneTransformation * vec4(position, 1.0)).xyz;
vec3 usingNormal = (boneTransformation * vec4(normal, 1.0)).xyz;
vec4 viewPos = view * model * vec4(usingPosition, 1.0);
gl_Position = projection * viewPos;
FragPos = vec3(model * vec4(usingPosition, 1.0f));
Normal = mat3(transpose(inverse(model))) * usingNormal;
TexCoords = texCoord;
float distance = length(viewPos.xyz);
Visibility = exp(-pow(distance * density, gradient));
Visibility = clamp(Visibility, 0.0f, 1.0f);
}
Wenn meine Frage oben, Mangel an Code oder vage beschreiben, lassen Sie es mich wissen, Dank!
Edit: (1)
In weiteren, meine Knochen Informationen wie diese (Code Holen Teil):
for (int i = 0; i < (int)nodeAnim->mNumPositionKeys; i++)
{
BoneKey key;
key.time = nodeAnim->mPositionKeys[i].mTime;
aiVector3D vec = nodeAnim->mPositionKeys[i].mValue;
key.vector = glm::vec3(vec.x, vec.y, vec.z);
currentBone->transformKeys.push_back(key);
}
einige Transformationsvektor hatte, so meinen Code über glm::mat4 transform = GetInterpolateTransform(time, bone->transformKeys);
, Absloutely, erhalten die gleichen Wert von ihm. Ich bin mir nicht sicher, ob ich eine Nomove-Keyframe-Animation gemacht habe, die die Transformationswerte liefert oder nicht (natürlich hat sie 7 Keyframes).
Ein Keyframe Inhalt wie folgt (Debug auf Kopf Knochen): 7 verschiedene Keyframe, gleichen Vektor Wert.
Edit: (2)
Wenn Sie meine dae-Datei zu testen, habe ich es in jsfiddle, kommen und es nehmen :). Eine andere Sache, in Unity meine Datei funktioniert korrekt, so denke ich, vielleicht nicht meine lokale Transformation tritt das Problem, es scheint, das Problem könnte eine andere wie ParentTransform oder bone-> transform ... etc? Ich aslo hinzufügen lokaler Transformationsmatrix mit allen Knochen, kann aber nicht herausfinden, warum COLLADA diesen Wert für meine unmove Animation enthält ...