Пример #1
0
        public void Construct(Aggregate aggregate)
        {
            Material = ((IIntersectable)aggregate).Material;
            Aggregate objects = new IntersectableList();

            foreach (IIntersectable intersectable in aggregate.GetObjects())
            {
                objects.Add(intersectable);
            }

            BoundingBox = ((IIntersectable)aggregate).BoundingBox;
            //Calculate max treed depth = 8+1.3*log(n);
            maxTreeDepth = (int)Math.Ceiling(8 + (1.3 * Math.Log(objects.Intersectables.Count)));

            RootNode = new BspNode();

            //Kick off the recursive tree construction
            RootNode.BuildSubTree(objects, BoundingBox, maxTreeDepth, 0);
        }
Пример #2
0
        public HitRecord Intersect(Ray ray)
        {
            #region BSP Tree Traversal
            BspNode              node = RootNode;
            HitRecord            hit = null;
            Stack <BspStackItem> nodeStack = new Stack <BspStackItem>();
            BspNode              first, second;

            float[] boxIntersections = node.BoundingBox.Intersect(ray);
            if (boxIntersections == null)
            {
                return(null);
            }
            float tmin = boxIntersections[0];
            float tmax = boxIntersections[1];

            float isect = float.MaxValue;

            while (node != null)
            {
                if (isect < tmin)
                {
                    return(hit);
                }
                if (!node.IsLeaf)
                {
                    //process interior node
                    //tsplit = compute ray-split plane intersection
                    //<order of children>
                    //<process of children>

                    float tSplit = node.DistanceToSplitPlane(ray);
                    //Order children
                    if (ray.Origin[node.Axis] < node.PlanePos)
                    {
                        first  = node.RightNode;
                        second = node.LeftNode;
                    }
                    else
                    {
                        first  = node.LeftNode;
                        second = node.RightNode;
                    }
                    //Process children
                    if (tSplit < 0 || tSplit > tmax || (tSplit == 0.0f && ray.Direction[node.Axis] > 0))
                    {
                        node = first;
                    }
                    else if (tSplit < tmin || (tSplit == 0.0f && ray.Direction[node.Axis] < 0))
                    {
                        node = second;
                    }
                    else
                    {
                        node = first;
                        BspStackItem item = new BspStackItem(second, tSplit, tmax);
                        nodeStack.Push(item);
                        tmax = tSplit;
                    }
                }
                else
                {
                    //Intersection = first intersection in leaf
                    HitRecord tmpHitRecord = node.Intersectables.Intersect(ray);;

                    if (tmpHitRecord != null)
                    {
                        isect = tmpHitRecord.Distance;
                        hit   = tmpHitRecord;
                    }

                    if (nodeStack.Count > 0)
                    {
                        BspStackItem sItem = nodeStack.Pop();
                        node = sItem.Node;
                        tmin = sItem.Tmin;
                        tmax = sItem.Tmax;
                    }
                    else
                    {
                        node = null;
                    }
                }
            }

            return(hit);

            #endregion
            #region simple tree traversal

            /**
             * Traverse the tree and do intersection
             */
            /*Stack<BspNode> nodesToVisit = new Stack<BspNode>();
             * nodesToVisit.Push(RootNode);
             * HitRecord hit = null;
             * HitRecord tempHit;
             * while (nodesToVisit.Count > 0)
             * {
             *  BspNode currentNode = nodesToVisit.Pop();
             *  if (currentNode.IsLeaf)
             *  {
             *      foreach (IIntersectable intersectable in currentNode.Intersectables)
             *      {
             *          tempHit = intersectable.Intersect(ray);
             *          if (tempHit != null)
             *          {
             *              if (hit == null) hit = tempHit;
             *              else if (tempHit.Distance < hit.Distance) hit = tempHit;
             *          }
             *      }
             *  }
             *  else
             *  {
             *      nodesToVisit.Push(currentNode.LeftNode);
             *      nodesToVisit.Push(currentNode.RightNode);
             *  }
             * }
             * return hit;*/
            #endregion
        }
Пример #3
0
 public BspStackItem(BspNode node, float tmin, float tmax)
 {
     Node = node;
     Tmin = tmin;
     Tmax = tmax;
 }
Пример #4
0
        public void BuildSubTree(Aggregate intersectables, IBoundingBox boundingBox, int maxTreeDepth, int currentTreeDetph)
        {
            Intersectables = intersectables;
            BoundingBox    = boundingBox;

            if (Intersectables.GetNumberOfComponents() <= 5 || currentTreeDetph == maxTreeDepth)
            {
                IsLeaf = true;
            }
            else
            {
                Aggregate leftIntersectables  = new IntersectableList();
                Aggregate rightIntersectables = new IntersectableList();
                //Find the maximal Axis
                Axis = 0;

                float max = BoundingBox.Dimension.X;
                if (BoundingBox.Dimension.Y > max)
                {
                    Axis = 1;
                }
                if (BoundingBox.Dimension.Z > max)
                {
                    Axis = 2;
                }

                //Axis = currentTreeDetph % 3;
                PlanePos = BoundingBox.MaxVector[Axis] - (BoundingBox.MaxVector[Axis] - BoundingBox.MinVector[Axis]) / 2;
                Vector3 leftMin  = Vector3.Zero;
                Vector3 leftMax  = Vector3.Zero;
                Vector3 rightMin = Vector3.Zero;
                Vector3 rightMax = Vector3.Zero;


                switch (Axis)
                {
                case 0:
                    leftMin  = new Vector3(PlanePos, BoundingBox.MinVector.Y, BoundingBox.MinVector.Z);
                    leftMax  = new Vector3(BoundingBox.MaxVector);
                    rightMin = new Vector3(BoundingBox.MinVector);
                    rightMax = new Vector3(PlanePos, BoundingBox.MaxVector.Y, BoundingBox.MaxVector.Z);
                    break;

                case 1:
                    leftMin  = new Vector3(BoundingBox.MinVector.X, PlanePos, BoundingBox.MinVector.Z);
                    leftMax  = new Vector3(BoundingBox.MaxVector);
                    rightMin = new Vector3(BoundingBox.MinVector);
                    rightMax = new Vector3(BoundingBox.MaxVector.X, PlanePos, BoundingBox.MaxVector.Z);
                    break;

                case 2:
                    leftMin  = new Vector3(BoundingBox.MinVector.X, BoundingBox.MinVector.Y, PlanePos);
                    leftMax  = new Vector3(BoundingBox.MaxVector);
                    rightMin = new Vector3(BoundingBox.MinVector);
                    rightMax = new Vector3(BoundingBox.MaxVector.X, BoundingBox.MaxVector.Y, PlanePos);
                    break;
                }


                IBoundingBox leftBb  = new AxisAlignedBoundingBox(leftMin, leftMax);
                IBoundingBox rightBb = new AxisAlignedBoundingBox(rightMin, rightMax);

                LeftNode  = new BspNode();
                RightNode = new BspNode();
                foreach (IIntersectable intersectable in Intersectables.GetObjects())
                {
                    if (intersectable.BoundingBox.Intersect(leftBb))
                    {
                        leftIntersectables.Add(intersectable);
                    }
                    if (intersectable.BoundingBox.Intersect(rightBb))
                    {
                        rightIntersectables.Add(intersectable);
                    }
                }
                LeftNode.BuildSubTree(leftIntersectables, leftBb, maxTreeDepth, currentTreeDetph + 1);
                RightNode.BuildSubTree(rightIntersectables, rightBb, maxTreeDepth, currentTreeDetph + 1);
                Intersectables = null; //Clear up the intersectables in non leaf nodes to save space
            }
        }