91 lines
4.2 KiB
C++
91 lines
4.2 KiB
C++
// Real packed bear assets: the auxiliary Hedra group precedes the moving Bip01 group.
|
|
#include "granny.h"
|
|
#include "../../src/platform/PackBackend.h"
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
int failures = 0;
|
|
void check(bool ok, const char* message) {
|
|
if (!ok) { std::fprintf(stderr, "FAIL %s\n", message); ++failures; }
|
|
}
|
|
granny_file* load(const std::string& path) {
|
|
std::vector<uint8_t> bytes;
|
|
if (!mtpack40250::read(path, bytes)) return nullptr;
|
|
return GrannyReadEntireFileFromMemory(bytes.size(), bytes.data());
|
|
}
|
|
void test_motion(granny_model* model, const char* name) {
|
|
const std::string base = "d:/ymir work/monster/bear/";
|
|
granny_file* file = load(base + name + ".gr2");
|
|
check(file != nullptr, "bear animation loads from the live pack path");
|
|
if (!file) return;
|
|
auto* info = GrannyGetFileInfo(file);
|
|
check(info && info->AnimationCount == 1, "one animation");
|
|
if (!info || info->AnimationCount != 1) { GrannyFreeFile(file); return; }
|
|
auto* animation = info->Animations[0];
|
|
check(animation->TrackGroupCount == 2, "both track groups exposed safely");
|
|
const bool auxiliaryFirst = animation->TrackGroupCount > 0 &&
|
|
!std::strcmp(animation->TrackGroups[0]->Name, "Hedra");
|
|
check(auxiliaryFirst, "auxiliary group first");
|
|
if (animation->TrackGroupCount == 2 && auxiliaryFirst) {
|
|
check(!std::strcmp(animation->TrackGroups[1]->Name, "Bip01"), "model group second");
|
|
}
|
|
std::vector<uint8_t> msa;
|
|
check(mtpack40250::read(base + name + ".msa", msa), "motion specification loads");
|
|
float accumulation[3] = {};
|
|
std::istringstream lines(std::string(msa.begin(), msa.end()));
|
|
for (std::string line; std::getline(lines, line);)
|
|
if (line.rfind("Accumulation", 0) == 0)
|
|
std::sscanf(line.c_str(), "Accumulation %f %f %f", accumulation, accumulation + 1, accumulation + 2);
|
|
check(accumulation[1] < 0, "moving resource has forward accumulation");
|
|
for (bool inverse : {false, true}) {
|
|
auto* instance = GrannyInstantiateModel(model);
|
|
auto* control = GrannyPlayControlledAnimation(0, animation, instance);
|
|
check(control != nullptr, "animation binds to named model");
|
|
if (control) {
|
|
GrannySetControlLoopCount(control, 0);
|
|
const float dt = 0.1f;
|
|
const float clock = animation->Duration + dt; // across the loop boundary
|
|
GrannySetModelClock(instance, clock);
|
|
float matrix[16] = {0,1,0,0, -1,0,0,0, 0,0,1,0, 100,200,0,1};
|
|
GrannyUpdateModelMatrix(instance, dt, matrix, matrix, inverse);
|
|
const float expectedX = 100 - (inverse ? -1.0f : 1.0f) * accumulation[1] * dt / animation->Duration;
|
|
check(std::abs(matrix[12] - expectedX) < 0.02f && std::abs(matrix[13] - 200) < 0.02f,
|
|
"model group root displacement, loop, rotation and inverse");
|
|
}
|
|
GrannyFreeModelInstance(instance);
|
|
}
|
|
// Hedra has no root displacement even though the other group moves.
|
|
granny_model decoration = *model;
|
|
decoration.Name = "Hedra";
|
|
auto* instance = GrannyInstantiateModel(&decoration);
|
|
auto* control = GrannyPlayControlledAnimation(0, animation, instance);
|
|
check(control != nullptr, "auxiliary object binds to its own group");
|
|
GrannySetModelClock(instance, 0.1f);
|
|
float matrix[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
|
|
GrannyUpdateModelMatrix(instance, 0.1f, matrix, matrix, false);
|
|
check(matrix[12] == 0 && matrix[13] == 0, "auxiliary group does not inherit bear movement");
|
|
GrannyFreeModelInstance(instance);
|
|
GrannyFreeFile(file);
|
|
}
|
|
}
|
|
int main(int argc, char** argv) {
|
|
if (argc < 2 || !mtpack40250::initialize(argv[1])) return std::getenv("MT_ASSETS_STRICT") ? 1 : 77;
|
|
auto* file = load("d:/ymir work/monster/bear/bear.gr2");
|
|
check(file != nullptr, "bear model loads");
|
|
if (!file) return 1;
|
|
auto* info = GrannyGetFileInfo(file);
|
|
check(info && info->ModelCount == 1, "one bear model");
|
|
if (info && info->ModelCount == 1) {
|
|
test_motion(info->Models[0], "02");
|
|
test_motion(info->Models[0], "03");
|
|
}
|
|
GrannyFreeFile(file);
|
|
return failures ? 1 : 0;
|
|
}
|