101 lines
3.8 KiB
C++
101 lines
3.8 KiB
C++
#include <cstring>
|
|
#include <filesystem>
|
|
#include <string>
|
|
#include <vector>
|
|
#include "Fixtures.h"
|
|
#include "avatar/AvatarInstance.h"
|
|
#include "avatar/VrmDocument.h"
|
|
#include "common/ECS.h"
|
|
#include "filesystem/FileData.h"
|
|
#include "filesystem/Filesystem.h"
|
|
#include "graphics/Mesh.h"
|
|
#include "graphics/RenderSystem3D.h"
|
|
#include "model3d/Model3D.h"
|
|
#include "model3d/ModelData.h"
|
|
#include "zeroerr/assert.h"
|
|
#include "zeroerr/unittest.h"
|
|
|
|
namespace {
|
|
std::vector<std::byte> vrmGlb(std::string json) {
|
|
while (json.size() % 4) json += ' ';
|
|
std::vector<std::byte> bytes(20 + json.size());
|
|
const uint32_t header[] = {0x46546c67, 2, static_cast<uint32_t>(bytes.size()), static_cast<uint32_t>(json.size()),
|
|
0x4e4f534a};
|
|
std::memcpy(bytes.data(), header, 20);
|
|
std::memcpy(bytes.data() + 20, json.data(), json.size());
|
|
return bytes;
|
|
}
|
|
const char* minimalVrm = R"({"asset":{"version":"2.0"},"nodes":[{"name":"head"}],
|
|
"extensions":{"VRMC_vrm":{"specVersion":"1.0","humanoid":{"humanBones":{"head":{"node":0}}}}}})";
|
|
} // namespace
|
|
|
|
TEST_CASE("avatar.vrm.parseVersionAndHumanoid") {
|
|
auto bytes = vrmGlb(minimalVrm);
|
|
auto result = eve::avatar::parseVrm(bytes);
|
|
REQUIRE(result.ok());
|
|
REQUIRE_EQ(result.value().version, std::string("1.0"));
|
|
REQUIRE_EQ(result.value().humanoid.at("head"), 0);
|
|
}
|
|
|
|
TEST_CASE("avatar.vrm.rejectTruncatedAndUnknownVersion") {
|
|
auto bytes = vrmGlb(minimalVrm);
|
|
bytes.pop_back();
|
|
auto truncated = eve::avatar::parseVrm(bytes);
|
|
REQUIRE(!truncated.ok());
|
|
std::string future = minimalVrm;
|
|
future.replace(future.find("specVersion\":\"1.0") + 14, 3, "9.0");
|
|
auto unknown = eve::avatar::parseVrm(vrmGlb(future));
|
|
REQUIRE(!unknown.ok());
|
|
}
|
|
|
|
TEST_CASE("avatar.vrm.rejectInvalidNodeReference") {
|
|
std::string invalid = minimalVrm;
|
|
invalid.replace(invalid.find("\"node\":0"), 8, "\"node\":7");
|
|
auto result = eve::avatar::parseVrm(vrmGlb(invalid));
|
|
REQUIRE(!result.ok());
|
|
}
|
|
|
|
TEST_CASE("avatar.vrm.failedLoadPreservesPath") {
|
|
eve::avatar::AvatarInstance avatar("vroid");
|
|
auto result = avatar.loadVroidModel("does-not-exist.vrm");
|
|
REQUIRE(!result.ok());
|
|
REQUIRE(avatar.getVroidModelPath().empty());
|
|
REQUIRE_EQ(avatar.getVroidMeshCount(), 0);
|
|
}
|
|
|
|
TEST_CASE("avatar.vrm.providerAbsentDoesNotPublish") {
|
|
auto* fs = eve::filesystem::Filesystem::create();
|
|
REQUIRE(fs->setIdentity("ev_ut_vrm_absent", true));
|
|
REQUIRE(fs->setupWriteDirectory());
|
|
const auto directory = (std::filesystem::path(__FILE__).parent_path() / "assets/vrm").string();
|
|
fs->allowMountingForPath(directory);
|
|
REQUIRE(fs->mount(directory, "", false));
|
|
eve::avatar::AvatarInstance avatar("vroid");
|
|
auto result = avatar.loadVroidModel("contract.vrm");
|
|
REQUIRE(!result.ok());
|
|
REQUIRE_EQ(avatar.getVroidMeshCount(), 0);
|
|
REQUIRE(avatar.getVroidModelPath().empty());
|
|
REQUIRE(fs->unmount(directory));
|
|
}
|
|
|
|
TEST_CASE("avatar.vrm.graphicsBackendSupportIsExplicit") {
|
|
GfxFixture graphics(320, 240);
|
|
auto* fs = eve::filesystem::Filesystem::create();
|
|
REQUIRE(fs->setIdentity("ev_ut_vrm_backend", true));
|
|
REQUIRE(fs->setupWriteDirectory());
|
|
const auto directory = (std::filesystem::path(__FILE__).parent_path() / "assets/vrm").string();
|
|
fs->allowMountingForPath(directory);
|
|
REQUIRE(fs->mount(directory, "", false));
|
|
eve::avatar::AvatarInstance avatar("vroid");
|
|
auto result = avatar.loadVroidModel("contract.vrm");
|
|
if (graphics.gfx->getBackendName() == "vulkan") {
|
|
REQUIRE(result.ok());
|
|
REQUIRE_EQ(avatar.getVroidMeshCount(), 2);
|
|
} else {
|
|
REQUIRE(!result.ok());
|
|
REQUIRE_EQ(avatar.getVroidMeshCount(), 0);
|
|
REQUIRE(avatar.getVroidModelPath().empty());
|
|
}
|
|
REQUIRE(fs->unmount(directory));
|
|
}
|