mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 10:22:52 +01:00
Load and associate model data when creating objects
This commit is contained in:
parent
6888fa3558
commit
218ffdf66c
@ -148,6 +148,10 @@ public:
|
||||
return numatomics_;
|
||||
}
|
||||
|
||||
bool isLoaded() const override {
|
||||
return model_ != nullptr;
|
||||
}
|
||||
|
||||
enum {
|
||||
/// Cull model if player doesn't look at it. Ignored in GTA 3.
|
||||
NORMAL_CULL = 1,
|
||||
@ -213,6 +217,10 @@ public:
|
||||
return model_;
|
||||
}
|
||||
|
||||
bool isLoaded() const override {
|
||||
return model_ != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Model* model_ = nullptr;
|
||||
};
|
||||
|
@ -336,13 +336,21 @@ void GameData::loadDFF(const std::string& name, bool async) {
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::getNameAndLod(std::string& name, int& lod) {
|
||||
auto lodpos = name.rfind("_l");
|
||||
if (lodpos != std::string::npos) {
|
||||
lod = std::atoi(name.substr(lodpos + 1).c_str());
|
||||
name = name.substr(0, lodpos);
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadModelFile(const std::string& name) {
|
||||
LoaderDFF l;
|
||||
auto file = index.openFilePath(name);
|
||||
if (!file) {
|
||||
logger->log("Data", Logger::Error, "Failed to load model file " + name);
|
||||
return;
|
||||
}
|
||||
LoaderDFF l;
|
||||
auto m = l.loadFromMemory(file);
|
||||
if (!m) {
|
||||
logger->log("Data", Logger::Error, "Error loading model file " + name);
|
||||
@ -353,12 +361,8 @@ void GameData::loadModelFile(const std::string& name) {
|
||||
for (auto& frame : m->frames) {
|
||||
/// @todo this is useful elsewhere, please move elsewhere
|
||||
std::string name = frame->getName();
|
||||
auto lodpos = name.rfind("_l");
|
||||
int lod = 0;
|
||||
if (lodpos != std::string::npos) {
|
||||
lod = std::atoi(name.substr(lodpos + 1).c_str());
|
||||
name = name.substr(0, lodpos);
|
||||
}
|
||||
getNameAndLod(name, lod);
|
||||
for (auto& model : modelinfo) {
|
||||
auto info = model.second.get();
|
||||
if (info->type() != ModelDataType::SimpleInfo) {
|
||||
@ -372,6 +376,62 @@ void GameData::loadModelFile(const std::string& name) {
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadModel(ModelID model) {
|
||||
auto info = modelinfo[model].get();
|
||||
/// @todo replace openFile with API for loading from CDIMAGE archives
|
||||
auto name = info->name;
|
||||
|
||||
// Re-direct special models
|
||||
switch (info->type()) {
|
||||
case ModelDataType::ClumpInfo:
|
||||
// Re-direct the hier objects to the special object ids
|
||||
name = engine->state->specialModels[info->id()];
|
||||
break;
|
||||
case ModelDataType::PedInfo:
|
||||
static const std::string specialPrefix("special");
|
||||
if (!name.compare(0, specialPrefix.size(), specialPrefix)) {
|
||||
auto sid = name.substr(specialPrefix.size());
|
||||
unsigned short specialID = std::atoi(sid.c_str());
|
||||
name = engine->state->specialCharacters[specialID];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||
auto file = index.openFile(name + ".dff");
|
||||
if (!file) {
|
||||
logger->error("Data", "Failed to load model for " +
|
||||
std::to_string(model) + " [" + name + "]");
|
||||
return;
|
||||
}
|
||||
LoaderDFF l;
|
||||
auto m = l.loadFromMemory(file);
|
||||
if (!m) {
|
||||
logger->error("Data",
|
||||
"Error loading model file for " + std::to_string(model));
|
||||
return;
|
||||
}
|
||||
/// @todo handle timeinfo models correctly.
|
||||
auto isSimple = info->type() == ModelDataType::SimpleInfo;
|
||||
if (isSimple) {
|
||||
auto simple = static_cast<SimpleModelInfo*>(info);
|
||||
// Associate atomics
|
||||
for (auto& frame : m->frames) {
|
||||
auto name = frame->getName();
|
||||
int lod = 0;
|
||||
getNameAndLod(name, lod);
|
||||
simple->setAtomic(m, lod, frame);
|
||||
}
|
||||
} else {
|
||||
// Associate clumps
|
||||
auto clump = static_cast<ClumpModelInfo*>(info);
|
||||
clump->setModel(m);
|
||||
/// @todo how is LOD handled for clump objects?
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadIFP(const std::string& name) {
|
||||
auto f = index.openFile(name);
|
||||
|
||||
|
@ -123,11 +123,21 @@ public:
|
||||
*/
|
||||
void loadDFF(const std::string& name, bool async = false);
|
||||
|
||||
/**
|
||||
* Converts combined {name}_l{LOD} into name and lod.
|
||||
*/
|
||||
static void getNameAndLod(std::string& name, int& lod);
|
||||
|
||||
/**
|
||||
* Loads a DFF and associates its atomics with models.
|
||||
*/
|
||||
void loadModelFile(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads and associates a model's data
|
||||
*/
|
||||
void loadModel(ModelID model);
|
||||
|
||||
/**
|
||||
* Loads an IFP file containing animations
|
||||
*/
|
||||
|
@ -164,6 +164,12 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
|
||||
const glm::quat& rot) {
|
||||
auto oi = data->findModelInfo<SimpleModelInfo>(id);
|
||||
if (oi) {
|
||||
// Request loading of the model if it isn't loaded already.
|
||||
/// @todo implment streaming properly
|
||||
if (!oi->isLoaded()) {
|
||||
data->loadModel(oi->id());
|
||||
}
|
||||
|
||||
std::string modelname = oi->name;
|
||||
std::string texturename = oi->textureslot;
|
||||
|
||||
@ -255,6 +261,11 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id,
|
||||
std::string texturename;
|
||||
|
||||
if (modelinfo) {
|
||||
/// @todo track if the current cutscene model is loaded
|
||||
if (true || !modelinfo->isLoaded()) {
|
||||
data->loadModel(id);
|
||||
}
|
||||
|
||||
modelname = modelinfo->name;
|
||||
texturename = modelinfo->textureslot;
|
||||
|
||||
@ -320,6 +331,10 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
|
||||
logger->info("World", "Creating Vehicle ID " + std::to_string(id) +
|
||||
" (" + vti->vehiclename_ + ")");
|
||||
|
||||
if (!vti->isLoaded()) {
|
||||
data->loadModel(id);
|
||||
}
|
||||
|
||||
if (!vti->name.empty()) {
|
||||
data->loadDFF(vti->name + ".dff");
|
||||
}
|
||||
@ -397,6 +412,10 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id,
|
||||
GameObjectID gid) {
|
||||
auto pt = data->findModelInfo<PedModelInfo>(id);
|
||||
if (pt) {
|
||||
if (!pt->isLoaded()) {
|
||||
data->loadModel(id);
|
||||
}
|
||||
|
||||
std::string modelname = pt->name;
|
||||
std::string texturename = pt->textureslot;
|
||||
|
||||
@ -471,6 +490,10 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (! modelInfo->isLoaded()) {
|
||||
data->loadModel(id);
|
||||
}
|
||||
|
||||
data->loadDFF(modelInfo->name + ".dff");
|
||||
data->loadTXD(modelInfo->textureslot + ".txd");
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <data/WeaponData.hpp>
|
||||
#include <loaders/GenericDATLoader.hpp>
|
||||
#include <objects/PickupObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include "test_globals.hpp"
|
||||
|
||||
// Tests against loading various data files
|
||||
@ -93,6 +95,32 @@ BOOST_AUTO_TEST_CASE(test_model_files_loaded) {
|
||||
BOOST_CHECK_EQUAL(ak47->name, "ak47");
|
||||
BOOST_CHECK_NE(ak47->getAtomic(0), nullptr);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_model_archive_loaded) {
|
||||
auto& d = Global::get().d;
|
||||
auto& e = Global::get().e;
|
||||
|
||||
/// @todo Implement streaming
|
||||
// Currently, instanciating an entity will load the model
|
||||
{
|
||||
auto crim = d->findModelInfo<PedModelInfo>(24);
|
||||
auto pickup = e->createPickup({}, 24, PickupObject::InShop);
|
||||
|
||||
BOOST_REQUIRE(crim->type() == ModelDataType::PedInfo);
|
||||
BOOST_CHECK_NE(crim->getModel(), nullptr);
|
||||
|
||||
e->destroyObject(pickup);
|
||||
}
|
||||
{
|
||||
auto info = d->findModelInfo<SimpleModelInfo>(2202);
|
||||
auto inst = e->createInstance(2202, {});
|
||||
|
||||
BOOST_REQUIRE(info->type() == ModelDataType::SimpleInfo);
|
||||
BOOST_CHECK_NE(info->getAtomic(0), nullptr);
|
||||
|
||||
e->destroyObject(inst);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user