bool GLENGINE::LoadTexture(const char * filename, const char * name, bool mask) { GLuint texture = 0; uint8_t * pixels; std::string str(name); TEXTURE * tex; tex = textures[str]; if (tex) { if (tex->pixels) UnloadTexture(name); } std::cout << "Loading texture \"" << filename << "\"..."; bool result = false; if (mask) result = CreateTex(filename, &texture, &pixels, "mask.bmp"); else result = CreateTex(filename, &texture, &pixels, 0); if (!result) { std::cout << "Failed\n"; return false; } PrintErrorLine(__LINE__); tex = new TEXTURE; tex->pixels = pixels; tex->texID = texture; textures[str] = tex; std::cout << "OK\n"; return true; }
C3DOTextureHandler::C3DOTextureHandler() { PrintLoadMsg("Creating unit textures"); CFileHandler file("unittextures/tatex/teamtex.txt"); CSimpleParser parser(file); std::set<std::string> teamTexes; while(!file.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } TexFile* texfiles[10000]; int numfiles = 0; int totalSize = 0; std::vector<std::string> filesBMP = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); files.insert(files.end(),filesBMP.begin(),filesBMP.end()); std::set<string> usedNames; for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { std::string s = std::string(*fi); std::string s2 = s; s2.erase(0, s2.find_last_of('/') + 1); s2 = StringToLower(s2.substr(0, s2.find_last_of('.'))); //avoid duplicate names and give tga images priority if(usedNames.find(s2)!=usedNames.end()) continue; usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = CreateTex(s, s2, false); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } else { TexFile* tex = CreateTex(s, s2, true); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } } // "TAPalette.h" for(int a=0;a<256;++a){ string name="ta_color"; char t[50]; sprintf(t,"%i",a); name+=t; TexFile* tex=new TexFile; tex->name=name; tex->tex.Alloc(1,1); tex->tex.mem[0]=palette[a][0]; tex->tex.mem[1]=palette[a][1]; tex->tex.mem[2]=palette[a][2]; tex->tex.mem[3]=0; //teamcolor tex->tex2.Alloc(1,1); tex->tex2.mem[0]=0; //self illum tex->tex2.mem[1]=30; //reflectivity tex->tex2.mem[2]=0; tex->tex2.mem[3]=255; texfiles[numfiles++]=tex; totalSize+=tex->tex.xsize*tex->tex.ysize; } //pessimistic guess about how much space will be wasted totalSize=(int)(totalSize * 1.2f); if(totalSize<1024*1024){ bigTexX=1024; bigTexY=1024; } else if(totalSize<1024*2048){ bigTexX=1024; bigTexY=2048; } else if(totalSize<2048*2048){ bigTexX=2048; bigTexY=2048; } else { bigTexX=2048; bigTexY=2048; handleerror(0,"Too many/large unit textures to fit in 2048*2048","Error",0); } qsort(texfiles,numfiles,sizeof(TexFile*),CompareTatex2); unsigned char* bigtex1 = new unsigned char[bigTexX*bigTexY*4]; unsigned char* bigtex2 = new unsigned char[bigTexX*bigTexY*4]; for(int a=0;a<bigTexX*bigTexY;++a) { bigtex1[a*4+0] = 128; bigtex1[a*4+1] = 128; bigtex1[a*4+2] = 128; bigtex1[a*4+3] = 0; bigtex2[a*4+0] = 0; bigtex2[a*4+1] = 128; bigtex2[a*4+2] = 0; bigtex2[a*4+3] = 255; } int cury=0; int maxy=0; int curx=0; int foundx = 0, foundy = 0; std::list<int2> nextSub; std::list<int2> thisSub; for(int a=0;a<numfiles;++a){ CBitmap* curtex1=&texfiles[a]->tex; CBitmap* curtex2=&texfiles[a]->tex2; bool done=false; while(!done){ // Find space for us if(thisSub.empty()){ if(nextSub.empty()){ cury=maxy; maxy+=curtex1->ysize; if(maxy>bigTexY){ handleerror(0,"Too many/large unit textures","Error",0); break; } thisSub.push_back(int2(0,cury)); } else { thisSub=nextSub; nextSub.clear(); } } if(thisSub.front().x+curtex1->xsize>bigTexX){ thisSub.clear(); continue; } if(thisSub.front().y+curtex1->ysize>maxy){ thisSub.pop_front(); continue; } // ok found space for us foundx=thisSub.front().x; foundy=thisSub.front().y; done=true; if(thisSub.front().y+curtex1->ysize<maxy){ nextSub.push_back(int2(thisSub.front().x,thisSub.front().y+curtex1->ysize)); } thisSub.front().x+=curtex1->xsize; while(thisSub.size()>1 && thisSub.front().x >= (++thisSub.begin())->x){ (++thisSub.begin())->x=thisSub.front().x; thisSub.erase(thisSub.begin()); } } for(int y=0;y<curtex1->ysize;y++){ for(int x=0;x<curtex1->xsize;x++){ // if(curtex1->mem[(y*curtex1->xsize+x)*4]==254 && curtex1->mem[(y*curtex1->xsize+x)*4+1]==0 && curtex1->mem[(y*curtex1->xsize+x)*4+2]==254){ // bigtex1[((cury+y)*bigTexX+(curx+x))*4+3] = 0; // } else { for(int col=0;col<4;col++){ bigtex1[((foundy+y)*bigTexX+(foundx+x))*4+col] = curtex1->mem[(y*curtex1->xsize+x)*4+col]; bigtex2[((foundy+y)*bigTexX+(foundx+x))*4+col] = curtex2->mem[(y*curtex1->xsize+x)*4+col]; // } } } } UnitTexture* unittex=new UnitTexture; unittex->xstart=(foundx+0.5f)/(float)bigTexX; unittex->ystart=(foundy+0.5f)/(float)bigTexY; unittex->xend=(foundx+curtex1->xsize-0.5f)/(float)bigTexX; unittex->yend=(foundy+curtex1->ysize-0.5f)/(float)bigTexY; textures[texfiles[a]->name]=unittex; curx+=curtex1->xsize; delete texfiles[a]; } glGenTextures(1, &atlas3do1); glBindTexture(GL_TEXTURE_2D, atlas3do1); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); glGenTextures(1, &atlas3do2); glBindTexture(GL_TEXTURE_2D, atlas3do2); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); // CBitmap save(tex,bigTexX,bigTexY); // save.Save("unittex-1x.jpg"); UnitTexture* t=new UnitTexture; t->xstart=0; t->ystart=0; t->xend=1; t->yend=1; textures[" "]=t; delete[] bigtex1; delete[] bigtex2; }
C3DOTextureHandler::C3DOTextureHandler() { CFileHandler teamTexFile("unittextures/tatex/teamtex.txt"); CFileHandler paletteFile("unittextures/tatex/palette.pal"); CSimpleParser parser(teamTexFile); std::set<std::string> teamTexes; while (!parser.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } TexFile* texfiles[10000]; int numfiles = 0; int totalSize = 0; const std::vector<std::string>& filesBMP = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); files.insert(files.end(), filesBMP.begin(), filesBMP.end()); std::set<string> usedNames; for (std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { const std::string& s = *fi; const std::string s2 = StringToLower(FileSystem::GetBasename(s)); // avoid duplicate names and give tga images priority if (usedNames.find(s2) != usedNames.end()) { continue; } usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = CreateTex(s, s2, false); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } else { TexFile* tex = CreateTex(s, s2, true); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } } if (paletteFile.FileExists()) { palette.Init(paletteFile); } for (unsigned a = 0; a < CTAPalette::NUM_PALETTE_ENTRIES; ++a) { const std::string name = "ta_color" + IntToString(a, "%i"); TexFile* tex = new TexFile; tex->name = name; tex->tex.Alloc(1, 1); tex->tex.mem[0] = palette[a][0]; tex->tex.mem[1] = palette[a][1]; tex->tex.mem[2] = palette[a][2]; tex->tex.mem[3] = 0; // teamcolor tex->tex2.Alloc(1, 1); tex->tex2.mem[0] = 0; // self illum tex->tex2.mem[1] = 30; // reflectivity tex->tex2.mem[2] = 0; tex->tex2.mem[3] = 255; texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } // pessimistic guess about how much space will be wasted totalSize = (int)(totalSize * 1.2f); if (totalSize < 1024*1024) { bigTexX = 1024; bigTexY = 1024; } else if (totalSize < 1024*2048) { bigTexX = 1024; bigTexY = 2048; } else if (totalSize < 2048*2048) { bigTexX = 2048; bigTexY = 2048; } else { bigTexX = 2048; bigTexY = 2048; throw content_error("Too many/large texture in 3do texture-atlas to fit in 2048*2048"); } qsort(texfiles,numfiles,sizeof(TexFile*), CompareTatex2); unsigned char* bigtex1 = new unsigned char[bigTexX * bigTexY * 4]; unsigned char* bigtex2 = new unsigned char[bigTexX * bigTexY * 4]; for (int a = 0; a < (bigTexX * bigTexY); ++a) { bigtex1[a*4 + 0] = 128; bigtex1[a*4 + 1] = 128; bigtex1[a*4 + 2] = 128; bigtex1[a*4 + 3] = 0; bigtex2[a*4 + 0] = 0; bigtex2[a*4 + 1] = 128; bigtex2[a*4 + 2] = 0; bigtex2[a*4 + 3] = 255; } int cury = 0; int maxy = 0; int foundx = 0; int foundy = 0; std::list<int2> nextSub; std::list<int2> thisSub; for (int a = 0; a < numfiles; ++a) { CBitmap* curtex1 = &texfiles[a]->tex; CBitmap* curtex2 = &texfiles[a]->tex2; bool done = false; while (!done) { // Find space for us if (thisSub.empty()) { if (nextSub.empty()) { cury = maxy; maxy += curtex1->ysize; if (maxy > bigTexY) { delete[] bigtex1; delete[] bigtex2; throw content_error("Too many/large texture in 3do texture-atlas to fit in 2048*2048"); } thisSub.push_back(int2(0, cury)); } else { thisSub = nextSub; nextSub.clear(); } } if (thisSub.front().x + curtex1->xsize>bigTexX) { thisSub.clear(); continue; } if(thisSub.front().y+curtex1->ysize>maxy){ thisSub.pop_front(); continue; } // ok found space for us foundx=thisSub.front().x; foundy=thisSub.front().y; done=true; if (thisSub.front().y + curtex1->ysize<maxy){ nextSub.push_back(int2(thisSub.front().x, thisSub.front().y + curtex1->ysize)); } thisSub.front().x += curtex1->xsize; while ((thisSub.size() > 1) && (thisSub.front().x >= (++thisSub.begin())->x)) { (++thisSub.begin())->x = thisSub.front().x; thisSub.erase(thisSub.begin()); } } for (int y = 0; y < curtex1->ysize; ++y) { for (int x = 0; x < curtex1->xsize; ++x) { for (int col = 0; col < 4; ++col) { bigtex1[(((foundy + y) * bigTexX + (foundx + x)) * 4) + col] = curtex1->mem[(((y * curtex1->xsize) + x) * 4) + col]; bigtex2[(((foundy + y) * bigTexX + (foundx + x)) * 4) + col] = curtex2->mem[(((y * curtex1->xsize) + x) * 4) + col]; } } } UnitTexture* unittex = new UnitTexture; unittex->xstart = (foundx + 0.5f) / (float)bigTexX; unittex->ystart = (foundy + 0.5f) / (float)bigTexY; unittex->xend = (foundx + curtex1->xsize - 0.5f) / (float)bigTexX; unittex->yend = (foundy + curtex1->ysize - 0.5f) / (float)bigTexY; textures[texfiles[a]->name] = unittex; delete texfiles[a]; } glGenTextures(1, &atlas3do1); glBindTexture(GL_TEXTURE_2D, atlas3do1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); glGenTextures(1, &atlas3do2); glBindTexture(GL_TEXTURE_2D, atlas3do2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8, bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); // CBitmap save(tex, bigTexX, bigTexY); // save.Save("unittex-1x.jpg"); UnitTexture* t = new UnitTexture(); t->xstart = 0.0f; t->ystart = 0.0f; t->xend = 1.0f; t->yend = 1.0f; textures["___dummy___"] = t; delete[] bigtex1; delete[] bigtex2; }
std::vector<TexFile*> C3DOTextureHandler::LoadTexFiles() { CFileHandler teamTexFile("unittextures/tatex/teamtex.txt"); CFileHandler paletteFile("unittextures/tatex/palette.pal"); CSimpleParser parser(teamTexFile); std::set<std::string> teamTexes; while (!parser.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } std::vector<TexFile*> texfiles; const std::vector<std::string>& filesBMP = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); files.insert(files.end(), filesBMP.begin(), filesBMP.end()); std::set<string> usedNames; for (std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { const std::string& s = *fi; const std::string s2 = StringToLower(FileSystem::GetBasename(s)); // avoid duplicate names and give tga images priority if (usedNames.find(s2) != usedNames.end()) { continue; } usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = CreateTex(s, s2, false); texfiles.push_back(tex); } else { TexFile* tex = CreateTex(s, s2, true); texfiles.push_back(tex); } } if (paletteFile.FileExists()) { palette.Init(paletteFile); } for (unsigned a = 0; a < CTAPalette::NUM_PALETTE_ENTRIES; ++a) { TexFile* tex = new TexFile(); tex->name = "ta_color" + IntToString(a, "%i"); tex->tex.Alloc(1, 1); tex->tex.mem[0] = palette[a][0]; tex->tex.mem[1] = palette[a][1]; tex->tex.mem[2] = palette[a][2]; tex->tex.mem[3] = 0; // teamcolor tex->tex2.Alloc(1, 1); tex->tex2.mem[0] = 0; // self illum tex->tex2.mem[1] = 30; // reflectivity tex->tex2.mem[2] = 0; tex->tex2.mem[3] = 255; texfiles.push_back(tex); } return texfiles; }