public static OctreeNode Read(BinaryReader br, Octree octree) { OctreeNode node = new OctreeNode(); int childMask; int nodeMask; int iNode; childMask = br.ReadByte(); node.ChildType = br.ReadByte(); node.Flags = (SplitFlags)br.ReadByte(); for (iNode = 0, nodeMask = 1; iNode < 8; iNode++, nodeMask <<= 1) { if ((childMask & nodeMask) > 0) { if ((node.ChildType & nodeMask) > 0) { node.Children[iNode] = OctreeLeaf.Read(br, octree); } else { node.Children[iNode] = Read(br, octree); } } else { if ((((iNode & 1) == 0) || node.Flags.HasFlag(SplitFlags.SplitInX)) && (((iNode & 2) == 0) || node.Flags.HasFlag(SplitFlags.SplitInY)) && (((iNode & 4) == 0) || node.Flags.HasFlag(SplitFlags.SplitInZ))) { node.Children[iNode] = new OctreeLeaf(0, 0); node.ChildType |= nodeMask; } } } return(node); }
public static Octree ReadFromMemory(BinaryReader br) { Octree octree = new Octree { version = (int)br.ReadUInt32(), numModels = (int)br.ReadUInt32(), pathLength = br.ReadByte(), // what on earth is path length? hasMatrix = br.ReadBoolean() }; if (octree.hasMatrix) { // load M34 return(null); } octree.bounds.Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); octree.bounds.Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); int faceDataLength = (int)br.ReadUInt32(); octree.faceData = new ushort[faceDataLength]; for (int i = 0; i < faceDataLength; i++) { octree.faceData[i] = br.ReadUInt16(); } octree.root = OctreeNode.Read(br, octree); Console.WriteLine($"{octree.GetNodeFaceDataLength(octree.root)} :: {octree.faceData.Length}"); br.ReadUInt32(); // checksum return(octree); }
public static OctreeChild Create(BoundingBox bounds, List <OctreeFace> faces, int depth = -1) { depth++; OctreeChild node = new OctreeChild(); Vector3 centre = (bounds.Min + bounds.Max) * 0.5f; BoundingBox childBounds = new BoundingBox(); SplitFlags splitFlags = 0; if (depth > Octree.MaxDepth || (depth > 0 && faces.Count < Octree.MaxFacesPerLeaf)) { splitFlags = 0; if (faces.Count > Octree.MaxFacesPerLeaf / 8) { if (bounds.Max.X - bounds.Min.X > 100.0f) { splitFlags |= SplitFlags.SplitInX; } if (bounds.Max.Z - bounds.Min.Z > 100.0f) { splitFlags |= SplitFlags.SplitInZ; } } if (splitFlags == 0) { node = OctreeLeaf.Create(depth, faces); depth--; return(node); } } else { DetermineSplittage(depth, faces, centre, ref splitFlags); } if (depth > 0 && splitFlags == 0) { node = OctreeLeaf.Create(depth, faces); depth--; return(node); } //numNodes++; node = new OctreeNode { ChildType = 0, Flags = splitFlags }; for (int i = 0; i < (node as OctreeNode).Children.Length; i++) { if (node.Flags.HasFlag(SplitFlags.SplitInX)) { if ((i & 1) == 1) { childBounds.Min.X = centre.X; childBounds.Max.X = bounds.Max.X; } else { childBounds.Min.X = bounds.Min.X; childBounds.Max.X = centre.X; } } else { if ((i & 1) == 1) { continue; } else { childBounds.Min.X = bounds.Min.X; childBounds.Max.X = bounds.Max.X; } } if (node.Flags.HasFlag(SplitFlags.SplitInY)) { if ((i & 2) == 2) { childBounds.Min.Y = centre.Y; childBounds.Max.Y = bounds.Max.Y; } else { childBounds.Min.Y = bounds.Min.Y; childBounds.Max.Y = centre.Y; } } else { if ((i & 2) == 2) { continue; } else { childBounds.Min.Y = bounds.Min.Y; childBounds.Max.Y = bounds.Max.Y; } } if (node.Flags.HasFlag(SplitFlags.SplitInZ)) { if ((i & 4) == 4) { childBounds.Min.Z = centre.Z; childBounds.Max.Z = bounds.Max.Z; } else { childBounds.Min.Z = bounds.Min.Z; childBounds.Max.Z = centre.Z; } } else { if ((i & 4) == 4) { continue; } else { childBounds.Min.Z = bounds.Min.Z; childBounds.Max.Z = bounds.Max.Z; } } //Logger.LogToFile(Logger.LogLevel.All, $"{depth}\t{i}\t{childBounds.Min}\t{childBounds.Max}"); List <OctreeFace> childFaces = Octree.FindFacesFromList(faces, childBounds); (node as OctreeNode).Children[i] = Create(childBounds, childFaces, depth); } depth--; return(node); }