Commit 2ef9bc31 by NTAuthority

COLL loading (for GTA3 only - not VC yet) and using them for bounding boxes)

parent 34bf607e
Pipeline #82 skipped
#pragma once
#include <Streaming.common.h>
#ifndef COLLISION_H
#define COLLISION_H
#include "src/collision.h"
#endif
namespace krt
{
class CollisionStore : public streaming::StreamingTypeInterface
{
public:
struct CollisionModel
{
streaming::ident_t modelIndex;
std::string name;
std::shared_ptr<CColModel> model;
};
class CollisionArchive
{
public:
inline streaming::ident_t GetID() const
{
return m_id;
}
inline const std::vector<std::unique_ptr<CollisionModel>>& GetModels() const
{
return m_models;
}
inline CollisionArchive(const vfs::DevicePtr& device, const std::string& pathToRes) : m_location(device, pathToRes)
{
}
private:
friend class CollisionStore;
private:
CollisionStore* m_store;
streaming::ident_t m_id;
std::vector<std::unique_ptr<CollisionModel>> m_models;
DeviceResourceLocation m_location;
};
public:
CollisionStore(streaming::StreamMan& streaming);
~CollisionStore();
streaming::ident_t RegisterCollisionArchive(const std::string& name, const std::string& filePath);
virtual void LoadResource(streaming::ident_t localID, const void* dataBuf, size_t memSize) override;
virtual void UnloadResource(streaming::ident_t localID) override;
virtual size_t GetObjectMemorySize(streaming::ident_t localID) const override;
private:
streaming::StreamMan& m_streaming;
std::vector<std::shared_ptr<CollisionArchive>> m_entries;
std::atomic<streaming::ident_t> m_curIndex;
};
}
\ No newline at end of file
......@@ -9,6 +9,7 @@
#include "ModelInfo.h"
#include "Streaming.h"
#include "TexDict.h"
#include "CollisionStore.h"
#include "World.h"
#include "Console.Commands.h"
......@@ -36,6 +37,7 @@ public:
inline streaming::StreamMan& GetStreaming(void) { return this->streaming; }
inline TextureManager& GetTextureManager(void) { return this->texManager; }
inline ModelManager& GetModelManager(void) { return this->modelManager; }
inline CollisionStore& GetCollisionStore(void) { return this->colStore; }
inline World* GetWorld(void) { return &theWorld; }
......@@ -74,6 +76,7 @@ private:
TextureManager texManager;
ModelManager modelManager;
CollisionStore colStore;
World theWorld;
......
......@@ -8,6 +8,13 @@
#include <Console.CommandHelpers.h>
// custom include guard
#ifndef COLLISION_H
#define COLLISION_H
#include "src/collision.h"
#endif
#define MODEL_ID_BASE 0
#define MAX_MODELS 20000
......@@ -33,6 +40,21 @@ struct ModelManager : public streaming::StreamingTypeInterface
inline ModelResource* GetLODModel(void) { return this->lod_model; }
inline std::shared_ptr<CColModel> GetCollisionModel()
{
if (this->col_model.expired())
{
return nullptr;
}
return this->col_model.lock();
}
inline void SetCollisionModel(const std::shared_ptr<CColModel>& pointer)
{
this->col_model = pointer;
}
rw::Object* CloneModel(void);
void ReleaseModel(rw::Object* rwobj);
......@@ -80,6 +102,8 @@ struct ModelManager : public streaming::StreamingTypeInterface
ModelResource* non_lod_model; // non-SA: model of a higher-quality model than this one
ModelResource* lod_model; // model of a lower quality model than this one.
std::weak_ptr<CColModel> col_model;
eModelType modelType;
DeviceResourceLocation vfsResLoc;
......
#include "StdInc.h"
#include "CollisionStore.h"
#include "ModelInfo.h"
#include "Game.h"
#include <vfs/Manager.h>
#define COL_ID_BASE 25000
#define MAX_COLS 1000
namespace krt
{
CollisionStore::CollisionStore(streaming::StreamMan& streaming) : m_streaming(streaming), m_curIndex(0)
{
bool didRegister = streaming.RegisterResourceType(COL_ID_BASE, MAX_COLS, this);
assert(didRegister == true);
m_entries.resize(MAX_COLS);
}
CollisionStore::~CollisionStore()
{
// remove all entries
for (auto& entry : m_entries)
{
if (entry.get())
{
m_streaming.UnlinkResource(entry->GetID());
}
}
// clear the entry list and unregister ourselves
m_entries.clear();
m_streaming.UnregisterResourceType(COL_ID_BASE);
}
streaming::ident_t CollisionStore::RegisterCollisionArchive(const std::string& name, const std::string& filePath)
{
// get an identifier
streaming::ident_t id = (m_curIndex.fetch_add(1)) + COL_ID_BASE;
// get a device
vfs::DevicePtr resDevice = vfs::GetDevice(filePath);
if (resDevice == nullptr)
{
// no device? no entry
return -1;
}
// check whether this resource even exists
if (resDevice->GetLength(filePath) == -1)
{
// non-existent entry
return -1;
}
// create a new archive
auto archive = std::make_shared<CollisionArchive>(resDevice, filePath);
archive->m_id = id;
archive->m_store = this;
// register with streaming
if (!m_streaming.LinkResource(id, name, &archive->m_location))
{
// registration failed
return -1;
}
// store us
m_entries[id - COL_ID_BASE] = archive;
return id;
}
enum { COLL = 0x4C4C4F43 };
void CollisionStore::LoadResource(streaming::ident_t localID, const void* dataBuf, size_t memSize)
{
struct
{
uint32_t ident;
uint32_t size;
} header;
vfs::StreamPtr stream = vfs::OpenRead(vfs::MakeMemoryFilename(dataBuf, memSize));
auto archive = m_entries[localID];
while (true)
{
// read the header
if (stream->Read(&header, sizeof(header)) != sizeof(header))
{
break;
}
// does the identification match?
if (header.ident != COLL)
{
break;
}
// read the collision data
std::vector<uint8_t> data = stream->Read(header.size);
// read the name
char name[24];
memcpy(name, &data[0], sizeof(name));
// read the collision model
std::shared_ptr<CColModel> model = std::make_shared<CColModel>();
readColModel(model.get(), &data[24]);
// get the model info
ModelManager::ModelResource* modelResource = theGame->GetModelManager().GetModelByName(name);
// store data
std::unique_ptr<CollisionModel> colModel = std::make_unique<CollisionModel>();
colModel->name = name;
colModel->model = model;
if (modelResource)
{
colModel->modelIndex = modelResource->GetID();
modelResource->SetCollisionModel(model);
}
else
{
colModel->modelIndex = -1;
}
archive->m_models.push_back(std::move(colModel));
}
}
void CollisionStore::UnloadResource(streaming::ident_t localID)
{
std::shared_ptr<CollisionArchive> archive = m_entries[localID];
// this should dereference everything inside
archive->m_models.clear();
}
size_t CollisionStore::GetObjectMemorySize(streaming::ident_t localID) const
{
return 1;
}
ConsoleCommand loadCollCommand("load_coll", [] (const std::string& path)
{
streaming::ident_t identifier = theGame->GetCollisionStore().RegisterCollisionArchive(path, path);
if (identifier != -1)
{
theGame->GetStreaming().Request(identifier);
theGame->GetStreaming().LoadingBarrier();
}
});
}
\ No newline at end of file
......@@ -306,6 +306,24 @@ static bool RpClumpCalculateBoundingSphere(rw::Clump* clump, rw::Sphere& sphereO
bool Entity::GetWorldBoundingSphere(rw::Sphere& sphereOut) const
{
// prefer a collision model
auto colModel = GetModelInfo()->GetCollisionModel();
if (colModel)
{
sphereOut.center = rw::add(colModel->boundingSphere.center, this->GetMatrix().pos);
sphereOut.radius = colModel->boundingSphere.radius;
// if the radius is empty, don't do anything
if (sphereOut.radius == 0.0f)
{
return false;
}
return true;
}
// try RW objects
rw::Object* rwObj = this->rwObject;
if (rwObj == NULL)
......
......@@ -30,7 +30,7 @@ namespace krt
Game* theGame = NULL;
Game::Game(const std::vector<std::pair<std::string, std::string>>& setList) : streaming(GAME_NUM_STREAMING_CHANNELS), texManager(streaming), modelManager(streaming, texManager)
Game::Game(const std::vector<std::pair<std::string, std::string>>& setList) : streaming(GAME_NUM_STREAMING_CHANNELS), texManager(streaming), modelManager(streaming, texManager), colStore(streaming)
{
assert(theGame == NULL);
......
......@@ -87,6 +87,12 @@ void GameUniverse::LoadConfiguration(const std::string& relativePath)
localConsole.ExecuteSingleCommand(ProgramArguments{"add_cdimage", m_configuration.gameName, path});
});
ConsoleCommand colFileCmg(&localConsole, "COLFILE",
[&] (int levelNum, const std::string& fileName)
{
localConsole.ExecuteSingleCommand(ProgramArguments{"load_coll", GetMountPoint() + fileName});
});
// run the configuration file
localConsole.AddToBuffer(std::string(reinterpret_cast<char*>(string.data()), string.size()));
localConsole.ExecuteBuffer();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment