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();
        }
예제 #4
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)
        {
            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;
            }
        }
예제 #6
0
        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();
        }
예제 #7
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();
        }