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

Load objects directly

This commit is contained in:
Daniel Evans 2016-09-11 20:04:07 +01:00
parent 218ffdf66c
commit 6951434be8
25 changed files with 267 additions and 272 deletions

View File

@ -126,6 +126,11 @@ public:
atomics_[n] = atomic; atomics_[n] = atomic;
} }
/// @todo remove this
Model* getModel() const {
return model_;
}
ModelFrame* getAtomic(int n) const { ModelFrame* getAtomic(int n) const {
return atomics_[n]; return atomics_[n];
} }

View File

@ -344,6 +344,21 @@ void GameData::getNameAndLod(std::string& name, int& lod) {
} }
} }
Model* GameData::loadClump(const std::string& name) {
auto file = index.openFile(name);
if (!file) {
logger->error("Data", "Failed to load model " + name);
return nullptr;
}
LoaderDFF l;
auto m = l.loadFromMemory(file);
if (!m) {
logger->error("Data", "Error loading model file " + name);
return nullptr;
}
return m;
}
void GameData::loadModelFile(const std::string& name) { void GameData::loadModelFile(const std::string& name) {
auto file = index.openFilePath(name); auto file = index.openFilePath(name);
if (!file) { if (!file) {
@ -386,6 +401,8 @@ void GameData::loadModel(ModelID model) {
case ModelDataType::ClumpInfo: case ModelDataType::ClumpInfo:
// Re-direct the hier objects to the special object ids // Re-direct the hier objects to the special object ids
name = engine->state->specialModels[info->id()]; name = engine->state->specialModels[info->id()];
/// @todo remove this from here
loadTXD(name + ".txd");
break; break;
case ModelDataType::PedInfo: case ModelDataType::PedInfo:
static const std::string specialPrefix("special"); static const std::string specialPrefix("special");
@ -393,6 +410,8 @@ void GameData::loadModel(ModelID model) {
auto sid = name.substr(specialPrefix.size()); auto sid = name.substr(specialPrefix.size());
unsigned short specialID = std::atoi(sid.c_str()); unsigned short specialID = std::atoi(sid.c_str());
name = engine->state->specialCharacters[specialID]; name = engine->state->specialCharacters[specialID];
/// @todo remove this from here
loadTXD(name + ".txd");
break; break;
} }
default: default:

View File

@ -128,6 +128,11 @@ public:
*/ */
static void getNameAndLod(std::string& name, int& lod); static void getNameAndLod(std::string& name, int& lod);
/**
* Loads an archived model and returns it directly
*/
Model* loadClump(const std::string& name);
/** /**
* Loads a DFF and associates its atomics with models. * Loads a DFF and associates its atomics with models.
*/ */

View File

@ -178,18 +178,10 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
std::transform(std::begin(texturename), std::end(texturename), std::transform(std::begin(texturename), std::end(texturename),
std::begin(texturename), tolower); std::begin(texturename), tolower);
// Ensure the relevant data is loaded.
if (!modelname.empty()) {
if (modelname != "null") {
data->loadDFF(modelname + ".dff", false);
}
}
if (!texturename.empty()) { if (!texturename.empty()) {
data->loadTXD(texturename + ".txd", true); data->loadTXD(texturename + ".txd", true);
} }
ModelRef m = data->models[modelname];
// Check for dynamic data. // Check for dynamic data.
auto dyit = data->dynamicObjectData.find(oi->name); auto dyit = data->dynamicObjectData.find(oi->name);
std::shared_ptr<DynamicObjectData> dydata; std::shared_ptr<DynamicObjectData> dydata;
@ -203,7 +195,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
} }
auto instance = new InstanceObject( auto instance = new InstanceObject(
this, pos, rot, m, glm::vec3(1.f, 1.f, 1.f), oi, nullptr, dydata); this, pos, rot, glm::vec3(1.f, 1.f, 1.f), oi, nullptr, dydata);
instancePool.insert(instance); instancePool.insert(instance);
allObjects.push_back(instance); allObjects.push_back(instance);
@ -257,65 +249,34 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id,
const glm::vec3& pos, const glm::vec3& pos,
const glm::quat& rot) { const glm::quat& rot) {
auto modelinfo = data->modelinfo[id].get(); auto modelinfo = data->modelinfo[id].get();
std::string modelname;
if (!modelinfo) {
return nullptr;
}
auto clumpmodel = static_cast<ClumpModelInfo*>(modelinfo);
std::string texturename; std::string texturename;
if (modelinfo) { /// @todo track if the current cutscene model is loaded
/// @todo track if the current cutscene model is loaded if (true || !modelinfo->isLoaded()) {
if (true || !modelinfo->isLoaded()) { data->loadModel(id);
data->loadModel(id);
}
modelname = modelinfo->name;
texturename = modelinfo->textureslot;
/// @todo Store loaded models directly
switch (modelinfo->type()) {
case ModelDataType::ClumpInfo:
// Re-direct the hier objects to the special object ids
modelname = state->specialModels[id];
texturename = state->specialModels[id];
break;
case ModelDataType::PedInfo:
static const std::string specialPrefix("special");
if (!modelname.compare(0, specialPrefix.size(),
specialPrefix)) {
auto sid = modelname.substr(specialPrefix.size());
unsigned short specialID = std::atoi(sid.c_str());
modelname = state->specialCharacters[specialID];
texturename = state->specialCharacters[specialID];
break;
}
default:
break;
}
} }
auto model = clumpmodel->getModel();
texturename = modelinfo->textureslot;
if (id == 0) { if (id == 0) {
auto playerobj = pedestrianPool.find(state->playerObject); auto playerobj = pedestrianPool.find(state->playerObject);
if (playerobj) { if (playerobj) {
modelname = playerobj->model->name; model = playerobj->getModel();
} }
} }
// Ensure the relevant data is loaded.
if (modelname.empty()) {
logger->error(
"World", "Cutscene object " + std::to_string(id) + " has no model");
return nullptr;
}
if (modelname != "null") {
data->loadDFF(modelname + ".dff", false);
}
if (!texturename.empty()) { if (!texturename.empty()) {
data->loadTXD(texturename + ".txd", true); data->loadTXD(texturename + ".txd", true);
} }
ModelRef m = data->models[modelname]; auto instance = new CutsceneObject(this, pos, rot, model, modelinfo);
auto instance = new CutsceneObject(this, pos, rot, m, modelinfo);
cutscenePool.insert(instance); cutscenePool.insert(instance);
allObjects.push_back(instance); allObjects.push_back(instance);
@ -327,83 +288,76 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot, const glm::quat& rot,
GameObjectID gid) { GameObjectID gid) {
auto vti = data->findModelInfo<VehicleModelInfo>(id); auto vti = data->findModelInfo<VehicleModelInfo>(id);
if (vti) { if (!vti) {
logger->info("World", "Creating Vehicle ID " + std::to_string(id) + return nullptr;
" (" + vti->vehiclename_ + ")"); }
logger->info("World", "Creating Vehicle ID " + std::to_string(id) + " (" +
vti->vehiclename_ + ")");
if (!vti->isLoaded()) { if (!vti->isLoaded()) {
data->loadModel(id); data->loadModel(id);
} }
if (!vti->name.empty()) { if (!vti->textureslot.empty()) {
data->loadDFF(vti->name + ".dff"); data->loadTXD(vti->textureslot + ".txd");
} }
if (!vti->textureslot.empty()) {
data->loadTXD(vti->textureslot + ".txd");
}
glm::u8vec3 prim(255), sec(128); glm::u8vec3 prim(255), sec(128);
auto palit = data->vehiclePalettes.find( auto palit = data->vehiclePalettes.find(
vti->name); // modelname is conveniently lowercase (usually) vti->name); // modelname is conveniently lowercase (usually)
if (palit != data->vehiclePalettes.end() && palit->second.size() > 0) { if (palit != data->vehiclePalettes.end() && palit->second.size() > 0) {
std::uniform_int_distribution<int> uniform( std::uniform_int_distribution<int> uniform(0, palit->second.size() - 1);
0, palit->second.size() - 1); int set = uniform(randomEngine);
int set = uniform(randomEngine); prim = data->vehicleColours[palit->second[set].first];
prim = data->vehicleColours[palit->second[set].first]; sec = data->vehicleColours[palit->second[set].second];
sec = data->vehicleColours[palit->second[set].second]; } else {
} else { logger->warning("World", "No colour palette for vehicle " + vti->name);
logger->warning("World", }
"No colour palette for vehicle " + vti->name);
}
ModelRef& m = data->models[vti->name]; auto model = vti->getModel();
auto model = m->resource; auto info = data->vehicleInfo.find(vti->handling_);
auto info = data->vehicleInfo.find(vti->handling_); if (model && info != data->vehicleInfo.end()) {
if (model && info != data->vehicleInfo.end()) { if (info->second->wheels.size() == 0 &&
if (info->second->wheels.size() == 0 && info->second->seats.size() == 0) {
info->second->seats.size() == 0) { for (const ModelFrame* f : model->frames) {
for (const ModelFrame* f : model->frames) { const std::string& name = f->getName();
const std::string& name = f->getName();
if (name.size() > 5 && name.substr(0, 5) == "wheel") { if (name.size() > 5 && name.substr(0, 5) == "wheel") {
auto frameTrans = f->getMatrix(); auto frameTrans = f->getMatrix();
info->second->wheels.push_back( info->second->wheels.push_back({glm::vec3(frameTrans[3])});
{glm::vec3(frameTrans[3])}); }
} if (name == "ped_frontseat") {
if (name == "ped_frontseat") { auto p = f->getDefaultTranslation();
auto p = f->getDefaultTranslation(); // Left seat
// Left seat p.x = -p.x;
p.x = -p.x; info->second->seats.front.push_back({p});
info->second->seats.front.push_back({p}); // Right seat
// Right seat p.x = -p.x;
p.x = -p.x; info->second->seats.front.push_back({p});
info->second->seats.front.push_back({p}); }
} if (name == "ped_backseat") {
if (name == "ped_backseat") { // @todo how does this work for the barracks, ambulance
// @todo how does this work for the barracks, ambulance // or coach?
// or coach? auto p = f->getDefaultTranslation();
auto p = f->getDefaultTranslation(); // Left seat
// Left seat p.x = -p.x;
p.x = -p.x; info->second->seats.back.push_back({p});
info->second->seats.back.push_back({p}); // Right seat
// Right seat p.x = -p.x;
p.x = -p.x; info->second->seats.back.push_back({p});
info->second->seats.back.push_back({p});
}
} }
} }
} }
auto vehicle =
new VehicleObject{this, pos, rot, m, vti, info->second, prim, sec};
vehicle->setGameObjectID(gid);
vehiclePool.insert(vehicle);
allObjects.push_back(vehicle);
return vehicle;
} }
return nullptr;
auto vehicle =
new VehicleObject{this, pos, rot, vti, info->second, prim, sec};
vehicle->setGameObjectID(gid);
vehiclePool.insert(vehicle);
allObjects.push_back(vehicle);
return vehicle;
} }
CharacterObject* GameWorld::createPedestrian(const uint16_t id, CharacterObject* GameWorld::createPedestrian(const uint16_t id,
@ -411,46 +365,26 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id,
const glm::quat& rot, const glm::quat& rot,
GameObjectID gid) { GameObjectID gid) {
auto pt = data->findModelInfo<PedModelInfo>(id); auto pt = data->findModelInfo<PedModelInfo>(id);
if (pt) { if (!pt) {
if (!pt->isLoaded()) { return nullptr;
data->loadModel(id);
}
std::string modelname = pt->name;
std::string texturename = pt->textureslot;
// Ensure the relevant data is loaded.
if (!modelname.empty()) {
// Some model names have special meanings.
/// @todo Should CharacterObjects handle this?
static std::string specialPrefix("special");
if (!modelname.compare(0, specialPrefix.size(), specialPrefix)) {
auto sid = modelname.substr(specialPrefix.size());
unsigned short specialID = std::atoi(sid.c_str());
modelname = state->specialCharacters[specialID];
texturename = state->specialCharacters[specialID];
}
if (modelname != "null") {
data->loadDFF(modelname + ".dff");
}
}
if (!texturename.empty()) {
data->loadTXD(texturename + ".txd");
}
ModelRef m = data->models[modelname];
if (m && m->resource) {
auto ped = new CharacterObject(this, pos, rot, m, pt);
ped->setGameObjectID(gid);
new DefaultAIController(ped);
pedestrianPool.insert(ped);
allObjects.push_back(ped);
return ped;
}
} }
return nullptr;
if (!pt->isLoaded()) {
data->loadModel(id);
}
std::string texturename = pt->textureslot;
if (!texturename.empty()) {
data->loadTXD(texturename + ".txd");
}
auto ped = new CharacterObject(this, pos, rot, pt);
ped->setGameObjectID(gid);
new DefaultAIController(ped);
pedestrianPool.insert(ped);
allObjects.push_back(ped);
return ped;
} }
CharacterObject* GameWorld::createPlayer(const glm::vec3& pos, CharacterObject* GameWorld::createPlayer(const glm::vec3& pos,
@ -458,28 +392,28 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos,
GameObjectID gid) { GameObjectID gid) {
// Player object ID is hardcoded to 0. // Player object ID is hardcoded to 0.
auto pt = data->findModelInfo<PedModelInfo>(0); auto pt = data->findModelInfo<PedModelInfo>(0);
if (pt) { if (!pt) {
// Model name is also hardcoded. return nullptr;
std::string modelname = "player";
std::string texturename = "player";
// Ensure the relevant data is loaded.
data->loadDFF(modelname + ".dff");
data->loadTXD(texturename + ".txd");
ModelRef m = data->models[modelname];
if (m && m->resource) {
auto ped = new CharacterObject(this, pos, rot, m, nullptr);
ped->setGameObjectID(gid);
ped->setLifetime(GameObject::PlayerLifetime);
players.push_back(new PlayerController(ped));
pedestrianPool.insert(ped);
allObjects.push_back(ped);
return ped;
}
} }
return nullptr;
// Model name is also hardcoded.
std::string modelname = "player";
std::string texturename = "player";
if (!pt->isLoaded()) {
auto model = data->loadClump(modelname + ".dff");
pt->setModel(model);
}
data->loadTXD(texturename + ".txd");
auto ped = new CharacterObject(this, pos, rot, pt);
ped->setGameObjectID(gid);
ped->setLifetime(GameObject::PlayerLifetime);
players.push_back(new PlayerController(ped));
pedestrianPool.insert(ped);
allObjects.push_back(ped);
return ped;
} }
PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) { PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
@ -490,11 +424,10 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
return nullptr; return nullptr;
} }
if (! modelInfo->isLoaded()) { if (!modelInfo->isLoaded()) {
data->loadModel(id); data->loadModel(id);
} }
data->loadDFF(modelInfo->name + ".dff");
data->loadTXD(modelInfo->textureslot + ".txd"); data->loadTXD(modelInfo->textureslot + ".txd");
PickupObject* pickup = nullptr; PickupObject* pickup = nullptr;
@ -881,7 +814,6 @@ void GameWorld::loadSpecialCharacter(const unsigned short index,
::tolower); ::tolower);
/// @todo a bit more smarter than this /// @todo a bit more smarter than this
state->specialCharacters[index] = lowerName; state->specialCharacters[index] = lowerName;
data->loadDFF(lowerName + ".dff");
} }
void GameWorld::loadSpecialModel(const unsigned short index, void GameWorld::loadSpecialModel(const unsigned short index,

View File

@ -9,7 +9,7 @@
#include <objects/ProjectileObject.hpp> #include <objects/ProjectileObject.hpp>
void WeaponItem::fireHitscan(CharacterObject* owner) { void WeaponItem::fireHitscan(CharacterObject* owner) {
auto handFrame = owner->model->resource->findFrame("srhand"); auto handFrame = owner->getModel()->findFrame("srhand");
glm::mat4 handMatrix; glm::mat4 handMatrix;
if (handFrame) { if (handFrame) {
while (handFrame->getParent()) { while (handFrame->getParent()) {

View File

@ -14,9 +14,9 @@ static glm::vec3 enter_offset(0.81756252f, 0.34800607f, -0.486281008f);
const float CharacterObject::DefaultJumpSpeed = 2.f; const float CharacterObject::DefaultJumpSpeed = 2.f;
CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, const glm::quat& rot,
BaseModelInfo *modelinfo) BaseModelInfo *modelinfo)
: GameObject(engine, pos, rot, modelinfo, model) : GameObject(engine, pos, rot, modelinfo)
, currentState({}) , currentState({})
, currentVehicle(nullptr) , currentVehicle(nullptr)
, currentSeat(0) , currentSeat(0)
@ -65,9 +65,11 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos,
animations.kd_front = engine->data->animations["kd_front"]; animations.kd_front = engine->data->animations["kd_front"];
animations.ko_shot_front = engine->data->animations["ko_shot_front"]; animations.ko_shot_front = engine->data->animations["ko_shot_front"];
if (model) { auto info = getModelInfo<PedModelInfo>();
if (info->getModel()) {
setModel(info->getModel());
skeleton = new Skeleton; skeleton = new Skeleton;
animator = new Animator(model->resource, skeleton); animator = new Animator(getModel(), skeleton);
createActor(); createActor();
} }
@ -86,7 +88,7 @@ void CharacterObject::createActor(const glm::vec2& size) {
} }
// Don't create anything without a valid model. // Don't create anything without a valid model.
if (model) { if (getModel()) {
btTransform tf; btTransform tf;
tf.setIdentity(); tf.setIdentity();
tf.setOrigin(btVector3(position.x, position.y, position.z)); tf.setOrigin(btVector3(position.x, position.y, position.z));
@ -204,8 +206,8 @@ glm::vec3 CharacterObject::updateMovementAnimation(float dt) {
// If we have to, interrogate the movement animation // If we have to, interrogate the movement animation
if (movementAnimation != animations.idle) { if (movementAnimation != animations.idle) {
if (!model->resource->frames[0]->getChildren().empty()) { if (!getModel()->frames[0]->getChildren().empty()) {
ModelFrame* root = model->resource->frames[0]->getChildren()[0]; ModelFrame* root = getModel()->frames[0]->getChildren()[0];
auto it = movementAnimation->bones.find(root->getName()); auto it = movementAnimation->bones.find(root->getName());
if (it != movementAnimation->bones.end()) { if (it != movementAnimation->bones.end()) {
AnimationBone* rootBone = it->second; AnimationBone* rootBone = it->second;
@ -265,22 +267,20 @@ void CharacterObject::changeCharacterModel(const std::string& name) {
std::transform(modelName.begin(), modelName.end(), modelName.begin(), std::transform(modelName.begin(), modelName.end(), modelName.begin(),
::tolower); ::tolower);
engine->data->loadDFF(modelName + ".dff"); /// @todo don't model leak here
engine->data->loadTXD(modelName + ".txd");
auto& models = engine->data->models; engine->data->loadTXD(modelName + ".txd");
auto mfind = models.find(modelName); auto newmodel = engine->data->loadClump(modelName + ".dff");
if (mfind != models.end()) {
model = mfind->second;
}
if (skeleton) { if (skeleton) {
delete animator; delete animator;
delete skeleton; delete skeleton;
} }
setModel(newmodel);
skeleton = new Skeleton; skeleton = new Skeleton;
animator = new Animator(model->resource, skeleton); animator = new Animator(getModel(), skeleton);
} }
void CharacterObject::updateCharacter(float dt) { void CharacterObject::updateCharacter(float dt) {

View File

@ -140,8 +140,7 @@ public:
* @param ped PEDS_t struct to use. * @param ped PEDS_t struct to use.
*/ */
CharacterObject(GameWorld* engine, const glm::vec3& pos, CharacterObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, const glm::quat& rot, BaseModelInfo* modelinfo);
BaseModelInfo* modelinfo);
~CharacterObject(); ~CharacterObject();
@ -149,7 +148,6 @@ public:
return Character; return Character;
} }
void tick(float dt); void tick(float dt);
const CharacterState& getCurrentState() const { const CharacterState& getCurrentState() const {

View File

@ -3,13 +3,19 @@
#include <objects/CutsceneObject.hpp> #include <objects/CutsceneObject.hpp>
CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos, CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos,
const glm::quat &rot, const glm::quat &rot, Model *model,
const ModelRef &model, BaseModelInfo *modelinfo) BaseModelInfo *modelinfo)
: GameObject(engine, pos, rot, modelinfo, model) : GameObject(engine, pos, rot, modelinfo)
, _parent(nullptr) , _parent(nullptr)
, _bone(nullptr) { , _bone(nullptr) {
if (model) {
setModel(model);
}
else {
setModel(getModelInfo<ClumpModelInfo>()->getModel());
}
skeleton = new Skeleton; skeleton = new Skeleton;
animator = new Animator(model->resource, skeleton); animator = new Animator(getModel(), skeleton);
} }
CutsceneObject::~CutsceneObject() { CutsceneObject::~CutsceneObject() {

View File

@ -12,7 +12,8 @@ class CutsceneObject : public GameObject {
public: public:
CutsceneObject(GameWorld* engine, const glm::vec3& pos, CutsceneObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, BaseModelInfo *modelinfo); const glm::quat& rot, Model* model,
BaseModelInfo* modelinfo);
~CutsceneObject(); ~CutsceneObject();
Type type() { Type type() {

View File

@ -30,13 +30,20 @@ class GameObject {
BaseModelInfo* modelinfo_; BaseModelInfo* modelinfo_;
/**
* Model used for rendering
*/
Model* model_;
protected:
void changeModelInfo(BaseModelInfo* next) {
modelinfo_ = next;
}
public: public:
glm::vec3 position; glm::vec3 position;
glm::quat rotation; glm::quat rotation;
/// Reference to Model data
ModelRef model;
GameWorld* engine; GameWorld* engine;
Animator* animator; /// Object's animator. Animator* animator; /// Object's animator.
@ -55,14 +62,14 @@ public:
bool visible; bool visible;
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot,
BaseModelInfo* modelinfo, ModelRef model) BaseModelInfo* modelinfo)
: _lastPosition(pos) : _lastPosition(pos)
, _lastRotation(rot) , _lastRotation(rot)
, objectID(0) , objectID(0)
, modelinfo_(modelinfo) , modelinfo_(modelinfo)
, model_(nullptr)
, position(pos) , position(pos)
, rotation(rot) , rotation(rot)
, model(model)
, engine(engine) , engine(engine)
, animator(nullptr) , animator(nullptr)
, skeleton(nullptr) , skeleton(nullptr)
@ -96,6 +103,20 @@ public:
return static_cast<T*>(modelinfo_); return static_cast<T*>(modelinfo_);
} }
/**
* @return The model used in rendering
*/
Model* getModel() const {
return model_;
}
/**
* Changes the current model, used for re-dressing chars
*/
void setModel(Model* model) {
model_ = model;
}
/** /**
* @brief Enumeration of possible object types. * @brief Enumeration of possible object types.
*/ */

View File

@ -6,12 +6,10 @@
#include <objects/InstanceObject.hpp> #include <objects/InstanceObject.hpp>
InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos, InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, const glm::quat& rot, const glm::vec3& scale,
const glm::vec3& scale, BaseModelInfo* modelinfo, InstanceObject* lod,
BaseModelInfo *modelinfo,
InstanceObject* lod,
std::shared_ptr<DynamicObjectData> dyn) std::shared_ptr<DynamicObjectData> dyn)
: GameObject(engine, pos, rot, modelinfo, model) : GameObject(engine, pos, rot, modelinfo)
, health(100.f) , health(100.f)
, scale(scale) , scale(scale)
, body(nullptr) , body(nullptr)
@ -123,15 +121,21 @@ void InstanceObject::tick(float dt) {
if (animator) animator->tick(dt); if (animator) animator->tick(dt);
} }
void InstanceObject::changeModel(BaseModelInfo *incoming) { void InstanceObject::changeModel(BaseModelInfo* incoming) {
if (body) { if (body) {
delete body; delete body;
body = nullptr; body = nullptr;
} }
/// @todo store the new object
if (incoming) { if (incoming) {
if (!incoming->isLoaded()) {
engine->data->loadModel(incoming->id());
}
changeModelInfo(incoming);
/// @todo this should only be temporary
setModel(getModelInfo<SimpleModelInfo>()->getModel());
auto bod = new CollisionInstance; auto bod = new CollisionInstance;
if (bod->createPhysicsBody(this, incoming->name, dynamics.get())) { if (bod->createPhysicsBody(this, incoming->name, dynamics.get())) {

View File

@ -22,9 +22,9 @@ public:
bool _enablePhysics; bool _enablePhysics;
InstanceObject(GameWorld* engine, const glm::vec3& pos, InstanceObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, const glm::quat& rot, const glm::vec3& scale,
const glm::vec3& scale, BaseModelInfo* modelinfo, BaseModelInfo* modelinfo, InstanceObject* lod,
InstanceObject* lod, std::shared_ptr<DynamicObjectData> dyn); std::shared_ptr<DynamicObjectData> dyn);
~InstanceObject(); ~InstanceObject();
Type type() { Type type() {

View File

@ -60,7 +60,7 @@ uint32_t PickupObject::behaviourFlags(PickupType type) {
PickupObject::PickupObject(GameWorld* world, const glm::vec3& position, PickupObject::PickupObject(GameWorld* world, const glm::vec3& position,
BaseModelInfo* modelinfo, PickupType type) BaseModelInfo* modelinfo, PickupType type)
: GameObject(world, position, glm::quat(), modelinfo, nullptr) : GameObject(world, position, glm::quat(), modelinfo)
, m_ghost(nullptr) , m_ghost(nullptr)
, m_shape(nullptr) , m_shape(nullptr)
, m_enabled(false) , m_enabled(false)

View File

@ -107,7 +107,7 @@ void ProjectileObject::cleanup() {
ProjectileObject::ProjectileObject(GameWorld* world, const glm::vec3& position, ProjectileObject::ProjectileObject(GameWorld* world, const glm::vec3& position,
const ProjectileObject::ProjectileInfo& info) const ProjectileObject::ProjectileInfo& info)
: GameObject(world, position, glm::quat(), nullptr, nullptr) : GameObject(world, position, glm::quat(), nullptr)
, _info(info) , _info(info)
, _body(nullptr) , _body(nullptr)
, _ghostBody(nullptr) , _ghostBody(nullptr)

View File

@ -83,10 +83,10 @@ private:
}; };
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const ModelRef& model, const glm::quat& rot, BaseModelInfo* modelinfo,
BaseModelInfo *modelinfo, VehicleInfoHandle info, VehicleInfoHandle info, const glm::u8vec3& prim,
const glm::u8vec3& prim, const glm::u8vec3& sec) const glm::u8vec3& sec)
: GameObject(engine, pos, rot, modelinfo, model) : GameObject(engine, pos, rot, modelinfo)
, steerAngle(0.f) , steerAngle(0.f)
, throttle(0.f) , throttle(0.f)
, brake(0.f) , brake(0.f)
@ -152,7 +152,9 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos,
// Hide all LOD and damage frames. // Hide all LOD and damage frames.
skeleton = new Skeleton; skeleton = new Skeleton;
for (ModelFrame* frame : model->resource->frames) { setModel(getVehicle()->getModel());
for (ModelFrame* frame : getModel()->frames) {
auto& name = frame->getName(); auto& name = frame->getName();
bool isDam = name.find("_dam") != name.npos; bool isDam = name.find("_dam") != name.npos;
bool isLod = name.find("lo") != name.npos; bool isLod = name.find("lo") != name.npos;
@ -554,7 +556,7 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) {
if (skeleton->getData(p->normal->getIndex()).enabled) { if (skeleton->getData(p->normal->getIndex()).enabled) {
auto& geom = auto& geom =
model->resource->geometries[p->normal->getGeometries()[0]]; getModel()->geometries[p->normal->getGeometries()[0]];
auto pp = auto pp =
p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f); p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f);
float td = glm::distance( float td = glm::distance(
@ -678,7 +680,7 @@ void VehicleObject::createObjectHinge(Part* part) {
if (okframe->getGeometries().size() == 0) return; if (okframe->getGeometries().size() == 0) return;
auto& geom = model->resource->geometries[okframe->getGeometries()[0]]; auto& geom = getModel()->geometries[okframe->getGeometries()[0]];
auto gbounds = geom->geometryBounds; auto gbounds = geom->geometryBounds;
if (fn.find("door") != fn.npos) { if (fn.find("door") != fn.npos) {

View File

@ -49,9 +49,8 @@ public:
std::map<std::string, Part> dynamicParts; std::map<std::string, Part> dynamicParts;
VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot,
const ModelRef& model, BaseModelInfo* modelinfo, BaseModelInfo* modelinfo, VehicleInfoHandle info,
VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& prim, const glm::u8vec3& sec);
const glm::u8vec3& sec);
virtual ~VehicleObject(); virtual ~VehicleObject();

View File

@ -177,7 +177,7 @@ void ObjectRenderer::renderItem(InventoryItem* item,
void ObjectRenderer::renderInstance(InstanceObject* instance, void ObjectRenderer::renderInstance(InstanceObject* instance,
RenderList& outList) { RenderList& outList) {
if (!instance->model->resource) { if (!instance->getModel()) {
return; return;
} }
@ -203,7 +203,7 @@ void ObjectRenderer::renderInstance(InstanceObject* instance,
auto matrixModel = instance->getTimeAdjustedTransform(m_renderAlpha); auto matrixModel = instance->getTimeAdjustedTransform(m_renderAlpha);
float mindist = glm::length(instance->getPosition() - m_camera.position) - float mindist = glm::length(instance->getPosition() - m_camera.position) -
instance->model->resource->getBoundingRadius(); instance->getModel()->getBoundingRadius();
mindist *= 1.f / kDrawDistanceFactor; mindist *= 1.f / kDrawDistanceFactor;
Model* model = nullptr; Model* model = nullptr;
@ -230,7 +230,7 @@ void ObjectRenderer::renderInstance(InstanceObject* instance,
instance->LODinstance->getModelInfo<SimpleModelInfo>(); instance->LODinstance->getModelInfo<SimpleModelInfo>();
float LODrange = lodmodelinfo->getLodDistance(0); float LODrange = lodmodelinfo->getLodDistance(0);
if (mindist <= LODrange && if (mindist <= LODrange &&
instance->LODinstance->model->resource) { instance->LODinstance->getModel()) {
// The model matrix needs to be for the LOD instead // The model matrix needs to be for the LOD instead
matrixModel = matrixModel =
instance->LODinstance->getTimeAdjustedTransform( instance->LODinstance->getTimeAdjustedTransform(
@ -238,27 +238,27 @@ void ObjectRenderer::renderInstance(InstanceObject* instance,
// If the object is only just out of range, keep // If the object is only just out of range, keep
// rendering it and screen-door the LOD. // rendering it and screen-door the LOD.
if (overlap < fadeRange) { if (overlap < fadeRange) {
model = instance->LODinstance->model->resource; model = instance->LODinstance->getModel();
fadingModel = instance->model->resource; fadingModel = instance->getModel();
opacity = 1.f - (overlap / fadeRange); opacity = 1.f - (overlap / fadeRange);
} else { } else {
model = instance->LODinstance->model->resource; model = instance->LODinstance->getModel();
} }
} }
} }
// We don't have a LOD object, so fade out gracefully. // We don't have a LOD object, so fade out gracefully.
else if (overlap < fadeRange) { else if (overlap < fadeRange) {
fadingModel = instance->model->resource; fadingModel = instance->getModel();
opacity = 1.f - (overlap / fadeRange); opacity = 1.f - (overlap / fadeRange);
} }
} }
// Otherwise, if we aren't marked as a LOD model, we can render // Otherwise, if we aren't marked as a LOD model, we can render
else if (!modelinfo->LOD) { else if (!modelinfo->LOD) {
model = instance->model->resource; model = instance->getModel();
} }
} else { } else {
auto root = instance->model->resource->frames[0]; auto root = instance->getModel()->frames[0];
auto objectModel = instance->model->resource; auto objectModel = instance->getModel();
fadingFrame = nullptr; fadingFrame = nullptr;
fadingModel = nullptr; fadingModel = nullptr;
@ -316,15 +316,15 @@ void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,
matrixModel = pedestrian->getTimeAdjustedTransform(m_renderAlpha); matrixModel = pedestrian->getTimeAdjustedTransform(m_renderAlpha);
} }
if (!pedestrian->model->resource) return; if (!pedestrian->getModel()) return;
auto root = pedestrian->model->resource->frames[0]; auto root = pedestrian->getModel()->frames[0];
renderFrame(pedestrian->model->resource, root->getChildren()[0], renderFrame(pedestrian->getModel(), root->getChildren()[0],
matrixModel, pedestrian, 1.f, outList); matrixModel, pedestrian, 1.f, outList);
if (pedestrian->getActiveItem()) { if (pedestrian->getActiveItem()) {
auto handFrame = pedestrian->model->resource->findFrame("srhand"); auto handFrame = pedestrian->getModel()->findFrame("srhand");
glm::mat4 localMatrix; glm::mat4 localMatrix;
if (handFrame) { if (handFrame) {
while (handFrame->getParent()) { while (handFrame->getParent()) {
@ -365,15 +365,15 @@ void ObjectRenderer::renderWheel(VehicleObject* vehicle, Model* model,
void ObjectRenderer::renderVehicle(VehicleObject* vehicle, void ObjectRenderer::renderVehicle(VehicleObject* vehicle,
RenderList& outList) { RenderList& outList) {
RW_CHECK(vehicle->model, "Vehicle model is null"); RW_CHECK(vehicle->getModel(), "Vehicle model is null");
if (!vehicle->model) { if (!vehicle->getModel()) {
return; return;
} }
glm::mat4 matrixModel = vehicle->getTimeAdjustedTransform(m_renderAlpha); glm::mat4 matrixModel = vehicle->getTimeAdjustedTransform(m_renderAlpha);
renderFrame(vehicle->model->resource, vehicle->model->resource->frames[0], renderFrame(vehicle->getModel(), vehicle->getModel()->frames[0],
matrixModel, vehicle, 1.f, outList); matrixModel, vehicle, 1.f, outList);
auto modelinfo = vehicle->getVehicle(); auto modelinfo = vehicle->getVehicle();
@ -466,7 +466,7 @@ void ObjectRenderer::renderCutsceneObject(CutsceneObject* cutscene,
RenderList& outList) { RenderList& outList) {
if (!m_world->state->currentCutscene) return; if (!m_world->state->currentCutscene) return;
if (!cutscene->model->resource) { if (!cutscene->getModel()) {
return; return;
} }
@ -492,7 +492,7 @@ void ObjectRenderer::renderCutsceneObject(CutsceneObject* cutscene,
matrixModel = glm::translate(matrixModel, cutsceneOffset); matrixModel = glm::translate(matrixModel, cutsceneOffset);
} }
auto model = cutscene->model->resource; auto model = cutscene->getModel();
if (cutscene->getParentActor()) { if (cutscene->getParentActor()) {
glm::mat4 align; glm::mat4 align;
/// @todo figure out where this 90 degree offset is coming from. /// @todo figure out where this 90 degree offset is coming from.

View File

@ -35,8 +35,7 @@ inline bool isInModel(const ScriptArguments& args, CharacterObject* character,
if (data) { if (data) {
auto vehicle = getCharacterVehicle(character); auto vehicle = getCharacterVehicle(character);
if (vehicle) { if (vehicle) {
return vehicle->model ? vehicle->model->name == data->name return vehicle->getVehicle()->id() == model;
: false;
} }
} }
return false; return false;

View File

@ -6836,12 +6836,18 @@ void opcode_023c(const ScriptArguments& args, const ScriptInt arg1, const Script
@arg arg1 @arg arg1
*/ */
bool opcode_023d(const ScriptArguments& args, const ScriptInt arg1) { bool opcode_023d(const ScriptArguments& args, const ScriptInt arg1) {
/// @todo re-implement this when streaming is added
return true;
RW_UNUSED(args);
RW_UNUSED(arg1);
#if 0
auto model = args.getState()->specialCharacters[arg1]; auto model = args.getState()->specialCharacters[arg1];
auto modelfind = args.getWorld()->data->models.find(model); auto modelfind = args.getWorld()->data->models.find(model);
if( modelfind != args.getWorld()->data->models.end() && modelfind->second->resource != nullptr ) { if( modelfind != args.getWorld()->data->models.end() && modelfind->second->resource != nullptr ) {
return true; return true;
} }
return false; return false;
#endif
} }
/** /**
@ -8455,7 +8461,7 @@ void opcode_02f4(const ScriptArguments& args, const ScriptObject object0, const
auto actor = args.getObject<CutsceneObject>(0); auto actor = args.getObject<CutsceneObject>(0);
CutsceneObject* object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset ); CutsceneObject* object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset );
auto headframe = actor->model->resource->findFrame("shead"); auto headframe = actor->getModel()->findFrame("shead");
actor->skeleton->setEnabled(headframe, false); actor->skeleton->setEnabled(headframe, false);
object->setParentActor(actor, headframe); object->setParentActor(actor, headframe);
@ -11346,17 +11352,14 @@ void opcode_03b6(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa
auto newobjectid = args.getWorld()->data->findModelObject(newmodel); auto newobjectid = args.getWorld()->data->findModelObject(newmodel);
auto nobj = args.getWorld()->data->findModelInfo<SimpleModelInfo>(newobjectid); auto nobj = args.getWorld()->data->findModelInfo<SimpleModelInfo>(newobjectid);
/// @todo Objects need to adopt the new object ID, not just the model.
for(auto p : args.getWorld()->instancePool.objects) { for(auto p : args.getWorld()->instancePool.objects) {
auto o = p.second; auto o = p.second;
if( !o->model ) continue; if( !o->getModel() ) continue;
if( o->model->name != oldmodel ) continue; if( o->getModelInfo<BaseModelInfo>()->name != oldmodel ) continue;
float d = glm::distance(coord, o->getPosition()); float d = glm::distance(coord, o->getPosition());
if( d < radius ) { if( d < radius ) {
args.getWorld()->data->loadDFF(newmodel + ".dff", false);
InstanceObject* inst = static_cast<InstanceObject*>(o); InstanceObject* inst = static_cast<InstanceObject*>(o);
inst->changeModel(nobj); inst->changeModel(nobj);
inst->model = args.getWorld()->data->models[newmodel];
} }
} }
} }

View File

@ -201,7 +201,8 @@ Menu* DebugState::createMapMenu() {
for (auto& i : gw->instancePool.objects) { for (auto& i : gw->instancePool.objects) {
auto obj = static_cast<InstanceObject*>(i.second); auto obj = static_cast<InstanceObject*>(i.second);
if (std::find(garageDoorModels.begin(), garageDoorModels.end(), if (std::find(garageDoorModels.begin(), garageDoorModels.end(),
obj->model->name) != garageDoorModels.end()) { obj->getModelInfo<BaseModelInfo>()->name) !=
garageDoorModels.end()) {
obj->setSolid(false); obj->setSolid(false);
} }
} }

View File

@ -238,9 +238,9 @@ void IngameState::tick(float dt) {
? static_cast<CharacterObject*>(target)->getCurrentVehicle() ? static_cast<CharacterObject*>(target)->getCurrentVehicle()
: nullptr; : nullptr;
if (vehicle) { if (vehicle) {
auto model = vehicle->model; auto model = vehicle->getModel();
float maxDist = 0.f; float maxDist = 0.f;
for (auto& g : model->resource->geometries) { for (auto& g : model->geometries) {
float partSize = glm::length(g->geometryBounds.center) + float partSize = glm::length(g->geometryBounds.center) +
g->geometryBounds.radius; g->geometryBounds.radius;
maxDist = std::max(partSize, maxDist); maxDist = std::max(partSize, maxDist);

View File

@ -194,7 +194,7 @@ void ViewerWidget::showObject(qint16 item) {
RW_CHECK(dummyObject != nullptr, "Dummy Object is null"); RW_CHECK(dummyObject != nullptr, "Dummy Object is null");
if (dummyObject != nullptr) { if (dummyObject != nullptr) {
activeModel = dummyObject->model->resource; activeModel = dummyObject->getModel();
} }
} }
} }

View File

@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(test_activities) {
VehicleObject* vehicle = Global::get().e->createVehicle( VehicleObject* vehicle = Global::get().e->createVehicle(
90u, glm::vec3(10.f, 0.f, 0.f), glm::quat()); 90u, glm::vec3(10.f, 0.f, 0.f), glm::quat());
BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle != nullptr);
BOOST_REQUIRE(vehicle->model != nullptr); BOOST_REQUIRE(vehicle->getModel() != 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});

View File

@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(vehicle_parts) {
Global::get().e->createVehicle(90u, glm::vec3(), glm::quat()); Global::get().e->createVehicle(90u, glm::vec3(), glm::quat());
BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle != nullptr);
BOOST_REQUIRE(vehicle->model != nullptr); BOOST_REQUIRE(vehicle->getModel() != nullptr);
VehicleObject::Part* part = vehicle->getPart("bonnet_dummy"); VehicleObject::Part* part = vehicle->getPart("bonnet_dummy");
@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(vehicle_part_vis) {
Global::get().e->createVehicle(90u, glm::vec3(), glm::quat()); Global::get().e->createVehicle(90u, glm::vec3(), glm::quat());
BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle != nullptr);
BOOST_REQUIRE(vehicle->model != nullptr); BOOST_REQUIRE(vehicle->getModel() != nullptr);
VehicleObject::Part* bonnetpart = vehicle->getPart("bonnet_dummy"); VehicleObject::Part* bonnetpart = vehicle->getPart("bonnet_dummy");
auto skel = vehicle->skeleton; auto skel = vehicle->skeleton;

View File

@ -12,7 +12,7 @@ BOOST_AUTO_TEST_CASE(TestWeaponScan) {
// Test RADIUS scan // Test RADIUS scan
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});
BOOST_REQUIRE(character != nullptr); BOOST_REQUIRE(character != nullptr);
BOOST_REQUIRE(character->model != nullptr); BOOST_REQUIRE(character->getModel() != nullptr);
BOOST_REQUIRE(character->physObject != nullptr); BOOST_REQUIRE(character->physObject != nullptr);
WeaponScan scan(10.f, {0.f, 0.f, 10.f}, {0.f, 0.f, -10.f}); WeaponScan scan(10.f, {0.f, 0.f, 10.f}, {0.f, 0.f, -10.f});