From c67d7d48c26fc65ecc08573ee24083f7ae18f6e4 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sat, 12 Mar 2011 21:29:37 +0000 Subject: [PATCH] - some initial work to allow saving models in the current v4 g3d format (new commandline option to test it also) and also convert textures into png --- source/glest_game/main/main.cpp | 43 ++++ source/shared_lib/include/graphics/model.h | 13 +- source/shared_lib/sources/graphics/model.cpp | 247 +++++++++++++++---- 3 files changed, 255 insertions(+), 48 deletions(-) diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 82c021fa..a10be238 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -99,6 +99,7 @@ const char *GAME_ARGS[] = { "--ini-path", "--log-path", "--show-ini-settings", + "--convert-model", "--disable-backtrace", "--disable-vbo", "--verbose" @@ -122,6 +123,7 @@ enum GAME_ARG_TYPE { GAME_ARG_INI_PATH, GAME_ARG_LOG_PATH, GAME_ARG_SHOW_INI_SETTINGS, + GAME_ARG_CONVERT_MODEL, GAME_ARG_DISABLE_BACKTRACE, GAME_ARG_DISABLE_VBO, GAME_ARG_VERBOSE_MODE @@ -859,6 +861,12 @@ void printParameterHelp(const char *argv0, bool foundInvalidArgs) { printf("\n%s=x\t\t\tdisplays merged ini settings information.",GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]); printf("\n \t\tWhere x is an optional property name to filter (default shows all)."); printf("\n \t\texample: %s %s=DebugMode",argv0,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]); + + printf("\n%s=x=format\t\t\tconvert a model to current g3d format.",GAME_ARGS[GAME_ARG_CONVERT_MODEL]); + printf("\n \t\tWhere x is the filename for the g3d model."); + printf("\n \t\tWhere format is the optional texture format to convert to (default is png)."); + printf("\n \t\texample: %s %s=techs/megapack/factions/tech/units/castle/models/castle.g3d",argv0,GAME_ARGS[GAME_ARG_CONVERT_MODEL]); + printf("\n%s\t\tdisables stack backtrace on errors.",GAME_ARGS[GAME_ARG_DISABLE_BACKTRACE]); printf("\n%s\t\tdisables trying to use Vertex Buffer Objects.",GAME_ARGS[GAME_ARG_DISABLE_VBO]); printf("\n%s\t\t\tdisplays verbose information in the console.",GAME_ARGS[GAME_ARG_VERBOSE_MODE]); @@ -1787,6 +1795,41 @@ int glestMain(int argc, char** argv) { return -1; } + if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CONVERT_MODEL]) == true) { + int foundParamIndIndex = -1; + hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODEL]) + string("="),&foundParamIndIndex); + if(foundParamIndIndex < 0) { + hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODEL]),&foundParamIndIndex); + } + string paramValue = argv[foundParamIndIndex]; + vector paramPartTokens; + Tokenize(paramValue,paramPartTokens,"="); + if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) { + string modelFile = paramPartTokens[1]; + string textureFormat = "png"; + if(paramPartTokens.size() >= 3) { + textureFormat = paramPartTokens[2]; + } + + printf("About to convert model [%s] using texture format [%s]\n",modelFile.c_str(),textureFormat.c_str()); + + Model *model = renderer.newModel(rsGlobal); + model->load(modelFile); + model->save(modelFile,textureFormat); + + //!!! + delete mainWindow; + return -1; + + } + else { + printf("\nInvalid model name specified on commandline [%s] model [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL)); + printParameterHelp(argv[0],foundInvalidArgs); + delete mainWindow; + return -1; + } + } + gameInitialized = true; // Setup the screenshots folder diff --git a/source/shared_lib/include/graphics/model.h b/source/shared_lib/include/graphics/model.h index 65f3e178..97f11ac0 100644 --- a/source/shared_lib/include/graphics/model.h +++ b/source/shared_lib/include/graphics/model.h @@ -46,6 +46,7 @@ private: bool texturesOwned[meshTextureCount]; string texturePaths[meshTextureCount]; + string name; //vertex data counts uint32 frameCount; uint32 vertexCount; @@ -69,6 +70,8 @@ private: bool twoSided; bool customColor; + uint32 textureFlags; + InterpolationData *interpolationData; TextureManager *textureManager; @@ -128,11 +131,15 @@ public: void updateInterpolationData(float t, bool cycle); void updateInterpolationVertices(float t, bool cycle); + Texture2D *loadMeshTexture(TextureManager *textureManager, string textureFile, + int textureChannelCount, bool &textureOwned, + bool deletePixMapAfterLoad); + //load void loadV2(const string &dir, FILE *f, TextureManager *textureManager,bool deletePixMapAfterLoad); void loadV3(const string &dir, FILE *f, TextureManager *textureManager,bool deletePixMapAfterLoad); void load(const string &dir, FILE *f, TextureManager *textureManager,bool deletePixMapAfterLoad); - void save(const string &dir, FILE *f); + void save(const string &dir, FILE *f, TextureManager *textureManager, string convertTextureToFormat); void deletePixels(); @@ -185,9 +192,9 @@ public: //io void load(const string &path,bool deletePixMapAfterLoad=false); - void save(const string &path); + void save(const string &path, string convertTextureToFormat=""); void loadG3d(const string &path,bool deletePixMapAfterLoad=false); - void saveS3d(const string &path); + void saveG3d(const string &path, string convertTextureToFormat=""); void setTextureManager(TextureManager *textureManager) {this->textureManager= textureManager;} void deletePixels(); diff --git a/source/shared_lib/sources/graphics/model.cpp b/source/shared_lib/sources/graphics/model.cpp index 58ccd3ab..0e445414 100644 --- a/source/shared_lib/sources/graphics/model.cpp +++ b/source/shared_lib/sources/graphics/model.cpp @@ -60,6 +60,8 @@ Mesh::Mesh() { twoSided= false; customColor= false; + textureFlags=0; + hasBuiltVBOs = false; // Vertex Buffer Object Names m_nVBOVertices = 0; @@ -214,6 +216,13 @@ void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager,boo twoSided= false; customColor= false; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Load v2, this = %p Found meshHeader.hasTexture = %d, texName [%s] mtDiffuse = %d\n",this,meshHeader.hasTexture,toLower(reinterpret_cast(meshHeader.texName)).c_str(),mtDiffuse); + + textureFlags= 0; + if(meshHeader.hasTexture == true) { + textureFlags= 1; + } + //texture if(meshHeader.hasTexture && textureManager!=NULL){ texturePaths[mtDiffuse]= toLower(reinterpret_cast(meshHeader.texName)); @@ -272,8 +281,15 @@ void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager,boo twoSided= (meshHeader.properties & mp3TwoSided) != 0; customColor= (meshHeader.properties & mp3CustomColor) != 0; + textureFlags= 0; + if((meshHeader.properties & mp3NoTexture) != mp3NoTexture) { + textureFlags= 1; + } + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Load v3, this = %p Found meshHeader.properties = %d, textureFlags = %d, texName [%s] mtDiffuse = %d\n",this,meshHeader.properties,textureFlags,toLower(reinterpret_cast(meshHeader.texName)).c_str(),mtDiffuse); + //texture - if(!(meshHeader.properties & mp3NoTexture) && textureManager!=NULL){ + if((meshHeader.properties & mp3NoTexture) != mp3NoTexture && textureManager!=NULL){ texturePaths[mtDiffuse]= toLower(reinterpret_cast(meshHeader.texName)); string texPath= dir; @@ -309,13 +325,37 @@ void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager,boo readBytes = fread(indices, sizeof(uint32)*indexCount, 1, f); } -void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager,bool deletePixMapAfterLoad) { +Texture2D* Mesh::loadMeshTexture(TextureManager *textureManager, string textureFile, + int textureChannelCount, bool &textureOwned, bool deletePixMapAfterLoad) { + Texture2D* texture = static_cast(textureManager->getTexture(textureFile)); + if(texture == NULL) { + texture = textureManager->newTexture2D(); + if(textureChannelCount != -1) { + texture->getPixmap()->init(textureChannelCount); + } + texture->load(textureFile); + textureOwned = true; + texture->init(textureManager->getTextureFilter(),textureManager->getMaxAnisotropy()); + if(deletePixMapAfterLoad == true) { + texture->deletePixels(); + } + } + + return texture; +} + +void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager, + bool deletePixMapAfterLoad) { this->textureManager = textureManager; //read header MeshHeader meshHeader; size_t readBytes = fread(&meshHeader, sizeof(MeshHeader), 1, f); + name = reinterpret_cast(meshHeader.name); + + //printf("Load, Found meshTextureCount = %d, meshHeader.textures = %d\n",meshTextureCount,meshHeader.textures); + //init frameCount= meshHeader.frameCount; vertexCount= meshHeader.vertexCount; @@ -333,6 +373,10 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager,bool specularPower= meshHeader.specularPower; opacity= meshHeader.opacity; + textureFlags= meshHeader.textures; + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Load v4, this = %p Found meshHeader.textures = %d\n",this,meshHeader.textures); + //maps uint32 flag= 1; for(int i=0; i(textureManager->getTexture(mapFullPath)); - if(textures[i]==NULL){ - textures[i]= textureManager->newTexture2D(); - if(meshTextureChannelCount[i] != -1){ - textures[i]->getPixmap()->init(meshTextureChannelCount[i]); - } - textures[i]->load(mapFullPath); - texturesOwned[i]=true; - textures[i]->init(textureManager->getTextureFilter(),textureManager->getMaxAnisotropy()); - if(deletePixMapAfterLoad == true) { - textures[i]->deletePixels(); - } - } + textures[i] = loadMeshTexture(textureManager, mapFullPath, + meshTextureChannelCount[i],texturesOwned[i],deletePixMapAfterLoad); } flag*= 2; } @@ -378,34 +411,101 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager,bool } } -void Mesh::save(const string &dir, FILE *f){ - /*MeshHeader meshHeader; - meshHeader.vertexFrameCount= vertexFrameCount; - meshHeader.normalFrameCount= normalFrameCount; - meshHeader.texCoordFrameCount= texCoordFrameCount; - meshHeader.colorFrameCount= colorFrameCount; - meshHeader.pointCount= pointCount; - meshHeader.indexCount= indexCount; - meshHeader.properties= 0; +void Mesh::save(const string &dir, FILE *f, TextureManager *textureManager, string convertTextureToFormat) { + MeshHeader meshHeader; + memset(&meshHeader, 0, sizeof(struct MeshHeader)); - if(twoSided) meshHeader.properties|= mpTwoSided; - if(customTexture) meshHeader.properties|= mpCustomTexture; + strncpy((char*)meshHeader.name, (char*)name.c_str(), name.length()); + meshHeader.frameCount= frameCount; + meshHeader.vertexCount= vertexCount; + meshHeader.indexCount = indexCount; - if(texture==NULL){ - meshHeader.properties|= mpNoTexture; - meshHeader.texName[0]= '\0'; + //material + memcpy((float32*)meshHeader.diffuseColor, (float32*)diffuseColor.ptr(), sizeof(float32) * 3); + memcpy((float32*)meshHeader.specularColor, (float32*)specularColor.ptr(), sizeof(float32) * 3); + meshHeader.specularPower = specularPower; + meshHeader.opacity = opacity; + + //properties + meshHeader.properties = 0; + if(customColor) { + meshHeader.properties |= mpfCustomColor; } - else{ - strcpy(reinterpret_cast(meshHeader.texName), texName.c_str()); - texture->getPixmap()->saveTga(dir+"/"+texName); + if(twoSided) { + meshHeader.properties |= mpfTwoSided; } + meshHeader.textures = textureFlags; fwrite(&meshHeader, sizeof(MeshHeader), 1, f); - fwrite(vertices, sizeof(Vec3f)*vertexFrameCount*pointCount, 1, f); - fwrite(normals, sizeof(Vec3f)*normalFrameCount*pointCount, 1, f); - fwrite(texCoords, sizeof(Vec2f)*texCoordFrameCount*pointCount, 1, f); - fwrite(colors, sizeof(Vec4f)*colorFrameCount, 1, f); - fwrite(indices, sizeof(uint32)*indexCount, 1, f);*/ + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Save, this = %p, Found meshTextureCount = %d, meshHeader.textures = %d\n",this,meshTextureCount,meshHeader.textures); + + //maps + uint32 flag= 1; + for(int i=0; i< meshTextureCount; ++i) { + if((meshHeader.textures & flag)) { + uint8 cMapPath[mapPathSize]; + memset(&cMapPath[0],0,mapPathSize); + + Texture2D *texture = textures[i]; + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Save, [%d] mesh texture ptr [%p]\n",i,texture); + + if(texture != NULL) { + string file = toLower(texture->getPath()); + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Save, Found mesh texture [%s]\n",file.c_str()); + + if(toLower(convertTextureToFormat) != "" && + EndsWith(file, "." + convertTextureToFormat) == false) { + string fileExt = extractExtension(file); + replaceAll(file, "." + fileExt, "." + convertTextureToFormat); + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Save, Convert from [%s] to [%s]\n",texture->getPath().c_str(),file.c_str()); + + if(convertTextureToFormat == "tga") { + texture->getPixmap()->saveTga(file); + } + else if(convertTextureToFormat == "bmp") { + texture->getPixmap()->saveBmp(file); + } + //else if(convertTextureToFormat == "jpg") { + // texture->getPixmap()->saveJpg(file); + //} + else if(convertTextureToFormat == "png") { + texture->getPixmap()->savePng(file); + } + else { + throw runtime_error("Unsuppoted texture format: [" + convertTextureToFormat + "]"); + } + + //textureManager->endTexture(texture); + texture = loadMeshTexture(textureManager,file, + meshTextureChannelCount[i], + texturesOwned[i], + false); + + } + + file = extractFileFromDirectoryPath(texture->getPath()); + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Save, new texture file [%s]\n",file.c_str()); + + memcpy(&cMapPath[0],file.c_str(),file.length()); + } + + fwrite(cMapPath, mapPathSize, 1, f); + } + flag*= 2; + } + + //read data + fwrite(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f); + fwrite(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f); + if(meshHeader.textures != 0) { + fwrite(texCoords, sizeof(Vec2f)*vertexCount, 1, f); + } + fwrite(indices, sizeof(uint32)*indexCount, 1, f); } void Mesh::computeTangents(){ @@ -535,10 +635,10 @@ void Model::load(const string &path, bool deletePixMapAfterLoad) { this->fileName = path; } -void Model::save(const string &path) { +void Model::save(const string &path, string convertTextureToFormat) { string extension= path.substr(path.find_last_of('.')+1); - if(extension=="g3d" ||extension=="G3D" || extension=="s3d" || extension=="S3D"){ - saveS3d(path); + if(extension=="g3d" ||extension=="G3D") { + saveG3d(path,convertTextureToFormat); } else{ throw runtime_error("Unknown model format: " + extension); @@ -604,12 +704,17 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad) { } fileVersion= fileHeader.version; + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Load model, fileVersion = %d\n",fileVersion); + //version 4 if(fileHeader.version == 4) { //model header ModelHeader modelHeader; readBytes = fread(&modelHeader, sizeof(ModelHeader), 1, f); meshCount= modelHeader.meshCount; + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("meshCount = %d\n",meshCount); + if(modelHeader.type != mtMorphMesh) { throw runtime_error("Invalid model type"); } @@ -623,8 +728,10 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad) { } //version 3 else if(fileHeader.version==3){ - readBytes = fread(&meshCount, sizeof(meshCount), 1, f); + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("meshCount = %d\n",meshCount); + meshes= new Mesh[meshCount]; for(uint32 i=0; i