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(); }
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; //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true); //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false); MyPhysics.CastRay(from, to, m_hits); bool hasInteractive = false; int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].HkHitInfo.Body.UserObject == Character.VirtualPhysics) || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { //We must take only closest hit (others are hidden behind) var h = m_hits[index]; var entity = h.HkHitInfo.Body.GetEntity(); var interactive = entity as IMyUseObject; // TODO: Uncomment to enforce that character must face object by front to activate it //if (TestInteractionDirection(head.Forward, h.Position - GetPosition())) //return; if (entity != null) { MyUseObjectsComponentBase useObject = null; entity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(h.HkHitInfo.GetShapeKey(0)); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < 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; } }
protected override void DoDetection(bool useHead) { ProfilerShort.Begin("DoDetection"); 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; 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; //EnableDetectorsInArea(from); GatherDetectorsInArea(from); float closestDetector = float.MaxValue; IMyEntity closestEntity = null; IMyUseObject closestInteractive = null; foreach (var entity in m_detectableEntities) { if (entity == Character) { continue; } var use = entity.Components.Get <MyUseObjectsComponentBase>() as MyUseObjectsComponent; if (use != null) { float detectorDistance; var interactive = use.RaycastDetectors(from, to, out detectorDistance); if (Math.Abs(detectorDistance) < Math.Abs(closestDetector)) { closestDetector = detectorDistance; closestEntity = entity; closestInteractive = interactive; } } //Floating object handling - give FO useobject component! var use2 = entity as IMyUseObject; if (use2 != null) { var m = use2.ActivationMatrix; var ray = new RayD(from, to - from); var obb = new MyOrientedBoundingBoxD(m); var dist = obb.Intersects(ref ray); if (dist.HasValue && Math.Abs(dist.Value) < Math.Abs(closestDetector)) { closestDetector = (float)dist.Value; closestEntity = entity; closestInteractive = use2; } } } m_detectableEntities.Clear(); //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true); //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false); StartPosition = from; MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.FloatingObjectCollisionLayer); bool hasInteractive = false; int index = 0; while (index < m_hits.Count && (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) || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer)) // Skip invalid hits and self character { index++; } if (index < m_hits.Count && m_hits[index].HkHitInfo.HitFraction > closestDetector - 0.05f)//compensation { // TODO: Uncomment to enforce that character must face object by front to activate it //if (TestInteractionDirection(head.Forward, h.Position - GetPosition())) //return; HitPosition = from + dir * closestDetector; MyUseObjectsComponentBase useObject; if (closestEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject)) { var detectorPhysics = useObject.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = ((MyPhysicsBody)detectorPhysics).RigidBody; } else { HitMaterial = closestEntity.Physics.GetMaterialAt(HitPosition); HitBody = ((MyPhysicsBody)closestEntity.Physics).RigidBody; } DetectedEntity = closestEntity; var interactive = closestInteractive; if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } //if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) if (interactive != null && interactive.SupportedActions != UseActionEnum.None && closestDetector * MyConstants.DEFAULT_INTERACTIVE_DISTANCE < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
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) { ProfilerShort.Begin("DoDetection"); 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; 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; LineD intersectionLine = new LineD(from, to); // Processing of hit entities var geometryHit = MyEntities.GetIntersectionWithLine(ref intersectionLine, null, null, ignoreFloatingObjects: false); bool hasUseObject = false; if (geometryHit.HasValue) { var hitEntity = geometryHit.Value.Entity; // Cube Grids are special case var cubeGrid = hitEntity as MyCubeGrid; if (cubeGrid != null) { // For hit cube grids get the fat hit fatblock instead. var slimBlock = cubeGrid.GetTargetedBlock(geometryHit.Value.IntersectionPointInWorldSpace); if (slimBlock != null && slimBlock.FatBlock != null) { hitEntity = slimBlock.FatBlock; } } m_hitUseComponents.Clear(); var hitUseObject = hitEntity as IMyUseObject; // Retrive all above use components from parent structure. (Because of subParts) GetUseComponentsFromParentStructure(hitEntity, m_hitUseComponents); // Check for UseObjects and entities with UseObjectComponentBase. // Assuming that entity cannot be IMyUseObject and have UseObjectComponentBase in hierarchy // at the same time. if (hitUseObject != null || m_hitUseComponents.Count > 0) { if (m_hitUseComponents.Count > 0) { // Process the valid hit entity var closestDetectorDistance = float.MaxValue; double physicalHitDistance = Vector3D.Distance(from, geometryHit.Value.IntersectionPointInWorldSpace); MyUseObjectsComponentBase hitUseComp = null; // Evaluate the set of found detectors and try to find the closest one foreach (var hitUseComponent in m_hitUseComponents) { float detectorDistance; var interactive = hitUseComponent.RaycastDetectors(from, to, out detectorDistance); detectorDistance *= MyConstants.DEFAULT_INTERACTIVE_DISTANCE; if (Math.Abs(detectorDistance) < Math.Abs(closestDetectorDistance) && (detectorDistance < physicalHitDistance)) // Remove to fix the problem with picking through physic bodies, { // but will introduce new problem with detectors inside physic bodies. closestDetectorDistance = detectorDistance; hitUseComp = hitUseComponent; hitEntity = hitUseComponent.Entity; hitUseObject = interactive; } } // Detector found if (hitUseComp != null) { // Process successful hit with results var detectorPhysics = hitUseComp.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = geometryHit.Value.Entity.Physics.RigidBody; HitPosition = geometryHit.Value.IntersectionPointInWorldSpace; DetectedEntity = hitEntity; } } else { // Case for hitting IMyUseObject already before even looking for UseComponent. // Floating object case. HitMaterial = hitEntity.Physics.GetMaterialAt(HitPosition); HitBody = hitEntity.Physics.RigidBody; } // General logic for processing both cases. if (hitUseObject != null) { HitPosition = geometryHit.Value.IntersectionPointInWorldSpace; DetectedEntity = hitEntity; if (UseObject != null && UseObject != hitEntity && UseObject != hitUseObject) { UseObject.OnSelectionLost(); } if (Character == MySession.Static.ControlledEntity && hitUseObject.SupportedActions != UseActionEnum.None) { HandleInteractiveObject(hitUseObject); UseObject = hitUseObject; hasUseObject = true; } } } } if (!hasUseObject) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
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; } }
protected override void DoDetection(bool useHead) { ProfilerShort.Begin("DoDetection"); 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; 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; // Processing of hit entities MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.FloatingObjectCollisionLayer); bool hasUseObject = false; int index = 0; while (index < m_hits.Count) { var hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); // Skip invalid hits if (m_hits[index].HkHitInfo.Body == null || hitEntity == null || hitEntity == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer) { index++; continue; } // Cube Grids are special case var cubeGrid = hitEntity as MyCubeGrid; if (cubeGrid != null) { // Correct the hit position (Physics offset) var correctedPosition = m_hits[index].Position - m_hits[index].HkHitInfo.Normal * m_hits[index].HkHitInfo.GetConvexRadius(); // For hit cube grids get the fat hit fatblock instead. var slimBlock = cubeGrid.GetTargetedBlock(correctedPosition); if (slimBlock != null && slimBlock.FatBlock != null) { hitEntity = slimBlock.FatBlock; } } m_hitUseComponents.Clear(); var hitUseObject = hitEntity as IMyUseObject; // Retrive all above use components from parent structure. (Because of subParts) GetUseComponentsFromParentStructure(hitEntity, m_hitUseComponents); // Check for UseObjects and entities with UseObjectComponentBase. // Assuming that entity cannot be IMyUseObject and have UseObjectComponentBase in hierarchy // at the same time. if (hitUseObject != null || m_hitUseComponents.Count > 0) { if (m_hitUseComponents.Count > 0) { // Process the valid hit entity var closestDetectorDistance = float.MaxValue; MyUseObjectsComponentBase hitUseComp = null; // Evaluate the set of found detectors and try to find the closest one foreach (var hitUseComponent in m_hitUseComponents) { float detectorDistance; var interactive = hitUseComponent.RaycastDetectors(from, to, out detectorDistance); if (Math.Abs(detectorDistance) < Math.Abs(closestDetectorDistance)) { closestDetectorDistance = detectorDistance; hitUseComp = hitUseComponent; hitEntity = hitUseComponent.Entity; hitUseObject = interactive; } } // Detector found if (hitUseComp != null) { // Process successful hit with results var detectorPhysics = hitUseComp.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; DetectedEntity = hitEntity; } } else { // Case for hitting IMyUseObject already before even looking for UseComponent. // Floating object case. HitMaterial = hitEntity.Physics.GetMaterialAt(HitPosition); HitBody = m_hits[index].HkHitInfo.Body; } // General logic for processing both cases. if (hitUseObject != null) { HitPosition = m_hits[index].Position; DetectedEntity = hitEntity; if (UseObject != null && UseObject != hitEntity) { UseObject.OnSelectionLost(); } if (hitUseObject.SupportedActions != UseActionEnum.None && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(hitUseObject); UseObject = hitUseObject; hasUseObject = true; } } break; } index++; } if (!hasUseObject) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
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(); }