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:
parent
ce4b8fc83a
commit
d1e7dcdcd1
20
rwengine/include/data/Loader.hpp
Normal file
20
rwengine/include/data/Loader.hpp
Normal 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();
|
||||
};
|
34
rwengine/include/data/ResourceHandle.hpp
Normal file
34
rwengine/include/data/ResourceHandle.hpp
Normal 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) { }
|
||||
};
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
{
|
||||
|
||||
|
40
rwengine/include/loaders/BackgroundLoader.hpp
Normal file
40
rwengine/include/loaders/BackgroundLoader.hpp
Normal 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;
|
||||
};
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() ) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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 ) {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
23
rwengine/tests/test_Loader.cpp
Normal file
23
rwengine/tests/test_Loader.cpp
Normal 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()
|
24
rwengine/tests/test_Resource.cpp
Normal file
24
rwengine/tests/test_Resource.cpp
Normal 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()
|
@ -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);
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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") };
|
||||
|
||||
auto index = &Global::get().e->gameData.index;
|
||||
auto job = new BackgroundLoaderJob<Model, LoaderDFF>{ &ctx, index, "landstal.dff", modelRef };
|
||||
|
||||
ctx.queueJob(lmj);
|
||||
ctx.queueJob(job);
|
||||
|
||||
while( ! done ) {
|
||||
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 );
|
||||
|
||||
delete m;
|
||||
BOOST_CHECK( modelRef->resource->frames.size() > 0 );
|
||||
|
||||
delete modelRef->resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user