Пример #1
0
        private bool FindInteractionVolumeHit(Ray ray, out int interactionVolumeHitIndex, out IntersectInfo info)
        {
            interactionVolumeHitIndex = -1;
            if (interactionVolumes.Count == 0 || interactionVolumes[0].CollisionVolume == null)
            {
                info = null;
                return(false);
            }

            List <IRayTraceable> mesheTraceables = new List <IRayTraceable>();

            foreach (InteractionVolume interactionVolume in interactionVolumes)
            {
                IRayTraceable traceData = interactionVolume.CollisionVolume;
                mesheTraceables.Add(new Transform(traceData, interactionVolume.TotalTransform));
            }
            IRayTraceable allObjects = BoundingVolumeHierarchy.CreateNewHierachy(mesheTraceables);

            info = allObjects.GetClosestIntersection(ray);
            if (info != null)
            {
                for (int i = 0; i < interactionVolumes.Count; i++)
                {
                    List <IRayTraceable> insideBounds = new List <IRayTraceable>();
                    interactionVolumes[i].CollisionVolume.GetContained(insideBounds, info.closestHitObject.GetAxisAlignedBoundingBox());
                    if (insideBounds.Contains(info.closestHitObject))
                    {
                        interactionVolumeHitIndex = i;
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #2
0
        public IEnumerable IntersectionIterator(Ray ray)
        {
            if (ray.Intersection(Aabb))
            {
                IRayTraceable checkFirst  = nodeA;
                IRayTraceable checkSecond = nodeB;
                if (ray.directionNormal[splitingPlane] < 0)
                {
                    checkFirst  = nodeB;
                    checkSecond = nodeA;
                }

                foreach (IntersectInfo info in checkFirst.IntersectionIterator(ray))
                {
                    if (info != null && info.hitType != IntersectionType.None)
                    {
                        yield return(info);
                    }
                }

                if (checkSecond != null)
                {
                    foreach (IntersectInfo info in checkSecond.IntersectionIterator(ray))
                    {
                        if (info != null && info.hitType != IntersectionType.None)
                        {
                            yield return(info);
                        }
                    }
                }
            }
        }
Пример #3
0
 public BoundingVolumeHierarchy(IRayTraceable nodeA, IRayTraceable nodeB, int splitingPlane)
 {
     this.splitingPlane = splitingPlane;
     this.nodeA         = nodeA;
     this.nodeB         = nodeB;
     this.Aabb          = nodeA.GetAxisAlignedBoundingBox() + nodeB.GetAxisAlignedBoundingBox(); // we can cache this because it is not allowed to change.
 }
Пример #4
0
        private void AddTestStl()
        {
            Stopwatch loadTime = new Stopwatch();

            loadTime.Start();

            PolygonMesh.Mesh simpleMesh = StlProcessing.Load("Simple.stl")[0].Meshes[0];
            //PolygonMesh.Mesh simpleMesh = StlProcessing.Load("Complex.stl");
            //PolygonMesh.Mesh simpleMesh = StlProcessing.Load("bunny.stl");
            //PolygonMesh.Mesh simpleMesh = StlProcessing.Load("bunny_binary.stl");

            loadTime.Stop();

            timingStrings.Add("Time to load STL {0:0.0}s".FormatWith(loadTime.Elapsed.TotalSeconds));

            Stopwatch bvhTime = new Stopwatch();

            bvhTime.Start();
            IRayTraceable bvhCollection = MeshToBVH.Convert(simpleMesh);

            bvhTime.Stop();

            timingStrings.Add("Time to create BVH {0:0.0}s".FormatWith(bvhTime.Elapsed.TotalSeconds));

            renderCollection.Add(bvhCollection);
        }
Пример #5
0
        public static void CreateITraceableForMeshGroup(List <PlatingMeshGroupData> perMeshGroupInfo, List <MeshGroup> meshGroups, int meshGroupIndex, ReportProgressRatio reportProgress)
        {
            if (meshGroups != null)
            {
                MeshGroup meshGroup = meshGroups[meshGroupIndex];
                perMeshGroupInfo[meshGroupIndex].meshTraceableData.Clear();
                int totalActionCount = 0;
                foreach (Mesh mesh in meshGroup.Meshes)
                {
                    totalActionCount += mesh.Faces.Count;
                }
                int  currentAction   = 0;
                bool needUpdateTitle = true;
                for (int i = 0; i < meshGroup.Meshes.Count; i++)
                {
                    Mesh mesh = meshGroup.Meshes[i];
                    List <IRayTraceable> allPolys = AddTraceDataForMesh(mesh, totalActionCount, ref currentAction, ref needUpdateTitle, reportProgress);

                    needUpdateTitle = true;
                    if (reportProgress != null)
                    {
                        bool continueProcessing;
                        reportProgress(currentAction / (double)totalActionCount, "Creating Trace Group", out continueProcessing);
                    }

                    // only allow limited recusion to speed this up building this data
                    IRayTraceable traceData = BoundingVolumeHierarchy.CreateNewHierachy(allPolys, 0);
                    perMeshGroupInfo[meshGroupIndex].meshTraceableData.Add(traceData);
                }
            }
        }
Пример #6
0
 public Transform(IRayTraceable root, Matrix4X4 transform)
 {
     this.child = root;
     WorldToAxis = transform;
     AxisToWorld = Matrix4X4.Invert(WorldToAxis);
     AxisToWorld = transform;
     WorldToAxis = Matrix4X4.Invert(AxisToWorld);
 }
Пример #7
0
 public Transform(IRayTraceable root, Matrix4X4 transform)
 {
     this.child  = root;
     WorldToAxis = transform;
     AxisToWorld = Matrix4X4.Invert(WorldToAxis);
     AxisToWorld = transform;
     WorldToAxis = Matrix4X4.Invert(AxisToWorld);
 }
Пример #8
0
 public IntersectInfo(IntersectInfo copyInfo)
 {
     this.hitType          = copyInfo.hitType;
     this.closestHitObject = copyInfo.closestHitObject;
     this.hitPosition      = copyInfo.hitPosition;
     this.normalAtHit      = copyInfo.normalAtHit;
     this.distanceToHit    = copyInfo.distanceToHit;
 }
Пример #9
0
        public IntersectInfo GetClosestIntersection(Ray ray)
        {
            if (ray.Intersection(Aabb))
            {
                IRayTraceable checkFirst  = nodeA;
                IRayTraceable checkSecond = nodeB;
                if (ray.directionNormal[splitingPlane] < 0)
                {
                    checkFirst  = nodeB;
                    checkSecond = nodeA;
                }

                IntersectInfo infoFirst = checkFirst.GetClosestIntersection(ray);
                if (infoFirst != null && infoFirst.hitType != IntersectionType.None)
                {
                    if (ray.isShadowRay)
                    {
                        return(infoFirst);
                    }
                    else
                    {
                        ray.maxDistanceToConsider = infoFirst.distanceToHit;
                    }
                }
                if (checkSecond != null)
                {
                    IntersectInfo infoSecond = checkSecond.GetClosestIntersection(ray);
                    if (infoSecond != null && infoSecond.hitType != IntersectionType.None)
                    {
                        if (ray.isShadowRay)
                        {
                            return(infoSecond);
                        }
                        else
                        {
                            ray.maxDistanceToConsider = infoSecond.distanceToHit;
                        }
                    }
                    if (infoFirst != null && infoFirst.hitType != IntersectionType.None && infoFirst.distanceToHit >= 0)
                    {
                        if (infoSecond != null && infoSecond.hitType != IntersectionType.None && infoSecond.distanceToHit < infoFirst.distanceToHit && infoSecond.distanceToHit >= 0)
                        {
                            return(infoSecond);
                        }
                        else
                        {
                            return(infoFirst);
                        }
                    }

                    return(infoSecond); // we don't have to test it because it didn't hit.
                }
                return(infoFirst);
            }

            return(null);
        }
Пример #10
0
 long CalculateIntersectCostsForItem(IRayTraceable item, int numInterations)
 {
     Stopwatch timer = new Stopwatch();
     timer.Start();
     for (int i = 0; i < numInterations; i++)
     {
         item.GetClosestIntersection(GetRandomIntersectingRay());
     }
     return timer.ElapsedMilliseconds;
 }
Пример #11
0
        long CalculateIntersectCostsForItem(IRayTraceable item, int numInterations)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            for (int i = 0; i < numInterations; i++)
            {
                item.GetClosestIntersection(GetRandomIntersectingRay());
            }
            return(timer.ElapsedMilliseconds);
        }
Пример #12
0
        private IntersectInfo FindNextIntersections(IRayTraceable element, Ray ray, IntersectInfo info, IntersectionType intersectionType)
        {
            // get all the intersection for the object
            Ray currentRayCheckBackfaces = new Ray(ray);

            currentRayCheckBackfaces.intersectionType      = intersectionType;
            currentRayCheckBackfaces.minDistanceToConsider = ((info.hitPosition + ray.directionNormal * Ray.sameSurfaceOffset) - ray.origin).Length;
            currentRayCheckBackfaces.maxDistanceToConsider = double.PositiveInfinity;

            return(element.GetClosestIntersection(currentRayCheckBackfaces));
        }
Пример #13
0
        /// <summary>
        /// This will remove the shapes from 'Shapes' and add them to a Bounding Volume Hierarchy.  Then add that at a single element
        /// to 'Shapes'.  You could also create a list of 'List<IRayTraceable>' and put that dirrectly into a BVH and then add that
        /// to the Shapes list (there could be more than 1 BVH in the 'Shapes' list.
        /// </summary>
        public IRayTraceable MoveShapesIntoBoundingVolumeHierachy()
        {
            IRayTraceable rootObject = BoundingVolumeHierarchy.CreateNewHierachy(shapes);

            if (rootObject != null)
            {
                shapes.Clear();
                shapes.Add(rootObject);
            }

            return(rootObject);
        }
Пример #14
0
        private void AddBoxAndBoxBooleanTest()
        {
            BoxShape box1 = new BoxShape(new Vector3(.5, .5, .5), new Vector3(1.5, 1.5, 1.5),
                                         new SolidMaterial(RGBA_Floats.Green, .01, 0.0, 2.0));

            List <IRayTraceable> subtractShapes = new List <IRayTraceable>();
            SolidMaterial        material       = new SolidMaterial(RGBA_Floats.Red, 0, 0, 0);

            subtractShapes.Add(new BoxShape(new Vector3(), new Vector3(1, 1, 1), material));

            IRayTraceable subtractGroup = BoundingVolumeHierarchy.CreateNewHierachy(subtractShapes);
            Difference    merge         = new Difference(box1, subtractGroup);

            renderCollection.Add(merge);
        }
Пример #15
0
        private bool FindMeshGroupHitPosition(Vector2 screenPosition, out int meshHitIndex)
        {
            meshHitIndex = 0;
            if (MeshGroupExtraData.Count == 0 || MeshGroupExtraData[0].meshTraceableData == null)
            {
                return(false);
            }

            List <IRayTraceable> mesheTraceables = new List <IRayTraceable>();

            for (int i = 0; i < MeshGroupExtraData.Count; i++)
            {
                foreach (IRayTraceable traceData in MeshGroupExtraData[i].meshTraceableData)
                {
                    mesheTraceables.Add(new Transform(traceData, MeshGroupTransforms[i].TotalTransform));
                }
            }
            IRayTraceable allObjects = BoundingVolumeHierarchy.CreateNewHierachy(mesheTraceables);

            Vector2       meshViewerWidgetScreenPosition = meshViewerWidget.TransformFromParentSpace(this, screenPosition);
            Ray           ray  = meshViewerWidget.TrackballTumbleWidget.GetRayFromScreen(meshViewerWidgetScreenPosition);
            IntersectInfo info = allObjects.GetClosestIntersection(ray);

            if (info != null)
            {
                meshSelectInfo.planeDownHitPos = info.hitPosition;
                meshSelectInfo.lastMoveDelta   = new Vector3();

                for (int i = 0; i < MeshGroupExtraData.Count; i++)
                {
                    List <IRayTraceable> insideBounds = new List <IRayTraceable>();
                    foreach (IRayTraceable traceData in MeshGroupExtraData[i].meshTraceableData)
                    {
                        traceData.GetContained(insideBounds, info.closestHitObject.GetAxisAlignedBoundingBox());
                    }
                    if (insideBounds.Contains(info.closestHitObject))
                    {
                        meshHitIndex = i;
                        return(true);
                    }
                }
            }

            return(false);
        }
Пример #16
0
        public override void OnMouseDown(MouseEventArgs mouseEvent)
        {
            base.OnMouseDown(mouseEvent);

            lastMouseMovePoint.x = mouseEvent.X;
            lastMouseMovePoint.y = mouseEvent.Y;

            if (Focused && MouseCaptured)
            {
                if (trackBallController.CurrentTrackingType == TrackBallController.MouseDownType.None)
                {
                    if (Focused && MouseCaptured && mouseEvent.Button == MouseButtons.Left)
                    {
                        trackBallController.OnMouseDown(lastMouseMovePoint, Matrix4X4.Identity);
                    }
                    else if (mouseEvent.Button == MouseButtons.Middle)
                    {
                        trackBallController.OnMouseDown(lastMouseMovePoint, Matrix4X4.Identity, TrackBallController.MouseDownType.Translation);
                    }
                }

                if (MouseCaptured)
                {
                    lastMouseMovePoint.x             = mouseEvent.X;
                    lastMouseMovePoint.y             = mouseEvent.Y;
                    cameraDataAtStartOfMouseTracking = cameraData;
                    cameraDataAtStartOfMouseTracking.cameraMatrix = scene.camera.axisToWorld;

                    Ray rayAtPoint = scene.camera.GetRay(lastMouseMovePoint.x, lastMouseMovePoint.y);

                    IntersectInfo info = raytracer.TracePrimaryRay(rayAtPoint, scene);
                    if (info != null)
                    {
                        focusedObject = (BaseShape)info.closestHitObject;
                        if (focusedObject != null && mouseEvent.Clicks == 2)
                        {
                            cameraData.lookAtPoint = focusedObject.GetAxisAlignedBoundingBox().Center;
                            OrientCamera();
                        }
                    }
                }
            }
        }
Пример #17
0
        public void GetClosestIntersections(RayBundle rayBundle, int rayIndexToStartCheckingFrom, IntersectInfo[] intersectionsForBundle)
        {
            int startRayIndex = FindFirstRay(rayBundle, rayIndexToStartCheckingFrom);

            if (startRayIndex != -1)
            {
                IRayTraceable checkFirst  = nodeA;
                IRayTraceable checkSecond = nodeB;
                if (rayBundle.rayArray[startRayIndex].directionNormal[splitingPlane] < 0)
                {
                    checkFirst  = nodeB;
                    checkSecond = nodeA;
                }

                checkFirst.GetClosestIntersections(rayBundle, startRayIndex, intersectionsForBundle);
                if (checkSecond != null)
                {
                    checkSecond.GetClosestIntersections(rayBundle, startRayIndex, intersectionsForBundle);
                }
            }
        }
Пример #18
0
        private void AddBoxAndSheresBooleanTest()
        {
            RayTracer.BoxShape box1 = new RayTracer.BoxShape(new Vector3(.5, .5, .5), new Vector3(1.5, 1.5, 1.5),
                                                             new RayTracer.SolidMaterial(RGBA_Floats.Green, 0, 0, 0));//.01, 0.0, 2.0));

            List <RayTracer.IRayTraceable> subtractShapes = new List <RayTracer.IRayTraceable>();

            RayTracer.SolidMaterial material = new RayTracer.SolidMaterial(RGBA_Floats.Red, 0, 0, 0);

#if true
            // two big spheres.  Looks good.
            subtractShapes.Add(new RayTracer.SphereShape(new Vector3(.5, .5, 1), .6, material));
            subtractShapes.Add(new RayTracer.SphereShape(new Vector3(1.5, .5, 1), .6, material));

            Transform cylinder = new Transform(new RayTracer.CylinderShape(.1, 3, material));
            cylinder.MoveToAbsolute(1, 1, 1);
            cylinder.RotateRelative(.1, .6, .6);
            //subtractShapes.Add(cylinder);
            //renderCollection.Add(cylinder);
#else
            for (int z = 0; z < 6; z++)
            {
                for (int y = 0; y < 6; y++)
                {
                    for (int x = 0; x < 6; x++)
                    {
                        subtractShapes.Add(new SphereShape(new Vector3(x * .2 + .5, y * .2 + .5, z * .2 + .5), .1, material));
                        //subtractShapes.Add(new SphereShape(new Vector3(x * .2 + .5, y * .2 + .5, z * .2 + .5), .13, material));
                    }
                }
            }
#endif


            IRayTraceable subtractGroup = BoundingVolumeHierarchy.CreateNewHierachy(subtractShapes);
            Difference    merge         = new Difference(box1, subtractGroup);

            renderCollection.Add(merge);
        }
Пример #19
0
        private void CreateScene()
        {
            scene            = new Scene();
            scene.camera     = new Camera((int)Width, (int)Height, MathHelper.DegreesToRadians(40));
            scene.background = new Background(new RGBA_Floats(0.5, .5, .5), 0.4);

            //AddBoxAndSheresBooleanTest();
            //AddBoxAndBoxBooleanTest();
#if false
            renderCollection.Add(new BoxShape(new Vector3(), new Vector3(1, 1, 1),
                                              new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
            renderCollection.Add(new BoxShape(new Vector3(.5, .5, .5), new Vector3(1.5, 1.5, 1.5),
                                              new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0)));
#endif
            //renderCollection.Add(new CylinderShape(.25, 1, new SolidMaterial(RGBA_Floats.Cyan, 0, 0, 0)));

            AddTestStl();
            //AddPolygonTest();
            //AddSphereAndBox();
            //AddAxisMarker();
            //AddCubeOfShperes();

            //renderCollection.Add(MakerGearXCariage());

            allObjects         = BoundingVolumeHierarchy.CreateNewHierachy(renderCollection);
            trackBallTransform = new Transform(allObjects);
            //allObjects = root;
            scene.shapes.Add(trackBallTransform);

            //AddAFloor();

            //add two lights for better lighting effects
            scene.lights.Add(new Light(new Vector3(50, 10, 100), new RGBA_Floats(0.8, 0.8, 0.8)));
            scene.lights.Add(new Light(new Vector3(-30, 150, 50), new RGBA_Floats(0.8, 0.8, 0.8)));

            OrientCamera();
        }
Пример #20
0
 public Transform(IRayTraceable root)
 {
     this.child = root;
 }
Пример #21
0
        public static IRayTraceable CreateNewHierachy(List <IRayTraceable> traceableItems, int maxRecursion = int.MaxValue, int recursionDepth = 0, SortingAccelerator accelerator = null)
        {
            if (accelerator == null)
            {
                accelerator = new SortingAccelerator();
            }

            int numItems = traceableItems.Count;

            if (numItems == 0)
            {
                return(null);
            }

            if (numItems == 1)
            {
                return(traceableItems[0]);
            }

            int bestAxis                    = -1;
            int bestIndexToSplitOn          = -1;
            CompareCentersOnAxis axisSorter = new CompareCentersOnAxis(0);

            if (recursionDepth < maxRecursion)
            {
                if (numItems > 5000)
                {
                    bestAxis           = accelerator.NextAxis;
                    bestIndexToSplitOn = numItems / 2;
                }
                else
                {
                    double totalIntersectCost = 0;
                    int    skipInterval       = 1;
                    for (int i = 0; i < numItems; i += skipInterval)
                    {
                        IRayTraceable item = traceableItems[i];
                        totalIntersectCost += item.GetIntersectCost();
                    }

                    // get the bounding box of all the items we are going to consider.
                    AxisAlignedBoundingBox OverallBox = traceableItems[0].GetAxisAlignedBoundingBox();
                    for (int i = skipInterval; i < numItems; i += skipInterval)
                    {
                        OverallBox += traceableItems[i].GetAxisAlignedBoundingBox();
                    }
                    double areaOfTotalBounds = OverallBox.GetSurfaceArea();

                    double bestCost = totalIntersectCost;

                    Vector3  totalDeviationOnAxis = new Vector3();
                    double[] surfaceArreaOfItem   = new double[numItems - 1];
                    double[] rightBoundsAtItem    = new double[numItems - 1];

                    for (int axis = 0; axis < 3; axis++)
                    {
                        double intersectCostOnLeft = 0;

                        axisSorter.WhichAxis = axis;
                        traceableItems.Sort(axisSorter);

                        // Get all left bounds
                        AxisAlignedBoundingBox currentLeftBounds = traceableItems[0].GetAxisAlignedBoundingBox();
                        surfaceArreaOfItem[0] = currentLeftBounds.GetSurfaceArea();
                        for (int itemIndex = 1; itemIndex < numItems - 1; itemIndex += skipInterval)
                        {
                            currentLeftBounds            += traceableItems[itemIndex].GetAxisAlignedBoundingBox();
                            surfaceArreaOfItem[itemIndex] = currentLeftBounds.GetSurfaceArea();

                            totalDeviationOnAxis[axis] += Math.Abs(traceableItems[itemIndex].GetCenter()[axis] - traceableItems[itemIndex - 1].GetCenter()[axis]);
                        }

                        // Get all right bounds
                        if (numItems > 1)
                        {
                            AxisAlignedBoundingBox currentRightBounds = traceableItems[numItems - 1].GetAxisAlignedBoundingBox();
                            rightBoundsAtItem[numItems - 2] = currentRightBounds.GetSurfaceArea();
                            for (int itemIndex = numItems - 1; itemIndex > 1; itemIndex -= skipInterval)
                            {
                                currentRightBounds += traceableItems[itemIndex - 1].GetAxisAlignedBoundingBox();
                                rightBoundsAtItem[itemIndex - 2] = currentRightBounds.GetSurfaceArea();
                            }
                        }

                        // Sweep from left
                        for (int itemIndex = 0; itemIndex < numItems - 1; itemIndex += skipInterval)
                        {
                            double thisCost = 0;

                            {
                                // Evaluate Surface Cost Equation
                                double costOfTwoAABB = 2 * AxisAlignedBoundingBox.GetIntersectCost(); // the cost of the two children AABB tests

                                // do the left cost
                                intersectCostOnLeft += traceableItems[itemIndex].GetIntersectCost();
                                double leftCost = (surfaceArreaOfItem[itemIndex] / areaOfTotalBounds) * intersectCostOnLeft;

                                // do the right cost
                                double intersectCostOnRight = totalIntersectCost - intersectCostOnLeft;
                                double rightCost            = (rightBoundsAtItem[itemIndex] / areaOfTotalBounds) * intersectCostOnRight;

                                thisCost = costOfTwoAABB + leftCost + rightCost;
                            }

                            if (thisCost < bestCost + .000000001) // if it is less within some tiny error
                            {
                                if (thisCost > bestCost - .000000001)
                                {
                                    // they are the same within the error
                                    if (axis > 0 && bestAxis != axis) // we have changed axis since last best and we need to decide if this is better than the last axis best
                                    {
                                        if (totalDeviationOnAxis[axis] > totalDeviationOnAxis[axis - 1])
                                        {
                                            // this new axis is better and we'll switch to it.  Otherwise don't switch.
                                            bestCost           = thisCost;
                                            bestIndexToSplitOn = itemIndex;
                                            bestAxis           = axis;
                                        }
                                    }
                                }
                                else // this is just better
                                {
                                    bestCost           = thisCost;
                                    bestIndexToSplitOn = itemIndex;
                                    bestAxis           = axis;
                                }
                            }
                        }
                    }
                }
            }

            if (bestAxis == -1)
            {
                // No better partition found
                return(new UnboundCollection(traceableItems));
            }
            else
            {
                axisSorter.WhichAxis = bestAxis;
                traceableItems.Sort(axisSorter);
                List <IRayTraceable> leftItems  = new List <IRayTraceable>(bestIndexToSplitOn + 1);
                List <IRayTraceable> rightItems = new List <IRayTraceable>(numItems - bestIndexToSplitOn + 1);
                for (int i = 0; i <= bestIndexToSplitOn; i++)
                {
                    leftItems.Add(traceableItems[i]);
                }
                for (int i = bestIndexToSplitOn + 1; i < numItems; i++)
                {
                    rightItems.Add(traceableItems[i]);
                }
                IRayTraceable           leftGroup  = CreateNewHierachy(leftItems, maxRecursion, recursionDepth + 1, accelerator);
                IRayTraceable           rightGroup = CreateNewHierachy(rightItems, maxRecursion, recursionDepth + 1, accelerator);
                BoundingVolumeHierarchy newBVHNode = new BoundingVolumeHierarchy(leftGroup, rightGroup, bestAxis);
                return(newBVHNode);
            }
        }
Пример #22
0
        private IntersectInfo FindNextIntersections(IRayTraceable element, Ray ray, IntersectInfo info, IntersectionType intersectionType)
        {
            // get all the intersection for the object
            Ray currentRayCheckBackfaces = new Ray(ray);
            currentRayCheckBackfaces.intersectionType = intersectionType;
            currentRayCheckBackfaces.minDistanceToConsider = ((info.hitPosition + ray.direction * Ray.sameSurfaceOffset) - ray.origin).Length;
            currentRayCheckBackfaces.maxDistanceToConsider = double.PositiveInfinity;

            return element.GetClosestIntersection(currentRayCheckBackfaces);
        }
Пример #23
0
 public Difference(IRayTraceable primary, IRayTraceable subtract)
 {
     this.primary = primary;
     this.subtract = subtract;
 }
Пример #24
0
 public Transform(IRayTraceable root)
 {
     this.child = root;
 }
Пример #25
0
 public Difference(IRayTraceable primary, IRayTraceable subtract)
 {
     this.primary  = primary;
     this.subtract = subtract;
 }
Пример #26
0
 public InteractionVolume(IRayTraceable collisionVolume, MeshViewerWidget meshViewerToDrawWith)
 {
     this.collisionVolume      = collisionVolume;
     this.meshViewerToDrawWith = meshViewerToDrawWith;
 }
Пример #27
0
        public void DifferenceTestsForBox()
        {
            SolidMaterial redMaterial  = new SolidMaterial(RGBA_Floats.Red, 0, 0, 0);
            SolidMaterial blueMaterial = new SolidMaterial(RGBA_Floats.Blue, 0, 0, 0);
            Ray           castRay      = new Ray(new Vector3(0, -1, 0), Vector3.UnitY);

            BoxShape box1X1 = new BoxShape(new Vector3(-.5, -.5, -.5), new Vector3(.5, .5, .5), blueMaterial);

            // just a box all by itself
            {
                IntersectInfo testInfo = box1X1.GetClosestIntersection(castRay);

                Assert.IsTrue(testInfo.hitType == IntersectionType.FrontFace, "Found Hit : Box No CSG");
                Assert.IsTrue(testInfo.closestHitObject == box1X1, "Found Hit : Box No CSG");
                Assert.IsTrue(testInfo.hitPosition == new Vector3(0, -.5, 0), "Hit position y = -.5 : Box No CSG");
                Assert.IsTrue(testInfo.distanceToHit == .5, "Hit length = .5 : Box No CSG");
                Assert.IsTrue(testInfo.normalAtHit == -Vector3.UnitY, "Normal Correct : Box No CSG");
            }

            // one subtract from the front of a box, the front faces are aligned
            {
                BoxShape      subtractBox = new BoxShape(new Vector3(-.5, -.5, -.5), new Vector3(.5, 0, .5), redMaterial);
                Difference    merge       = new Difference(box1X1, subtractBox);
                IntersectInfo testInfo    = merge.GetClosestIntersection(castRay);

                Assert.IsTrue(testInfo.hitType == IntersectionType.FrontFace, "Found Hit : One Subtract");
                Assert.IsTrue(testInfo.closestHitObject == subtractBox, "Found Hit : One Subtract");
                Assert.IsTrue(testInfo.hitPosition == new Vector3(0, 0, 0), "Hit position y = 0 : One Subtract");
                Assert.IsTrue(testInfo.distanceToHit == 1, "Hit length = 1 : One Subtract");
                Assert.IsTrue(testInfo.normalAtHit == -Vector3.UnitY, "Normal Correct : One Subtract");
            }

#if false
            // An internal primary object that needs to be skipped over
            {
                List <IRayTraceable> primaryShapes = new List <IRayTraceable>();
                BoxShape             insideBox     = new BoxShape(new Vector3(-.1, -.1, -.1), new Vector3(.1, .1, .1), blueMaterial);
                primaryShapes.Add(box1X1);
                primaryShapes.Add(insideBox);
                IRayTraceable primamryGroup = BoundingVolumeHierarchy.CreateNewHierachy(primaryShapes);

                List <IRayTraceable> subtractShapes = new List <IRayTraceable>();
                subtractShapes.Add(new BoxShape(new Vector3(-.5, -.5, -.5), new Vector3(.5, .4, .5), redMaterial));

                IRayTraceable subtractGroup = BoundingVolumeHierarchy.CreateNewHierachy(subtractShapes);
                Difference    merge         = new Difference(primamryGroup, subtractGroup);

                IntersectInfo testInfo = merge.GetClosestIntersection(castRay);

                Assert.IsTrue(testInfo.isHit == true, "Found Hit : 5 Subtracts");
                //Assert.IsTrue(testInfo.closestHitObject == subtractBox, "Found Hit : 5 Subtracts");
                Assert.IsTrue(testInfo.hitPosition == new Vector3(0, 0, 0), "Hit position y = 0 : 5 Subtracts");
                Assert.IsTrue(testInfo.distanceToHit == 1, "Hit length = 1 : 5 Subtracts");
                Assert.IsTrue(testInfo.normalAtHit == -Vector3.UnitY, "Normal Correct : 5 Subtracts");
            }

            // Go through 5 subtract boxes to get to 1/2 way through the main box.
            {
                List <IRayTraceable> subtractShapes = new List <IRayTraceable>();

                for (int i = 0; i < 5; i++)
                {
                    subtractShapes.Add(new BoxShape(new Vector3(-.5, -.5 + i * .1, -.5), new Vector3(.5, -.4 + i * .1, .5), redMaterial));
                }

                IRayTraceable subtractGroup = BoundingVolumeHierarchy.CreateNewHierachy(subtractShapes);
                Difference    merge         = new Difference(box1X1, subtractGroup);

                IntersectInfo testInfo = merge.GetClosestIntersection(castRay);

                Assert.IsTrue(testInfo.isHit == true, "Found Hit : 5 Subtracts");
                //Assert.IsTrue(testInfo.closestHitObject == subtractBox, "Found Hit : 5 Subtracts");
                Assert.IsTrue(testInfo.hitPosition == new Vector3(0, 0, 0), "Hit position y = 0 : 5 Subtracts");
                Assert.IsTrue(testInfo.distanceToHit == 1, "Hit length = 1 : 5 Subtracts");
                Assert.IsTrue(testInfo.normalAtHit == -Vector3.UnitY, "Normal Correct : 5 Subtracts");
            }
#endif
        }