/// <summary> /// Construct a new MDLObject /// </summary> /// <returns></returns> public MDLObject NewMDLObject() { MDLObject o = new MDLObject(); o.nchildren = 0; o.childrens = null; o.lodval = 0; o.type = MDLType.mdl_empty; o.textidx = -1; return(o); }
// SaveToFile sub part - save a child object void SaveObject(MDLObject po, BinaryWriter bw, int GroupPos, int MeshPos, int TextPos, int TextGeoPos) { if (po.type == MDLType.mdl_group) { bw.Write((int)5); bw.Write(po.nchildren); for (int n = 0; n < po.nchildren; n++) { SaveObject(po.childrens[n], bw, GroupPos, MeshPos, TextPos, TextGeoPos); bw.Write((int)0); } bw.Write((int)9); bw.Write(GroupPos); bw.Write((int)6); } if (po.type == MDLType.mdl_lod) { bw.Write((int)5); bw.Write(po.nchildren); for (int n = 0; n < po.nchildren; n++) { SaveObject(po.childrens[n], bw, GroupPos, MeshPos, TextPos, TextGeoPos); if (po.childrens[n].lodval != 0) { bw.Write((int)1); bw.Write(po.childrens[n].lodval); bw.Write((int)10); } bw.Write((int)0); } bw.Write((int)9); bw.Write(GroupPos); bw.Write((int)6); } if (po.type == MDLType.mdl_mesh) { if (po.textidx != -1) { bw.Write((int)9); bw.Write(TextPos + po.textidx); } // save mesh bw.Write((int)9); bw.Write(MeshPos); bw.Write((int)7); bw.Write((int)po.mesh.nvertex); bw.Write((int)po.mesh.nfaces); for (int v = 0; v < po.mesh.nvertex; v++) { bw.Write(po.mesh.vertices[v].x); bw.Write(po.mesh.vertices[v].y); bw.Write(po.mesh.vertices[v].z); bw.Write(po.mesh.vertices[v].mx); bw.Write(po.mesh.vertices[v].my); bw.Write(po.mesh.vertices[v].nx); bw.Write(po.mesh.vertices[v].ny); bw.Write(po.mesh.vertices[v].nz); } for (int v = 0; v < po.mesh.nfaces; v++) { bw.Write(po.mesh.faces[v]); } if (po.textidx != -1) { bw.Write((int)9); bw.Write(TextGeoPos); bw.Write((int)6); } } }
/// <summary> /// Read a binary MDL file /// a real mess ! /// return true on success /// </summary> /// <param name="sFileName"></param> /// <returns></returns> public bool ReadFromFile(string sFileName) { FileStream cf; try { cf = new FileStream(sFileName, FileMode.Open, FileAccess.Read, FileShare.Read); } catch { return(false); } BinaryReader br = new BinaryReader(cf); uint cookie = br.ReadUInt32(); if (cookie != 0xDEBADF00) { br.Close(); cf.Close(); return(false); } MDLHeader header = new MDLHeader(); if (!header.ReadHeader(br)) { br.Close(); cf.Close(); return(false); } NumTextures = 0; for (int i = 0; i < header.nb_tags; i++) { string tag = ParseString(br); header.TagsNames[i] = tag; if ((tag != "model") && (tag != "effect")) { NumTextures++; } } int idx = 0; int[] TexturesIdx = new int[NumTextures]; if (NumTextures != 0) { Textures = new string[NumTextures]; for (int i = 0; i < header.nb_tags; i++) { string tag = header.TagsNames[i]; if ((tag != "model") && (tag != "effect")) { Textures[idx] = tag; TexturesIdx[idx] = i; idx++; } } } // ASSERT(idx==NumTextures); for (int i = 0; i < header.l2; i++) { int uk1 = br.ReadInt32(); string tag = ParseString(br); header.L2Vals[i].Name = tag; header.L2Vals[i].Value = uk1; } for (int i = 0; i < header.l3; i++) { string tag = ParseString(br); header.l3names[i] = tag; } // LOOP LEVEL 3 int lastText = -1; //MDLObject lastObject = new MDLObject(); MDLObject [] stackedObjects = new MDLObject[500]; int[] stack = new int[200]; int sopos = -1; for (int L3 = 0; L3 < header.l3; L3++) { int l3val = br.ReadInt32(); bool cont = true; int stackpos = -1; // LOOL LEVEL 2 while (cont) { int token = br.ReadInt32(); switch (token) { case 5: { // start of group // push # val int nentry = br.ReadInt32(); stack[++stackpos] = nentry; break; } case 9: { int l2idx = br.ReadInt32(); if ((l2idx < 0) || (l2idx > header.l2)) { //ReadError.Format("unmatched l2idx = %s",l2idx); cont = false; break; } else { string l2type = header.L2Vals[l2idx].Name; bool matched = false; if (l2type == "MeshGeo") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { cont = false; break; } MDLMesh mesh = new MDLMesh(); mesh.nvertex = br.ReadInt32(); mesh.nfaces = br.ReadInt32(); mesh.vertices = new MDLVertice[mesh.nvertex]; for (int n = 0; n < mesh.nvertex; n++) { // read vertice MDLVertice vert = new MDLVertice(); vert.x = br.ReadSingle(); vert.y = br.ReadSingle();; vert.z = br.ReadSingle();; vert.mx = br.ReadSingle();; vert.my = br.ReadSingle();; vert.nx = br.ReadSingle();; vert.ny = br.ReadSingle();; vert.nz = br.ReadSingle();; mesh.vertices[n] = vert; } mesh.faces = new ushort[mesh.nfaces]; for (int n = 0; n < mesh.nfaces; n++) { mesh.faces[n] = br.ReadUInt16(); } stackedObjects[++sopos] = NewMDLObject(); stackedObjects[sopos].mesh = mesh; stackedObjects[sopos].type = MDLType.mdl_mesh; } if (l2type == "ModifiableNumber") { int six = br.ReadInt32(); matched = true; } if (l2type == "LightsGeo") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { // ReadError.Format("bad data %d in LightsGeo",datatype); cont = false; break; } if (NumLights != 0) { // ReadError.Format("double ligths!!!"); cont = false; break; } int nlite = br.ReadInt32(); NumLights = nlite; Lights = new MDLLight[nlite]; for (int n = 0; n < nlite; n++) { MDLLight lite = new MDLLight(); lite.Read(br); Lights[n] = lite; } } if (l2type == "FrameData") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { //ReadError.Format("bad data %d in FrameData",datatype); cont = false; break; } if (NumFrameDatas != 0) { // ReadError.Format("double framedata!!!"); cont = false; break; } int ndata = br.ReadInt32(); NumFrameDatas = ndata; FrameDatas = new MDLFrameData[ndata]; for (int n = 0; n < ndata; n++) { MDLFrameData data = new MDLFrameData(); data.name = ParseString(br); data.Read(br); FrameDatas[n] = data; } } if (l2type == "TextureGeo") { matched = true; int six = br.ReadInt32(); // ASSERT(lastObject != NULL); stackedObjects[sopos].textidx = lastText; } if (l2type == "LODGeo") { matched = true; int six = br.ReadInt32(); MDLObject lastObject = NewMDLObject(); lastObject.type = MDLType.mdl_lod; lastObject.nchildren = stack[stackpos] + 1; lastObject.childrens = new MDLObject[lastObject.nchildren]; for (int n = 0; n < lastObject.nchildren; n++) { lastObject.childrens[n] = stackedObjects[sopos--]; } stackedObjects[++sopos] = lastObject; stackpos--; } if (l2type == "GroupGeo") { matched = true; int six = br.ReadInt32(); MDLObject lastObject = NewMDLObject(); lastObject.type = MDLType.mdl_group; lastObject.nchildren = stack[stackpos]; lastObject.childrens = new MDLObject[lastObject.nchildren]; for (int n = 0; n < lastObject.nchildren; n++) { lastObject.childrens[n] = stackedObjects[sopos--]; } stackedObjects[++sopos] = lastObject; stackpos--; } if (l2type == "time") { matched = true; //ReadError.Format("!!time!!"), cont = false; break; } if (l2type == "ImportImage") { matched = true; cont = false; int datatype = br.ReadInt32(); if (datatype != 7) { // ReadError.Format("bad data %d in ImportImage",datatype); cont = false; break; } MDLImage img = new MDLImage(0, 0); img.Read(br); stackedObjects[++sopos] = NewMDLObject(); stackedObjects[sopos].image = img; stackedObjects[sopos].type = MDLType.mdl_image; break; } if (!matched) { for (int n = 0; n < header.nb_tags; n++) { if (l2type == header.TagsNames[n]) { matched = true; lastText = -1; for (int p = 0; p < NumTextures; p++) { if (TexturesIdx[p] == header.L2Vals[l2idx].Value) { lastText = p; } } // ASSERT(lastText != -1); } } } if (!matched) { //ReadError.Format("unmatched l2type = %s\n",l2type); cont = false; break; } } break; } case 1: { float val = br.ReadSingle(); if (header.l3names[L3] == "frame") { FrameVal = val; } else { // ASSERT(lastObject != NULL); stackedObjects[sopos].lodval = val; } break; } case 10: { // handle 10 break; } case 0: { if (stackpos >= 0) { //stack[stackpos] -=1; } else { cont = false; } break; } default: //ReadError.Format("unknow token = %d\n",token); cont = false; break; } // switch } // while(cont) } // l3 RootObject = stackedObjects[sopos]; br.Close(); cf.Close(); return(true); }
/// <summary> /// Read a binary MDL file /// a real mess ! /// return true on success /// </summary> /// <param name="sFileName"></param> /// <returns></returns> public bool ReadFromFile(string sFileName) { FileStream cf; try { cf = new FileStream(sFileName, FileMode.Open, FileAccess.Read, FileShare.Read); } catch { return(false); } BinaryReader br = new BinaryReader(cf); header = new MDLHeader(); if (!header.ReadHeader(br)) { br.Close(); cf.Close(); return(false); } // Read in namespaces for (int i = 0; i < header.ImportedNameSpacesCount; i++) { string tag = ReadAlignedString(br); header.NameSpaces.Add(tag); //if ((tag != "model") && (tag != "effect")) // NumTextures++; } // Count number of names spaecs we dont recognize and assume they are texture namespaces. NumTextures = header.NameSpaces.Count(x => x != "model" && x != "effect"); Textures = header.NameSpaces.Where(x => x != "model" && x != "effect").ToDictionary(x => x, x => this.header.NameSpaces.IndexOf(x)); // ASSERT(idx==NumTextures); for (int i = 0; i < header.ImportedSymoblCount; i++) { int uk1 = br.ReadInt32(); string tag = ReadAlignedString(br); SymbolPair sp; sp.Name = tag; sp.Value = uk1; header.ImportedSymbols.Add(sp); } for (int i = 0; i < header.ExportedSymbolCount; i++) { string tag = ReadAlignedString(br); header.ExportedSymbols.Add(tag); } // LOOP LEVEL 3 int lastText = -1; //MDLObject lastObject = new MDLObject(); MDLObject[] stackedObjects = new MDLObject[500]; int[] stack = new int[200]; int sopos = -1; for (int L3 = 0; L3 < header.ExportedSymbolCount; L3++) { int l3val = br.ReadInt32(); bool cont = true; int stackpos = -1; // LOOL LEVEL 2 while (cont) { int token = br.ReadInt32(); switch (token) { case 5: { // start of group // push # val int nentry = br.ReadInt32(); stack[++stackpos] = nentry; break; } case 9: { int l2idx = br.ReadInt32(); if ((l2idx < 0) || (l2idx > header.ImportedSymoblCount)) { //ReadError.Format("unmatched l2idx = %s",l2idx); cont = false; break; } else { string l2type = header.ImportedSymbols[l2idx].Name; bool matched = false; if (l2type == "MeshGeo") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { cont = false; break; } MDLMesh mesh = new MDLMesh(); mesh.nvertex = br.ReadInt32(); mesh.nfaces = br.ReadInt32(); mesh.vertices = new MDLVertice[mesh.nvertex]; for (int n = 0; n < mesh.nvertex; n++) { // read vertice MDLVertice vert = new MDLVertice(); vert.x = br.ReadSingle(); vert.y = br.ReadSingle();; vert.z = br.ReadSingle();; vert.mx = br.ReadSingle();; vert.my = br.ReadSingle();; vert.nx = br.ReadSingle();; vert.ny = br.ReadSingle();; vert.nz = br.ReadSingle();; mesh.vertices[n] = vert; } mesh.faces = new ushort[mesh.nfaces]; for (int n = 0; n < mesh.nfaces; n++) { mesh.faces[n] = br.ReadUInt16(); } stackedObjects[++sopos] = NewMDLObject(); stackedObjects[sopos].mesh = mesh; stackedObjects[sopos].type = MDLType.mdl_mesh; } if (l2type == "ModifiableNumber") { int six = br.ReadInt32(); matched = true; } if (l2type == "LightsGeo") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { // ReadError.Format("bad data %d in LightsGeo",datatype); cont = false; break; } if (NumLights != 0) { // ReadError.Format("double ligths!!!"); cont = false; break; } int nlite = br.ReadInt32(); NumLights = nlite; Lights = new List <MDLLight>(); for (int n = 0; n < nlite; n++) { MDLLight lite = new MDLLight(); lite.Read(br); Lights.Add(lite); } } if (l2type == "FrameData") { matched = true; int datatype = br.ReadInt32(); if (datatype != 7) { //ReadError.Format("bad data %d in FrameData",datatype); cont = false; break; } if (NumFrameDatas != 0) { // ReadError.Format("double framedata!!!"); cont = false; break; } int ndata = br.ReadInt32(); NumFrameDatas = ndata; FrameDatas = new List <MDLFrameData>(); for (int n = 0; n < ndata; n++) { MDLFrameData data = new MDLFrameData(); data.name = ReadAlignedString(br); data.Read(br); FrameDatas.Add(data); } } if (l2type == "TextureGeo") { matched = true; int six = br.ReadInt32(); // ASSERT(lastObject != NULL); stackedObjects[sopos].textidx = lastText; } if (l2type == "LODGeo") { matched = true; int six = br.ReadInt32(); MDLObject lastObject = NewMDLObject(); lastObject.type = MDLType.mdl_lod; lastObject.nchildren = stack[stackpos] + 1; lastObject.childrens = new MDLObject[lastObject.nchildren]; for (int n = 0; n < lastObject.nchildren; n++) { lastObject.childrens[n] = stackedObjects[sopos--]; } stackedObjects[++sopos] = lastObject; stackpos--; } if (l2type == "GroupGeo") { matched = true; int six = br.ReadInt32(); MDLObject lastObject = NewMDLObject(); lastObject.type = MDLType.mdl_group; lastObject.nchildren = stack[stackpos]; lastObject.childrens = new MDLObject[lastObject.nchildren]; for (int n = 0; n < lastObject.nchildren; n++) { lastObject.childrens[n] = stackedObjects[sopos--]; } stackedObjects[++sopos] = lastObject; stackpos--; } if (l2type == "time") { matched = true; //ReadError.Format("!!time!!"), cont = false; break; } if (l2type == "ImportImage") { matched = true; cont = false; int datatype = br.ReadInt32(); if (datatype != 7) { // ReadError.Format("bad data %d in ImportImage",datatype); cont = false; break; } MDLImage img = new MDLImage(); img.Read(br); stackedObjects[++sopos] = NewMDLObject(); stackedObjects[sopos].image = img; stackedObjects[sopos].type = MDLType.mdl_image; break; } if (!matched) { for (int n = 0; n < header.ImportedNameSpacesCount; n++) { if (l2type == header.NameSpaces[n]) { matched = true; lastText = -1; for (int p = 0; p < NumTextures; p++) { if (Textures.ElementAt(p).Value == header.ImportedSymbols[l2idx].Value) { lastText = p; } } // ASSERT(lastText != -1); } } } if (!matched) { //ReadError.Format("unmatched l2type = %s\n",l2type); cont = false; break; } } break; } case 1: { float val = br.ReadSingle(); if (header.ExportedSymbols[L3] == "frame") { FrameVal = val; } else { // ASSERT(lastObject != NULL); stackedObjects[sopos].lodval = val; } break; } case 10: { // handle 10 break; } case 0: { if (stackpos >= 0) { //stack[stackpos] -=1; } else { cont = false; } break; } default: //ReadError.Format("unknow token = %d\n",token); cont = false; break; } // switch } // while(cont) } // l3 RootObject = new List <MDLObject>(stackedObjects.Where(x => x != null));//[sopos]; br.Close(); cf.Close(); return(true); }