Bring over test sources (not compiled yet!)

This commit is contained in:
Lars Mueller 2024-05-15 02:57:44 +02:00
parent 72cecd1b6a
commit cbc6b2b394
5 changed files with 272 additions and 0 deletions

@ -0,0 +1,54 @@
{
"scene" : 0,
"scenes" : [
{
"nodes" : [ 0 ]
}
],
"nodes" : [
{
"mesh" : 0
}
],
"meshes" : [
{
"primitives" : [ {
"attributes" : {
"POSITION" : 0
}
} ]
}
],
"buffers" : [
{
"uri" : "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA",
"byteLength" : 36
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteOffset" : 1,
"byteLength" : 36,
"target" : 34962
}
],
"accessors" : [
{
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 3,
"type" : "VEC3",
"max" : [ 1.0, 1.0, 0.0 ],
"min" : [ 0.0, 0.0, 0.0 ]
}
],
"asset" : {
"version" : "2.0"
}
}

@ -0,0 +1 @@
{

@ -0,0 +1,131 @@
{
"scene" : 0,
"scenes" : [ {
"nodes" : [ 0, 1 ]
} ],
"nodes" : [ {
"skin" : 0,
"mesh" : 0
}, {
"children" : [ 2 ]
}, {
"translation" : [ 0.0, 1.0, 0.0 ],
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ]
} ],
"meshes" : [ {
"primitives" : [ {
"attributes" : {
"POSITION" : 1,
"JOINTS_0" : 2,
"WEIGHTS_0" : 3
},
"indices" : 0
} ]
} ],
"skins" : [ {
"inverseBindMatrices" : 4,
"joints" : [ 1, 2 ]
} ],
"animations" : [ {
"channels" : [ {
"sampler" : 0,
"target" : {
"node" : 2,
"path" : "rotation"
}
} ],
"samplers" : [ {
"input" : 5,
"interpolation" : "LINEAR",
"output" : 6
} ]
} ],
"buffers" : [ {
"uri" : "data:application/gltf-buffer;base64,AAABAAMAAAADAAIAAgADAAUAAgAFAAQABAAFAAcABAAHAAYABgAHAAkABgAJAAgAAAAAvwAAAAAAAAAAAAAAPwAAAAAAAAAAAAAAvwAAAD8AAAAAAAAAPwAAAD8AAAAAAAAAvwAAgD8AAAAAAAAAPwAAgD8AAAAAAAAAvwAAwD8AAAAAAAAAPwAAwD8AAAAAAAAAvwAAAEAAAAAAAAAAPwAAAEAAAAAA",
"byteLength" : 168
}, {
"uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAgD4AAEA/AAAAAAAAAAAAAIA+AABAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAA=",
"byteLength" : 320
}, {
"uri" : "data:application/gltf-buffer;base64,AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8=",
"byteLength" : 128
}, {
"uri" : "data:application/gltf-buffer;base64,AAAAAAAAAD8AAIA/AADAPwAAAEAAACBAAABAQAAAYEAAAIBAAACQQAAAoEAAALBAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAPT9ND/0/TQ/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAPT9NL/0/TQ/AAAAAAAAAAD0/TS/9P00PwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAAAAAAAAAIA/",
"byteLength" : 240
} ],
"bufferViews" : [ {
"buffer" : 0,
"byteLength" : 48,
"target" : 34963
}, {
"buffer" : 0,
"byteOffset" : 48,
"byteLength" : 120,
"target" : 34962
}, {
"buffer" : 1,
"byteLength" : 320,
"byteStride" : 16
}, {
"buffer" : 2,
"byteLength" : 128
}, {
"buffer" : 3,
"byteLength" : 240
} ],
"accessors" : [ {
"bufferView" : 0,
"componentType" : 5123,
"count" : 24,
"type" : "SCALAR"
}, {
"bufferView" : 1,
"componentType" : 5126,
"count" : 10,
"type" : "VEC3",
"max" : [ 0.5, 2.0, 0.0 ],
"min" : [ -0.5, 0.0, 0.0 ]
}, {
"bufferView" : 2,
"componentType" : 5123,
"count" : 10,
"type" : "VEC4"
}, {
"bufferView" : 2,
"byteOffset" : 160,
"componentType" : 5126,
"count" : 10,
"type" : "VEC4"
}, {
"bufferView" : 3,
"componentType" : 5126,
"count" : 2,
"type" : "MAT4"
}, {
"bufferView" : 4,
"componentType" : 5126,
"count" : 12,
"type" : "SCALAR",
"max" : [ 5.5 ],
"min" : [ 0.0 ]
}, {
"bufferView" : 4,
"byteOffset" : 48,
"componentType" : 5126,
"count" : 12,
"type" : "VEC4",
"max" : [ 0.0, 0.0, 0.707, 1.0 ],
"min" : [ 0.0, 0.0, -0.707, 0.707 ]
} ],
"asset" : {
"version" : "2.0"
}
}

@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "CSceneManager.h"
#include "CSkinnedMesh.h"
#include "content/subgames.h"
#include "filesys.h"
@ -365,4 +366,89 @@ SECTION("simple sparse accessor")
CHECK(vertices[i].Pos == expectedPositions[i]);
}
// https://github.com/KhronosGroup/glTF-Sample-Models/tree/main/2.0/SimpleSkin
SECTION("simple skin")
{
using CSkinnedMesh = irr::scene::CSkinnedMesh;
const auto mesh = loadMesh(model_path + "simple_skin.gltf");
REQUIRE(mesh != nullptr);
auto csm = dynamic_cast<const CSkinnedMesh*>(mesh);
const auto joints = csm->getAllJoints();
REQUIRE(joints.size() == 3);
const auto findJoint = [&](const std::function<bool(CSkinnedMesh::SJoint*)> &predicate) {
for (std::size_t i = 0; i < joints.size(); ++i) {
if (predicate(joints[i])) {
return joints[i];
}
}
throw std::runtime_error("joint not found");
};
// Check the node hierarchy
const auto parent = findJoint([](auto joint) {
return !joint->Children.empty();
});
REQUIRE(parent->Children.size() == 1);
const auto child = parent->Children[0];
REQUIRE(child != parent);
SECTION("transformations are correct")
{
CHECK(parent->Animatedposition == v3f(0, 0, 0));
CHECK(parent->Animatedrotation == irr::core::quaternion());
CHECK(parent->Animatedscale == v3f(1, 1, 1));
CHECK(parent->GlobalInversedMatrix == irr::core::matrix4());
const v3f childTranslation(0, 1, 0);
CHECK(child->Animatedposition == childTranslation);
CHECK(child->Animatedrotation == irr::core::quaternion());
CHECK(child->Animatedscale == v3f(1, 1, 1));
irr::core::matrix4 inverseBindMatrix;
inverseBindMatrix.setInverseTranslation(childTranslation);
CHECK(child->GlobalInversedMatrix == inverseBindMatrix);
}
SECTION("weights are correct")
{
const auto weights = [&](const CSkinnedMesh::SJoint* joint) {
std::unordered_map<irr::u32, irr::f32> weights;
for (std::size_t i = 0; i < joint->Weights.size(); ++i) {
const auto weight = joint->Weights[i];
REQUIRE(weight.buffer_id == 0);
weights[weight.vertex_id] = weight.strength;
}
return weights;
};
const auto parentWeights = weights(parent);
const auto childWeights = weights(child);
const auto checkWeights = [&](irr::u32 index, irr::f32 parentWeight, irr::f32 childWeight) {
const auto getWeight = [](auto weights, auto index) {
const auto it = weights.find(index);
return it == weights.end() ? 0.0f : it->second;
};
CHECK(getWeight(parentWeights, index) == parentWeight);
CHECK(getWeight(childWeights, index) == childWeight);
};
checkWeights(0, 1.00, 0.00);
checkWeights(1, 1.00, 0.00);
checkWeights(2, 0.75, 0.25);
checkWeights(3, 0.75, 0.25);
checkWeights(4, 0.50, 0.50);
checkWeights(5, 0.50, 0.50);
checkWeights(6, 0.25, 0.75);
checkWeights(7, 0.25, 0.75);
checkWeights(8, 0.00, 1.00);
checkWeights(9, 0.00, 1.00);
}
SECTION("there should be a third node not involved in skinning")
{
const auto other = findJoint([&](auto joint) {
return joint != child && joint != parent;
});
CHECK(other->Weights.empty());
}
}
}