bool WorldModel_Raw::Read(const char* path) { FILE* rf = fopen(path, "rb"); if (!rf) { printf("ERROR: Can't open raw model file: %s\n", path); return false; } char ident[8]; int readOperation = 0; READ_OR_RETURN(&ident, 8); CMP_OR_RETURN(ident, RAW_VMAP_MAGIC); // we have to read one int. This is needed during the export and we have to skip it here uint32 tempNVectors; READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); uint32 groups; READ_OR_RETURN(&groups, sizeof(uint32)); READ_OR_RETURN(&RootWMOID, sizeof(uint32)); groupsArray.resize(groups); bool succeed = true; for (uint32 g = 0; g < groups && succeed; ++g) { succeed = groupsArray[g].Read(rf); } fclose(rf); return succeed; }
//================================================================= bool TileAssembler::convertRawFile(const std::string& pModelFilename) { bool success = true; std::string filename = iSrcDir; if (filename.length() >0) filename.append("/"); filename.append(pModelFilename); FILE *rf = fopen(filename.c_str(), "rb"); if (!rf) { printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str()); printf("... or form: %s",filename.c_str() ); return false; } char ident[8]; int readOperation = 1; // temporary use defines to simplify read/check code (close file and return at fail) #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } READ_OR_RETURN(&ident, 8); CMP_OR_RETURN(ident, "VMAP003"); // we have to read one int. This is needed during the export and we have to skip it here uint32 tempNVectors; READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); uint32 groups; uint32 RootWMOID; char blockId[5]; blockId[4] = 0; int blocksize; READ_OR_RETURN(&groups, sizeof(uint32)); READ_OR_RETURN(&RootWMOID, sizeof(uint32)); std::vector<GroupModel> groupsArray; for (uint32 g=0; g<groups; ++g) { std::vector<MeshTriangle> triangles; std::vector<Vector3> vertexArray; uint32 mogpflags, GroupWMOID; READ_OR_RETURN(&mogpflags, sizeof(uint32)); READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); float bbox1[3], bbox2[3]; READ_OR_RETURN(bbox1, sizeof(float)*3); READ_OR_RETURN(bbox2, sizeof(float)*3); uint32 liquidflags; READ_OR_RETURN(&liquidflags, sizeof(uint32)); // will this ever be used? what is it good for anyway?? uint32 branches; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "GRP "); READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&branches, sizeof(uint32)); for (uint32 b=0; b<branches; ++b) { uint32 indexes; // indexes for each branch (not used jet) READ_OR_RETURN(&indexes, sizeof(uint32)); } // ---- indexes READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "INDX"); READ_OR_RETURN(&blocksize, sizeof(int)); uint32 nindexes; READ_OR_RETURN(&nindexes, sizeof(uint32)); if (nindexes >0) { uint16 *indexarray = new uint16[nindexes]; READ_OR_RETURN(indexarray, nindexes*sizeof(uint16)); for (uint32 i=0; i<nindexes; i+=3) { triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2])); } delete[] indexarray; } // ---- vectors READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "VERT"); READ_OR_RETURN(&blocksize, sizeof(int)); uint32 nvectors; READ_OR_RETURN(&nvectors, sizeof(uint32)); if (nvectors >0) { float *vectorarray = new float[nvectors*3]; READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); for (uint32 i=0; i<nvectors; ++i) { vertexArray.push_back( Vector3(vectorarray + 3*i) ); } delete[] vectorarray; } // ----- liquid WmoLiquid *liquid = 0; if (liquidflags& 1) { WMOLiquidHeader hlq; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "LIQU"); READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); uint32 size = hlq.xverts*hlq.yverts; READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float)); size = hlq.xtiles*hlq.ytiles; READ_OR_RETURN(liquid->GetFlagsStorage(), size); } groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2)))); groupsArray.back().setMeshData(vertexArray, triangles); groupsArray.back().setLiquidData(liquid); // drop of temporary use defines #undef READ_OR_RETURN #undef CMP_OR_RETURN } fclose(rf); // write WorldModel WorldModel model; model.setRootWmoID(RootWMOID); if (groupsArray.size()) { model.setGroupModels(groupsArray); success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); } //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; return success; }
bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) { std::string modelFilename = iSrcDir + "/" + spawn.name; ModelPosition modelPosition; modelPosition.iDir = spawn.iRot; modelPosition.iScale = spawn.iScale; modelPosition.init(); FILE *rf = fopen(modelFilename.c_str(), "rb"); if (!rf) { printf("ERROR: Can't open model file: %s\n", modelFilename.c_str()); return false; } AABox modelBound; bool boundEmpty=true; char ident[8]; int readOperation = 1; // temporary use defines to simplify read/check code (close file and return at fail) #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } READ_OR_RETURN(&ident, 8); CMP_OR_RETURN(ident, "VMAP003"); // we have to read one int. This is needed during the export and we have to skip it here uint32 tempNVectors; READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); uint32 groups, wmoRootId; char blockId[5]; blockId[4] = 0; int blocksize; float *vectorarray = 0; READ_OR_RETURN(&groups, sizeof(uint32)); READ_OR_RETURN(&wmoRootId, sizeof(uint32)); if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... { fseek(rf, 3*sizeof(uint32) + 6*sizeof(float), SEEK_CUR); READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "GRP "); READ_OR_RETURN(&blocksize, sizeof(int)); fseek(rf, blocksize, SEEK_CUR); // ---- indexes READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "INDX"); READ_OR_RETURN(&blocksize, sizeof(int)); fseek(rf, blocksize, SEEK_CUR); // ---- vectors READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "VERT"); READ_OR_RETURN(&blocksize, sizeof(int)); uint32 nvectors; READ_OR_RETURN(&nvectors, sizeof(uint32)); if (nvectors >0) { vectorarray = new float[nvectors*3]; READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); } else { std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; return false; } for (uint32 i=0, indexNo=0; indexNo<nvectors; indexNo++, i+=3) { Vector3 v = Vector3(vectorarray[i+0], vectorarray[i+1], vectorarray[i+2]); v = modelPosition.transform(v); if (boundEmpty) modelBound = AABox(v, v), boundEmpty=false; else modelBound.merge(v); } delete[] vectorarray; // drop of temporary use defines #undef READ_OR_RETURN #undef CMP_OR_RETURN } spawn.iBound = modelBound + spawn.iPos; spawn.flags |= MOD_HAS_BOUND; fclose(rf); return true; }
bool GroupModel_Raw::Read(FILE* rf) { char blockId[5]; blockId[4] = 0; int blocksize; int readOperation = 0; READ_OR_RETURN(&mogpflags, sizeof(uint32)); READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); Vector3 vec1, vec2; READ_OR_RETURN(&vec1, sizeof(Vector3)); READ_OR_RETURN(&vec2, sizeof(Vector3)); bounds.set(vec1, vec2); READ_OR_RETURN(&liquidflags, sizeof(uint32)); // will this ever be used? what is it good for anyway?? uint32 branches; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "GRP "); READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&branches, sizeof(uint32)); for (uint32 b = 0; b < branches; ++b) { uint32 indexes; // indexes for each branch (not used jet) READ_OR_RETURN(&indexes, sizeof(uint32)); } // ---- indexes READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "INDX"); READ_OR_RETURN(&blocksize, sizeof(int)); uint32 nindexes; READ_OR_RETURN(&nindexes, sizeof(uint32)); if (nindexes > 0) { uint16* indexarray = new uint16[nindexes]; if (fread(indexarray, nindexes * sizeof(uint16), 1, rf) != 1) { fclose(rf); delete[] indexarray; printf("readfail, op = %i\n", readOperation); return false; } triangles.reserve(nindexes / 3); for (uint32 i = 0; i < nindexes; i += 3) { triangles.push_back(MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2])); } delete[] indexarray; } // ---- vectors READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "VERT"); READ_OR_RETURN(&blocksize, sizeof(int)); uint32 nvectors; READ_OR_RETURN(&nvectors, sizeof(uint32)); if (nvectors > 0) { float* vectorarray = new float[nvectors * 3]; if (fread(vectorarray, nvectors * sizeof(float) * 3, 1, rf) != 1) { fclose(rf); delete[] vectorarray; printf("readfail, op = %i\n", readOperation); return false; } for (uint32 i = 0; i < nvectors; ++i) { vertexArray.push_back(Vector3(vectorarray + 3 * i)); } delete[] vectorarray; } // ----- liquid liquid = 0; if (liquidflags & 1) { WMOLiquidHeader hlq; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "LIQU"); READ_OR_RETURN(&blocksize, sizeof(int)); READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); uint32 size = hlq.xverts * hlq.yverts; READ_OR_RETURN(liquid->GetHeightStorage(), size * sizeof(float)); size = hlq.xtiles * hlq.ytiles; READ_OR_RETURN(liquid->GetFlagsStorage(), size); } return true; }