Animation unit tests now compile.

not all of them pass tho...
This commit is contained in:
Anthony J. Thibault 2018-02-09 11:00:57 -08:00
parent 354fae5063
commit f291ddae97
3 changed files with 91 additions and 81 deletions

View file

@ -93,6 +93,9 @@ void makeTestFBXJoints(FBXGeometry& geometry) {
}
void AnimInverseKinematicsTests::testSingleChain() {
AnimContext context(false, false, false, glm::mat4(), glm::mat4());
FBXGeometry geometry;
makeTestFBXJoints(geometry);
@ -108,14 +111,14 @@ void AnimInverseKinematicsTests::testSingleChain() {
//
// A------>B------>C------>D
AnimPose pose;
pose.scale = glm::vec3(1.0f);
pose.rot = identity;
pose.trans = origin;
pose.scale() = glm::vec3(1.0f);
pose.rot() = identity;
pose.trans() = origin;
AnimPoseVec poses;
poses.push_back(pose);
pose.trans = xAxis;
pose.trans() = xAxis;
for (int i = 1; i < (int)geometry.joints.size(); ++i) {
poses.push_back(pose);
}
@ -133,8 +136,13 @@ void AnimInverseKinematicsTests::testSingleChain() {
AnimVariantMap varMap;
varMap.set("positionD", targetPosition);
varMap.set("rotationD", targetRotation);
varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition);
ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType"));
varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition);
varMap.set("poleVectorEnabledD", false);
std::vector<float> flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f};
ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"),
QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"),
QString("poleReferenceVectorD"), QString("poleVectorD"));
AnimNode::Triggers triggers;
// the IK solution should be:
@ -147,14 +155,14 @@ void AnimInverseKinematicsTests::testSingleChain() {
// iterate several times
float dt = 1.0f;
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses);
// verify absolute results
// NOTE: since we expect this solution to converge very quickly (one loop)
@ -165,27 +173,27 @@ void AnimInverseKinematicsTests::testSingleChain() {
}
ikDoll.computeAbsolutePoses(absolutePoses);
const float acceptableAngleError = 0.001f;
QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[2].rot, quaterTurnAroundZ, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[3].rot, quaterTurnAroundZ, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError);
QCOMPARE_QUATS(absolutePoses[3].rot(), quaterTurnAroundZ, acceptableAngleError);
const float acceptableTranslationError = 0.025f;
QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, targetPosition, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), targetPosition, acceptableTranslationError);
// verify relative results
QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[2].rot, quaterTurnAroundZ, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[2].rot(), quaterTurnAroundZ, acceptableAngleError);
QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngleError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableTranslationError);
QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableTranslationError);
}
{ // hard test IK of joint C
// load intial poses that look like this:
@ -196,15 +204,15 @@ void AnimInverseKinematicsTests::testSingleChain() {
// A------>B
//
AnimPose pose;
pose.scale = glm::vec3(1.0f);
pose.rot = identity;
pose.trans = origin;
pose.scale() = glm::vec3(1.0f);
pose.rot() = identity;
pose.trans() = origin;
AnimPoseVec poses;
poses.push_back(pose);
pose.trans = xAxis;
pose.trans() = xAxis;
pose.rot = quaterTurnAroundZ;
pose.rot() = quaterTurnAroundZ;
poses.push_back(pose);
poses.push_back(pose);
poses.push_back(pose);
@ -222,8 +230,12 @@ void AnimInverseKinematicsTests::testSingleChain() {
AnimVariantMap varMap;
varMap.set("positionD", targetPosition);
varMap.set("rotationD", targetRotation);
varMap.set("targetType", (int)IKTarget::Type::RotationAndPosition);
ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetType"));
varMap.set("targetTypeD", (int)IKTarget::Type::RotationAndPosition);
varMap.set("poleVectorEnabledD", false);
std::vector<float> flexCoefficients = {1.0f, 1.0f, 1.0f, 1.0f};
ikDoll.setTargetVars(QString("D"), QString("positionD"), QString("rotationD"), QString("targetTypeD"),
QString("weightD"), 1.0f, flexCoefficients, QString("poleVectorEnabledD"),
QString("poleReferenceVectorD"), QString("poleVectorD"));
AnimNode::Triggers triggers;
// the IK solution should be:
@ -233,15 +245,15 @@ void AnimInverseKinematicsTests::testSingleChain() {
// iterate several times
float dt = 1.0f;
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, dt, triggers, poses);
const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
ikDoll.overlay(varMap, context, dt, triggers, poses);
const AnimPoseVec& relativePoses = ikDoll.overlay(varMap, context, dt, triggers, poses);
// verify absolute results
// NOTE: the IK algorithm doesn't converge very fast for full-reach targets,
@ -256,27 +268,27 @@ void AnimInverseKinematicsTests::testSingleChain() {
}
ikDoll.computeAbsolutePoses(absolutePoses);
float acceptableAngle = 0.01f; // radians
QCOMPARE_QUATS(absolutePoses[0].rot, identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[1].rot, identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[2].rot, identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[3].rot, identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[0].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[1].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[2].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(absolutePoses[3].rot(), identity, acceptableAngle);
float acceptableDistance = 0.03f;
QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans, origin, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans, xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans, 2.0f * xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans, 3.0f * xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[0].trans(), origin, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[1].trans(), xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[2].trans(), 2.0f * xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(absolutePoses[3].trans(), 3.0f * xAxis, acceptableDistance);
// verify relative results
QCOMPARE_QUATS(relativePoses[0].rot, identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[1].rot, identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[2].rot, identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[3].rot, identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[0].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[1].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[2].rot(), identity, acceptableAngle);
QCOMPARE_QUATS(relativePoses[3].rot(), identity, acceptableAngle);
QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans, origin, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans, xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans, xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans, xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[0].trans(), origin, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[1].trans(), xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[2].trans(), xAxis, acceptableDistance);
QCOMPARE_WITH_ABS_ERROR(relativePoses[3].trans(), xAxis, acceptableDistance);
}
}
@ -293,6 +305,6 @@ void AnimInverseKinematicsTests::testBar() {
AnimPose poseC = poseA * poseB;
glm::vec3 expectedTransC = transA + transB;
QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans, EPSILON);
QCOMPARE_WITH_ABS_ERROR(expectedTransC, poseC.trans(), EPSILON);
}

View file

@ -59,6 +59,7 @@ static float framesToSec(float secs) {
}
void AnimTests::testClipEvaulate() {
AnimContext context(false, false, false, glm::mat4(), glm::mat4());
QString id = "myClipNode";
QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx";
float startFrame = 2.0f;
@ -73,12 +74,12 @@ void AnimTests::testClipEvaulate() {
AnimClip clip(id, url, startFrame, endFrame, timeScale, loopFlag, mirrorFlag);
AnimNode::Triggers triggers;
clip.evaluate(vars, framesToSec(10.0f), triggers);
clip.evaluate(vars, context, framesToSec(10.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 12.0f, EPSILON);
// does it loop?
triggers.clear();
clip.evaluate(vars, framesToSec(12.0f), triggers);
clip.evaluate(vars, context, framesToSec(12.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 3.0f, EPSILON); // Note: frame 3 and not 4, because extra frame between start and end.
// did we receive a loop trigger?
@ -87,7 +88,7 @@ void AnimTests::testClipEvaulate() {
// does it pause at end?
triggers.clear();
clip.setLoopFlagVar("FalseVar");
clip.evaluate(vars, framesToSec(20.0f), triggers);
clip.evaluate(vars, context, framesToSec(20.0f), triggers);
QCOMPARE_WITH_ABS_ERROR(clip._frame, 22.0f, EPSILON);
// did we receive a done trigger?
@ -95,6 +96,7 @@ void AnimTests::testClipEvaulate() {
}
void AnimTests::testClipEvaulateWithVars() {
AnimContext context(false, false, false, glm::mat4(), glm::mat4());
QString id = "myClipNode";
QString url = "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx";
float startFrame = 2.0f;
@ -121,7 +123,7 @@ void AnimTests::testClipEvaulateWithVars() {
clip.setLoopFlagVar("loopFlag2");
AnimNode::Triggers triggers;
clip.evaluate(vars, framesToSec(0.1f), triggers);
clip.evaluate(vars, context, framesToSec(0.1f), triggers);
// verify that the values from the AnimVariantMap made it into the clipNode's
// internal state

View file

@ -49,21 +49,21 @@
static void reportJoint(const Rig& rig, int index) { // Handy for debugging
std::cout << "\n";
std::cout << index << " " << rig->getAnimSkeleton()->getJointName(index).toUtf8().data() << "\n";
std::cout << index << " " << rig.getAnimSkeleton()->getJointName(index).toUtf8().data() << "\n";
glm::vec3 pos;
rig->getJointPosition(index, pos);
rig.getJointPosition(index, pos);
glm::quat rot;
rig->getJointRotation(index, rot);
rig.getJointRotation(index, rot);
std::cout << " pos:" << pos << "\n";
std::cout << " rot:" << safeEulerAngles(rot) << "\n";
std::cout << "\n";
}
static void reportByName(const Rig& rig, const QString& name) {
int jointIndex = rig->indexOfJoint(name);
int jointIndex = rig.indexOfJoint(name);
reportJoint(rig, jointIndex);
}
static void reportAll(const Rig& rig) {
for (int i = 0; i < rig->getJointStateCount(); i++) {
for (int i = 0; i < rig.getJointStateCount(); i++) {
reportJoint(rig, i);
}
}
@ -77,18 +77,14 @@ static void reportSome(const Rig& rig) {
QTEST_MAIN(RigTests)
void RigTests::initTestCase() {
//#define FROM_FILE "/Users/howardstearns/howardHiFi/Zack.fbx"
#ifdef FROM_FILE
QFile file(FROM_FILE);
// TODO: include this fbx in the test case assets, we are not testing networking here.
QString fileName("/Users/howardstearns/howardHiFi/Zack.fbx");
QFile file(fileName);
QCOMPARE(file.open(QIODevice::ReadOnly), true);
FBXGeometry* geometry = readFBX(file.readAll(), QVariantHash());
#else
QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx");
QNetworkReply* reply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request
auto fbxHttpCode = !reply->isFinished() ? -1 : reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QCOMPARE(fbxHttpCode, 200);
FBXGeometry* geometry = readFBX(reply->readAll(), QVariantHash());
#endif
QVERIFY((bool)geometry);
_rig.initJointStates(*geometry, glm::mat4());