static void parseKeyFramer(MeshModel* root) { _log("KeyFramer"); enterChunk(); std::string file_3ds; unsigned short rev, curr_time = 0; while (int id = nextChunk()) { switch (id) { case 0xb009: //CURR_TIME in.sgetn((char*)&curr_time, 2); _log("CURR_TIME: " + itoa(curr_time)); break; case 0xb00a: //KFHDR in.sgetn((char*)&rev, 2); file_3ds = parseString(); in.sgetn((char*)&anim_len, 2); _log("KFHDR: revision=" + itoa(rev) + " 3dsfile=" + file_3ds + " anim_len=" + itoa(anim_len)); break; case 0xb002: //object keyframer data... parseMeshInfo(root, curr_time); break; } } if (!collapse) { root->setAnimator(new Animator(root, anim_len)); } leaveChunk(); }
static MeshModel* parseFile() { unsigned short id; int len; in.sgetn((char*)&id, 2); in.sgetn((char*)&len, 4); if (id != CHUNK_MAIN) return 0; chunk_end = (int)in.pubseekoff(0, std::ios_base::cur) + len - 6; enterChunk(); MeshModel* root = new MeshModel(); while (int id = nextChunk()) { switch (id) { case CHUNK_SCENE: parseScene(root); break; case CHUNK_KEYFRAMER: parseKeyFramer(root); break; } } leaveChunk(); return root; }
static void parseFaceList() { unsigned short cnt; in.sgetn((char*)&cnt, 2); _log("FaceList cnt=" + itoa(cnt)); while (cnt--) { unsigned short v[4]; in.sgetn((char*)v, 8); Face3DS face; face.verts[0] = v[0]; face.verts[1] = v[1]; face.verts[2] = v[2]; if (flip_tris) std::swap(face.verts[1], face.verts[2]); faces.push_back(face); } enterChunk(); while (int id = nextChunk()) { switch (id) { case CHUNK_FACEMAT: parseFaceMat(); break; } } leaveChunk(); }
static int nextChunk() { in.pubseekoff(chunk_end, std::ios_base::beg); if (chunk_end == parent_end.back()) return 0; unsigned short id; int len; in.sgetn((char*)&id, 2); in.sgetn((char*)&len, 4); chunk_end = (int)in.pubseekoff(0, std::ios_base::cur) + len - 6; return id; }
static void parseFaceMat() { std::string name = parseString(); _log("FaceMat: " + name); Brush mat = materials_map[name]; unsigned short cnt; in.sgetn((char*)&cnt, 2); while (cnt--) { unsigned short face; in.sgetn((char*)&face, 2); faces[face].brush = mat; } }
static void parseVertList() { unsigned short cnt; in.sgetn((char*)&cnt, 2); _log("VertList cnt=" + itoa(cnt)); while (cnt--) { Surface::Vertex v; in.sgetn((char*)&v.coords, 12); if (conv) v.coords = conv_tform * v.coords; MeshLoader::addVertex(v); } }
static void parseMapList() { _log("MapList"); unsigned short cnt; in.sgetn((char*)&cnt, 2); for (int k = 0; k < cnt; ++k) { float uv[2]; in.sgetn((char*)uv, 8); Surface::Vertex& v = MeshLoader::refVertex(k); v.tex_coords[0][0] = v.tex_coords[1][0] = uv[0]; v.tex_coords[0][1] = v.tex_coords[1][1] = 1 - uv[1]; // v->tex_coords[0]=v->tex_coords[1]=Vector( uv[0],1-uv[1],1 ); } }
static Vector parseColor() { Vector v; unsigned char rgb[3]; enterChunk(); while (int id = nextChunk()) { switch (id) { case CHUNK_RGBF: in.sgetn((char*)&v, 12); break; case CHUNK_RGBB: in.sgetn((char*)rgb, 3); v = Vector(rgb[0] / 255.0f, rgb[1] / 255.0f, rgb[2] / 255.0f); } } leaveChunk(); return v; }
static void parseMeshInfo(MeshModel* root, float curr_time) { _log("OBJECT_NODE_TAG"); enterChunk(); std::string name, inst; Vector pivot; Animation anim; unsigned short id = 65535, parent = 65535, flags1, flags2; Box box = Box(Vector(), Vector()); Vector box_centre; while (int chunk_id = nextChunk()) { switch (chunk_id) { case 0xb030: //NODE_ID in.sgetn((char*)&id, 2); _log("NODE_ID: " + itoa(id)); break; case 0xb010: //NODE_HDR name = parseString(); in.sgetn((char*)&flags1, 2); in.sgetn((char*)&flags2, 2); in.sgetn((char*)&parent, 2); _log("NODE_HDR: name=" + name + " parent=" + itoa(parent)); break; case 0xb011: //INSTANCE NAME inst = parseString(); _log("INSTANCE_NAME: " + inst); break; case 0xb013: //PIVOT in.sgetn((char*)&pivot, 12); if (conv) pivot = conv_tform * pivot; _log("PIVOT: " + ftoa(pivot.x) + "," + ftoa(pivot.y) + "," + ftoa(pivot.z)); break; case 0xb014: //BOUNDBOX in.sgetn((char*)&(box.a), 12); in.sgetn((char*)&(box.b), 12); box_centre = box.centre(); if (conv) box_centre = conv_tform * box_centre; _log("BOUNDBOX: min=" + ftoa(box.a.x) + "," + ftoa(box.a.y) + "," + ftoa(box.a.z) + " max=" + ftoa(box.b.x) + "," + ftoa(box.b.y) + "," + ftoa(box.b.z)); break; case 0xb020: //POS_TRACK_TAG case 0xb021: //ROT_TRACK_TAG case 0xb022: //SCALE_TRACK_TAG if (!collapse) parseAnimKeys(&anim, chunk_id); break; } } leaveChunk(); MeshModel* p = root; if (parent != 65535) { std::map<int, MeshModel*>::const_iterator it = id_map.find(parent); if (it == id_map.end()) return; p = it->second; } MeshModel* mesh = 0; if (name == "$$$DUMMY") { mesh = new MeshModel(); mesh->SetName(inst); mesh->SetParent(p); } else { std::map<std::string, MeshModel*>::const_iterator it = name_map.find(name); if (it == name_map.end()) return; mesh = it->second; name_map.erase(name); if (pivot != Vector()) { mesh->transform(-pivot); } Transform t = mesh->GetWorldTransform(); mesh->SetParent(p); mesh->SetWorldTransform(t); } mesh->setAnimation(anim); if (id != 65535) id_map[id] = mesh; }
static void parseAnimKeys(Animation* anim, int type) { int cnt = 0; short t_flags; in.sgetn((char*)&t_flags, 2); in.pubseekoff(8, std::ios_base::cur); in.sgetn((char*)&cnt, 2); in.pubseekoff(2, std::ios_base::cur); _log("ANIM_TRACK: frames=" + itoa(cnt)); Vector pos, axis, scale; float angle; Quat quat; for (int k = 0; k < cnt; ++k) { int time; short flags; in.sgetn((char*)&time, 4); in.sgetn((char*)&flags, 2); float tens = 0, cont = 0, bias = 0, ease_to = 0, ease_from = 0; if (flags & 1) in.sgetn((char*)&tens, 4); if (flags & 2) in.sgetn((char*)&cont, 4); if (flags & 4) in.sgetn((char*)&bias, 4); if (flags & 8) in.sgetn((char*)&ease_to, 4); if (flags & 16) in.sgetn((char*)&ease_from, 4); switch (type) { case 0xb020: //POS_TRACK_TAG in.sgetn((char*)&pos, 12); if (conv) pos = conv_tform * pos; // _log( "POS_KEY: time="+itoa(time)+" pos="+ftoa( pos.x )+","+ftoa( pos.y )+","+ftoa( pos.z ) ); if (time <= anim_len) anim->setPositionKey(time, pos); break; case 0xb021: //ROT_TRACK_TAG in.sgetn((char*)&angle, 4); in.sgetn((char*)&axis, 12); // _log( "ROT_KEY: time="+itoa(time)+" angle="+ftoa(angle)+" axis="+ftoa(axis.x)+","+ftoa(axis.y)+","+ftoa(axis.z) ); if (axis.length() > FLT_EPSILON) { if (flip_tris) angle = -angle; if (conv) axis = conv_tform.m * axis; quat = Quat(cosf(angle / 2), axis.normalized() * sinf(angle / 2)) * quat; quat.normalize(); } if (time <= anim_len) anim->setRotationKey(time, quat); break; case 0xb022: //SCL_TRACK_TAG in.sgetn((char*)&scale, 12); if (conv) scale = conv_tform.m * scale; // scale.x=fabs(scale.x);scale.y=fabs(scale.y);scale.z=fabs(scale.z); _log("SCL_KEY: time=" + itoa(time) + " scale=" + ftoa(scale.x) + "," + ftoa(scale.y) + "," + ftoa(scale.z)); if (time <= anim_len) anim->setScaleKey(time, scale); break; } } }
static void parseTriMesh(MeshModel* mesh) { _log("TriMesh"); enterChunk(); Transform tform; faces.clear(); MeshLoader::beginMesh(); while (int id = nextChunk()) { switch (id) { case CHUNK_VERTLIST: if (!animonly) parseVertList(); break; case CHUNK_MAPLIST: if (!animonly) parseMapList(); break; case CHUNK_FACELIST: if (!animonly) parseFaceList(); break; case CHUNK_TRMATRIX: in.sgetn((char*)&tform, 48); if (conv) tform = conv_tform * tform * -conv_tform; break; } } leaveChunk(); //should really do something here... // bool neg_x=tform.m.j.cross(tform.m.k).dot(tform.m.i)<0; int k; mesh->SetWorldTransform(tform); if (animonly) { MeshLoader::endMesh(0); return; } Transform inv_tform = -tform; for (k = 0; k < MeshLoader::numVertices(); ++k) { Surface::Vertex& v = MeshLoader::refVertex(k); v.coords = inv_tform * v.coords; } for (k = 0; k < faces.size(); ++k) { const Face3DS& f = faces[k]; MeshLoader::addTriangle(f.verts, f.brush); } MeshLoader::endMesh(mesh); mesh->updateNormals(); faces.clear(); }