bool Model::LoadS3O(const char *filename, IProgressCtl& /*progctl*/) { S3OHeader header; size_t read_result; FILE *file = fopen (filename, "rb"); if (!file) return false; read_result = fread (&header, sizeof(S3OHeader), 1, file); if (read_result != (size_t)1) throw std::runtime_error ("Couldn't read S3O header."); logger.Trace (NL_Error,"Wrong version. Only version 1 is supported"); if (memcmp (header.magic, S3O_ID, 12)) { logger.Trace (NL_Error, "S3O model %s has wrong identification", filename); fclose (file); return false; } if (header.version != 0) { logger.Trace (NL_Error, "S3O model %s has wrong version (%d, wanted: %d)", filename, header.version, 0); fclose (file); return false; } radius = header.radius; mid.set (-header.midx, header.midy, header.midz); height = header.height; root = S3O_LoadObject (file, header.rootPiece); MirrorX(root); string mdlPath = GetFilePath (filename); // load textures for (int tex=0;tex<2;tex++) { if ( !(tex ? header.texture2 : header.texture1)) continue; texBindings.push_back(TextureBinding()); TextureBinding &tb = texBindings.back (); tb.name = ReadString (tex ? header.texture2 : header.texture1, file); tb.texture = new Texture (tb.name, mdlPath); if (!tb.texture->IsLoaded ()) tb.texture = 0; } mapping = MAPPING_S3O; fclose (file); return true; }
static MdlObject *S3O_LoadObject (FILE *f, ulong offset) { int oldofs = ftell(f); MdlObject *obj = new MdlObject; PolyMesh* pm; obj->geometry = pm = new PolyMesh; // Read piece header S3OPiece piece; fseek (f, offset, SEEK_SET); fread (&piece, sizeof(S3OPiece), 1, f); // Read name obj->name = ReadString (piece.name, f); obj->position.set(piece.xoffset,piece.yoffset,piece.zoffset); // Read child objects fseek (f, piece.childs, SEEK_SET); for (int a=0;a<piece.numChilds;a++) { ulong chOffset; fread (&chOffset, sizeof(ulong), 1, f); MdlObject *child = S3O_LoadObject (f, chOffset); if (child) { child->parent = obj; obj->childs.push_back (child); } } // Read vertices pm->verts.resize (piece.numVertices); fseek (f, piece.vertices, SEEK_SET); for (int a=0;a<piece.numVertices;a++) { S3OVertex sv; fread (&sv, sizeof(S3OVertex), 1, f); pm->verts [a].normal.set (sv.xnormal, sv.ynormal, sv.znormal); pm->verts [a].pos.set (sv.xpos, sv.ypos, sv.zpos); pm->verts [a].tc[0] = Vector2(sv.texu, sv.texv); } // Read primitives - 0=triangles,1 triangle strips,2=quads fseek (f, piece.vertexTable, SEEK_SET); switch (piece.primitiveType) { case 0: { // triangles for (int i=0;i<piece.vertexTableSize;i+=3) { ulong index; Poly *pl = new Poly; pl->verts.resize(3); for (int a=0;a<3;a++) { fread (&index,4,1,f); pl->verts [a] = index; } pm->poly.push_back (pl); } break;} case 1: { // tristrips ulong *data=new ulong[piece.vertexTableSize]; fread (data,4,piece.vertexTableSize, f); for (int i=0;i<piece.vertexTableSize;) { // find out how long this strip is int first=i; while (i<piece.vertexTableSize && data[i]!=-1) i++; // create triangles from it for (int a=2;a<i-first;a++) { Poly *pl = new Poly; pl->verts.resize(3); for (int x=0;x<3;x++) pl->verts[(a&1)?x:2-x]=data[first+a+x-2]; pm->poly.push_back(pl); } } delete[] data; break;} case 2: { // quads for (int i=0;i<piece.vertexTableSize;i+=4) { ulong index; Poly *pl = new Poly; pl->verts.resize(4); for (int a=0;a<4;a++) { fread (&index,4,1,f); pl->verts [a] = index; } pm->poly.push_back (pl); } break;} } // fltk::message("object %s has %d polygon and %d vertices", obj->name.c_str(), obj->poly.size(),pm->verts.size()); fseek (f, oldofs, SEEK_SET); return obj; }