Fixing animation bugs
This commit is contained in:
parent
b5877a488d
commit
2a16970cde
@ -251,7 +251,7 @@ namespace ZL
|
||||
}
|
||||
|
||||
std::getline(f, tempLine);//=== Vertex Weights ===
|
||||
std::vector<std::array<BoneWeight, 3>> localVerticesBoneWeight;
|
||||
std::vector<std::array<BoneWeight, MAX_BONE_COUNT>> localVerticesBoneWeight;
|
||||
localVerticesBoneWeight.resize(numberVertices);
|
||||
|
||||
for (int i = 0; i < numberVertices; i++)
|
||||
@ -268,9 +268,9 @@ namespace ZL
|
||||
throw std::runtime_error("No number found in the input string.");
|
||||
}
|
||||
|
||||
if (boneCount > 3)
|
||||
if (boneCount > MAX_BONE_COUNT)
|
||||
{
|
||||
throw std::runtime_error("more than 3 bones");
|
||||
throw std::runtime_error("more than 5 bones");
|
||||
}
|
||||
|
||||
float sumWeights = 0;
|
||||
@ -464,6 +464,7 @@ namespace ZL
|
||||
//std::vector<Matrix3f> skinningMatrixForEachBone;
|
||||
skinningMatrixForEachBone.resize(currentBones.size());
|
||||
|
||||
|
||||
for (int i = 0; i < currentBones.size(); i++)
|
||||
{
|
||||
currentBones[i].boneStartWorld.v[0] = oneFrameBones[i].boneStartWorld.v[0] + t * (nextFrameBones[i].boneStartWorld.v[0] - oneFrameBones[i].boneStartWorld.v[0]);
|
||||
@ -472,8 +473,10 @@ namespace ZL
|
||||
|
||||
Vector4f q1 = MatrixToQuat(oneFrameBones[i].boneMatrixWorld);
|
||||
Vector4f q2 = MatrixToQuat(nextFrameBones[i].boneMatrixWorld);
|
||||
Vector4f q1_norm = q1.normalized();
|
||||
Vector4f q2_norm = q2.normalized();
|
||||
|
||||
Vector4f result = slerp(q1, q2, t);
|
||||
Vector4f result = slerp(q1_norm, q2_norm, t);
|
||||
|
||||
currentBones[i].boneMatrixWorld = QuatToMatrix(result);
|
||||
|
||||
@ -486,7 +489,20 @@ namespace ZL
|
||||
skinningMatrixForEachBone[i] = MultMatrixMatrix(currentBoneMatrixWorld4, inverstedStartBoneMatrixWorld4);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
for (int i = 0; i < currentBones.size(); i++)
|
||||
{
|
||||
currentBones[i].boneStartWorld = oneFrameBones[i].boneStartWorld;
|
||||
currentBones[i].boneMatrixWorld = oneFrameBones[i].boneMatrixWorld;
|
||||
Matrix4f currentBoneMatrixWorld4 = MakeMatrix4x4(currentBones[i].boneMatrixWorld, currentBones[i].boneStartWorld);
|
||||
Matrix4f startBoneMatrixWorld4 = MakeMatrix4x4(animations[0].keyFrames[0].bones[i].boneMatrixWorld, animations[0].keyFrames[0].bones[i].boneStartWorld);
|
||||
Matrix4f inverstedStartBoneMatrixWorld4 = InverseMatrix(startBoneMatrixWorld4);
|
||||
skinningMatrixForEachBone[i] = MultMatrixMatrix(currentBoneMatrixWorld4, inverstedStartBoneMatrixWorld4);
|
||||
|
||||
}
|
||||
*/
|
||||
for (int i = 0; i < mesh.PositionData.size(); i++)
|
||||
{
|
||||
Vector4f originalPos = {
|
||||
@ -495,17 +511,30 @@ namespace ZL
|
||||
startMesh.PositionData[i].v[2], 1.0};
|
||||
|
||||
Vector4f finalPos = Vector4f{0.f, 0.f, 0.f, 0.f};
|
||||
|
||||
bool vMoved = false;
|
||||
//Vector3f finalPos = Vector3f{ 0.f, 0.f, 0.f };
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
for (int j = 0; j < MAX_BONE_COUNT; j++)
|
||||
{
|
||||
if (verticesBoneWeight[i][j].weight != 0)
|
||||
{
|
||||
vMoved = true;
|
||||
//finalPos = finalPos + MultVectorMatrix(originalPos, skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex]) * verticesBoneWeight[i][j].weight;
|
||||
finalPos = finalPos + MultMatrixVector(skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex], originalPos) * verticesBoneWeight[i][j].weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(finalPos.v[0] - originalPos.v[0]) > 1 || abs(finalPos.v[1] - originalPos.v[1]) > 1 || abs(finalPos.v[2] - originalPos.v[2]) > 1)
|
||||
{
|
||||
std::cout << "Hello!" << std::endl;
|
||||
}
|
||||
|
||||
if (!vMoved)
|
||||
{
|
||||
std::cout << "Hello!" << std::endl;
|
||||
}
|
||||
|
||||
mesh.PositionData[i].v[0] = finalPos.v[0];
|
||||
mesh.PositionData[i].v[1] = finalPos.v[1];
|
||||
mesh.PositionData[i].v[2] = finalPos.v[2];
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
constexpr int MAX_BONE_COUNT = 6;
|
||||
struct Bone
|
||||
{
|
||||
Vector3f boneStartWorld;
|
||||
@ -39,7 +40,9 @@ namespace ZL
|
||||
{
|
||||
VertexDataStruct mesh;
|
||||
VertexDataStruct startMesh;
|
||||
std::vector<std::array<BoneWeight, 3>> verticesBoneWeight;
|
||||
std::vector<std::array<BoneWeight, MAX_BONE_COUNT>> verticesBoneWeight;
|
||||
|
||||
Matrix4f armatureMatrix;
|
||||
|
||||
std::vector<Bone> startBones;
|
||||
std::vector<Bone> currentBones;
|
||||
|
||||
166
Math.cpp
166
Math.cpp
@ -247,68 +247,42 @@ namespace ZL {
|
||||
Vector4f MatrixToQuat(const Matrix3f& m)
|
||||
{
|
||||
Vector4f r;
|
||||
float f;
|
||||
float trace = m.m[0] + m.m[4] + m.m[8];
|
||||
|
||||
|
||||
if (m.m[0] >= m.m[4] && m.m[0] >= m.m[8])
|
||||
if (trace > 0)
|
||||
{
|
||||
f = sqrtf(1.0 + m.m[0] - m.m[4] - m.m[8]);
|
||||
if (f != 0)
|
||||
{
|
||||
r.v[3] = (m.m[5] - m.m[7]) / (f + f);
|
||||
r.v[0] = f / 2;
|
||||
r.v[1] = (m.m[3] + m.m[1]) / (f + f);
|
||||
r.v[2] = (m.m[6] + m.m[2]) / (f + f);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.v[3] = 1;
|
||||
r.v[2] = 0;
|
||||
r.v[1] = 0;
|
||||
r.v[0] = 0;
|
||||
}
|
||||
float s = 0.5f / sqrtf(trace + 1.0f);
|
||||
r.v[3] = 0.25f / s;
|
||||
r.v[0] = (m.m[5] - m.m[7]) * s;
|
||||
r.v[1] = (m.m[6] - m.m[2]) * s;
|
||||
r.v[2] = (m.m[1] - m.m[3]) * s;
|
||||
}
|
||||
else if (m.m[0] > m.m[4] && m.m[0] > m.m[8])
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[0] - m.m[4] - m.m[8]);
|
||||
r.v[3] = (m.m[5] - m.m[7]) / s;
|
||||
r.v[0] = 0.25f * s;
|
||||
r.v[1] = (m.m[1] + m.m[3]) / s;
|
||||
r.v[2] = (m.m[6] + m.m[2]) / s;
|
||||
}
|
||||
else if (m.m[4] > m.m[8])
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[4] - m.m[0] - m.m[8]);
|
||||
r.v[3] = (m.m[6] - m.m[2]) / s;
|
||||
r.v[0] = (m.m[1] + m.m[3]) / s;
|
||||
r.v[1] = 0.25f * s;
|
||||
r.v[2] = (m.m[5] + m.m[7]) / s;
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = 2.0f * sqrtf(1.0f + m.m[8] - m.m[0] - m.m[4]);
|
||||
r.v[3] = (m.m[1] - m.m[3]) / s;
|
||||
r.v[0] = (m.m[6] + m.m[2]) / s;
|
||||
r.v[1] = (m.m[5] + m.m[7]) / s;
|
||||
r.v[2] = 0.25f * s;
|
||||
}
|
||||
|
||||
if (m.m[4] >= m.m[0] && m.m[4] >= m.m[8])
|
||||
{
|
||||
f = sqrtf(1 + m.m[4] - m.m[0] - m.m[8]);
|
||||
if (f != 0)
|
||||
{
|
||||
r.v[3] = (m.m[6] - m.m[2]) / (f + f);
|
||||
r.v[1] = f / 2;
|
||||
r.v[0] = (m.m[1] + m.m[3]) / (f + f);
|
||||
r.v[2] = (m.m[7] + m.m[5]) / (f + f);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.v[3] = 1;
|
||||
r.v[2] = 0;
|
||||
r.v[1] = 0;
|
||||
r.v[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m.m[8] >= m.m[4] && m.m[8] >= m.m[0])
|
||||
{
|
||||
f = sqrtf(1 + m.m[8] - m.m[2]);
|
||||
if (f != 0)
|
||||
{
|
||||
r.v[3] = (m.m[1] - m.m[3]) / (f + f);
|
||||
r.v[2] = f / 2;
|
||||
r.v[1] = (m.m[5] + m.m[7]) / (f + f);
|
||||
r.v[0] = (m.m[6] + m.m[2]) / (f + f);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.v[3] = 1;
|
||||
r.v[2] = 0;
|
||||
r.v[1] = 0;
|
||||
r.v[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
return r.normalized();
|
||||
}
|
||||
|
||||
Vector4f QuatFromRotateAroundX(float angle)
|
||||
@ -681,65 +655,51 @@ namespace ZL {
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, double t)
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, float t)
|
||||
{
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double cosTheta = q1.dot(q2);
|
||||
const float epsilon = 1e-6f;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> cosTheta < 0, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
Vector4f q2Adjusted = q2;
|
||||
if (cosTheta < 0.0) {
|
||||
//q2Adjusted = { -q2.w, -q2.x, -q2.y, -q2.z };
|
||||
q2Adjusted.v[0] = -q2.v[0];
|
||||
q2Adjusted.v[1] = -q2.v[1];
|
||||
q2Adjusted.v[2] = -q2.v[2];
|
||||
q2Adjusted.v[3] = -q2.v[3];
|
||||
// Нормализация входных кватернионов
|
||||
Vector4f q1_norm = q1.normalized();
|
||||
Vector4f q2_norm = q2.normalized();
|
||||
|
||||
float cosTheta = q1_norm.dot(q2_norm);
|
||||
|
||||
// Если q1 и q2 близки к противоположным направлениям, корректируем q2
|
||||
Vector4f q2_adjusted = q2_norm;
|
||||
if (cosTheta < 0.0f) {
|
||||
q2_adjusted.v[0] = -q2_adjusted.v[0];
|
||||
q2_adjusted.v[1] = -q2_adjusted.v[1];
|
||||
q2_adjusted.v[2] = -q2_adjusted.v[2];
|
||||
q2_adjusted.v[3] = -q2_adjusted.v[3];
|
||||
cosTheta = -cosTheta;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
const double epsilon = 1e-6;
|
||||
if (cosTheta > 1.0 - epsilon) {
|
||||
|
||||
// Если кватернионы близки, используем линейную интерполяцию
|
||||
if (cosTheta > 1.0f - epsilon) {
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = q1.v[0] + t * (q2Adjusted.v[0] - q1.v[0]);
|
||||
result.v[1] = q1.v[1] + t * (q2Adjusted.v[1] - q1.v[1]);
|
||||
result.v[2] = q1.v[2] + t * (q2Adjusted.v[2] - q1.v[2]);
|
||||
result.v[3] = q1.v[3] + t * (q2Adjusted.v[3] - q1.v[3]);
|
||||
|
||||
/*Quaternion result = {
|
||||
q1.w + t * (q2Adjusted.w - q1.w),
|
||||
q1.x + t * (q2Adjusted.x - q1.x),
|
||||
q1.y + t * (q2Adjusted.y - q1.y),
|
||||
q1.z + t * (q2Adjusted.z - q1.z)
|
||||
};*/
|
||||
result.v[0] = q1_norm.v[0] + t * (q2_adjusted.v[0] - q1_norm.v[0]);
|
||||
result.v[1] = q1_norm.v[1] + t * (q2_adjusted.v[1] - q1_norm.v[1]);
|
||||
result.v[2] = q1_norm.v[2] + t * (q2_adjusted.v[2] - q1_norm.v[2]);
|
||||
result.v[3] = q1_norm.v[3] + t * (q2_adjusted.v[3] - q1_norm.v[3]);
|
||||
|
||||
return result.normalized();
|
||||
}
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> theta
|
||||
double theta = std::acos(cosTheta);
|
||||
double sinTheta = std::sin(theta);
|
||||
// Иначе используем сферическую интерполяцию
|
||||
float theta = std::acos(cosTheta);
|
||||
float sinTheta = std::sin(theta);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double coeff1 = std::sin((1.0 - t) * theta) / sinTheta;
|
||||
double coeff2 = std::sin(t * theta) / sinTheta;
|
||||
float coeff1 = std::sin((1.0f - t) * theta) / sinTheta;
|
||||
float coeff2 = std::sin(t * theta) / sinTheta;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/*
|
||||
Quaternion result = {
|
||||
coeff1 * q1.w + coeff2 * q2Adjusted.w,
|
||||
coeff1 * q1.x + coeff2 * q2Adjusted.x,
|
||||
coeff1 * q1.y + coeff2 * q2Adjusted.y,
|
||||
coeff1 * q1.z + coeff2 * q2Adjusted.z
|
||||
};*/
|
||||
Vector4f result;
|
||||
|
||||
result.v[0] = coeff1 * q1.v[0] + coeff2 * q2Adjusted.v[0];
|
||||
result.v[1] = coeff1 * q1.v[1] + coeff2 * q2Adjusted.v[1];
|
||||
result.v[2] = coeff1 * q1.v[2] + coeff2 * q2Adjusted.v[2];
|
||||
result.v[3] = coeff1 * q1.v[3] + coeff2 * q2Adjusted.v[3];
|
||||
|
||||
result.v[0] = coeff1 * q1_norm.v[0] + coeff2 * q2_adjusted.v[0];
|
||||
result.v[1] = coeff1 * q1_norm.v[1] + coeff2 * q2_adjusted.v[1];
|
||||
result.v[2] = coeff1 * q1_norm.v[2] + coeff2 * q2_adjusted.v[2];
|
||||
result.v[3] = coeff1 * q1_norm.v[3] + coeff2 * q2_adjusted.v[3];
|
||||
|
||||
return result.normalized();
|
||||
}
|
||||
|
||||
2
Math.h
2
Math.h
@ -100,7 +100,7 @@ namespace ZL {
|
||||
Vector4f MultVectorMatrix(Vector4f v, Matrix4f mt);
|
||||
Vector4f MultMatrixVector(Matrix4f mt, Vector4f v);
|
||||
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, double t);
|
||||
Vector4f slerp(const Vector4f& q1, const Vector4f& q2, float t);
|
||||
Matrix3f InverseMatrix(const Matrix3f& m);
|
||||
Matrix4f InverseMatrix(const Matrix4f& m);
|
||||
Matrix3f MultMatrixMatrix(const Matrix3f& m1, const Matrix3f& m2);
|
||||
|
||||
37
main.cpp
37
main.cpp
@ -144,6 +144,34 @@ namespace ZL
|
||||
|
||||
glViewport(0, 0, Env::width, Env::height);
|
||||
|
||||
renderer.shaderManager.PushShader(colorShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast<float>(Env::width) / static_cast<float>(Env::height), 50, 10000);
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
|
||||
renderer.TranslateMatrix({ 0,0, -100 * Env::zoom });
|
||||
|
||||
float t = 0.3;
|
||||
|
||||
renderer.RotateMatrix(QuatFromRotateAroundX(t * M_PI / 2.0));
|
||||
|
||||
GameObjects::bxMutable.AssignFrom(GameObjects::bx.mesh);
|
||||
GameObjects::bxMutable.RefreshVBO();
|
||||
renderer.DrawVertexRenderStruct(GameObjects::bxMutable);
|
||||
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
|
||||
renderer.shaderManager.PopShader();
|
||||
#if 0
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
|
||||
@ -217,6 +245,7 @@ namespace ZL
|
||||
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
#endif
|
||||
CheckGlError();
|
||||
|
||||
}
|
||||
@ -318,7 +347,8 @@ namespace ZL
|
||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./defaultColor.vertex", "./defaultColor.fragment");
|
||||
std::cout << "Hello test 2x" << std::endl;
|
||||
|
||||
GameObjects::bx.LoadFromFile("mesh_armature_and_animation_data.txt");
|
||||
//GameObjects::bx.LoadFromFile("mesh_armature_and_animation_data.txt");
|
||||
GameObjects::bx.LoadFromFile("via004.txt");
|
||||
|
||||
std::cout << "Hello test 3" << std::endl;
|
||||
|
||||
@ -337,6 +367,7 @@ namespace ZL
|
||||
GameObjects::testObjMeshMutable.data = GameObjects::testObjMesh;
|
||||
GameObjects::testObjMeshMutable.RefreshVBO();
|
||||
|
||||
/*
|
||||
GameObjects::textMesh = LoadFromTextFile("./mesh001.txt");
|
||||
|
||||
GameObjects::coneMesh = LoadFromTextFile("./cone001.txt");
|
||||
@ -347,7 +378,7 @@ namespace ZL
|
||||
GameObjects::textMeshMutable.RefreshVBO();
|
||||
GameObjects::coneMeshMutable.AssignFrom(GameObjects::coneMesh);
|
||||
GameObjects::coneMeshMutable.RefreshVBO();
|
||||
|
||||
*/
|
||||
|
||||
ActiveObject ao1;
|
||||
|
||||
@ -425,7 +456,7 @@ namespace ZL
|
||||
static int x = 0;
|
||||
|
||||
GameObjects::bx.Interpolate(x);
|
||||
x = x + 2;
|
||||
x = x + 3;
|
||||
}
|
||||
if (event.type == SDL_MOUSEWHEEL) {
|
||||
|
||||
|
||||
17393
via004.txt
Normal file
17393
via004.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user