最近私はボーンアニメーションのインポートに取り組んでいます。そのため、Iimpテクニックを使用した3Dミニクラフトのようなモデルを作成し、Assimpアニメーションのインポートをテストしました。出力フォーマットはCOLLADA(*。dae)で、私が使用したツールはBlenderです。プログラミング面では、私の環境はopengl/glm/assimpです。私の問題のこれらの情報は十分だと思います.1つは、モデルのアニメーション、私はちょうどassimpアニメーションをテストするための7 unmoveキーフレームを記録します。Assimpアニメーションボーン変換
まず、ローカル変換部分以外の変換は正しいと思いますので、関数はglm::mat4(1.0f)
のみを返し、結果はバインドポーズ(不明)モデルを返します。 (下図参照)
第2に、値glm::mat4(1.0f)
をbone->localTransform = transform * scaling * glm::mat4(1.0f);
に戻すと、モデルが変形します。 (
bone->localTransform = glm::mat4(1.0f) * scaling * rotate;
:この画像は:(地面の下にある)
ここでコード:ブレンダーで
テスト画像とモデル(画像下記参照)
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);
}
をコードアイデアが参照されMatrix calculations for gpu skinningとSkeletal Animation With Assimp
全体として、私はassimpからのすべての情報をMeshModelにフェッチして骨構造に保存しますが、情報は問題ないと思いますか?
最後の事、私の頂点シェーダコード:
#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);
}
上記の私の質問の場合、コードの欠如や漠然と説明し、おかげで、私に知らせてください!
編集:このような追加的な、私の骨の情報(コードフェッチ部分)では(1)
:
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);
}
は、いくつかの形質転換ベクターを持っていたのでglm::mat4 transform = GetInterpolateTransform(time, bone->transformKeys);
上記の私のコード、Absloutely、取得と同じ値です。私は変換値が真であるかどうかを指定するnomoveキーフレームアニメーションを作成したかどうかはわかりません(もちろん7つのキーフレームがあります)。
このようなキーフレームのコンテンツ(頭骨のデバッグ): 7つの異なるキーフレーム、同じベクトル値。
編集:あなたは私のDAEファイルをテストする場合(2)
を、私は、jsfiddleに入れて来て、それを取る:)。もう一つ、ユニティで私のファイルが正しく動作するので、おそらく私のローカル変換が問題を起こしていないと思われます。問題はparentTransformやbone-> transform ...などのようなものかもしれませんね?私はすべての骨を使ってローカル変換行列を追加しますが、なぜ私のunmoveアニメーションにこれらの値が含まれているのかわかりません...