1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 00:59:47 +02:00

Threaded model and texture loading

This commit is contained in:
Daniel Evans 2014-06-06 12:18:32 +01:00
parent f24ceeb42f
commit 61931145fe
35 changed files with 345 additions and 168 deletions

View File

@ -52,6 +52,9 @@ public:
virtual void complete() {}
};
// TODO: refactor everything to remove this.
class GameWorld;
class WorkContext
{
std::queue<WorkJob*> _workQueue;
@ -62,10 +65,12 @@ class WorkContext
std::mutex _inMutex;
std::mutex _outMutex;
GameWorld* _world;
public:
WorkContext()
: _worker(this) { }
WorkContext(GameWorld* world = nullptr)
: _worker(this), _world(world) { }
void queueJob( WorkJob* job )
{
@ -79,6 +84,15 @@ public:
const std::queue<WorkJob*> getWorkQueue() const { return _workQueue; }
const std::queue<WorkJob*> getCompleteQueue() const { return _completeQueue; }
bool isEmpty() {
std::lock_guard<std::mutex> guardIn( _inMutex );
std::lock_guard<std::mutex> guardOu( _outMutex );
return (getWorkQueue().size() + getCompleteQueue().size()) == 0;
}
GameWorld* getWorld() const { return _world; }
void update();
};

View File

@ -11,6 +11,16 @@ class 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 GTATypes
{
@ -46,7 +56,6 @@ struct WaterRect
float xLeft, yBottom;
float xRight, yTop;
};
}
#endif

View File

@ -55,7 +55,7 @@ public:
struct GTAFile
{
bool archived; /// Is the file inside an IMG or on the filesystem?
std::string path; /// Path to the file containing the file
std::string path; /// Path to the file containing the file.
};
/**
@ -113,12 +113,12 @@ public:
/**
* Attempts to load a TXD, or does nothing if it has already been loaded
*/
void loadTXD(const std::string& name);
void loadTXD(const std::string& name, bool async = false);
/**
* Attempts to load a DFF or does nothing if is already loaded
*/
void loadDFF(const std::string& name);
void loadDFF(const std::string& name, bool async = false);
/**
* Loads an IFP file containing animations
@ -129,11 +129,19 @@ public:
* Loads data from an object definition dat.
*/
void loadDynamicObjects(const std::string& name);
/**
* Returns a pointer to the named file if it is available, the memory must be freed.
* Returns a pointer to the named file if it is available,
* the memory must be freed by the caller.
* @param name the filename in the archive
* @return pointer to the data, NULL if it is not available
* @return pointer to the data, NULL if it is not available
*/
char* openFile(const std::string& name);
/**
* @brief loadFile Marks a file as open, and opens it.
* @param name
* @return
*/
char* loadFile(const std::string& name);
@ -157,9 +165,9 @@ public:
std::map<std::string, std::string> ideLocations;
/**
* Maps file names to their locations
* Maps file names to data about the file.
*/
std::map<std::string, GTAFile> fileLocations;
std::map<std::string, GTAFile> _knownFiles;
/**
* Map of loaded archives
@ -190,11 +198,11 @@ public:
* Weather Loader
*/
WeatherLoader weatherLoader;
/**
* Loaded models
*/
std::map<std::string, Model*> models;
std::map<std::string, ModelHandle*> models;
/**
* Loaded Textures and their atlas entries.

View File

@ -9,7 +9,6 @@
#include <memory>
class GTAAIController;
class Model;
class ModelFrame;
class Animator;
@ -23,7 +22,7 @@ struct GameObject
glm::vec3 position;
glm::quat rotation;
Model* model; /// Cached pointer to Object's Model.
ModelHandle* model; /// Cached pointer to Object's Model.
GameWorld* engine;
@ -34,7 +33,7 @@ struct GameObject
*/
float mHealth;
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, Model* model)
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model)
: position(pos), rotation(rot), model(model), engine(engine), animator(nullptr), mHealth(0.f)
{}

View File

@ -8,6 +8,8 @@
#include <ai/GTAAINode.hpp>
#include <ai/AIGraph.hpp>
class WorkContext;
class GameObject;
class GTACharacter;
class GTAInstance;
@ -31,6 +33,8 @@ class GameWorld
public:
GameWorld(const std::string& gamepath);
~GameWorld();
/**
* Loads the game data
@ -191,7 +195,11 @@ public:
btBroadphaseInterface* broadphase;
btSequentialImpulseConstraintSolver* solver;
btDiscreteDynamicsWorld* dynamicsWorld;
/**
* Work related
*/
WorkContext* _work;
};
#endif

View File

@ -27,8 +27,6 @@ public:
#include <functional>
class LoaderIMG;
class LoadModelJob : public WorkJob
{
public:
@ -36,13 +34,12 @@ public:
private:
GameData* _gameData;
LoaderIMG* _archive;
std::string _file;
ModelCallback _callback;
char* _data;
public:
LoadModelJob(WorkContext* context, GameData* gd, LoaderIMG& archive, const std::string& file, ModelCallback cb);
LoadModelJob(WorkContext* context, GameData* gd, const std::string& file, ModelCallback cb);
void work();

View File

@ -19,4 +19,23 @@ public:
bool loadFromMemory(char *data, GameData* gameData);
};
#include <WorkContext.hpp>
#include <functional>
// TODO: refactor this interface to be more like ModelLoader so they can be rolled into one.
class LoadTextureArchiveJob : public WorkJob
{
private:
GameData* _gameData;
std::string _file;
char* _data;
public:
LoadTextureArchiveJob(WorkContext* context, GameData* gd, const std::string& file);
void work();
void complete();
};
#endif

View File

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

View File

@ -17,7 +17,7 @@ struct GTAInstance : public GameObject
GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
Model* model,
ModelHandle* model,
const glm::vec3& scale,
std::shared_ptr<ObjectData> obj,
std::shared_ptr<GTAInstance> lod

View File

@ -52,7 +52,7 @@ public:
GTAVehicle(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
Model* model,
ModelHandle* model,
VehicleDataHandle data,
VehicleInfoHandle info,
const glm::vec3& prim,

View File

@ -82,9 +82,9 @@ void GameData::load()
parseDAT(datpath+"/data/default.dat");
parseDAT(datpath+"/data/gta3.dat");
fileLocations.insert({"wheels.DFF", {false, datpath+"/models/Generic/wheels.DFF"}});
fileLocations.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
fileLocations.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
_knownFiles.insert({"wheels.DFF", {false, datpath+"/models/Generic/wheels.DFF"}});
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
loadDFF("wheels.DFF");
loadTXD("particle.txd");
@ -147,7 +147,7 @@ void GameData::parseDAT(const std::string& path)
}
texpath = findPathRealCase(datpath, texpath);
std::string texname = texpath.substr(texpath.find_last_of("/")+1);
fileLocations.insert({ texname, { false, texpath }});
_knownFiles.insert({ texname, { false, texpath }});
loadTXD(texname);
}
}
@ -201,12 +201,12 @@ void GameData::loadIMG(const std::string& name)
else
{
// Enter the asset twice..
fileLocations.insert({ filename, { true, archivePath }});
_knownFiles.insert({ filename, { true, archivePath }});
for(size_t t = 0; t < filename.size(); ++t)
{
filename[t] = tolower(filename[t]);
}
fileLocations.insert({ filename, { true, archivePath }});
_knownFiles.insert({ filename, { true, archivePath }});
}
}
archives.insert({archivePath, imgLoader});
@ -388,32 +388,54 @@ void GameData::loadWater(const std::string& path)
}
}
void GameData::loadTXD(const std::string& name)
void GameData::loadTXD(const std::string& name, bool async)
{
if( loadedFiles.find(name) != loadedFiles.end()) {
if( loadedFiles.find(name) != loadedFiles.end() ) {
return;
}
char* file = loadFile(name);
if(file) {
textureLoader.loadFromMemory(file, this);
delete[] file;
loadedFiles[name] = true;
auto j = new LoadTextureArchiveJob(this->engine->_work, this, name);
if( async ) {
this->engine->_work->queueJob( j );
}
else {
j->work();
j->complete();
delete j;
}
}
void GameData::loadDFF(const std::string& name)
void GameData::loadDFF(const std::string& name, bool async)
{
if( loadedFiles.find(name) != loadedFiles.end()) {
auto realname = name.substr(0, name.size() - 4);
if( models.find(realname) != models.end() ) {
return;
}
char *file = loadFile(name);
if(file)
{
LoaderDFF dffLoader;
models[name.substr(0, name.size() - 4)] = dffLoader.loadFromMemory(file, this);
delete[] file;
// 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;
}
);
if( async ) {
this->engine->_work->queueJob( j );
}
else {
j->work();
j->complete();
delete j;
}
}
void GameData::loadIFP(const std::string &name)
@ -471,15 +493,10 @@ void GameData::loadDynamicObjects(const std::string& name)
}
}
char* GameData::loadFile(const std::string& name)
char* GameData::openFile(const std::string& name)
{
if( loadedFiles.find(name) != loadedFiles.end()) {
std::cerr << "File " << name << " already loaded!" << std::endl;
return nullptr;
}
auto i = fileLocations.find(name);
if(i != fileLocations.end())
auto i = _knownFiles.find(name);
if(i != _knownFiles.end())
{
if(i->second.archived)
{
@ -487,7 +504,6 @@ char* GameData::loadFile(const std::string& name)
auto ai = archives.find(i->second.path);
if(ai != archives.end())
{
loadedFiles[name] = true;
return ai->second.loadToMemory(name);
}
else
@ -509,8 +525,6 @@ char* GameData::loadFile(const std::string& name)
char *data = new char[length];
dfile.read(data, length);
loadedFiles[name] = true;
return data;
}
}
@ -525,6 +539,18 @@ char* GameData::loadFile(const std::string& name)
return nullptr;
}
char* GameData::loadFile(const std::string &name)
{
auto it = loadedFiles.find(name);
if( it != loadedFiles.end() ) {
std::cerr << "File " << name << " already loaded?" << std::endl;
}
loadedFiles[name] = true;
return openFile(name);
}
TextureAtlas* GameData::getAtlas(size_t i)
{
if( i < atlases.size() ) {

View File

@ -4,6 +4,7 @@
#include <ai/GTADefaultAIController.hpp>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <render/Model.hpp>
#include <WorkContext.hpp>
// 3 isn't enough to cause a factory.
#include <objects/GTACharacter.hpp>
@ -11,11 +12,18 @@
#include <objects/GTAVehicle.hpp>
GameWorld::GameWorld(const std::string& path)
: gameTime(0.f), gameData(path), renderer(this), randomEngine(rand())
: gameTime(0.f), gameData(path), renderer(this), randomEngine(rand()),
_work( new WorkContext( this ) )
{
gameData.engine = this;
}
GameWorld::~GameWorld()
{
delete _work;
// TODO: delete other things.
}
bool GameWorld::load()
{
collisionConfig = new btDefaultCollisionConfiguration;
@ -174,10 +182,10 @@ GTAInstance *GameWorld::createInstance(const uint16_t id, const glm::vec3& pos,
if( oi != objectTypes.end()) {
// Make sure the DFF and TXD are loaded
if(! oi->second->modelName.empty()) {
gameData.loadDFF(oi->second->modelName + ".dff");
gameData.loadDFF(oi->second->modelName + ".dff", true);
}
if(! oi->second->textureName.empty()) {
gameData.loadTXD(oi->second->textureName + ".txd");
gameData.loadTXD(oi->second->textureName + ".txd", true);
}
auto instance = std::shared_ptr<GTAInstance>(new GTAInstance(
@ -236,7 +244,8 @@ GTAVehicle *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, co
}
}
Model* model = gameData.models[vti->second->modelName];
ModelHandle* m = gameData.models[vti->second->modelName];
auto model = m->model;
auto info = gameData.vehicleInfo.find(vti->second->handlingID);
if(model && info != gameData.vehicleInfo.end()) {
if( info->second->wheels.size() == 0 && info->second->seats.size() == 0 ) {
@ -258,7 +267,7 @@ GTAVehicle *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, co
}
}
vehicleInstances.push_back(new GTAVehicle{ this, pos, rot, model, vti->second, info->second, prim, sec });
vehicleInstances.push_back(new GTAVehicle{ this, pos, rot, m, vti->second, info->second, prim, sec });
return vehicleInstances.back();
}
return nullptr;
@ -280,10 +289,10 @@ GTACharacter* GameWorld::createPedestrian(const uint16_t id, const glm::vec3 &po
gameData.loadTXD(pt->textureName + ".txd");
}
Model* model = gameData.models[pt->modelName];
ModelHandle* m = gameData.models[pt->modelName];
if(model != nullptr) {
auto ped = new GTACharacter( this, pos, rot, model, pt );
if(m != nullptr) {
auto ped = new GTACharacter( this, pos, rot, m, pt );
pedestrians.push_back(ped);
new GTADefaultAIController(ped);
return ped;

View File

@ -312,25 +312,28 @@ RW::BSSectionHeader LoaderDFF::readHeader(char *data, size_t &dataI)
return readStructure<RW::BSSectionHeader>(data, dataI);
}
#include <loaders/LoaderIMG.hpp>
LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, LoaderIMG &archive, const std::string &file, ModelCallback cb)
: WorkJob(context), _gameData(gd), _archive(&archive), _file(file), _callback(cb), _data(nullptr)
LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, const std::string &file, ModelCallback cb)
: WorkJob(context), _gameData(gd), _file(file), _callback(cb), _data(nullptr)
{
}
void LoadModelJob::work()
{
_data = _archive->loadToMemory(_file);
_data = _gameData->openFile(_file);
}
void LoadModelJob::complete()
{
// TODO allow some of the loading to process in a seperate thread.
LoaderDFF loader;
Model* m = nullptr;
// TODO error status
if( _data ) {
Model* m = loader.loadFromMemory(_data, _gameData);
// TODO allow some of the loading to process in a seperate thread.
LoaderDFF loader;
m = loader.loadFromMemory(_data, _gameData);
}
_callback(m);

View File

@ -217,3 +217,26 @@ bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
return true;
}
LoadTextureArchiveJob::LoadTextureArchiveJob(WorkContext *context, GameData *gd, const std::string &file)
: WorkJob(context), _gameData(gd), _file(file), _data(nullptr)
{
}
void LoadTextureArchiveJob::work()
{
_data = _gameData->openFile(_file);
}
void LoadTextureArchiveJob::complete()
{
// TODO error status
if(_data) {
TextureLoader loader;
loader.loadFromMemory(_data, _gameData);
}
delete[] _data;
}

View File

@ -7,7 +7,7 @@
// TODO: make this not hardcoded
static glm::vec3 enter_offset(0.81756252f, 0.34800607f, -0.486281008f);
GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, std::shared_ptr<CharacterData> data)
GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, std::shared_ptr<CharacterData> data)
: GameObject(engine, pos, rot, model),
currentVehicle(nullptr), currentSeat(0),
_hasTargetPosition(false),
@ -35,7 +35,7 @@ GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::q
if(model) {
animator = new Animator();
animator->setModel(model);
animator->setModel(model->model);
createActor();
enterAction(Idle);

View File

@ -2,11 +2,10 @@
#include <engine/GameWorld.hpp>
#include <data/CollisionModel.hpp>
GTAInstance::GTAInstance(
GameWorld* engine,
GTAInstance::GTAInstance(GameWorld* engine,
const glm::vec3& pos,
const glm::quat& rot,
Model* model,
ModelHandle *model,
const glm::vec3& scale,
std::shared_ptr<ObjectData> obj,
std::shared_ptr<GTAInstance> lod

View File

@ -6,7 +6,7 @@
#include <data/CollisionModel.hpp>
#include <render/Model.hpp>
GTAVehicle::GTAVehicle(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::vec3& prim, const glm::vec3& sec)
GTAVehicle::GTAVehicle(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::vec3& prim, const glm::vec3& sec)
: GameObject(engine, pos, rot, model),
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false),
damageFlags(0), vehicle(data), info(info), colourPrimary(prim),

View File

@ -268,9 +268,9 @@ void GTARenderer::renderWorld(float alpha)
matrixModel = glm::translate(matrixModel, charac->getPosition());
matrixModel = matrixModel * glm::mat4_cast(charac->getRotation());
if(!charac->model) continue;
if(!charac->model->model) continue;
renderModel(charac->model, matrixModel, charac, charac->animator);
renderModel(charac->model->model, matrixModel, charac, charac->animator);
}
for(size_t i = 0; i < engine->objectInstances.size(); ++i) {
@ -284,24 +284,24 @@ void GTARenderer::renderWorld(float alpha)
}
}
if(!inst.model)
{
std::cout << "model " << inst.model << " not loaded (" << engine->gameData.models.size() << " models loaded)" << std::endl;
}
glm::mat4 matrixModel;
matrixModel = glm::translate(matrixModel, inst.position);
matrixModel = glm::scale(matrixModel, inst.scale);
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
if(!inst.model->model)
{
continue;
}
float mindist = 100000.f;
for (size_t g = 0; g < inst.model->geometries.size(); g++)
{
RW::BSGeometryBounds& bounds = inst.model->geometries[g]->geometryBounds;
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - camera.worldPos) - bounds.radius);
}
if ( mindist > inst.object->drawDistance[0] ) {
glm::mat4 matrixModel;
matrixModel = glm::translate(matrixModel, inst.position);
matrixModel = glm::scale(matrixModel, inst.scale);
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
float mindist = 100000.f;
for (size_t g = 0; g < inst.model->model->geometries.size(); g++)
{
RW::BSGeometryBounds& bounds = inst.model->model->geometries[g]->geometryBounds;
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - camera.worldPos) - bounds.radius);
}
if ( mindist > inst.object->drawDistance[0] ) {
if ( !inst.LODinstance ) {
culled++;
continue;
@ -311,13 +311,13 @@ void GTARenderer::renderWorld(float alpha)
culled++;
continue;
}
else {
renderModel(inst.LODinstance->model, matrixModel);
else if (inst.LODinstance->model->model) {
renderModel(inst.LODinstance->model->model, matrixModel);
}
}
}
}
else if (! inst.object->LOD ) {
renderModel(inst.model, matrixModel);
renderModel(inst.model->model, matrixModel);
}
}
@ -333,13 +333,13 @@ void GTARenderer::renderWorld(float alpha)
matrixModel = glm::translate(matrixModel, inst->getPosition());
matrixModel = matrixModel * glm::mat4_cast(inst->getRotation());
renderModel(inst->model, matrixModel, inst);
renderModel(inst->model->model, matrixModel, inst);
// Draw wheels n' stuff
for( size_t w = 0; w < inst->info->wheels.size(); ++w) {
auto woi = engine->objectTypes.find(inst->vehicle->wheelModelID);
if(woi != engine->objectTypes.end()) {
Model* wheelModel = engine->gameData.models["wheels"];
Model* wheelModel = engine->gameData.models["wheels"]->model;
if( wheelModel) {
// Tell bullet to update the matrix for this wheel.
inst->physVehicle->updateWheelTransform(w, false);

View File

@ -1,5 +1,6 @@
add_executable(rwgame
main.cpp
loadingstate.cpp
ingamestate.cpp
pausestate.cpp
menustate.cpp

View File

@ -119,6 +119,12 @@ struct StateManager
states.push_back(state);
state->enter();
}
void exec(State* state)
{
exit();
enter(state);
}
void tick(float dt)
{

View File

@ -67,7 +67,7 @@ void IngameState::tick(float dt)
float viewDistance = 2.f;
if( _playerCharacter->getCurrentVehicle() ) {
auto model = _playerCharacter->getCurrentVehicle()->model;
for(auto& g : model->geometries) {
for(auto& g : model->model->geometries) {
viewDistance = std::max(
(glm::length(g->geometryBounds.center) + g->geometryBounds.radius) * 1.5f,
viewDistance);

55
rwgame/loadingstate.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "loadingstate.hpp"
#include "menustate.hpp"
#include "game.hpp"
LoadingState::LoadingState()
{
}
void LoadingState::enter()
{
// Load all of the files waiting to be loaded.
auto world = getWorld();
// Loade all of the IDEs.
for(std::map<std::string, std::string>::iterator it = world->gameData.ideLocations.begin();
it != world->gameData.ideLocations.end();
++it) {
world->defineItems(it->second);
}
// Load IPLs
for(std::map<std::string, std::string>::iterator it = world->gameData.iplLocations.begin();
it != world->gameData.iplLocations.end();
++it) {
world->loadZone(it->second);
world->placeItems(it->second);
}
}
void LoadingState::exit()
{
}
void LoadingState::tick(float dt)
{
// Check to see if the GameWorld has run out of jobs
// (i.e. it's time to open the main menu)
if( getWorld()->_work->isEmpty() ) {
StateManager::get().exec(new MenuState);
}
}
void LoadingState::handleEvent(const sf::Event &e)
{
State::handleEvent(e);
}
void LoadingState::draw(sf::RenderWindow &w)
{
// Display some manner of loading screen.
sf::Text loadingText("Loading...", getFont(), 28);
loadingText.setPosition({30.f, 20.f});
w.draw(loadingText);
}

21
rwgame/loadingstate.hpp Normal file
View File

@ -0,0 +1,21 @@
#ifndef LOADINGSTATE_HHP
#define LOADINGSTATE_HPP
#include "State.hpp"
class LoadingState : public State
{
public:
LoadingState();
virtual void enter();
virtual void exit();
virtual void tick(float dt);
virtual void draw(sf::RenderWindow &w);
virtual void handleEvent(const sf::Event& event);
};
#endif // MENUSTATE_HPP

View File

@ -13,7 +13,7 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "menustate.hpp"
#include "loadingstate.hpp"
#include <SFML/Graphics.hpp>
#include <memory>
@ -39,8 +39,8 @@ int debugMode = 0;
sf::Font font;
glm::vec3 viewPosition;
glm::vec2 viewAngles;
glm::vec3 viewPosition { -200.f, -100.f, 45.f };
glm::vec2 viewAngles { -0.90f, 0.2f };
void setViewParameters(const glm::vec3 &center, const glm::vec2 &angles)
{
@ -293,23 +293,6 @@ void init(std::string gtapath, bool loadWorld)
// Set time to noon.
gta->gameTime = 12.f * 60.f;
// Loade all of the IDEs.
for(std::map<std::string, std::string>::iterator it = gta->gameData.ideLocations.begin();
it != gta->gameData.ideLocations.end();
++it) {
gta->defineItems(it->second);
}
if(loadWorld) {
// Load IPLs
for(std::map<std::string, std::string>::iterator it = gta->gameData.iplLocations.begin();
it != gta->gameData.iplLocations.end();
++it) {
gta->loadZone(it->second);
gta->placeItems(it->second);
}
}
debugDrawer = new DebugDraw;
debugDrawer->setShaderProgram(gta->renderer.worldProgram);
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
@ -361,6 +344,8 @@ void update(float dt)
void render(float alpha)
{
gta->_work->update();
// Update aspect ratio..
gta->renderer.camera.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
@ -491,9 +476,7 @@ int main(int argc, char *argv[])
sf::Clock clock;
MenuState* menuState = new MenuState();
StateManager::get().enter(menuState);
StateManager::get().enter(new LoadingState);
float accum = 0.f;
float ts = 1.f / 60.f;

View File

@ -1,7 +1,7 @@
#include "DFFFramesTreeModel.hpp"
#include <render/Model.hpp>
DFFFramesTreeModel::DFFFramesTreeModel(Model* m, QObject* parent)
DFFFramesTreeModel::DFFFramesTreeModel(ModelHandle *m, QObject* parent)
: QAbstractItemModel(parent), model(m)
{
@ -29,7 +29,7 @@ int DFFFramesTreeModel::rowCount(const QModelIndex& parent) const
QModelIndex DFFFramesTreeModel::index(int row, int column, const QModelIndex& parent) const
{
if(parent.row() == -1 && parent.column() == -1) {
return createIndex(row, column, model->frames[model->rootFrameIdx]);
return createIndex(row, column, model->model->frames[model->model->rootFrameIdx]);
}
ModelFrame* f = static_cast<ModelFrame*>(parent.internalPointer());
ModelFrame* p = f->getChildren()[row];

View File

@ -2,14 +2,14 @@
#ifndef _DFFFRAMESTREEMODEL_HPP_
#define _DFFFRAMESTREEMODEL_HPP_
#include <QAbstractItemModel>
#include <engine/GTATypes.hpp>
class Model;
class DFFFramesTreeModel : public QAbstractItemModel
{
Model* model;
ModelHandle* model;
public:
explicit DFFFramesTreeModel(Model* m, QObject* parent = 0);
explicit DFFFramesTreeModel(ModelHandle* m, QObject* parent = 0);
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
@ -24,4 +24,4 @@ public:
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};
#endif
#endif

View File

@ -8,7 +8,7 @@ ModelFramesWidget::ModelFramesWidget(QWidget* parent, Qt::WindowFlags flags)
setWidget(tree);
}
void ModelFramesWidget::setModel(Model* model)
void ModelFramesWidget::setModel(ModelHandle *model)
{
if(framemodel) {
delete framemodel;

View File

@ -4,20 +4,20 @@
#include <QDockWidget>
#include <QTreeView>
#include "DFFFramesTreeModel.hpp"
#include <engine/GTATypes.hpp>
class Model;
class ModelFramesWidget : public QDockWidget
{
Q_OBJECT
Model* gmodel;
ModelHandle* gmodel;
DFFFramesTreeModel* framemodel;
QTreeView* tree;
public:
ModelFramesWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0);
void setModel(Model* model);
void setModel(ModelHandle* model);
};
#endif
#endif

View File

@ -71,7 +71,7 @@ void ViewerWidget::paintGL()
glUniformMatrix4fv(r.uniView, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(r.uniProj, 1, GL_FALSE, glm::value_ptr(proj));
gworld->renderer.renderModel(cmodel, m, dummyObject);
gworld->renderer.renderModel(cmodel->model, m, dummyObject);
}
}
@ -108,7 +108,7 @@ void ViewerWidget::showDFF(const QString& file)
dummyObject = new GameObject(gworld, glm::vec3(), glm::quat(), cmodel);
float radius = 0.f;
for(auto& g
: cmodel->geometries) {
: cmodel->model->geometries) {
radius = std::max(
radius,
glm::length(g->geometryBounds.center)+g->geometryBounds.radius);
@ -130,13 +130,13 @@ void ViewerWidget::showAnimation(Animation *anim)
if(dummyObject) {
if(dummyObject->animator == nullptr) {
dummyObject->animator = new Animator;
dummyObject->animator->setModel(dummyObject->model);
dummyObject->animator->setModel(dummyObject->model->model);
}
dummyObject->animator->setAnimation(canimation);
}
}
Model* ViewerWidget::currentModel() const
ModelHandle* ViewerWidget::currentModel() const
{
return cmodel;
}

View File

@ -19,7 +19,7 @@ class ViewerWidget : public QGLWidget
GameObject* dummyObject;
Model* cmodel;
ModelHandle* cmodel;
Animation* canimation;
float viewDistance;
@ -44,7 +44,7 @@ public:
FileMode fileMode() const;
Model* currentModel() const;
ModelHandle *currentModel() const;
GameWorld* world();

View File

@ -12,7 +12,7 @@ BOOST_AUTO_TEST_CASE(test_matrix)
Animator animator;
Global::get().e->gameData.loadDFF("player.dff");
Model* test_model = Global::get().e->gameData.models["player"];
ModelHandle* test_model = Global::get().e->gameData.models["player"];
BOOST_REQUIRE( test_model );
@ -34,16 +34,16 @@ BOOST_AUTO_TEST_CASE(test_matrix)
};
animator.setAnimation(&animation);
animator.setModel( test_model );
animator.setModel( test_model->model );
{
auto intp_matrix = animator.getFrameMatrixAt( test_model->frames[0], 0.0f );
auto intp_matrix = animator.getFrameMatrixAt( test_model->model->frames[0], 0.0f );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.f, 0.f)), 0.0f );
}
{
auto intp_matrix = animator.getFrameMatrixAt( test_model->frames[0], 0.5f );
auto intp_matrix = animator.getFrameMatrixAt( test_model->model->frames[0], 0.5f );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( 0.0f, glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.5f, 0.0f)) );
}
@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
Animator animator;
Global::get().e->gameData.loadDFF("player.dff");
Model* test_model = Global::get().e->gameData.models["player"];
ModelHandle* test_model = Global::get().e->gameData.models["player"];
BOOST_REQUIRE( test_model );
@ -82,10 +82,10 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
};
animator.setAnimation(&animation);
animator.setModel( test_model );
animator.setModel( test_model->model );
{
auto intp_matrix = animator.getFrameMatrix( test_model->frames[0] );
auto intp_matrix = animator.getFrameMatrix( test_model->model->frames[0] );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.f, 0.f)), 0.0f );
}
@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
animator.tick( 1.f );
{
auto intp_matrix = animator.getFrameMatrix( test_model->frames[0], 0.5f );
auto intp_matrix = animator.getFrameMatrix( test_model->model->frames[0], 0.5f );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( 0.0f, glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.5f, 0.0f)) );
}
@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
animator.tick( 1.f );
{
auto intp_matrix = animator.getFrameMatrix( test_model->frames[0], 0.5f );
auto intp_matrix = animator.getFrameMatrix( test_model->model->frames[0], 0.5f );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( 0.0f, glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 1.5f, 0.0f)) );
}
@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
animator.tick( 1.f );
{
auto intp_matrix = animator.getFrameMatrix( test_model->frames[0], 0.5f );
auto intp_matrix = animator.getFrameMatrix( test_model->model->frames[0], 0.5f );
auto intp_col = intp_matrix[3];
BOOST_CHECK_EQUAL( 0.0f, glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.5f, 0.0f)) );
}

View File

@ -58,6 +58,7 @@ BOOST_AUTO_TEST_CASE(test_activities)
{
GTAVehicle* vehicle = Global::get().e->createVehicle(90u, glm::vec3(10.f, 0.f, 0.f), glm::quat());
BOOST_REQUIRE(vehicle != nullptr);
BOOST_REQUIRE(vehicle->model != nullptr);
auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f});

View File

@ -50,6 +50,10 @@ public:
}
e->dynamicsWorld->setGravity(btVector3(0.f, 0.f, 0.f));
while( ! e->_work->isEmpty() ) {
std::this_thread::yield();
}
}
~Global() {

View File

@ -7,12 +7,8 @@ BOOST_AUTO_TEST_SUITE(LoaderDFFTests)
BOOST_AUTO_TEST_CASE(test_open_dff)
{
LoaderIMG archive;
BOOST_REQUIRE( archive.load(Global::getGamePath() + "/models/gta3") );
{
auto d = archive.loadToMemory("landstal.dff");
auto d = Global::get().e->gameData.openFile("landstal.dff");
LoaderDFF loader;
@ -29,16 +25,12 @@ BOOST_AUTO_TEST_CASE(test_open_dff)
BOOST_AUTO_TEST_CASE(test_modeljob)
{
LoaderIMG archive;
BOOST_REQUIRE( archive.load(Global::getGamePath() + "/models/gta3") );
{
WorkContext ctx;
Model* m = nullptr;
bool done = false;
LoadModelJob* lmj = new LoadModelJob(&ctx, &Global::get().e->gameData, archive, "landstal.dff",
LoadModelJob* lmj = new LoadModelJob(&ctx, &Global::get().e->gameData, "landstal.dff",
[&](Model* model) { m = model; done = true; });
ctx.queueJob(lmj);

View File

@ -31,8 +31,8 @@ BOOST_AUTO_TEST_CASE(vehicle_frame_flags)
BOOST_REQUIRE(vehicle != nullptr);
BOOST_REQUIRE(vehicle->model != nullptr);
auto bonnet_ok = vehicle->model->findFrame("bonnet_hi_ok");
auto bonnet_dam = vehicle->model->findFrame("bonnet_hi_dam");
auto bonnet_ok = vehicle->model->model->findFrame("bonnet_hi_ok");
auto bonnet_dam = vehicle->model->model->findFrame("bonnet_hi_dam");
BOOST_REQUIRE(bonnet_ok != nullptr);
BOOST_REQUIRE(bonnet_dam != nullptr);