public static PolygonSoupChunk Read(BinaryReader br) { PolygonSoupChunk result = new PolygonSoupChunk(); result.Position = br.ReadVector3I(); result.Scale = br.ReadSingle(); uint propertyListStart = br.ReadUInt32(); uint pointListStart = br.ReadUInt32(); br.ReadInt16(); // Length byte propertyListCount = br.ReadByte(); result.QuadCount = br.ReadByte(); int pointCount = br.ReadByte(); result.Unknown10 = br.ReadByte(); result.Unknown11 = br.ReadInt16(); br.BaseStream.Position = pointListStart; for (int i = 0; i < pointCount; i++) { result.PointList.Add(br.ReadVector3S()); } br.BaseStream.Position = propertyListStart; for (int i = 0; i < propertyListCount; i++) { result.PropertyList.Add(PolygonSoupProperty.Read(br)); } return(result); }
public bool Read(BundleEntry entry, ILoader loader = null) { Clear(); MemoryStream ms = entry.MakeStream(); BinaryReader2 br = new BinaryReader2(ms); br.BigEndian = entry.Console; Min = br.ReadVector3F(); Unknown4 = br.ReadInt32(); Max = br.ReadVector3F(); Unknown8 = br.ReadInt32(); uint chunkPointerStart = br.ReadUInt32(); uint boxListStart = br.ReadUInt32(); int chunkCount = br.ReadInt32(); br.ReadUInt32(); // FileSize List <uint> chunkPointers = new List <uint>(); // No Data if (chunkCount == 0) { br.Close(); ms.Close(); return(true); } br.BaseStream.Position = chunkPointerStart; for (int i = 0; i < chunkCount; i++) { chunkPointers.Add(br.ReadUInt32()); } for (int i = 0; i < chunkCount; i++) { // Read Vertically long pos = boxListStart + 0x70 * (i / 4) + 4 * (i % 4); BoxF boundingBox = new BoxF(); br.BaseStream.Position = pos; float minX = br.ReadSingle(); br.BaseStream.Position += 12; float minY = br.ReadSingle(); br.BaseStream.Position += 12; float minZ = br.ReadSingle(); boundingBox.Min = new Vector3(minX, minY, minZ); br.BaseStream.Position += 12; float maxX = br.ReadSingle(); br.BaseStream.Position += 12; float maxY = br.ReadSingle(); br.BaseStream.Position += 12; float maxZ = br.ReadSingle(); br.BaseStream.Position += 12; boundingBox.Max = new Vector3(maxX, maxY, maxZ); PolygonSoupBoundingBox box = new PolygonSoupBoundingBox(boundingBox, br.ReadInt32()); BoundingBoxes.Add(box); } for (int i = 0; i < chunkPointers.Count; i++) { br.BaseStream.Position = chunkPointers[i]; Chunks.Add(PolygonSoupChunk.Read(br)); } br.Close(); ms.Close(); return(true); }
public void ImportObj(string path) { GenericModel model = OBJImporter.ImportOBJ(path); model.SplitByPointCount(255); // Verify data before applying foreach (GenericMesh mesh in model.Meshes) { // Get highest point uint pointCount = 0; foreach (uint key in mesh.Vertices.Keys) { if (pointCount < key) { pointCount = key; } } pointCount++; // Is it too big for a byte? if (pointCount > 256) { throw new ReadFailedError("Too many points for mesh: " + mesh.Name + ", " + pointCount + " > 256"); } foreach (Face face in mesh.Faces) { // Triangulation required for now. if (face.Indices.Count > 3) { throw new ReadFailedError("Please triangulate your mesh: " + mesh.Name); } // Material names are required if (string.IsNullOrEmpty(face.Material?.Name)) { throw new ReadFailedError("Invalid Material for mesh: " + mesh.Name); } // Verify that all data is there string[] split = face.Material.Name.Split('_'); if (split.Length < 7) { throw new ReadFailedError("Invalid Material Data: " + face.Material.Name + ", for mesh: " + mesh.Name); } // Verify that all data can be parsed try { Utilities.Parse(split[1], true, out ushort _); Utilities.Parse(split[2], true, out ushort _); Utilities.Parse(split[3], true, out byte _); Utilities.Parse(split[4], true, out byte _); Utilities.Parse(split[5], true, out byte _); Utilities.Parse(split[6], true, out byte _); } catch (NotSupportedException) { throw new ReadFailedError("Unable to Parse Material Data: " + face.Material.Name + ", for mesh: " + mesh.Name); } } } // Clear existing data Chunks.Clear(); BoundingBoxes.Clear(); // Global vertices list to calculate the bounding box List <Vector3> vertices = new List <Vector3>(); // Generate PolygonSoupChunks and BoundingBoxes foreach (GenericMesh mesh in model.Meshes) { PolygonSoupChunk chunk = new PolygonSoupChunk(); foreach (Face face in mesh.Faces) { PolygonSoupProperty property = new PolygonSoupProperty(); // Set Indices property.Indices[0] = (byte)face.Indices[0]; property.Indices[1] = (byte)face.Indices[1]; property.Indices[2] = (byte)face.Indices[2]; if (face.Indices.Count > 3) { property.Indices[3] = (byte)face.Indices[3]; } else { property.Indices[3] = 0xFF; } // Get data from material name string materialName = face.Material.Name; string[] split = materialName.Split('_'); // Parse the values Utilities.Parse(split[1], true, out ushort unknownProperty1); Utilities.Parse(split[2], true, out ushort unknownProperty2); Utilities.Parse(split[3], true, out byte unknownByte1); Utilities.Parse(split[4], true, out byte unknownByte2); Utilities.Parse(split[5], true, out byte unknownByte3); Utilities.Parse(split[6], true, out byte unknownByte4); // Combine unknownProperty1 and unknownProperty2 property.UnknownProperty = (uint)((unknownProperty2 << 16) | unknownProperty1); // Set unknown bytes property.UnknownBytes[0] = unknownByte1; property.UnknownBytes[1] = unknownByte2; property.UnknownBytes[2] = unknownByte3; property.UnknownBytes[3] = unknownByte4; // Add the property chunk.PropertyList.Add(property); } // Add the vertices to the global vertices list vertices.AddRange(mesh.Vertices.Values.ToArray()); // Get the minimum and maximum point of the mesh Vector3 min = MathUtils.MinBounds(mesh.Vertices.Values.ToArray()); Vector3 max = MathUtils.MaxBounds(mesh.Vertices.Values.ToArray()); // Use the minimum as the position Vector3 position = min; // Set the scale to something standard float scale = 0.015f; // Get the point count uint pointCount = 0; foreach (uint key in mesh.Vertices.Keys) { if (pointCount < key) { pointCount = key; } } pointCount++; Vector3S[] verts = new Vector3S[pointCount]; foreach (uint key in mesh.Vertices.Keys) { // Convert the point to a short and apply position and scale verts[key] = new Vector3S((mesh.Vertices[key] - position) / scale); } chunk.PointList = verts.ToList(); // Quads are currently unsupported chunk.QuadCount = 0; chunk.Scale = scale; // Set the position and apply scale chunk.Position = new Vector3I(position / scale); // Add the chunk Chunks.Add(chunk); // Add the bounding box BoundingBoxes.Add(new PolygonSoupBoundingBox(new BoxF(min, max), -1)); } // Calculate Bounding Box Min = MathUtils.MinBounds(vertices.ToArray()); Max = MathUtils.MaxBounds(vertices.ToArray()); }