Bibliothèque sequa::3d (espace de noms sequa::three_d), sans dépendance à un moteur : interface I3DEngineAdapter, tampons et négociation des capacités, synchronisation de la scène par deltas versionnés tout ou rien (SceneState, snapshot), demandes d'image et mesures communes. NullEngineAdapter (SIMULÉ) pour les tests. Types provisoires en attendant le format du schéma.
75 lines
2.4 KiB
C++
75 lines
2.4 KiB
C++
// SPDX-License-Identifier: MPL-2.0
|
|
#include "sequa/3d/scene.hpp"
|
|
|
|
#include <doctest/doctest.h>
|
|
|
|
using namespace sequa::three_d;
|
|
|
|
namespace {
|
|
|
|
Transform at(float x)
|
|
{
|
|
Transform t;
|
|
t.position = {x, 0, 0};
|
|
return t;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_CASE("SceneState : creation, deplacement, destruction")
|
|
{
|
|
SceneState scene;
|
|
REQUIRE_FALSE(scene.apply({1, {CreateObject{1, at(0), {}}, CreateObject{2, at(5), {}}}}));
|
|
REQUIRE_FALSE(scene.apply({2, {SetTransform{1, at(3)}, DestroyObject{2}}}));
|
|
|
|
CHECK(scene.world_version() == 2);
|
|
REQUIRE(scene.objects().size() == 1);
|
|
CHECK(scene.objects().at(1).transform == at(3));
|
|
}
|
|
|
|
TEST_CASE("SceneState : version non croissante refusee")
|
|
{
|
|
SceneState scene;
|
|
REQUIRE_FALSE(scene.apply({5, {}}));
|
|
const auto error = scene.apply({5, {}});
|
|
REQUIRE(error.has_value());
|
|
CHECK(error->code == Error::Code::invalid_argument);
|
|
CHECK(scene.apply({4, {}}).has_value());
|
|
}
|
|
|
|
TEST_CASE("SceneState : un delta invalide ne modifie rien (tout ou rien)")
|
|
{
|
|
SceneState scene;
|
|
REQUIRE_FALSE(scene.apply({1, {CreateObject{1, at(0), {}}}}));
|
|
|
|
// Le déplacement de 1 est valide, mais 99 est inconnu : rien ne doit être appliqué.
|
|
CHECK(scene.apply({2, {SetTransform{1, at(7)}, SetTransform{99, at(1)}}}).has_value());
|
|
CHECK(scene.world_version() == 1);
|
|
CHECK(scene.objects().at(1).transform == at(0));
|
|
|
|
CHECK(scene.apply({2, {CreateObject{1, at(0), {}}}}).has_value()); // doublon
|
|
CHECK(scene.apply({2, {CreateObject{invalid_object, at(0), {}}}}).has_value());
|
|
CHECK(scene.world_version() == 1);
|
|
}
|
|
|
|
TEST_CASE("SceneState : le snapshot reconstruit une scene identique")
|
|
{
|
|
SceneState scene;
|
|
Visual sphere;
|
|
sphere.primitive = Primitive::sphere;
|
|
sphere.semantic_class = 3;
|
|
REQUIRE_FALSE(scene.apply({1, {CreateObject{7, at(1), {}}, CreateObject{3, at(2), sphere}}}));
|
|
REQUIRE_FALSE(scene.apply({4, {SetCamera{Camera{at(-10), 60, 0.1f, 500}}}}));
|
|
|
|
const SceneDelta snapshot = scene.snapshot();
|
|
CHECK(snapshot.world_version == 4);
|
|
REQUIRE(snapshot.commands.size() == 3);
|
|
CHECK(std::get<CreateObject>(snapshot.commands[0]).id == 3); // ordre par id croissant
|
|
CHECK(std::holds_alternative<SetCamera>(snapshot.commands[2]));
|
|
|
|
SceneState copy;
|
|
REQUIRE_FALSE(copy.apply(snapshot));
|
|
CHECK(copy.objects() == scene.objects());
|
|
CHECK(copy.camera() == scene.camera());
|
|
}
|