forked from 0ad/0ad
Adds test for loading actor and model having proper flags.
Differential Revision: https://code.wildfiregames.com/D5172 This was SVN commit r27925.
This commit is contained in:
parent
debbcba9a6
commit
ba1a67a824
@ -17,19 +17,147 @@
|
||||
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "graphics/ColladaManager.h"
|
||||
#include "graphics/Decal.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
#include "graphics/ObjectEntry.h"
|
||||
#include "graphics/ObjectManager.h"
|
||||
#include "graphics/ShaderDefines.h"
|
||||
#include "graphics/SkeletonAnimManager.h"
|
||||
#include "graphics/Terrain.h"
|
||||
#include "graphics/Unit.h"
|
||||
#include "graphics/UnitManager.h"
|
||||
#include "lib/file/io/io.h"
|
||||
#include "ps/ConfigDB.h"
|
||||
#include "ps/CStrInternStatic.h"
|
||||
#include "ps/ProfileViewer.h"
|
||||
#include "ps/VideoMode.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "renderer/backend/dummy/Device.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr std::string_view TEST_SKELETON_XML{R"(<?xml version="1.0" encoding="UTF-8"?><skeletons></skeletons>)"};
|
||||
|
||||
constexpr std::string_view TEST_MESH_XML{R"(<?xml version="1.0" encoding="utf-8"?>
|
||||
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
|
||||
<asset>
|
||||
<unit name="meter" meter="1"/>
|
||||
<up_axis>Z_UP</up_axis>
|
||||
</asset>
|
||||
<library_geometries>
|
||||
<geometry id="Plane-mesh" name="Plane">
|
||||
<mesh>
|
||||
<source id="Plane-mesh-positions">
|
||||
<float_array id="Plane-mesh-positions-array" count="12">1 1 0 1 -1 0 -1 -0.9999998 0 -0.9999997 1 0</float_array>
|
||||
</source>
|
||||
<source id="Plane-mesh-normals">
|
||||
<float_array id="Plane-mesh-normals-array" count="3">0 0 1</float_array>
|
||||
</source>
|
||||
<source id="Plane-mesh-map-0">
|
||||
<float_array id="Plane-mesh-map-0-array" count="8">0 0 1 0 1 1 0 1</float_array>
|
||||
</source>
|
||||
<vertices id="Plane-mesh-vertices">
|
||||
<input semantic="POSITION" source="#Plane-mesh-positions"/>
|
||||
</vertices>
|
||||
<polylist count="1">
|
||||
<input semantic="VERTEX" source="#Plane-mesh-vertices" offset="0"/>
|
||||
<input semantic="NORMAL" source="#Plane-mesh-normals" offset="1"/>
|
||||
<input semantic="TEXCOORD" source="#Plane-mesh-map-0" offset="2" set="0"/>
|
||||
<vcount>4 </vcount>
|
||||
<p>0 0 0 3 0 1 2 0 2 1 0 3</p>
|
||||
</polylist>
|
||||
</mesh>
|
||||
</geometry>
|
||||
</library_geometries>
|
||||
<library_visual_scenes>
|
||||
<visual_scene id="Scene" name="Scene">
|
||||
<node id="Plane" type="NODE"><instance_geometry url="#Plane-mesh"/></node>
|
||||
</visual_scene>
|
||||
</library_visual_scenes>
|
||||
<scene><instance_visual_scene url="#Scene"/></scene>
|
||||
</COLLADA>)"};
|
||||
|
||||
constexpr std::string_view TEST_ACTOR_WITH_SHADOWS_NAME{"test_with_shadows.xml"};
|
||||
constexpr std::string_view TEST_ACTOR_WITH_SHADOWS_XML{R"(<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<castshadow/>
|
||||
<group>
|
||||
<variant><mesh>test.dae</mesh></variant>
|
||||
</group>
|
||||
</actor>)"};
|
||||
}
|
||||
|
||||
class TestModel : public CxxTest::TestSuite
|
||||
{
|
||||
OsPath m_ModPath;
|
||||
OsPath m_CachePath;
|
||||
std::unique_ptr<CProfileViewer> m_Viewer;
|
||||
std::unique_ptr<CRenderer> m_Renderer;
|
||||
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
g_VFS = CreateVfs();
|
||||
|
||||
CConfigDB::Initialise();
|
||||
CConfigDB::Instance()->SetValueString(CFG_SYSTEM, "rendererbackend", "dummy");
|
||||
CXeromyces::Startup();
|
||||
|
||||
TestLogger logger;
|
||||
|
||||
g_VideoMode.InitNonSDL();
|
||||
g_VideoMode.CreateBackendDevice(false);
|
||||
m_Viewer = std::make_unique<CProfileViewer>();
|
||||
m_Renderer = std::make_unique<CRenderer>(g_VideoMode.GetBackendDevice());
|
||||
|
||||
m_ModPath = DataDir() / "mods" / "_test.model" / "";
|
||||
m_CachePath = DataDir() / "_testcache" / "";
|
||||
|
||||
const OsPath skeletonsPath = m_ModPath / "art" / "skeletons";
|
||||
TS_ASSERT_EQUALS(INFO::OK, CreateDirectories(skeletonsPath, 0700, false));
|
||||
|
||||
const OsPath meshesPath = m_ModPath / "art" / "meshes";
|
||||
TS_ASSERT_EQUALS(INFO::OK, CreateDirectories(meshesPath, 0700, false));
|
||||
|
||||
const OsPath testSkeletonPath = skeletonsPath / "test.xml";
|
||||
TS_ASSERT_EQUALS(INFO::OK, io::Store(testSkeletonPath, TEST_SKELETON_XML.data(), TEST_SKELETON_XML.size()));
|
||||
|
||||
const OsPath testMeshPath = meshesPath / "test.dae";
|
||||
TS_ASSERT_EQUALS(INFO::OK, io::Store(testMeshPath, TEST_MESH_XML.data(), TEST_MESH_XML.size()));
|
||||
|
||||
const OsPath actorsPath = m_ModPath / "art" / "actors";
|
||||
TS_ASSERT_EQUALS(INFO::OK, CreateDirectories(actorsPath, 0700, false));
|
||||
|
||||
const OsPath testActorPath = actorsPath / TEST_ACTOR_WITH_SHADOWS_NAME.data();
|
||||
TS_ASSERT_EQUALS(INFO::OK, io::Store(testActorPath, TEST_ACTOR_WITH_SHADOWS_XML.data(), TEST_ACTOR_WITH_SHADOWS_XML.size()));
|
||||
|
||||
TS_ASSERT_OK(g_VFS->Mount(L"", m_ModPath));
|
||||
TS_ASSERT_OK(g_VFS->Mount(L"cache/", m_CachePath, 0, VFS_MAX_PRIORITY));
|
||||
}
|
||||
|
||||
void tearDown()
|
||||
{
|
||||
m_Renderer.reset();
|
||||
m_Viewer.reset();
|
||||
g_VideoMode.Shutdown();
|
||||
|
||||
CXeromyces::Terminate();
|
||||
CConfigDB::Shutdown();
|
||||
g_VFS.reset();
|
||||
|
||||
DeleteDirectory(m_ModPath);
|
||||
DeleteDirectory(m_CachePath);
|
||||
}
|
||||
|
||||
bool HasShaderDefine(const CShaderDefines& defines, CStrIntern define)
|
||||
{
|
||||
const auto& map = defines.GetMap();
|
||||
@ -42,11 +170,21 @@ public:
|
||||
return HasShaderDefine(model->GetMaterial().GetShaderDefines(), define);
|
||||
}
|
||||
|
||||
bool HasMaterialDefine(CModelDecal* model, CStrIntern define)
|
||||
{
|
||||
return HasShaderDefine(model->m_Decal.m_Material.GetShaderDefines(), define);
|
||||
}
|
||||
|
||||
void test_model_with_flags()
|
||||
{
|
||||
TestLogger logger;
|
||||
|
||||
CMaterial material{};
|
||||
CSimulation2 simulation{nullptr, g_ScriptContext, nullptr};
|
||||
|
||||
CTerrain terrain;
|
||||
terrain.Initialize(4, nullptr);
|
||||
|
||||
// TODO: load a proper mock for modeldef.
|
||||
CModelDefPtr modeldef = std::make_shared<CModelDef>();
|
||||
|
||||
@ -55,6 +193,9 @@ public:
|
||||
SPropPoint propPoint{};
|
||||
model->AddProp(&propPoint, std::make_unique<CModel>(simulation, material, modeldef), nullptr);
|
||||
|
||||
SDecal decal{CMaterial{}, 4.0f, 4.0f, 0.0f, 4.0f, 4.0f, false};
|
||||
model->AddProp(&propPoint, std::make_unique<CModelDecal>(&terrain, decal), nullptr);
|
||||
|
||||
model->AddFlagsRec(ModelFlag::IGNORE_LOS);
|
||||
model->RemoveShadowsRec();
|
||||
|
||||
@ -62,9 +203,16 @@ public:
|
||||
TS_ASSERT(HasMaterialDefine(model.get(), str_IGNORE_LOS));
|
||||
for (const CModel::Prop& prop : model->GetProps())
|
||||
{
|
||||
TS_ASSERT(prop.m_Model->ToCModel());
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_IGNORE_LOS));
|
||||
TS_ASSERT(prop.m_Model->ToCModel() || prop.m_Model->ToCModelDecal());
|
||||
if (prop.m_Model->ToCModel())
|
||||
{
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_IGNORE_LOS));
|
||||
}
|
||||
else if (prop.m_Model->ToCModelDecal())
|
||||
{
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModelDecal(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<CModelAbstract> clonedModel = model->Clone();
|
||||
@ -75,9 +223,50 @@ public:
|
||||
TS_ASSERT_EQUALS(model->GetProps().size(), clonedModel->ToCModel()->GetProps().size());
|
||||
for (const CModel::Prop& prop : clonedModel->ToCModel()->GetProps())
|
||||
{
|
||||
TS_ASSERT(prop.m_Model->ToCModel());
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_IGNORE_LOS));
|
||||
TS_ASSERT(prop.m_Model->ToCModel() || prop.m_Model->ToCModelDecal());
|
||||
if (prop.m_Model->ToCModel())
|
||||
{
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModel(), str_IGNORE_LOS));
|
||||
}
|
||||
else if (prop.m_Model->ToCModelDecal())
|
||||
{
|
||||
TS_ASSERT(HasMaterialDefine(prop.m_Model->ToCModelDecal(), str_DISABLE_RECEIVE_SHADOWS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_unit_reload()
|
||||
{
|
||||
TestLogger logger;
|
||||
|
||||
CColladaManager colladaManager{g_VFS};
|
||||
CMeshManager meshManager{colladaManager};
|
||||
CSkeletonAnimManager skeletonAnimationManager{colladaManager};
|
||||
|
||||
CUnitManager unitManager;
|
||||
CSimulation2 simulation{&unitManager, g_ScriptContext, nullptr};
|
||||
CObjectManager objectManager{
|
||||
meshManager, skeletonAnimationManager, simulation};
|
||||
unitManager.SetObjectManager(objectManager);
|
||||
|
||||
const CStrW actorName = CStr{TEST_ACTOR_WITH_SHADOWS_NAME}.FromUTF8();
|
||||
|
||||
const entity_id_t id = 1;
|
||||
const uint32_t seed = 1;
|
||||
CUnit* unit = unitManager.CreateUnit(actorName, id, seed);
|
||||
TS_ASSERT(unit);
|
||||
CModel* model = unit->GetModel().ToCModel();
|
||||
TS_ASSERT(model);
|
||||
TS_ASSERT((model->GetFlags() & ModelFlag::CAST_SHADOWS) == ModelFlag::CAST_SHADOWS);
|
||||
|
||||
auto [success, actor] = objectManager.FindActorDef(actorName);
|
||||
TS_ASSERT(success);
|
||||
const uint32_t newSeed = 2;
|
||||
// Trigger the unit reload.
|
||||
unit->SetActorSelections(actor.PickSelectionsAtRandom(newSeed));
|
||||
model = unit->GetModel().ToCModel();
|
||||
TS_ASSERT(model);
|
||||
TS_ASSERT((model->GetFlags() & ModelFlag::CAST_SHADOWS) == ModelFlag::CAST_SHADOWS);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user