public static OctreeLeaf Read(BinaryReader br, Octree octree) { OctreeLeaf leaf = new OctreeLeaf { FaceData = octree.ReadFaceData((int)br.ReadUInt32()) }; //if ((leaf.FaceData.Length == 12 && leaf.FaceData[1] == 0x0536) || (leaf.FaceData.Length == 8 && leaf.FaceData[1] == 0x054C)) //{ // Logger.LogToFile(Logger.LogLevel.All, string.Join(" ", Array.ConvertAll(leaf.FaceData, x => $"0x{x.ToString("X4")}"))); //} return(leaf); }
public int GetLeafFaceDataLength(OctreeLeaf leaf) { int l = 0; if (leaf.FaceData.Length > 0) { for (l = 0; leaf.FaceData[l] != 0xffff; l++) { } return(l + 1); } else { return(0); } }
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 OctreeLeaf Create(int depth, List <OctreeFace> faces) { OctreeLeaf leaf = new OctreeLeaf(); if (faces.Count > 0) { List <ushort> faceData = new List <ushort>(); int stackSize = faces.Count * 6 + 2; bool notYetFoundAFace = true; ushort modelIndex = 0, lastModelIndex = 0xffff, firstFaceIndex = 0xffff, lastFaceIndex = 0xffff; leaf.NumFaces = 0; for (int i = 0; i < faces.Count; i++) { OctreeFace face = faces[i]; if (face.HitNumber == depth || face.HitNumber < depth) { if (notYetFoundAFace) { faceData.Add(modelIndex); faceData.Add(face.FaceNum); lastModelIndex = 0; firstFaceIndex = face.FaceNum; notYetFoundAFace = false; } else { if (face.FaceNum != lastFaceIndex + 1 || modelIndex != lastModelIndex) { faceData = EncodeRun(faceData, (ushort)(lastFaceIndex - firstFaceIndex)); if (modelIndex != lastModelIndex) { faceData.Add(0xfffe); faceData.Add(modelIndex); lastModelIndex = modelIndex; } faceData.Add(face.FaceNum); firstFaceIndex = face.FaceNum; } } lastFaceIndex = face.FaceNum; leaf.NumFaces++; } } faceData = EncodeRun(faceData, (ushort)(lastFaceIndex - firstFaceIndex)); faceData.Add(0xffff); leaf.FaceData = faceData.ToArray(); } else { leaf.FaceData = new ushort[0]; } //OctreeFace poop = faces.FirstOrDefault(f => f.FaceNum == 8090); //if (poop != null) //{ // Logger.LogToFile(Logger.LogLevel.All, $"{poop.Vertices[0]}\t{poop.Vertices[1]}\t{poop.Vertices[2]}"); // Logger.LogToFile(Logger.LogLevel.All, string.Join(" ", Array.ConvertAll(leaf.FaceData, x => $"0x{x.ToString("X4")}"))); //} return(leaf); }
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); }