1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 10:22:52 +01:00

Remove global texture list and use a slot name to lookup textures

This commit is contained in:
Daniel Evans 2016-12-03 21:18:28 +00:00
parent 6ca849dd8f
commit d75c476221
11 changed files with 92 additions and 84 deletions

View File

@ -37,13 +37,13 @@ void GameData::load() {
/// @todo cuts.img files should be loaded differently to gta3.img /// @todo cuts.img files should be loaded differently to gta3.img
loadIMG("anim/cuts.img"); loadIMG("anim/cuts.img");
loadLevelFile("data/default.dat"); textureslots["particle"] = loadTextureArchive("particle.txd");
loadLevelFile("data/gta3.dat"); textureslots["icons"] = loadTextureArchive("icons.txd");
textureslots["hud"] = loadTextureArchive("hud.txd");
loadTXD("particle.txd"); textureslots["fonts"] = loadTextureArchive("fonts.txd");
loadTXD("icons.txd"); textureslots["generic"] = loadTextureArchive("generic.txd");
loadTXD("hud.txd"); auto misc = loadTextureArchive("misc.txd");
loadTXD("fonts.txd"); textureslots["generic"].insert(misc.begin(), misc.end());
loadCarcols("data/carcols.dat"); loadCarcols("data/carcols.dat");
loadWeather("data/timecyc.dat"); loadWeather("data/timecyc.dat");
@ -52,6 +52,9 @@ void GameData::load() {
loadWeaponDAT("data/weapon.dat"); loadWeaponDAT("data/weapon.dat");
loadIFP("ped.ifp"); loadIFP("ped.ifp");
loadLevelFile("data/default.dat");
loadLevelFile("data/gta3.dat");
} }
void GameData::loadLevelFile(const std::string& path) { void GameData::loadLevelFile(const std::string& path) {
@ -63,6 +66,9 @@ void GameData::loadLevelFile(const std::string& path) {
return; return;
} }
// Reset texture slot
currenttextureslot = "generic";
for (std::string line, cmd; std::getline(datfile, line);) { for (std::string line, cmd; std::getline(datfile, line);) {
if (line.size() == 0 || line[0] == '#') continue; if (line.size() == 0 || line[0] == '#') continue;
#ifndef RW_WINDOWS #ifndef RW_WINDOWS
@ -296,23 +302,41 @@ void GameData::loadWater(const std::string& path) {
} }
void GameData::loadTXD(const std::string& name) { void GameData::loadTXD(const std::string& name) {
if (loadedFiles.find(name) != loadedFiles.end()) { auto slot = name;
auto ext = name.find(".txd");
if (ext != std::string::npos) {
slot = name.substr(0, ext);
}
// Set the current texture slot
currenttextureslot = slot;
// Check if this texture slot is loaded already
auto slotit = textureslots.find(slot);
if (slotit != textureslots.end()) {
return; return;
} }
loadedFiles[name] = true; textureslots[slot] = std::move(loadTextureArchive(name));
}
TextureArchive GameData::loadTextureArchive(const std::string& name) {
/// @todo refactor loadTXD to use correct file locations /// @todo refactor loadTXD to use correct file locations
auto file = index.openFile(name); auto file = index.openFile(name);
if (!file) { if (!file) {
logger->error("Data", "Failed to open txd: " + name); logger->error("Data", "Failed to open txd: " + name);
return; return {};
} }
TextureArchive textures;
TextureLoader l; TextureLoader l;
if (!l.loadFromMemory(file, textures)) { if (!l.loadFromMemory(file, textures)) {
logger->error("Data", "Error loading txd: " + name); logger->error("Data", "Error loading txd: " + name);
return {};
} }
return textures;
} }
void GameData::getNameAndLod(std::string& name, int& lod) { void GameData::getNameAndLod(std::string& name, int& lod) {
@ -330,6 +354,11 @@ Model* GameData::loadClump(const std::string& name) {
return nullptr; return nullptr;
} }
LoaderDFF l; LoaderDFF l;
l.setTextureLookupCallback(
[&](const std::string& texture, const std::string&) {
// Lookup the texture in the current texture slot
return findSlotTexture(currenttextureslot, texture);
});
auto m = l.loadFromMemory(file); auto m = l.loadFromMemory(file);
if (!m) { if (!m) {
logger->error("Data", "Error loading model file " + name); logger->error("Data", "Error loading model file " + name);
@ -345,6 +374,12 @@ void GameData::loadModelFile(const std::string& name) {
return; return;
} }
LoaderDFF l; LoaderDFF l;
l.setTextureLookupCallback(
[&](const std::string& texture, const std::string&) {
// Lookup the texture in the current texture slot
return findSlotTexture(currenttextureslot, texture);
});
auto m = l.loadFromMemory(file); auto m = l.loadFromMemory(file);
if (!m) { if (!m) {
logger->log("Data", Logger::Error, "Error loading model file " + name); logger->log("Data", Logger::Error, "Error loading model file " + name);
@ -374,14 +409,14 @@ void GameData::loadModel(ModelID model) {
auto info = modelinfo[model].get(); auto info = modelinfo[model].get();
/// @todo replace openFile with API for loading from CDIMAGE archives /// @todo replace openFile with API for loading from CDIMAGE archives
auto name = info->name; auto name = info->name;
auto slotname = info->textureslot;
// Re-direct special models // Re-direct special models
switch (info->type()) { switch (info->type()) {
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 slotname = name;
loadTXD(name + ".txd");
break; break;
case ModelDataType::PedInfo: case ModelDataType::PedInfo:
static const std::string specialPrefix("special"); static const std::string specialPrefix("special");
@ -389,8 +424,7 @@ 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 slotname = name;
loadTXD(name + ".txd");
break; break;
} }
default: default:
@ -398,6 +432,12 @@ void GameData::loadModel(ModelID model) {
} }
std::transform(name.begin(), name.end(), name.begin(), ::tolower); std::transform(name.begin(), name.end(), name.begin(), ::tolower);
std::transform(slotname.begin(), slotname.end(), slotname.begin(),
::tolower);
/// @todo remove this from here
loadTXD(slotname + ".txd");
auto file = index.openFile(name + ".dff"); auto file = index.openFile(name + ".dff");
if (!file) { if (!file) {
logger->error("Data", "Failed to load model for " + logger->error("Data", "Failed to load model for " +
@ -405,6 +445,11 @@ void GameData::loadModel(ModelID model) {
return; return;
} }
LoaderDFF l; LoaderDFF l;
l.setTextureLookupCallback(
[&](const std::string& texture, const std::string&) {
// Lookup the texture in the current texture slot
return findSlotTexture(currenttextureslot, texture);
});
auto m = l.loadFromMemory(file); auto m = l.loadFromMemory(file);
if (!m) { if (!m) {
logger->error("Data", logger->error("Data",

View File

@ -39,6 +39,7 @@ class GameData {
private: private:
std::string datpath; std::string datpath;
std::string splash; std::string splash;
std::string currenttextureslot;
Logger* logger; Logger* logger;
public: public:
@ -111,10 +112,16 @@ public:
void loadLevelFile(const std::string& path); void loadLevelFile(const std::string& path);
/** /**
* Attempts to load a TXD, or does nothing if it has already been loaded * Loads the txt slot if it is not already loaded and sets
* the current TXD slot
*/ */
void loadTXD(const std::string& name); void loadTXD(const std::string& name);
/**
* Loads a named texture archive from the game data
*/
TextureArchive loadTextureArchive(const std::string& name);
/** /**
* Converts combined {name}_l{LOD} into name and lod. * Converts combined {name}_l{LOD} into name and lod.
*/ */
@ -155,9 +162,17 @@ public:
void loadSplash(const std::string& name); void loadSplash(const std::string& name);
TextureData::Handle findTexture(const std::string& name, TextureData::Handle findSlotTexture(const std::string& slot,
const std::string& alpha = "") { const std::string& texture) const {
return textures[{name, alpha}]; auto slotit = textureslots.find(slot);
if (slotit == textureslots.end()) {
return nullptr;
}
auto textureit = slotit->second.find(texture);
if (textureit == slotit->second.end()) {
return nullptr;
}
return textureit->second;
} }
FileIndex index; FileIndex index;
@ -222,9 +237,9 @@ public:
WeatherLoader weatherLoader; WeatherLoader weatherLoader;
/** /**
* Loaded textures (Textures are ID by name and alpha pairs) * Texture slots, containing loaded textures.
*/ */
std::map<std::pair<std::string, std::string>, TextureData::Handle> textures; std::map<std::string, TextureArchive> textureslots;
/** /**
* Texture atlases. * Texture atlases.

View File

@ -158,18 +158,6 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
data->loadModel(oi->id()); data->loadModel(oi->id());
} }
std::string modelname = oi->name;
std::string texturename = oi->textureslot;
std::transform(std::begin(modelname), std::end(modelname),
std::begin(modelname), tolower);
std::transform(std::begin(texturename), std::end(texturename),
std::begin(texturename), tolower);
if (!texturename.empty()) {
data->loadTXD(texturename + ".txd");
}
// 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;
@ -177,7 +165,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
dydata = dyit->second; dydata = dyit->second;
} }
if (modelname.empty()) { if (oi->name.empty()) {
logger->warning( logger->warning(
"World", "Instance with missing model: " + std::to_string(id)); "World", "Instance with missing model: " + std::to_string(id));
} }
@ -243,15 +231,12 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id,
} }
auto clumpmodel = static_cast<ClumpModelInfo*>(modelinfo); auto clumpmodel = static_cast<ClumpModelInfo*>(modelinfo);
std::string texturename;
if (!clumpmodel->isLoaded()) { if (!clumpmodel->isLoaded()) {
data->loadModel(id); data->loadModel(id);
} }
auto model = clumpmodel->getModel(); 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) {
@ -259,10 +244,6 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id,
} }
} }
if (!texturename.empty()) {
data->loadTXD(texturename + ".txd");
}
auto instance = new CutsceneObject(this, pos, rot, model, modelinfo); auto instance = new CutsceneObject(this, pos, rot, model, modelinfo);
cutscenePool.insert(instance); cutscenePool.insert(instance);
@ -285,10 +266,6 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
data->loadModel(id); data->loadModel(id);
} }
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)
@ -361,12 +338,6 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id,
data->loadModel(id); data->loadModel(id);
} }
std::string texturename = pt->textureslot;
if (!texturename.empty()) {
data->loadTXD(texturename + ".txd");
}
auto ped = new CharacterObject(this, pos, rot, pt); auto ped = new CharacterObject(this, pos, rot, pt);
ped->setGameObjectID(gid); ped->setGameObjectID(gid);
new DefaultAIController(ped); new DefaultAIController(ped);
@ -388,13 +359,12 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos,
std::string modelname = "player"; std::string modelname = "player";
std::string texturename = "player"; std::string texturename = "player";
data->loadTXD(texturename + ".txd");
if (!pt->isLoaded()) { if (!pt->isLoaded()) {
auto model = data->loadClump(modelname + ".dff"); auto model = data->loadClump(modelname + ".dff");
pt->setModel(model); pt->setModel(model);
} }
data->loadTXD(texturename + ".txd");
auto ped = new CharacterObject(this, pos, rot, pt); auto ped = new CharacterObject(this, pos, rot, pt);
ped->setGameObjectID(gid); ped->setGameObjectID(gid);
ped->setLifetime(GameObject::PlayerLifetime); ped->setLifetime(GameObject::PlayerLifetime);
@ -416,8 +386,6 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
data->loadModel(id); data->loadModel(id);
} }
data->loadTXD(modelInfo->textureslot + ".txd");
PickupObject* pickup = nullptr; PickupObject* pickup = nullptr;
auto pickuptype = (PickupObject::PickupType)type; auto pickuptype = (PickupObject::PickupType)type;

View File

@ -83,7 +83,7 @@ PickupObject::PickupObject(GameWorld* world, const glm::vec3& position,
m_corona->particle.direction = glm::vec3(0.f, 0.f, 1.f); m_corona->particle.direction = glm::vec3(0.f, 0.f, 1.f);
m_corona->particle.orientation = VisualFX::ParticleData::Camera; m_corona->particle.orientation = VisualFX::ParticleData::Camera;
m_corona->particle.colour = glm::vec4(1.0f, 0.3f, 0.3f, 0.3f); m_corona->particle.colour = glm::vec4(1.0f, 0.3f, 0.3f, 0.3f);
m_corona->particle.texture = engine->data->findTexture("coronacircle"); m_corona->particle.texture = engine->data->findSlotTexture("particle", "coronacircle");
auto flags = behaviourFlags(m_type); auto flags = behaviourFlags(m_type);
RW_UNUSED(flags); RW_UNUSED(flags);

View File

@ -71,7 +71,7 @@ void ProjectileObject::explode() {
0.f}); 0.f});
} }
auto tex = engine->data->findTexture("explo02"); auto tex = engine->data->findSlotTexture("particle", "explo02");
auto explosion = engine->createEffect(VisualFX::Particle); auto explosion = engine->createEffect(VisualFX::Particle);
explosion->particle.size = glm::vec2(exp_size); explosion->particle.size = glm::vec2(exp_size);

View File

@ -404,7 +404,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
GLuint splashTexName = 0; GLuint splashTexName = 0;
auto fc = world->state->fadeColour; auto fc = world->state->fadeColour;
if ((fc.r + fc.g + fc.b) == 0 && world->state->currentSplash.size() > 0) { if ((fc.r + fc.g + fc.b) == 0 && world->state->currentSplash.size() > 0) {
auto splash = world->data->findTexture(world->state->currentSplash); auto splash = world->data->findSlotTexture("generic", world->state->currentSplash);
if (splash) { if (splash) {
splashTexName = splash->getName(); splashTexName = splash->getName();
} }
@ -494,16 +494,6 @@ void GameRenderer::renderGeometry(Model* model, size_t g,
if (mat.textures.size() > 0) { if (mat.textures.size() > 0) {
auto tex = mat.textures[0].texture; auto tex = mat.textures[0].texture;
if (!tex) {
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
tex = data->findTexture(tC, tA);
if (!tex) {
// logger->warning("Renderer", "Missing texture: " + tC
// + " " + tA);
}
mat.textures[0].texture = tex;
}
if (tex) { if (tex) {
dp.textures = {tex->getName()}; dp.textures = {tex->getName()};
} }

View File

@ -115,7 +115,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
for (int m = 0; m < MAP_BLOCK_SIZE; ++m) { for (int m = 0; m < MAP_BLOCK_SIZE; ++m) {
std::string num = (m < 10 ? "0" : ""); std::string num = (m < 10 ? "0" : "");
std::string name = "radar" + num + std::to_string(m); std::string name = "radar" + num + std::to_string(m);
auto texture = world->data->textures[{name, ""}]; auto texture = world->data->findSlotTexture(name, name);
glBindTexture(GL_TEXTURE_2D, texture->getName()); glBindTexture(GL_TEXTURE_2D, texture->getName());
@ -140,7 +140,8 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
// We only need the outer ring if we're clipping. // We only need the outer ring if we're clipping.
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO); glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO);
TextureData::Handle radarDisc = data->findTexture("radardisc"); TextureData::Handle radarDisc =
data->findSlotTexture("hud", "radardisc");
glm::mat4 model; glm::mat4 model;
model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f)); model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f));
@ -257,7 +258,7 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view,
GLuint tex = 0; GLuint tex = 0;
if (!texture.empty()) { if (!texture.empty()) {
auto sprite = data->findTexture(texture); auto sprite = data->findSlotTexture("hud", texture);
tex = sprite->getName(); tex = sprite->getName();
} }
renderer->setUniform(rectProg, "colour", colour); renderer->setUniform(rectProg, "colour", colour);

View File

@ -61,17 +61,6 @@ void ObjectRenderer::renderGeometry(Model* model, size_t g,
if (mat.textures.size() > 0) { if (mat.textures.size() > 0) {
auto tex = mat.textures[0].texture; auto tex = mat.textures[0].texture;
if (!tex) {
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
tex = m_world->data->findTexture(tC, tA);
if (!tex) {
// logger->warning("Renderer", "Missing texture: " + tC
// + " " + tA);
dp.textures = {m_errorTexture};
}
mat.textures[0].texture = tex;
}
if (tex) { if (tex) {
if (tex->isTransparent()) { if (tex->isTransparent()) {
isTransparent = true; isTransparent = true;

View File

@ -284,7 +284,7 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
Renderer::DrawParameters dp; Renderer::DrawParameters dp;
dp.start = 0; dp.start = 0;
dp.count = gb.getCount(); dp.count = gb.getCount();
auto ftexture = renderer->getData()->findTexture(fonts[ti.font]); auto ftexture = renderer->getData()->findSlotTexture("fonts", fonts[ti.font]);
dp.textures = {ftexture->getName()}; dp.textures = {ftexture->getName()};
dp.depthWrite = false; dp.depthWrite = false;

View File

@ -98,7 +98,7 @@ void WaterRenderer::setDataTexture(GLuint fbBinding, GLuint dataTex) {
void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) { void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) {
auto r = renderer->getRenderer(); auto r = renderer->getRenderer();
auto waterTex = world->data->findTexture("water_old"); auto waterTex = world->data->findSlotTexture("particle", "water_old");
RW_CHECK(waterTex != nullptr, "Water texture is null"); RW_CHECK(waterTex != nullptr, "Water texture is null");
if (waterTex == nullptr) { if (waterTex == nullptr) {
// Can't render water if we don't have a texture. // Can't render water if we don't have a texture.

View File

@ -168,7 +168,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world,
} }
TextureData::Handle itemTexture = TextureData::Handle itemTexture =
render->getData()->findTexture(itemTextureName); render->getData()->findSlotTexture("hud", itemTextureName);
RW_CHECK(itemTexture != nullptr, "Item has 0 texture"); RW_CHECK(itemTexture != nullptr, "Item has 0 texture");
if (itemTexture != nullptr) { if (itemTexture != nullptr) {
RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture"); RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture");