internal void SplitNode(IBVHNodeAdapter <T> nAda)
        {
            // second, decide which axis to split on, and sort..
            List <T> splitlist = GObjects;

            splitlist.ForEach(o => nAda.UnmapObject(o));
            int center = (int)(splitlist.Count / 2);             // find the center object

            SplitAxisOpt <T> bestSplit = EachAxis.Min((axis) =>
            {
                var orderedlist = new List <T>(splitlist);
                switch (axis)
                {
                case Axis.X:
                    orderedlist.Sort(delegate(T go1, T go2) { return(nAda.GetObjectPos(go1).x.CompareTo(nAda.GetObjectPos(go2).x)); });
                    break;

                case Axis.Y:
                    orderedlist.Sort(delegate(T go1, T go2) { return(nAda.GetObjectPos(go1).y.CompareTo(nAda.GetObjectPos(go2).y)); });
                    break;

                case Axis.Z:
                    orderedlist.Sort(delegate(T go1, T go2) { return(nAda.GetObjectPos(go1).z.CompareTo(nAda.GetObjectPos(go2).z)); });
                    break;

                default:
                    throw new NotImplementedException("unknown split axis: " + axis.ToString());
                }

                var left_s  = orderedlist.GetRange(0, center);
                var right_s = orderedlist.GetRange(center, splitlist.Count - center);

                float SAH = SAofList(nAda, left_s) * left_s.Count + SAofList(nAda, right_s) * right_s.Count;
                return(new SplitAxisOpt <T>(SAH, axis, left_s, right_s));
            });

            // perform the split
            GObjects   = null;
            this.Left  = new BVHNode <T>(nAda.BVH, this, bestSplit.left, bestSplit.axis, this.Depth + 1);           // Split the Hierarchy to the left
            this.Right = new BVHNode <T>(nAda.BVH, this, bestSplit.right, bestSplit.axis, this.Depth + 1);          // Split the Hierarchy to the right
        }
        internal void Remove(IBVHNodeAdapter <T> nAda, T newOb)
        {
            if (GObjects == null)
            {
                throw new Exception("removeObject() called on nonLeaf!");
            }

            nAda.UnmapObject(newOb);
            GObjects.Remove(newOb);
            if (GObjects.Count > 0)
            {
                RefitVolume(nAda);
            }
            else
            {
                // our leaf is empty, so collapse it if we are not the root...
                if (Parent != null)
                {
                    GObjects = null;
                    Parent.RemoveLeaf(nAda, this);
                    Parent = null;
                }
            }
        }