diff --git a/AnimModel.cpp b/AnimModel.cpp index 54e0d2b6..1c6814f8 100644 --- a/AnimModel.cpp +++ b/AnimModel.cpp @@ -449,12 +449,16 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable asText = asReplacableTexture.substr(1, asReplacableTexture.length() - 1); // zapamiętanie tekstu else if (asReplacableTexture != "none") ReplacableSkinId[1] = - TTexturesManager::GetTextureID(NULL, NULL, asReplacableTexture.c_str()); - if (TTexturesManager::GetAlpha(ReplacableSkinId[1])) - iTexAlpha = - 0x31310031; // tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych - else - iTexAlpha = 0x30300030; // tekstura nieprzezroczysta - nie renderować w cyklu + TTexturesManager.GetTextureId( asReplacableTexture, "" ); + if( ( ReplacableSkinId[ 1 ] != 0 ) + && ( TTexturesManager.Texture( ReplacableSkinId[ 1 ] ).has_alpha ) ) { + // tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych + iTexAlpha = 0x31310031; + } + else{ + // tekstura nieprzezroczysta - nie renderować w cyklu + iTexAlpha = 0x30300030; + } // przezroczystych return (Init(TModelsManager::GetModel(asName.c_str()))); } diff --git a/AnimModel.h b/AnimModel.h index 8ceebcda..bc688a5d 100644 --- a/AnimModel.h +++ b/AnimModel.h @@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/. #define AnimModelH #include "Model3d.h" +#include "Texture.h" const int iMaxNumLights = 8; @@ -148,7 +149,7 @@ class TAnimModel void RaAnimate(); // przeliczenie animacji egzemplarza void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu public: - GLuint ReplacableSkinId[5]; // McZapkie-020802: zmienialne skory + texture_manager::size_type ReplacableSkinId[5]; // McZapkie-020802: zmienialne skory static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane // również bez wyświetlania TAnimModel(); diff --git a/DynObj.cpp b/DynObj.cpp index 7c4618e0..2af42063 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -4417,7 +4417,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, Global::asCurrentTexturePath + ReplacableSkin; // skory tez z dynamic/... std::string x = TextureTest(Global::asCurrentTexturePath + "nowhere"); // na razie prymitywnie if (!x.empty()) - ReplacableSkinID[4] = TTexturesManager::GetTextureID(NULL, NULL, Global::asCurrentTexturePath + "nowhere", 9); + ReplacableSkinID[4] = TTexturesManager.GetTextureId( Global::asCurrentTexturePath + "nowhere", "", 9); /* if ((i = ReplacableSkin.Pos("|")) > 0) // replacable dzielone { @@ -4480,24 +4480,22 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, */ if (iMultiTex > 0) { // jeśli model ma 4 tekstury - ReplacableSkinID[1] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin + ",1", Global::iDynamicFiltering); + ReplacableSkinID[1] = TTexturesManager.GetTextureId( + ReplacableSkin + ",1", "", Global::iDynamicFiltering); if (ReplacableSkinID[1]) { // pierwsza z zestawu znaleziona - ReplacableSkinID[2] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin + ",2", Global::iDynamicFiltering); + ReplacableSkinID[2] = TTexturesManager.GetTextureId( + ReplacableSkin + ",2", "", Global::iDynamicFiltering); if (ReplacableSkinID[2]) { iMultiTex = 2; // już są dwie - ReplacableSkinID[3] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin + ",3", - Global::iDynamicFiltering); + ReplacableSkinID[3] = TTexturesManager.GetTextureId( + ReplacableSkin + ",3", "", Global::iDynamicFiltering); if (ReplacableSkinID[3]) { iMultiTex = 3; // a teraz nawet trzy - ReplacableSkinID[4] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin + ",4", - Global::iDynamicFiltering); + ReplacableSkinID[4] = TTexturesManager.GetTextureId( + ReplacableSkin + ",4", "", Global::iDynamicFiltering); if (ReplacableSkinID[4]) iMultiTex = 4; // jak są cztery, to blokujemy podmianę tekstury // rozkładem @@ -4507,14 +4505,14 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, else { // zestaw nie zadziałał, próbujemy normanie iMultiTex = 0; - ReplacableSkinID[1] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin, Global::iDynamicFiltering); + ReplacableSkinID[1] = TTexturesManager.GetTextureId( + ReplacableSkin, "", Global::iDynamicFiltering); } } else - ReplacableSkinID[1] = TTexturesManager::GetTextureID( - NULL, NULL, ReplacableSkin, Global::iDynamicFiltering); - if (TTexturesManager::GetAlpha(ReplacableSkinID[1])) + ReplacableSkinID[1] = TTexturesManager.GetTextureId( + ReplacableSkin, "", Global::iDynamicFiltering); + if (TTexturesManager.Texture(ReplacableSkinID[1]).has_alpha) iAlpha = 0x31310031; // tekstura -1 z kanałem alfa - nie renderować w cyklu // nieprzezroczystych else @@ -4522,21 +4520,22 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, // renderować w // cyklu przezroczystych if (ReplacableSkinID[2]) - if (TTexturesManager::GetAlpha(ReplacableSkinID[2])) + if (TTexturesManager.Texture(ReplacableSkinID[2]).has_alpha) iAlpha |= 0x02020002; // tekstura -2 z kanałem alfa - nie renderować // w cyklu // nieprzezroczystych if (ReplacableSkinID[3]) - if (TTexturesManager::GetAlpha(ReplacableSkinID[3])) + if (TTexturesManager.Texture(ReplacableSkinID[3]).has_alpha) iAlpha |= 0x04040004; // tekstura -3 z kanałem alfa - nie renderować // w cyklu // nieprzezroczystych if (ReplacableSkinID[4]) - if (TTexturesManager::GetAlpha(ReplacableSkinID[4])) + if (TTexturesManager.Texture(ReplacableSkinID[4]).has_alpha) iAlpha |= 0x08080008; // tekstura -4 z kanałem alfa - nie renderować // w cyklu // nieprzezroczystych } +/* // Winger 040304 - ladowanie przedsionkow dla EZT if (MoverParameters->TrainType == dt_EZT) { @@ -4544,6 +4543,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, asModel = BaseDir + asModel; mdPrzedsionek = TModelsManager::GetModel(asModel, true); } +*/ if (!MoverParameters->LoadAccepted.empty()) // if (MoverParameters->LoadAccepted!=AnsiString("")); // && // MoverParameters->LoadType!=AnsiString("passengers")) @@ -5849,13 +5849,13 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer) std::string x = TextureTest(asBaseDir + numer + "@" + MoverParameters->TypeName); if (!x.empty()) { - ReplacableSkinID[4] = TTexturesManager::GetTextureID( NULL, NULL, x, 9); // rozmywania 0,1,4,5 nie nadają się + ReplacableSkinID[4] = TTexturesManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się return; } x = TextureTest(asBaseDir + numer ); if (!x.empty()) { - ReplacableSkinID[4] = TTexturesManager::GetTextureID( NULL, NULL, x, 9); // rozmywania 0,1,4,5 nie nadają się + ReplacableSkinID[4] = TTexturesManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się return; } if (to.empty()) @@ -5863,17 +5863,17 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer) x = TextureTest(asBaseDir + to + "@" + MoverParameters->TypeName); // w pierwszej kolejności z nazwą FIZ/MMD if (!x.empty()) { - ReplacableSkinID[4] = TTexturesManager::GetTextureID( NULL, NULL, x, 9); // rozmywania 0,1,4,5 nie nadają się + ReplacableSkinID[4] = TTexturesManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się return; } x = TextureTest(asBaseDir + to); // na razie prymitywnie if (!x.empty()) - ReplacableSkinID[4] = TTexturesManager::GetTextureID( NULL, NULL, x, 9); // rozmywania 0,1,4,5 nie nadają się + ReplacableSkinID[4] = TTexturesManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się else { x = TextureTest(asBaseDir + "nowhere"); // jak nie znalazł dedykowanej, to niech daje nowhere if (!x.empty()) - ReplacableSkinID[4] = TTexturesManager::GetTextureID(NULL, NULL, x, 9); + ReplacableSkinID[4] = TTexturesManager.GetTextureId( x, "", 9); } // Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa // tekstury nr 4 diff --git a/DynObj.h b/DynObj.h index e49ff803..56f31d02 100644 --- a/DynObj.h +++ b/DynObj.h @@ -395,7 +395,7 @@ private: int iCabs; // maski bitowe modeli kabin TTrack *MyTrack; // McZapkie-030303: tor na ktorym stoi, ABu std::string asBaseDir; - GLuint ReplacableSkinID[5]; // McZapkie:zmienialne nadwozie + texture_manager::size_type ReplacableSkinID[5]; // McZapkie:zmienialne nadwozie int iAlpha; // maska przezroczystości tekstur int iMultiTex; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna int iOverheadMask; // maska przydzielana przez AI pojazdom posiadającym pantograf, aby wymuszały diff --git a/Globals.cpp b/Globals.cpp index 397f0a6d..1780eee5 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -60,8 +60,8 @@ int Global::iScreenMode[12] = {0, 0, 0, 0, 0, 0, double Global::fSunDeclination = 0.0; // deklinacja Słońca double Global::fTimeAngleDeg = 0.0; // godzina w postaci kąta float Global::fClockAngleDeg[6]; // kąty obrotu cylindrów dla zegara cyfrowego -char *Global::szTexturesTGA[4] = {"tga", "dds", "tex", "bmp"}; // lista tekstur od TGA -char *Global::szTexturesDDS[4] = {"dds", "tga", "tex", "bmp"}; // lista tekstur od DDS +std::string Global::szTexturesTGA = ".tga"; // lista tekstur od TGA +std::string Global::szTexturesDDS = ".dds"; // lista tekstur od DDS int Global::iKeyLast = 0; // ostatnio naciśnięty klawisz w celu logowania GLuint Global::iTextureId = 0; // ostatnio użyta tekstura 2D int Global::iPause = 0x10; // globalna pauza ruchu @@ -135,7 +135,7 @@ int Global::iDynamicFiltering = 5; // domyślne rozmywanie tekstur pojazdów bool Global::bUseVBO = false; // czy jest VBO w karcie graficznej (czy użyć) GLint Global::iMaxTextureSize = 16384; // maksymalny rozmiar tekstury bool Global::bSmoothTraction = false; // wygładzanie drutów starym sposobem -char **Global::szDefaultExt = Global::szTexturesDDS; // domyślnie od DDS +std::string Global::szDefaultExt = Global::szTexturesDDS; // domyślnie od DDS int Global::iMultisampling = 2; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px bool Global::bGlutFont = false; // czy tekst generowany przez GLUT32.DLL int Global::iConvertModels = 7; // tworzenie plików binarnych, +2-optymalizacja transformów @@ -422,6 +422,12 @@ void Global::ConfigParse(cParser &Parser) // domyślnie od TGA Global::szDefaultExt = Global::szTexturesTGA; } + else { + Global::szDefaultExt = + ( token[ 0 ] == '.' ? + token : + "." + token ); + } } else if (token == "newaircouplers") { diff --git a/Globals.h b/Globals.h index 38f18281..c50f5d83 100644 --- a/Globals.h +++ b/Globals.h @@ -184,7 +184,7 @@ class Global static double fFogStart; static double fFogEnd; static TGround *pGround; - static char **szDefaultExt; + static std::string szDefaultExt; static std::string SceneryFile; static char CreatorName1[20]; static char CreatorName2[20]; @@ -258,8 +258,8 @@ class Global static double fTimeAngleDeg; // godzina w postaci kąta static float fClockAngleDeg[6]; // kąty obrotu cylindrów dla zegara cyfrowego static double fLatitudeDeg; // szerokość geograficzna - static char *szTexturesTGA[4]; // lista tekstur od TGA - static char *szTexturesDDS[4]; // lista tekstur od DDS + static std::string szTexturesTGA; // lista tekstur od TGA + static std::string szTexturesDDS; // lista tekstur od DDS static int iMultisampling; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px static bool bGlutFont; // tekst generowany przez GLUT static int iKeyLast; // ostatnio naciśnięty klawisz w celu logowania diff --git a/Ground.cpp b/Ground.cpp index 39f74e65..69df2d6e 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -2103,14 +2103,14 @@ TGroundNode * TGround::AddGroundNode(cParser *parser) // PROBLEND Q: 13122011 - Szociu: 27012012 PROBLEND = true; // domyslnie uruchomione nowe wyświetlanie tmp->PROBLEND = true; // odwolanie do tgroundnode, bo rendering jest w tej klasie - if (str.find("@") != string::npos) // sprawdza, czy w nazwie tekstury jest znak "@" + if (str.find('@') != string::npos) // sprawdza, czy w nazwie tekstury jest znak "@" { PROBLEND = false; // jeśli jest, wyswietla po staremu tmp->PROBLEND = false; } #endif - tmp->TextureID = TTexturesManager::GetTextureID(szTexturePath, szSceneryPath, str.c_str()); - tmp->iFlags = TTexturesManager::GetAlpha(tmp->TextureID) ? 0x220 : 0x210; // z usuwaniem + tmp->TextureID = TTexturesManager.GetTextureId( str, szTexturePath ); + tmp->iFlags = TTexturesManager.Texture(tmp->TextureID).has_alpha ? 0x220 : 0x210; // z usuwaniem if (((tmp->iType == GL_TRIANGLES) && (tmp->iFlags & 0x10)) ? Global::pTerrainCompact->TerrainLoaded() : false) diff --git a/Ground.h b/Ground.h index 099eff67..b78023d6 100644 --- a/Ground.h +++ b/Ground.h @@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/. #include "VBO.h" #include "Classes.h" #include "ResourceManager.h" +#include "Texture.h" #include "dumb3d.h" #include "Names.h" @@ -141,7 +142,7 @@ class TGroundNode : public Resource GLuint DisplayListID; // numer siatki DisplayLists bool PROBLEND; int iVboPtr; // indeks w buforze VBO - GLuint TextureID; // główna (jedna) tekstura obiektu + texture_manager::size_type TextureID; // główna (jedna) tekstura obiektu int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany int Ambient[4], Diffuse[4], Specular[4]; // oświetlenie bool bVisible; diff --git a/Model3d.cpp b/Model3d.cpp index f70dd091..59f9bbbc 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -411,13 +411,12 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic) TextureNameSet(texture.c_str()); if (texture.find_first_of("/\\") == texture.npos) texture.insert(0, Global::asCurrentTexturePath.c_str()); - TextureID = TTexturesManager::GetTextureID( - szTexturePath, const_cast(Global::asCurrentTexturePath.c_str()), texture); + TextureID = TTexturesManager.GetTextureId( texture, szTexturePath ); // TexAlpha=TTexturesManager::GetAlpha(TextureID); // iFlags|=TexAlpha?0x20:0x10; //0x10-nieprzezroczysta, 0x20-przezroczysta if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity // 0! - iFlags |= TTexturesManager::GetAlpha(TextureID) ? + iFlags |= TTexturesManager.Texture(TextureID).has_alpha ? 0x20 : 0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta else @@ -616,7 +615,7 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic) return iNumVerts; // do określenia wielkości VBO }; -int TSubModel::TriangleAdd(TModel3d *m, int tex, int tri) +int TSubModel::TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri) { // dodanie trójkątów do submodelu, używane // przy tworzeniu E3D terenu TSubModel *s = this; @@ -637,7 +636,7 @@ int TSubModel::TriangleAdd(TModel3d *m, int tex, int tri) m->AddTo(this, s); } // s->asTexture=AnsiString(TTexturesManager::GetName(tex).c_str()); - s->TextureNameSet(TTexturesManager::GetName(tex).c_str()); + s->TextureNameSet(TTexturesManager.Texture(tex).name.c_str()); s->TextureID = tex; s->eType = GL_TRIANGLES; // iAnimOwner=0; //roboczy wskaźnik na wierzchołek @@ -1625,15 +1624,14 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v, TStringPack *t, TS std::string tex = pTexture; if (tex.find_last_of("/\\") == std::string::npos) tex.insert(0, Global::asCurrentTexturePath); - TextureID = TTexturesManager::GetTextureID( - szTexturePath, const_cast(Global::asCurrentTexturePath.c_str()), tex); + TextureID = TTexturesManager.GetTextureId( tex, szTexturePath ); // TexAlpha=TTexturesManager::GetAlpha(TextureID); //zmienna robocza // ustawienie cyklu przezroczyste/nieprzezroczyste zależnie od własności // stałej tekstury // iFlags=(iFlags&~0x30)|(TTexturesManager::GetAlpha(TextureID)?0x20:0x10); // //0x10-nieprzezroczysta, 0x20-przezroczysta if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity 0! - iFlags |= TTexturesManager::GetAlpha(TextureID) ? + iFlags |= TTexturesManager.Texture(TextureID).has_alpha ? 0x20 : 0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta else diff --git a/Model3d.h b/Model3d.h index 0653673b..c6adc688 100644 --- a/Model3d.h +++ b/Model3d.h @@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/. #include "dumb3d.h" #include "Float3d.h" #include "VBO.h" +#include "Texture.h" using namespace Math3D; @@ -215,7 +216,7 @@ class TSubModel // światła float fCosViewAngle; // cos kata pod jakim sie teraz patrzy // Ra: dalej są zmienne robocze, można je przestawiać z zachowaniem rozmiaru klasy - int TextureID; // numer tekstury, -1 wymienna, 0 brak + texture_manager::size_type TextureID; // numer tekstury, -1 wymienna, 0 brak bool bWire; // nie używane, ale wczytywane // short TexAlpha; //Ra: nie używane już GLuint uiDisplayList; // roboczy numer listy wyświetlania @@ -271,7 +272,7 @@ class TSubModel { return Child; }; - int TriangleAdd(TModel3d *m, int tex, int tri); + int TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri); float8 * TrianglePtr(int tex, int pos, int *la, int *ld, int *ls); // float8* TrianglePtr(const char *tex,int tri); // void SetRotate(vector3 vNewRotateAxis,float fNewAngle); diff --git a/Texture.cpp b/Texture.cpp index e16d85c8..1ad3622a 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -26,11 +26,20 @@ http://mozilla.org/MPL/2.0/. #include "Usefull.h" #include "TextureDDS.h" +texture_manager TTexturesManager; + +/* TTexturesManager::Alphas TTexturesManager::_alphas; TTexturesManager::Names TTexturesManager::_names; +*/ +void +texture_manager::Init() { -void TTexturesManager::Init(){}; + // since index 0 is used to indicate no texture, we put a blank entry in the first texture slot + m_textures.emplace_back( opengl_texture() ); +} +/* TTexturesManager::Names::iterator TTexturesManager::LoadFromFile(std::string fileName, int filter) { @@ -81,7 +90,8 @@ TTexturesManager::Names::iterator TTexturesManager::LoadFromFile(std::string fil // WriteLog("OK"); //Ra: "OK" nie potrzeba, samo "Failed" wystarczy return ret.first; }; - +*/ +/* struct ReplaceSlash { const char operator()(const char input) @@ -89,159 +99,137 @@ struct ReplaceSlash return input == '/' ? '\\' : input; } }; +*/ +// ustalenie numeru tekstury, wczytanie jeśli nie jeszcze takiej nie było +texture_manager::size_type +texture_manager::GetTextureId( std::string Filename, std::string const &Dir, int const Filter ) { -GLuint TTexturesManager::GetTextureID(char *dir, char *where, std::string fileName, int filter) -{ // ustalenie numeru tekstury, wczytanie jeśli nie jeszcze takiej nie było - /* - // Ra: niby tak jest lepiej, ale działa gorzej, więc przywrócone jest oryginalne - //najpierw szukamy w katalogu, z którego wywoływana jest tekstura, potem z wyższego - //Ra: przerobić na wyszukiwanie w drzewie nazw, do którego zapisywać np. rozmiary, - przezroczystość - //Ra: ustalać, które tekstury można wczytać już w trakcie symulacji - size_t pos=fileName.find(':'); //szukamy dwukropka - if (pos!=std::string::npos) //po dwukropku mogą być podane dodatkowe informacje - fileName=fileName.substr(0,pos); //niebędące nazwą tekstury - std::transform(fileName.begin(),fileName.end(),fileName.begin(),ReplaceSlash()); //zamiana "/" - na "\" - //jeśli bieżaca ścieżka do tekstur nie została dodana to dodajemy domyślną - //if (fileName.find('\\')==std::string::npos) //bz sensu - // fileName.insert(0,szDefaultTexturePath); - //najpierw szukamy w podanym katalogu, potem w domyślnym - Names::iterator iter; - std::ifstream file; - if ((fileName.find('.')==fileName.npos)?true:(fileName.rfind('.')second; //znalezione! - if (dir) - {//może we wskazanym katalogu? - test=fileName; - test.insert(0,dir); //jeszcze próba z dodatkową ścieżką - test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeń - iter=_names.find(test); //czy mamy już w magazynie? - if (iter!=_names.end()) - return iter->second; //znalezione! - } - //} - //for (int i=0;i<4;++i) - //{//w magazynie nie ma, to sprawdzamy na dysku - test=fileName; - if (where) test.insert(0,where); //ścieżka obiektu wywołującego - test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeń - file.open(test.c_str()); - if (!file.is_open()) - {test=fileName; - if (dir) test.insert(0,dir); //próba z dodatkową ścieżką - test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeń - file.open(test.c_str()); - } - if (file.is_open()) - {//jak znaleziony, to plik zostaje otwarty - fileName=test; //zapamiętanie znalezionego rozszerzenia - break; //wyjście z pętli na etapie danego rozszerzenia - } - } - } - else - {//gdy jest kropka, to rozszerzenie jest jawne - std::string test; //zmienna robocza - //najpierw szukamy w magazynie - test=fileName; - if (where) test.insert(0,where); //ścieżka obiektu wywołującego - iter=_names.find(test); //czy mamy już w magazynie? - if (iter!=_names.end()) - return iter->second; //znalezione! - test=fileName; - if (dir) test.insert(0,dir); //jeszcze próba z dodatkową ścieżką - iter=_names.find(test); //czy mamy już w magazynie? - if (iter!=_names.end()) - return iter->second; //znalezione! - //w magazynie nie ma, to sprawdzamy na dysku - test=fileName; - if (where) test.insert(0,where); //ścieżka obiektu wywołującego - file.open(test.c_str()); - if (!file.is_open()) - {//jak znaleziony, to plik zostaje otwarty - test=fileName; - if (dir) test.insert(0,dir); //próba z dodatkową ścieżką - file.open(test.c_str()); - if (file.is_open()) - fileName=test; //ustalenie nowej nazwy - } - } - if (file.is_open()) - {//plik pozostaje otwarty, gdy znaleziono na dysku - file.close(); //można już zamknąć - iter=LoadFromFile(fileName,filter); //doda się do magazynu i zwróci swoją pozycję - } - */ - size_t pos = fileName.find(':'); // szukamy dwukropka - if (pos != std::string::npos) // po dwukropku mogą być podane dodatkowe informacje - fileName = fileName.substr(0, pos); // niebędące nazwą tekstury - pos = fileName.find('|'); // szukamy separatora tekstur - if (pos != std::string::npos) // po | może być nazwa kolejnej tekstury - fileName = fileName.substr(0, pos); // i trzeba to obciąć - std::transform(fileName.begin(), fileName.end(), fileName.begin(), ReplaceSlash()); - // jeśli bieżaca ścieżka do tekstur nie została dodana to dodajemy domyślną - if (fileName.find('\\') == std::string::npos) - fileName.insert(0, szTexturePath); - Names::iterator iter; - if (fileName.find('.') == std::string::npos) - { // Ra: wypróbowanie rozszerzeń po kolei, zaczynając od domyślnego - fileName.append("."); // kropka będze na pewno, resztę trzeba próbować - std::string test; // zmienna robocza - for (int i = 0; i < 4; ++i) - { // najpierw szukamy w magazynie - test = fileName; - test.append(Global::szDefaultExt[i]); - iter = _names.find(fileName); // czy mamy już w magazynie? - if (iter != _names.end()) - return iter->second; // znalezione! - test.insert(0, szTexturePath); // jeszcze próba z dodatkową ścieżką - iter = _names.find(fileName); // czy mamy już w magazynie? - if (iter != _names.end()) - return iter->second; // znalezione! - } - for (int i = 0; i < 4; ++i) - { // w magazynie nie ma, to sprawdzamy na dysku - test = fileName; - test.append(Global::szDefaultExt[i]); - std::ifstream file(test.c_str()); - if (!file.is_open()) - { - test.insert(0, szTexturePath); - file.open(test.c_str()); + if( Filename.find( ':' ) != std::string::npos ) + Filename.erase( Filename.find( ':' ) ); // po dwukropku mogą być podane dodatkowe informacje niebędące nazwą tekstury + if( Filename.find( '|' ) != std::string::npos ) + Filename.erase( Filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury + for( char &c : Filename ) { + // change forward slashes to windows ones. NOTE: probably not strictly necessary, but eh + c = ( c == '/' ? '\\' : c ); + } +/* + std::transform( + Filename.begin(), Filename.end(), + Filename.begin(), + []( char Char ){ return Char == '/' ? '\\' : Char; } ); +*/ + if( Filename.find( '\\' ) == std::string::npos ) { + // jeśli bieżaca ścieżka do tekstur nie została dodana to dodajemy domyślną + Filename = szTexturePath + Filename; + } + + std::vector extensions{ { ".dds" }, { ".tga" }, { ".bmp" }, { ".ext" } }; + + // try to locate requested texture in the databank + auto lookup = find_in_databank( Filename + Global::szDefaultExt ); + if( lookup != npos ) { + // start with the default extension... + return lookup; + } + else { + // ...then try recognized file extensions other than default + for( auto const &extension : extensions ) { + + if( extension == Global::szDefaultExt ) { + // we already tried this one + continue; } - if (file.is_open()) - { - fileName.append(Global::szDefaultExt[i]); // dopisanie znalezionego - file.close(); - break; // wyjście z pętli na etapie danego rozszerzenia + lookup = find_in_databank( Filename + extension ); + if( lookup != npos ) { + + return lookup; } } } - iter = _names.find(fileName); // czy mamy już w magazynie - if (iter == _names.end()) - iter = LoadFromFile(fileName, filter); - return (iter != _names.end() ? iter->second : 0); + // if we don't have the texture in the databank, check if it's on disk + std::string filename = find_on_disk( Filename + Global::szDefaultExt ); + if( true == filename.empty() ) { + // if the default lookup fails, try other known extensions + for( auto const &extension : extensions ) { + + if( extension == Global::szDefaultExt ) { + // we already tried this one + continue; + } + filename = find_on_disk( Filename + extension ); + if( false == filename.empty() ) { + // we found something, don't bother with others + break; + } + } + } + + if( true == filename.empty() ) { + // there's nothing matching in the databank nor on the disk, report failure + return npos; + } + + opengl_texture texture; + texture.name = filename; + m_textures.emplace_back( texture ); + auto const textureindex = m_textures.size() - 1; + m_texturemappings.emplace( filename, textureindex ); + + WriteLog( "Created texture object for file \"" + filename + "\"" ); + + return textureindex; }; +// checks whether specified texture is in the texture bank. returns texture id, or npos. +texture_manager::size_type +texture_manager::find_in_databank( std::string const &Texturename ) { + + auto lookup = m_texturemappings.find( Texturename ); + if( lookup != m_texturemappings.end() ) { + return lookup->second; + } + // jeszcze próba z dodatkową ścieżką + lookup = m_texturemappings.find( szTexturePath + Texturename ); + + return ( + lookup != m_texturemappings.end() ? + lookup->second : + npos ); +} + +// checks whether specified file exists. +std::string +texture_manager::find_on_disk( std::string const &Texturename ) { + + { + std::ifstream file( Texturename ); + if( true == file.is_open() ) { + // success + return Texturename; + } + + } + // if we fail make a last ditch attempt in the default textures directory + { + std::ifstream file( szTexturePath + Texturename ); + if( true == file.is_open() ) { + // success + return szTexturePath + Texturename; + } + + } + // no results either way, report failure + return ""; +} + +/* bool TTexturesManager::GetAlpha(GLuint id) { // atrybut przezroczystości dla tekstury o podanym numerze (id) Alphas::iterator iter = _alphas.find(id); return (iter != _alphas.end() ? iter->second : false); } - +*/ +/* TTexturesManager::AlphaValue TTexturesManager::LoadBMP(std::string const &fileName) { @@ -797,6 +785,8 @@ TTexturesManager::AlphaValue TTexturesManager::LoadDDS(std::string fileName, int return std::make_pair(id, data.components == 4); }; +*/ +/* void TTexturesManager::SetFiltering(int filter) { if (filter < 4) // rozmycie przy powiększeniu @@ -910,17 +900,16 @@ GLuint TTexturesManager::CreateTexture(GLubyte *buff, GLint bpp, int width, int return ID; } - -void TTexturesManager::Free() -{ // usunięcie wszyskich tekstur (bez usuwania struktury) - // for (Names::iterator iter = _names.begin(); iter != _names.end(); iter++) - if( false == _names.empty() ) { - for( auto const &texture : _names ) { - glDeleteTextures( 1, &texture.second ); - } - } +*/ +void +texture_manager::Free() +{ + for( auto const &texture : m_textures ) { + // usunięcie wszyskich tekstur (bez usuwania struktury) + glDeleteTextures( 1, &texture.id ); + } } - +/* std::string TTexturesManager::GetName(GLuint id) { // pobranie nazwy tekstury for( auto const &pair : _names ) { @@ -928,3 +917,4 @@ std::string TTexturesManager::GetName(GLuint id) } return ""; }; +*/ \ No newline at end of file diff --git a/Texture.h b/Texture.h index 8810d537..6d058f8f 100644 --- a/Texture.h +++ b/Texture.h @@ -12,49 +12,56 @@ http://mozilla.org/MPL/2.0/. #include #include "opengl/glew.h" +struct opengl_texture { + + GLuint id{ -1 }; // associated GL resource + bool has_alpha{ false }; // indicates the texture has alpha channel + bool is_ready{ false }; // indicates the texture was processed and is ready for use + std::string name; // name of the texture source file + std::vector data; // texture data + /*std::atomic*/ bool is_loaded{ false }; // indicates the texture data was loaded and can be processed + /*std::atomic*/ bool is_good{ false }; // indicates the texture data was retrieved without errors +}; + +class texture_manager { + +private: + typedef std::vector opengltexture_array; + +public: + typedef opengltexture_array::size_type size_type; + + ~texture_manager() { Free(); } + + size_type GetTextureId( std::string Filename, std::string const &Dir, int const Filter = -1 ); + opengl_texture &Texture( size_type const Id ) { return m_textures.at( Id ); } + void Init(); + void Free(); + +private: + typedef std::unordered_map index_map; /* -//Ra: miejsce umieszczenia tego jest deczko bezsensowne -void glDebug() -{//logowanie błędów OpenGL - GLenum err; - if (Global::iErorrCounter==326) //tu wpisz o 1 mniej niz wartość, przy której się wyłożyło - Global::iErorrCounter=Global::iErorrCounter+0; //do zastawiania pułapki przed błędnym kodem - while ((err=glGetError())!=GL_NO_ERROR) //dalej jest pułapka po wykonaniu błędnego kodu - WriteLog("OpenGL error found: "+AnsiString(err)+", step:"+AnsiString(Global::iErorrCounter)); - ++Global::iErorrCounter; -}; + opengltexture_array::size_type LoadFromFile(std::string name, int filter = -1); */ - -class TTexturesManager -{ - public: - static void Init(); - static void Free(); - - static GLuint GetTextureID(char *dir, char *where, std::string name, int filter = -1); - static bool GetAlpha(GLuint ID); // McZapkie-141203: czy tekstura ma polprzeroczystosc - static std::string GetName(GLuint id); - - private: - typedef std::pair AlphaValue; - - typedef std::map Names; - typedef std::map Alphas; - - static Names::iterator LoadFromFile(std::string name, int filter = -1); - - static AlphaValue LoadBMP(std::string const &fileName); - static AlphaValue LoadTEX(std::string fileName); - static AlphaValue LoadTGA(std::string fileName, int filter = -1); - static AlphaValue LoadDDS(std::string fileName, int filter = -1); - - static void SetFiltering(int filter); - static void SetFiltering(bool alpha, bool hash); - static GLuint CreateTexture(GLubyte *buff, GLint bpp, int width, int height, bool bHasAlpha, - bool bHash, bool bDollar = true, int filter = -1); - - static Names _names; - static Alphas _alphas; - // std::list Textures; +/* + bool LoadBMP( std::string const &fileName); + bool LoadTEX( std::string fileName ); + bool LoadTGA( std::string fileName, int filter = -1 ); + bool LoadDDS( std::string fileName, int filter = -1 ); +*/ + // checks whether specified texture is in the texture bank. returns texture id, or npos. + size_type find_in_databank( std::string const &Texturename ); + // checks whether specified file exists. returns name of the located file, or empty string. + std::string find_on_disk( std::string const &Texturename ); +/* + void SetFiltering(int filter); + void SetFiltering(bool alpha, bool hash); + GLuint CreateTexture(GLubyte *buff, GLint bpp, int width, int height, bool bHasAlpha, + bool bHash, bool bDollar = true, int filter = -1); +*/ + static const size_type npos{ 0 }; // should be -1, but the rest of the code uses -1 for something else + opengltexture_array m_textures; + index_map m_texturemappings; }; -//--------------------------------------------------------------------------- + +extern texture_manager TTexturesManager; \ No newline at end of file diff --git a/Track.cpp b/Track.cpp index 7386b98e..fd32a2ad 100644 --- a/Track.cpp +++ b/Track.cpp @@ -508,8 +508,8 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) parser->getTokens(); *parser >> token; str = token; // railtex - TextureID1 = (str == "none" ? 0 : TTexturesManager::GetTextureID( - szTexturePath, szSceneryPath, str, + TextureID1 = (str == "none" ? 0 : TTexturesManager.GetTextureId( + str, szTexturePath, (iCategoryFlag & 1) ? Global::iRailProFiltering : Global::iBallastFiltering)); parser->getTokens(); @@ -519,8 +519,8 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name) parser->getTokens(); *parser >> token; str = token; // sub || railtex - TextureID2 = (str == "none" ? 0 : TTexturesManager::GetTextureID( - szTexturePath, szSceneryPath, str, + TextureID2 = (str == "none" ? 0 : TTexturesManager.GetTextureId( + str, szTexturePath, (eType == tt_Normal) ? Global::iBallastFiltering : Global::iRailProFiltering)); parser->getTokens(3); diff --git a/Track.h b/Track.h index 6382f0f0..0d3d9e5e 100644 --- a/Track.h +++ b/Track.h @@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/. #include "opengl/glew.h" #include "ResourceManager.h" #include "Segment.h" +#include "Texture.h" class TEvent; @@ -136,8 +137,8 @@ class TTrack : public Resource TTrack *trNext = nullptr; // odcinek od strony punktu 2 - to powinno być w segmencie TTrack *trPrev = nullptr; // odcinek od strony punktu 1 // McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur - GLuint TextureID1 = 0; // tekstura szyn albo nawierzchni - GLuint TextureID2 = 0; // tekstura automatycznej podsypki albo pobocza + texture_manager::size_type TextureID1 = 0; // tekstura szyn albo nawierzchni + texture_manager::size_type TextureID2 = 0; // tekstura automatycznej podsypki albo pobocza float fTexLength = 4.0; // długość powtarzania tekstury w metrach float fTexRatio1 = 1.0; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...) float fTexRatio2 = 1.0; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...) diff --git a/World.cpp b/World.cpp index 6ebe9161..9cfa8762 100644 --- a/World.cpp +++ b/World.cpp @@ -71,7 +71,7 @@ TWorld::~TWorld() // Ground.Free(); //Ra: usunięcie obiektów przed usunięciem dźwięków - sypie się TSoundsManager::Free(); TModelsManager::Free(); - TTexturesManager::Free(); +// TTexturesManager.Free(); glDeleteLists(base, 96); if (hinstGLUT32) FreeLibrary(hinstGLUT32); @@ -479,8 +479,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC) glDisable(GL_DEPTH_TEST); // Disables depth testing glColor3f(3.0f, 3.0f, 3.0f); - GLuint logo; - logo = TTexturesManager::GetTextureID(szTexturePath, szSceneryPath, "logo", 6); + auto logo = TTexturesManager.GetTextureId( "logo", szTexturePath, 6 ); glBindTexture(GL_TEXTURE_2D, logo); // Select our texture glBegin(GL_QUADS); // Drawing using triangles @@ -527,8 +526,9 @@ bool TWorld::Init(HWND NhWnd, HDC hDC) glPrint("Tekstury / Textures..."); } SwapBuffers(hDC); // Swap Buffers (Double Buffering) - - TTexturesManager::Init(); +/* + TTexturesManager.Init(); +*/ WriteLog("Textures init OK"); if (Global::detonatoryOK) { @@ -663,9 +663,9 @@ bool TWorld::Init(HWND NhWnd, HDC hDC) // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //{Texture blends with object // background} if (Global::bOldSmudge == true) - light = TTexturesManager::GetTextureID(szTexturePath, szSceneryPath, "smuga.tga"); + light = TTexturesManager.GetTextureId( "smuga.tga", szTexturePath ); else - light = TTexturesManager::GetTextureID(szTexturePath, szSceneryPath, "smuga2.tga"); + light = TTexturesManager.GetTextureId( "smuga2.tga", szTexturePath ); // Camera.Reset(); Timer::ResetTimers(); WriteLog( "Load time: " + diff --git a/World.h b/World.h index 7868971c..f710a515 100644 --- a/World.h +++ b/World.h @@ -51,7 +51,7 @@ class TWorld TDynamicObject *pDynamicNearest; bool Paused; GLuint base; // numer DL dla znaków w napisach - GLuint light; // numer tekstury dla smugi + texture_manager::size_type light; // numer tekstury dla smugi TSky Clouds; TEvent *KeyEvents[10]; // eventy wyzwalane z klawiaury TMoverParameters *mvControlled; // wskaźnik na człon silnikowy, do wyświetlania jego parametrów diff --git a/stdafx.h b/stdafx.h index 22d52bd3..d4c1225e 100644 --- a/stdafx.h +++ b/stdafx.h @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include