private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); Vector3D from = head.Translation; Vector3D dir = head.Forward; if (!useHead) { var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) if (Character == MySession.Static.LocalCharacter) { from = MySector.MainCamera.WorldMatrix.Translation; dir = MySector.MainCamera.WorldMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, from, (Vector3)dir); } else { from = headPos; dir = head.Forward; } } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_rayOrigin = from; m_rayDirection = dir; m_hits.Sort(CompareHits); if (m_hits.Count > 0) { bool isValidBlock = false; bool isPhysicalBlock = false; for (int index = 0; index < m_hits.Count; index++) { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); // Ignore self-interaction if (entity == Character) { continue; } if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // If hit-entity is a grid, raycast it to see which block we hit first if (entity is MyCubeGrid) { MyCubeGrid grid = entity as MyCubeGrid; List <MyCube> cubeList = grid.RayCastBlocksAllOrdered(from, to); if (cubeList != null && cubeList.Count > 0) { var slimblock = cubeList[0].CubeBlock; if (slimblock.FatBlock != null) { entity = slimblock.FatBlock; isPhysicalBlock = true; hitEntity = entity; ShapeKey = 0; } } } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; break; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); break; } index++; } } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
/// <summary> /// Processes previously acquired raycast results. /// Returns safe camera eye position (As far from target as possible, but not colliding, best case = desired eye pos). /// </summary> private MyCameraRaycastResult RaycastOccludingObjects(MyEntity controlledEntity, ref Vector3D raycastOrigin, ref Vector3D raycastEnd, ref Vector3D raycastSafeCameraStart, out Vector3D outSafePosition) { Vector3D rayDirection = raycastEnd - raycastOrigin; rayDirection.Normalize(); outSafePosition = m_position; double closestDistanceSquared = double.PositiveInfinity; bool positionChanged = false; // ray cast - very close objects MyPhysics.CastRay(raycastOrigin, raycastOrigin + CAMERA_RADIUS * rayDirection, m_raycastList); foreach (MyPhysics.HitInfo rb in m_raycastList) { if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody) || rb.HkHitInfo.GetHitEntity() == controlledEntity) { continue; } if (rb.HkHitInfo.GetHitEntity() is IMyHandheldGunObject <Game.Weapons.MyDeviceBase> ) // ignore player weapons { continue; } double distSq = Vector3D.DistanceSquared(rb.Position, raycastOrigin); if (distSq < closestDistanceSquared) { closestDistanceSquared = distSq; float dist = (float)Math.Sqrt(distSq) - CAMERA_RADIUS; outSafePosition = raycastOrigin + rayDirection * dist; positionChanged = true; } } if (m_debugDraw) { foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawPoint(raycastResult.Position, Color.Red, false); } } // shape cast - further objects if ((raycastEnd - raycastOrigin).LengthSquared() > CAMERA_RADIUS * CAMERA_RADIUS) { HkShape shapeSphere = new HkSphereShape(CAMERA_RADIUS); MatrixD raycastOriginTransform = MatrixD.Identity; raycastOriginTransform.Translation = raycastOrigin + CAMERA_RADIUS * rayDirection; MyPhysics.CastShapeReturnContactBodyDatas(raycastEnd, shapeSphere, ref raycastOriginTransform, 0, 0, m_raycastList); //MyPhysics.CastRay(raycastOrigin + CAMERA_RADIUS * rayDirection, raycastEnd, m_raycastList, 0); foreach (MyPhysics.HitInfo rb in m_raycastList) { IMyEntity hitEntity = rb.HkHitInfo.GetHitEntity(); if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || hitEntity == controlledEntity || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody)) { continue; } if (hitEntity is IMyHandheldGunObject <Game.Weapons.MyDeviceBase> ) { // ignore player weapons continue; } double distSq = Vector3D.DistanceSquared(rb.Position, raycastOrigin); if (distSq < closestDistanceSquared) { closestDistanceSquared = distSq; float dist = (float)Math.Sqrt(distSq); outSafePosition = raycastOrigin + rayDirection * dist; positionChanged = true; } } shapeSphere.RemoveReference(); } if (m_debugDraw) { foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawSphere(raycastResult.Position, CAMERA_RADIUS, Color.Red, 1, false); } } if (closestDistanceSquared < (raycastSafeCameraStart - raycastOrigin).LengthSquared() + CAMERA_RADIUS) { return(MyCameraRaycastResult.FoundOccluderNoSpace); // obstacle too close, switch to first person } // last check - isn't there voxel between safe pos and entity pos if (!positionChanged) { //Vector3D entityPos = controlledEntity.PositionComp.GetPosition(); MyPhysics.CastRay(m_target, raycastSafeCameraStart, m_raycastList); if (m_debugDraw) { BoundingBoxD bb = new BoundingBoxD(m_target, raycastSafeCameraStart); VRageRender.MyRenderProxy.DebugDrawAABB(bb, Color.Magenta); } foreach (var collision in m_raycastList) { if (collision.HkHitInfo.GetHitEntity() is MyVoxelBase) { return(MyCameraRaycastResult.FoundOccluderNoSpace); } } } return(positionChanged ? MyCameraRaycastResult.FoundOccluder : MyCameraRaycastResult.Ok); }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5f; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); HitBody = m_hits[index].HkHitInfo.Body; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override void DoDetection(bool useHead) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; //var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { isValidBlock = m_hits[index].HkHitInfo.Body != null && m_hits[index].HkHitInfo.GetHitEntity() != Character && m_hits[index].HkHitInfo.GetHitEntity() != null && !m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = m_hits[index].HkHitInfo.GetHitEntity() != null && m_hits[index].HkHitInfo.GetHitEntity().Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(SHAPE_RADIUS); IMyEntity hitEntity = null; int shapeKey = -1; Vector3D hitPosition = Vector3D.Zero; m_hits.Clear(); try { MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].Body == null || m_hits[index].Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].Body.UserObject == Character.VirtualPhysics) || m_hits[index].Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].Body.GetEntity(); shapeKey = m_hits[index].ShapeKey; hitPosition = m_hits[index].HitPosition; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(shapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, hitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } }
private void DoDetection(bool useHead, bool doModelIntersection) { bool flag; if (ReferenceEquals(base.Character, MySession.Static.ControlledEntity)) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } MatrixD xd = base.Character.GetHeadMatrix(false, true, false, false, false); Vector3D translation = xd.Translation; Vector3D forward = xd.Forward; if (!useHead) { Vector3D planePoint = xd.Translation - (xd.Forward * 0.3); if (!ReferenceEquals(base.Character, MySession.Static.LocalCharacter)) { translation = planePoint; forward = xd.Forward; } else { translation = MySector.MainCamera.WorldMatrix.Translation; forward = MySector.MainCamera.WorldMatrix.Forward; translation = MyUtils.LinePlaneIntersection(planePoint, (Vector3)forward, translation, (Vector3)forward); } } Vector3D to = translation + (forward * 2.5); base.StartPosition = translation; MatrixD transform = MatrixD.CreateTranslation(translation); HkShape shape = (HkShape) new HkSphereShape(this.ShapeRadius); IMyEntity objA = null; base.ShapeKey = uint.MaxValue; base.HitPosition = Vector3D.Zero; base.HitNormal = Vector3.Zero; base.HitMaterial = MyStringHash.NullOrEmpty; base.HitTag = null; this.m_hits.Clear(); Vector3 zero = (Vector3)Vector3D.Zero; try { bool flag2; bool flag3; int num; base.EnableDetectorsInArea(translation); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref transform, 0, 0f, this.m_hits, true); this.m_rayOrigin = translation; this.m_rayDirection = forward; this.m_hits.Sort(new Comparison <MyPhysics.HitInfo>(this.CompareHits)); if (this.m_hits.Count <= 0) { goto TR_0012; } else { flag2 = false; flag3 = false; num = 0; } goto TR_002F; TR_0017: num++; TR_002F: while (true) { if (num >= this.m_hits.Count) { break; } HkRigidBody hkEntity = this.m_hits[num].HkHitInfo.Body; IMyEntity hitEntity = this.m_hits[num].HkHitInfo.GetHitEntity(); if (!ReferenceEquals(hitEntity, base.Character)) { int num1; if (hitEntity is MyEntitySubpart) { hitEntity = hitEntity.Parent; } if (((hkEntity == null) || (hitEntity == null)) || ReferenceEquals(hitEntity, base.Character)) { num1 = 0; } else { num1 = (int)!hkEntity.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); } flag2 = (bool)num1; flag3 = (hitEntity != null) && (hitEntity.Physics != null); if (ReferenceEquals(objA, null) & flag2) { objA = hitEntity; base.ShapeKey = this.m_hits[num].HkHitInfo.GetShapeKey(0); } if (hitEntity is MyCubeGrid) { List <MyCube> list = (hitEntity as MyCubeGrid).RayCastBlocksAllOrdered(translation, to); if ((list != null) && (list.Count > 0)) { MySlimBlock cubeBlock = list[0].CubeBlock; if (cubeBlock.FatBlock != null) { flag3 = true; objA = cubeBlock.FatBlock; base.ShapeKey = 0; } } } if (!((base.HitMaterial.Equals(MyStringHash.NullOrEmpty) & flag2) & flag3)) { if (hkEntity == null) { num++; goto TR_0017; } else { zero = this.m_hits[num].GetFixedPosition(); } } else { base.HitBody = hkEntity; base.HitNormal = this.m_hits[num].HkHitInfo.Normal; base.HitPosition = this.m_hits[num].GetFixedPosition(); base.HitMaterial = hkEntity.GetBody().GetMaterialAt(base.HitPosition); zero = (Vector3)base.HitPosition; } break; } goto TR_0017; } } finally { shape.RemoveReference(); } TR_0012: flag = false; IMyUseObject interactive = objA as IMyUseObject; base.DetectedEntity = objA; if (objA != null) { MyUseObjectsComponentBase component = null; objA.Components.TryGet <MyUseObjectsComponentBase>(out component); if (component != null) { interactive = component.GetInteractiveObject(base.ShapeKey); } if (doModelIntersection) { LineD line = new LineD(translation, to); MyCharacter character = objA as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?nullable; if (objA.GetIntersectionWithLine(ref line, out nullable, IntersectionFlags.ALL_TRIANGLES)) { base.HitPosition = nullable.Value.IntersectionPointInWorldSpace; base.HitNormal = nullable.Value.NormalInWorldSpace; } } else if (character.GetIntersectionWithLine(ref line, ref base.CharHitInfo, IntersectionFlags.ALL_TRIANGLES)) { base.HitPosition = base.CharHitInfo.Triangle.IntersectionPointInWorldSpace; base.HitNormal = base.CharHitInfo.Triangle.NormalInWorldSpace; base.HitTag = base.CharHitInfo; } } } if (((interactive != null) && ((interactive.SupportedActions != UseActionEnum.None) && (Vector3D.Distance(translation, zero) < interactive.InteractiveDistance))) && ReferenceEquals(base.Character, MySession.Static.ControlledEntity)) { HandleInteractiveObject(interactive); base.UseObject = interactive; flag = true; } if (!flag) { base.UseObject = null; } base.DisableDetectors(); }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_hits.Sort(delegate(MyPhysics.HitInfo info1, MyPhysics.HitInfo info2) { float dot1 = Vector3.Dot(head.Forward, Vector3.Normalize(info1.Position - StartPosition)); float dot2 = Vector3.Dot(head.Forward, Vector3.Normalize(info2.Position - StartPosition)); return(dot1.CompareTo(dot2)); }); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }