-
Notifications
You must be signed in to change notification settings - Fork 9
/
bone.cpp
104 lines (91 loc) · 3.25 KB
/
bone.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
MabiMe Character Simulator - by Yai (Sophie N)
Email: sinoc300@gmail.com
Copyright (C) 2016
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bone.h"
#include <QMatrix4x4>
#include <QMatrix3x3>
Bone::Bone(QList<FRM::Bone*> *boneData, int boneIndex, Bone* parent)
{
FRM::Bone *bone = boneData->at(boneIndex);
id = bone->boneID;
name = bone->name;
parentBone = parent;
// extract the bone data from the FRM raw and convert it into easy to use values
QMatrix4x4 matrix(bone->link);
worldMatrix = matrix.transposed();
bool inv = true;
bindMatrix = worldMatrix.inverted(&inv);
translation = matrix.transposed().column(3).toVector3D();
scale = QVector3D(matrix.transposed().row(0).toVector3D().length(),
matrix.transposed().row(1).toVector3D().length(),
matrix.transposed().row(2).toVector3D().length());
rotation = QQuaternion::fromRotationMatrix(matrix.transposed().toGenericMatrix<3,3>());
// search and add children recursively to build a bone tree
for (int i = 0; i < boneData->count(); i++) {
FRM::Bone *b = boneData->at(i);
if (b->parentID == id) {
Bone *childBone = new Bone(boneData, i, this);
children.append(childBone);
}
}
}
const QString Bone::getName() {
return name;
}
void Bone::updateBone() {
// create a matrix from the stored translation, rotation and scale
QMatrix4x4 matrix;
matrix.translate(translation);
matrix.rotate(rotation);
matrix.scale(scale);
// generate new matrix. if a child multiply it from the parent matrix first
worldMatrix = matrix;
// if (boneParent != nullptr) worldMatrix = boneParent->worldMatrix * matrix;
// else worldMatrix = matrix;
for (int i = 0; i < children.count(); i++) {
children[i]->updateBone();
}
}
const QMatrix4x4 Bone::getMatrix() {
if (parentBone != nullptr) return parentBone->getMatrix() * worldMatrix;
return worldMatrix;
}
const QMatrix4x4 Bone::getLocalMatrix() {
if (parentBone != nullptr) return parentBone->getLocalMatrix() * (bindMatrix * worldMatrix);
// qDebug() << (bindMatrix * worldMatrix);
return (bindMatrix * worldMatrix);
}
Bone* Bone::findBone(QString boneName) {
if (boneName == name) return this;
for (int i = 0; i < children.count(); i++) {
Bone *b = children[i]->findBone(boneName);
if (b != nullptr) return b;
}
return nullptr;
}
void Bone::setX(GLfloat x) {
translation.setX(x);
updateBone();
}
void Bone::setY(GLfloat y) {
translation.setY(y);
updateBone();
}
Bone* Bone::getParent() {
return parentBone;
}
QList<Bone*> Bone::getChildren() {
return children;
}