/// <summary> /// Project a point into 2D space /// </summary> public static Vector2 Project(BoundingFrustum VisibleArea, Vector3 Point) { //Acquires the frustum of the area of the screen in view. //Then it stores the corners of the area. Vector3[] corners = VisibleArea.GetCorners(); Ray ray = new Ray(Point, Point - Manager.CameraFocus - Manager.CameraLocation); float? DistanceToFar = ray.Intersects(VisibleArea.Far); float? DistanceToNear = ray.Intersects(VisibleArea.Near); Vector3 ScreenCoord; if (DistanceToFar.HasValue) { ScreenCoord = ray.Position + ray.Direction * DistanceToFar.Value; ScreenCoord = new Vector3( Vector3.Dot( Vector3.Normalize(corners[5] - corners[4]) , ScreenCoord - corners[4]) / (corners[5] - corners[4]).Length() , Vector3.Dot( Vector3.Normalize(corners[7] - corners[4]) , ScreenCoord - corners[4]) / (corners[7] - corners[4]).Length() , 0); } else { //Make sure this is off the screen return Vector2.One * (Manager.GameWindow.Width + Manager.GameWindow.Height); } return new Vector2(ScreenCoord.X * Manager.GameWindow.Width, ScreenCoord.Y * Manager.GameWindow.Height); }
public static VoxLocation? GetOuter(Ray camRay, VoxState state) { camRay.Position -= new Vector3(state.World.worldMin.X * Region.WIDTH, 0, state.World.worldMin.Y * Region.DEPTH); VRay vr = new VRay(camRay.Position, camRay.Direction); Vector3I loc = vr.GetNextLocation(); // Check For World Intersect BoundingBox bb = new BoundingBox(Vector3.Zero, new Vector3(VoxWorld.WIDTH * Region.WIDTH, Region.HEIGHT, VoxWorld.DEPTH * Region.DEPTH)); if(!camRay.Intersects(bb).HasValue) return null; // Move In World while(!IsInBounds(loc)) loc = vr.GetNextLocation(); // Move Through World VoxLocation pvl = new VoxLocation(loc); while(IsInBounds(loc)) { VoxLocation vl = new VoxLocation(loc); Region region = state.World.regions[vl.RegionIndex]; if(region != null) { ushort id = region.voxels[vl.VoxelIndex].ID; if(id != 0) return pvl; } loc = vr.GetNextLocation(); pvl = vl; } return null; }
public Vector3? GetCollisionPosition() { MouseState mouseState = Mouse.GetState(); Vector3 nearSource = new Vector3(mouseState.X, mouseState.Y, 0f); Vector3 farSource = new Vector3(mouseState.X, mouseState.Y, 1f); Vector3 nearPoint = device.Viewport.Unproject( nearSource, camera.projection, camera.view, Matrix.Identity); Vector3 farPoint = device.Viewport.Unproject( farSource, camera.projection, camera.view, Matrix.Identity); Vector3 direction = farPoint - nearPoint; direction.Normalize(); Ray pickRay = new Ray(nearPoint, direction); Nullable<float> result = pickRay.Intersects(new Plane(Vector3.Up, 0f)); Vector3? resultVector = direction * result; Vector3? collisionPoint = resultVector + nearPoint; return collisionPoint; }
public void BoundingCylinder_Ray_Test() { BoundingCylinder cyl = new BoundingCylinder (sideA: Vector3.Zero, sideB: Vector3.Up * 100, radius: 100f); Ray ray; ray = new Ray (position: new Vector3 (0, 0, 0), direction: Vector3.Up); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 0, 0), direction: Vector3.Down); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 0, 0), direction: Vector3.Forward); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 0, 0), direction: Vector3.Left); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, -1, 0), direction: Vector3.Forward); Assert.IsNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, -1, 0), direction: Vector3.Left); Assert.IsNull (ray.Intersects (cyl)); // hier sollte eigentlich (0,100,0) auch noch drin sein, nicht nur (0,99,0), // also wie bei SideA! ray = new Ray (position: new Vector3 (0, 99, 0), direction: Vector3.Forward); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 99, 0), direction: Vector3.Left); Assert.IsNotNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 101, 0), direction: Vector3.Forward); Assert.IsNull (ray.Intersects (cyl)); ray = new Ray (position: new Vector3 (0, 101, 0), direction: Vector3.Left); Assert.IsNull (ray.Intersects (cyl)); }
/// <summary> /// Defines the closest obstacle /// </summary> public void DetectClosestObstacle() { float closestObstacleDistance = float.MaxValue; _closestObstacle = null; var localAgentMatrix = Matrix.Invert(AutonomousAgent.ParentObject.World); foreach (SceneEntity obstacle in Context.Keys) { Vector3 localPos = Vector3.Transform(obstacle.World.Translation, localAgentMatrix); if (UseLineOfSight) { if (localPos.Z > 0f) continue; } float expandedRadius = obstacle.WorldBoundingSphere.Radius + AutonomousAgent.ParentObject.WorldBoundingSphere.Radius - AllowedPenetration; var ray = new Ray(Vector3.Zero, Vector3.Forward); float? result = ray.Intersects(new BoundingSphere(localPos, expandedRadius)); if (result.HasValue && result.Value < closestObstacleDistance) { closestObstacleDistance = result.Value; _closestObstacle = obstacle; _closestObstacleLocalPosition = localPos; } } }
public override void CalculateLocalMouse(Ray mouseRay, Action<VertexPositionColor, VertexPositionColor> debug) { MouseHover = false; var verts = new Vector3[3]; verts[0] = new Vector3(-0.5f, -0.5f, 0); verts[1] = new Vector3(0.5f, -0.5f, 0); verts[2] = new Vector3(-0.5f, 0.5f, 0); for (int i = 0; i < 3; ++i) verts[i] = Vector3.Transform(verts[i], localTransformation); debug(new VertexPositionColor(verts[0], Color.Red), new VertexPositionColor(verts[1], Color.Red)); debug(new VertexPositionColor(verts[0], Color.Green), new VertexPositionColor(verts[2], Color.Green)); var distance = mouseRay.Intersects(new Plane(verts[0], verts[1], verts[2])); if (distance == null || !distance.HasValue) return; if (distance.Value < 0) return; //GUI plane is behind camera var interesectionPoint = mouseRay.Position + (mouseRay.Direction * distance.Value); debug(new VertexPositionColor(verts[0], Color.Blue), new VertexPositionColor(interesectionPoint, Color.Blue)); var x = ScalarProjection(interesectionPoint - verts[0], verts[1] - verts[0]) / (verts[1] - verts[0]).Length(); var y = ScalarProjection(interesectionPoint - verts[0], verts[2] - verts[0]) / (verts[2] - verts[0]).Length(); LocalMouseX = (int)(x * uiCamera.viewportDimensions.X); LocalMouseY = (int)(y * uiCamera.viewportDimensions.Y); MouseHover = true; }
private void GenerateRect() { int minX = int.MaxValue; int minZ = int.MaxValue; int maxX = int.MinValue; int maxZ = int.MinValue; var corners = Frustum.GetCorners(); Plane plane = new Plane(new Vector4(0, 1, 0, 0)); for (int i = 4; i < corners.Length; i++) { Ray ray = new Ray(corners[i - 4], corners[i]); var distance = ray.Intersects(plane); if (distance.HasValue) { var pos2 = ray.Position + ray.Direction * distance.Value; if ((int)pos2.X > maxX) maxX = (int)pos2.X; if ((int)pos2.X < minX) minX = (int)pos2.X; if ((int)pos2.Z > maxZ) maxZ = (int)pos2.Z; if ((int)pos2.Z < minZ) minZ = (int)pos2.Z; } // Console.WriteLine("distance[{0}]: {1} pos2:{2}", i, distance, pos2.ToString()); } quadRect = new Rectangle(minX, minZ, Math.Abs(maxX - minX), Math.Abs(maxZ - minZ)); // Console.WriteLine("X: {0},{1} Z:{2},{3}", minX, maxX, minZ, maxZ); }
public static void CalculateMouse3DPosition() { Plane GroundPlane = new Plane(0, 1, 0, 0); // x - lewo prawo Z- gora dol int mouseX = mouseState.X; int mouseY = mouseState.Y; Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f); Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f); Matrix world = Matrix.CreateTranslation(0, 0, 0); Vector3 nearPoint = device.Viewport.Unproject(nearsource, Projection, View, Matrix.Identity); Vector3 farPoint = device.Viewport.Unproject(farsource, Projection, View, Matrix.Identity); Vector3 direction = farPoint - nearPoint; direction.Normalize(); Ray pickRay = new Ray(nearPoint, direction); float? position = pickRay.Intersects(GroundPlane); if (position != null) { MousePosition = pickRay.Position + pickRay.Direction * position.Value; MousePosition.Y = 30f; } else MousePosition = new Vector3(0, 0, 0); }
public static List<IPickable> GetPickables(Point a_clickPoint) { var camera = CameraManager.ActiveCamera; Vector3 nearSource = camera.Viewport.Unproject(new Vector3(a_clickPoint.X, a_clickPoint.Y, camera.Viewport.MinDepth), camera.Projection, camera.View, Matrix.Identity); Vector3 farSource = camera.Viewport.Unproject(new Vector3(a_clickPoint.X, a_clickPoint.Y, camera.Viewport.MaxDepth), camera.Projection, camera.View, Matrix.Identity); Vector3 direction = farSource - nearSource; direction.Normalize(); var ray = new Ray(nearSource, direction); var pickables = new List<IPickable>(); var rays = new List<Ray>(); var map = new Dictionary<float?, IPickable>(); foreach (var pickable in ComponentManager.Pickables.Values) { BoundingBox boundingBox = pickable.GetBoundingBox(); float? distance; ray.Intersects(ref boundingBox, out distance); if (distance != null) { map[distance] = pickable; pickables.Add(pickable); } } return pickables; }
public float? checkCollisionAgainstEnvironment(Ray ray) { float? collided = null; foreach (Collidable c in stationaryCollidables) { if (c.type == CollisionType.environment && collided == null) { Vector3[] points = new Vector3[2]; points[0] = Vector3.Transform(c.boundingBox.Min, c.getComponent<Spatial>().transform); points[1] = Vector3.Transform(c.boundingBox.Max, c.getComponent<Spatial>().transform); BoundingBox bb = BoundingBox.CreateFromPoints(points); if (ray.Intersects(bb) != null) { if (c.children.Count > 0) { collided = checkAgainstChildren(c, ray); } else { collided = checkAgainstMesh(c.getComponent<Drawable3D>(), ray); } } } } return collided; }
public static Vector3? GetRayPlaneIntersectionPoint(Ray ray, Plane plane) { float? distance = ray.Intersects(plane); if (distance.HasValue) return ray.Position + ray.Direction * distance.Value; else return null; }
// überprüft, ob ein Strahl ein Dreieck schneidet protected float? FindIntersection(Ray ray, ITriangle triangle) { // überprüfen, ob der Strahl die vom Dreieck aufgespannte Ebene schneidet float? f = ray.Intersects(new Plane(triangle.P0, triangle.P1, triangle.P2)); // wenn ja, überprüfen ob Schnittpunkt im Dreieck liegt if (f != null && IsInsideTriangle(triangle, ray.Position + ray.Direction * f.Value)) return f; return null; }
public static float? CastBulletRay(Entity targetEntity, GraphicsDevice GraphicsDevice) { Vector3 near = new Vector3(GraphicsDevice.Viewport.Width * 0.5f, GraphicsDevice.Viewport.Height * 0.5f, 0.0f); Vector3 far = new Vector3(GraphicsDevice.Viewport.Width * 0.5f, GraphicsDevice.Viewport.Height * 0.5f, 1.0f); near = GraphicsDevice.Viewport.Unproject(near, Projection(GraphicsDevice), LookAt(), Matrix.Identity); far = GraphicsDevice.Viewport.Unproject(far, Projection(GraphicsDevice), LookAt(), Matrix.Identity); Ray ray = new Ray(near, Vector3.Normalize(far - near)); return ray.Intersects(targetEntity.model.boundingbox); }
public bool CheckRayIntersection(Ray ray, BoundingSphere sphere) { if (ray.Intersects(sphere) != null) { drawSpheres = sphere; return true; } else { return false; } }
public static Vector3 getIntersectedQuadNode(Ray intersected) { Vector3 v = Vector3.Zero; BoundingBox tmp; foreach(QuadNode q in QuadNodeController.QuadNodeList) { if((intersected.Intersects(q.Bounds))!=null) { // prezri vsetky bunky terenu v patchi a zisti ktoru malu bunku pretina int minX = (int)q.Bounds.Min.X; int minZ = (int)q.Bounds.Min.Z; int maxX = (int)q.Bounds.Max.X; int maxZ = (int)q.Bounds.Max.Z; for (int j = minX; j < maxX; j++) { for (int k = minZ; k < maxZ; k++) { v.X = j; v.Y = StaticHelpers.StaticHelper.GetHeightAt(k, j); v.Z = k; tmp.Min = v; tmp.Max = v + new Vector3(1); if (intersected.Intersects(tmp) != null) { return v; } } } return q.Bounds.Min + (q.Bounds.Max - q.Bounds.Min) /2; } } return Vector3.Zero; }
public override GameObjectDistance Intersects(Ray ray) { foreach (BoundingSphere sphere in Bounds) { float? distance = ray.Intersects (sphere); if (distance != null) { GameObjectDistance intersection = new GameObjectDistance () { Object=this, Distance=distance.Value }; return intersection; } } return null; }
public static Node getNodeIntersected(Ray mouseRay) { foreach (Node q in tileList) { if ((mouseRay.Intersects(q.Box)) != null) { //return q.Box.Min + (q.Box.Max - q.Box.Min) / 2; return q; } } return PathFinderManager.tileList[0, 0]; }
public static Vector3 GetPosition(Ray ray) { Plane plane = new Plane(new Vector3(0, 1, 0), 0); float? distance = ray.Intersects(plane); //ripped from http://xboxforums.create.msdn.com/forums/p/10441/212094.aspx //how the f**k does this work? double denominator = Vector3.Dot(plane.Normal, ray.Direction); double numerator = Vector3.Dot(plane.Normal, ray.Position) + plane.D; double t = -(numerator / denominator); return ray.Position + ray.Direction * (float)t; }
public Vector3? GetCollisionTest() { Vector3 direction = camera.cameraDirection; //farPoint - nearPoint; direction.Normalize(); Ray pickRay = new Ray(camera.cameraPosition, direction); Nullable<float> result = pickRay.Intersects(new Plane(Vector3.Up, -1f)); Vector3? resultVector = direction * result; Vector3? collisionPoint = resultVector + camera.cameraPosition; return collisionPoint; }
public Entity CheckEntity(Vector3 start, Vector3 direction, Entity sender) { Ray ray = new Ray(start, direction); foreach (var ent in Entities) { if (ent == sender) continue; if (ray.Intersects(ent.CollisionBox) != null) return ent; } return null; }
public void CheckHits(Player player, OtherPlayer[] players) { if (players[id] != null) { Vector3 shooterPos = players[id].GetPosition(); BoundingSphere b = new BoundingSphere(player.GetPosition(), Constants.BOLLRADIE); Ray r = new Ray(shooterPos, dir); if (r.Intersects(b) != null) { player.ChangeLifeStatus(false); } } }
/// <summary> /// Mira si un objeto es intersecado por el rayo. /// </summary> /// <param name="objeto">Objeto que se desea mirar</param> /// <param name="r">Rayo del mouse.</param> /// <param name="intersectionDistance">Out: Distancia donde se intersecto el objeto.</param> /// <returns>True si el objeto es intersectado por el rayo, de lo contrario false.</returns> public static bool intersectObject(GameObject objeto, Ray r, out float intersectionDistance) { //Posiciona el bounding box del objeto en coordenadas del mundo. Matrix world = Matrix.CreateScale(objeto.Size) * Matrix.CreateTranslation(objeto.Position); BoundingBox box = new BoundingBox(); box.Max = Vector3.Transform(objeto.BoundingBox.Max, world); box.Min = Vector3.Transform(objeto.BoundingBox.Min, world); float? d; if ((d = r.Intersects(box)).HasValue == false) { intersectionDistance = 0f; return false; } intersectionDistance = d.Value; return true; }
public static Vector3 MouseToWorld(MouseState ms, Matrix view, Matrix projection, Matrix world) { Vector3 nearsource = new Vector3((float)ms.X, (float)ms.Y, 0f); Vector3 farsource = new Vector3((float)ms.X, (float)ms.Y, 1f); Vector3 nearPoint = GameContainer.Graphics.GraphicsDevice.Viewport.Unproject(nearsource, projection, view, world); Vector3 farPoint = GameContainer.Graphics.GraphicsDevice.Viewport.Unproject(farsource, projection, view, world); Vector3 direction = Vector3.Normalize(farPoint - nearPoint); Ray pickRay = new Ray(nearPoint, direction); float? distance = pickRay.Intersects(new Plane(Vector3.Backward, -4)); // hack if (distance.HasValue) { return pickRay.Position + (pickRay.Direction * distance.Value); } else { return Vector3.Zero; } }
public Vector3? GetCollisionPosition() { MouseState mousestate = Mouse.GetState(); Vector3 near = new Vector3(mousestate.X,mousestate.Y,0f); Vector3 far = new Vector3(mousestate.X,mousestate.Y,1f); Vector3 nearPoint = graphicDevice.Viewport.Unproject(near,camera.projection,camera.view,Matrix.Identity); Vector3 farPoint = graphicDevice.Viewport.Unproject(far,camera.projection,camera.view,Matrix.Identity); Vector3 Direction = farPoint - nearPoint; Direction.Normalize(); Ray pickRay = new Ray(nearPoint,Direction); Nullable<float> result = pickRay.Intersects(new Plane(Vector3.Up, 0f)); Vector3? ResultVector = Direction * result; Vector3? Collision = ResultVector + nearPoint; return Collision; }
public void interact() { bool v = false; foreach (GameObject go in Tools.Quick.game.Oom.onMapObject) { if(Vector3.Distance(go.getposition(),position)<Tools.Quick.distInteract) { Ray r = new Ray(position, Tools.Quick.game.camera.lookat); foreach (BoundingSphere bsph in go.getHitSphere()) { if(Convert.ToBoolean(r.Intersects(bsph))) { v = true; } } if (v) go.action(); } } }
public RayIntersectionResult RayIntersection(Ray ray) { var closestIntersection = new RayIntersectionResult{ distance = float.PositiveInfinity, face = null }; foreach (var face in Faces) { var plane = ConstructPlane(face); var intersectionDistance = ray.Intersects(plane); if (intersectionDistance.HasValue && intersectionDistance.Value < closestIntersection.distance) { var intersectionPoint = ray.Position + (ray.Direction * intersectionDistance.Value); if (IsPointOnFace(intersectionPoint, face)) { closestIntersection.distance = intersectionDistance.Value; closestIntersection.face = face; } } } if (closestIntersection.face == null) return null; return closestIntersection; }
/// <summary> /// Computes the intersection, if any, between a ray and the objects in the character's bounding box. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="length">Length of the ray to use in units of the ray's length.</param> /// <param name="earliestHit">Earliest intersection location and information.</param> /// <returns>Whether or not the ray hit anything.</returns> public bool RayCast(Ray ray, float length, out RayHit earliestHit) { earliestHit = new RayHit(); earliestHit.T = float.MaxValue; foreach (var collidable in character.Body.CollisionInformation.OverlappedCollidables) { //Check to see if the collidable is hit by the ray. float? t = ray.Intersects(collidable.BoundingBox); if (t != null && t < length) { //Is it an earlier hit than the current earliest? RayHit hit; if (collidable.RayCast(ray, length, SupportRayFilter, out hit) && hit.T < earliestHit.T) { earliestHit = hit; } } } if (earliestHit.T == float.MaxValue) return false; return true; }
public float? IntersectDistance(BoundingSphere sphere, Vector2 mouseLocation) { Matrix view = Global.view; Matrix projection = Global.projection; Viewport viewport = Global.GraphicsDevice.Viewport; Vector3 nearPoint = viewport.Unproject(new Vector3(mouseLocation.X, mouseLocation.Y, 0.0f), projection, view, Matrix.Identity); Vector3 farPoint = viewport.Unproject(new Vector3(mouseLocation.X, mouseLocation.Y, 1.0f), projection, view, Matrix.Identity); Vector3 direction = farPoint - nearPoint; direction.Normalize(); Ray mouseRay = new Ray(nearPoint, direction); return mouseRay.Intersects(sphere); //bounding box or frustum? }
public static VoxLocation? GetLevel(Ray camRay, VoxState state, int h) { camRay.Position -= new Vector3(state.World.worldMin.X * Region.WIDTH, 0, state.World.worldMin.Y * Region.DEPTH); VRay vr = new VRay(camRay.Position, camRay.Direction); Vector3I loc = vr.GetNextLocation(); // Check For World Intersect BoundingBox bb = new BoundingBox(new Vector3(0, h - 1, 0), new Vector3(VoxWorld.WIDTH * Region.WIDTH, h, VoxWorld.DEPTH * Region.DEPTH)); if(!camRay.Intersects(bb).HasValue) return null; // Move In World while(!IsInBounds(loc)) loc = vr.GetNextLocation(); // Move Through World while(IsInBounds(loc)) { VoxLocation vl = new VoxLocation(loc); Region region = state.World.regions[vl.RegionIndex]; ushort id = region.voxels[vl.VoxelIndex].ID; if(loc.Y == h) return vl; loc = vr.GetNextLocation(); } return null; }
public RayIntersectionResult RayIntersection(Ray ray) { var closestIntersection = new RayIntersectionResult { Distance = float.PositiveInfinity, Intersects = false }; for (int vindex = 0; vindex < indicies.Length; vindex += 3) { var p = indicies.Skip(vindex).Take(3).Select(i => verticies[i].Position).ToArray(); var plane = new Plane(p[0], p[1], p[2]); var intersectionDistance = ray.Intersects(plane); if (intersectionDistance.HasValue && intersectionDistance.Value < closestIntersection.Distance) { var intersectionPoint = ray.Position + (ray.Direction * intersectionDistance.Value); if (IsPointOnFace(intersectionPoint, p)) { closestIntersection.Distance = intersectionDistance.Value; closestIntersection.Intersects = true; var tc = indicies.Skip(vindex).Take(3).Select(i => verticies[i].TextureCoordinate).ToArray(); var bv = p.Select(v => v - intersectionPoint).ToArray(); var area = Vector3.Cross(p[0] - p[1], p[0] - p[2]).Length(); var baryArea = new float[] { Vector3.Cross(bv[1], bv[2]).Length() / area, Vector3.Cross(bv[2], bv[0]).Length() / area, Vector3.Cross(bv[0], bv[1]).Length() / area }; var uv = (tc[0] * baryArea[0]) + (tc[1] * baryArea[1]) + (tc[2] * baryArea[2]); closestIntersection.UV = uv; } } } return closestIntersection; }
// Algorithm copied from: http://www.cs.utah.edu/~awilliam/box/box.pdf // This is the non-optimized version of: /* * Ray-box intersection using IEEE numerical properties to ensure that the * test is both robust and efficient, as described in: * * Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley * "An Efficient and Robust Ray-Box Intersection Algorithm" * Journal of graphics tools, 10(1):49-54, 2005 * */ private bool ComputeEntryAndExitSignedDistances(Ray rtRay, out float tMin, out float tMax) { float yMin = float.MaxValue, zMin = float.MaxValue; float yMax = float.MinValue, zMax = float.MinValue; tMin = float.MaxValue; tMax = float.MinValue; if (rtRay.Direction.X > 0) { tMin = (Bounds.Min.X - rtRay.Origin.X) / rtRay.Direction.X; tMax = (Bounds.Max.X - rtRay.Origin.X) / rtRay.Direction.X; } else if (rtRay.Direction.X < 0) { tMin = (Bounds.Max.X - rtRay.Origin.X) / rtRay.Direction.X; tMax = (Bounds.Min.X - rtRay.Origin.X) / rtRay.Direction.X; } if (rtRay.Direction.Y > 0) { yMin = (Bounds.Min.Y - rtRay.Origin.Y) / rtRay.Direction.Y; yMax = (Bounds.Max.Y - rtRay.Origin.Y) / rtRay.Direction.Y; } else if (rtRay.Direction.Y < 0) { yMin = (Bounds.Max.Y - rtRay.Origin.Y) / rtRay.Direction.Y; yMax = (Bounds.Min.Y - rtRay.Origin.Y) / rtRay.Direction.Y; } if ((tMin > yMax) || (yMin > tMax)) { return(false); } if (yMin > tMin) { tMin = yMin; } if (yMax < tMax) { tMax = yMax; } if (rtRay.Direction.Z > 0) { zMin = (Bounds.Min.Z - rtRay.Origin.Z) / rtRay.Direction.Z; zMax = (Bounds.Max.Z - rtRay.Origin.Z) / rtRay.Direction.Z; } else if (rtRay.Direction.Z < 0) { zMin = (Bounds.Max.Z - rtRay.Origin.Z) / rtRay.Direction.Z; zMax = (Bounds.Min.Z - rtRay.Origin.Z) / rtRay.Direction.Z; } if ((tMin > zMax) || (zMin > tMax)) { return(false); } if (zMin > tMin) { tMin = zMin; } if (zMax < tMax) { tMax = zMax; } return(true); #if THIS_IS_USELESS // apparantly ray/BoundingBox returns _one_ of the intersection positions, but not always the closest one!! // USELESS!! Microsoft.Xna.Framework.Ray r = new Microsoft.Xna.Framework.Ray(rtRay.Origin, rtRay.Direction); float?dist = r.Intersects(Bounds); if (null == dist) { return(null); } float[] distances = new float[2]; if (Bounds.Contains(rtRay.Origin) == ContainmentType.Contains) { // originated from inside, let's find the back-end existing position Microsoft.Xna.Framework.Ray backRay = new Microsoft.Xna.Framework.Ray(rtRay.Origin, -rtRay.Direction); float?backDist = backRay.Intersects(Bounds); distances[0] = (float)-backDist; // this will be a negative value distances[1] = (float)dist; } else { // dist is the entry position, now find the exist position distances[0] = (float)dist; // advance the ray position without going out of this node r.Position = r.Position + (distances[0] + float.Epsilon) * r.Direction; if (Bounds.Contains(r.Position) == ContainmentType.Contains) { distances[1] = (float)r.Intersects(Bounds); } else { distances[1] = distances[0] + float.Epsilon; } } return(distances); #endif }
public bool RayCast(Microsoft.Xna.Framework.Ray ray, float maximumLength, IList <BroadPhaseEntry> outputIntersections) { if (maximumLength == float.MaxValue) { throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate infinite ray casts. Consider specifying a maximum length or using a broad phase which supports infinite ray casts."); } //Use 2d line rasterization. //Compute the exit location in the cell. //Test against each bounding box up until the exit value is reached. float length = 0; Int2 cellIndex; Vector3 currentPosition = ray.Position; Grid2DSortAndSweep.ComputeCell(ref currentPosition, out cellIndex); while (true) { float cellWidth = 1 / Grid2DSortAndSweep.cellSizeInverse; float nextT; //Distance along ray to next boundary. float nextTy; //Distance along ray to next boundary along y axis. float nextTz; //Distance along ray to next boundary along z axis. //Find the next cell. if (ray.Direction.Y > 0) { nextTy = ((cellIndex.Y + 1) * cellWidth - currentPosition.Y) / ray.Direction.Y; } else if (ray.Direction.Y < 0) { nextTy = ((cellIndex.Y) * cellWidth - currentPosition.Y) / ray.Direction.Y; } else { nextTy = 10e10f; } if (ray.Direction.Z > 0) { nextTz = ((cellIndex.Z + 1) * cellWidth - currentPosition.Z) / ray.Direction.Z; } else if (ray.Direction.Z < 0) { nextTz = ((cellIndex.Z) * cellWidth - currentPosition.Z) / ray.Direction.Z; } else { nextTz = 10e10f; } bool yIsMinimum = nextTy < nextTz; nextT = yIsMinimum ? nextTy : nextTz; //Grab the cell that we are currently in. GridCell2D cell; if (owner.cellSet.TryGetCell(ref cellIndex, out cell)) { float endingX; if (ray.Direction.X < 0) { endingX = currentPosition.X; } else { endingX = currentPosition.X + ray.Direction.X * nextT; } //To fully accelerate this, the entries list would need to contain both min and max interval markers. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list. //Consider some giant bounding box that spans the entire list. for (int i = 0; i < cell.entries.count && cell.entries.Elements[i].item.boundingBox.Min.X <= endingX; i++) //TODO: Try additional x axis pruning? { float?intersects; var item = cell.entries.Elements[i].item; ray.Intersects(ref item.boundingBox, out intersects); if (intersects != null && intersects < maximumLength && !outputIntersections.Contains(item)) { outputIntersections.Add(item); } } } //Move the position forward. length += nextT; if (length > maximumLength) //Note that this catches the case in which the ray is pointing right down the middle of a row (resulting in a nextT of 10e10f). { break; } Vector3 offset; Vector3.Multiply(ref ray.Direction, nextT, out offset); Vector3.Add(ref offset, ref currentPosition, out currentPosition); if (yIsMinimum) { if (ray.Direction.Y < 0) { cellIndex.Y -= 1; } else { cellIndex.Y += 1; } } else if (ray.Direction.Z < 0) { cellIndex.Z -= 1; } else { cellIndex.Z += 1; } } return(outputIntersections.Count > 0); }
public Nullable <float> Intersects(Ray ray) { return(ray.Intersects(this)); }