bool Save(const char* path){ BufferedFile<> fh; if(!fh.OpenWrite(path)) return false; char* ver = "ZMS0008"; fh << TerminatedString(&ver, 0, 255); fh << mFormat; mBoundingBox.pmin *= 0.01f; mBoundingBox.pmax *= 0.01f; fh << mBoundingBox; byte boneTable[64]; std::vector<short> boneLookup; if(mFormat & RMF_BONEINDICES && mFormat & RMF_BONEWEIGHTS){ memset(boneTable, 0xFF, 64); for(int i = 0; i < mVertCount; ++i){ for(int j = 0; j < 4; ++j){ if(mVertBones[i].mWeights[j] > 0.0f){ if(boneTable[mVertBones[i].mBones[j]] != 0xFF) continue; boneTable[mVertBones[i].mBones[j]] = (byte)boneLookup.size(); boneLookup.push_back(mVertBones[i].mBones[j]); } } } short boneCount = (short)boneLookup.size(); fh << boneCount; for(int i = 0; i < boneCount; ++i){ short boneId = boneLookup[i]; fh << boneId; } }else{ short boneCount = 0; fh << boneCount; } fh << mVertCount; if(mFormat & RMF_POSITIONS){ for(int i = 0; i < mVertCount; ++i){ mVertPos[i] *= 0.01f; fh << mVertPos[i]; } } if(mFormat & RMF_NORMALS){ for(int i = 0; i < mVertCount; ++i) fh << mVertNorm[i]; } if(mFormat & RMF_BONEINDICES && mFormat & RMF_BONEWEIGHTS){ for(int i = 0; i < mVertCount; ++i){ fh << mVertBones[i].mWeights[0]; fh << mVertBones[i].mWeights[1]; fh << mVertBones[i].mWeights[2]; fh << mVertBones[i].mWeights[3]; for(int j = 0; j < 4; ++j){ short tmpBone; if(mVertBones[i].mWeights[j] > 0.0f) tmpBone = boneTable[mVertBones[i].mBones[j]]; else tmpBone = 0; fh << tmpBone; } } } if(mFormat & RMF_UVMAP1){ for(int i = 0; i < mVertCount; ++i){ mVertUV[0][i].y = 1.0f - mVertUV[0][i].y; fh << mVertUV[0][i]; } } if(mFormat & RMF_UVMAP2){ for(int i = 0; i < mVertCount; ++i){ mVertUV[1][i].y = 1.0f - mVertUV[1][i].y; fh << mVertUV[1][i]; } } if(mFormat & RMF_UVMAP3){ for(int i = 0; i < mVertCount; ++i){ mVertUV[2][i].y = 1.0f - mVertUV[2][i].y; fh << mVertUV[2][i]; } } if(mFormat & RMF_UVMAP4){ for(int i = 0; i < mVertCount; ++i){ mVertUV[3][i].y = 1.0f - mVertUV[3][i].y; fh << mVertUV[3][i]; } } fh << mFaceCount; int faceSize = mFaceCount * 3; for(int i = 0; i < faceSize; ++i) fh << mFaces[i]; short stripCount = 0; fh << stripCount; short matType = 0; fh << matType; short somethingElseThatIForgot = 0; fh << somethingElseThatIForgot; fh.Close(); return true; }
// ===================================================================================== // TEX_InitFromWad // ===================================================================================== bool TEX_InitFromWad() { int i, j; wadinfo_t wadinfo; char szTmpWad[1024]; // arbitrary, but needs to be large. char* pszWadFile; const char* pszWadroot; wadpath_t* currentwad; Log("\n"); // looks cleaner szTmpWad[0] = 0; pszWadroot = getenv("WADROOT"); #ifdef HLCSG_AUTOWAD autowad_UpdateUsedWads(); #endif // for eachwadpath for (i = 0; i < g_iNumWadPaths; i++) { FILE* texfile; // temporary used in this loop bool bExcludeThisWad = false; currentwad = g_pWadPaths[i]; pszWadFile = currentwad->path; #ifdef HLCSG_AUTOWAD #ifdef _DEBUG Log("[dbg] Attempting to parse wad: '%s'\n", pszWadFile); #endif if (g_bWadAutoDetect && !currentwad->usedtextures) continue; #ifdef _DEBUG Log("[dbg] Parsing wad\n"); #endif #endif texfiles[nTexFiles] = fopen(pszWadFile, "rb"); #ifdef SYSTEM_WIN32 if (!texfiles[nTexFiles]) { // cant find it, maybe this wad file has a hard code drive if (pszWadFile[1] == ':') { pszWadFile += 2; // skip past the drive texfiles[nTexFiles] = fopen(pszWadFile, "rb"); } } #endif if (!texfiles[nTexFiles] && pszWadroot) { char szTmp[_MAX_PATH]; char szFile[_MAX_PATH]; char szSubdir[_MAX_PATH]; ExtractFile(pszWadFile, szFile); ExtractFilePath(pszWadFile, szTmp); ExtractFile(szTmp, szSubdir); // szSubdir will have a trailing separator safe_snprintf(szTmp, _MAX_PATH, "%s" SYSTEM_SLASH_STR "%s%s", pszWadroot, szSubdir, szFile); texfiles[nTexFiles] = fopen(szTmp, "rb"); #ifdef SYSTEM_POSIX if (!texfiles[nTexFiles]) { // if we cant find it, Convert to lower case and try again strlwr(szTmp); texfiles[nTexFiles] = fopen(szTmp, "rb"); } #endif } if (!texfiles[nTexFiles]) { // still cant find it, error out Fatal(assume_COULD_NOT_FIND_WAD, "Could not open wad file %s", pszWadFile); continue; } // look and see if we're supposed to include the textures from this WAD in the bsp. WadInclude_i it; for (it = g_WadInclude.begin(); it != g_WadInclude.end(); it++) { if (stristr(pszWadFile, it->c_str())) { Log("Including Wadfile: %s\n", pszWadFile); bExcludeThisWad = true; // wadincluding this one s_WadIncludeMap[nTexFiles] = true; break; } } if (!bExcludeThisWad) { Log("Using Wadfile: %s\n", pszWadFile); safe_snprintf(szTmpWad, 1024, "%s%s;", szTmpWad, pszWadFile); } // temp assignment to make things cleaner: texfile = texfiles[nTexFiles]; // read in this wadfiles information SafeRead(texfile, &wadinfo, sizeof(wadinfo)); // make sure its a valid format if (strncmp(wadinfo.identification, "WAD2", 4) && strncmp(wadinfo.identification, "WAD3", 4)) { Log(" - "); Error("%s isn't a Wadfile!", pszWadFile); } wadinfo.numlumps = LittleLong(wadinfo.numlumps); wadinfo.infotableofs = LittleLong(wadinfo.infotableofs); // read in lump if (fseek(texfile, wadinfo.infotableofs, SEEK_SET)) Warning("fseek to %d in wadfile %s failed\n", wadinfo.infotableofs, pszWadFile); // memalloc for this lump lumpinfo = (lumpinfo_t*)realloc(lumpinfo, (nTexLumps + wadinfo.numlumps) * sizeof(lumpinfo_t)); // for each texlump for (j = 0; j < wadinfo.numlumps; j++, nTexLumps++) { SafeRead(texfile, &lumpinfo[nTexLumps], (sizeof(lumpinfo_t) - sizeof(int)) ); // iTexFile is NOT read from file if (!TerminatedString(lumpinfo[nTexLumps].name, MAXWADNAME)) { lumpinfo[nTexLumps].name[MAXWADNAME - 1] = 0; Log(" - "); Warning("Unterminated texture name : wad[%s] texture[%d] name[%s]\n", pszWadFile, nTexLumps, lumpinfo[nTexLumps].name); } CleanupName(lumpinfo[nTexLumps].name, lumpinfo[nTexLumps].name); lumpinfo[nTexLumps].filepos = LittleLong(lumpinfo[nTexLumps].filepos); lumpinfo[nTexLumps].disksize = LittleLong(lumpinfo[nTexLumps].disksize); lumpinfo[nTexLumps].iTexFile = nTexFiles; if (lumpinfo[nTexLumps].disksize > MAX_TEXTURE_SIZE) { Log(" - "); Warning("Larger than expected texture (%d bytes): '%s'", lumpinfo[nTexLumps].disksize, lumpinfo[nTexLumps].name); } } // AJM: this feature is dependant on autowad. :( // CONSIDER: making it standard? #ifdef HLCSG_AUTOWAD { double percused = ((float)(currentwad->usedtextures) / (float)(g_numUsedTextures)) * 100; Log(" - Contains %i used texture%s, %2.2f percent of map (%d textures in wad)\n", currentwad->usedtextures, currentwad->usedtextures == 1 ? "" : "s", percused, wadinfo.numlumps); } #endif nTexFiles++; hlassume(nTexFiles < MAX_TEXFILES, assume_MAX_TEXFILES); } //Log("num of used textures: %i\n", g_numUsedTextures); // AJM: Tommy suggested i add this warning message in, and it certianly doesnt // hurt to be cautious. Especially one of the possible side effects he mentioned was svc_bad if (nTexFiles > 8) { Log("\n"); Warning("More than 8 wadfiles are in use. (%i)\n" "This may be harmless, and if no strange side effects are occurring, then\n" "it can safely be ignored. However, if your map starts exhibiting strange\n" "or obscure errors, consider this as suspect.\n" , nTexFiles); } // sort texlumps in memory by name qsort((void*)lumpinfo, (size_t) nTexLumps, sizeof(lumpinfo[0]), lump_sorter_by_name); SetKeyValue(&g_entities[0], "wad", szTmpWad); Log("\n"); CheckFatal(); return true; }