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

Merge pull request #254 from danhedron/texture-slots

Load textures into separate groups
This commit is contained in:
Daniel Evans 2016-12-04 01:04:53 +00:00 committed by GitHub
commit 04e79a5117
16 changed files with 102 additions and 102 deletions

View File

@ -5,7 +5,6 @@
#include <engine/GameState.hpp>
#include <engine/GameWorld.hpp>
#include <loaders/LoaderCOL.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIPL.hpp>
#include <script/SCMFile.hpp>
@ -23,6 +22,10 @@
GameData::GameData(Logger* log, const std::string& path)
: datpath(path), logger(log), engine(nullptr) {
dffLoader.setTextureLookupCallback(
[&](const std::string& texture, const std::string&) {
return findSlotTexture(currenttextureslot, texture);
});
}
GameData::~GameData() {
@ -37,13 +40,13 @@ void GameData::load() {
/// @todo cuts.img files should be loaded differently to gta3.img
loadIMG("anim/cuts.img");
loadLevelFile("data/default.dat");
loadLevelFile("data/gta3.dat");
loadTXD("particle.txd");
loadTXD("icons.txd");
loadTXD("hud.txd");
loadTXD("fonts.txd");
textureslots["particle"] = loadTextureArchive("particle.txd");
textureslots["icons"] = loadTextureArchive("icons.txd");
textureslots["hud"] = loadTextureArchive("hud.txd");
textureslots["fonts"] = loadTextureArchive("fonts.txd");
textureslots["generic"] = loadTextureArchive("generic.txd");
auto misc = loadTextureArchive("misc.txd");
textureslots["generic"].insert(misc.begin(), misc.end());
loadCarcols("data/carcols.dat");
loadWeather("data/timecyc.dat");
@ -52,6 +55,9 @@ void GameData::load() {
loadWeaponDAT("data/weapon.dat");
loadIFP("ped.ifp");
loadLevelFile("data/default.dat");
loadLevelFile("data/gta3.dat");
}
void GameData::loadLevelFile(const std::string& path) {
@ -63,6 +69,9 @@ void GameData::loadLevelFile(const std::string& path) {
return;
}
// Reset texture slot
currenttextureslot = "generic";
for (std::string line, cmd; std::getline(datfile, line);) {
if (line.size() == 0 || line[0] == '#') continue;
#ifndef RW_WINDOWS
@ -296,23 +305,41 @@ void GameData::loadWater(const std::string& path) {
}
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;
}
loadedFiles[name] = true;
textureslots[slot] = std::move(loadTextureArchive(name));
}
TextureArchive GameData::loadTextureArchive(const std::string& name) {
/// @todo refactor loadTXD to use correct file locations
auto file = index.openFile(name);
if (!file) {
logger->error("Data", "Failed to open txd: " + name);
return;
return {};
}
TextureArchive textures;
TextureLoader l;
if (!l.loadFromMemory(file, textures)) {
logger->error("Data", "Error loading txd: " + name);
return {};
}
return textures;
}
void GameData::getNameAndLod(std::string& name, int& lod) {
@ -329,8 +356,7 @@ Model* GameData::loadClump(const std::string& name) {
logger->error("Data", "Failed to load model " + name);
return nullptr;
}
LoaderDFF l;
auto m = l.loadFromMemory(file);
auto m = dffLoader.loadFromMemory(file);
if (!m) {
logger->error("Data", "Error loading model file " + name);
return nullptr;
@ -344,8 +370,7 @@ void GameData::loadModelFile(const std::string& name) {
logger->log("Data", Logger::Error, "Failed to load model file " + name);
return;
}
LoaderDFF l;
auto m = l.loadFromMemory(file);
auto m = dffLoader.loadFromMemory(file);
if (!m) {
logger->log("Data", Logger::Error, "Error loading model file " + name);
return;
@ -374,14 +399,14 @@ void GameData::loadModel(ModelID model) {
auto info = modelinfo[model].get();
/// @todo replace openFile with API for loading from CDIMAGE archives
auto name = info->name;
auto slotname = info->textureslot;
// 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()];
/// @todo remove this from here
loadTXD(name + ".txd");
slotname = name;
break;
case ModelDataType::PedInfo:
static const std::string specialPrefix("special");
@ -389,8 +414,7 @@ void GameData::loadModel(ModelID model) {
auto sid = name.substr(specialPrefix.size());
unsigned short specialID = std::atoi(sid.c_str());
name = engine->state->specialCharacters[specialID];
/// @todo remove this from here
loadTXD(name + ".txd");
slotname = name;
break;
}
default:
@ -398,14 +422,19 @@ void GameData::loadModel(ModelID model) {
}
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");
if (!file) {
logger->error("Data", "Failed to load model for " +
std::to_string(model) + " [" + name + "]");
return;
}
LoaderDFF l;
auto m = l.loadFromMemory(file);
auto m = dffLoader.loadFromMemory(file);
if (!m) {
logger->error("Data",
"Error loading model file for " + std::to_string(model));

View File

@ -39,8 +39,10 @@ class GameData {
private:
std::string datpath;
std::string splash;
std::string currenttextureslot;
Logger* logger;
LoaderDFF dffLoader;
public:
/**
* ctor
@ -111,10 +113,16 @@ public:
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);
/**
* Loads a named texture archive from the game data
*/
TextureArchive loadTextureArchive(const std::string& name);
/**
* Converts combined {name}_l{LOD} into name and lod.
*/
@ -155,9 +163,17 @@ public:
void loadSplash(const std::string& name);
TextureData::Handle findTexture(const std::string& name,
const std::string& alpha = "") {
return textures[{name, alpha}];
TextureData::Handle findSlotTexture(const std::string& slot,
const std::string& texture) const {
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;
@ -222,9 +238,9 @@ public:
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.

View File

@ -158,18 +158,6 @@ InstanceObject* GameWorld::createInstance(const uint16_t 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.
auto dyit = data->dynamicObjectData.find(oi->name);
std::shared_ptr<DynamicObjectData> dydata;
@ -177,7 +165,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id,
dydata = dyit->second;
}
if (modelname.empty()) {
if (oi->name.empty()) {
logger->warning(
"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);
std::string texturename;
if (!clumpmodel->isLoaded()) {
data->loadModel(id);
}
auto model = clumpmodel->getModel();
texturename = modelinfo->textureslot;
if (id == 0) {
auto playerobj = pedestrianPool.find(state->playerObject);
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);
cutscenePool.insert(instance);
@ -285,10 +266,6 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
data->loadModel(id);
}
if (!vti->textureslot.empty()) {
data->loadTXD(vti->textureslot + ".txd");
}
glm::u8vec3 prim(255), sec(128);
auto palit = data->vehiclePalettes.find(
vti->name); // modelname is conveniently lowercase (usually)
@ -361,12 +338,6 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id,
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);
@ -388,13 +359,12 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos,
std::string modelname = "player";
std::string texturename = "player";
data->loadTXD(texturename + ".txd");
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);
@ -416,8 +386,6 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
data->loadModel(id);
}
data->loadTXD(modelInfo->textureslot + ".txd");
PickupObject* pickup = nullptr;
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.orientation = VisualFX::ParticleData::Camera;
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);
RW_UNUSED(flags);

View File

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

View File

@ -404,7 +404,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
GLuint splashTexName = 0;
auto fc = world->state->fadeColour;
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) {
splashTexName = splash->getName();
}
@ -494,16 +494,6 @@ void GameRenderer::renderGeometry(Model* model, size_t g,
if (mat.textures.size() > 0) {
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) {
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) {
std::string num = (m < 10 ? "0" : "");
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());
@ -140,7 +140,8 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
glDisable(GL_STENCIL_TEST);
// We only need the outer ring if we're clipping.
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;
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;
if (!texture.empty()) {
auto sprite = data->findTexture(texture);
auto sprite = data->findSlotTexture("hud", texture);
tex = sprite->getName();
}
renderer->setUniform(rectProg, "colour", colour);

View File

@ -61,17 +61,6 @@ void ObjectRenderer::renderGeometry(Model* model, size_t g,
if (mat.textures.size() > 0) {
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->isTransparent()) {
isTransparent = true;

View File

@ -284,7 +284,7 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
Renderer::DrawParameters dp;
dp.start = 0;
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.depthWrite = false;

View File

@ -98,7 +98,7 @@ void WaterRenderer::setDataTexture(GLuint fbBinding, GLuint dataTex) {
void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) {
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");
if (waterTex == nullptr) {
// 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 =
render->getData()->findTexture(itemTextureName);
render->getData()->findSlotTexture("hud", itemTextureName);
RW_CHECK(itemTexture != nullptr, "Item has 0 texture");
if (itemTexture != nullptr) {
RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture");

View File

@ -1,6 +1,7 @@
#pragma once
#include <gl/gl_core_3_3.h>
#include <glm/glm.hpp>
#include <map>
#include <memory>
@ -37,3 +38,4 @@ private:
glm::ivec2 size;
bool hasAlpha;
};
using TextureArchive = std::map<std::string, TextureData::Handle>;

View File

@ -341,8 +341,10 @@ void LoaderDFF::readTexture(Model *model, const RWBStream &stream) {
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower);
TextureData::Handle textureinst =
texturelookup ? texturelookup(name, alpha) : nullptr;
model->geometries.back()->materials.back().textures.push_back(
{name, alpha, nullptr});
{name, alpha, textureinst});
}
void LoaderDFF::readGeometryExtension(Model *model, const RWBStream &stream) {

View File

@ -2,14 +2,14 @@
#ifndef _LOADERDFF_HPP_
#define _LOADERDFF_HPP_
#include <gl/TextureData.hpp>
#include <loaders/RWBinaryStream.hpp>
#include <platform/FileHandle.hpp>
#include <functional>
#include <string>
#include <vector>
class Model;
class GameData;
class DFFLoaderException {
std::string _message;
@ -48,7 +48,16 @@ class LoaderDFF {
void readAtomic(Model* model, const RWBStream& stream);
public:
using TextureLookupCallback = std::function<TextureData::Handle(
const std::string&, const std::string&)>;
Model* loadFromMemory(FileHandle file);
void setTextureLookupCallback(TextureLookupCallback tlc) {
texturelookup = tlc;
}
private:
TextureLookupCallback texturelookup;
};
#endif

View File

@ -182,11 +182,7 @@ bool TextureLoader::loadFromMemory(FileHandle file,
auto texture = createTexture(texNative, rootSection);
inTextures[{name, alpha}] = texture;
if (!alpha.empty()) {
inTextures[{name, ""}] = texture;
}
inTextures[name] = texture;
}
return true;

View File

@ -11,8 +11,6 @@
// This might suffice
#include <gl/TextureData.hpp>
typedef std::map<std::pair<std::string, std::string>, TextureData::Handle>
TextureArchive;
class FileIndex;