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; }