InteractNode GetInteractNode(Microsoft.Xna.Framework.Ray lookRay) { float collisionDist; CollisionSkin skin = null; Vector3 pos, normal; Segment seg = new Segment(lookRay.Position, lookRay.Direction * MAX_INTERACT_DIST); scene.GetPhysicsEngine().CollisionSystem.SegmentIntersect(out collisionDist, out skin, out pos, out normal, seg, pred); float bestDist = (skin != null) ? collisionDist : float.PositiveInfinity; InteractNode bestNode = null; for (int i = 0; i < interactables.Count; i++) { InteractObject interactObj = interactables[i].GetInteractObject(); BoundingBox bounds = interactObj.Transformation.TransformBounds(interactObj.GetMesh().GetBounds()); float? intersection = lookRay.Intersects(bounds); if (intersection.HasValue) { float dist = intersection.Value; if (dist < bestDist && dist <= MAX_INTERACT_DIST) { InteractNode node = interactObj.GetInteractNode(); if (node.IsEnabled()) { bestDist = dist; bestNode = interactObj.GetInteractNode(); } } } } return bestNode; }
Vector3 GetTerrainVector(Microsoft.Xna.Framework.Ray mRay) { Vector3 pos = new Vector3(0, 0, 0); Nullable<float> curDist = 10000f; for (int i = 0; i < terrainEngine.vertices.Length - 3; i += 3) { Nullable<float> rayDist; Vector3 firstPos; firstPos = terrainEngine.vertices[i].Position; BoundingSphere sphere = new BoundingSphere(firstPos, 2); rayDist = mRay.Intersects(sphere); if (rayDist != null) { if (rayDist < curDist) { curDist = rayDist; pos = sphere.Center; posList.Add(pos); } } } return pos; }
public override HitType GetHit(Microsoft.Xna.Framework.Ray ray, float maxDistance, out float hitDistance) { BoundingBox hitBounds = model.GetHitBounds(); float? dist; ray.Intersects(ref hitBounds, out dist); if (dist.HasValue && dist.Value <= maxDistance) { float bestDist = float.PositiveInfinity; HitType bestHit = HitType.None; SortedList<HitType, BoundingBox> hitBoxes = model.GetHitBoxes(); for (int i = 0; i < hitBoxes.Count; i++) { HitType currHitType = hitBoxes.Keys[i]; float? hitDist; BoundingBox bounds = hitBoxes[currHitType]; ray.Intersects(ref bounds, out hitDist); if (hitDist.HasValue && hitDist.Value <= maxDistance && hitDist.Value < bestDist) { bestDist = hitDist.Value; bestHit = currHitType; } } hitDistance = bestDist; return bestHit; } hitDistance = 0; return HitType.None; }
public void GetData(Microsoft.Xna.Framework.Rectangle playerBounds, Color[] result, Color[] buffer, int startIndex, int count) { Point currentPoint = new Point(0, 0); MapSegment segment1 = null; MapSegment segment2 = null; Rectangle segment1Rect = Rectangle.Empty; Rectangle segment2Rect = Rectangle.Empty; foreach (MapSegment seg in this.segments) { Rectangle textureRect = new Rectangle(currentPoint.X, currentPoint.Y, seg.MapTexture.Width, seg.MapTexture.Height); if (playerBounds.Intersects(textureRect)) { if (segment1 == null) { segment1 = seg; segment1Rect = textureRect; } else if (segment2 == null) { segment2 = seg; segment2Rect = textureRect; } else { throw new ArgumentException("Goose object intersects more than two level segments. Please increase the size of the segments to avoid this."); } } currentPoint.X += seg.DisplayTexture.Width; } for (int i = 0; i < result.Length; i++) { result[i] = ColorConsts.SolidWallColor; } if (segment1 != null) { Texture2D texture = segment1.MapTexture; Rectangle bounds = Intersect(playerBounds, segment1Rect); bounds.Offset(-segment1Rect.X, -segment1Rect.Y); lock (syncObj) { if (segment2 == null) { texture.GetData<Color>(0, bounds, result, 0, bounds.Width * bounds.Height); return; } else { texture.GetData<Color>(0, bounds, buffer, 0, bounds.Width * bounds.Height); } } bounds.Offset(segment1Rect.Location); MapData(playerBounds, bounds, result, buffer); } if (segment2 != null) { Texture2D texture = segment2.MapTexture; Rectangle bounds = Intersect(playerBounds, segment2Rect); bounds.Offset(-segment2Rect.X, -segment2Rect.Y); lock (syncObj) { texture.GetData<Color>(0, bounds, buffer, 0, bounds.Width * bounds.Height); } bounds.Offset(segment2Rect.Location); MapData(playerBounds, bounds, result, buffer); } }
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 void GetEntries(Microsoft.Xna.Framework.BoundingSphere boundingShape, IList<BroadPhaseEntry> overlaps) { //Create a bounding box based on the bounding sphere. //Compute the min and max of the bounding box. //Loop through the cells and select bounding boxes which overlap the x axis. #if !WINDOWS Vector3 offset = new Vector3(); #else Vector3 offset; #endif offset.X = boundingShape.Radius; offset.Y = offset.X; offset.Z = offset.Y; BoundingBox box; Vector3.Add(ref boundingShape.Center, ref offset, out box.Max); Vector3.Subtract(ref boundingShape.Center, ref offset, out box.Min); Int2 min, max; Grid2DSortAndSweep.ComputeCell(ref box.Min, out min); Grid2DSortAndSweep.ComputeCell(ref box.Max, out max); for (int i = min.Y; i <= max.Y; i++) { for (int j = min.Z; j <= max.Z; j++) { //Grab the cell that we are currently in. Int2 cellIndex; cellIndex.Y = i; cellIndex.Z = j; GridCell2D cell; if (owner.cellSet.TryGetCell(ref cellIndex, out cell)) { //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 k = 0; k < cell.entries.count && cell.entries.Elements[k].item.boundingBox.Min.X <= box.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test. { bool intersects; var item = cell.entries.Elements[k].item; boundingShape.Intersects(ref item.boundingBox, out intersects); if (intersects && !overlaps.Contains(item)) { overlaps.Add(item); } } } } } }