Animation
애니메이션도 FBX 확장자를 사용한다.
- 애니메이션
- Clip
- Duration
- FrameRate
- FrameCount
- ModelKeyFrame
- ModelKeyframe
- BoneName
- KeyframeData(여러개)
- KeyframeData
- Time
- Scale
- Rotation
- translate 이렇게 필요하다.
- Clip
각 클립에는 총 얼마나 진행하는지, 몇 프레임이 필요한지, 프레임 레이트가 몇인지 필요하다.
그리고 클립에는 KeyFrame을 갖고있는데 KeyFrame에는 어떤 본인지 알 수 있는 이름과 각 프레임 데이터들이 있다.
그리고 프레임 데이터에는 Scale, Rotation, Translate의 데이터를 갖고있다.
Type.h
struct asBlendWeight
{
Vector4 Indices = Vector4(0, 0, 0, 0);
Vector4 Weights = Vector4(0, 0, 0, 0);
void Set(UINT index, UINT boneIndex, float weight)
{
float i = (float)boneIndex;
float w = weight;
switch (index)
{
case 0: Indices.x = i; Weights.x = w; break;
case 1: Indices.y = i; Weights.y = w; break;
case 2: Indices.z = i; Weights.z = w; break;
case 3: Indices.w = i; Weights.w = w; break;
}
}
};
struct asBoneWeights
{
private:
typedef pair<int, float> Pair;
vector<Pair> BoneWeights;
public:
void AddWeights(UINT boneIndex, float boneWeights)
{
if (boneWeights <= 0.0f) return;
bool bInsert = false;
vector<Pair>::iterator it = BoneWeights.begin();
while (it != BoneWeights.end())
{
if (boneWeights > it->second)
{
BoneWeights.insert(it, Pair(boneIndex, boneWeights));
bInsert = true;
break;
}
it++;
} // while(it)
if (bInsert == false)
BoneWeights.push_back(Pair(boneIndex, boneWeights));
}
void GetBlendWeights(asBlendWeight& blendWeights)
{
for (UINT i = 0; i < BoneWeights.size(); i++)
{
if (i >= 4) return;
blendWeights.Set(i, BoneWeights[i].first, BoneWeights[i].second);
}
}
void Normalize()
{
float totalWeight = 0.0f;
int i = 0;
vector<Pair>::iterator it = BoneWeights.begin();
while (it != BoneWeights.end())
{
if (i < 4)
{
totalWeight += it->second;
i++; it++;
}
else
it = BoneWeights.erase(it);
}
float scale = 1.0f / totalWeight;
it = BoneWeights.begin();
while (it != BoneWeights.end())
{
it->second *= scale;
it++;
}
}
};
각 Index와 가중치를 갖고있는 구조체이다.
가중치는 큰 순서부터 넣는게 국룰이라고 한다.
Convert.cpp
void Converter::ReadSkinData()
{
for (UINT i = 0; i < scene->mNumMeshes; i++)
{
aiMesh* aiMesh = scene->mMeshes[i];
if (aiMesh->HasBones() == false) { continue; }
asMesh* mesh = meshes[i];
vector<asBoneWeights> boneWeights;
boneWeights.assign(mesh->Vertices.size(), asBoneWeights());
for (UINT b = 0; b < aiMesh->mNumBones; b++)
{
aiBone* aiMeshBone = aiMesh->mBones[b];
UINT boneIndex = 0;
for (asBone* bone : bones)
{
if (bone->Name == (string)aiMeshBone->mName.C_Str())
{
boneIndex = bone->Index;
break;
}
}// for(bone)
for (UINT w = 0; w < aiMeshBone->mNumWeights; w++)
{
UINT index = aiMeshBone->mWeights[w].mVertexId;
float weight = aiMeshBone->mWeights[w].mWeight;
boneWeights[index].AddWeights(boneIndex, weight);
}
}// for(b)
for (UINT w = 0; w < boneWeights.size(); w++)
{
boneWeights[i].Normalize();
asBlendWeight blendWeight;
boneWeights[w].GetBlendWeights(blendWeight);
mesh->Vertices[w].BlendIndices = blendWeight.Indices;
mesh->Vertices[w].BlendWeights = blendWeight.Weights;
}
}
}
각 매쉬에 있는 본에 Index와 Weight를 가져와서 새로 생성해준다.
그런 뒤, 하나씩 넣어준다.