Пример #1
0
	public void Instanciate(MyPhysics physics)
	{
		mPosition = this.transform.position;
		mCollider = GetComponent<Collision>();
		mMass = Mathf.Pow (mCollider.size, 3);
		physics.AddBody (this);
		Instanciated = true;
	}
Пример #2
0
        private MyEntity FindBody(out Vector3D pivot)
        {
            pivot = Vector3D.Zero;
            if (CubeGrid.Physics == null)
            {
                return(null);
            }
            Quaternion orientation;
            Vector3    halfExtents;

            foreach (var m in m_lockPositions)
            {
                GetBoxFromMatrix(m, out halfExtents, out pivot, out orientation);
                HkBoxShape boxShape;
                try
                {
                    halfExtents *= new Vector3(2.0f, 1.0f, 2.0f);
                    orientation.Normalize();
                    MyPhysics.GetPenetrationsBox(ref halfExtents, ref pivot, ref orientation, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                    boxShape = new HkBoxShape(halfExtents);
                    Matrix tranform = Matrix.CreateFromQuaternion(orientation);
                    //tranform.Translation = pivot;
                    //MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD(new BoundingBoxD(-halfExtents, halfExtents),tranform);
                    //tranform.Translation = Vector3D.Zero;
                    //MyRenderProxy.DebugDrawOBB(obb, Color.Red, 1, false, false);

                    foreach (var obj in m_penetrations)
                    {
                        var entity = MyPhysicsExtensions.GetCollisionEntity(obj) as MyEntity;

                        if (entity == null)// || entity.Parent != null)
                        {
                            continue;
                        }

                        if (entity.GetPhysicsBody().WeldInfo.Children.Count > 0)
                        {
                            Matrix t2;
                            foreach (var child in entity.GetPhysicsBody().WeldInfo.Children)
                            {
                                var childEnt = child.Entity as MyEntity;
                                t2             = childEnt.GetPhysicsBody().WeldInfo.Transform *entity.Physics.RigidBody.GetRigidBodyMatrix();
                                t2.Translation = entity.Physics.ClusterToWorld(t2.Translation);
                                //obb = new MyOrientedBoundingBoxD((BoundingBoxD)childEnt.PositionComp.LocalAABB, t2);
                                //MyRenderProxy.DebugDrawOBB(obb, Color.Green, 1, false, false);
                                t2.Translation = t2.Translation - pivot;
                                if (MyPhysics.IsPenetratingShapeShape(boxShape, ref tranform, child.WeldedRigidBody.GetShape(), ref t2))
                                {
                                    if (
                                        CanAttachTo(obj, child.Entity as MyEntity))
                                    {
                                        return(child.Entity as MyEntity);
                                    }
                                }
                            }
                            t2             = entity.Physics.RigidBody.GetRigidBodyMatrix();
                            t2.Translation = entity.Physics.ClusterToWorld(t2.Translation) - pivot;

                            if (MyPhysics.IsPenetratingShapeShape(boxShape, ref tranform, entity.GetPhysicsBody().GetShape(), ref t2) &&
                                CanAttachTo(obj, entity))
                            {
                                return(entity);
                            }
                        }
                        else if (CanAttachTo(obj, entity))
                        {
                            return(entity);
                        }
                    }
                }
                finally
                {
                    boxShape.Base.RemoveReference();
                    m_penetrations.Clear();
                }
            }
            return(null);
        }
        protected Vector3D?GetFreeSpacePlacementPosition(bool copyPaste, out bool buildAllowed)
        {
            Vector3D?freePlacementIntersectionPoint = null;

            buildAllowed = false;

            float gridSize = PreviewGrids[0].GridSize;

            double shortestDistance = double.MaxValue;
            double?currentRayInts   = MyCubeBuilder.GetCurrentRayIntersection();

            if (currentRayInts.HasValue)
            {
                shortestDistance = currentRayInts.Value;
            }

            Vector3D worldRefPointOffset = Vector3D.Zero;

            if (copyPaste)
            {
                Matrix firstGridOrientation = GetFirstGridOrientationMatrix();
                worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation);
            }

            Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero);

            Matrix blockLocalTransform;

            foreach (var block in PreviewGrids[0].GetBlocks())
            {
                Vector3 halfExt  = block.BlockDefinition.Size * PreviewGrids[0].GridSize * 0.5f;
                Vector3 minLocal = block.Min * PreviewGrids[0].GridSize - Vector3.Half * PreviewGrids[0].GridSize;
                Vector3 maxLocal = block.Max * PreviewGrids[0].GridSize + Vector3.Half * PreviewGrids[0].GridSize;

                block.Orientation.GetMatrix(out blockLocalTransform);
                blockLocalTransform.Translation = 0.5f * (minLocal + maxLocal);

                MatrixD  blockWorldTransform = blockLocalTransform * PreviewGrids[0].WorldMatrix;
                Vector3D offset = blockWorldTransform.Translation + worldRefPointOffset - worldRefPoint;

                HkShape shape = new HkBoxShape(halfExt);

                Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset;
                double   castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart);
                rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection;

                Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset;
                MatrixD  matrix = blockWorldTransform;
                matrix.Translation = rayStart;

                try
                {
                    float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter);
                    if (dist.HasValue && dist.Value != 0f)
                    {
                        Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart);

                        const bool debugDraw = false;
                        if (debugDraw)
                        {
                            Color        green      = Color.Green;
                            BoundingBoxD localAABB  = new BoundingBoxD(-halfExt, halfExt);
                            MatrixD      drawMatrix = matrix;
                            drawMatrix.Translation = intersectionPoint;
                            MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);
                        }

                        double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart;
                        if (fixedDistance <= 0)
                        {
                            fixedDistance    = 0;
                            shortestDistance = 0;
                            break;
                        }

                        if (fixedDistance < shortestDistance)
                        {
                            shortestDistance = fixedDistance;
                        }

                        buildAllowed = true;
                    }
                }
                finally
                {
                    shape.RemoveReference();
                }
            }

            float boxRadius    = (float)PreviewGrids[0].PositionComp.WorldAABB.HalfExtents.Length();
            float dragDistance = 1.5f * boxRadius;

            if (shortestDistance < dragDistance)
            {
                shortestDistance = dragDistance;
                buildAllowed     = false;
            }

            if (shortestDistance < m_dragDistance)
            {
                freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection;
            }

            return(freePlacementIntersectionPoint);
        }
Пример #4
0
        /// <summary>
        /// Finds the closest foot support position using raycast - should raycast from start and from end of the foot
        /// </summary>
        /// <param name="from">Vector3 from - the world coordinate from witch to ray cast - usually the foot world position on the ground</param>
        /// <param name="up">Vector3 up - defining the world up vector used to raycast to the ground</param>
        /// <param name="WorldMatrix">is the world matrix of the model</param>
        /// <param name="castUpLimit">is the height from where we start casting</param>
        /// <param name="castDownLimit">is the height to how much deep we cast</param>
        /// <param name="footDimension">this is the foot dimension, used to create shape cast and also ankle's height, X = width, Z = length, Y = height</param>
        /// <returns>returns CashHit if hit or null otherwise</returns>
        public static CastHit?GetClosestFootSupportPosition(MyEntity characterEntity, MyEntity characterTool, Vector3 from, Vector3 up, Vector3 footDimension, Matrix WorldMatrix, float castDownLimit, float castUpLimit, uint raycastFilterLayer = 0)
        {
            bool    gotHit = false;
            CastHit hit    = new CastHit();
            MatrixD matrix = WorldMatrix;
            Vector3 footTranslationFromAnkle = Vector3.Zero;//new Vector3(0, footDimension.Y, - footDimension.Y + footDimension.X);    // assunming the -Z is facing front

            // set the proper translation
            matrix.Translation       = Vector3.Zero;                                        // just keep the matrix's orientation etc.
            footTranslationFromAnkle = Vector3.Transform(footTranslationFromAnkle, matrix); // get it to the world
            matrix.Translation       = from + up * castUpLimit + footTranslationFromAnkle;  // set the matrix translation to position from where we cast - we need to shift from the ankle

            // our shape cast returned data structure
            //HkContactPointData? cpd = null;
            //// do the foot cast shape, raycast sometimes don't return a value and we need to make sure that we do nut fall into hole
            //HkShape shape = new HkBoxShape(footDimension * 0.5f);
            Vector3 capsA = new Vector3(0, footDimension.Y / 2, 0);
            Vector3 capsB = new Vector3(0, footDimension.Y / 2, -footDimension.Z);
            //capsA = Vector3.Transform(capsA, WorldMatrix.GetOrientation());
            //capsB = Vector3.Transform(capsB, WorldMatrix.GetOrientation());

            //HkShape shape = new HkCapsuleShape(capsA, capsB, footDimension.X / 2);
            Vector3 castFrom = from + up * castUpLimit;
            Vector3 castTo   = from - up * castDownLimit;

            //cpd = MyPhysics.CastShapeReturnContactData(castTo + footTranslationFromAnkle, shape, ref matrix, Physics.CharacterProxy.CharacterCollisionFilter, 0.0f);



            //var hit = MyPhysics.CastRay(castFrom, castTo, out position, out normal, Physics.CharacterProxy.CharacterCollisionFilter, true);

            //LineD castLine = new LineD(castFrom, castTo);
            //var result = MyEntities.GetIntersectionWithLine(ref castLine, characterEntity, characterTool, true, false, true);

            //if (result != null)
            //{
            //    hit.Position = result.Value.IntersectionPointInWorldSpace;
            //    hit.Normal = result.Value.NormalInWorldSpace;
            //    gotHit = true;
            //    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
            //    {
            //        VRageRender.MyRenderProxy.DebugDrawSphere(hit.Position, 0.02f, Color.Gray, 1, false);
            //        VRageRender.MyRenderProxy.DebugDrawText3D(hit.Position, "Entity Intersection hit", Color.Gray, 1, false);
            //    }

            //}

            if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTLINE)
            {
                VRageRender.MyRenderProxy.DebugDrawText3D(castFrom + footTranslationFromAnkle, "Cast line", Color.White, 1, false);
                VRageRender.MyRenderProxy.DebugDrawLine3D(castFrom + footTranslationFromAnkle, castTo + footTranslationFromAnkle, Color.White, Color.White, false);
            }

            if (MyFakes.ENABLE_FOOT_IK_USE_HAVOK_RAYCAST)
            {
                // do the ray cast also, because ground may not be flat and we will use this to correct values just using raycast, this takes in consideration convex shape radius and ignores it
                MyPhysics.HitInfo hitInfo;
                if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTLINE)
                {
                    VRageRender.MyRenderProxy.DebugDrawText3D(castFrom, "Raycast line", Color.Green, 1, false);
                    VRageRender.MyRenderProxy.DebugDrawLine3D(castFrom, castTo, Color.Green, Color.Green, false);
                }

                if (MyPhysics.CastRay(castFrom, castTo, out hitInfo, raycastFilterLayer, true))
                {
                    gotHit = true;
                    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
                    {
                        VRageRender.MyRenderProxy.DebugDrawSphere(hitInfo.Position, 0.02f, Color.Green, 1, false);
                        VRageRender.MyRenderProxy.DebugDrawText3D(hitInfo.Position, "RayCast hit", Color.Green, 1, false);
                    }
                    // this is hack, if RayCast returns a hit above the graphics cast, take this one
                    if (Vector3.Dot(hitInfo.Position, up) > Vector3.Dot(hit.Position, up))
                    {
                        hit.Position = hitInfo.Position;
                        hit.Normal   = hitInfo.HkHitInfo.Normal;
                    }
                }
            }


            //    // now we need to recalculate the hit position to center
            //    cp.HitPosition = from - Vector3.Dot(WorldMatrix.Translation - cp.HitPosition, up) * up;

            //    //cp.HitPosition.Interpolate3(castFrom, castTo, cp.DistanceFraction);
            //    //cp.HitPosition -= footTranslationFromAnkle;

            //    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
            //    {
            //        VRageRender.MyRenderProxy.DebugDrawSphere(cp.HitPosition, 0.03f, Color.Violet, 1, false);
            //        VRageRender.MyRenderProxy.DebugDrawText3D(cp.HitPosition, "ShapeCast hit Centered", Color.Violet, 1, false);
            //    }

            //    // shape cast correction using the normal
            //    //float dotProductAbs = WorldMatrix.Forward.Dot(cp.Normal);
            //    //cp.HitPosition -= WorldMatrix.Up * (1 - dotProductAbs) * footDimension.Y;

            //    // draw shape and ray cast hits
            //    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
            //    {
            //        matrix.Translation = cp.HitPosition;
            //        VRageRender.MyRenderProxy.DebugDrawOBB(Matrix.CreateScale(footDimension) * matrix, Color.White, 1, false, false);
            //        VRageRender.MyRenderProxy.DebugDrawCapsule(Vector3.Transform(capsA, WorldMatrix.GetOrientation()) + cp.HitPosition, Vector3.Transform(capsB, WorldMatrix.GetOrientation()) + cp.HitPosition, footDimension.X, Color.Red, false);

            //    }
            //    // use raycast to correct position
            //    //if (hit)
            //    //{

            //    //    // draw shape and ray cast hits
            //    //    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
            //    //    {
            //    //        VRageRender.MyRenderProxy.DebugDrawSphere(position, 0.02f, Color.Green, 1, false, false);
            //    //        VRageRender.MyRenderProxy.DebugDrawText3D(position, "RayCast hit", Color.Green, 1, false);

            //    //    }

            //    //    // shift the foot  up for the ankle height according to the normal orientation
            //    //    //float dotProductAbs = Math.Abs( WorldMatrix.Forward.Dot(normal));

            //    //    //{
            //    //    //    // get the difference between shape and ray cast and set the position
            //    //    //    Vector3 difference = (position - cp.HitPosition) * (dotProductAbs);
            //    //    //    cp.HitPosition = position - difference; // prefer shapecast when the ground is on ankle

            //    //    //}
            //    //    cp.HitPosition.Interpolate3(cp.HitPosition, position, Vector3.Dot(WorldMatrix.Up, normal));
            //    //    //cp.Normal = normal;

            //    //}


            //    // where will be final foot if not ankle's shifted
            //    if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW && MyDebugDrawSettings.DEBUG_DRAW_CHARACTER_IK_RAYCASTHITS)
            //    {
            //        matrix.Translation = cp.HitPosition;
            //        VRageRender.MyRenderProxy.DebugDrawSphere(cp.HitPosition, 0.02f, Color.Red, 1, false, false);
            //        VRageRender.MyRenderProxy.DebugDrawText3D(cp.HitPosition, "Final hit", Color.Red, 1, false);
            //        VRageRender.MyRenderProxy.DebugDrawLine3D(cp.HitPosition, cp.HitPosition + cp.Normal, Color.YellowGreen, Color.YellowGreen, false);
            //        VRageRender.MyRenderProxy.DebugDrawOBB(Matrix.CreateScale(footDimension) * matrix, Color.Cyan, 1, false, false);
            //    }


            //}

            return(gotHit ? new CastHit?(hit) : null);
        }
Пример #5
0
        private void ThrustDamage()
        {
            if (m_flames.Count > 0 && MySession.Static.ThrusterDamage && Sync.IsServer && IsWorking && CubeGrid.InScene && CubeGrid.Physics != null && CubeGrid.Physics.Enabled)
            {
                if (CurrentStrength == 0 && !MyFakes.INACTIVE_THRUSTER_DMG)
                {
                    return;
                }

                UpdateThrustFlame();

                foreach (var flameInfo in m_flames)
                {
                    var     l = GetDamageCapsuleLine(flameInfo);
                    HkShape shape;
                    if (l.Length != 0)
                    {
                        shape = new HkCapsuleShape(Vector3.Zero, l.To - l.From, flameInfo.Radius * BlockDefinition.FlameDamageLengthScale);
                    }
                    else
                    {
                        shape = new HkSphereShape(flameInfo.Radius * BlockDefinition.FlameDamageLengthScale);
                    }
                    MyPhysics.GetPenetrationsShape(shape, ref l.From, ref Quaternion.Identity, m_flameCollisionsList, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                    shape.RemoveReference();

                    foreach (var obj in m_flameCollisionsList)
                    {
                        var ent = obj.GetCollisionEntity();
                        if (ent == null || ent.Equals(this))
                        {
                            continue;
                        }

                        if (!(ent is MyCharacter))
                        {
                            ent = ent.GetTopMostParent();
                        }
                        if (m_damagedEntities.Contains(ent))
                        {
                            continue;
                        }
                        else
                        {
                            m_damagedEntities.Add(ent);
                        }

                        if (ent is IMyDestroyableObject)
                        {
                            (ent as IMyDestroyableObject).DoDamage(flameInfo.Radius * BlockDefinition.FlameDamage * 10, MyDamageType.Environment, true, attackerId: EntityId);
                        }
                        else if (ent is MyCubeGrid)
                        {
                            var grid = ent as MyCubeGrid;
                            if (grid.BlocksDestructionEnabled)
                            {
                                DamageGrid(flameInfo, l, grid);
                            }
                        }
                    }
                    m_damagedEntities.Clear();
                    m_flameCollisionsList.Clear();
                }
            }
        }
Пример #6
0
        private MyStringHash RayCastGround()
        {
            MyStringHash walkSurfaceMaterial = new MyStringHash();

            float maxDistValue = MyConstants.DEFAULT_GROUND_SEARCH_DISTANCE;
            var   from         = m_character.PositionComp.GetPosition() + m_character.PositionComp.WorldMatrix.Up * 0.5; //(needs some small distance from the bottom or the following call to HavokWorld.CastRay will find no hits)
            var   to           = from + m_character.PositionComp.WorldMatrix.Down * maxDistValue;

            MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.CharacterCollisionLayer);

            // Skips invalid hits (null body, self character)
            int index = 0;

            while ((index < m_hits.Count) && ((m_hits[index].HkHitInfo.Body == null) || (m_hits[index].HkHitInfo.GetHitEntity() == Entity.Components)))
            {
                index++;
            }

            if (m_hits.Count == 0)
            {
                if ((m_standingOnGrid != null || m_standingOnVoxel != null) && ShouldUpdateSoundEmitters)
                {
                    m_standingOnGrid  = null;
                    m_standingOnVoxel = null;
                    MyEntity3DSoundEmitter.UpdateEntityEmitters(true, true, false);
                }
                else
                {
                    m_standingOnGrid  = null;
                    m_standingOnVoxel = null;
                }
            }

            if (index < m_hits.Count)
            {
                // We must take only closest hit (others are hidden behind)
                var h      = m_hits[index];
                var entity = h.HkHitInfo.GetHitEntity();

                var sqDist = Vector3D.DistanceSquared((Vector3D)h.Position, from);
                if (sqDist < maxDistValue * maxDistValue)
                {
                    var cubeGrid  = entity as MyCubeGrid;
                    var voxelBase = entity as MyVoxelBase;

                    if (((cubeGrid != null && m_standingOnGrid != cubeGrid) || (voxelBase != null && m_standingOnVoxel != voxelBase)) && ShouldUpdateSoundEmitters)
                    {
                        m_standingOnGrid  = cubeGrid;
                        m_standingOnVoxel = voxelBase;
                        MyEntity3DSoundEmitter.UpdateEntityEmitters(true, true, true);
                    }
                    else
                    {
                        m_standingOnGrid  = cubeGrid;
                        m_standingOnVoxel = voxelBase;
                    }
                    if (cubeGrid != null || voxelBase != null)
                    {
                        m_jumpReady = true;
                    }

                    if (cubeGrid != null)
                    {
                        walkSurfaceMaterial = cubeGrid.Physics.GetMaterialAt(h.Position + m_character.PositionComp.WorldMatrix.Down * 0.1f);
                    }
                    else if (voxelBase != null && voxelBase.Storage != null && voxelBase.Storage.DataProvider != null)
                    {
                        var materialDefinition = voxelBase.GetMaterialAt(ref h.Position);
                        if (materialDefinition != null)
                        {
                            walkSurfaceMaterial = MyStringHash.GetOrCompute(materialDefinition.MaterialTypeName);
                        }
                    }
                    if (walkSurfaceMaterial.ToString().Length == 0)
                    {
                        walkSurfaceMaterial = MyMaterialType.ROCK;
                    }
                }
            }

            m_hits.Clear();

            return(walkSurfaceMaterial);
        }
Пример #7
0
        private void GetHitEntityAndPosition(LineD line, out IMyEntity entity, out MyHitInfo hitInfoRet, out object customdata)
        {
            entity     = null;
            hitInfoRet = new MyHitInfo();
            customdata = null;

            // 1. rough raycast
            int raycastListIndex = 0;

            do
            {
                if (entity == null)
                {
                    if (raycastListIndex == 0) // cast only the first iteration
                    {
                        ProfilerShort.Begin("MyGamePruningStructure::CastProjectileRay");
                        MyPhysics.CastRay(line.From, line.To, m_raycastResult,
                                          MyPhysics.CollisionLayers.DefaultCollisionLayer);
                        ProfilerShort.End();
                    }

                    if (raycastListIndex < m_raycastResult.Count)
                    {
                        MyPhysics.HitInfo hitInfo = m_raycastResult[raycastListIndex];

                        entity = hitInfo.HkHitInfo.GetHitEntity() as MyEntity;
                        hitInfoRet.Position = hitInfo.Position;
                        hitInfoRet.Normal   = hitInfo.HkHitInfo.Normal;
                        hitInfoRet.ShapeKey = hitInfo.HkHitInfo.GetShapeKey(0);
                    }
                }

                // 2. prevent shooting through characters, retest trajectory between entity and player
                if (!(entity is MyCharacter) || entity == null)
                {
                    // first: raycast, get all entities in line, limit distance if possible
                    LineD lineLimited = new LineD(line.From, entity == null ? line.To : hitInfoRet.Position);
                    if (m_entityRaycastResult == null)
                    {
                        m_entityRaycastResult = new List <MyLineSegmentOverlapResult <MyEntity> >(16);
                    }
                    else
                    {
                        m_entityRaycastResult.Clear();
                    }
                    MyGamePruningStructure.GetAllEntitiesInRay(ref lineLimited, m_entityRaycastResult);
                    // second: precise tests, find best result
                    double    bestDistanceSq = double.MaxValue;
                    IMyEntity entityBest     = null;
                    for (int i = 0; i < m_entityRaycastResult.Count; i++)
                    {
                        if (m_entityRaycastResult[i].Element is MyCharacter)
                        {
                            MyCharacter hitCharacter = m_entityRaycastResult[i].Element as MyCharacter;
                            bool        intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                            if (intersection)
                            {
                                double distanceSq =
                                    Vector3D.DistanceSquared(m_charHitInfo.Triangle.IntersectionPointInWorldSpace,
                                                             line.From);
                                if (distanceSq < bestDistanceSq && !IsIgnoredEntity(hitCharacter))
                                {
                                    bestDistanceSq      = distanceSq;
                                    entityBest          = hitCharacter;
                                    hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                                    hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                                    customdata          = m_charHitInfo;
                                }
                            }
                        }
                    }
                    // finally: do we have best result? then return it
                    if (entityBest != null)
                    {
                        entity = entityBest;
                        return; // this was precise result, so return
                    }
                }

                // 3. nothing found in the precise test? then fallback to already found results
                if (entity == null)
                {
                    return;                // no fallback results
                }
                if (entity is MyCharacter) // retest character found in fallback
                {
                    MyCharacter hitCharacter = entity as MyCharacter;
                    bool        intersection = hitCharacter.GetIntersectionWithLine(ref line, ref m_charHitInfo);
                    if (intersection)
                    {
                        hitInfoRet.Position = m_charHitInfo.Triangle.IntersectionPointInWorldSpace;
                        hitInfoRet.Normal   = m_charHitInfo.Triangle.NormalInWorldSpace;
                        customdata          = m_charHitInfo;
                    }
                    else
                    {
                        entity = null; // no hit.
                    }
                }
                else
                {
                    MyCubeGrid grid = entity as MyCubeGrid;
                    if (grid != null)
                    {
                        bool success = grid.GetIntersectionWithLine(ref line, ref m_cubeGridHitInfo);
                        if (success)
                        {
                            hitInfoRet.Position = m_cubeGridHitInfo.Triangle.IntersectionPointInWorldSpace;
                            hitInfoRet.Normal   = m_cubeGridHitInfo.Triangle.NormalInWorldSpace;
                            if (Vector3.Dot(hitInfoRet.Normal, line.Direction) > 0)
                            {
                                hitInfoRet.Normal = -hitInfoRet.Normal;
                            }

                            customdata = m_cubeGridHitInfo;
                        }

                        MyHitInfo info = new MyHitInfo();
                        info.Position = hitInfoRet.Position;
                        info.Normal   = hitInfoRet.Normal;
                    }
                }
            } while (entity == null && ++raycastListIndex < m_entityRaycastResult.Count);
        }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <returns>False if no correct position was found</returns>
        private void HandleIntersection(MyEntity controlledEntity)
        {
            Debug.Assert(controlledEntity != null);
            MyEntity parentEntity           = controlledEntity.GetTopMostParent() ?? controlledEntity;
            var      parentEntityAsCubeGrid = parentEntity as MyCubeGrid;

            if (parentEntityAsCubeGrid != null && parentEntityAsCubeGrid.IsStatic)
            {
                parentEntity = controlledEntity;  // cancel previous assignment, topmost parent is a station, we need smaller bounding box
            }
            // line from target to eye
            LineD line = new LineD(m_target, m_position);
            // oriented bb of the entity
            MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity);
            // oriented bb of the entity + camera radius
            MyOrientedBoundingBoxD safeObbWithCollisionExtents =
                new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation);

            // start = target, end = eye
            // find safe start...
            LineD    safeOBBLine      = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From);
            double?  safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
            Vector3D castStartSafe    = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;

            if (controlledEntity.Parent != null && safeIntersection != null)
            {
                MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe);
                HkShape hkSphere       = new HkSphereShape(CAMERA_RADIUS * 2);
                var     hitInfo        = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0);

                //VRageRender.MyRenderProxy.DebugDrawCapsule(castStartSafe, m_target, CAMERA_RADIUS * 2, Color.Orange, false);

                MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null;
                MyEntity entity    = controlledEntity;

                var hitEntityWeldingGroup = hitEntity != null?MyWeldingGroups.Static.GetGroup(hitEntity) : null;

                bool weldingGroupEquals = false;

                while (entity != null && !weldingGroupEquals)
                {
                    if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity))
                    {
                        weldingGroupEquals = true;
                    }

                    entity = entity.Parent;
                }

                if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals)
                {
                    castStartSafe = castStartSafe + hitInfo.Value.HkHitInfo.HitFraction * (m_target - castStartSafe);
                }
                else
                {
                    safeObb = GetEntitySafeOBB(controlledEntity);
                    safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation);
                    safeIntersection            = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                    castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target;
                }
                hkSphere.RemoveReference();
            }

            // raycast against occluders
            Vector3D safePositionCandidate;

            //double lastSafeMinimumDistance = m_safeMinimumDistance;
            m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist
            m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE);
            //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance)
            //{
            //    castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance;
            //    m_safeMinimumDistance = lastSafeMinimumDistance;
            //}
            Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe;
            MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position,
                                                                          ref castStartSafe, out safePositionCandidate);

            // visual debugging :)
            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true);
                VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple,
                                                           false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red,
                                                           false);
                VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false);

                VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 1.0f, Color.LightPink, 1, false);
            }

            switch (raycastResult)
            {
            case MyCameraRaycastResult.Ok:
            case MyCameraRaycastResult.FoundOccluder:
                m_positionCurrentIsSafe = true;
                {
                    double distFromCandidateToTarget = (safePositionCandidate - m_target).Length();
                    if (m_disableSpringThisFrame)
                    {
                        m_lastRaycastDist = (float)distFromCandidateToTarget;
                    }

                    if (!m_disableSpringThisFrame &&
                        ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance) ||
                         raycastResult == MyCameraRaycastResult.Ok))
                    {
                        // now we need it from the other side
                        double newDist = (safePositionCandidate - m_position).Length();
                        // new safe position is further from target => change over time (zoom out)
                        if (m_positionSafeZoomingOutTimeout <= 0)
                        {
                            float distDiffZoomSpeed = 1 -
                                                      MathHelper.Clamp((float)Math.Abs(m_lastRaycastDist - newDist), 0.0f,
                                                                       1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                            m_positionSafeZoomingOutSpeed += distDiffZoomSpeed;
                            m_positionSafeZoomingOutSpeed  = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f,
                                                                              1.0f);

                            Vector3D targetToPosSafe     = m_positionSafe - m_target;
                            double   lenTargetToPosSafe  = targetToPosSafe.Length();
                            Vector3D rotatedPositionSafe = m_target +
                                                           Vector3D.Normalize(safePositionCandidate - m_target) *
                                                           lenTargetToPosSafe;
                            m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate,
                                                           m_positionSafeZoomingOutSpeed);
                        }
                        else
                        {
                            m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS;

                            Vector3D targetToPosSafe    = m_positionSafe - m_target;
                            double   lenTargetToPosSafe = targetToPosSafe.Length();
                            m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe;
                        }
                    }
                    else
                    {
                        // new safe position is closer or closer than safe distance => instant change
                        m_positionSafeZoomingOutSpeed   = 0.0f; // set zooming out speed to zero for next time
                        m_positionSafeZoomingOutTimeout = 0;    // controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0;
                        m_positionSafe           = safePositionCandidate;
                        m_disableSpringThisFrame = true;
                    }
                }
                break;

            //case MyCameraRaycastResult.FoundOccluderNoSpace:
            default:
                m_positionSafeZoomingOutSpeed = 1.0f;     // we're in first person, change instantly to third if possible
                m_positionCurrentIsSafe       = false;
                break;
            }

            m_lastRaycastDist = (float)(m_positionSafe - m_position).Length();

            if (m_debugDraw)
            {
                VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false);
                VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false);
            }
        }
Пример #9
0
        public override bool Update(bool hasFocus)
        {
            m_ticks = MyPerformanceCounter.ElapsedTicks;
            m_frameCounter++;

            double secondsFromStart = MyPerformanceCounter.TicksToMs(m_ticks - m_startTime) / 1000;

            if (secondsFromStart > 1)
            {
                double updateLagOverMeasureTime = (secondsFromStart - m_frameCounter * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);
                m_updateLag = updateLagOverMeasureTime / secondsFromStart * 1000;

                m_startTime    = m_ticks;
                m_frameCounter = 0;

                if (Sync.Layer != null)
                {
                    m_sentLastSec     = (Sync.Layer.TransportLayer.ByteCountSent - m_lastSent) / secondsFromStart;
                    m_receivedLastSec = (Sync.Layer.TransportLayer.ByteCountReceived - m_lastReceived) / secondsFromStart;

                    m_lastReceived = Sync.Layer.TransportLayer.ByteCountReceived;
                    m_lastSent     = Sync.Layer.TransportLayer.ByteCountSent;
                }
            }

            Stats.Timing.Write("FPS", MyFpsManager.GetFps(), VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);
            Stats.Timing.Increment("UPS", 1000);
            Stats.Timing.Write("Simulation speed", Sandbox.Engine.Physics.MyPhysics.SimulationRatio, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 2);
            Stats.Timing.Write("Server simulation speed", Sync.ServerSimulationRatio, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 2);
            Stats.Timing.WriteFormat("Frame time: {0} ms", MyFpsManager.FrameTime, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
            Stats.Timing.WriteFormat("Frame avg time: {0} ms", MyFpsManager.FrameTimeAvg, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
            Stats.Timing.WriteFormat("Frame min time: {0} ms", MyFpsManager.FrameTimeMin, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
            Stats.Timing.WriteFormat("Frame max time: {0} ms", MyFpsManager.FrameTimeMax, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
            Stats.Timing.Write("Update lag (per s)", (float)m_updateLag, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 4);
            Stats.Timing.Write("GC Memory", GC.GetTotalMemory(false), VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);
#if !XB1
            Stats.Timing.Write("Process memory", WinApi.WorkingSet, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);
#endif // !XB1
            Stats.Timing.Write("Active parcticle effects", MyParticlesManager.ParticleEffectsForUpdate.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);
            //Stats.Timing.Write("Billboards total", VRageRender.MyPerformanceCounter.PerCameraDraw11Read.BillboardsDrawn, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);

            if (MyPhysics.GetClusterList() != null)
            {
                double i   = 0.0;
                double sum = 0.0;
                double max = 0.0;
                foreach (Havok.HkWorld havokWorld in MyPhysics.GetClusterList())
                {
                    i += 1.0;
                    var value = havokWorld.StepDuration.TotalMilliseconds;
                    sum += value;
                    if (value > max)
                    {
                        max = value;
                    }
                }
                Stats.Timing.WriteFormat("Physics worlds count: {0}", (float)i, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 0);
                Stats.Timing.WriteFormat("Physics step time (sum): {0} ms", (float)sum, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
                Stats.Timing.WriteFormat("Physics step time (avg): {0} ms", (float)(sum / i), VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
                Stats.Timing.WriteFormat("Physics step time (max): {0} ms", (float)max, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 1);
            }

            if (Sync.Layer != null)
            {
                Stats.Timing.Write("Received KB/s", (float)m_receivedLastSec / 1024, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 2);
                Stats.Timing.Write("Sent KB/s", (float)m_sentLastSec / 1024, VRage.Stats.MyStatTypeEnum.CurrentValue, 0, 2);
            }

            return(base.Update(hasFocus));
        }
        /// <summary>
        /// Returns true if the given small block connects to large one. One of the given AABB's is inflated with 0.05 to reduce inaccuracies.
        /// </summary>
        /// <param name="smallBlock">small block</param>
        /// <param name="smallBlockWorldAabb">small block world AABB</param>
        /// <param name="largeBlock">large block</param>
        /// <param name="largeBlockWorldAabb">large block wotld AABB</param>
        /// <returns>true when connected</returns>
        private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb)
        {
            Debug.Assert(GetCubeSize(smallBlock) == MyCubeSize.Small);
            Debug.Assert(GetCubeSize(largeBlock) == MyCubeSize.Large);
            Debug.Assert(!(smallBlock.FatBlock is MyCompoundCubeBlock));
            Debug.Assert(!(largeBlock.FatBlock is MyCompoundCubeBlock));

            BoundingBoxD smallBlockWorldAabbReduced = smallBlockWorldAabb;

            smallBlockWorldAabbReduced.Inflate(-smallBlock.CubeGrid.GridSize / 4);

            // Small block aabb penetrates large block aabb (large timbers).
            bool penetratesAabbs = largeBlockWorldAabb.Intersects(smallBlockWorldAabbReduced);

            if (!penetratesAabbs)
            {
                Vector3I addDir = GetSmallBlockAddDirection(ref smallBlockWorldAabb, ref smallBlockWorldAabbReduced, ref largeBlockWorldAabb);
                // Check small grid mount points
                Quaternion smallBlockRotation;
                smallBlock.Orientation.GetQuaternion(out smallBlockRotation);
                smallBlockRotation = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * smallBlockRotation;
                if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref smallBlockRotation, ref addDir))
                {
                    return(false);
                }
            }

            BoundingBoxD smallBlockWorldAabbInflated = smallBlockWorldAabb;

            smallBlockWorldAabbInflated.Inflate(2 * smallBlock.CubeGrid.GridSize / 3);

            // Trim small block aabb with large block aabb.
            BoundingBoxD intersectedBox       = smallBlockWorldAabbInflated.Intersect(largeBlockWorldAabb);
            Vector3D     intersectedBoxCenter = intersectedBox.Center;
            HkShape      shape = new HkBoxShape((Vector3)intersectedBox.HalfExtents);

            Quaternion largeRotation;

            largeBlock.Orientation.GetQuaternion(out largeRotation);
            largeRotation = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * largeRotation;
            Vector3D largeTranslation;

            largeBlock.ComputeWorldCenter(out largeTranslation);

            bool result = false;

            try
            {
                if (largeBlock.FatBlock != null)
                {
                    MyModel model = largeBlock.FatBlock.Model;
                    if (model != null)
                    {
                        HkShape[] shapes = model.HavokCollisionShapes;
                        if (shapes == null || shapes.Length == 0)
                        {
                            return(false);
                        }

                        for (int i = 0; i < shapes.Length; ++i)
                        {
                            result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapes[i], ref largeTranslation, ref largeRotation);
                            if (result)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                        result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                        shapeLarge.RemoveReference();
                    }
                }
                else
                {
                    HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                    result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                    shapeLarge.RemoveReference();
                }
            }
            finally
            {
                shape.RemoveReference();
            }

            return(result);
        }
Пример #11
0
        protected MyMotorRotor FindMatchingRotor()
        {
            Debug.Assert(CubeGrid != null);
            Debug.Assert(m_penetrations != null);
            Debug.Assert(CubeGrid.Physics != null);
            if (CubeGrid == null)
            {
                MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): Cube grid == null!");
                return(null);
            }

            if (m_penetrations == null)
            {
                MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): penetrations cache == null!");
                return(null);
            }

            if (CubeGrid.Physics == null)
            {
                MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): Cube grid physics == null!");
                return(null);
            }

            Quaternion orientation;
            Vector3D   pos;
            Vector3    halfExtents;

            ComputeRotorQueryBox(out pos, out halfExtents, out orientation);
            try
            {
                MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref orientation, m_penetrations, MyPhysics.DefaultCollisionLayer);
                foreach (var obj in m_penetrations)
                {
                    if (obj == null)
                    {
                        continue;
                    }

                    if (obj == CubeGrid.Physics.RigidBody || obj == CubeGrid.Physics.RigidBody2)
                    {
                        continue;
                    }

                    var entity = obj.GetEntity();
                    if (entity == null)
                    {
                        continue;
                    }

                    var grid = entity as MyCubeGrid;
                    if (grid == null)
                    {
                        continue;
                    }

                    // Rotor should always be on position [0,0,0];
                    var pos2     = Vector3.Transform(DummyPosition, CubeGrid.WorldMatrix);
                    var blockPos = grid.RayCastBlocks(pos2, pos2 + WorldMatrix.Up);
                    if (blockPos.HasValue)
                    {
                        var slimBlock = grid.GetCubeBlock(blockPos.Value);
                        if (slimBlock == null || slimBlock.FatBlock == null)
                        {
                            continue;
                        }

                        var rotor = slimBlock.FatBlock as MyMotorRotor;
                        if (rotor != null)
                        {
                            return(rotor);
                        }
                    }
                }
            }
            finally
            {
                m_penetrations.Clear();
            }
            return(null);
        }
Пример #12
0
        public override void UpdateBeforeSimulation()
        {
            int num = 0;

            if ((m_rayCastQueue.Count > 0) && ((this.m_rayCastCounter % 20) == 0))
            {
                while ((num < 50) && (m_rayCastQueue.Count > 0))
                {
                    int                 randomInt = MyUtils.GetRandomInt(m_rayCastQueue.Count - 1);
                    MyEntity            entity    = m_rayCastQueue[randomInt].Entity;
                    MyEntityRayCastPair local1    = m_rayCastQueue[randomInt];
                    Vector3D            position  = m_rayCastQueue[randomInt].Position;
                    MyParticleEffect    particle  = m_rayCastQueue[randomInt].Particle;
                    if (entity is MyCubeGrid)
                    {
                        particle.Stop(true);
                        MyCubeGrid grid = entity as MyCubeGrid;
                        MatrixD    worldMatrixNormalizedInv = grid.PositionComp.WorldMatrixNormalizedInv;
                        if (grid.BlocksDestructionEnabled)
                        {
                            grid.Physics.ApplyDeformation(6f, 3f, 3f, (Vector3)Vector3.Transform((Vector3)position, worldMatrixNormalizedInv), Vector3.Normalize(Vector3.Transform((Vector3)m_directionFromSunNormalized, worldMatrixNormalizedInv)), MyDamageType.Environment, 0f, 0f, 0L);
                        }
                        m_rayCastQueue.RemoveAt(randomInt);
                        this.m_hitLst.Clear();
                        break;
                    }
                }
            }
            this.m_rayCastCounter++;
            if (IsActive)
            {
                float num2 = (MySandboxGame.TotalGamePlayTimeInMilliseconds - m_timeLastUpdate) / 1000f;
                m_timeLastUpdate = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                if (!MySandboxGame.IsPaused)
                {
                    m_deltaTime += num2;
                    float num3 = m_speed * m_deltaTime;
                    if (num3 >= 60000f)
                    {
                        IsActive = false;
                        StopCue();
                    }
                    else
                    {
                        Vector3D translation;
                        if (MySession.Static.LocalCharacter != null)
                        {
                            translation = MySession.Static.LocalCharacter.Entity.WorldMatrix.Translation;
                        }
                        else
                        {
                            translation = Vector3D.Zero;
                        }
                        Vector3D point = translation;
                        m_planeMiddle          = new PlaneD(m_initialSunWindPosition + (m_directionFromSunNormalized * num3), m_directionFromSunNormalized);
                        m_distanceToSunWind    = m_planeMiddle.DistanceToPoint(ref point);
                        m_positionOnCameraLine = -m_directionFromSunNormalized * m_distanceToSunWind;
                        Vector3D position = m_positionOnCameraLine + (m_directionFromSunNormalized * 2000.0);
                        Vector3D vectord3 = m_positionOnCameraLine + (m_directionFromSunNormalized * -2000.0);
                        m_planeFront = new PlaneD(position, m_directionFromSunNormalized);
                        m_planeBack  = new PlaneD(vectord3, m_directionFromSunNormalized);
                        m_planeFront.DistanceToPoint(ref point);
                        m_planeBack.DistanceToPoint(ref point);
                        int index = 0;
                        while (index < m_sunwindEntities.Count)
                        {
                            if (m_sunwindEntities[index].MarkedForClose)
                            {
                                m_sunwindEntities.RemoveAtFast <IMyEntity>(index);
                                continue;
                            }
                            index++;
                        }
                        Quaternion orientation = Quaternion.CreateFromRotationMatrix(Matrix.CreateFromDir((Vector3)m_directionFromSunNormalized, (Vector3)m_downVector));
                        Vector3    halfExtents = new Vector3(10000f, 10000f, 2000f);
                        MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(position + (m_directionFromSunNormalized * 2500.0), halfExtents, orientation), Color.Red.ToVector3(), 1f, false, false, false);
                        if (this.m_rayCastCounter == 120)
                        {
                            Vector3D translation = position + (m_directionFromSunNormalized * 2500.0);
                            MyPhysics.GetPenetrationsBox(ref halfExtents, ref translation, ref orientation, m_intersectionLst, 15);
                            using (List <HkBodyCollision> .Enumerator enumerator = m_intersectionLst.GetEnumerator())
                            {
                                while (enumerator.MoveNext())
                                {
                                    IMyEntity collisionEntity = enumerator.Current.GetCollisionEntity();
                                    if (!(collisionEntity is MyVoxelMap) && !m_sunwindEntities.Contains(collisionEntity))
                                    {
                                        m_sunwindEntities.Add(collisionEntity);
                                    }
                                }
                            }
                            m_intersectionLst.Clear();
                            int num6 = 0;
                            while (true)
                            {
                                if (num6 >= m_sunwindEntities.Count)
                                {
                                    this.m_rayCastCounter = 0;
                                    break;
                                }
                                IMyEntity item = m_sunwindEntities[num6];
                                if (item is MyCubeGrid)
                                {
                                    MyCubeGrid   grid2     = item as MyCubeGrid;
                                    BoundingBoxD worldAABB = grid2.PositionComp.WorldAABB;
                                    double       num7      = (worldAABB.Center - worldAABB.Min).Length();
                                    double       num8      = ((worldAABB.Center - worldAABB.Min) / m_rightVector).AbsMin();
                                    double       num9      = ((worldAABB.Center - worldAABB.Min) / m_downVector).AbsMin();
                                    Vector3I     vectori   = grid2.Max - grid2.Min;
                                    Math.Max(vectori.X, Math.Max(vectori.Y, vectori.Z));
                                    MatrixD  worldMatrixNormalizedInv = grid2.PositionComp.WorldMatrixNormalizedInv;
                                    Vector3D vectord6 = (worldAABB.Center - (num8 * m_rightVector)) - (num9 * m_downVector);
                                    int      num10    = 0;
                                    while (true)
                                    {
                                        if (num10 >= (num8 * 2.0))
                                        {
                                            m_sunwindEntities.Remove(grid2);
                                            num6--;
                                            break;
                                        }
                                        int num11 = 0;
                                        while (true)
                                        {
                                            if (num11 >= (num9 * 2.0))
                                            {
                                                num10 += (grid2.GridSizeEnum == MyCubeSize.Large) ? 0x19 : 10;
                                                break;
                                            }
                                            Vector3D to          = ((vectord6 + (num10 * m_rightVector)) + (num11 * m_downVector)) + (((float)num7) * m_directionFromSunNormalized);
                                            Vector3  vector2     = MyUtils.GetRandomVector3CircleNormalized();
                                            float    randomFloat = MyUtils.GetRandomFloat(0f, (grid2.GridSizeEnum == MyCubeSize.Large) ? ((float)10) : ((float)5));
                                            to += ((m_rightVector * vector2.X) * randomFloat) + ((m_downVector * vector2.Z) * randomFloat);
                                            LineD ed = new LineD(to - (m_directionFromSunNormalized * ((float)num7)), to);
                                            if (grid2.RayCastBlocks(ed.From, ed.To) != null)
                                            {
                                                ed.From = to - (m_directionFromSunNormalized * 1000.0);
                                                MyPhysics.CastRay(ed.From, ed.To, this.m_hitLst, 0);
                                                this.m_rayCastCounter++;
                                                if ((this.m_hitLst.Count == 0) || !ReferenceEquals(this.m_hitLst[0].HkHitInfo.GetHitEntity(), grid2.Components))
                                                {
                                                    this.m_hitLst.Clear();
                                                }
                                                else
                                                {
                                                    MyParticleEffect effect2;
                                                    MyParticlesManager.TryCreateParticleEffect("Dummy", MatrixD.CreateWorld(this.m_hitLst[0].Position, Vector3D.Forward, Vector3D.Up), out effect2);
                                                    MyEntityRayCastPair pair = new MyEntityRayCastPair {
                                                        Entity   = grid2,
                                                        _Ray     = ed,
                                                        Position = this.m_hitLst[0].Position,
                                                        Particle = effect2
                                                    };
                                                    m_rayCastQueue.Add(pair);
                                                }
                                            }
                                            num11 += (grid2.GridSizeEnum == MyCubeSize.Large) ? 0x19 : 10;
                                        }
                                    }
                                }
                                else
                                {
                                    m_sunwindEntities.Remove(item);
                                    num6--;
                                }
                                num6++;
                            }
                        }
                        if (m_distanceToSunWind <= 10000.0)
                        {
                            m_smallBillboardsStarted = true;
                        }
                        ComputeMaxDistances();
                        base.UpdateBeforeSimulation();
                    }
                }
            }
        }
Пример #13
0
 void Start()
 {
     physics = FindObjectOfType <MyPhysics> ();
 }
        public override void UpdateBeforeSimulation100()
        {
            base.UpdateBeforeSimulation100();
            Debug.Assert(m_initialized, "SolarGameLogic was not initialized before use!");

            if (m_solarBlock.CubeGrid.Physics == null)
            {
                return;
            }

            float angleToSun = Vector3.Dot(Vector3.Transform(m_panelOrientation, m_solarBlock.WorldMatrix.GetOrientation()), MySector.DirectionToSunNormalized);

            if ((angleToSun < 0 && !m_isTwoSided) || !m_solarBlock.IsFunctional)
            {
                m_maxOutput = 0;
                return;
            }

            m_currentPivot %= 8;

            MatrixD rot   = m_solarBlock.WorldMatrix.GetOrientation();
            float   scale = (float)m_solarBlock.WorldMatrix.Forward.Dot(Vector3.Transform(m_panelOrientation, rot));
            float   unit  = m_solarBlock.BlockDefinition.CubeSize == MyCubeSize.Large ? 2.5f : 0.5f;

            Vector3D pivot = m_solarBlock.WorldMatrix.Translation;

            pivot += ((m_currentPivot % 4 - 1.5f) * unit * scale * (m_solarBlock.BlockDefinition.Size.X / 4f)) * m_solarBlock.WorldMatrix.Left;
            pivot += ((m_currentPivot / 4 - 0.5f) * unit * scale * (m_solarBlock.BlockDefinition.Size.Y / 2f)) * m_solarBlock.WorldMatrix.Up;
            pivot += unit * scale * (m_solarBlock.BlockDefinition.Size.Z / 2f) * Vector3.Transform(m_panelOrientation, rot) * m_panelOffset;

            LineD l = new LineD(pivot + MySector.DirectionToSunNormalized * 1000, pivot + MySector.DirectionToSunNormalized * m_solarBlock.CubeGrid.GridSize / 4); //shadows are drawn only 1000m

            MyPhysics.CastRay(l.From, l.To, m_hitList);
            m_pivotInSun[m_currentPivot] = true;
            foreach (var hit in m_hitList)
            {
                var ent = hit.HkHitInfo.GetHitEntity();
                if (ent != m_solarBlock.CubeGrid)
                {
                    m_pivotInSun[m_currentPivot] = false;
                    break;
                }
                else
                {
                    var grid = ent as MyCubeGrid;
                    var pos  = grid.RayCastBlocks(l.From, l.To);
                    if (pos.HasValue && grid.GetCubeBlock(pos.Value) != m_solarBlock.SlimBlock)
                    {
                        m_pivotInSun[m_currentPivot] = false;
                        break;
                    }
                }
            }
            int pivotsInSun = 0;

            foreach (bool p in m_pivotInSun)
            {
                if (p)
                {
                    pivotsInSun++;
                }
            }

            m_maxOutput = angleToSun;
            if (m_maxOutput < 0)
            {
                if (m_isTwoSided)
                {
                    m_maxOutput = Math.Abs(m_maxOutput);
                }
                else
                {
                    m_maxOutput = 0;
                }
            }
            m_maxOutput *= pivotsInSun / 8f;
            m_currentPivot++;
        }
Пример #15
0
        public static List <CollectibleInfo> FindCollectiblesInRadius(Vector3D fromPosition, double radius, bool doRaycast = false)
        {
            Debug.Assert(m_retvalCollectibleInfos.Count == 0, "The result of the last call of FindComponentsInRadius was not cleared!");

            List <MyPhysics.HitInfo> hits = new List <MyPhysics.HitInfo>();

            BoundingSphereD sphere   = new BoundingSphereD(fromPosition, radius);
            var             entities = MyEntities.GetEntitiesInSphere(ref sphere);

            foreach (var entity in entities)
            {
                bool addCollectibleInfo = false;

                CollectibleInfo info  = new CollectibleInfo();
                MyCubeBlock     block = null;
                MyCubeGrid      grid  = TryGetAsComponent(entity, out block);
                if (grid != null)
                {
                    info.EntityId     = grid.EntityId;
                    info.DefinitionId = GetComponentId(block.SlimBlock);
                    if (block.BlockDefinition.Components != null)
                    {
                        info.Amount = block.BlockDefinition.Components[0].Count;
                    }
                    else
                    {
                        Debug.Assert(false, "Block definition does not have any components!");
                        info.Amount = 0;
                    }
                    addCollectibleInfo = true;
                }
                else if (entity is MyFloatingObject)
                {
                    var floatingObj = entity as MyFloatingObject;
                    var defId       = floatingObj.Item.Content.GetObjectId();
                    if (MyDefinitionManager.Static.GetPhysicalItemDefinition(defId).Public)
                    {
                        info.EntityId      = floatingObj.EntityId;
                        info.DefinitionId  = defId;
                        info.Amount        = floatingObj.Item.Amount;
                        addCollectibleInfo = true;
                    }
                }

                if (addCollectibleInfo)
                {
                    bool hitSomething = false;
                    MyPhysics.CastRay(fromPosition, entity.WorldMatrix.Translation, hits, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                    foreach (var hit in hits)
                    {
                        var hitEntity = hit.HkHitInfo.GetHitEntity();
                        if (hitEntity == entity)
                        {
                            continue;
                        }
                        if (hitEntity is MyCharacter)
                        {
                            continue;
                        }
                        if (hitEntity is MyFracturedPiece)
                        {
                            continue;
                        }
                        if (hitEntity is MyFloatingObject)
                        {
                            continue;
                        }
                        MyCubeBlock dummy = null;
                        if (TryGetAsComponent(hitEntity as MyEntity, out dummy) != null)
                        {
                            continue;
                        }
                        hitSomething = true;
                        break;
                    }

                    if (!hitSomething)
                    {
                        m_retvalCollectibleInfos.Add(info);
                    }
                }
            }
            entities.Clear();

            return(m_retvalCollectibleInfos);
        }
Пример #16
0
	void Start () {
		physics = FindObjectOfType<MyPhysics> ();
	}
        /// <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);
                float closestFraction = 1.0f;
                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;
                    }

                    if (rb.HkHitInfo.HitFraction < closestFraction)
                    {
                        outSafePosition        = Vector3D.Lerp(raycastOrigin, raycastEnd - CAMERA_RADIUS * rayDirection, rb.HkHitInfo.HitFraction);
                        closestDistanceSquared = Vector3D.DistanceSquared(raycastOrigin, outSafePosition);
                        positionChanged        = true;
                        closestFraction        = rb.HkHitInfo.HitFraction;
                    }
                }
                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);
        }
Пример #18
0
        public override bool HandleInput()
        {
            if (base.HandleInput())
            {
                return(true);
            }

            bool handled = false;

            if (MyInput.Static.IsAnyCtrlKeyPressed() && MyInput.Static.IsNewLeftMouseReleased())
            {
                Hammer();
            }

            if (MyInput.Static.IsNewKeyPressed(MyKeys.NumPad1))
            {
                ApplyMassMultiplier = !ApplyMassMultiplier;
                handled             = true;
            }
            var mul = 1;

            if (MyInput.Static.IsKeyPress(MyKeys.N))
            {
                mul = 10;
            }
            if (MyInput.Static.IsKeyPress(MyKeys.B))
            {
                mul = 100;
            }
            if (MyInput.Static.IsNewKeyPressed(MyKeys.OemQuotes))
            {
                if (MassMultiplier > 1)
                {
                    MassMultiplier += mul;
                }
                else
                {
                    MassMultiplier *= mul;
                }
                handled = true;
            }
            if (MyInput.Static.IsNewKeyPressed(MyKeys.OemSemicolon))
            {
                if (MassMultiplier > 1)
                {
                    MassMultiplier -= mul;
                }
                else
                {
                    MassMultiplier /= mul;
                }
                handled = true;
            }

            if (MySector.MainCamera != null)
            {
                List <MyPhysics.HitInfo> lst = new List <MyPhysics.HitInfo>();
                MyPhysics.CastRay(MySector.MainCamera.Position, MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * 100, lst);
                foreach (var hit in lst)
                {
                    VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(600, 10), hit.HkHitInfo.Body.GetEntity().ToString() + " "
                                                              + MyDestructionHelper.MassFromHavok(hit.HkHitInfo.Body.Mass), Color.White, 0.8f);
                    VRageRender.MyRenderProxy.DebugDrawText2D(new Vector2(600, 30), "Layer: " + hit.HkHitInfo.Body.Layer, Color.White, 0.8f);

                    if (hit.HkHitInfo.Body.GetEntity() is MyCubeGrid)
                    {
                        var grid = hit.HkHitInfo.Body.GetEntity() as MyCubeGrid;
                        var det  = grid.GetBlocks().FirstElement().FatBlock.UseObjectsComponent.DetectorPhysics;
                        //var layer = det.RigidBody.Layer;
                    }

                    break;
                }
            }

            if (MyInput.Static.IsNewKeyPressed(MyKeys.NumPad9))
            {
                MyScriptManager.Static.LoadData();
            }

            if (MyAudio.Static != null)
            {
                foreach (var em in MyAudio.Static.Get3DSounds())
                {
                    VRageRender.MyRenderProxy.DebugDrawSphere(em.SourcePosition, 0.1f, Color.Red, 1, false);
                }
            }

            return(handled);
        }
        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
            {
                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;
            }
        }
Пример #20
0
        private void Hammer()
        {
            var   IntersectionStart     = MySector.MainCamera.Position;
            var   IntersectionDirection = MySector.MainCamera.ForwardVector;
            LineD line = new LineD(IntersectionStart, IntersectionStart + IntersectionDirection * 200);

            var m_tmpHitList = new List <MyPhysics.HitInfo>();

            MyPhysics.CastRay(line.From, line.To, m_tmpHitList, MyPhysics.ObjectDetectionCollisionLayer);
            // Remove character hits.
            m_tmpHitList.RemoveAll(delegate(MyPhysics.HitInfo hit)
            {
                return(hit.HkHitInfo.Body.GetEntity() == MySession.ControlledEntity.Entity);
            });

            if (m_tmpHitList.Count == 0)
            {
                return;
            }

            MyEntity closestEntity = null;

            MyPhysics.HitInfo closestHit = default(MyPhysics.HitInfo);

            foreach (var hit in m_tmpHitList)
            {
                if (hit.HkHitInfo.Body != null)
                {
                    closestEntity = hit.HkHitInfo.Body.GetEntity() as MyEntity;
                    closestHit    = hit;
                    break;
                }
            }
            if (closestEntity == null)
            {
                return;
            }
            HkdFractureImpactDetails details = HkdFractureImpactDetails.Create();

            details.SetBreakingBody(closestEntity.Physics.RigidBody);
            details.SetContactPoint(closestEntity.Physics.WorldToCluster(closestHit.Position));
            details.SetDestructionRadius(RADIUS);
            details.SetBreakingImpulse(Sandbox.MyDestructionConstants.STRENGTH * 10);
            if (HammerForce)
            {
                details.SetParticleVelocity(-line.Direction * 20);
            }
            details.SetParticlePosition(closestEntity.Physics.WorldToCluster(closestHit.Position));
            details.SetParticleMass(1000000);
            //details.ZeroColidingParticleVelocity();
            details.Flag = details.Flag | HkdFractureImpactDetails.Flags.FLAG_DONT_RECURSE;
            if (closestEntity.Physics.HavokWorld.DestructionWorld != null)
            {
                MyPhysics.FractureImpactDetails destruction = new MyPhysics.FractureImpactDetails();
                destruction.Details = details;
                destruction.World   = closestEntity.Physics.HavokWorld;
                destruction.Entity  = closestEntity;
                MyPhysics.EnqueueDestruction(destruction);
                //closestGrid.Physics.HavokWorld.DestructionWorld.TriggerDestruction(ref details);
            }
            //details.RemoveReference();
        }
Пример #21
0
        /// <summary>
        /// Performes a physics raycast
        /// It can be recursive (it calls CastDDA when it hits a grid).
        /// </summary>
        /// <param name="fromWorldPos"></param>
        /// <returns>Returns starting damage for current stack</returns>
        private MyRaycastDamageInfo CastPhysicsRay(Vector3D fromWorldPos)
        {
            Vector3D  pos       = Vector3D.Zero;
            IMyEntity hitEntity = null;

            var hitInfo = MyPhysics.CastRay(fromWorldPos, m_explosion.Center, MyPhysics.ExplosionRaycastLayer);

            if (hitInfo.HasValue)
            {
                hitEntity = (hitInfo.Value.HkHitInfo.Body.UserObject != null) ? ((MyPhysicsBody)hitInfo.Value.HkHitInfo.Body.UserObject).Entity : null;
                pos       = hitInfo.Value.Position;
            }
            Vector3D direction      = (m_explosion.Center - fromWorldPos);
            float    lengthToCenter = (float)direction.Length();

            direction.Normalize();

            var grid = (hitEntity as MyCubeGrid);

            if (grid == null)
            {
                MyCubeBlock hitBlock = hitEntity as MyCubeBlock;
                if (hitBlock != null)
                {
                    grid = hitBlock.CubeGrid;
                }
            }
            if (grid != null)
            {
                //Try advancing the point to find the intersected block
                //If the block is a cube, this is necessary because the raycast will return a point somewhere outside the cube
                //If the block is not a full cube (slope, special block), the raycast can return inside the cube
                //It advances 4 times, each time one 8th the grid size
                for (int i = 0; i < 5; i++)
                {
                    Vector3D localPos  = Vector3D.Transform(pos, grid.PositionComp.WorldMatrixNormalizedInv) / grid.GridSize;
                    Vector3I gridPos   = Vector3I.Round(localPos);
                    var      cubeBlock = grid.GetCubeBlock(gridPos);
                    if (cubeBlock != null)
                    {
                        if (m_castBlocks.Contains(cubeBlock))
                        {
                            //This shouldn't happen
                            //There is a corner case where the explosion position is inside the empty cell, but this should be handleded somewhere higher
                            System.Diagnostics.Debug.Fail("Raycast failed!");
                            DrawRay(fromWorldPos, pos, Color.Red);
                            return(new MyRaycastDamageInfo(0f, lengthToCenter));
                        }
                        else
                        {
                            if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS)
                            {
                                DrawRay(fromWorldPos, pos, Color.Blue);
                            }
                            return(CastDDA(cubeBlock));
                        }
                    }
                    pos += direction * grid.GridSize / 8f;
                }
                //We hit a grid but were unable to find the hit cube. Send another raycast
                //Ideally, we would want to get the cube in all cases, but it also has to be fast
                //We need to check if the explosion center is between the initial start position (fromWorldPos) and the new one (pos)

                Vector3D min = new Vector3D(Math.Min(fromWorldPos.X, pos.X), Math.Min(fromWorldPos.Y, pos.Y), Math.Min(fromWorldPos.Z, pos.Z));
                Vector3D max = new Vector3D(Math.Max(fromWorldPos.X, pos.X), Math.Max(fromWorldPos.Y, pos.Y), Math.Max(fromWorldPos.Z, pos.Z));

                BoundingBoxD boundingBox = new BoundingBoxD(min, max);
                if (boundingBox.Contains(m_explosion.Center) == ContainmentType.Contains)
                {
                    return(new MyRaycastDamageInfo(m_explosionDamage, lengthToCenter));
                }

                stackOverflowGuard++;
                if (stackOverflowGuard > MAX_PHYSICS_RECURSION_COUNT)
                {
                    System.Diagnostics.Debug.Fail("Potential stack overflow!");
                    if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS)
                    {
                        DrawRay(fromWorldPos, pos, Color.Red);
                    }
                    return(new MyRaycastDamageInfo(0f, lengthToCenter));
                }
                else
                {
                    if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS)
                    {
                        DrawRay(fromWorldPos, pos, Color.White);
                    }
                    return(CastPhysicsRay(pos));
                }
            }
            else if (hitInfo.HasValue)
            {
                //Something was hit, but it wasn't a grid. This needs to be handled somehow
                if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS)
                {
                    DrawRay(fromWorldPos, pos, Color.Violet);
                }
                return(new MyRaycastDamageInfo(0, lengthToCenter));
            }

            //Nothing was hit, so we can assume the there was nothing blocking the explosion
            if (MyDebugDrawSettings.DEBUG_DRAW_EXPLOSION_HAVOK_RAYCASTS)
            {
                DrawRay(fromWorldPos, pos, Color.Salmon);
            }
            return(new MyRaycastDamageInfo(m_explosionDamage, lengthToCenter));
        }
Пример #22
0
        private void TrySpawnBot()
        {
            Vector3D cameraPos, cameraDir;

            if (MySession.Static.GetCameraControllerEnum() == MyCameraControllerEnum.ThirdPersonSpectator || MySession.Static.GetCameraControllerEnum() == MyCameraControllerEnum.Entity)
            {
                var headMatrix = MySession.Static.ControlledEntity.GetHeadMatrix(true, true);
                cameraPos = headMatrix.Translation;
                cameraDir = headMatrix.Forward;
            }
            else
            {
                cameraPos = MySector.MainCamera.Position;
                cameraDir = MySector.MainCamera.WorldMatrix.Forward;
            }


            List<MyPhysics.HitInfo> hitInfos = new List<MyPhysics.HitInfo>();

            var line = new LineD(MySector.MainCamera.Position, MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * 1000);

            MyPhysics.CastRay(line.From, line.To, hitInfos, MyPhysics.CollisionLayers.DefaultCollisionLayer);

            //MyPhysics.CastRay(cameraPos, cameraPos + cameraDir * 1000, hitInfos, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);
            if (hitInfos.Count == 0)
            //return;
            {
                MyAIComponent.Static.SpawnNewBot(BotToSpawn, cameraPos);
                return;
            }

            MyPhysics.HitInfo? closestValidHit = null;
            foreach (var hitInfo in hitInfos)
            {
                var ent = hitInfo.HkHitInfo.GetHitEntity();
                if (ent is MyCubeGrid)
                {
                    closestValidHit = hitInfo;
                    break;
                }
                else if (ent is MyVoxelBase)
                {
                    closestValidHit = hitInfo;
                    break;
                }
                else if (ent is MyVoxelPhysics)
                {
                    closestValidHit = hitInfo;
                    break;
                }
            }

            /*
            if (closestValidHit.HasValue)
            {
                Vector3D position = closestValidHit.Value.Position;
                MyAIComponent.Static.SpawnNewBot(BotToSpawn, position);
            }
             */
            Vector3D position;
            if (closestValidHit.HasValue)
                position = closestValidHit.Value.Position;
            else
                position = MySector.MainCamera.Position;

            MyAIComponent.Static.SpawnNewBot(BotToSpawn, position);
            
        }
        public override void Draw()
        {
            base.Draw();

            if (!MyFakes.ENABLE_ARMOR_HAND)
            {
                return;
            }

            Vector3  forward = MySector.MainCamera.ForwardVector;
            Vector3D origin  = MySector.MainCamera.Position;
            Vector3D end     = origin + forward * 100f;

            m_lastCubeGrid = null;
            m_lastBone     = null;

            var hitInfo   = MyPhysics.CastRay(origin, end, MyPhysics.ExplosionRaycastLayer);
            var hitEntity = hitInfo.HasValue ? ((MyPhysicsBody)hitInfo.Value.HkHitInfo.Body.UserObject).Entity : null;

            var grid = (hitEntity as MyCubeGrid);

            if (grid != null)
            {
                m_lastCubeGrid = grid;
                double shortestDistance = double.MaxValue;

                LineD    line            = new LineD(origin, end);
                Vector3I hitCube         = new Vector3I();
                double   distanceSquared = double.MaxValue;

                if (m_lastCubeGrid.GetLineIntersectionExactGrid(ref line, ref hitCube, ref distanceSquared))
                {
                    m_lastCube = hitCube;
                }
                else
                {
                    m_lastCube = null;
                }

                foreach (var bone in grid.Skeleton.Bones)
                {
                    var bonePos = (Vector3D)(bone.Key / (float)grid.Skeleton.BoneDensity) * grid.GridSize + bone.Value;
                    bonePos -= new Vector3D(grid.GridSize / grid.Skeleton.BoneDensity);
                    Vector3D pos = Vector3D.Transform(bonePos, grid.PositionComp.WorldMatrix);

                    Color color = Color.Red;

                    double distance = MyUtils.GetPointLineDistance(ref origin, ref end, ref pos);
                    if (distance < 0.1f)
                    {
                        double distanceToCamera = (origin - pos).LengthSquared();
                        if (distanceToCamera < shortestDistance)
                        {
                            shortestDistance = distanceToCamera;

                            color      = Color.Blue;
                            m_lastBone = bone.Key;
                        }
                    }

                    MyRenderProxy.DebugDrawSphere(pos, 0.05f, color.ToVector3(), 0.5f, false, true);
                }
            }
        }
        /// <summary>
        /// Handles camera collisions with environment
        /// </summary>
        /// <param name="controlledEntity"></param>
        /// <param name="shakeActive"></param>
        /// <param name="headPosition"></param>
        /// <param name="headDirection"></param>
        /// <returns>False if no correct position was found</returns>
        private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection)
        {
            var line = new LineD(m_target, m_position);

            var      safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length());
            Vector3D castStartSafe;

            {
                MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation);
                double?safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine);
                if (!safeIntersection.HasValue)
                {
                    safeIntersection = safeOBB.HalfExtent.Length();
                }
                double safeDistance = safeIntersection.Value;
                castStartSafe = line.From + line.Direction * safeDistance;
            }

            {
                double?unsafeIntersection = safeOBB.Intersects(ref safeOBBLine);
                if (!requireRaycast && unsafeIntersection.HasValue)
                {
                    var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value;
                    var castEndUnsafe   = castStartSafe + line.Direction;
                    // short raycast, not causing problems with asteroids generating geometry
                    Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.DefaultCollisionLayer);
                    if (!IsRaycastOK(m_raycastList))
                    {
                        return(false);
                    }
                }
            }

            if (requireRaycast)
            {
                // short raycast, not causing problems with asteroids generating geometry
                Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.DefaultCollisionLayer);
                if (!IsRaycastOK(m_raycastList))
                {
                    return(false);
                }
            }

            HkShape shape = new HkSphereShape(CAMERA_RADIUS);

            try
            {
                // small shape, not causing problems with asteroids generating geometry
                Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, 15);
                if (m_rigidList.Count > 0)
                {
                    bool sameGrid = false;
                    if (MySession.ControlledEntity != null && m_rigidList[0] != null)
                    {
                        sameGrid = m_rigidList[0].UserObject == ((MyEntity)MySession.ControlledEntity).Physics;
                    }

                    if (sameGrid)
                    {
                        castStartSafe += line.Direction;
                    }
                }

                var  shapeCastLine = new LineD(castStartSafe, m_position);
                uint steps         = 1;
                uint stepIdx       = 0;
                if (shapeCastLine.Length > SHAPE_CAST_STEP)
                {
                    steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP);
                    if (steps >= SHAPE_CAST_MAX_STEP_COUNT)
                    {
                        steps = SHAPE_CAST_MAX_STEP_COUNT - 1;
                    }
                    stepIdx = m_updateCount % steps;
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;

                    Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps);
                    shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step);
                }

                if (false)
                {
                    BoundingBoxD bbox = BoundingBoxD.CreateInvalid();
                    bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS));
                    bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS));
                    VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true);
                }

                var matrix = MatrixD.CreateTranslation(shapeCastLine.From);
                HkContactPointData?cpd;
                if (controlledEntity.Physics.CharacterProxy != null)
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, controlledEntity.Physics.CharacterCollisionFilter, 0.0f);
                }
                else
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, HkGroupFilter.CalcFilterInfo(MyPhysics.DefaultCollisionLayer, 0), 0.0f);
                }
                if (cpd.HasValue)
                {
                    var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction;
                    m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length();
                }
                else
                {
                    m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity;
                }


                float?dist = null;
                for (int i = 0; i < steps; ++i)
                {
                    if (m_lastShapeCastDistance[i] != float.PositiveInfinity)
                    {
                        dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity);
                    }
                }

                if (dist.HasValue)
                {
                    if (dist == 0.0f)
                    {
                        return(false);
                    }
                    else
                    {
                        m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value;
                    }
                }
                else
                {
                    m_positionSafe = m_position;
                }
                return(true);
            }
            finally
            {
                shape.RemoveReference();
            }
        }
        public override void UpdateAfterSimulation()
        {
            base.UpdateAfterSimulation();

            m_rootIslands.Clear();
            m_rootEntityIslandIndex.Clear();

            var clusterList = MyPhysics.GetClusterList();

            if (clusterList != null)
            {
                foreach (Havok.HkWorld havokWorld in MyPhysics.GetClusterList())
                {
                    var islandCount = havokWorld.GetActiveSimulationIslandsCount();

                    for (int i = 0; i < islandCount; i++)
                    {
                        havokWorld.GetActiveSimulationIslandRigidBodies(i, m_rigidBodies);

                        HashSet <IMyEntity> island = null;

                        foreach (var rigidBody in m_rigidBodies)
                        {
                            var ents = rigidBody.GetAllEntities();
                            foreach (var entity in ents)
                            {
                                var topParent = entity.GetTopMostParent();

                                foreach (var rootIsland in m_rootIslands)
                                {
                                    if (rootIsland.RootEntities.Contains(topParent))
                                    {
                                        island = rootIsland.RootEntities;
                                        break;
                                    }
                                }
                            }
                            ents.Clear();
                        }

                        if (island == null)
                        {
                            IslandData islandData = new IslandData()
                            {
                                AABB           = BoundingBoxD.CreateInvalid(),
                                RootEntities   = new HashSet <IMyEntity>(),
                                ClientPriority = new Dictionary <ulong, float>()
                            };
                            island = islandData.RootEntities;
                            m_rootIslands.Add(islandData);
                        }

                        foreach (var rigidBody in m_rigidBodies)
                        {
                            var ents = rigidBody.GetAllEntities();
                            foreach (var entity in ents)
                            {
                                var topParent = entity.GetTopMostParent();
                                island.Add(topParent);
                            }
                            ents.Clear();
                        }

                        m_rigidBodies.Clear();
                    }
                }

                for (int i = 0; i < m_rootIslands.Count; i++)
                {
                    var islandData = m_rootIslands[i];
                    islandData.AABB = BoundingBoxD.CreateInvalid();

                    foreach (var entity in islandData.RootEntities)
                    {
                        islandData.AABB.Include(entity.PositionComp.WorldAABB);

                        m_rootEntityIslandIndex[entity] = i;
                    }

                    m_rootIslands[i] = islandData;
                }
            }
        }
        public override void Draw()
        {
            base.Draw();
            if (MyTrashRemoval.PreviewEnabled && MySession.Static.HasCreativeRights)
            {
                DrawTrashAdminView();
            }

            bool visible = false;

            for (int i = 0; i < RenderObjectIDs.Length; i++)
            {
                if (RenderObjectIDs[i] == MyRenderProxy.RENDER_ID_UNASSIGNED)
                {
                    break;
                }
                if (MyRenderProxy.VisibleObjectsRead.Contains(this.RenderObjectIDs[i]))
                {
                    visible = true;
                    break;
                }
            }
            if (visible)
            {
                foreach (var block in m_grid.BlocksForDraw)
                {
                    if (MyRenderProxy.VisibleObjectsRead.Contains(block.Render.RenderObjectIDs[0]))
                    {
                        block.Render.Draw();
                    }
                }
            }
            if (MyCubeGrid.ShowCenterOfMass && !IsStatic && Container.Entity.Physics != null && Container.Entity.Physics.HasRigidBody)
            {
                var  matrix = Container.Entity.Physics.GetWorldMatrix();
                var  center = Container.Entity.Physics.CenterOfMassWorld;
                var  cam    = MySector.MainCamera.Position;
                var  dist   = Vector3.Distance(cam, center);
                bool draw   = false;
                if (dist < 30)
                {
                    draw = true;
                }
                else if (dist < 200)
                {
                    draw = true;
                    MyPhysics.CastRay(cam, center, m_tmpHitList, MyPhysics.CollisionLayers.DynamicDoubledCollisionLayer);
                    foreach (var hit in m_tmpHitList)
                    {
                        if (hit.HkHitInfo.GetHitEntity() != this)
                        {
                            draw = false;
                            break;
                        }
                    }
                    m_tmpHitList.Clear();
                }
                if (draw)
                {
                    float size      = MathHelper.Lerp(1, 9, dist / 200);
                    var   mat       = "WeaponLaserIgnoreDepth";
                    var   color     = Color.Yellow.ToVector4();
                    var   thickness = 0.02f * size;
                    MySimpleObjectDraw.DrawLine(center - matrix.Up * 0.5f * size, center + matrix.Up * 0.5f * size, mat, ref color, thickness);
                    MySimpleObjectDraw.DrawLine(center - matrix.Forward * 0.5f * size, center + matrix.Forward * 0.5f * size, mat, ref color, thickness);
                    MySimpleObjectDraw.DrawLine(center - matrix.Right * 0.5f * size, center + matrix.Right * 0.5f * size, mat, ref color, thickness);
                    MyTransparentGeometry.AddBillboardOriented("RedDotIgnoreDepth", Color.White.ToVector4(), center, MySector.MainCamera.LeftVector,
                                                               MySector.MainCamera.UpVector, 0.1f * size);
                }
            }
            if (MyCubeGrid.ShowGridPivot)
            {
                var  matrix = Container.Entity.WorldMatrix;
                var  pos    = matrix.Translation;
                var  cam    = MySector.MainCamera.Position;
                var  dist   = Vector3.Distance(cam, pos);
                bool draw   = false;
                if (dist < 30)
                {
                    draw = true;
                }
                else if (dist < 200)
                {
                    draw = true;
                    MyPhysics.CastRay(cam, pos, m_tmpHitList, MyPhysics.CollisionLayers.DynamicDoubledCollisionLayer);
                    foreach (var hit in m_tmpHitList)
                    {
                        if (hit.HkHitInfo.GetHitEntity() != this)
                        {
                            draw = false;
                            break;
                        }
                    }
                    m_tmpHitList.Clear();
                }
                if (draw)
                {
                    float size      = MathHelper.Lerp(1, 9, dist / 200);
                    var   mat       = "WeaponLaserIgnoreDepth";
                    var   thickness = 0.02f * size;
                    var   color     = Color.Green.ToVector4();
                    MySimpleObjectDraw.DrawLine(pos, pos + matrix.Up * 0.5f * size, mat, ref color, thickness);
                    color = Color.Blue.ToVector4();
                    MySimpleObjectDraw.DrawLine(pos, pos + matrix.Forward * 0.5f * size, mat, ref color, thickness);
                    color = Color.Red.ToVector4();
                    MySimpleObjectDraw.DrawLine(pos, pos + matrix.Right * 0.5f * size, mat, ref color, thickness);
                    MyTransparentGeometry.AddBillboardOriented("RedDotIgnoreDepth", Color.White.ToVector4(), pos, MySector.MainCamera.LeftVector,
                                                               MySector.MainCamera.UpVector, 0.1f * size);
                    MyRenderProxy.DebugDrawAxis(matrix, 0.5f, false);//DX 11 desnt support depthRead false
                }
            }

            if (MyCubeGrid.ShowStructuralIntegrity)
            {
                if (m_grid.StructuralIntegrity == null)
                {
                    if (MyFakes.ENABLE_STRUCTURAL_INTEGRITY)
                    {
                        m_grid.CreateStructuralIntegrity();

                        if (m_grid.StructuralIntegrity != null)
                        {
                            m_grid.StructuralIntegrity.EnabledOnlyForDraw = true;
                        }
                    }
                }
                else
                {
                    m_grid.StructuralIntegrity.Draw();
                }
            }
            else
            if (m_grid.StructuralIntegrity != null && m_grid.StructuralIntegrity.EnabledOnlyForDraw)
            {
                m_grid.CloseStructuralIntegrity();
            }

            if (MyFakes.ENABLE_ATMOSPHERIC_ENTRYEFFECT)
            {
                ProfilerShort.Begin("DrawAtmosphericEntryEffect");
                DrawAtmosphericEntryEffect();
                ProfilerShort.End();
            }
        }
Пример #27
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();
        }
Пример #28
0
        public static void OnGlobalSpawnEvent(object senderEvent)
        {
            // Select a spawn group to spawn
            MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup();

            if (spawnGroup == null)
            {
                return;
            }

            spawnGroup.ReloadPrefabs();

            ProfilerShort.Begin("Generate position and direction");

            double   spawnDistance  = NEUTRAL_SHIP_SPAWN_DISTANCE;
            Vector3D playerPosition = Vector3D.Zero;
            bool     isWorldLimited = MyEntities.IsWorldLimited();
            int      numPlayers     = 0;

            if (isWorldLimited)
            {
                spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius);
            }
            else
            {
                // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player
                // so cargo ships will be spawned around every player at some time
                var players = MySession.Static.Players.GetOnlinePlayers();
                // In DS there can be no players connected
                numPlayers = Math.Max(0, players.Count - 1);
                int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers);
                int i = 0;
                foreach (var player in players)
                {
                    if (i == randomPlayerPosition)
                    {
                        if (player.Character != null)
                        {
                            playerPosition = player.GetPosition();
                        }
                        break;
                    }
                    i++;
                }
            }
            if (spawnDistance < 0.0f)
            {
                MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!");
                return;
            }

            double       forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            BoundingBoxD spawnBox;

            if (isWorldLimited)
            {
                spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance));
            }
            else
            {
                // We need to extend bouding box so cargo ships aren't spawned near other players
                GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox);
                // Forbidden radius is sphere around all players in box.
                // Bounding box is generated from players positions so their distance to center shall be same for all players
                forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            }

            // Get the direction to the center and deviate it randomly
            Vector3D?origin = MyUtils.GetRandomBorderPosition(ref spawnBox);

            origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius);
            if (!origin.HasValue)
            {
                MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found");
                MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                ProfilerShort.End();
                return;
            }

            // Radius in arc units of the forbidden sphere in the center, when viewed from origin
            float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length());

            // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians
            Vector3D direction = -Vector3D.Normalize(origin.Value);
            float    theta     = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD);
            float    phi       = MyUtils.GetRandomRadian();
            Vector3D cosVec    = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D sinVec    = Vector3D.Cross(direction, cosVec);

            cosVec   *= (Math.Sin(theta) * Math.Cos(phi));
            sinVec   *= (Math.Sin(theta) * Math.Sin(phi));
            direction = direction * Math.Cos(theta) + cosVec + sinVec;

            Vector3D destination  = Vector3D.Zero;
            RayD     ray          = new RayD(origin.Value, direction);
            double?  intersection = ray.Intersects(spawnBox);
            Vector3D directionMult;

            if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH)
            {
                directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH;
            }
            else
            {
                directionMult = direction * intersection.Value;
            }
            destination = origin.Value + directionMult;

            Vector3D upVector     = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D rightVector  = Vector3D.Cross(direction, upVector);
            MatrixD  originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector);

            ProfilerShort.End();

            ProfilerShort.Begin("Check free space");

            // CH:TODO: Convex cast to detect collision
            // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions)
            m_raycastHits.Clear();
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId);
                Debug.Assert(prefabDef != null);

                Vector3D shipPosition    = Vector3.Transform(shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                float    radius          = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius;

                MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.ObjectDetectionCollisionLayer);
                if (m_raycastHits.Count() > 0)
                {
                    MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }

                for (int i = 0; i < 4; ++i)
                {
                    Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius;
                    MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.ObjectDetectionCollisionLayer);

                    if (m_raycastHits.Count() > 0)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                        MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                        ProfilerShort.End();
                        return;
                    }
                }
            }

            ProfilerShort.End();

            ProfilerShort.Begin("Spawn ships");

            long spawnGroupId = MyPirateAntennas.GetPiratesId();

            // The ships were collision-free. Now spawn them
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                ProfilerShort.Begin(shipPrefab.BeaconText);

                // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate
                Vector3D shipPosition    = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                Vector3D up = Vector3D.CalculatePerpendicularVector(-direction);

                m_tmpGridList.Clear();

                // CH: We don't want a new identity for each ship anymore. We should handle that in a better way...

                /*if (shipPrefab.ResetOwnership)
                 * {
                 *  if (spawnGroupId == 0)
                 *  {
                 *      //This is not an NPC so that it doesn't show up in assign ownership drop down menu
                 *      MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC");
                 *      spawnGroupId = spawnGroupIdentity.IdentityId;
                 *  }
                 * }*/

                // Deploy ship
                ProfilerShort.Begin("Spawn cargo ship");
                MyPrefabManager.Static.SpawnPrefab(
                    resultList: m_tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: up,
                    initialLinearVelocity: shipPrefab.Speed * direction,
                    beaconName: shipPrefab.BeaconText,
                    spawningOptions: Sandbox.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection |
                    Sandbox.ModAPI.SpawningOptions.SpawnRandomCargo |
                    Sandbox.ModAPI.SpawningOptions.DisableDampeners,
                    ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0,
                    updateSync: true);
                ProfilerShort.End();

                foreach (var grid in m_tmpGridList)
                {
                    var cockpit = grid.GetFirstBlockOfType <MyCockpit>();
                    if (cockpit != null)
                    {
                        MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction);
                        cockpit.AttachAutopilot(ai);
                        break;
                    }
                }

                m_tmpGridList.Clear();

                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
        /// <summary>
        /// Casts preview grids aabbs and get shortest distance. Returns shortest intersection or null.
        /// </summary>
        protected Vector3D?GetFreeSpacePlacementPositionGridAabbs(bool copyPaste, out bool buildAllowed)
        {
            Vector3D?freePlacementIntersectionPoint = null;

            buildAllowed = true;

            float gridSize = PreviewGrids[0].GridSize;

            double shortestDistance = double.MaxValue;
            double?currentRayInts   = MyCubeBuilder.GetCurrentRayIntersection();

            if (currentRayInts.HasValue)
            {
                shortestDistance = currentRayInts.Value;
            }

            Vector3D worldRefPointOffset = Vector3D.Zero;

            if (copyPaste)
            {
                Matrix firstGridOrientation = GetFirstGridOrientationMatrix();
                worldRefPointOffset = Vector3.TransformNormal(m_dragPointToPositionLocal, firstGridOrientation);
            }

            Vector3D worldRefPoint = PreviewGrids[0].GridIntegerToWorld(Vector3I.Zero);

            foreach (var grid in PreviewGrids)
            {
                Vector3 halfExt  = grid.PositionComp.LocalAABB.HalfExtents;
                Vector3 minLocal = grid.Min * grid.GridSize - Vector3.Half * grid.GridSize;
                Vector3 maxLocal = grid.Max * grid.GridSize + Vector3.Half * grid.GridSize;

                MatrixD gridWorlTransform = MatrixD.Identity;
                gridWorlTransform.Translation = 0.5f * (minLocal + maxLocal);
                gridWorlTransform             = gridWorlTransform * grid.WorldMatrix;

                Vector3I size       = grid.Max - grid.Min + Vector3I.One;
                Vector3  sizeOffset = Vector3I.Abs((size % 2) - Vector3I.One) * 0.5 * grid.GridSize;
                sizeOffset = Vector3.TransformNormal(sizeOffset, grid.WorldMatrix);
                Vector3D offset = gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint /*- sizeOffset*/;// Vector3.Zero;// gridWorlTransform.Translation + worldRefPointOffset - worldRefPoint;

                HkShape shape = new HkBoxShape(halfExt);

                Vector3D rayStart = MyCubeBuilder.IntersectionStart + offset;
                double   castPlaneDistanceToRayStart = DistanceFromCharacterPlane(ref rayStart);
                rayStart -= castPlaneDistanceToRayStart * MyCubeBuilder.IntersectionDirection;

                Vector3D rayEnd = MyCubeBuilder.IntersectionStart + (m_dragDistance - castPlaneDistanceToRayStart) * MyCubeBuilder.IntersectionDirection + offset;
                MatrixD  matrix = gridWorlTransform;
                matrix.Translation = rayStart;

                try
                {
                    float?dist = MyPhysics.CastShape(rayEnd, shape, ref matrix, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter);
                    if (dist.HasValue && dist.Value != 0f)
                    {
                        Vector3D intersectionPoint = rayStart + dist.Value * (rayEnd - rayStart);

                        const bool debugDraw = true;
                        if (debugDraw)
                        {
                            Color        green     = Color.Green;
                            BoundingBoxD localAABB = new BoundingBoxD(-halfExt, halfExt);
                            localAABB.Inflate(0.03f);
                            MatrixD drawMatrix = matrix;
                            drawMatrix.Translation = intersectionPoint;
                            MySimpleObjectDraw.DrawTransparentBox(ref drawMatrix, ref localAABB, ref green, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);
                        }

                        double fixedDistance = DistanceFromCharacterPlane(ref intersectionPoint) - castPlaneDistanceToRayStart;
                        if (fixedDistance <= 0)
                        {
                            fixedDistance    = 0;
                            shortestDistance = 0;
                            buildAllowed     = false;
                            break;
                        }

                        if (fixedDistance < shortestDistance)
                        {
                            shortestDistance = fixedDistance;
                        }
                    }
                    else
                    {
                        buildAllowed = false;
                    }
                }
                finally
                {
                    shape.RemoveReference();
                }
            }

            if (shortestDistance != 0 && shortestDistance < m_dragDistance)
            {
                freePlacementIntersectionPoint = MyCubeBuilder.IntersectionStart + shortestDistance * MyCubeBuilder.IntersectionDirection;
            }
            else
            {
                buildAllowed = false;
            }

            return(freePlacementIntersectionPoint);
        }
Пример #30
0
        private MyAttachableTopBlockBase FindMatchingTop()
        {
            Debug.Assert(CubeGrid != null);
            Debug.Assert(m_penetrations != null);
            Debug.Assert(CubeGrid.Physics != null);
            if (CubeGrid == null)
            {
                MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): Cube grid == null!");
                return(null);
            }

            if (m_penetrations == null)
            {
                MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): penetrations cache == null!");
                return(null);
            }

            if (CubeGrid.Physics == null)
            {
                MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): Cube grid physics == null!");
                return(null);
            }

            Quaternion orientation;
            Vector3D   pos;
            Vector3    halfExtents;

            ComputeTopQueryBox(out pos, out halfExtents, out orientation);
            try
            {
                MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref orientation, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer);
                foreach (var obj in m_penetrations)
                {
                    var entity = obj.GetCollisionEntity();
                    if (entity == null || entity == CubeGrid)
                    {
                        continue;
                    }

                    MyAttachableTopBlockBase top = FindTopInGrid(entity, pos);

                    if (top != null)
                    {
                        return(top);
                    }

                    MyPhysicsBody body = entity.Physics as MyPhysicsBody;
                    if (body != null)
                    {
                        foreach (var child in body.WeldInfo.Children)
                        {
                            top = FindTopInGrid(child.Entity, pos);
                            if (top != null)
                            {
                                return(top);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                m_penetrations.Clear();
            }
            return(null);
        }
Пример #31
0
        private void PlaceAreaMarker()
        {
            Vector3D cameraPos, cameraDir;

            if (MySession.GetCameraControllerEnum() == Common.ObjectBuilders.MyCameraControllerEnum.ThirdPersonSpectator || MySession.GetCameraControllerEnum() == Common.ObjectBuilders.MyCameraControllerEnum.Entity)
            {
                var headMatrix = MySession.ControlledEntity.GetHeadMatrix(true, true);
                cameraPos = headMatrix.Translation;
                cameraDir = headMatrix.Forward;
            }
            else
            {
                cameraPos = MySector.MainCamera.Position;
                cameraDir = MySector.MainCamera.WorldMatrix.Forward;
            }

            List <MyPhysics.HitInfo> hitInfos = new List <MyPhysics.HitInfo>();

            MyPhysics.CastRay(cameraPos, cameraPos + cameraDir * 100, hitInfos, MyPhysics.ObjectDetectionCollisionLayer);
            if (hitInfos.Count == 0)
            {
                return;
            }

            MyPhysics.HitInfo?closestValidHit = null;
            foreach (var hitInfo in hitInfos)
            {
                var ent = hitInfo.HkHitInfo.Body.GetEntity();
                if (ent is MyCubeGrid)
                {
                    closestValidHit = hitInfo;
                    break;
                }
                else if (ent is MyVoxelMap)
                {
                    closestValidHit = hitInfo;
                    break;
                }
            }

            if (closestValidHit.HasValue)
            {
                MyAreaMarkerDefinition definition = AreaMarkerDefinition;
                Debug.Assert(definition != null, "Area marker definition cannot be null!");
                if (definition == null)
                {
                    return;
                }

                Vector3D position = closestValidHit.Value.Position;

                var forward = Vector3D.Reject(cameraDir, Vector3D.Up);

                if (Vector3D.IsZero(forward))
                {
                    forward = Vector3D.Forward;
                }

                var positionAndOrientation = new MyPositionAndOrientation(position, Vector3D.Normalize(forward), Vector3D.Up);

                MyObjectBuilder_AreaMarker objectBuilder = (MyObjectBuilder_AreaMarker)MyObjectBuilderSerializer.CreateNewObject(definition.Id);
                objectBuilder.PersistentFlags        = MyPersistentEntityFlags2.Enabled | MyPersistentEntityFlags2.InScene;
                objectBuilder.PositionAndOrientation = positionAndOrientation;

                if (objectBuilder.IsSynced)
                {
                    MySyncCreate.RequestEntityCreate(objectBuilder);
                }
                else
                {
                    MyAreaMarker flag = MyEntityFactory.CreateEntity <MyAreaMarker>(objectBuilder);
                    flag.Init(objectBuilder);

                    MyEntities.Add(flag);
                }
            }
        }
        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;
            }
        }