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; }
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 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; }
struct fiasco * fiasco_alloc_from_file(const char * file) { uint8_t byte; uint32_t length; uint32_t count; uint8_t length8; uint8_t count8; char type[13]; char device[17]; char hwrevs[1024]; char version[257]; char layout[257]; uint16_t hash; off_t offset; struct image * image; char hwrev[9]; unsigned char buf[512]; unsigned char *pbuf; struct fiasco * fiasco = fiasco_alloc_empty(); if ( ! fiasco ) return NULL; fiasco->fd = open(file, O_RDONLY); if ( fiasco->fd < 0 ) { ERROR_INFO("Cannot open file"); fiasco_free(fiasco); return NULL; } fiasco->orig_filename = strdup(file); READ_OR_FAIL(fiasco, &byte, 1); if ( byte != 0xb4 ) FIASCO_READ_ERROR(fiasco, "Invalid fiasco signature"); READ_OR_FAIL(fiasco, &length, 4); length = ntohl(length); READ_OR_FAIL(fiasco, &count, 4); count = ntohl(count); VERBOSE("Number of header blocks: %d\n", count); while ( count > 0 ) { READ_OR_FAIL(fiasco, &byte, 1); READ_OR_FAIL(fiasco, &length8, 1); READ_OR_FAIL(fiasco, buf, length8); if ( byte == 0xe8 ) { memset(fiasco->name, 0, sizeof(fiasco->name)); strncpy(fiasco->name, (char *)buf, length8); VERBOSE("Fiasco name: %s\n", fiasco->name); } else if ( byte == 0x31 ) { memset(fiasco->swver, 0, sizeof(fiasco->swver)); strncpy(fiasco->swver, (char *)buf, length8); VERBOSE("SW version: %s\n", fiasco->swver); } else { VERBOSE("Unknown header %#x\n", byte); } --count; } /* walk the tree */ while ( 1 ) { /* If end of file, return fiasco image */ READ_OR_RETURN(fiasco, buf, 7); /* Header of next image */ if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) { ERROR("Invalid next image header"); return fiasco; } count8 = buf[1]; if ( count8 > 0 ) --count8; READ_OR_RETURN(fiasco, &hash, 2); hash = ntohs(hash); memset(type, 0, sizeof(type)); READ_OR_RETURN(fiasco, type, 12); byte = type[0]; if ( byte == 0xFF ) return fiasco; VERBOSE(" %s\n", type); READ_OR_RETURN(fiasco, &length, 4); length = ntohl(length); /* unknown */ READ_OR_RETURN(fiasco, buf, 4); VERBOSE(" size: %d bytes\n", length); VERBOSE(" hash: %#04x\n", hash); VERBOSE(" subsections: %d\n", count8); memset(device, 0, sizeof(device)); memset(hwrevs, 0, sizeof(hwrevs)); memset(version, 0, sizeof(version)); memset(layout, 0, sizeof(layout)); while ( count8 > 0 ) { READ_OR_RETURN(fiasco, &byte, 1); READ_OR_RETURN(fiasco, &length8, 1); READ_OR_RETURN(fiasco, buf, length8); VERBOSE(" subinfo\n"); VERBOSE(" length: %d\n", length8); VERBOSE(" type: "); if ( byte == '1' ) { memset(version, 0, sizeof(version)); strncpy(version, (char *)buf, length8); VERBOSE("version string\n"); VERBOSE(" version: %s\n", version); } else if ( byte == '2' ) { int tmp = length8; if ( tmp > 16 ) tmp = 16; memset(device, 0, sizeof(device)); strncpy(device, (char *)buf, tmp); VERBOSE("hw revision\n"); VERBOSE(" device: %s\n", device); pbuf = buf + strlen(device) + 1; while ( pbuf < buf + length8 ) { while ( pbuf < buf + length8 && *pbuf < 32 ) ++pbuf; if ( pbuf >= buf + length8 ) break; tmp = buf + length8 - pbuf; if ( tmp > 8 ) tmp = 8; memset(hwrev, 0, sizeof(hwrev)); strncpy(hwrev, (char *)pbuf, tmp); if ( ! hwrevs[0] ) strcpy(hwrevs, hwrev); else { size_t len1 = strlen(hwrevs); size_t len2 = strlen(hwrev); if ( len1 + len2 + 2 < sizeof(hwrevs) ) { hwrevs[len1] = ','; memcpy(hwrevs+len1+1, hwrev, len2+1); } } VERBOSE(" hw revision: %s\n", hwrev); pbuf += strlen(hwrev) + 1; } } else if ( byte == '3' ) { memset(layout, 0, sizeof(layout)); strncpy(layout, (char *)buf, length8); VERBOSE("layout\n"); } else { VERBOSE("unknown ('%c':%#x)\n", byte, byte); } --count8; } /* unknown */ READ_OR_RETURN(fiasco, buf, 1); offset = lseek(fiasco->fd, 0, SEEK_CUR); if ( offset == (off_t)-1 ) FIASCO_READ_ERROR(fiasco, "Cannot get offset of file"); VERBOSE(" version: %s\n", version); VERBOSE(" device: %s\n", device); VERBOSE(" hwrevs: %s\n", hwrevs); VERBOSE(" data at: %#08x\n", (unsigned int)offset); image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout); if ( ! image ) FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); fiasco_add_image(fiasco, image); if ( lseek(fiasco->fd, offset+length, SEEK_SET) == (off_t)-1 ) FIASCO_READ_ERROR(fiasco, "Cannot seek to next image in file"); } }