mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Threaded model and texture loading
This commit is contained in:
parent
f24ceeb42f
commit
61931145fe
@ -52,6 +52,9 @@ public:
|
|||||||
virtual void complete() {}
|
virtual void complete() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: refactor everything to remove this.
|
||||||
|
class GameWorld;
|
||||||
|
|
||||||
class WorkContext
|
class WorkContext
|
||||||
{
|
{
|
||||||
std::queue<WorkJob*> _workQueue;
|
std::queue<WorkJob*> _workQueue;
|
||||||
@ -62,10 +65,12 @@ class WorkContext
|
|||||||
std::mutex _inMutex;
|
std::mutex _inMutex;
|
||||||
std::mutex _outMutex;
|
std::mutex _outMutex;
|
||||||
|
|
||||||
|
GameWorld* _world;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WorkContext()
|
WorkContext(GameWorld* world = nullptr)
|
||||||
: _worker(this) { }
|
: _worker(this), _world(world) { }
|
||||||
|
|
||||||
void queueJob( WorkJob* job )
|
void queueJob( WorkJob* job )
|
||||||
{
|
{
|
||||||
@ -79,6 +84,15 @@ public:
|
|||||||
const std::queue<WorkJob*> getWorkQueue() const { return _workQueue; }
|
const std::queue<WorkJob*> getWorkQueue() const { return _workQueue; }
|
||||||
const std::queue<WorkJob*> getCompleteQueue() const { return _completeQueue; }
|
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();
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,16 @@ class Animation;
|
|||||||
|
|
||||||
typedef std::map<std::string, Animation*> AnimationSet;
|
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
|
namespace GTATypes
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -46,7 +56,6 @@ struct WaterRect
|
|||||||
float xLeft, yBottom;
|
float xLeft, yBottom;
|
||||||
float xRight, yTop;
|
float xRight, yTop;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
struct GTAFile
|
struct GTAFile
|
||||||
{
|
{
|
||||||
bool archived; /// Is the file inside an IMG or on the filesystem?
|
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
|
* 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
|
* 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
|
* Loads an IFP file containing animations
|
||||||
@ -131,10 +131,18 @@ public:
|
|||||||
void loadDynamicObjects(const std::string& name);
|
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
|
* @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);
|
char* loadFile(const std::string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,9 +165,9 @@ public:
|
|||||||
std::map<std::string, std::string> ideLocations;
|
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
|
* Map of loaded archives
|
||||||
@ -194,7 +202,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Loaded models
|
* Loaded models
|
||||||
*/
|
*/
|
||||||
std::map<std::string, Model*> models;
|
std::map<std::string, ModelHandle*> models;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loaded Textures and their atlas entries.
|
* Loaded Textures and their atlas entries.
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class GTAAIController;
|
class GTAAIController;
|
||||||
class Model;
|
|
||||||
class ModelFrame;
|
class ModelFrame;
|
||||||
class Animator;
|
class Animator;
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ struct GameObject
|
|||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
|
|
||||||
Model* model; /// Cached pointer to Object's Model.
|
ModelHandle* model; /// Cached pointer to Object's Model.
|
||||||
|
|
||||||
GameWorld* engine;
|
GameWorld* engine;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ struct GameObject
|
|||||||
*/
|
*/
|
||||||
float mHealth;
|
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)
|
: position(pos), rotation(rot), model(model), engine(engine), animator(nullptr), mHealth(0.f)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <ai/GTAAINode.hpp>
|
#include <ai/GTAAINode.hpp>
|
||||||
#include <ai/AIGraph.hpp>
|
#include <ai/AIGraph.hpp>
|
||||||
|
|
||||||
|
class WorkContext;
|
||||||
|
|
||||||
class GameObject;
|
class GameObject;
|
||||||
class GTACharacter;
|
class GTACharacter;
|
||||||
class GTAInstance;
|
class GTAInstance;
|
||||||
@ -32,6 +34,8 @@ public:
|
|||||||
|
|
||||||
GameWorld(const std::string& gamepath);
|
GameWorld(const std::string& gamepath);
|
||||||
|
|
||||||
|
~GameWorld();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the game data
|
* Loads the game data
|
||||||
*/
|
*/
|
||||||
@ -192,6 +196,10 @@ public:
|
|||||||
btSequentialImpulseConstraintSolver* solver;
|
btSequentialImpulseConstraintSolver* solver;
|
||||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
btDiscreteDynamicsWorld* dynamicsWorld;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work related
|
||||||
|
*/
|
||||||
|
WorkContext* _work;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,8 +27,6 @@ public:
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class LoaderIMG;
|
|
||||||
|
|
||||||
class LoadModelJob : public WorkJob
|
class LoadModelJob : public WorkJob
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -36,13 +34,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GameData* _gameData;
|
GameData* _gameData;
|
||||||
LoaderIMG* _archive;
|
|
||||||
std::string _file;
|
std::string _file;
|
||||||
ModelCallback _callback;
|
ModelCallback _callback;
|
||||||
char* _data;
|
char* _data;
|
||||||
public:
|
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();
|
void work();
|
||||||
|
|
||||||
|
@ -19,4 +19,23 @@ public:
|
|||||||
bool loadFromMemory(char *data, GameData* gameData);
|
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
|
#endif
|
||||||
|
@ -90,7 +90,7 @@ public:
|
|||||||
* @param model
|
* @param model
|
||||||
* @param ped PEDS_t struct to use.
|
* @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();
|
~GTACharacter();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ struct GTAInstance : public GameObject
|
|||||||
GameWorld* engine,
|
GameWorld* engine,
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::quat& rot,
|
const glm::quat& rot,
|
||||||
Model* model,
|
ModelHandle* model,
|
||||||
const glm::vec3& scale,
|
const glm::vec3& scale,
|
||||||
std::shared_ptr<ObjectData> obj,
|
std::shared_ptr<ObjectData> obj,
|
||||||
std::shared_ptr<GTAInstance> lod
|
std::shared_ptr<GTAInstance> lod
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
GTAVehicle(GameWorld* engine,
|
GTAVehicle(GameWorld* engine,
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::quat& rot,
|
const glm::quat& rot,
|
||||||
Model* model,
|
ModelHandle* model,
|
||||||
VehicleDataHandle data,
|
VehicleDataHandle data,
|
||||||
VehicleInfoHandle info,
|
VehicleInfoHandle info,
|
||||||
const glm::vec3& prim,
|
const glm::vec3& prim,
|
||||||
|
@ -82,9 +82,9 @@ void GameData::load()
|
|||||||
parseDAT(datpath+"/data/default.dat");
|
parseDAT(datpath+"/data/default.dat");
|
||||||
parseDAT(datpath+"/data/gta3.dat");
|
parseDAT(datpath+"/data/gta3.dat");
|
||||||
|
|
||||||
fileLocations.insert({"wheels.DFF", {false, datpath+"/models/Generic/wheels.DFF"}});
|
_knownFiles.insert({"wheels.DFF", {false, datpath+"/models/Generic/wheels.DFF"}});
|
||||||
fileLocations.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
|
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
|
||||||
fileLocations.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
|
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
|
||||||
loadDFF("wheels.DFF");
|
loadDFF("wheels.DFF");
|
||||||
loadTXD("particle.txd");
|
loadTXD("particle.txd");
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ void GameData::parseDAT(const std::string& path)
|
|||||||
}
|
}
|
||||||
texpath = findPathRealCase(datpath, texpath);
|
texpath = findPathRealCase(datpath, texpath);
|
||||||
std::string texname = texpath.substr(texpath.find_last_of("/")+1);
|
std::string texname = texpath.substr(texpath.find_last_of("/")+1);
|
||||||
fileLocations.insert({ texname, { false, texpath }});
|
_knownFiles.insert({ texname, { false, texpath }});
|
||||||
loadTXD(texname);
|
loadTXD(texname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,12 +201,12 @@ void GameData::loadIMG(const std::string& name)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Enter the asset twice..
|
// Enter the asset twice..
|
||||||
fileLocations.insert({ filename, { true, archivePath }});
|
_knownFiles.insert({ filename, { true, archivePath }});
|
||||||
for(size_t t = 0; t < filename.size(); ++t)
|
for(size_t t = 0; t < filename.size(); ++t)
|
||||||
{
|
{
|
||||||
filename[t] = tolower(filename[t]);
|
filename[t] = tolower(filename[t]);
|
||||||
}
|
}
|
||||||
fileLocations.insert({ filename, { true, archivePath }});
|
_knownFiles.insert({ filename, { true, archivePath }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
archives.insert({archivePath, imgLoader});
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* file = loadFile(name);
|
loadedFiles[name] = true;
|
||||||
if(file) {
|
|
||||||
textureLoader.loadFromMemory(file, this);
|
auto j = new LoadTextureArchiveJob(this->engine->_work, this, name);
|
||||||
delete[] file;
|
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *file = loadFile(name);
|
// Before starting the job make sure the file isn't loaded again.
|
||||||
if(file)
|
loadedFiles.insert({name, true});
|
||||||
{
|
|
||||||
LoaderDFF dffLoader;
|
models[realname] = new ModelHandle(realname);
|
||||||
models[name.substr(0, name.size() - 4)] = dffLoader.loadFromMemory(file, this);
|
|
||||||
delete[] file;
|
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)
|
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()) {
|
auto i = _knownFiles.find(name);
|
||||||
std::cerr << "File " << name << " already loaded!" << std::endl;
|
if(i != _knownFiles.end())
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto i = fileLocations.find(name);
|
|
||||||
if(i != fileLocations.end())
|
|
||||||
{
|
{
|
||||||
if(i->second.archived)
|
if(i->second.archived)
|
||||||
{
|
{
|
||||||
@ -487,7 +504,6 @@ char* GameData::loadFile(const std::string& name)
|
|||||||
auto ai = archives.find(i->second.path);
|
auto ai = archives.find(i->second.path);
|
||||||
if(ai != archives.end())
|
if(ai != archives.end())
|
||||||
{
|
{
|
||||||
loadedFiles[name] = true;
|
|
||||||
return ai->second.loadToMemory(name);
|
return ai->second.loadToMemory(name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -509,8 +525,6 @@ char* GameData::loadFile(const std::string& name)
|
|||||||
char *data = new char[length];
|
char *data = new char[length];
|
||||||
dfile.read(data, length);
|
dfile.read(data, length);
|
||||||
|
|
||||||
loadedFiles[name] = true;
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,6 +539,18 @@ char* GameData::loadFile(const std::string& name)
|
|||||||
return nullptr;
|
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)
|
TextureAtlas* GameData::getAtlas(size_t i)
|
||||||
{
|
{
|
||||||
if( i < atlases.size() ) {
|
if( i < atlases.size() ) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <ai/GTADefaultAIController.hpp>
|
#include <ai/GTADefaultAIController.hpp>
|
||||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||||
#include <render/Model.hpp>
|
#include <render/Model.hpp>
|
||||||
|
#include <WorkContext.hpp>
|
||||||
|
|
||||||
// 3 isn't enough to cause a factory.
|
// 3 isn't enough to cause a factory.
|
||||||
#include <objects/GTACharacter.hpp>
|
#include <objects/GTACharacter.hpp>
|
||||||
@ -11,11 +12,18 @@
|
|||||||
#include <objects/GTAVehicle.hpp>
|
#include <objects/GTAVehicle.hpp>
|
||||||
|
|
||||||
GameWorld::GameWorld(const std::string& path)
|
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;
|
gameData.engine = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameWorld::~GameWorld()
|
||||||
|
{
|
||||||
|
delete _work;
|
||||||
|
// TODO: delete other things.
|
||||||
|
}
|
||||||
|
|
||||||
bool GameWorld::load()
|
bool GameWorld::load()
|
||||||
{
|
{
|
||||||
collisionConfig = new btDefaultCollisionConfiguration;
|
collisionConfig = new btDefaultCollisionConfiguration;
|
||||||
@ -174,10 +182,10 @@ GTAInstance *GameWorld::createInstance(const uint16_t id, const glm::vec3& pos,
|
|||||||
if( oi != objectTypes.end()) {
|
if( oi != objectTypes.end()) {
|
||||||
// Make sure the DFF and TXD are loaded
|
// Make sure the DFF and TXD are loaded
|
||||||
if(! oi->second->modelName.empty()) {
|
if(! oi->second->modelName.empty()) {
|
||||||
gameData.loadDFF(oi->second->modelName + ".dff");
|
gameData.loadDFF(oi->second->modelName + ".dff", true);
|
||||||
}
|
}
|
||||||
if(! oi->second->textureName.empty()) {
|
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(
|
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);
|
auto info = gameData.vehicleInfo.find(vti->second->handlingID);
|
||||||
if(model && info != gameData.vehicleInfo.end()) {
|
if(model && info != gameData.vehicleInfo.end()) {
|
||||||
if( info->second->wheels.size() == 0 && info->second->seats.size() == 0 ) {
|
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 vehicleInstances.back();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -280,10 +289,10 @@ GTACharacter* GameWorld::createPedestrian(const uint16_t id, const glm::vec3 &po
|
|||||||
gameData.loadTXD(pt->textureName + ".txd");
|
gameData.loadTXD(pt->textureName + ".txd");
|
||||||
}
|
}
|
||||||
|
|
||||||
Model* model = gameData.models[pt->modelName];
|
ModelHandle* m = gameData.models[pt->modelName];
|
||||||
|
|
||||||
if(model != nullptr) {
|
if(m != nullptr) {
|
||||||
auto ped = new GTACharacter( this, pos, rot, model, pt );
|
auto ped = new GTACharacter( this, pos, rot, m, pt );
|
||||||
pedestrians.push_back(ped);
|
pedestrians.push_back(ped);
|
||||||
new GTADefaultAIController(ped);
|
new GTADefaultAIController(ped);
|
||||||
return ped;
|
return ped;
|
||||||
|
@ -312,25 +312,28 @@ RW::BSSectionHeader LoaderDFF::readHeader(char *data, size_t &dataI)
|
|||||||
return readStructure<RW::BSSectionHeader>(data, dataI);
|
return readStructure<RW::BSSectionHeader>(data, dataI);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <loaders/LoaderIMG.hpp>
|
LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, const std::string &file, ModelCallback cb)
|
||||||
|
: WorkJob(context), _gameData(gd), _file(file), _callback(cb), _data(nullptr)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadModelJob::work()
|
void LoadModelJob::work()
|
||||||
{
|
{
|
||||||
_data = _archive->loadToMemory(_file);
|
_data = _gameData->openFile(_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadModelJob::complete()
|
void LoadModelJob::complete()
|
||||||
{
|
{
|
||||||
|
Model* m = nullptr;
|
||||||
|
// TODO error status
|
||||||
|
if( _data ) {
|
||||||
|
|
||||||
// TODO allow some of the loading to process in a seperate thread.
|
// TODO allow some of the loading to process in a seperate thread.
|
||||||
LoaderDFF loader;
|
LoaderDFF loader;
|
||||||
|
|
||||||
Model* m = loader.loadFromMemory(_data, _gameData);
|
m = loader.loadFromMemory(_data, _gameData);
|
||||||
|
}
|
||||||
|
|
||||||
_callback(m);
|
_callback(m);
|
||||||
|
|
||||||
|
@ -217,3 +217,26 @@ bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
|
|||||||
|
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// TODO: make this not hardcoded
|
// TODO: make this not hardcoded
|
||||||
static glm::vec3 enter_offset(0.81756252f, 0.34800607f, -0.486281008f);
|
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),
|
: GameObject(engine, pos, rot, model),
|
||||||
currentVehicle(nullptr), currentSeat(0),
|
currentVehicle(nullptr), currentSeat(0),
|
||||||
_hasTargetPosition(false),
|
_hasTargetPosition(false),
|
||||||
@ -35,7 +35,7 @@ GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::q
|
|||||||
|
|
||||||
if(model) {
|
if(model) {
|
||||||
animator = new Animator();
|
animator = new Animator();
|
||||||
animator->setModel(model);
|
animator->setModel(model->model);
|
||||||
|
|
||||||
createActor();
|
createActor();
|
||||||
enterAction(Idle);
|
enterAction(Idle);
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
#include <engine/GameWorld.hpp>
|
#include <engine/GameWorld.hpp>
|
||||||
#include <data/CollisionModel.hpp>
|
#include <data/CollisionModel.hpp>
|
||||||
|
|
||||||
GTAInstance::GTAInstance(
|
GTAInstance::GTAInstance(GameWorld* engine,
|
||||||
GameWorld* engine,
|
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::quat& rot,
|
const glm::quat& rot,
|
||||||
Model* model,
|
ModelHandle *model,
|
||||||
const glm::vec3& scale,
|
const glm::vec3& scale,
|
||||||
std::shared_ptr<ObjectData> obj,
|
std::shared_ptr<ObjectData> obj,
|
||||||
std::shared_ptr<GTAInstance> lod
|
std::shared_ptr<GTAInstance> lod
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <data/CollisionModel.hpp>
|
#include <data/CollisionModel.hpp>
|
||||||
#include <render/Model.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),
|
: GameObject(engine, pos, rot, model),
|
||||||
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false),
|
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false),
|
||||||
damageFlags(0), vehicle(data), info(info), colourPrimary(prim),
|
damageFlags(0), vehicle(data), info(info), colourPrimary(prim),
|
||||||
|
@ -268,9 +268,9 @@ void GTARenderer::renderWorld(float alpha)
|
|||||||
matrixModel = glm::translate(matrixModel, charac->getPosition());
|
matrixModel = glm::translate(matrixModel, charac->getPosition());
|
||||||
matrixModel = matrixModel * glm::mat4_cast(charac->getRotation());
|
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) {
|
for(size_t i = 0; i < engine->objectInstances.size(); ++i) {
|
||||||
@ -284,9 +284,9 @@ void GTARenderer::renderWorld(float alpha)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!inst.model)
|
if(!inst.model->model)
|
||||||
{
|
{
|
||||||
std::cout << "model " << inst.model << " not loaded (" << engine->gameData.models.size() << " models loaded)" << std::endl;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 matrixModel;
|
glm::mat4 matrixModel;
|
||||||
@ -295,9 +295,9 @@ void GTARenderer::renderWorld(float alpha)
|
|||||||
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
|
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
|
||||||
|
|
||||||
float mindist = 100000.f;
|
float mindist = 100000.f;
|
||||||
for (size_t g = 0; g < inst.model->geometries.size(); g++)
|
for (size_t g = 0; g < inst.model->model->geometries.size(); g++)
|
||||||
{
|
{
|
||||||
RW::BSGeometryBounds& bounds = inst.model->geometries[g]->geometryBounds;
|
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);
|
mindist = std::min(mindist, glm::length((glm::vec3(matrixModel[3])+bounds.center) - camera.worldPos) - bounds.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,13 +311,13 @@ void GTARenderer::renderWorld(float alpha)
|
|||||||
culled++;
|
culled++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else if (inst.LODinstance->model->model) {
|
||||||
renderModel(inst.LODinstance->model, matrixModel);
|
renderModel(inst.LODinstance->model->model, matrixModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (! inst.object->LOD ) {
|
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 = glm::translate(matrixModel, inst->getPosition());
|
||||||
matrixModel = matrixModel * glm::mat4_cast(inst->getRotation());
|
matrixModel = matrixModel * glm::mat4_cast(inst->getRotation());
|
||||||
|
|
||||||
renderModel(inst->model, matrixModel, inst);
|
renderModel(inst->model->model, matrixModel, inst);
|
||||||
|
|
||||||
// Draw wheels n' stuff
|
// Draw wheels n' stuff
|
||||||
for( size_t w = 0; w < inst->info->wheels.size(); ++w) {
|
for( size_t w = 0; w < inst->info->wheels.size(); ++w) {
|
||||||
auto woi = engine->objectTypes.find(inst->vehicle->wheelModelID);
|
auto woi = engine->objectTypes.find(inst->vehicle->wheelModelID);
|
||||||
if(woi != engine->objectTypes.end()) {
|
if(woi != engine->objectTypes.end()) {
|
||||||
Model* wheelModel = engine->gameData.models["wheels"];
|
Model* wheelModel = engine->gameData.models["wheels"]->model;
|
||||||
if( wheelModel) {
|
if( wheelModel) {
|
||||||
// Tell bullet to update the matrix for this wheel.
|
// Tell bullet to update the matrix for this wheel.
|
||||||
inst->physVehicle->updateWheelTransform(w, false);
|
inst->physVehicle->updateWheelTransform(w, false);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
add_executable(rwgame
|
add_executable(rwgame
|
||||||
main.cpp
|
main.cpp
|
||||||
|
loadingstate.cpp
|
||||||
ingamestate.cpp
|
ingamestate.cpp
|
||||||
pausestate.cpp
|
pausestate.cpp
|
||||||
menustate.cpp
|
menustate.cpp
|
||||||
|
@ -120,6 +120,12 @@ struct StateManager
|
|||||||
state->enter();
|
state->enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exec(State* state)
|
||||||
|
{
|
||||||
|
exit();
|
||||||
|
enter(state);
|
||||||
|
}
|
||||||
|
|
||||||
void tick(float dt)
|
void tick(float dt)
|
||||||
{
|
{
|
||||||
states.back()->tick(dt);
|
states.back()->tick(dt);
|
||||||
|
@ -67,7 +67,7 @@ void IngameState::tick(float dt)
|
|||||||
float viewDistance = 2.f;
|
float viewDistance = 2.f;
|
||||||
if( _playerCharacter->getCurrentVehicle() ) {
|
if( _playerCharacter->getCurrentVehicle() ) {
|
||||||
auto model = _playerCharacter->getCurrentVehicle()->model;
|
auto model = _playerCharacter->getCurrentVehicle()->model;
|
||||||
for(auto& g : model->geometries) {
|
for(auto& g : model->model->geometries) {
|
||||||
viewDistance = std::max(
|
viewDistance = std::max(
|
||||||
(glm::length(g->geometryBounds.center) + g->geometryBounds.radius) * 1.5f,
|
(glm::length(g->geometryBounds.center) + g->geometryBounds.radius) * 1.5f,
|
||||||
viewDistance);
|
viewDistance);
|
||||||
|
55
rwgame/loadingstate.cpp
Normal file
55
rwgame/loadingstate.cpp
Normal 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
21
rwgame/loadingstate.hpp
Normal 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
|
@ -13,7 +13,7 @@
|
|||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include "menustate.hpp"
|
#include "loadingstate.hpp"
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -39,8 +39,8 @@ int debugMode = 0;
|
|||||||
|
|
||||||
sf::Font font;
|
sf::Font font;
|
||||||
|
|
||||||
glm::vec3 viewPosition;
|
glm::vec3 viewPosition { -200.f, -100.f, 45.f };
|
||||||
glm::vec2 viewAngles;
|
glm::vec2 viewAngles { -0.90f, 0.2f };
|
||||||
|
|
||||||
void setViewParameters(const glm::vec3 ¢er, const glm::vec2 &angles)
|
void setViewParameters(const glm::vec3 ¢er, const glm::vec2 &angles)
|
||||||
{
|
{
|
||||||
@ -293,23 +293,6 @@ void init(std::string gtapath, bool loadWorld)
|
|||||||
// Set time to noon.
|
// Set time to noon.
|
||||||
gta->gameTime = 12.f * 60.f;
|
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 = new DebugDraw;
|
||||||
debugDrawer->setShaderProgram(gta->renderer.worldProgram);
|
debugDrawer->setShaderProgram(gta->renderer.worldProgram);
|
||||||
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||||
@ -361,6 +344,8 @@ void update(float dt)
|
|||||||
|
|
||||||
void render(float alpha)
|
void render(float alpha)
|
||||||
{
|
{
|
||||||
|
gta->_work->update();
|
||||||
|
|
||||||
// Update aspect ratio..
|
// Update aspect ratio..
|
||||||
gta->renderer.camera.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
|
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;
|
sf::Clock clock;
|
||||||
|
|
||||||
MenuState* menuState = new MenuState();
|
StateManager::get().enter(new LoadingState);
|
||||||
|
|
||||||
StateManager::get().enter(menuState);
|
|
||||||
|
|
||||||
float accum = 0.f;
|
float accum = 0.f;
|
||||||
float ts = 1.f / 60.f;
|
float ts = 1.f / 60.f;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "DFFFramesTreeModel.hpp"
|
#include "DFFFramesTreeModel.hpp"
|
||||||
#include <render/Model.hpp>
|
#include <render/Model.hpp>
|
||||||
|
|
||||||
DFFFramesTreeModel::DFFFramesTreeModel(Model* m, QObject* parent)
|
DFFFramesTreeModel::DFFFramesTreeModel(ModelHandle *m, QObject* parent)
|
||||||
: QAbstractItemModel(parent), model(m)
|
: 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
|
QModelIndex DFFFramesTreeModel::index(int row, int column, const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
if(parent.row() == -1 && parent.column() == -1) {
|
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* f = static_cast<ModelFrame*>(parent.internalPointer());
|
||||||
ModelFrame* p = f->getChildren()[row];
|
ModelFrame* p = f->getChildren()[row];
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
#ifndef _DFFFRAMESTREEMODEL_HPP_
|
#ifndef _DFFFRAMESTREEMODEL_HPP_
|
||||||
#define _DFFFRAMESTREEMODEL_HPP_
|
#define _DFFFRAMESTREEMODEL_HPP_
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
#include <engine/GTATypes.hpp>
|
||||||
|
|
||||||
class Model;
|
|
||||||
class DFFFramesTreeModel : public QAbstractItemModel
|
class DFFFramesTreeModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Model* model;
|
ModelHandle* model;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit DFFFramesTreeModel(Model* m, QObject* parent = 0);
|
explicit DFFFramesTreeModel(ModelHandle* m, QObject* parent = 0);
|
||||||
|
|
||||||
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ ModelFramesWidget::ModelFramesWidget(QWidget* parent, Qt::WindowFlags flags)
|
|||||||
setWidget(tree);
|
setWidget(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelFramesWidget::setModel(Model* model)
|
void ModelFramesWidget::setModel(ModelHandle *model)
|
||||||
{
|
{
|
||||||
if(framemodel) {
|
if(framemodel) {
|
||||||
delete framemodel;
|
delete framemodel;
|
||||||
|
@ -4,20 +4,20 @@
|
|||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include "DFFFramesTreeModel.hpp"
|
#include "DFFFramesTreeModel.hpp"
|
||||||
|
#include <engine/GTATypes.hpp>
|
||||||
|
|
||||||
class Model;
|
|
||||||
class ModelFramesWidget : public QDockWidget
|
class ModelFramesWidget : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Model* gmodel;
|
ModelHandle* gmodel;
|
||||||
DFFFramesTreeModel* framemodel;
|
DFFFramesTreeModel* framemodel;
|
||||||
QTreeView* tree;
|
QTreeView* tree;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ModelFramesWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0);
|
ModelFramesWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0);
|
||||||
|
|
||||||
void setModel(Model* model);
|
void setModel(ModelHandle* model);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -71,7 +71,7 @@ void ViewerWidget::paintGL()
|
|||||||
glUniformMatrix4fv(r.uniView, 1, GL_FALSE, glm::value_ptr(view));
|
glUniformMatrix4fv(r.uniView, 1, GL_FALSE, glm::value_ptr(view));
|
||||||
glUniformMatrix4fv(r.uniProj, 1, GL_FALSE, glm::value_ptr(proj));
|
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);
|
dummyObject = new GameObject(gworld, glm::vec3(), glm::quat(), cmodel);
|
||||||
float radius = 0.f;
|
float radius = 0.f;
|
||||||
for(auto& g
|
for(auto& g
|
||||||
: cmodel->geometries) {
|
: cmodel->model->geometries) {
|
||||||
radius = std::max(
|
radius = std::max(
|
||||||
radius,
|
radius,
|
||||||
glm::length(g->geometryBounds.center)+g->geometryBounds.radius);
|
glm::length(g->geometryBounds.center)+g->geometryBounds.radius);
|
||||||
@ -130,13 +130,13 @@ void ViewerWidget::showAnimation(Animation *anim)
|
|||||||
if(dummyObject) {
|
if(dummyObject) {
|
||||||
if(dummyObject->animator == nullptr) {
|
if(dummyObject->animator == nullptr) {
|
||||||
dummyObject->animator = new Animator;
|
dummyObject->animator = new Animator;
|
||||||
dummyObject->animator->setModel(dummyObject->model);
|
dummyObject->animator->setModel(dummyObject->model->model);
|
||||||
}
|
}
|
||||||
dummyObject->animator->setAnimation(canimation);
|
dummyObject->animator->setAnimation(canimation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Model* ViewerWidget::currentModel() const
|
ModelHandle* ViewerWidget::currentModel() const
|
||||||
{
|
{
|
||||||
return cmodel;
|
return cmodel;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class ViewerWidget : public QGLWidget
|
|||||||
|
|
||||||
GameObject* dummyObject;
|
GameObject* dummyObject;
|
||||||
|
|
||||||
Model* cmodel;
|
ModelHandle* cmodel;
|
||||||
Animation* canimation;
|
Animation* canimation;
|
||||||
|
|
||||||
float viewDistance;
|
float viewDistance;
|
||||||
@ -44,7 +44,7 @@ public:
|
|||||||
|
|
||||||
FileMode fileMode() const;
|
FileMode fileMode() const;
|
||||||
|
|
||||||
Model* currentModel() const;
|
ModelHandle *currentModel() const;
|
||||||
|
|
||||||
GameWorld* world();
|
GameWorld* world();
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ BOOST_AUTO_TEST_CASE(test_matrix)
|
|||||||
Animator animator;
|
Animator animator;
|
||||||
|
|
||||||
Global::get().e->gameData.loadDFF("player.dff");
|
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 );
|
BOOST_REQUIRE( test_model );
|
||||||
|
|
||||||
@ -34,16 +34,16 @@ BOOST_AUTO_TEST_CASE(test_matrix)
|
|||||||
};
|
};
|
||||||
|
|
||||||
animator.setAnimation(&animation);
|
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];
|
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 );
|
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];
|
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)) );
|
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;
|
Animator animator;
|
||||||
|
|
||||||
Global::get().e->gameData.loadDFF("player.dff");
|
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 );
|
BOOST_REQUIRE( test_model );
|
||||||
|
|
||||||
@ -82,10 +82,10 @@ BOOST_AUTO_TEST_CASE(test_interpolate)
|
|||||||
};
|
};
|
||||||
|
|
||||||
animator.setAnimation(&animation);
|
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];
|
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 );
|
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 );
|
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];
|
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)) );
|
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 );
|
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];
|
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)) );
|
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 );
|
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];
|
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)) );
|
BOOST_CHECK_EQUAL( 0.0f, glm::distance(glm::vec3(intp_col), glm::vec3(0.f, 0.5f, 0.0f)) );
|
||||||
}
|
}
|
||||||
|
@ -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());
|
GTAVehicle* vehicle = Global::get().e->createVehicle(90u, glm::vec3(10.f, 0.f, 0.f), glm::quat());
|
||||||
BOOST_REQUIRE(vehicle != nullptr);
|
BOOST_REQUIRE(vehicle != nullptr);
|
||||||
|
BOOST_REQUIRE(vehicle->model != nullptr);
|
||||||
|
|
||||||
auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f});
|
auto character = Global::get().e->createPedestrian(1, {0.f, 0.f, 0.f});
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
e->dynamicsWorld->setGravity(btVector3(0.f, 0.f, 0.f));
|
e->dynamicsWorld->setGravity(btVector3(0.f, 0.f, 0.f));
|
||||||
|
|
||||||
|
while( ! e->_work->isEmpty() ) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~Global() {
|
~Global() {
|
||||||
|
@ -7,12 +7,8 @@ BOOST_AUTO_TEST_SUITE(LoaderDFFTests)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_open_dff)
|
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;
|
LoaderDFF loader;
|
||||||
|
|
||||||
@ -29,16 +25,12 @@ BOOST_AUTO_TEST_CASE(test_open_dff)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_modeljob)
|
BOOST_AUTO_TEST_CASE(test_modeljob)
|
||||||
{
|
{
|
||||||
LoaderIMG archive;
|
|
||||||
|
|
||||||
BOOST_REQUIRE( archive.load(Global::getGamePath() + "/models/gta3") );
|
|
||||||
|
|
||||||
{
|
{
|
||||||
WorkContext ctx;
|
WorkContext ctx;
|
||||||
|
|
||||||
Model* m = nullptr;
|
Model* m = nullptr;
|
||||||
bool done = false;
|
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; });
|
[&](Model* model) { m = model; done = true; });
|
||||||
|
|
||||||
ctx.queueJob(lmj);
|
ctx.queueJob(lmj);
|
||||||
|
@ -31,8 +31,8 @@ BOOST_AUTO_TEST_CASE(vehicle_frame_flags)
|
|||||||
BOOST_REQUIRE(vehicle != nullptr);
|
BOOST_REQUIRE(vehicle != nullptr);
|
||||||
BOOST_REQUIRE(vehicle->model != nullptr);
|
BOOST_REQUIRE(vehicle->model != nullptr);
|
||||||
|
|
||||||
auto bonnet_ok = vehicle->model->findFrame("bonnet_hi_ok");
|
auto bonnet_ok = vehicle->model->model->findFrame("bonnet_hi_ok");
|
||||||
auto bonnet_dam = vehicle->model->findFrame("bonnet_hi_dam");
|
auto bonnet_dam = vehicle->model->model->findFrame("bonnet_hi_dam");
|
||||||
|
|
||||||
BOOST_REQUIRE(bonnet_ok != nullptr);
|
BOOST_REQUIRE(bonnet_ok != nullptr);
|
||||||
BOOST_REQUIRE(bonnet_dam != nullptr);
|
BOOST_REQUIRE(bonnet_dam != nullptr);
|
||||||
|
Loading…
Reference in New Issue
Block a user