void ReadChunk(FileStream fileStream, BinaryReader binaryReader) { string chunkType = new string(binaryReader.ReadChars(4)); int chunkLength = (int)binaryReader.ReadUInt32(); if (chunkType == "PNTS") { Debug.WriteLine(chunkType + ", length " + chunkLength); int vertexCount = chunkLength / 12; model.vertices = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { model.vertices[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), -binaryReader.ReadSingle()); } } else if (chunkType == "SRFS") { Debug.WriteLine(chunkType + ", length " + chunkLength); string stuff = new string(binaryReader.ReadChars(chunkLength)); string[] splitStrings = stuff.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < splitStrings.Length; i++) { model.surfaces.Add(new Surface()); model.surfaces[i].name = splitStrings[i]; } } else if (chunkType == "POLS") { Debug.WriteLine(chunkType + ", length " + chunkLength); long startPoint = fileStream.Position; while (fileStream.Position < startPoint + chunkLength) { Polygon polygon; UInt16 vertCount = binaryReader.ReadUInt16(); polygon.indices = new UInt16[vertCount]; polygon.uv = new Vector2[vertCount]; polygon.uvIndices = new int[vertCount]; for (int i = 0; i < vertCount; i++) { polygon.indices[i] = binaryReader.ReadUInt16(); } polygon.surface = binaryReader.ReadInt16(); model.polygons.Add(polygon); if (polygon.surface < 1) { Debug.WriteLine(" DETAIL POLYGONS FOUND"); } } } else if (chunkType == "SURF") { Debug.WriteLine(chunkType + ", length " + chunkLength); long startPoint = fileStream.Position; List <char> chars = new List <char>(); bool hasFoundEnd = false; while (!hasFoundEnd) { char currentChar = binaryReader.ReadChar(); if (currentChar == '\0') { hasFoundEnd = true; } else { chars.Add(currentChar); } } string surfaceName = new string(chars.ToArray()); Debug.WriteLine(" SURF name: " + surfaceName); // Padding if (surfaceName.Length % 2 == 0) { binaryReader.ReadByte(); } Surface currentSurface = null; foreach (Surface surface in model.surfaces) { if (surface.name == surfaceName) { currentSurface = surface; } } if (currentSurface == null) { Debug.WriteLine(" Couldn't find surface named " + surfaceName); } // now check the sub-chunks while (fileStream.Position < startPoint + chunkLength) { ReadSurfChunk(fileStream, binaryReader, currentSurface); } } else { Debug.WriteLine("Unknown chunk type: " + chunkType + ", length " + chunkLength); fileStream.Seek(chunkLength, SeekOrigin.Current); } }
void ReadSurfChunk(FileStream fileStream, BinaryReader binaryReader, Surface surface) { string chunkType = new string(binaryReader.ReadChars(4)); int chunkLength = (int)binaryReader.ReadUInt16(); if (chunkType == "COLR") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); int r = (int)binaryReader.ReadByte(); int g = (int)binaryReader.ReadByte(); int b = (int)binaryReader.ReadByte(); surface.color = Color.FromArgb(r, g, b); binaryReader.ReadByte(); // usually 00, supposedly unused/unread, but the lightwave 8 exporter seems to do FF instead? whatever } else if (chunkType == "FLAG") { // SURFACE FLAGS Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.surfaceFlags = (SurfaceFlags)binaryReader.ReadUInt16(); Debug.WriteLine(" Surface Flags: "+ surface.surfaceFlags); } else if (chunkType == "LUMI") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.luminosity = binaryReader.ReadUInt16(); Debug.WriteLine(" Luminosity: "+ surface.luminosity); } else if (chunkType == "DIFF") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.diffuse = binaryReader.ReadUInt16(); Debug.WriteLine(" Diffuse: "+ surface.diffuse); } else if (chunkType == "SPEC") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.specularity = binaryReader.ReadUInt16(); Debug.WriteLine(" Specularity: "+ surface.specularity); } else if (chunkType == "GLOS") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.glossiness = binaryReader.ReadUInt16(); Debug.WriteLine(" Glossiness: "+ surface.glossiness); } else if (chunkType == "REFL") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.reflection = binaryReader.ReadUInt16(); Debug.WriteLine(" Reflection: "+ surface.reflection); } else if (chunkType == "TRAN") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); surface.transparency = binaryReader.ReadUInt16(); Debug.WriteLine(" Transparency: "+ surface.transparency); } else if (chunkType == "CTEX" || chunkType == "LTEX" || chunkType == "DTEX" || chunkType == "STEX" || chunkType == "RTEX" || chunkType == "TTEX" || chunkType == "BTEX") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); currentTextureType = chunkType; fileStream.Seek(chunkLength, SeekOrigin.Current); } else if (chunkType == "TIMG") { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); if (currentTextureType != "CTEX") { fileStream.Seek(chunkLength, SeekOrigin.Current); return; } List <char> chars = new List <char>(); bool hasFoundEnd = false; while (!hasFoundEnd) { char currentChar = binaryReader.ReadChar(); if (currentChar == '\0') { hasFoundEnd = true; } else { chars.Add(currentChar); } } string texturePath = new string(chars.ToArray()); // Padding if (texturePath.Length % 2 == 0) { binaryReader.ReadByte(); } Debug.WriteLine(" TIMG path: "+ texturePath); if (texturePath != "(none)") { surface.colorTextureImage = texturePath; } } else if (chunkType == "TFLG") { // TEXTURE FLAGS Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); if (currentTextureType != "CTEX") { fileStream.Seek(chunkLength, SeekOrigin.Current); return; } surface.colorTextureFlags = (TextureFlags)binaryReader.ReadUInt16(); Debug.WriteLine(" Texture Flags: "+ surface.colorTextureFlags); } else if (chunkType == "TSIZ") { // TEXTURE SIZE Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); if (currentTextureType != "CTEX") { fileStream.Seek(chunkLength, SeekOrigin.Current); return; } surface.colorTextureSize = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); Debug.WriteLine(" Texture Size: "+ surface.colorTextureSize); } else if (chunkType == "TCTR") { // TEXTURE CENTER Debug.WriteLine(" "+ chunkType + ", length " + chunkLength); if (currentTextureType != "CTEX") { fileStream.Seek(chunkLength, SeekOrigin.Current); return; } surface.colorTextureCenter = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); Debug.WriteLine(" Texture Center: "+ surface.colorTextureCenter); } else { Debug.WriteLine(" "+ chunkType + ", length " + chunkLength + ", UNHANDLED SURF SUB-CHUNK TYPE"); fileStream.Seek(chunkLength, SeekOrigin.Current); } }