/// <summary> /// Read mesh data to record array. /// </summary> /// <param name="record">Destination record index.</param> private bool ReadMesh(int record) { // Create empty mesh records[record].PureMesh = new PureMesh(); // Create plane array int faceCount = records[record].Header.PlaneCount; records[record].PureMesh.Planes = new PurePlane[faceCount]; // Get reader for normal data long normalPosition = records[record].Header.NormalListOffset; BinaryReader normalReader = records[record].MemoryFile.GetReader(normalPosition); // Read native data into plane array int uniqueTextureCount = 0; MeshVersions version = records[record].Version; long position = records[record].Header.PlaneListOffset; BinaryReader reader = records[record].MemoryFile.GetReader(position); BinaryReader pointReader = records[record].MemoryFile.GetReader(); BinaryReader planeDataReader = records[record].MemoryFile.GetReader(); int minX = 0, maxX = 0, minY = 0, maxY = 0, minZ = 0, maxZ = 0; for (int plane = 0; plane < faceCount; plane++) { // Read plane header records[record].PureMesh.Planes[plane].Header.Position = reader.BaseStream.Position; records[record].PureMesh.Planes[plane].Header.PlanePointCount = reader.ReadByte(); records[record].PureMesh.Planes[plane].Header.Unknown1 = reader.ReadByte(); records[record].PureMesh.Planes[plane].Header.Texture = reader.ReadUInt16(); records[record].PureMesh.Planes[plane].Header.UVunpack = reader.ReadInt32(); // Read the normal data for this plane Int32 nx = normalReader.ReadInt32(); Int32 ny = normalReader.ReadInt32(); Int32 nz = normalReader.ReadInt32(); // Build list of unique textures across all planes - this will be used later to create submesh buffers UInt16 textureBitfield = records[record].PureMesh.Planes[plane].Header.Texture; int textureArchive = textureBitfield >> 7; int textureRecord = textureBitfield & 0x7f; bool foundTexture = false; for (int i = 0; i < uniqueTextureCount; i++) { if (uniqueTextureBuffer[i].Archive == textureArchive && uniqueTextureBuffer[i].Record == textureRecord) { foundTexture = true; break; } } if (!foundTexture) { uniqueTextureBuffer[uniqueTextureCount].Archive = textureArchive; uniqueTextureBuffer[uniqueTextureCount].Record = textureRecord; uniqueTextureCount++; } // Store texture index for this plane records[record].PureMesh.Planes[plane].TextureIndex.Archive = textureArchive; records[record].PureMesh.Planes[plane].TextureIndex.Record = textureRecord; // Read plane points int pointCount = records[record].PureMesh.Planes[plane].Header.PlanePointCount; records[record].PureMesh.Planes[plane].Points = new FaceUVTool.DFPurePoint[pointCount]; for (int point = 0; point < pointCount; point++) { // Read offset int pointOffset = reader.ReadInt32(); // Read UV data int u = reader.ReadInt16(); int v = reader.ReadInt16(); // Fix some UV coordinates (process only the first 3 points as // coordinates from point 4 and above are ignored) if (point < 3) { // Fix incorrect coordinates FixBadUVCoordinates(record, plane, point, ref u, ref v); // Fix coordinates which require specific unpacking if (records[record].PureMesh.Planes[plane].Header.UVunpack == 0) { UVunpack(ref u); UVunpack(ref v); } } // Store UV coordinates records[record].PureMesh.Planes[plane].Points[point].u = u; records[record].PureMesh.Planes[plane].Points[point].v = v; // Get point position long pointPosition = records[record].Header.PointListOffset; switch (version) { case MeshVersions.Version27: case MeshVersions.Version26: pointPosition += pointOffset; break; case MeshVersions.Version25: pointPosition += (pointOffset * 3); break; } // Read native point values pointReader.BaseStream.Position = pointPosition; int x = pointReader.ReadInt32(); int y = pointReader.ReadInt32(); int z = pointReader.ReadInt32(); // Find min/max values of native points so far // This can be used to construct a tight box around mesh if (x < minX) { minX = x; } if (x > maxX) { maxX = x; } if (y < minY) { minY = y; } if (y > maxY) { maxY = y; } if (z < minZ) { minZ = z; } if (z > maxZ) { maxZ = z; } // Store native point values records[record].PureMesh.Planes[plane].Points[point].x = x; records[record].PureMesh.Planes[plane].Points[point].y = y; records[record].PureMesh.Planes[plane].Points[point].z = z; // Store native normal values for each vertex records[record].PureMesh.Planes[plane].Points[point].nx = nx; records[record].PureMesh.Planes[plane].Points[point].ny = ny; records[record].PureMesh.Planes[plane].Points[point].nz = nz; } // Read unknown plane data planeDataReader.BaseStream.Position = records[record].Header.PlaneDataOffset + plane * 24; records[record].PureMesh.Planes[plane].PlaneData = planeDataReader.ReadBytes(24); // Store size of mesh DFMesh.DFPoint size = new DFMesh.DFPoint(); size.X = (maxX / pointDivisor - minX / pointDivisor); size.Y = (maxY / pointDivisor - minY / pointDivisor); size.Z = (maxZ / pointDivisor - minZ / pointDivisor); records[record].PureMesh.Size = size; // Store centre of mesh DFMesh.DFPoint centre = new DFMesh.DFPoint(); centre.X = size.X / 2; centre.Y = size.Y / 2; centre.Z = size.Z / 2; records[record].PureMesh.Centre = centre; } //// Read unknown object data, but ignore known non-conforming objects //if (records[record].Header.ObjectDataCount > 0 && // records[record].ObjectId != 4722 && // records[record].ObjectId != 7614) //{ // // Create object data record array // records[record].ObjectDataRecords = new ObjectDataRecord[records[record].Header.ObjectDataCount]; // // Start reading // reader.BaseStream.Position = records[record].Header.ObjectDataOffset; // for (int i = 0; i < records[record].Header.ObjectDataCount; i++) // { // // Read object data record header // records[record].ObjectDataRecords[i].Header.N1 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N2 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N3 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N4 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.SubRecordCount = reader.ReadInt16(); // // Read unknown sub-records // records[record].ObjectDataRecords[i].SubRecords = new ObjectDataSubRecord[records[record].ObjectDataRecords[i].Header.SubRecordCount]; // for (int j = 0; j < records[record].ObjectDataRecords[i].Header.SubRecordCount; j++) // { // records[record].ObjectDataRecords[i].SubRecords[j].Unknown1 = reader.ReadBytes(6); // } // } //} // Copy valid part of unique texture list into pureMesh data and create plane buffer for decomposition records[record].PureMesh.UniqueTextures = new TextureIndex[uniqueTextureCount]; for (int i = 0; i < uniqueTextureCount; i++) { records[record].PureMesh.UniqueTextures[i] = uniqueTextureBuffer[i]; subMeshBuffer[i].TextureArchive = uniqueTextureBuffer[i].Archive; subMeshBuffer[i].TextureRecord = uniqueTextureBuffer[i].Record; subMeshBuffer[i].planeCount = 0; subMeshBuffer[i].PlaneBuffer = new DFPlaneBuffer[planeBufferLength]; } return(true); }
/// <summary> /// Read mesh data to record array. /// </summary> /// <param name="record">Destination record index.</param> private bool ReadMesh(int record) { // Create empty mesh records[record].PureMesh = new PureMesh(); // Create plane array int faceCount = records[record].Header.PlaneCount; records[record].PureMesh.Planes = new PurePlane[faceCount]; // Get reader for normal data long normalPosition = records[record].Header.NormalListOffset; BinaryReader normalReader = records[record].MemoryFile.GetReader(normalPosition); // Read native data into plane array int uniqueTextureCount = 0; MeshVersions version = records[record].Version; long position = records[record].Header.PlaneListOffset; BinaryReader reader = records[record].MemoryFile.GetReader(position); BinaryReader pointReader = records[record].MemoryFile.GetReader(); BinaryReader planeDataReader = records[record].MemoryFile.GetReader(); for (int plane = 0; plane < faceCount; plane++) { // Read plane header records[record].PureMesh.Planes[plane].Header.Position = reader.BaseStream.Position; records[record].PureMesh.Planes[plane].Header.PlanePointCount = reader.ReadByte(); records[record].PureMesh.Planes[plane].Header.Unknown1 = reader.ReadByte(); records[record].PureMesh.Planes[plane].Header.Texture = reader.ReadUInt16(); records[record].PureMesh.Planes[plane].Header.Unknown2 = reader.ReadUInt32(); // Read the normal data for this plane Int32 nx = normalReader.ReadInt32(); Int32 ny = normalReader.ReadInt32(); Int32 nz = normalReader.ReadInt32(); // Build list of unique textures across all planes - this will be used later to create submesh buffers UInt16 textureBitfield = records[record].PureMesh.Planes[plane].Header.Texture; int textureArchive = textureBitfield >> 7; int textureRecord = textureBitfield & 0x7f; bool foundTexture = false; for (int i = 0; i < uniqueTextureCount; i++) { if (uniqueTextureBuffer[i].Archive == textureArchive && uniqueTextureBuffer[i].Record == textureRecord) { foundTexture = true; break; } } if (!foundTexture) { uniqueTextureBuffer[uniqueTextureCount].Archive = textureArchive; uniqueTextureBuffer[uniqueTextureCount].Record = textureRecord; uniqueTextureCount++; } // Store texture index for this plane records[record].PureMesh.Planes[plane].TextureIndex.Archive = textureArchive; records[record].PureMesh.Planes[plane].TextureIndex.Record = textureRecord; // Read plane points int pointCount = records[record].PureMesh.Planes[plane].Header.PlanePointCount; records[record].PureMesh.Planes[plane].Points = new FaceUVTool.DFPurePoint[pointCount]; for (int point = 0; point < pointCount; point++) { // Read offset int pointOffset = reader.ReadInt32(); // Read UV data Int16 u = reader.ReadInt16(); Int16 v = reader.ReadInt16(); // Fix certain UV coordinates that are // packed oddly, or aligned outside of poly. int threshold = 14335; while (u > threshold) { u = (Int16)(0x4000 - u); } while (u < -threshold) { u = (Int16)(0x4000 + u); } while (v > threshold) { v = (Int16)(0x4000 - v); } while (v < -threshold) { v = (Int16)(0x4000 + v); } // Store UV coordinates records[record].PureMesh.Planes[plane].Points[point].u = u; records[record].PureMesh.Planes[plane].Points[point].v = v; // Get point position long pointPosition = records[record].Header.PointListOffset; switch (version) { case MeshVersions.Version27: case MeshVersions.Version26: pointPosition += pointOffset; break; case MeshVersions.Version25: pointPosition += (pointOffset * 3); break; } // Store native point values pointReader.BaseStream.Position = pointPosition; records[record].PureMesh.Planes[plane].Points[point].x = pointReader.ReadInt32(); records[record].PureMesh.Planes[plane].Points[point].y = pointReader.ReadInt32(); records[record].PureMesh.Planes[plane].Points[point].z = pointReader.ReadInt32(); // Store native normal values for each vertex records[record].PureMesh.Planes[plane].Points[point].nx = nx; records[record].PureMesh.Planes[plane].Points[point].ny = ny; records[record].PureMesh.Planes[plane].Points[point].nz = nz; } // Read unknown plane data planeDataReader.BaseStream.Position = records[record].Header.PlaneDataOffset + plane * 24; records[record].PureMesh.Planes[plane].PlaneData = planeDataReader.ReadBytes(24); } //// Read unknown object data, but ignore known non-conforming objects //if (records[record].Header.ObjectDataCount > 0 && // records[record].ObjectId != 4722 && // records[record].ObjectId != 7614) //{ // // Create object data record array // records[record].ObjectDataRecords = new ObjectDataRecord[records[record].Header.ObjectDataCount]; // // Start reading // reader.BaseStream.Position = records[record].Header.ObjectDataOffset; // for (int i = 0; i < records[record].Header.ObjectDataCount; i++) // { // // Read object data record header // records[record].ObjectDataRecords[i].Header.N1 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N2 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N3 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.N4 = reader.ReadInt32(); // records[record].ObjectDataRecords[i].Header.SubRecordCount = reader.ReadInt16(); // // Read unknown sub-records // records[record].ObjectDataRecords[i].SubRecords = new ObjectDataSubRecord[records[record].ObjectDataRecords[i].Header.SubRecordCount]; // for (int j = 0; j < records[record].ObjectDataRecords[i].Header.SubRecordCount; j++) // { // records[record].ObjectDataRecords[i].SubRecords[j].Unknown1 = reader.ReadBytes(6); // } // } //} // Copy valid part of unique texture list into pureMesh data and create plane buffer for decomposition records[record].PureMesh.UniqueTextures = new TextureIndex[uniqueTextureCount]; for (int i = 0; i < uniqueTextureCount; i++) { records[record].PureMesh.UniqueTextures[i] = uniqueTextureBuffer[i]; subMeshBuffer[i].TextureArchive = uniqueTextureBuffer[i].Archive; subMeshBuffer[i].TextureRecord = uniqueTextureBuffer[i].Record; subMeshBuffer[i].planeCount = 0; subMeshBuffer[i].PlaneBuffer = new DFPlaneBuffer[planeBufferLength]; } return(true); }
/// <summary> /// Read mesh data to record array. /// </summary> /// <param name="Record">Destination record index.</param> private bool ReadMesh(int Record) { // Create empty mesh Records[Record].PureMesh = new PureMesh(); // Create plane array int faceCount = Records[Record].Header.PlaneCount; Records[Record].PureMesh.Planes = new PurePlane[faceCount]; // Get reader for normal data long normalPosition = Records[Record].Header.NormalListOffset; BinaryReader normalReader = Records[Record].MemoryFile.GetReader(normalPosition); // Read native data into plane array int uniqueTextureCount = 0; MeshVersions version = Records[Record].Version; long position = Records[Record].Header.PlaneListOffset; BinaryReader reader = Records[Record].MemoryFile.GetReader(position); BinaryReader pointReader = Records[Record].MemoryFile.GetReader(); BinaryReader planeDataReader = Records[Record].MemoryFile.GetReader(); for (int plane = 0; plane < faceCount; plane++) { // Read plane header Records[Record].PureMesh.Planes[plane].Header.Position = reader.BaseStream.Position; Records[Record].PureMesh.Planes[plane].Header.PlanePointCount = reader.ReadByte(); Records[Record].PureMesh.Planes[plane].Header.Unknown1 = reader.ReadByte(); Records[Record].PureMesh.Planes[plane].Header.Texture = reader.ReadUInt16(); Records[Record].PureMesh.Planes[plane].Header.Unknown2 = reader.ReadUInt32(); // Read the normal data for this plane Int32 nx = normalReader.ReadInt32(); Int32 ny = normalReader.ReadInt32(); Int32 nz = normalReader.ReadInt32(); // Build list of unique textures across all planes - this will be used later to create submesh buffers UInt16 textureBitfield = Records[Record].PureMesh.Planes[plane].Header.Texture; int textureArchive = textureBitfield >> 7; int textureRecord = textureBitfield & 0x7f; bool foundTexture = false; for (int i = 0; i < uniqueTextureCount; i++) { if (UniqueTextureBuffer[i].Archive == textureArchive && UniqueTextureBuffer[i].Record == textureRecord) { foundTexture = true; break; } } if (!foundTexture) { UniqueTextureBuffer[uniqueTextureCount].Archive = textureArchive; UniqueTextureBuffer[uniqueTextureCount].Record = textureRecord; uniqueTextureCount++; } // Store texture index for this plane Records[Record].PureMesh.Planes[plane].TextureIndex.Archive = textureArchive; Records[Record].PureMesh.Planes[plane].TextureIndex.Record = textureRecord; // Read plane points int pointCount = Records[Record].PureMesh.Planes[plane].Header.PlanePointCount; Records[Record].PureMesh.Planes[plane].Points = new FaceUVTool.DFPurePoint[pointCount]; for (int point = 0; point < pointCount; point++) { // Read offset int pointOffset = reader.ReadInt32(); // Read UV data Int16 u = reader.ReadInt16(); Int16 v = reader.ReadInt16(); // Fix certain UV coordinates that are // packed oddly, or aligned outside of poly. int threshold = 15000; while (u > threshold) { u = (Int16)(0x4000 - u); } while (u < -threshold) { u = (Int16)(0x4000 + u); } while (v > threshold) { v = (Int16)(0x4000 - v); } while (v < -threshold) { v = (Int16)(0x4000 + v); } // Store UV coordinates Records[Record].PureMesh.Planes[plane].Points[point].u = u; Records[Record].PureMesh.Planes[plane].Points[point].v = v; // Get point position long pointPosition = Records[Record].Header.PointListOffset; switch (version) { case MeshVersions.Version27: case MeshVersions.Version26: pointPosition += pointOffset; break; case MeshVersions.Version25: pointPosition += (pointOffset * 3); break; } // Store native point values pointReader.BaseStream.Position = pointPosition; Records[Record].PureMesh.Planes[plane].Points[point].x = pointReader.ReadInt32(); Records[Record].PureMesh.Planes[plane].Points[point].y = pointReader.ReadInt32(); Records[Record].PureMesh.Planes[plane].Points[point].z = pointReader.ReadInt32(); // Store native normal values for each vertex Records[Record].PureMesh.Planes[plane].Points[point].nx = nx; Records[Record].PureMesh.Planes[plane].Points[point].ny = ny; Records[Record].PureMesh.Planes[plane].Points[point].nz = nz; } // Read unknown plane data planeDataReader.BaseStream.Position = Records[Record].Header.PlaneDataOffset + plane * 24; Records[Record].PureMesh.Planes[plane].PlaneData = planeDataReader.ReadBytes(24); } // CURRENTLY UNUSED - Read start of object data //if (records[record].header.objectDataCount > 0) //{ // // Read first object data record only (format is not yet known enough to enumerate) // // This data is only loaded temporarily to look at for now // reader.BaseStream.Position = records[record].header.objectDataOffset; // // Read number array // objectDataHeader dataHeader = new objectDataHeader(); // dataHeader.numbers = new Int32[4]; // for (int i = 0; i < 4; i++) // { // dataHeader.numbers[i] = reader.ReadInt32(); // } // // Read sub-record count // dataHeader.subrecordCount = reader.ReadInt16(); //} // Copy valid part of unique texture list into pureMesh data and create plane buffer for decomposition Records[Record].PureMesh.UniqueTextures = new TextureIndex[uniqueTextureCount]; for (int i = 0; i < uniqueTextureCount; i++) { Records[Record].PureMesh.UniqueTextures[i] = UniqueTextureBuffer[i]; SubMeshBuffer[i].TextureArchive = UniqueTextureBuffer[i].Archive; SubMeshBuffer[i].TextureRecord = UniqueTextureBuffer[i].Record; SubMeshBuffer[i].planeCount = 0; SubMeshBuffer[i].PlaneBuffer = new DFPlaneBuffer[PlaneBufferLength]; } return(true); }