1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Overhaul Loader framework for Models

- Replace background model loader with generic background loader
- Replace ModelHandle object with generic resource handle
This commit is contained in:
Daniel Evans 2015-03-06 04:38:22 +00:00 committed by Daniel Evans
parent ce4b8fc83a
commit d1e7dcdcd1
30 changed files with 242 additions and 170 deletions

View File

@ -0,0 +1,20 @@
#pragma once
#include <WorkContext.hpp>
/**
* Generic base class for loader implementations
*/
template<class T> class Loader
{
public:
/**
* Type of the resource produced by the loader
*/
typedef T ResultType;
/**
* Method that should be used to export the loaded data
*/
ResultType get();
};

View File

@ -0,0 +1,34 @@
#pragma once
#include <memory>
#include <string>
namespace RW
{
/**
* Possible states for ResourceHandle
*/
enum ResourceState
{
/// Resource has been declared but not loaded
Loading = 0,
/// Resource has been loaded and is available
Loaded = 1,
/// Loading the resource failed
Failed = 2
};
};
template<class T> class ResourceHandle
{
public:
T* resource;
RW::ResourceState state;
std::string name;
typedef std::shared_ptr<ResourceHandle<T>> Ref;
ResourceHandle(const std::string& name)
: resource(nullptr), state(RW::Loading), name(name) { }
};

View File

@ -209,7 +209,7 @@ public:
/**
* Loaded models
*/
std::map<std::string, ModelHandle*> models;
std::map<std::string, ResourceHandle<Model>::Ref> models;
/**
* Loaded textures (Textures are ID by name and alpha pairs)

View File

@ -5,6 +5,7 @@
#include <engine/RWTypes.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIPL.hpp>
#include <render/Model.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <memory>
@ -31,7 +32,8 @@ public:
glm::vec3 position;
glm::quat rotation;
ModelHandle* model; /// Cached pointer to Object's Model.
/// Reference to Model data
ModelRef model;
GameWorld* engine;
@ -55,7 +57,7 @@ public:
*/
bool visible;
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model)
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelRef model)
: _lastPosition(pos), _lastRotation(rot), position(pos), rotation(rot),
model(model), engine(engine), animator(nullptr), skeleton(nullptr), mHealth(0.f),
_inWater(false), _lastHeight(std::numeric_limits<float>::max()), visible(true),

View File

@ -22,16 +22,6 @@ struct Animation;
typedef std::map<std::string, Animation*> AnimationSet;
class Model;
// TODO: Make generic.
struct ModelHandle {
Model* model;
std::string name;
ModelHandle(const std::string& name) : model( nullptr ), name(name) {}
};
namespace RWTypes
{

View File

@ -0,0 +1,40 @@
#pragma once
#include <WorkContext.hpp>
#include <data/ResourceHandle.hpp>
#include <core/FileIndex.hpp>
/**
* Implementation of a worker that loads a resource in the background.
*/
template<class T, class L> class BackgroundLoaderJob : public WorkJob
{
public:
typedef typename ResourceHandle<T>::Ref TypeRef;
BackgroundLoaderJob(WorkContext* context, FileIndex* index, const std::string& file, const TypeRef& ref)
:WorkJob(context), index(index), filename(file), resourceRef(ref)
{ }
void work()
{
data = index->openFile(filename);
}
void complete()
{
if( data )
{
L loader;
resourceRef->resource = loader.loadFromMemory(data);
resourceRef->state = RW::Loaded;
}
}
private:
FileIndex* index;
std::string filename;
FileHandle data;
TypeRef resourceRef;
};

View File

@ -11,6 +11,8 @@
#include <string>
#include <WorkContext.hpp>
#include <core/FileHandle.hpp>
#include <core/FileIndex.hpp>
#include <data/ResourceHandle.hpp>
class Model;
class GameData;
@ -54,28 +56,7 @@ class LoaderDFF
void readAtomic(Model* model, const RWBStream& stream);
public:
Model* loadFromMemory(FileHandle file, GameData* gameData);
};
#include <functional>
class LoadModelJob : public WorkJob
{
public:
typedef std::function<void ( Model* )> ModelCallback;
private:
GameData* _gameData;
std::string _file;
ModelCallback _callback;
FileHandle data;
public:
LoadModelJob(WorkContext* context, GameData* gd, const std::string& file, ModelCallback cb);
void work();
void complete();
Model* loadFromMemory(FileHandle file);
};
#endif

View File

@ -87,7 +87,7 @@ public:
* @param model
* @param ped PEDS_t struct to use.
*/
CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle *model, std::shared_ptr<CharacterData> data);
CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, std::shared_ptr< CharacterData > data);
~CharacterObject();

View File

@ -13,9 +13,7 @@ class CutsceneObject : public GameObject
public:
CutsceneObject(GameWorld* engine,
const glm::vec3& pos,
ModelHandle* model);
CutsceneObject(GameWorld* engine, const glm::vec3& pos, const ModelRef& model);
~CutsceneObject();
Type type() { return Cutscene; }

View File

@ -20,14 +20,7 @@ public:
std::shared_ptr<DynamicObjectData> dynamics;
bool _enablePhysics;
InstanceObject(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
ModelHandle* model,
const glm::vec3& scale,
std::shared_ptr<ObjectData> obj,
InstanceObject *lod,
std::shared_ptr<DynamicObjectData> dyn
InstanceObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, const glm::vec3& scale, std::shared_ptr< ObjectData > obj, InstanceObject* lod, std::shared_ptr< DynamicObjectData > dyn
);
~InstanceObject();

View File

@ -46,14 +46,7 @@ public:
std::map<std::string, Part> dynamicParts;
VehicleObject(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
ModelHandle* model,
VehicleDataHandle data,
VehicleInfoHandle info,
const glm::u8vec3& prim,
const glm::u8vec3& sec);
VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec);
virtual ~VehicleObject();

View File

@ -8,6 +8,7 @@
#include <algorithm>
#include <GL/glew.h>
#include <data/ResourceHandle.hpp>
#include <loaders/rwbinarystream.h>
#include "DrawBuffer.hpp"
#include "GeometryBuffer.hpp"
@ -166,4 +167,6 @@ public:
~Model();
};
typedef ResourceHandle<Model>::Ref ModelRef;
#endif

View File

@ -12,6 +12,7 @@
#include <loaders/GenericDATLoader.hpp>
#include <loaders/LoaderGXT.hpp>
#include <loaders/BackgroundLoader.hpp>
#include <iostream>
#include <fstream>
@ -87,10 +88,9 @@ GameData::GameData(const std::string& path)
GameData::~GameData()
{
for(auto& m : models) {
if(m.second->model) {
delete m.second->model;
if(m.second->resource) {
delete m.second->resource;
}
delete m.second;
}
}
@ -408,22 +408,18 @@ void GameData::loadDFF(const std::string& name, bool async)
// Before starting the job make sure the file isn't loaded again.
loadedFiles.insert({name, true});
models[realname] = new ModelHandle(realname);
auto j = new LoadModelJob(this->engine->_work, this, name,
[&, realname]( Model* model ) {
models[realname]->model = model;
}
);
models[realname] = ModelRef( new ResourceHandle<Model>(realname) );
auto job = new BackgroundLoaderJob<Model, LoaderDFF>
{ this->engine->_work, &this->index, name, models[realname] };
if( async ) {
this->engine->_work->queueJob( j );
this->engine->_work->queueJob( job );
}
else {
j->work();
j->complete();
delete j;
job->work();
job->complete();
delete job;
}
}

View File

@ -228,7 +228,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
gameData.loadTXD(texturename + ".txd", true);
}
ModelHandle* m = gameData.models[modelname];
ModelRef m = gameData.models[modelname];
// Check for dynamic data.
auto dyit = gameData.dynamicObjectData.find(oi->modelName);
@ -364,7 +364,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
}
ModelHandle* m = gameData.models[modelname];
ModelRef m = gameData.models[modelname];
auto instance = new CutsceneObject(
this,
@ -410,8 +410,8 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
}
}
ModelHandle* m = gameData.models[vti->modelName];
auto model = m->model;
ModelRef& m = gameData.models[vti->modelName];
auto model = m->resource;
auto info = gameData.vehicleInfo.find(vti->handlingID);
if(model && info != gameData.vehicleInfo.end()) {
if( info->second->wheels.size() == 0 && info->second->seats.size() == 0 ) {
@ -470,9 +470,9 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3
gameData.loadTXD(texturename + ".txd");
}
ModelHandle* m = gameData.models[modelname];
ModelRef m = gameData.models[modelname];
if(m && m->model) {
if(m && m->resource) {
auto ped = new CharacterObject( this, pos, rot, m, pt );
objects.insert(ped);
new DefaultAIController(ped);

View File

@ -9,7 +9,7 @@
void WeaponItem::fireHitscan()
{
auto handFrame = _character->model->model->findFrame("srhand");
auto handFrame = _character->model->resource->findFrame("srhand");
glm::mat4 handMatrix;
if( handFrame ) {
while( handFrame->getParent() ) {

View File

@ -414,7 +414,7 @@ void LoaderDFF::readAtomic(Model *model, const RWBStream &stream)
/// @todo are any atomic extensions important?
}
Model* LoaderDFF::loadFromMemory(FileHandle file, GameData *gameData)
Model* LoaderDFF::loadFromMemory(FileHandle file)
{
auto model = new Model;
@ -454,29 +454,3 @@ Model* LoaderDFF::loadFromMemory(FileHandle file, GameData *gameData)
return model;
}
LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, const std::string &file, ModelCallback cb)
: WorkJob(context), _gameData(gd), _file(file), _callback(cb)
{
}
void LoadModelJob::work()
{
data = _gameData->openFile(_file);
}
void LoadModelJob::complete()
{
Model* m = nullptr;
// TODO error status
if( data ) {
// TODO allow some of the loading to process in a seperate thread.
LoaderDFF loader;
m = loader.loadFromMemory(data, _gameData);
}
_callback(m);
}

View File

@ -9,7 +9,7 @@
// TODO: make this not hardcoded
static glm::vec3 enter_offset(0.81756252f, 0.34800607f, -0.486281008f);
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, std::shared_ptr<CharacterData> data)
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, std::shared_ptr<CharacterData> data)
: GameObject(engine, pos, rot, model),
currentVehicle(nullptr), currentSeat(0),
_hasTargetPosition(false), _activeInventoryItem(0),
@ -49,7 +49,7 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const
if(model) {
skeleton = new Skeleton;
animator = new Animator(model->model, skeleton);
animator = new Animator(model->resource, skeleton);
createActor();
}

View File

@ -2,11 +2,11 @@
#include <engine/Animator.hpp>
#include <data/Skeleton.hpp>
CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos, ModelHandle *model)
CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos, const ModelRef& model)
: GameObject(engine, pos, {}, model), _parent(nullptr), _bone(nullptr)
{
skeleton = new Skeleton;
animator = new Animator(model->model, skeleton);
animator = new Animator(model->resource, skeleton);
}
CutsceneObject::~CutsceneObject()

View File

@ -7,7 +7,7 @@
InstanceObject::InstanceObject(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
ModelHandle *model,
const ModelRef& model,
const glm::vec3& scale,
std::shared_ptr<ObjectData> obj,
InstanceObject* lod,

View File

@ -10,7 +10,7 @@
#define PART_CLOSE_VELOCITY 0.25f
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec)
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec)
: GameObject(engine, pos, rot, model),
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(true),
vehicle(data), info(info), colourPrimary(prim),
@ -64,7 +64,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
// Hide all LOD and damage frames.
skeleton = new Skeleton;
for(ModelFrame* frame : model->model->frames)
for(ModelFrame* frame : model->resource->frames)
{
auto& name = frame->getName();
bool isDam = name.find("_dam") != name.npos;
@ -477,7 +477,7 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg)
if( skeleton->getData(p->normal->getIndex()).enabled )
{
auto& geom = model->model->geometries[p->normal->getGeometries()[0]];
auto& geom = model->resource->geometries[p->normal->getGeometries()[0]];
auto pp = p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f);
float td = glm::distance(glm::vec3(pp)+geom->geometryBounds.center
, dpoint);
@ -627,7 +627,7 @@ void VehicleObject::createObjectHinge(btTransform& local, Part *part)
if( okframe->getGeometries().size() == 0 ) return;
auto& geom = model->model->geometries[okframe->getGeometries()[0]];
auto& geom = model->resource->geometries[okframe->getGeometries()[0]];
auto gbounds = geom->geometryBounds;
if( fn.find("door") != fn.npos ) {

View File

@ -351,11 +351,11 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
transparentDrawQueue.clear();
// Render arrows above anything that isn't radar only (or hidden)
ModelHandle* arrowModel = engine->gameData.models["arrow"];
if( arrowModel && arrowModel->model )
ModelRef& arrowModel = engine->gameData.models["arrow"];
if( arrowModel && arrowModel->resource )
{
auto arrowTex = engine->gameData.textures[{"copblue",""}];
auto arrowFrame = arrowModel->model->findFrame( "arrow" );
auto arrowFrame = arrowModel->resource->findFrame( "arrow" );
for( auto& blip : engine->state.radarBlips )
{
if( blip.second.display == BlipData::Show )
@ -381,7 +381,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
dp.ambient = 1.f;
dp.colour = glm::u8vec4(255, 255, 255, 255);
auto geom = arrowModel->model->geometries[arrowFrame->getGeometries()[0]];
auto geom = arrowModel->resource->geometries[arrowFrame->getGeometries()[0]];
Model::SubGeometry& sg = geom->subgeom[0];
dp.start = sg.start;
@ -550,7 +550,7 @@ void GameRenderer::renderPedestrian(CharacterObject *pedestrian)
{
glm::mat4 matrixModel = pedestrian->getTimeAdjustedTransform( _renderAlpha );
if(!pedestrian->model->model) return;
if(!pedestrian->model->resource) return;
if( pedestrian->isAnimationFixed() )
{
@ -559,12 +559,12 @@ void GameRenderer::renderPedestrian(CharacterObject *pedestrian)
matrixModel = glm::translate(matrixModel, -rtranslate);
}
auto root = pedestrian->model->model->frames[0];
auto root = pedestrian->model->resource->frames[0];
renderFrame(pedestrian->model->model, root->getChildren()[0], matrixModel, pedestrian, 1.f, pedestrian->animator);
renderFrame(pedestrian->model->resource, root->getChildren()[0], matrixModel, pedestrian, 1.f, pedestrian->animator);
if(pedestrian->getActiveItem()) {
auto handFrame = pedestrian->model->model->findFrame("srhand");
auto handFrame = pedestrian->model->resource->findFrame("srhand");
glm::mat4 localMatrix;
if( handFrame ) {
while( handFrame->getParent() ) {
@ -585,13 +585,13 @@ void GameRenderer::renderVehicle(VehicleObject *vehicle)
glm::mat4 matrixModel = vehicle->getTimeAdjustedTransform( _renderAlpha );
renderModel(vehicle->model->model, matrixModel, vehicle);
renderModel(vehicle->model->resource, matrixModel, vehicle);
// Draw wheels n' stuff
for( size_t w = 0; w < vehicle->info->wheels.size(); ++w) {
auto woi = engine->findObjectType<ObjectData>(vehicle->vehicle->wheelModelID);
if( woi ) {
Model* wheelModel = engine->gameData.models["wheels"]->model;
Model* wheelModel = engine->gameData.models["wheels"]->resource;
auto& wi = vehicle->physVehicle->getWheelInfo(w);
if( wheelModel ) {
// Construct our own matrix so we can use the local transform
@ -641,7 +641,7 @@ void GameRenderer::renderInstance(InstanceObject *instance)
}
}
if(!instance->model->model)
if(!instance->model->resource)
{
return;
}
@ -657,9 +657,9 @@ void GameRenderer::renderInstance(InstanceObject *instance)
}
float mindist = 100000.f;
for (size_t g = 0; g < instance->model->model->geometries.size(); g++)
for (size_t g = 0; g < instance->model->resource->geometries.size(); g++)
{
RW::BSGeometryBounds& bounds = instance->model->model->geometries[g]->geometryBounds;
RW::BSGeometryBounds& bounds = instance->model->resource->geometries[g]->geometryBounds;
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - _camera.position) - bounds.radius);
}
@ -680,20 +680,20 @@ void GameRenderer::renderInstance(InstanceObject *instance)
culled++;
return;
}
else if (instance->LODinstance->model->model) {
model = instance->LODinstance->model->model;
else if (instance->LODinstance->model->resource) {
model = instance->LODinstance->model->resource;
fadingModel = instance->model->model;
fadingModel = instance->model->resource;
opacity = (mindist) / instance->object->drawDistance[0];
}
}
else {
fadingModel = instance->model->model;
fadingModel = instance->model->resource;
opacity = (mindist) / instance->object->drawDistance[0];
}
}
else if (! instance->object->LOD ) {
model = instance->model->model;
model = instance->model->resource;
opacity = (mindist) / instance->object->drawDistance[0];
}
}
@ -703,14 +703,14 @@ void GameRenderer::renderInstance(InstanceObject *instance)
return;
}
auto root = instance->model->model->frames[0];
auto root = instance->model->resource->frames[0];
int lodInd = 1;
if( mindist > instance->object->drawDistance[0] ) {
lodInd = 2;
}
auto LODindex = root->getChildren().size() - lodInd;
auto f = root->getChildren()[LODindex];
model = instance->model->model;
model = instance->model->resource;
frame = f;
if( lodInd == 2 ) {
@ -750,9 +750,9 @@ void GameRenderer::renderPickup(PickupObject *pickup)
if( odata->ID >= 170 && odata->ID <= 184 )
{
auto weapons = engine->gameData.models["weapons"];
if( weapons && weapons->model && odata ) {
model = weapons->model;
itemModel = weapons->model->findFrame(odata->modelName + "_l0");
if( weapons && weapons->resource && odata ) {
model = weapons->resource;
itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
if ( ! itemModel )
{
engine->logger.error("Renderer", "Weapon frame " + odata->modelName + " not in model");
@ -762,9 +762,9 @@ void GameRenderer::renderPickup(PickupObject *pickup)
else
{
auto handle = engine->gameData.models[odata->modelName];
if ( handle && handle->model )
if ( handle && handle->resource )
{
model = handle->model;
model = handle->resource;
itemModel = model->frames[model->rootFrameIdx];
}
else
@ -784,7 +784,7 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene)
{
if(!engine->state.currentCutscene) return;
if(!cutscene->model->model)
if(!cutscene->model->resource)
{
return;
}
@ -808,9 +808,9 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene)
}
float mindist = 100000.f;
for (size_t g = 0; g < cutscene->model->model->geometries.size(); g++)
for (size_t g = 0; g < cutscene->model->resource->geometries.size(); g++)
{
RW::BSGeometryBounds& bounds = cutscene->model->model->geometries[g]->geometryBounds;
RW::BSGeometryBounds& bounds = cutscene->model->resource->geometries[g]->geometryBounds;
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - _camera.position) - bounds.radius);
}
@ -818,10 +818,10 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene)
glm::mat4 align;
/// @todo figure out where this 90 degree offset is coming from.
align = glm::rotate(align, glm::half_pi<float>(), {0.f, 1.f, 0.f});
renderModel(cutscene->model->model, matrixModel * align, cutscene);
renderModel(cutscene->model->resource, matrixModel * align, cutscene);
}
else {
renderModel(cutscene->model->model, matrixModel, cutscene);
renderModel(cutscene->model->resource, matrixModel, cutscene);
}
}
@ -831,11 +831,11 @@ void GameRenderer::renderProjectile(ProjectileObject *projectile)
auto odata = engine->findObjectType<ObjectData>(projectile->getProjectileInfo().weapon->modelID);
auto weapons = engine->gameData.models["weapons"];
if( weapons && weapons->model ) {
auto itemModel = weapons->model->findFrame(odata->modelName + "_l0");
if( weapons && weapons->resource ) {
auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
auto matrix = glm::inverse(itemModel->getTransform());
if(itemModel) {
renderFrame(weapons->model, itemModel, modelMatrix * matrix, nullptr, 1.f);
renderFrame(weapons->resource, itemModel, modelMatrix * matrix, nullptr, 1.f);
}
else {
engine->logger.error("Renderer", "Weapon frame " + odata->modelName + " not in model");
@ -875,11 +875,11 @@ void GameRenderer::renderItem(InventoryItem *item, const glm::mat4 &modelMatrix)
// srhand
std::shared_ptr<ObjectData> odata = engine->findObjectType<ObjectData>(item->getModelID());
auto weapons = engine->gameData.models["weapons"];
if( weapons && weapons->model ) {
auto itemModel = weapons->model->findFrame(odata->modelName + "_l0");
if( weapons && weapons->resource ) {
auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
auto matrix = glm::inverse(itemModel->getTransform());
if(itemModel) {
renderFrame(weapons->model, itemModel, modelMatrix * matrix, nullptr, 1.f);
renderFrame(weapons->resource, itemModel, modelMatrix * matrix, nullptr, 1.f);
}
else {
engine->logger.error("Renderer", "Weapon frame " + odata->modelName + " not in model");

View File

@ -408,7 +408,7 @@ bool game_special_char_loaded(const ScriptArguments& args)
auto chartype = args.getVM()->getWorld()->findObjectType<CharacterData>(args[0].integer);
if( chartype ) {
auto modelfind = args.getVM()->getWorld()->gameData.models.find(chartype->modelName);
if( modelfind != args.getVM()->getWorld()->gameData.models.end() && modelfind->second->model != nullptr ) {
if( modelfind != args.getVM()->getWorld()->gameData.models.end() && modelfind->second->resource != nullptr ) {
return true;
}
}
@ -616,7 +616,7 @@ void game_create_cutscene_head(const ScriptArguments& args)
auto actor = static_cast<GameObject*>(*args[0].handle);
CutsceneObject* object = args.getVM()->getWorld()->createCutsceneObject(id, args.getVM()->getWorld()->state.currentCutscene->meta.sceneOffset );
auto headframe = actor->model->model->findFrame("shead");
auto headframe = actor->model->resource->findFrame("shead");
actor->skeleton->setEnabled(headframe, false);
object->setParentActor(actor, headframe);

View File

@ -0,0 +1,23 @@
#include <boost/test/unit_test.hpp>
#include <data/Loader.hpp>
#include <test_globals.hpp>
class IntLoader : public Loader<int>
{
int data;
public:
IntLoader( int value ) : data( value ) { }
ResultType get() { return data; }
};
BOOST_AUTO_TEST_SUITE(LoaderTests)
BOOST_AUTO_TEST_CASE(test_product)
{
BOOST_CHECK( typeid(IntLoader::ResultType) == typeid(int) );
IntLoader loader( 42 );
BOOST_CHECK_EQUAL( loader.get(), 42 );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -0,0 +1,24 @@
#include <boost/test/unit_test.hpp>
#include <data/ResourceHandle.hpp>
#include <test_globals.hpp>
typedef ResourceHandle<int>::Ref IntRef;
BOOST_AUTO_TEST_SUITE(ResourceTests)
BOOST_AUTO_TEST_CASE(test_ResourceHandle)
{
int resource = 42;
IntRef ref { new ResourceHandle<int>("") };
BOOST_CHECK_EQUAL( ref->resource, nullptr );
BOOST_CHECK_EQUAL( ref->state, RW::Loading );
ref->state = RW::Loaded;
ref->resource = &resource;
BOOST_CHECK_EQUAL( ref->resource, &resource );
BOOST_CHECK_EQUAL( ref->state, RW::Loaded );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -141,7 +141,7 @@ void IngameState::tick(float dt)
auto vehicle = ( target->type() == GameObject::Character ) ? static_cast<CharacterObject*>(target)->getCurrentVehicle() : nullptr;
if( vehicle ) {
auto model = vehicle->model;
for(auto& g : model->model->geometries) {
for(auto& g : model->resource->geometries) {
viewDistance = std::max(
(glm::length(g->geometryBounds.center) + g->geometryBounds.radius) * 4.0f,
viewDistance);

View File

@ -15,9 +15,9 @@ BOOST_AUTO_TEST_CASE(test_matrix)
/** Models are currently needed to relate animation bones <=> model frame #s. */
Global::get().e->gameData.loadDFF("player.dff");
ModelHandle* test_model = Global::get().e->gameData.models["player"];
ModelRef& test_model = Global::get().e->gameData.models["player"];
Animator animator(test_model->model, &skeleton);
Animator animator(test_model->resource, &skeleton);
animation.duration = 1.f;
animation.bones["player"] = new AnimationBone{

View File

@ -8,7 +8,7 @@ BOOST_AUTO_TEST_SUITE(CutsceneTests)
BOOST_AUTO_TEST_CASE(test_load)
{
{
auto d = Global::get().e->gameData.openFile2("intro.dat");
auto d = Global::get().e->gameData.openFile("intro.dat");
CutsceneTracks tracks;

View File

@ -2,17 +2,18 @@
#include "test_globals.hpp"
#include <render/Model.hpp>
#include <WorkContext.hpp>
#include <loaders/BackgroundLoader.hpp>
BOOST_AUTO_TEST_SUITE(LoaderDFFTests)
BOOST_AUTO_TEST_CASE(test_load_dff)
{
{
auto d = Global::get().e->gameData.openFile2("landstal.dff");
auto d = Global::get().e->gameData.openFile("landstal.dff");
LoaderDFF loader;
Model* m = loader.loadFromMemory(d, &Global::get().e->gameData);
Model* m = loader.loadFromMemory(d);
BOOST_REQUIRE( m != nullptr );
@ -38,28 +39,28 @@ BOOST_AUTO_TEST_CASE(test_load_dff)
}
BOOST_AUTO_TEST_CASE(test_modeljob)
BOOST_AUTO_TEST_CASE(test_loader_job)
{
{
WorkContext ctx;
Model* m = nullptr;
bool done = false;
LoadModelJob* lmj = new LoadModelJob(&ctx, &Global::get().e->gameData, "landstal.dff",
[&](Model* model) { m = model; done = true; });
ResourceHandle<Model>::Ref modelRef { new ResourceHandle<Model>("landstal.dff") };
ctx.queueJob(lmj);
auto index = &Global::get().e->gameData.index;
auto job = new BackgroundLoaderJob<Model, LoaderDFF>{ &ctx, index, "landstal.dff", modelRef };
while( ! done ) {
ctx.queueJob(job);
while( modelRef->state == RW::Loading ) {
ctx.update();
std::this_thread::yield();
}
BOOST_REQUIRE( m != nullptr );
BOOST_REQUIRE( modelRef->resource != nullptr );
BOOST_CHECK( m->frames.size() > 0 );
BOOST_CHECK( modelRef->resource->frames.size() > 0 );
delete m;
delete modelRef->resource;
}
}

View File

@ -7,7 +7,7 @@ BOOST_AUTO_TEST_SUITE(RWBStreamTests)
BOOST_AUTO_TEST_CASE(iterate_stream_test)
{
{
auto d = Global::get().e->gameData.openFile2("landstal.dff");
auto d = Global::get().e->gameData.openFile("landstal.dff");
RWBStream stream(d->data, d->length);

View File

@ -8,7 +8,7 @@ BOOST_AUTO_TEST_SUITE(TextTests)
BOOST_AUTO_TEST_CASE(load_test)
{
{
auto d = Global::get().e->gameData.openFile2("english.gxt");
auto d = Global::get().e->gameData.openFile("english.gxt");
GameTexts texts;