예제 #1
0
파일: Octree.cs 프로젝트: q4a/ToxicRagers
        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);
        }
예제 #2
0
파일: Octree.cs 프로젝트: q4a/ToxicRagers
        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);
        }
예제 #3
0
파일: Octree.cs 프로젝트: q4a/ToxicRagers
        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);
        }