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();
        }
Пример #2
0
        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;
            }
        }
Пример #3
0
        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();
        }
Пример #5
0
        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;
            }
        }
Пример #8
0
        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();
        }
Пример #9
0
        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();
        }