/// <summary> /// 光线追踪测试 /// </summary> /// <param name="ray"></param> /// <returns></returns> public override RayCastResult Intersection(Ray ray, float nowbest) { // 包围盒测试失败 { (bool happened, float mint) = BoundBox.Intersection(ray); if (!happened || mint > nowbest) // 未相交 或 当前最小解已不是最优 { return(null); } } RayCastResult result = BVH.Intersection(ray, float.MaxValue); if (result != null) { result.material = Material; if (result.internalPoint) { result.IOR = 1.0f; } else { result.IOR = Material.Refraction.IOR; } } return(result); }
unsafe RayCastResult GetRayCastResultFromNative(NativeRayCastResult *native) { RayCastResult result = new RayCastResult(); if (native->shape != IntPtr.Zero) { result.Shape = PhysXPhysicsWorld.Instance.GetShapeByNativePointer(native->shape); result.Position = native->worldImpact; result.Normal = native->worldNormal; result.Distance = native->distance; if (result.Shape.ShapeType == Shape.Type.Mesh) { MeshShape meshShape = (MeshShape)result.Shape; if (meshShape.MeshType != MeshShape.MeshTypes.ConvexHullDecomposition) { result.TriangleID = native->faceID; } } else if (result.Shape.ShapeType == Shape.Type.HeightField) { result.TriangleID = native->faceID; } else { result.TriangleID = 0; } } return(result); }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present /// in the entry, this filter will be passed into inner ray casts.</param> /// <param name="result">Hit data, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayCastResult result) { var outputOverlappedElements = PhysicsResources.GetCollidableList(); BoundingBox boundingBox; castShape.GetSweptBoundingBox(ref startingTransform, ref sweep, out boundingBox); CollidableTree.GetOverlaps(boundingBox, outputOverlappedElements); result = new RayCastResult(); result.HitData.T = Fix64.MaxValue; for (int i = 0; i < outputOverlappedElements.Count; ++i) { RayHit hit; if (outputOverlappedElements.Elements[i].ConvexCast(castShape, ref startingTransform, ref sweep, filter, out hit)) { if (hit.T < result.HitData.T) { result.HitData = hit; result.HitObject = outputOverlappedElements.Elements[i]; } } } PhysicsResources.GiveBack(outputOverlappedElements); return(result.HitData.T < Fix64.MaxValue); }
/// <summary> /// Move vessel up /// </summary> /// <param name="v"></param> private static void MoveUp(Vessel v) { v.ResetCollisionIgnores(); // TODO: Try DisableSuspension() on wheels float upMovement = 0.0f; float vesselHeight = bounds.topLength + bounds.bottomLength; Vector3 up = (v.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; while (upMovement < maxUpMovement) { RayCastResult alt = GetRaycastAltitude(v, bounds.bottomPoint + up * vesselHeight, rayCastMask); // mask: ground only if (alt.altitude - vesselHeight < minDownMovement) { v.Translate(up * upMovementStep); upMovement += upMovementStep; } else { break; } } }
private float TestObjectVisibility(GameObject go) { int nSuccess = 0; var rayCastTargets = GetRayCastTargets(go); IList <Vector3> testPoints = rayCastTargets.GetTargetPoints(); for (int i = 0; i < testPoints.Count; i++) { var testPoint = testPoints[i]; var result = new RayCastResult(); result.Go = go; result.TestPoint = testPoint; result.IsObstructed = false; if (IsInLineOfSight(go, testPoint, out var obstructionPoint)) { nSuccess++; rayCastTargets.SetIsTargetVisible(i, true); } else { result.IsObstructed = true; result.ObstructionPoint = obstructionPoint; rayCastTargets.SetIsTargetVisible(i, false); } _raycastResults.Add(result); } return(nSuccess / (float)testPoints.Count); }
public List <RayCastResult> CastRaysAroundPosition(Vector3D position, Vector3D forward, double distance, int raysCount) { var results = new List <RayCastResult>(); for (int i = 0; i < raysCount; i++) { var rotation = MatrixD.CreateRotationY((2 * Math.PI / raysCount) * i); var direction = Vector3D.Rotate(forward, rotation); var from = position; var to = from + distance * direction; MyAPIGateway.Physics.CastRay(from, to, out var hitInfo); var result = new RayCastResult() { From = from, To = to, MaxDistance = distance, }; if (hitInfo != null) { result.IsHit = true; result.HitDistance = hitInfo.Fraction * distance; result.HitPosition = from + result.HitDistance.Value * direction; } results.Add(result); } return(results); }
/// <summary> /// Move vessel down /// </summary> /// <param name="v"></param> private static void MoveDown(Vessel v) { bounds.findBoundPoints(); RayCastResult alt = GetRaycastAltitude(v, bounds.bottomPoint, rayCastMask); RayCastResult alt2 = GetRaycastAltitude(v, bounds.topPoint, rayCastMask); Vector3 referencePoint = bounds.bottomPoint; if (alt.collider != alt2.collider) { minDownMovement = lastResortAltitude; if (alt2.altitude < alt.altitude) { referencePoint = bounds.topPoint; } } // Re-cast raycast including parts into the mask alt = GetRaycastAltitude(v, referencePoint, rayCastExtendedMask); float downMovement = alt.altitude; Vector3 up = (v.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; if (downMovement < minDownMovement + Configuration.HeightOffset) { return; } downMovement -= minDownMovement; v.Translate(-downMovement * (Vector3d)up); }
public override void Update(float time, float dTime) { MouseUsed = Window.MouseLeftDown; Vector3 rayStart = EngineBase.Renderer.Unproject(Window.MousePos, 0f); Vector3 rayEnd = EngineBase.Renderer.Unproject(Window.MousePos, 1f); Vector3 dir = (rayEnd - rayStart).Normalized(); Editor.Profiler.Begin("RAYCAST"); RayCastResult rc = level.Collisions.RayCast(rayStart, dir); Editor.Profiler.End("RAYCAST"); if (rc.Hit) { level.AddNode(terrainEditCursor); terrainEditCursor.Position = rc.PositionSnapped; if (Window.MouseLeftDown) { applyBrush(rc.Position); } } else { level.RemoveNode(terrainEditCursor); } base.Update(time, dTime); }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="result">Hit data, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayCastResult result) { var outputOverlappedElements = Resources.GetCollidableList(); var rayHits = Resources.GetRayHitList(); BoundingBox boundingBox; Toolbox.GetExpandedBoundingBox(ref castShape, ref startingTransform, ref sweep, out boundingBox); CollidableTree.GetOverlaps(boundingBox, outputOverlappedElements); result = new RayCastResult(); result.HitData.T = float.MaxValue; for (int i = 0; i < outputOverlappedElements.count; ++i) { RayHit hit; if (outputOverlappedElements.Elements[i].ConvexCast(castShape, ref startingTransform, ref sweep, out hit)) { if (hit.T < result.HitData.T) { result.HitData = hit; result.HitObject = outputOverlappedElements.Elements[i]; } } } Resources.GiveBack(rayHits); Resources.GiveBack(outputOverlappedElements); return(result.HitData.T < float.MaxValue); }
float testObjectVisibility(GameObject go, RayCastTargets targets) { int nSuccess = 0; var rayCastTargets = getRayCastTargets(go); List <Vector2> testPoints = rayCastTargets.getTargetPoints(); for (int i = 0; i < testPoints.Count; i++) { var testPoint = testPoints[i]; Vector2 obstructionPoint; var result = new RayCastResult(); result.go = go; result.testPoint = testPoint; result.isObstructed = false; if (isInLineOfSight(go, testPoint, out obstructionPoint)) { nSuccess++; rayCastTargets.SetIsTargetVisible(i, true); } else { result.isObstructed = true; result.obstructionPoint = obstructionPoint; rayCastTargets.SetIsTargetVisible(i, false); } raycastResults.Add(result); } return(nSuccess / (float)testPoints.Count); }
private static bool IsValid(RayCastResult r, List <NiAVObject> ignore) { var havokObj = r.HavokObject; if (havokObj != IntPtr.Zero) { uint flags = Memory.ReadUInt32(havokObj + 0x2C) & 0x7F; ulong mask = (ulong)1 << (int)flags; if ((RaycastMask & mask) == 0) { return(false); } } if (ignore != null && ignore.Count != 0) { var obj = r.Object; if (obj != null) { for (int i = 0; i < ignore.Count; i++) { var o = ignore[i]; if (o != null && o.Equals(obj)) { return(false); } } } } return(true); }
public bool RayCastAgainstEntity(Vector3 from, Vector3 to, out Vector3 pos, out float distance, out Entity hitEntity) { hitEntity = null; var dir = to - from; var dist = dir.Length(); var ndir = dir.Normalized(); distance = float.MaxValue; Ray ray = new Ray(from, ndir); pos = to; var rcr = new RayCastResult(); var bRay = MathConverter.Convert(ray); bool result = PhysSpace.RayCast(bRay, dist, out rcr); if (!result) { return(false); } var convex = rcr.HitObject as ConvexCollidable; pos = MathConverter.Convert(rcr.HitData.Location); if (convex != null) { hitEntity = convex.Entity.Tag as Entity; } distance = rcr.HitData.T; return(true); }
/// <summary> /// A convex-shaped ray-trace method for the special case of needing to handle Voxel collision types. /// </summary> /// <param name="shape">The shape of the convex ray source object.</param> /// <param name="start">The start of the ray.</param> /// <param name="dir">The normalized vector of the direction of the ray.</param> /// <param name="len">The length of the ray.</param> /// <param name="considerSolid">What materials are 'solid'.</param> /// <param name="filter">A function to identify what entities should be filtered out.</param> /// <param name="rayHit">Outputs the result of the ray trace.</param> /// <returns>Whether there was a collision.</returns> public bool SpecialCaseConvexTrace(ConvexShape shape, Location start, Location dir, double len, MaterialSolidity considerSolid, Func <BroadPhaseEntry, bool> filter, out RayCastResult rayHit) { RigidTransform rt = new RigidTransform(start.ToBVector(), BEPUutilities.Quaternion.Identity); BEPUutilities.Vector3 sweep = (dir * len).ToBVector(); RayCastResult best = new RayCastResult(new RayHit() { T = len }, null); bool hA = false; if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID)) { if (PhysicsWorld.ConvexCast(shape, ref rt, ref sweep, filter, out RayCastResult rcr)) { best = rcr; hA = true; } } if (considerSolid == MaterialSolidity.FULLSOLID) { rayHit = best; return(hA); } sweep = dir.ToBVector(); AABB box = new AABB() { Min = start, Max = start }; box.Include(start + dir * len); foreach (KeyValuePair <Vector3i, Chunk> chunk in LoadedChunks) { if (chunk.Value == null || chunk.Value.FCO == null) { continue; } if (!box.Intersects(new AABB() { Min = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE, Max = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE) })) { continue; } if (chunk.Value.FCO.ConvexCast(shape, ref rt, ref sweep, len, considerSolid, out RayHit temp)) { hA = true; if (temp.T < best.HitData.T) { best.HitData = temp; best.HitObject = chunk.Value.FCO; } } } rayHit = best; return(hA); }
/// <summary> /// A ray-trace method for the special case of needing to handle Voxel collision types. /// </summary> /// <param name="start">The start of the ray.</param> /// <param name="dir">The normalized vector of the direction of the ray.</param> /// <param name="len">The length of the ray.</param> /// <param name="considerSolid">What materials are 'solid'.</param> /// <param name="filter">A function to identify what entities should be filtered out.</param> /// <param name="rayHit">Outputs the result of the ray trace.</param> /// <returns>Whether there was a collision.</returns> public bool SpecialCaseRayTrace(Location start, Location dir, double len, MaterialSolidity considerSolid, Func <BroadPhaseEntry, bool> filter, out RayCastResult rayHit) { Ray ray = new Ray(start.ToBVector(), dir.ToBVector()); RayCastResult best = new RayCastResult(new RayHit() { T = len }, null); bool hA = false; if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID)) { if (PhysicsWorld.RayCast(ray, len, filter, out RayCastResult rcr)) { best = rcr; hA = true; } } if (considerSolid == MaterialSolidity.FULLSOLID) { rayHit = best; return(hA); } AABB box = new AABB() { Min = start, Max = start }; box.Include(start + dir * len); foreach (Dictionary <Vector3i, Chunk> chkmap in LoadedChunks) { foreach (Chunk chunk in chkmap.Values) { if (chunk == null || chunk.FCO == null) { continue; } if (!box.Intersects(new AABB() { Min = chunk.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE, Max = chunk.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE) })) { continue; } if (chunk.FCO.RayCast(ray, len, null, considerSolid, out RayHit temp)) { hA = true; if (temp.T < best.HitData.T) { best.HitData = temp; best.HitObject = chunk.FCO; } } } } rayHit = best; return(hA); }
private static bool BlockProjectile(RayCastResult result) { return(ObjectsBulletCantPass.Contains(result.HitObject.Name) // Filter objects bullet can passthrough like ladder // Not an optimal solution: https://www.mythologicinteractiveforums.com/viewtopic.php?f=31&t=3952&p=23291#p23291 || (result.HitObject.GetCollisionFilter().BlockExplosions && !ObjectsBulletCanDestroy.Contains(result.HitObject.Name))); }
protected override RayCastResult[] OnRayCastPiercing(Ray ray, int contactGroup) { if (float.IsNaN(ray.Origin.X)) { Log.Fatal("PhysicsWorld.RayCast: Single.IsNaN(ray.Origin.X)"); } if (float.IsNaN(ray.Direction.X)) { Log.Fatal("PhysicsWorld.RayCast: Single.IsNaN(ray.Direction.X)"); } if (ray.Direction == Vec3.Zero) { return(emptyPiercingRayCastResult); } Vec3 dirNormal = ray.Direction; float length = dirNormal.Normalize(); Ode.dGeomRaySet(rayCastGeomID, ray.Origin.X, ray.Origin.Y, ray.Origin.Z, dirNormal.X, dirNormal.Y, dirNormal.Z); Ode.dGeomRaySetLength(rayCastGeomID, length); int count; IntPtr data; Ode.DoRayCastPiercing(neoAxisAdditionsID, contactGroup, out count, out data); if (count == 0) { return(emptyPiercingRayCastResult); } RayCastResult[] array = new RayCastResult[count]; unsafe { Ode.RayCastResult *pointer = (Ode.RayCastResult *)data; for (int n = 0; n < count; n++) { RayCastResult result = new RayCastResult(); result.Shape = shapesDictionary[pointer->shapeDictionaryIndex].shape; result.Position = Convert.ToNet(pointer->position); result.Normal = Convert.ToNet(pointer->normal); result.Distance = pointer->distance; result.TriangleID = pointer->triangleID; array[n] = result; pointer++; } } //sort by distance ArrayUtils.SelectionSort(array, rayCastResultDistanceComparer); return(array); }
void RenderEntityOverCursor(Camera camera) { Vec2 mouse = renderTarget.GetFloatMousePosition(); _mouseOver = null; if (mouse.X < 0 || mouse.X > 1 || mouse.Y < 0 || mouse.Y > 1) { _worldViewModel.ClearMouseOverEntity(); } else { // Find entity under cursor of mouse Ray ray = camera.GetCameraToViewportRay(mouse); Map.Instance.GetObjects(ray, delegate(MapObject obj, float scale) { if (obj.UserData == null || !(obj.UserData is EntityModel)) { return(true); } _mouseOver = obj; return(false); }); if (_mouseOver != null) { // Put a yellow box around it and a tooltip camera.DebugGeometry.Color = new ColorValue(1, 1, 0); camera.DebugGeometry.AddBounds(_mouseOver.MapBounds); _worldViewModel.SetMouseOverEntity(((EntityModel)_mouseOver.UserData).Id); } else { _worldViewModel.ClearMouseOverEntity(); } RayCastResult result = PhysicsWorld.Instance.RayCast(ray, (int)ContactGroup.CastOnlyCollision); _mouseIntersection = result.Position; if (result.Shape != null) { camera.DebugGeometry.Color = new ColorValue(1, 0, 0); camera.DebugGeometry.AddSphere(new Sphere(result.Position, 0.2f)); } } SetToolTipString(); // Show all selected entities with a blue box around them // except MouseOver as it will be yellow camera.DebugGeometry.Color = new ColorValue(0.5f, 0.5f, 1); foreach (MapObject mo in _worldViewModel.SelectedEntities .Select(evm => Entities.Instance.GetByName(evm.Entity.Id.ToString())) .OfType <MapObject>() .Where(mo => mo != _mouseOver)) { camera.DebugGeometry.AddBounds(mo.MapBounds); } }
public bool RayCast(Vector3 pos, Vector3 dir, float dst, out RayCastResult result) { pos = TransformPointToLocalSpace(pos); dir = TransformDirToLocalSpace(dir); const float step = 0.1f; int prevX = int.MaxValue; int prevY = int.MaxValue; int prevZ = int.MaxValue; Vector3 stepOffset = dir.normalized * step; for (int i = 0; i < dst / step; i++) { int x = (int)Mathf.Floor(pos.x); int y = (int)Mathf.Floor(pos.y); int z = (int)Mathf.Floor(pos.z); if (x != prevX || y != prevY || z != prevZ) { for (int zo = 0; zo < 2; zo++) { for (int yo = 0; yo < 2; yo++) { for (int xo = 0; xo < 2; xo++) { int bx = x + xo; int by = y + yo; int bz = z + zo; var chunk = GetChunk(ChunkPos.FromVoxel(bx, by, bz, ChunkSize)); if (chunk != null) { int material = chunk.GetMaterial(((bx % ChunkSize) + ChunkSize) % ChunkSize, ((by % ChunkSize) + ChunkSize) % ChunkSize, ((bz % ChunkSize) + ChunkSize) % ChunkSize); if (material != 0) { result = new RayCastResult(new Vector3(x, y, z), new Vector3(prevX, prevY, prevZ), chunk); return(true); } } } } } prevX = x; prevY = y; prevZ = z; } pos += stepOffset; } result = new RayCastResult(Vector3.zero, Vector3.zero, null); return(false); }
/// <summary> /// /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="normal"></param> /// <param name="pos"></param> /// <returns></returns> public bool RayCastAgainstAll(Vector3 from, Vector3 to, out Vector3 normal, out Vector3 pos, out Entity hitEnt, Entity entToSkip = null) { var dir = to - from; var dist = dir.Length(); var ndir = dir.Normalized(); Ray ray = new Ray(from, ndir); normal = Vector3.Zero; pos = to; hitEnt = null; Func <BroadPhaseEntry, bool> filterFunc = delegate(BroadPhaseEntry bpe) { if (entToSkip == null) { return(true); } ConvexCollidable cc = bpe as ConvexCollidable; if (cc == null) { return(true); } Entity ent = cc.Entity.Tag as Entity; if (ent == null) { return(true); } if (ent == entToSkip) { return(false); } return(true); }; var rcr = new RayCastResult(); bool result = Space.RayCast(ray, dist, filterFunc, out rcr); if (!result) { return(false); } var convex = rcr.HitObject as ConvexCollidable; normal = rcr.HitData.Normal.Normalized(); pos = rcr.HitData.Location; hitEnt = (convex == null) ? null : convex.Entity.Tag as Entity; return(true); }
public override RayCastResult Intersection(Ray ray, float nowbest) { { float distance = (Position - ray.Origin).Length(); if (nowbest + R < distance) { return(null); } } Vector3f A = ray.Origin, B = ray.Direction, C = Position; Float a = Vector3f.Dot(B, B); Float b = Vector3f.Dot(B, (A - C)) * 2.0f; Float c = (A - C).LengthSquared() - R * R; float drt = b * b - 4 * a * c; if (drt < 0) { return(null); } drt = Math.Sqrt(drt); float x1 = (-b + drt) / a / 2; float x2 = (-b - drt) / a / 2; if (x1 < 0 && x2 < 0) { return(null); } float d; if (x1 > 0 && x2 > 0) { d = Math.Max(x1, x2); } else if (x1 > 0) { d = x1; } else { d = x2; } RayCastResult result = new RayCastResult(); //result.happened = true; result.obj = this; result.material = Material; result.coords = ray.Origin + ray.Direction * d; result.distance = d; result.normal = Vector3f.Normalize(result.coords - Position); return(result); }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present /// in the entry, this filter will be passed into inner ray casts.</param> /// <param name="result">Data and hit object from the first impact, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayCastResult result) { CompoundChild hitChild; RayHit rayHit; bool hit = ConvexCast(castShape, ref startingTransform, ref sweep, filter, out rayHit, out hitChild); result = new RayCastResult { HitData = rayHit, HitObject = hitChild.CollisionInformation }; return(hit); }
/// <summary> /// Tests a ray against the compound. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param> /// <param name="rayHit">Hit data and the hit child collidable, if any.</param> /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present /// in the entry, this filter will be passed into inner ray casts.</param> /// <returns>Whether or not the ray hit the entry.</returns> public bool RayCast(Ray ray, float maximumLength, Func <BroadPhaseEntry, bool> filter, out RayCastResult rayHit) { RayHit hitData; CompoundChild hitChild; bool hit = RayCast(ray, maximumLength, filter, out hitData, out hitChild); rayHit = new RayCastResult { HitData = hitData, HitObject = hitChild.CollisionInformation }; return(hit); }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="result">Data and hit object from the first impact, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayCastResult result) { CompoundChild hitChild; RayHit rayHit; bool hit = ConvexCast(castShape, ref startingTransform, ref sweep, out rayHit, out hitChild); result = new RayCastResult { HitData = rayHit, HitObject = hitChild.CollisionInformation }; return(hit); }
/// <summary> /// Tests a ray against the compound. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param> /// <param name="rayHit">Hit data and the hit child collidable, if any.</param> /// <returns>Whether or not the ray hit the entry.</returns> public bool RayCast(Ray ray, Fix64 maximumLength, out RayCastResult rayHit) { RayHit hitData; CompoundChild hitChild; bool hit = RayCast(ray, maximumLength, out hitData, out hitChild); rayHit = new RayCastResult { HitData = hitData, HitObject = hitChild.CollisionInformation }; return(hit); }
private void Trackball_GetOrbitRadius(object sender, GetOrbitRadiusArgs e) { //TODO: e should also pass in the mouse click point, so there is camera position, and click position, this // listener can decide which they want (I can't reuse the same direction, because of the perspective) RayCastResult result = _world.CastRay(e.Position, e.Direction, 30d, World.BodyFilterType.ExcludeBodies); if (result != null) { e.Result = result.HitDistance; } }
static int SortRayCastResultsMethod(RayCastResult r1, RayCastResult r2) { if (r1.Distance < r2.Distance) { return(-1); } if (r1.Distance > r2.Distance) { return(1); } return(0); }
public override RayCastResult Intersection(Ray ray, float nowbest) { if (ray.OriginObject == this) { return(null); } { (bool happened, Float mint) = BoundBox.Intersection(ray); if (!happened || mint > nowbest) // 未相交 或 当前最小解已不是最优 { return(null); } } Float u, v, t_tmp = 0; Vector3f pvec = Vector3f.Cross(ray.Direction, e2); // S1 Float det = Vector3f.Dot(e1, pvec); Float det_inv = 1.0f / det; Vector3f tvec = ray.Origin - v0; // S u = Vector3f.Dot(tvec, pvec) * det_inv; if (u < 0 || u > 1) { return(null); } Vector3f qvec = Vector3f.Cross(tvec, e1); // S2 v = Vector3f.Dot(ray.Direction, qvec) * det_inv; if (v < 0 || u + v > 1) { return(null); } t_tmp = Vector3f.Dot(e2, qvec) * det_inv; if (t_tmp < 0) { return(null); } RayCastResult result = new RayCastResult(); result.distance = t_tmp; result.obj = this; result.coords = ray.Origin + t_tmp * ray.Direction; result.uv = new Vector2f(u, v); result.normal = Tools.UVMerge(u, v, n0, n1, n2); result.internalPoint = (Vector3f.Dot(result.normal, ray.Direction) > 0); if (result.internalPoint) { result.normal = -result.normal; } return(result); }
OnCalculateIrradianceVolumeCell(Vec3 position) { tempCellLightItemList.Clear(); foreach (MyLight light in lights) { //simple culling method. need use grid if (!light.Bounds.IsContainsPoint(position)) { continue; } //calculate illumination float illumination = light.GetIllumination(position); if (illumination <= .00001f) { continue; } //check for direct visibility bool shadowed = false; if (calculateShadows) { Ray ray = light.GetCheckVisibilityRay(position); RayCastResult result = physicsScene.RayCast(ray, contactGroup); if (result.Shape != null) { shadowed = true; } } float power = 1; if (shadowed) { float coef = 1.0f - (shadowColor.Red + shadowColor.Green + shadowColor.Blue) / 3.0f; power *= coef; } if (power <= .005f) { continue; } tempCellLightItemList.Add(new IrradianceVolumeCellLightItem(light.Data, power)); } return(tempCellLightItemList.ToArray()); }
/// <summary> /// Get altitude of a RayCast /// </summary> /// <param name="v"></param> /// <param name="originPoint"></param> /// <param name="layerMask"></param> /// <returns></returns> internal static RayCastResult GetRaycastAltitude(Vessel v, Vector3 originPoint, int layerMask) { RaycastHit hit; Vector3 up = (v.transform.position - FlightGlobals.currentMainBody.transform.position).normalized; RayCastResult result = new RayCastResult(); if (Physics.Raycast(originPoint, -up, out hit, v.vesselRanges.landed.unload, layerMask)) { result.altitude = Vector3.Project(hit.point - originPoint, up).magnitude; result.collider = hit.collider; } return(result); }
} // Raycast /// <summary> /// Indicates if a ray intercepts a game object. /// </summary> public static GameObject3D Raycast(Ray ray, float distance, out RayCastResult result) { GameObject3D go = null; if (Scene.RayCast(ray, distance, out result)) { var entityCollision = result.HitObject as EntityCollidable; if (entityCollision != null) { go = (GameObject3D)entityCollision.Entity.Tag; } } return(go); } // Raycast
/// <summary> /// Tests a ray against the collidable. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param> /// <param name="result">Hit data, if any.</param> /// <returns>Whether or not the ray hit the entry.</returns> public bool RayCast(Ray ray, float maximumLength, out RayCastResult result) { var outputOverlappedElements = PhysicsResources.GetCollidableList(); CollidableTree.GetOverlaps(ray, maximumLength, outputOverlappedElements); result = new RayCastResult(); result.HitData.T = float.MaxValue; for (int i = 0; i < outputOverlappedElements.Count; ++i) { RayHit hit; if (outputOverlappedElements.Elements[i].RayCast(ray, maximumLength, out hit)) { if (hit.T < result.HitData.T) { result.HitData = hit; result.HitObject = outputOverlappedElements.Elements[i]; } } } PhysicsResources.GiveBack(outputOverlappedElements); return result.HitData.T < float.MaxValue; }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="result">Hit data, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayCastResult result) { var outputOverlappedElements = PhysicsResources.GetCollidableList(); BoundingBox boundingBox; castShape.GetSweptBoundingBox(ref startingTransform, ref sweep, out boundingBox); CollidableTree.GetOverlaps(boundingBox, outputOverlappedElements); result = new RayCastResult(); result.HitData.T = float.MaxValue; for (int i = 0; i < outputOverlappedElements.Count; ++i) { RayHit hit; if (outputOverlappedElements.Elements[i].ConvexCast(castShape, ref startingTransform, ref sweep, out hit)) { if (hit.T < result.HitData.T) { result.HitData = hit; result.HitObject = outputOverlappedElements.Elements[i]; } } } PhysicsResources.GiveBack(outputOverlappedElements); return result.HitData.T < float.MaxValue; }
protected override RayCastResult[] OnRayCastPiercing( Ray ray, int contactGroup ) { if( float.IsNaN( ray.Origin.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Origin.X)" ); if( float.IsNaN( ray.Direction.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Direction.X)" ); if( ray.Direction == Vec3.Zero ) return emptyPiercingRayCastResult; Vec3 dirNormal = ray.Direction; float length = dirNormal.Normalize(); Ode.dGeomRaySet( rayCastGeomID, ray.Origin.X, ray.Origin.Y, ray.Origin.Z, dirNormal.X, dirNormal.Y, dirNormal.Z ); Ode.dGeomRaySetLength( rayCastGeomID, length ); int count; IntPtr data; Ode.DoRayCastPiercing( neoAxisAdditionsID, contactGroup, out count, out data ); if( count == 0 ) return emptyPiercingRayCastResult; RayCastResult[] array = new RayCastResult[ count ]; unsafe { Ode.RayCastResult* pointer = (Ode.RayCastResult*)data; for( int n = 0; n < count; n++ ) { RayCastResult result = new RayCastResult(); result.Shape = shapesDictionary[ pointer->shapeDictionaryIndex ].shape; result.Position = Convert.ToNet( pointer->position ); result.Normal = Convert.ToNet( pointer->normal ); result.Distance = pointer->distance; result.TriangleID = pointer->triangleID; array[ n ] = result; pointer++; } } //sort by distance ArrayUtils.SelectionSort( array, rayCastResultDistanceComparer ); return array; }
/// <summary> /// Tests a ray against the compound. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param> /// <param name="rayHit">Hit data and the hit child collidable, if any.</param> /// <returns>Whether or not the ray hit the entry.</returns> public bool RayCast(Ray ray, float maximumLength, out RayCastResult rayHit) { rayHit = new RayCastResult(); var hitElements = Resources.GetCompoundChildList(); if (hierarchy.Tree.GetOverlaps(ray, maximumLength, hitElements)) { rayHit.HitData.T = float.MaxValue; for (int i = 0; i < hitElements.count; i++) { EntityCollidable candidate = hitElements.Elements[i].CollisionInformation; RayHit tempHit; if (candidate.RayCast(ray, maximumLength, out tempHit) && tempHit.T < rayHit.HitData.T) { rayHit.HitData = tempHit; rayHit.HitObject = candidate; } } Resources.GiveBack(hitElements); return rayHit.HitData.T != float.MaxValue; } Resources.GiveBack(hitElements); return false; }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="result">Hit data, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayCastResult result) { var outputOverlappedElements = Resources.GetCollidableList(); var rayHits = Resources.GetRayHitList(); BoundingBox boundingBox; Toolbox.GetExpandedBoundingBox(ref castShape, ref startingTransform, ref sweep, out boundingBox); CollidableTree.GetOverlaps(boundingBox, outputOverlappedElements); result = new RayCastResult(); result.HitData.T = float.MaxValue; for (int i = 0; i < outputOverlappedElements.count; ++i) { RayHit hit; if (outputOverlappedElements.Elements[i].ConvexCast(castShape, ref startingTransform, ref sweep, out hit)) { if (hit.T < result.HitData.T) { result.HitData = hit; result.HitObject = outputOverlappedElements.Elements[i]; } } } Resources.GiveBack(rayHits); Resources.GiveBack(outputOverlappedElements); return result.HitData.T < float.MaxValue; }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present /// in the entry, this filter will be passed into inner ray casts.</param> /// <param name="result">Data and hit object from the first impact, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func<BroadPhaseEntry, bool> filter, out RayCastResult result) { CompoundChild hitChild; RayHit rayHit; bool hit = ConvexCast(castShape, ref startingTransform, ref sweep, filter, out rayHit, out hitChild); result = new RayCastResult { HitData = rayHit, HitObject = hitChild.CollisionInformation }; return hit; }
/// <summary> /// Tests a ray against the compound. /// </summary> /// <param name="ray">Ray to test.</param> /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param> /// <param name="rayHit">Hit data and the hit child collidable, if any.</param> /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present /// in the entry, this filter will be passed into inner ray casts.</param> /// <returns>Whether or not the ray hit the entry.</returns> public bool RayCast(Ray ray, float maximumLength, Func<BroadPhaseEntry, bool> filter, out RayCastResult rayHit) { RayHit hitData; CompoundChild hitChild; bool hit = RayCast(ray, maximumLength, filter, out hitData, out hitChild); rayHit = new RayCastResult { HitData = hitData, HitObject = hitChild.CollisionInformation }; return hit; }
protected override RayCastResult OnRayCast( Ray ray, int contactGroup ) { if( float.IsNaN( ray.Origin.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Origin.X)" ); if( float.IsNaN( ray.Direction.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Direction.X)" ); if( ray.Direction == Vec3.Zero ) return new RayCastResult(); Vec3 dirNormal = ray.Direction; float length = dirNormal.Normalize(); Ode.dGeomRaySet( rayCastGeomID, ray.Origin.X, ray.Origin.Y, ray.Origin.Z, dirNormal.X, dirNormal.Y, dirNormal.Z ); Ode.dGeomRaySetLength( rayCastGeomID, length ); int count; IntPtr data; Ode.DoRayCast( neoAxisAdditionsID, contactGroup, out count, out data ); RayCastResult result = new RayCastResult(); if( count != 0 ) { unsafe { Ode.RayCastResult* pointer = (Ode.RayCastResult*)data; result.Shape = shapesDictionary[ pointer->shapeDictionaryIndex ].shape; result.Position = Convert.ToNet( pointer->position ); result.Normal = Convert.ToNet( pointer->normal ); result.Distance = pointer->distance; result.TriangleID = pointer->triangleID; } } return result; }
static int SortRayCastResultsMethod( RayCastResult r1, RayCastResult r2 ) { if( r1.Distance < r2.Distance ) return -1; if( r1.Distance > r2.Distance ) return 1; return 0; }
protected unsafe override RayCastResult[] OnRayCastPiercing( Ray ray, int contactGroup ) { if( float.IsNaN( ray.Origin.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Origin.X)" ); if( float.IsNaN( ray.Direction.X ) ) Log.Fatal( "PhysicsWorld.RayCast: Single.IsNaN(ray.Direction.X)" ); if( ray.Direction == Vec3.Zero ) return emptyPiercingRayCastResult; Vec3 normalDir = ray.Direction; float length = normalDir.Normalize(); Vec3 origin = ray.Origin; int count = PhysXNativeWrapper.PhysXNativeScene.RayCast( nativeScene, ref origin, ref normalDir, length, GetContactGroupMask( contactGroup ), true ); if( count == 0 ) return emptyPiercingRayCastResult; NativeRayCastResult* results = PhysXNativeScene.GetLastRayCastResults( nativeScene ); RayCastResult[] items = new RayCastResult[ count ]; NativeRayCastResult* nativeResult = results; for( int n = 0; n < count; n++ ) { items[ n ] = GetRayCastResultFromNative( nativeResult ); nativeResult++; } return items; }
/// <summary> /// This is a high-level function to cuts fixtures inside the given world, using the start and end points. /// Note: We don't support cutting when the start or end is inside a shape. /// </summary> /// <param name="world">The world.</param> /// <param name="start">The startpoint.</param> /// <param name="end">The endpoint.</param> /// <param name="thickness">The thickness of the cut</param> public static Vector2 Cut(World world, Vector2 start, Vector2 end, float thickness, Category collisionCategories = Category.None) { // The left side of the cut will remain part of the existing body; // the right side will be made into a new body List<Fixture> fixtures = new List<Fixture>(); List<Vector2> entryPoints = new List<Vector2>(); List<Vector2> exitPoints = new List<Vector2>(); List<RayCastResult> results = new List<RayCastResult>(); //float blockingFraction = float.MaxValue; Vector2 stoppingPoint = end; //We don't support cutting when the start or end is inside a shape. //if (world.TestPoint(start) != null || world.TestPoint(end) != null) // return; //Get the entry points world.RayCast((f, p, n, fr) => { RayCastResult r = new RayCastResult(); r.f = f; r.p = p; r.fr = fr; results.Add(r); return 1; }, start, end); results = results.OrderBy(p => p.fr).ToList(); foreach (RayCastResult r in results) { if ((r.f.CollisionCategories & collisionCategories) != Category.None) { stoppingPoint = r.p; break; } if (!r.f.TestPoint(ref end)) { if (world.FixtureCut != null) world.FixtureCut(r.f); fixtures.Add(r.f); entryPoints.Add(r.p); } } //Reverse the ray to get the exitpoints world.RayCast((f, p, n, fr) => { if (fixtures.Contains(f)) { exitPoints.Add(p); } return 1; }, end, start); Debug.Assert(entryPoints.Count == exitPoints.Count && entryPoints.Count == fixtures.Count); //Fixture containsEnd = world.TestPoint(end); //if (containsEnd != null) //{ // entryPoints.RemoveAt(0); // fixtures.Remove(containsEnd); //} //Fixture containsStart = world.TestPoint(start); //if (containsStart != null) //{ // exitPoints.RemoveAt(exitPoints.Count - 1); // fixtures.Remove(containsStart); //} //We only have a single point. We need at least 2 if (entryPoints.Count + exitPoints.Count < 2) return stoppingPoint; var query = (from fix in fixtures select fix.Body).Distinct(); foreach (Body b in query) { if (b == null || b.BodyType == BodyType.Static) continue; ContactEdge edge = b.ContactList; while (edge != null) { Contact c = edge.Contact; edge = edge.Next; world.ContactManager.Destroy(c); } List<Body> leftBodies = new List<Body>(); List<Body> rightBodies = new List<Body>(); //Body rightBody = new Body(world); List<Joint> leftJoints = new List<Joint>(); List<Joint> rightJoints = new List<Joint>(); foreach (Joint j in b.JointList) { if (isLeft(start, end, j.WorldAnchorA)) leftJoints.Add(j); else rightJoints.Add(j); } //List<Fixture> leftList = new List<Fixture>(); //List<Fixture> rightList = new List<Fixture>(); Fixture[] bodyFixtures = new Fixture[b.FixtureList.Count]; b.FixtureList.CopyTo(bodyFixtures); b.FixtureList.Clear(); //leftBodies.Add(b); // For each fixture that was sliced through... foreach (Fixture fix in (from f in bodyFixtures where fixtures.Contains(f) select f)) { int i = fixtures.IndexOf(fix); // split this in half and put the halves in the over/under lists Vertices first; Vertices second; SplitShape(fix, entryPoints[i], exitPoints[i], thickness, out first, out second); if (!SanityCheck(first) || !SanityCheck(second)) { continue; } PolygonShape leftShape = new PolygonShape(first, fix.Shape.Density); PolygonShape rightShape = new PolygonShape(second, fix.Shape.Density); if (!b.FixtureList.Any()) { if (leftShape.MassData.Area > rightShape.MassData.Area) { b.CreateFixture(leftShape, fix.UserData); leftBodies.Add(b); GlomFixture(world, b, rightBodies, rightShape, fix.UserData, rightJoints); } else { b.CreateFixture(rightShape, fix.UserData); rightBodies.Add(b); GlomFixture(world, b, leftBodies, leftShape, fix.UserData, leftJoints); } } else { GlomFixture(world, b, leftBodies, leftShape, fix.UserData, leftJoints); GlomFixture(world, b, rightBodies, rightShape, fix.UserData, rightJoints); } } // for each fixture that was NOT sliced through... foreach (Fixture fix in (from f in bodyFixtures where !fixtures.Contains(f) select f)) { if (isLeft(start, end, fix)) { GlomFixture(world, b, leftBodies, fix.Shape, fix.UserData, leftJoints); } else { GlomFixture(world, b, rightBodies, fix.Shape, fix.UserData, rightJoints); //rightBody.CreateFixture(fix.Shape.Clone(), fix.UserData); } } foreach (Body bod in leftBodies.Concat(rightBodies)) { bod.ResetMassData(); bod.BodyType = BodyType.Dynamic; bod.Rotation = b.Rotation; bod.LinearVelocity = b.LinearVelocity; bod.AngularVelocity = b.AngularVelocity; bod.Position = b.Position; } //b.JointList = null; //world.RemoveBody(b); foreach (Fixture f in bodyFixtures) { b.DestroyFixture(f); } world.ProcessChanges(); } return stoppingPoint; }
unsafe RayCastResult GetRayCastResultFromNative( NativeRayCastResult* native ) { RayCastResult result = new RayCastResult(); if( native->shape != IntPtr.Zero ) { result.Shape = PhysXPhysicsWorld.Instance.GetShapeByNativePointer( native->shape ); result.Position = native->worldImpact; result.Normal = native->worldNormal; result.Distance = native->distance; if( result.Shape.ShapeType == Shape.Type.Mesh ) { MeshShape meshShape = (MeshShape)result.Shape; if( meshShape.MeshType != MeshShape.MeshTypes.ConvexHullDecomposition ) result.TriangleID = native->faceID; } else if( result.Shape.ShapeType == Shape.Type.HeightField ) result.TriangleID = native->faceID; else result.TriangleID = 0; } return result; }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="result">Data and hit object from the first impact, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayCastResult result) { CompoundChild hitChild; RayHit rayHit; bool hit = ConvexCast(castShape, ref startingTransform, ref sweep, out rayHit, out hitChild); result = new RayCastResult { HitData = rayHit, HitObject = hitChild.CollisionInformation }; return hit; }