ufomodel.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../../shared/ufotypes.h"
00027 #include "../../common/mem.h"
00028 #include "../../shared/shared.h"
00029 #include "../../common/filesys.h"
00030 #include "../../common/qfiles.h"
00031 #include "../../shared/typedefs.h"
00032 #include "../../common/mem.h"
00033 #include "../../client/renderer/r_material.h"
00034 #include "../../client/renderer/r_image.h"
00035 #include "../../client/renderer/r_model.h"
00036 #include "../../client/renderer/r_state.h"
00037 #include "../../shared/images.h"
00038 
00039 #define VERSION "0.2"
00040 
00041 rstate_t r_state;
00042 image_t *r_noTexture;
00043 
00044 typedef enum {
00045     ACTION_NONE,
00046 
00047     ACTION_MDX,
00048     ACTION_SKINEDIT,
00049     ACTION_CHECK,
00050     ACTION_SKINFIX,
00051     ACTION_GLCMDSREMOVE
00052 } ufoModelAction_t;
00053 
00054 typedef struct modelConfig_s {
00055     qboolean overwrite;
00056     qboolean verbose;
00057     char fileName[MAX_QPATH];
00058     ufoModelAction_t action;
00059     float smoothness;
00060     char inputName[MAX_QPATH];
00061 } modelConfig_t;
00062 
00063 static modelConfig_t config;
00064 
00065 struct memPool_s *com_genericPool;
00066 struct memPool_s *com_fileSysPool;
00067 struct memPool_s *vid_modelPool;
00068 struct memPool_s *vid_imagePool;
00069 
00070 static void Exit(int exitCode) __attribute__ ((__noreturn__));
00071 
00072 static void Exit (int exitCode)
00073 {
00074     Mem_Shutdown();
00075 
00076     exit(exitCode);
00077 }
00078 
00079 void Com_Printf (const char *format, ...)
00080 {
00081     char out_buffer[4096];
00082     va_list argptr;
00083 
00084     va_start(argptr, format);
00085     Q_vsnprintf(out_buffer, sizeof(out_buffer), format, argptr);
00086     va_end(argptr);
00087 
00088     printf("%s", out_buffer);
00089 }
00090 
00091 void Com_DPrintf (int level, const char *fmt, ...)
00092 {
00093     if (config.verbose) {
00094         char outBuffer[4096];
00095         va_list argptr;
00096 
00097         va_start(argptr, fmt);
00098         Q_vsnprintf(outBuffer, sizeof(outBuffer), fmt, argptr);
00099         va_end(argptr);
00100 
00101         Com_Printf("%s", outBuffer);
00102     }
00103 }
00104 
00105 image_t *R_LoadImageData (const char *name, byte * pic, int width, int height, imagetype_t type)
00106 {
00107     image_t *image;
00108     size_t len;
00109 
00110     len = strlen(name);
00111     if (len >= sizeof(image->name))
00112         Com_Error(ERR_DROP, "R_LoadImageData: \"%s\" is too long", name);
00113     if (len == 0)
00114         Com_Error(ERR_DROP, "R_LoadImageData: name is empty");
00115 
00116     image = Mem_PoolAlloc(sizeof(*image), vid_imagePool, 0);
00117     image->has_alpha = qfalse;
00118     image->type = type;
00119     image->width = width;
00120     image->height = height;
00121 
00122     Q_strncpyz(image->name, name, sizeof(image->name));
00123     /* drop extension */
00124     if (len >= 4 && image->name[len - 4] == '.') {
00125         image->name[len - 4] = '\0';
00126         Com_Printf("Image with extension: '%s'\n", name);
00127     }
00128 
00129     return image;
00130 }
00131 
00132 image_t *R_FindImage (const char *pname, imagetype_t type)
00133 {
00134     char lname[MAX_QPATH];
00135     image_t *image;
00136     SDL_Surface *surf;
00137 
00138     if (!pname || !pname[0])
00139         Com_Error(ERR_FATAL, "R_FindImage: NULL name");
00140 
00141     /* drop extension */
00142     Com_StripExtension(pname, lname, sizeof(lname));
00143 
00144     if (Img_LoadImage(lname, &surf)) {
00145         image = R_LoadImageData(lname, surf->pixels, surf->w, surf->h, type);
00146         SDL_FreeSurface(surf);
00147     } else {
00148         image = NULL;
00149     }
00150 
00151     /* no fitting texture found */
00152     if (!image) {
00153         Com_Printf("  \\ - could not load skin '%s'\n", pname);
00154         image = r_noTexture;
00155     }
00156 
00157     return image;
00158 }
00159 
00164 void Com_Error (int code, const char *fmt, ...)
00165 {
00166     va_list argptr;
00167     static char msg[1024];
00168 
00169     va_start(argptr, fmt);
00170     Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
00171     va_end(argptr);
00172 
00173     fprintf(stderr, "Error: %s\n", msg);
00174     Exit(1);
00175 }
00176 
00177 
00182 static model_t *LoadModel (const char *name)
00183 {
00184     model_t *mod;
00185     byte *buf;
00186     int modfilelen;
00187 
00188     /* load the file */
00189     modfilelen = FS_LoadFile(name, &buf);
00190     if (!buf) {
00191         Com_Printf("Could not load '%s'\n", name);
00192         return NULL;
00193     }
00194 
00195     mod = Mem_PoolAlloc(sizeof(*mod), vid_modelPool, 0);
00196     Q_strncpyz(mod->name, name, sizeof(mod->name));
00197 
00198     /* call the appropriate loader */
00199     switch (LittleLong(*(unsigned *) buf)) {
00200     case IDALIASHEADER:
00201         /* MD2 header */
00202         R_ModLoadAliasMD2Model(mod, buf, modfilelen, qfalse);
00203         break;
00204 
00205     case DPMHEADER:
00206         R_ModLoadAliasDPMModel(mod, buf, modfilelen);
00207         break;
00208 
00209     case IDMD3HEADER:
00210         /* MD3 header */
00211         R_ModLoadAliasMD3Model(mod, buf, modfilelen);
00212         break;
00213 
00214     default:
00215         if (!Q_strcasecmp(mod->name + strlen(mod->name) - 4, ".obj"))
00216             R_LoadObjModel(mod, buf, modfilelen);
00217         else
00218             Com_Error(ERR_FATAL, "R_ModForName: unknown fileid for %s", mod->name);
00219     }
00220 
00221     FS_FreeFile(buf);
00222 
00223     return mod;
00224 }
00225 
00226 static void WriteToFile (const model_t *mod, const mAliasMesh_t *mesh, const char *fileName)
00227 {
00228     int i;
00229     qFILE f;
00230     uint32_t version = MDX_VERSION;
00231     int32_t numIndexes, numVerts, idx;
00232 
00233     Com_Printf("  \\ - writing to file '%s'\n", fileName);
00234 
00235     FS_OpenFile(fileName, &f, FILE_WRITE);
00236     if (!f.f) {
00237         Com_Printf("  \\ - can not open '%s' for writing\n", fileName);
00238         return;
00239     }
00240 
00241     FS_Write(IDMDXHEADER, strlen(IDMDXHEADER), &f);
00242     version = LittleLong(version);
00243     FS_Write(&version, sizeof(version), &f);
00244 
00245     numIndexes = LittleLong(mesh->num_tris * 3);
00246     numVerts = LittleLong(mesh->num_verts);
00247     FS_Write(&numVerts, sizeof(int32_t), &f);
00248     FS_Write(&numIndexes, sizeof(int32_t), &f);
00249 
00250     for (i = 0; i < mesh->num_tris * 3; i++) {
00251         idx = LittleLong(mesh->indexes[i]);
00252         FS_Write(&idx, sizeof(int32_t), &f);
00253     }
00254 
00255     FS_CloseFile(&f);
00256 }
00257 
00258 static int PrecalcNormalsAndTangents (const char *filename)
00259 {
00260     char mdxFileName[MAX_QPATH];
00261     model_t *mod;
00262     int i;
00263     int cntCalculated = 0;
00264 
00265     Com_Printf("- model '%s'\n", filename);
00266 
00267     Com_StripExtension(filename, mdxFileName, sizeof(mdxFileName));
00268     Q_strcat(mdxFileName, ".mdx", sizeof(mdxFileName));
00269 
00270     if (!config.overwrite && FS_CheckFile("%s", mdxFileName) != -1) {
00271         Com_Printf("  \\ - mdx already exists\n");
00272         return 0;
00273     }
00274 
00275     mod = LoadModel(filename);
00276     if (!mod)
00277         Com_Error(ERR_DROP, "Could not load %s", filename);
00278 
00279     Com_Printf("  \\ - # meshes '%i', # frames '%i'\n", mod->alias.num_meshes, mod->alias.num_frames);
00280 
00281     for (i = 0; i < mod->alias.num_meshes; i++) {
00282         mAliasMesh_t *mesh = &mod->alias.meshes[i];
00283         R_ModCalcUniqueNormalsAndTangents(mesh, mod->alias.num_frames, config.smoothness);
00286         WriteToFile(mod, mesh, mdxFileName);
00287 
00288         cntCalculated++;
00289     }
00290 
00291     return cntCalculated;
00292 }
00293 
00294 static void PrecalcNormalsAndTangentsBatch (const char *pattern)
00295 {
00296     const char *filename;
00297     int cntCalculated, cntAll;
00298 
00299     FS_BuildFileList(pattern);
00300 
00301     cntAll = cntCalculated = 0;
00302 
00303     while ((filename = FS_NextFileFromFileList(pattern)) != NULL) {
00304         cntAll++;
00305         cntCalculated += PrecalcNormalsAndTangents(filename);
00306     }
00307 
00308     FS_NextFileFromFileList(NULL);
00309 
00310     Com_Printf("%i/%i\n", cntCalculated, cntAll);
00311 }
00312 
00313 static void Usage (void)
00314 {
00315     Com_Printf("Usage:\n");
00316     Com_Printf(" -mdx                     generate mdx files\n");
00317     Com_Printf(" -skinfix                 fix skins for md2 models\n");
00318     Com_Printf(" -glcmds                  remove the unused glcmds from md2 models\n");
00319     Com_Printf(" -check                   perform general checks for all the models\n");
00320     Com_Printf(" -skinedit <filename>     edit skin of a model\n");
00321     Com_Printf(" -overwrite               overwrite existing mdx files\n");
00322     Com_Printf(" -s <float>               sets the smoothness value for normal-smoothing (in the range -1.0 to 1.0)\n");
00323     Com_Printf(" -f <filename>            build tangentspace for the specified model file\n");
00324     Com_Printf(" -v --verbose             print debug messages\n");
00325     Com_Printf(" -h --help                show this help screen\n");
00326 }
00327 
00328 static void UM_DefaultParameter (void)
00329 {
00330     config.smoothness = 0.5;
00331 }
00332 
00336 static void UM_Parameter (int argc, char **argv)
00337 {
00338     int i;
00339 
00340     for (i = 1; i < argc; i++) {
00341         if (!strcmp(argv[i], "-overwrite")) {
00342             config.overwrite = qtrue;
00343         } else if (!strcmp(argv[i], "-f") && (i + 1 < argc)) {
00344             Q_strncpyz(config.inputName, argv[++i], sizeof(config.inputName));
00345         } else if (!strcmp(argv[i], "-s") && (i + 1 < argc)) {
00346             config.smoothness = strtod(argv[++i], NULL);
00347             if (config.smoothness < -1.0 || config.smoothness > 1.0){
00348                 Usage();
00349                 Exit(1);
00350             }
00351         } else if (!strcmp(argv[i], "-mdx")) {
00352             config.action = ACTION_MDX;
00353         } else if (!strcmp(argv[i], "-glcmds")) {
00354             config.action = ACTION_GLCMDSREMOVE;
00355         } else if (!strcmp(argv[i], "-skinfix")) {
00356             config.action = ACTION_SKINFIX;
00357         } else if (!strcmp(argv[i], "-check")) {
00358             config.action = ACTION_CHECK;
00359         } else if (!strcmp(argv[i], "-skinedit")) {
00360             config.action = ACTION_SKINEDIT;
00361             if (i + 1 == argc) {
00362                 Usage();
00363                 Exit(1);
00364             }
00365             Q_strncpyz(config.fileName, argv[i + 1], sizeof(config.fileName));
00366             i++;
00367         } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) {
00368             config.verbose = qtrue;
00369         } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
00370             Usage();
00371             Exit(0);
00372         } else {
00373             Com_Printf("Parameters unknown. Try --help.\n");
00374             Usage();
00375             Exit(1);
00376         }
00377     }
00378 }
00379 
00380 static void MD2HeaderCheck (const dMD2Model_t *md2, const char *fileName, int bufSize)
00381 {
00382     /* sanity checks */
00383     const uint32_t version = LittleLong(md2->version);
00384     const uint32_t numSkins = LittleLong(md2->num_skins);
00385     const uint32_t numTris = LittleLong(md2->num_tris);
00386     const uint32_t numVerts = LittleLong(md2->num_verts);
00387 
00388     if (version != MD2_ALIAS_VERSION)
00389         Com_Error(ERR_DROP, "%s has wrong version number (%i should be %i)", fileName, version, MD2_ALIAS_VERSION);
00390 
00391     if (bufSize != LittleLong(md2->ofs_end))
00392         Com_Error(ERR_DROP, "model %s broken offset values (%i, %i)", fileName, bufSize, LittleLong(md2->ofs_end));
00393 
00394     if (numSkins == 0 || numSkins >= MD2_MAX_SKINS)
00395         Com_Error(ERR_DROP, "model '%s' has invalid skin number: %i", fileName, numSkins);
00396 
00397     if (numVerts == 0 || numVerts >= MD2_MAX_VERTS)
00398         Com_Error(ERR_DROP, "model %s has too many (or no) vertices (%i/%i)", fileName, numVerts, MD2_MAX_VERTS);
00399 
00400     if (numTris == 0 || numTris >= MD2_MAX_TRIANGLES)
00401         Com_Error(ERR_DROP, "model %s has too many (or no) triangles (%i/%i)", fileName, numTris, MD2_MAX_TRIANGLES);
00402 }
00403 
00404 static void MD2SkinEdit (const byte *buf, const char *fileName, int bufSize, void *userData)
00405 {
00406     const char *md2Path;
00407     uint32_t numSkins;
00408     int i;
00409     const dMD2Model_t *md2 = (const dMD2Model_t *)buf;
00410 
00411     MD2HeaderCheck(md2, fileName, bufSize);
00412 
00413     md2Path = (const char *) md2 + LittleLong(md2->ofs_skins);
00414     numSkins = LittleLong(md2->num_skins);
00415 
00416     for (i = 0; i < numSkins; i++) {
00417         const char *name = md2Path + i * MD2_MAX_SKINNAME;
00418         Com_Printf("  \\ - skin %i: %s\n", i, name);
00420     }
00421 }
00422 
00423 typedef void (*modelWorker_t) (const byte *buf, const char *fileName, int bufSize, void *userData);
00424 
00431 static void ModelWorker (modelWorker_t worker, const char *fileName, void *userData)
00432 {
00433     byte *buf = NULL;
00434     int modfilelen;
00435 
00436     /* load the file */
00437     modfilelen = FS_LoadFile(fileName, &buf);
00438     if (!buf)
00439         Com_Error(ERR_FATAL, "%s not found", fileName);
00440 
00441     switch (LittleLong(*(unsigned *) buf)) {
00442     case IDALIASHEADER:
00443     case DPMHEADER:
00444     case IDMD3HEADER:
00445     case IDBSPHEADER:
00446         worker(buf, fileName, modfilelen, userData);
00447         break;
00448 
00449     default:
00450         if (!Q_strcasecmp(fileName + strlen(fileName) - 4, ".obj"))
00451             worker(buf, fileName, modfilelen, userData);
00452         else
00453             Com_Error(ERR_DROP, "ModelWorker: unknown fileid for %s", fileName);
00454     }
00455 
00456     FS_FreeFile(buf);
00457 }
00458 
00459 static void MD2GLCmdsRemove (const byte *buf, const char *fileName, int bufSize, void *userData)
00460 {
00461     const char *md2Path;
00462     uint32_t numGLCmds;
00463     const dMD2Model_t *md2 = (const dMD2Model_t *)buf;
00464 
00465     MD2HeaderCheck(md2, fileName, bufSize);
00466 
00467     md2Path = (const char *) md2 + LittleLong(md2->ofs_glcmds);
00468     numGLCmds = LittleLong(md2->num_glcmds);
00469 
00470     if (numGLCmds > 0) {
00471         dMD2Model_t *fixedMD2 = Mem_Dup(buf, bufSize);
00472         const size_t delta = numGLCmds * sizeof(uint32_t);
00473         const uint32_t offset = LittleLong(fixedMD2->ofs_glcmds);
00474 
00475         if (LittleLong(fixedMD2->ofs_skins) > offset || LittleLong(fixedMD2->ofs_frames) > offset
00476          || LittleLong(fixedMD2->ofs_st) > offset || LittleLong(fixedMD2->ofs_tris) > offset) {
00477             Com_Error(ERR_DROP, "Unexpected order of the different data lumps");
00478         }
00479 
00480         fixedMD2->ofs_end = LittleLong(fixedMD2->ofs_end - delta);
00481         fixedMD2->ofs_glcmds = 0;
00482         fixedMD2->num_glcmds = 0;
00483 
00484         bufSize -= delta;
00485 
00486         FS_WriteFile(fixedMD2, bufSize, fileName);
00487 
00488         Mem_Free(fixedMD2);
00489 
00490         *(size_t *)userData += delta;
00491         Com_Printf("  \\ - removed %i glcmds from '%s' (save "UFO_SIZE_T" bytes)\n",
00492                 numGLCmds, fileName, delta);
00493     }
00494 }
00495 
00496 static void MD2SkinFix (const byte *buf, const char *fileName, int bufSize, void *userData)
00497 {
00498     const char *md2Path;
00499     uint32_t numSkins;
00500     int i;
00501     const dMD2Model_t *md2 = (const dMD2Model_t *)buf;
00502     byte *model = NULL;
00503 
00504     MD2HeaderCheck(md2, fileName, bufSize);
00505 
00506     md2Path = (const char *) md2 + LittleLong(md2->ofs_skins);
00507     numSkins = LittleLong(md2->num_skins);
00508 
00509     for (i = 0; i < numSkins; i++) {
00510         const char *extension;
00511         int errors = 0;
00512         const char *name = md2Path + i * MD2_MAX_SKINNAME;
00513 
00514         if (name[0] != '.')
00515             errors++;
00516         else
00517             /* skip the . to not confuse the extension extraction below */
00518             name++;
00519 
00520         extension = Com_GetExtension(name);
00521         if (extension != NULL)
00522             errors++;
00523 
00524         if (errors > 0) {
00525             dMD2Model_t *fixedMD2;
00526             char *skinPath;
00527             char path[MD2_MAX_SKINNAME];
00528             char pathBuf[MD2_MAX_SKINNAME];
00529             const char *fixedPath;
00530             if (model == NULL) {
00531                 model = Mem_Dup(buf, bufSize);
00532                 Com_Printf("model: %s\n", fileName);
00533             }
00534             fixedMD2 = (dMD2Model_t *)model;
00535             skinPath = (char *) fixedMD2 + LittleLong(fixedMD2->ofs_skins) + i * MD2_MAX_SKINNAME;
00536 
00537             memset(path, 0, sizeof(path));
00538 
00539             if (extension != NULL) {
00540                 Com_StripExtension(name, pathBuf, sizeof(pathBuf));
00541                 fixedPath = pathBuf;
00542             } else {
00543                 fixedPath = name;
00544             }
00545             if (name[0] != '.')
00546                 Com_sprintf(path, sizeof(path), ".%s", Com_SkipPath(fixedPath));
00547             Com_Printf("  \\ - skin %i: changed path to '%s'\n", i + 1, path);
00548             if (R_AliasModelGetSkin(fileName, path) == r_noTexture) {
00549                 Com_Printf("    \\ - could not load the skin with the new path\n");
00550             } else {
00551                 memcpy(skinPath, path, sizeof(path));
00552             }
00553         }
00554     }
00555     if (model != NULL) {
00556         FS_WriteFile(model, bufSize, fileName);
00557         Mem_Free(model);
00558     }
00559 }
00560 
00561 static void MD2Check (const byte *buf, const char *fileName, int bufSize, void *userData)
00562 {
00563     const char *md2Path;
00564     uint32_t numSkins;
00565     int i;
00566     qboolean headline = qfalse;
00567     const dMD2Model_t *md2 = (const dMD2Model_t *)buf;
00568 
00569     MD2HeaderCheck(md2, fileName, bufSize);
00570 
00571     md2Path = (const char *) md2 + LittleLong(md2->ofs_skins);
00572     numSkins = LittleLong(md2->num_skins);
00573 
00574     for (i = 0; i < numSkins; i++) {
00575         const char *extension;
00576         int errors = 0;
00577         const char *name = md2Path + i * MD2_MAX_SKINNAME;
00578 
00579         if (name[0] != '.')
00580             errors++;
00581         else
00582             /* skip the . to not confuse the extension extraction below */
00583             name++;
00584 
00585         extension = Com_GetExtension(name);
00586         if (extension != NULL)
00587             errors++;
00588 
00589         if (errors > 0) {
00590             if (!headline) {
00591                 Com_Printf("model: %s\n", fileName);
00592                 headline = qtrue;
00593             }
00594             Com_Printf("  \\ - skin %i: %s - %i errors/warnings\n", i + 1, name, errors);
00595             if (name[0] != '.')
00596                 Com_Printf("    \\ - skin contains full path\n");
00597             if (extension != NULL)
00598                 Com_Printf("    \\ - skin contains extension '%s'\n", extension);
00599             if (R_AliasModelGetSkin(fileName, md2Path + i * MD2_MAX_SKINNAME) == r_noTexture)
00600                 Com_Printf("  \\ - could not load the skin\n");
00601         }
00602     }
00603 }
00604 
00605 static void MD2Visitor (modelWorker_t worker, void *userData)
00606 {
00607     const char *fileName;
00608     const char *pattern = "**.md2";
00609 
00610     FS_BuildFileList(pattern);
00611 
00612     while ((fileName = FS_NextFileFromFileList(pattern)) != NULL)
00613         ModelWorker(worker, fileName, userData);
00614 
00615     FS_NextFileFromFileList(NULL);
00616 }
00617 
00618 static void ModelCheck (void)
00619 {
00620     MD2Visitor(MD2Check, NULL);
00621 }
00622 
00623 static void SkinFix (void)
00624 {
00625     MD2Visitor(MD2SkinFix, NULL);
00626 }
00627 
00628 static void GLCmdsRemove (void)
00629 {
00630     size_t bytes = 0;
00631     MD2Visitor(MD2GLCmdsRemove, &bytes);
00632     Com_Printf("Saved "UFO_SIZE_T"bytes after removing all glcmds from the md2 files\n", bytes);
00633 }
00634 
00635 int main (int argc, char **argv)
00636 {
00637     Com_Printf("---- ufomodel "VERSION" ----\n");
00638 
00639     UM_DefaultParameter();
00640     UM_Parameter(argc, argv);
00641 
00642     if (config.action == ACTION_NONE) {
00643         Usage();
00644         Exit(1);
00645     }
00646 
00647     Swap_Init();
00648     Mem_Init();
00649 
00650     com_genericPool = Mem_CreatePool("ufomodel");
00651     com_fileSysPool = Mem_CreatePool("ufomodel filesys");
00652     vid_modelPool = Mem_CreatePool("ufomodel model");
00653     vid_imagePool = Mem_CreatePool("ufomodel image");
00654 
00655     FS_InitFilesystem(qfalse);
00656 
00657     r_noTexture = Mem_PoolAlloc(sizeof(*r_noTexture), vid_imagePool, 0);
00658     Q_strncpyz(r_noTexture->name, "noTexture", sizeof(r_noTexture->name));
00659 
00660     switch (config.action) {
00661     case ACTION_MDX:
00662         if (config.inputName[0] == '\0') {
00663             PrecalcNormalsAndTangentsBatch("**.md2");
00664             PrecalcNormalsAndTangentsBatch("**.md3");
00665             PrecalcNormalsAndTangentsBatch("**.dpm");
00667             /*PrecalcNormalsAndTangentsBatch("**.obj");*/
00668         } else {
00669             PrecalcNormalsAndTangents(config.inputName);
00670         }
00671         break;
00672 
00673     case ACTION_SKINEDIT:
00674         ModelWorker(MD2SkinEdit, config.fileName, NULL);
00675         break;
00676 
00677     case ACTION_CHECK:
00678         ModelCheck();
00679         break;
00680 
00681     case ACTION_SKINFIX:
00682         SkinFix();
00683         break;
00684 
00685     case ACTION_GLCMDSREMOVE:
00686         GLCmdsRemove();
00687         break;
00688 
00689     default:
00690         Exit(1);
00691     }
00692 
00693     Mem_Shutdown();
00694 
00695     return 0;
00696 }

Generated by  doxygen 1.6.2