コード例 #1
0
        private void ComputeGravityAlignedOrientation(out MatrixD resultOrientationStorage)
        {
            // Y axis
            bool     inGravityField = true;
            Vector3D upVector       = -MyGravityProviderSystem.CalculateTotalGravityInPoint(Position);

            if (upVector.LengthSquared() < MyMathConstants.EPSILON)
            {
                upVector = m_lastUpVec;
                m_lastOrientationWeight = 1;
                inGravityField          = false;
            }
            else
            {
                m_lastUpVec = upVector;
            }
            upVector.Normalize();
            // X axis
            Vector3D rightVector = m_lastRightVec - Vector3D.Dot(m_lastRightVec, upVector) * upVector;

            if (rightVector.LengthSquared() < MyMathConstants.EPSILON)
            {
                rightVector = m_orientation.Right - Vector3D.Dot(m_orientation.Right, upVector) * upVector;
                // backup behavior if singularity happens
                if (rightVector.LengthSquared() < MyMathConstants.EPSILON)
                {
                    rightVector = m_orientation.Forward - Vector3D.Dot(m_orientation.Forward, upVector) * upVector;
                }
                // backup behavior if singularity happens
            }
            rightVector.Normalize();
            m_lastRightVec = rightVector;
            // Z axis
            Vector3D forwardVector;

            Vector3D.Cross(ref upVector, ref rightVector, out forwardVector);

            resultOrientationStorage         = MatrixD.Identity;
            resultOrientationStorage.Right   = rightVector;
            resultOrientationStorage.Up      = upVector;
            resultOrientationStorage.Forward = forwardVector;
            resultOrientationStorage         = MatrixD.CreateFromAxisAngle(Vector3D.Right, m_pitch) * resultOrientationStorage *
                                               MatrixD.CreateFromAxisAngle(upVector, m_yaw);
            upVector    = resultOrientationStorage.Up;
            rightVector = resultOrientationStorage.Right;
            resultOrientationStorage.Right = Math.Cos(m_roll) * rightVector + Math.Sin(m_roll) * upVector;
            resultOrientationStorage.Up    = -Math.Sin(m_roll) * rightVector + Math.Cos(m_roll) * upVector;

            if (inGravityField && m_lastOrientationWeight > 0)
            {
                m_lastOrientationWeight = Math.Max(0, m_lastOrientationWeight - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);

                resultOrientationStorage = MatrixD.Slerp(resultOrientationStorage, m_lastOrientation,
                                                         MathHelper.SmoothStepStable(m_lastOrientationWeight));
            }
            if (!inGravityField)
            {
                m_lastOrientation = resultOrientationStorage;
            }
        }
コード例 #2
0
        private Vector3D WorldPositionToLocalNavmeshPosition(Vector3D position, float heightIncrease)
        {
            Vector3D v      = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(this.Center));
            MatrixD  matrix = MatrixD.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp((Vector3)Vector3D.CalculatePerpendicularVector(v), (Vector3)v)));

            return(Vector3D.Transform((position - this.Center) + (heightIncrease * v), matrix));
        }
コード例 #3
0
        public override void UpdateBeforeSimulation()
        {
            //if (MyFakes.ENABLE_RAGDOLL_DEBUG) Debug.WriteLine("RagdollComponent.UpdateBeforeSimulation");
            base.UpdateBeforeSimulation();

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Update Ragdoll");
            UpdateRagdoll();
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            // TODO: This should be changed so the ragdoll gets registered in the generators, now for SE, apply gravity explictly
            // Apply Gravity on Ragdoll
            // OM: This should be called only in SE, in ME this is handled by world!
            if (Character.Physics != null &&
                Character.Physics.Ragdoll != null &&
                Character.Physics.Ragdoll.InWorld &&
                (!Character.Physics.Ragdoll.IsKeyframed || RagdollMapper.IsPartiallySimulated) &&
                (IsRagdollMoving || m_gravityTimer > 0))
            {
                Vector3 gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(Character.PositionComp.WorldAABB.Center) + Character.GetPhysicsBody().HavokWorld.Gravity *MyPerGameSettings.CharacterGravityMultiplier;
                Character.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, gravity * (MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(Character.Definition.Mass) : Character.Definition.Mass), null, null);
                m_gravityTimer = IsRagdollMoving ? GRAVITY_DELAY : m_gravityTimer - 1;
            }

            if (Character.Physics != null && Character.Physics.Ragdoll != null && IsRagdollMoving)
            {
                m_lastPosition = Character.Physics.Ragdoll.WorldMatrix.Translation;
            }
        }
コード例 #4
0
        public void Update()
        {
            ProfilerShort.Begin("MyBotNavigation.Update");
            AssertIsValid();

            if (m_entity == null)
            {
                return;
            }

            ProfilerShort.Begin("UpdateMatrices");
            UpdateMatrices();
            ProfilerShort.End();

            m_gravityDirection = MyGravityProviderSystem.CalculateTotalGravityInPoint(m_entity.PositionComp.WorldMatrix.Translation);
            if (!Vector3.IsZero(m_gravityDirection, 0.01f))
            {
                m_gravityDirection = Vector3D.Normalize(m_gravityDirection);
            }

            if (MyPerGameSettings.NavmeshPresumesDownwardGravity)
            {
                m_upVector = Vector3.Up;
            }
            else
            {
                m_upVector = -m_gravityDirection;
            }

            if (!m_speed.IsValid())
            {
                m_forwardVector         = PositionAndOrientation.Forward;
                m_speed                 = 0.0f;
                m_rotationSpeedModifier = 1;
            }

            ProfilerShort.Begin("Steering update");
            foreach (var steering in m_steerings)
            {
                ProfilerShort.Begin(steering.GetName());
                steering.Update();
                ProfilerShort.End();
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Aiming");
            m_aiming.Update();
            ProfilerShort.End();

            ProfilerShort.Begin("Steering accumulate correction");
            CorrectMovement(m_aiming.RotationHint);
            ProfilerShort.End();

            ProfilerShort.Begin("MoveCharacter");
            MoveCharacter();
            ProfilerShort.End();

            AssertIsValid();
            ProfilerShort.End();
        }
コード例 #5
0
 public void Update(int behaviorTicks)
 {
     this.m_stuckDetection.SetCurrentTicks(behaviorTicks);
     if (this.m_entity != null)
     {
         this.UpdateMatrices();
         this.m_gravityDirection = MyGravityProviderSystem.CalculateTotalGravityInPoint(this.m_entity.PositionComp.WorldMatrix.Translation);
         if (!Vector3.IsZero(this.m_gravityDirection, 0.01f))
         {
             this.m_gravityDirection = (Vector3)Vector3D.Normalize(this.m_gravityDirection);
         }
         this.m_upVector = !MyPerGameSettings.NavmeshPresumesDownwardGravity ? -this.m_gravityDirection : Vector3.Up;
         if (!this.m_speed.IsValid())
         {
             this.m_forwardVector         = (Vector3)this.PositionAndOrientation.Forward;
             this.m_speed                 = 0f;
             this.m_rotationSpeedModifier = 1f;
         }
         using (List <MySteeringBase> .Enumerator enumerator = this.m_steerings.GetEnumerator())
         {
             while (enumerator.MoveNext())
             {
                 enumerator.Current.Update();
             }
         }
         this.m_aiming.Update();
         this.CorrectMovement(this.m_aiming.RotationHint);
         if (this.m_speed < 0.1f)
         {
             this.m_speed = 0f;
         }
         this.MoveCharacter();
     }
 }
コード例 #6
0
        private unsafe void DebugDrawInternal()
        {
            if (this.m_navmeshOBBs != null)
            {
                this.m_navmeshOBBs.DebugDraw();
            }
            if (this.DrawNavmesh)
            {
                this.DrawPersistentDebugNavmesh(false);
            }
            if (this.DrawPhysicalMesh)
            {
                this.DebugDrawPhysicalShapes();
            }
            Vector3D position = MySession.Static.ControlledEntity.ControllerInfo.Controller.Player.GetPosition();
            double * numPtr1  = (double *)ref position.Y;

            numPtr1[0] += 2.4000000953674316;
            MyRenderProxy.DebugDrawText3D(position, $"X: {Math.Round(position.X, 2)}
Y: {Math.Round(position.Y, 2)}
Z: {Math.Round(position.Z, 2)}", Color.Red, 1f, true, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, -1, false);
            if (this.m_lastGroundMeshQuery.Count > 0)
            {
                MyRenderProxy.DebugDrawSphere(this.m_lastGroundMeshQuery[0].Center, 1f, Color.Yellow, 1f, true, false, true, false);
                foreach (BoundingBoxD xd2 in this.m_lastGroundMeshQuery)
                {
                    MyRenderProxy.DebugDrawOBB(xd2.Matrix, Color.Yellow, 0f, true, false, true, false);
                }
                if (this.m_navmeshOBBs != null)
                {
                    float num;
                    float num2;
                    foreach (MyNavmeshOBBs.OBBCoords coords in this.m_debugDrawIntersectedOBBs)
                    {
                        MyRenderProxy.DebugDrawOBB(new MyOrientedBoundingBoxD(coords.OBB.Center, new Vector3(coords.OBB.HalfExtent.X, coords.OBB.HalfExtent.Y / 2.0, coords.OBB.HalfExtent.Z), coords.OBB.Orientation), Color.White, 0f, true, false, false);
                    }
                    MyOrientedBoundingBoxD obb = this.m_navmeshOBBs.GetOBB(0, 0).Value;
                    MyPlanet planet            = this.GetPlanet(obb.Center);
                    Vector3 *points            = (Vector3 *)stackalloc byte[(((IntPtr)4) * sizeof(Vector3))];
                    GetMiddleOBBPoints(obb, ref points);
                    planet.Provider.Shape.GetBounds(points, 4, out num, out num2);
                    if (num.IsValid() && num2.IsValid())
                    {
                        Vector3D vectord2 = obb.Orientation.Up * num2;
                        MyRenderProxy.DebugDrawSphere(obb.Orientation.Up * num, 1f, Color.Blue, 0f, true, false, true, false);
                        MyRenderProxy.DebugDrawSphere(vectord2, 1f, Color.Blue, 0f, true, false, true, false);
                    }
                    DrawTerrainLimits(planet, obb);
                }
                MyRenderProxy.DebugDrawSphere(this.m_meshCenter, 2f, Color.Red, 0f, true, false, true, false);
            }
            if ((this.m_polygons != null) && (this.m_pathfindingDebugTarget != null))
            {
                Vector3D vectord3 = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(this.m_pathfindingDebugTarget.Value));
                MyRenderProxy.DebugDrawSphere(this.m_pathfindingDebugTarget.Value + (1.5 * vectord3), 0.2f, Color.Red, 0f, true, false, true, false);
            }
        }
コード例 #7
0
        public MyNavigationInputMesh(MyRDPathfinding rdPathfinding, MyPlanet planet, Vector3D center)
        {
            this.m_rdPathfinding = rdPathfinding;
            this.m_planet        = planet;
            this.m_center        = center;
            Vector3 v       = (Vector3) - Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(this.m_center));
            Vector3 forward = Vector3.CalculatePerpendicularVector(v);

            this.rdWorldQuaternion = Quaternion.Inverse(Quaternion.CreateFromForwardUp(forward, v));
        }
コード例 #8
0
        private Vector3D LocalPositionToWorldPosition(Vector3D position)
        {
            Vector3D worldPoint = position;

            if (this.m_navmeshOBBs != null)
            {
                worldPoint = this.Center;
            }
            Vector3D vectord2 = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(worldPoint));

            return(this.LocalNavmeshPositionToWorldPosition(this.m_navmeshOBBs.CenterOBB, position, worldPoint, (Vector3D)(-this.m_heightCoordTransformationIncrease * vectord2)));
        }
コード例 #9
0
        private void ComputeGravityAlignedOrientation(out MatrixD resultOrientationStorage)
        {
            Vector3D vectord3;
            bool     flag = true;
            Vector3D up   = -MyGravityProviderSystem.CalculateTotalGravityInPoint(base.Position);

            if (up.LengthSquared() >= 9.9999997473787516E-06)
            {
                this.m_lastUpVec = up;
            }
            else
            {
                up = this.m_lastUpVec;
                this.m_lastOrientationWeight = 1f;
                flag = false;
            }
            up.Normalize();
            Vector3D right = this.m_lastRightVec - (Vector3D.Dot(this.m_lastRightVec, up) * up);

            if (right.LengthSquared() < 9.9999997473787516E-06)
            {
                right = base.m_orientation.Right - (Vector3D.Dot(base.m_orientation.Right, up) * up);
                if (right.LengthSquared() < 9.9999997473787516E-06)
                {
                    right = base.m_orientation.Forward - (Vector3D.Dot(base.m_orientation.Forward, up) * up);
                }
            }
            right.Normalize();
            this.m_lastRightVec = right;
            Vector3D.Cross(ref up, ref right, out vectord3);
            resultOrientationStorage         = MatrixD.Identity;
            resultOrientationStorage.Right   = right;
            resultOrientationStorage.Up      = up;
            resultOrientationStorage.Forward = vectord3;
            resultOrientationStorage         = (MatrixD.CreateFromAxisAngle(Vector3D.Right, this.m_pitch) * resultOrientationStorage) * MatrixD.CreateFromAxisAngle(up, this.m_yaw);
            up    = resultOrientationStorage.Up;
            right = resultOrientationStorage.Right;
            resultOrientationStorage.Right = (Vector3D)((Math.Cos(this.m_roll) * right) + (Math.Sin(this.m_roll) * up));
            resultOrientationStorage.Up    = (Vector3D)((-Math.Sin(this.m_roll) * right) + (Math.Cos(this.m_roll) * up));
            if (flag && (this.m_lastOrientationWeight > 0f))
            {
                this.m_lastOrientationWeight     = Math.Max((float)0f, (float)(this.m_lastOrientationWeight - 0.01666667f));
                resultOrientationStorage         = MatrixD.Slerp(resultOrientationStorage, this.m_lastOrientation, MathHelper.SmoothStepStable(this.m_lastOrientationWeight));
                resultOrientationStorage         = MatrixD.Orthogonalize(resultOrientationStorage);
                resultOrientationStorage.Forward = Vector3D.Cross(resultOrientationStorage.Up, resultOrientationStorage.Right);
            }
            if (!flag)
            {
                this.m_lastOrientation = resultOrientationStorage;
            }
        }
コード例 #10
0
        private MyNavmeshManager CreateManager(Vector3D center, Vector3D?forwardDirection = new Vector3D?())
        {
            if (forwardDirection == null)
            {
                Vector3D v = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(center));
                forwardDirection = new Vector3D?(Vector3D.CalculatePerpendicularVector(v));
            }
            int tileSize          = 0x10;
            MyNavmeshManager item = new MyNavmeshManager(this, center, forwardDirection.Value, tileSize, 70, 0x19, this.GetRecastOptions(null))
            {
                DrawNavmesh = this.m_drawNavmesh
            };

            this.m_planetManagers[item.Planet].Add(item);
            return(item);
        }
コード例 #11
0
        public override void UpdateBeforeSimulation100()
        {
            base.UpdateBeforeSimulation100();
            if (m_soundEmitter != null)
            {
                m_soundEmitter.Update();
                if (m_soundEmitter.IsPlaying && (DateTime.UtcNow - m_soundStart).TotalSeconds >= 15f)//stop falling sound if it playing too long
                {
                    m_fallSoundShouldPlay.Value = false;
                }
            }

            var grav = MyGravityProviderSystem.CalculateTotalGravityInPoint(PositionComp.GetPosition());

            Physics.RigidBody.Gravity = grav;
        }
コード例 #12
0
        public void DebugDraw()
        {
            MatrixD  viewMatrix = MySector.MainCamera.ViewMatrix;
            Vector3D?nullable   = null;

            foreach (MyHighLevelPrimitive local1 in this.m_pathNodes)
            {
                Vector3D down = MyGravityProviderSystem.CalculateTotalGravityInPoint(local1.WorldPosition);
                if (Vector3D.IsZero(down, 0.001))
                {
                    down = Vector3D.Down;
                }
                down.Normalize();
                MyHighLevelPrimitive local2   = local1;
                Vector3D             position = local2.WorldPosition + (down * -10.0);
                MyRenderProxy.DebugDrawSphere(position, 1f, Color.IndianRed, 1f, false, false, true, false);
                MyRenderProxy.DebugDrawLine3D(local2.WorldPosition, position, Color.IndianRed, Color.IndianRed, false, false);
                if (nullable != null)
                {
                    MyRenderProxy.DebugDrawLine3D(position, nullable.Value, Color.IndianRed, Color.IndianRed, false, false);
                }
                nullable = new Vector3D?(position);
            }
            MyRenderProxy.DebugDrawSphere(this.m_startPoint, 0.5f, Color.HotPink, 1f, false, false, true, false);
            if (this.m_goal != null)
            {
                this.m_goal.DebugDraw();
            }
            if (MyFakes.DEBUG_DRAW_FOUND_PATH)
            {
                Vector3D?nullable2 = null;
                for (int i = 0; i < this.m_expandedPath.Count; i++)
                {
                    Vector3D position = new Vector3D(this.m_expandedPath[i]);
                    float    w        = (float)this.m_expandedPath[i].W;
                    Color    color    = (i == (this.m_expandedPath.Count - 1)) ? Color.OrangeRed : Color.Orange;
                    MyRenderProxy.DebugDrawPoint(position, color, false, false);
                    MyRenderProxy.DebugDrawText3D(position + (viewMatrix.Right * 0.10000000149011612), w.ToString(), color, 0.7f, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, -1, false);
                    if (nullable2 != null)
                    {
                        MyRenderProxy.DebugDrawLine3D(nullable2.Value, position, Color.Pink, Color.Pink, false, false);
                    }
                    nullable2 = new Vector3D?(position);
                }
            }
        }
コード例 #13
0
        private Vector3D WorldPositionToLocalNavmeshPosition(Vector3D position, float heightIncrease)
        {
            MyOrientedBoundingBoxD?oBB = this.m_navmeshOBBs.GetOBB(position);

            if (oBB != null)
            {
                MyOrientedBoundingBoxD local1 = oBB.Value;
            }
            else
            {
                Vector3D meshCenter = this.m_meshCenter;
            }
            Vector3D v      = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(this.m_meshCenter));
            MatrixD  matrix = MatrixD.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp((Vector3)Vector3D.CalculatePerpendicularVector(v), (Vector3)v)));

            return(Vector3D.Transform((position - this.m_meshCenter) + (heightIncrease * v), matrix));
        }
コード例 #14
0
        public override void UpdateBeforeSimulation()
        {
            //if (MyFakes.ENABLE_RAGDOLL_DEBUG) Debug.WriteLine("RagdollComponent.UpdateBeforeSimulation");
            base.UpdateBeforeSimulation();

            // TODO: This should be changed so the ragdoll gets registered in the generators, now for SE, apply gravity explictly
            // Apply Gravity on Ragdoll
            // OM: This should be called only in SE, in ME this is handled by world!
            if (Character.Physics.Ragdoll != null && Character.Physics.Ragdoll.InWorld && (!Character.Physics.Ragdoll.IsKeyframed || RagdollMapper.IsPartiallySimulated) && (MyPerGameSettings.Game == GameEnum.SE_GAME))
            {
                Vector3 gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(Character.PositionComp.WorldAABB.Center) + Character.Physics.HavokWorld.Gravity * MyCharacter.CHARACTER_GRAVITY_MULTIPLIER;
                Character.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_FORCE, gravity * (MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(Character.Definition.Mass) : Character.Definition.Mass), null, null);
            }

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Update Ragdoll");
            UpdateRagdoll();
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
コード例 #15
0
        public override void UpdateOnceBeforeFrame()
        {
            base.UpdateOnceBeforeFrame();

            Physics.Enabled = true;
            Physics.RigidBody.Activate();
            Physics.RigidBody.ContactPointCallbackDelay   = 0;
            Physics.RigidBody.ContactSoundCallbackEnabled = true;

            //return;
            if (InitialHit != null)
            {
                Physics.ApplyImpulse(InitialHit.Impulse, Physics.CenterOfMassWorld);

                MyPhysics.FractureImpactDetails fid = new Sandbox.Engine.Physics.MyPhysics.FractureImpactDetails();
                fid.Entity         = this;
                fid.World          = Physics.HavokWorld;
                fid.ContactInWorld = InitialHit.Position;

                HkdFractureImpactDetails details = HkdFractureImpactDetails.Create();
                details.SetBreakingBody(Physics.RigidBody);
                details.SetContactPoint(Physics.WorldToCluster(InitialHit.Position));
                details.SetDestructionRadius(0.05f);
                details.SetBreakingImpulse(30000);
                details.SetParticleVelocity(InitialHit.Impulse);
                details.SetParticlePosition(Physics.WorldToCluster(InitialHit.Position));
                details.SetParticleMass(500);

                fid.Details = details;
                MyPhysics.EnqueueDestruction(fid);
            }

            var grav = MyGravityProviderSystem.CalculateTotalGravityInPoint(PositionComp.GetPosition());

            Physics.RigidBody.Gravity = grav;
        }
コード例 #16
0
        private bool SpawnDrone(MyRadioAntenna antenna, long ownerId, Vector3D position, MySpawnGroupDefinition spawnGroup, Vector3?spawnUp = null, Vector3?spawnForward = null)
        {
            long     antennaEntityId = antenna.EntityId;
            Vector3D antennaPos      = antenna.PositionComp.GetPosition();

            Vector3D upVector;

            var planet = MyGamePruningStructure.GetClosestPlanet(position);

            if (planet != null)
            {
                if (!MyGravityProviderSystem.IsPositionInNaturalGravity(antennaPos))
                {
                    MySandboxGame.Log.WriteLine("Couldn't spawn drone; antenna is not in natural gravity but spawn location is.");
                    return(false);
                }
                planet.CorrectSpawnLocation(ref position, spawnGroup.SpawnRadius * 2.0);
                upVector = position - planet.PositionComp.GetPosition();
                upVector.Normalize();
            }
            else
            {
                var totalGravityInPoint = MyGravityProviderSystem.CalculateTotalGravityInPoint(position);
                if (totalGravityInPoint != Vector3.Zero)
                {
                    upVector = -totalGravityInPoint;
                    upVector.Normalize();
                }
                else if (spawnUp != null)
                {
                    upVector = spawnUp.Value;
                }
                else
                {
                    upVector = MyUtils.GetRandomVector3Normalized();
                }
            }

            Vector3D direction = MyUtils.GetRandomPerpendicularVector(ref upVector);

            if (spawnForward != null)
            {
                // Align forward to up vector.
                Vector3 forward = spawnForward.Value;
                if (Math.Abs(Vector3.Dot(forward, upVector)) >= 0.98f)
                {
                    forward = Vector3.CalculatePerpendicularVector(upVector);
                }
                else
                {
                    Vector3 right = Vector3.Cross(forward, upVector);
                    right.Normalize();
                    forward = Vector3.Cross(upVector, right);
                    forward.Normalize();
                }

                direction = forward;
            }

            MatrixD originMatrix = MatrixD.CreateWorld(position, direction, upVector);

            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);

                List <MyCubeGrid> tmpGridList = new List <MyCubeGrid>();

                Stack <Action> callback = new Stack <Action>();
                callback.Push(delegate() { ChangeDroneOwnership(tmpGridList, ownerId, antennaEntityId); });

                MyPrefabManager.Static.SpawnPrefab(
                    resultList: tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: upVector,
                    initialLinearVelocity: default(Vector3),
                    beaconName: null,
                    spawningOptions: VRage.Game.ModAPI.SpawningOptions.None,
                    ownerId: ownerId,
                    updateSync: true, callbacks: callback);
            }
            return(true);
        }
コード例 #17
0
        private bool CalculateComplete()
        {
            if (!Definition.RequiredSupport.HasValue)
            {
                return(true);
            }

            if (_shapeDirty)
            {
                CalculateShape();
            }
            var edge  = _bendy.Edges.FirstOrDefault();
            var curve = edge?.Curve;

            if (curve == null)
            {
                return(true);
            }

            var shape     = Definition.RequiredSupport.Value;
            var sphere    = new BoundingSphereD(Vector3D.Transform(_localBox.Center, Entity.PositionComp.WorldMatrix), _localBox.HalfExtents.Length());
            var supported = 0;
            var total     = 0;
            var entities  = MyEntities.GetTopMostEntitiesInSphere(ref sphere);

            using (entities.GetClearToken())
            {
                var gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(Entity.GetPosition());
                gravity.Normalize();

                for (var i = 0; i < shape.Segments; i++)
                {
                    var t   = (i + 0.5f) / shape.Segments;
                    var pos = curve.Sample(t);
                    pos += gravity;

                    var aabb = new BoundingBoxD(pos - 0.5f, pos + 0.5f);

                    var found = false;
                    foreach (var e in entities)
                    {
                        var vox  = e as MyVoxelBase;
                        var grid = e.Components.Get <MyGridDataComponent>();
                        if (vox != null)
                        {
                            Vector3I vc;
                            var      test = pos;
                            MyVoxelCoordSystems.WorldPositionToVoxelCoord(vox.PositionLeftBottomCorner, ref test, out vc);
                            _voxelStorage.Resize(Vector3I.One);
                            vox.Storage.ReadRange(_voxelStorage, MyStorageDataTypeFlags.Content, 0, in vc, in vc);
                            found |= _voxelStorage.Get(MyStorageDataTypeEnum.Content, ref Vector3I.Zero) > 0;
                        }
                        else if (grid != null)
                        {
                            found |= grid.AnyBlocksInAABB(aabb);
                        }

                        if (found)
                        {
                            break;
                        }
                    }

                    if (found)
                    {
                        supported++;
                    }
                    total++;
                }
            }

            return(supported >= 0.8 * total);
        }
コード例 #18
0
 public Vector3D GetTotalGravity()
 {
     return(MyGravityProviderSystem.CalculateTotalGravityInPoint(WorldMatrix.Translation));
 }
コード例 #19
0
        public override bool HandleRespawnRequest(bool joinGame, bool newIdentity, long medicalRoomId, string respawnShipId, MyPlayer.PlayerId playerId, Vector3D?spawnPosition, VRage.ObjectBuilders.SerializableDefinitionId?botDefinitionId)
        {
            MyPlayer player = Sync.Players.GetPlayerById(playerId);

            bool spawnAsNewPlayer = newIdentity || player == null;

            Debug.Assert(player == null || player.Identity != null, "Respawning player has no identity!");

            if (!MySessionComponentMissionTriggers.CanRespawn(playerId))
            {
                return(false);
            }

            Vector3D currentPosition = Vector3D.Zero;

            if (player != null && player.Character != null)
            {
                currentPosition = player.Character.PositionComp.GetPosition();
            }

            if (TryFindCryoChamberCharacter(player))
            {
                //Player found in chamber;
                return(true);
            }

            MyBotDefinition botDefinition = null;

            if (botDefinitionId != null)
            {
                MyDefinitionManager.Static.TryGetBotDefinition((MyDefinitionId)botDefinitionId, out botDefinition);
            }

            if (!spawnAsNewPlayer)
            {
                if (respawnShipId != null)
                {
                    SpawnAtShip(player, respawnShipId, botDefinition);
                    return(true);
                }

                if (spawnPosition.HasValue)
                {
                    Vector3D gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(spawnPosition.Value);
                    if (Vector3D.IsZero(gravity))
                    {
                        gravity = Vector3D.Down;
                    }
                    else
                    {
                        gravity.Normalize();
                    }
                    Vector3D perpendicular;
                    gravity.CalculatePerpendicularVector(out perpendicular);
                    player.SpawnAt(MatrixD.CreateWorld(spawnPosition.Value, perpendicular, -gravity), Vector3.Zero, null, botDefinition, true);

                    return(true);
                }

                // Find respawn block to spawn at
                MyRespawnComponent foundRespawn = null;
                if (medicalRoomId == 0 || !MyFakes.SHOW_FACTIONS_GUI)
                {
                    List <MyRespawnComponent> respawns = null;
                    var nearestRespawn = GetNearestRespawn(currentPosition, out respawns, MySession.Static.CreativeMode ? (long?)null : player.Identity.IdentityId);
                    if (joinGame && respawns.Count > 0)
                    {
                        foundRespawn = respawns[MyRandom.Instance.Next(0, respawns.Count)];
                    }
                }
                else
                {
                    foundRespawn = FindRespawnById(medicalRoomId, player);
                    if (foundRespawn == null)
                    {
                        return(false);
                    }
                }

                // If spawning in respawn block fails, we will spawn as a new player
                if (foundRespawn != null)
                {
                    SpawnInRespawn(player, foundRespawn, botDefinition);
                }
                else
                {
                    spawnAsNewPlayer = true;
                }
            }

            if (spawnAsNewPlayer)
            {
                bool resetIdentity = false;
                if (MySession.Static.Settings.PermanentDeath.Value)
                {
                    var oldIdentity = Sync.Players.TryGetPlayerIdentity(playerId);
                    resetIdentity = oldIdentity.FirstSpawnDone;
                }

                if (player == null)
                {
                    var identity = Sync.Players.CreateNewIdentity(player.DisplayName);
                    player        = Sync.Players.CreateNewPlayer(identity, playerId, player.DisplayName);
                    resetIdentity = false;
                }

                if (MySession.Static.CreativeMode)
                {
                    Vector3D?correctedPos = MyEntities.FindFreePlace(currentPosition, 2, 200);
                    if (correctedPos.HasValue)
                    {
                        currentPosition = correctedPos.Value;
                    }
                    player.SpawnAt(Matrix.CreateTranslation(currentPosition), Vector3.Zero, null, botDefinition);
                }
                else
                {
                    SpawnAsNewPlayer(player, currentPosition, respawnShipId, resetIdentity, botDefinition);
                }
            }

            return(true);
        }
コード例 #20
0
        public override void UpdateBeforeSimulation()
        {
            bool isDead;

            base.UpdateBeforeSimulation();
            this.UpdateRagdoll();
            if (base.Character.Physics == null)
            {
                goto TR_0004;
            }
            else if (base.Character.Physics.Ragdoll == null)
            {
                goto TR_0004;
            }
            else if (!base.Character.Physics.Ragdoll.InWorld)
            {
                goto TR_0004;
            }
            else
            {
                if (base.Character.Physics.Ragdoll.IsKeyframed && !this.RagdollMapper.IsPartiallySimulated)
                {
                    goto TR_0004;
                }
                if (this.IsRagdollMoving || (this.m_gravityTimer > 0))
                {
                    Vector3 vector = MyGravityProviderSystem.CalculateTotalGravityInPoint(base.Character.PositionComp.WorldAABB.Center) + (base.Character.GetPhysicsBody().HavokWorld.Gravity *MyPerGameSettings.CharacterGravityMultiplier);
                    isDead = base.Character.IsDead;
                    if (isDead)
                    {
                        foreach (HkRigidBody body in base.Character.Physics.Ragdoll.RigidBodies)
                        {
                            if (!body.IsFixedOrKeyframed)
                            {
                                body.ApplyForce(0.01666667f, vector * body.Mass);
                            }
                        }
                    }
                    else
                    {
                        vector *= MyFakes.RAGDOLL_GRAVITY_MULTIPLIER;
                        Vector3.ClampToSphere(ref vector, 500f);
                        foreach (HkRigidBody body2 in base.Character.Physics.Ragdoll.RigidBodies)
                        {
                            if (!body2.IsFixedOrKeyframed)
                            {
                                body2.ApplyForce(0.01666667f, vector);
                            }
                        }
                    }
                }
                else
                {
                    goto TR_0004;
                }
            }
            if (!this.IsRagdollMoving)
            {
                this.m_gravityTimer--;
            }
            else
            {
                this.m_gravityTimer = 300;
                if (isDead)
                {
                    this.m_gravityTimer /= 5;
                }
            }
TR_0004:
            if (((base.Character.Physics != null) && (base.Character.Physics.Ragdoll != null)) && this.IsRagdollMoving)
            {
                this.m_lastPosition = base.Character.Physics.Ragdoll.WorldMatrix.Translation;
            }
        }
コード例 #21
0
        private unsafe void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
        {
            Vector3I vectori3;
            Vector3I vectori4;
            bool     flag = cache != null;

            if (flag)
            {
                this.CheckCacheValidity();
            }
            Vector3D *vectordPtr1 = (Vector3D *)ref obb.HalfExtent;

            vectordPtr1[0] += new Vector3D((double)border, 0.0, (double)border);
            BoundingBoxD  aABB   = obb.GetAABB();
            int           num    = (int)Math.Round((double)(aABB.HalfExtents.Max() * 2.0));
            BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref aABB;

            xdPtr1 = (BoundingBoxD *)new BoundingBoxD(aABB.Min, aABB.Min + num);
            ((BoundingBoxD *)ref aABB).Translate(obb.Center - aABB.Center);
            bbList.Add(new BoundingBoxD(aABB.Min, aABB.Max));
            aABB = aABB.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            aABB.Translate(voxelBase.SizeInMetresHalf);
            Vector3I voxelCoord = Vector3I.Round(aABB.Min);
            Vector3I vectori2   = (Vector3I)(voxelCoord + num);

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref voxelCoord, out vectori3);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref vectori2, out vectori4);
            MyOrientedBoundingBoxD xd2 = obb;

            xd2.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            Vector3D *vectordPtr2 = (Vector3D *)ref xd2.Center;

            vectordPtr2[0] += voxelBase.SizeInMetresHalf;
            Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori3, ref vectori4);
            MyCellCoord            coord    = new MyCellCoord {
                Lod = 0
            };
            int     num2        = 0;
            Vector3 offset      = (Vector3)(originPosition - voxelBase.PositionLeftBottomCorner);
            Vector3 up          = -Vector3.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Matrix  rotation    = Matrix.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp(Vector3.CalculatePerpendicularVector(up), up)));
            Matrix  orientation = (Matrix)voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (iterator.IsValid())
            {
                BoundingBox box;
                MyIsoMesh   mesh;
                if (flag && cache.TryGetValue(iterator.Current, out mesh))
                {
                    if (mesh != null)
                    {
                        this.AddMeshTriangles(mesh, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                    continue;
                }
                coord.CoordInLod = iterator.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out box);
                if (!xd2.Intersects(ref box))
                {
                    num2++;
                    iterator.MoveNext();
                }
                else
                {
                    BoundingBoxD item = new BoundingBoxD(box.Min, box.Max).Translate(-voxelBase.SizeInMetresHalf);
                    bbList.Add(item);
                    Vector3I  lodVoxelMin = (coord.CoordInLod * 8) - 1;
                    MyIsoMesh mesh2       = MyPrecalcComponent.IsoMesher.Precalc(storage, 0, lodVoxelMin, (Vector3I)(((lodVoxelMin + 8) + 1) + 1), MyStorageDataTypeFlags.Content, 0);
                    if (flag)
                    {
                        cache[iterator.Current] = mesh2;
                    }
                    if (mesh2 != null)
                    {
                        this.AddMeshTriangles(mesh2, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                }
            }
        }
コード例 #22
0
        public MyNavmeshManager(MyRDPathfinding rdPathfinding, Vector3D center, Vector3D forwardDirection, int tileSize, int tileHeight, int tileLineCount, MyRecastOptions recastOptions)
        {
            Vector3 vector = new Vector3(ran.NextFloat(), ran.NextFloat(), ran.NextFloat());

            vector              -= Math.Min(vector.X, Math.Min(vector.Y, vector.Z));
            vector              /= Math.Max(vector.X, Math.Max(vector.Y, vector.Z));
            this.m_debugColor    = new Color(vector);
            this.m_tileSize      = tileSize;
            this.m_tileHeight    = tileHeight;
            this.m_tileLineCount = tileLineCount;
            this.Planet          = this.GetPlanet(center);
            this.m_heightCoordTransformationIncrease = 0.5f;
            float cellSize = 0.2f;

            this.m_recastOptions = recastOptions;
            float num2 = (this.m_tileSize * 0.5f) + (this.m_tileSize * ((float)Math.Floor((double)(this.m_tileLineCount * 0.5f))));
            float num3 = this.m_tileHeight * 0.5f;

            this.m_border = this.m_recastOptions.agentRadius + (3f * cellSize);
            float[] bMin = new float[] { -num2, -num3, -num2 };
            float[] bMax = new float[] { num2, num3, num2 };
            this.m_rdWrapper = new MyRDWrapper();
            this.m_rdWrapper.Init(cellSize, (float)this.m_tileSize, bMin, bMax);
            Vector3D vectord = Vector3D.CalculatePerpendicularVector(-Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(center)));

            this.m_navmeshOBBs   = new MyNavmeshOBBs(this.Planet, center, vectord, this.m_tileLineCount, this.m_tileSize, this.m_tileHeight);
            this.m_debugTileSize = new int?[this.m_tileLineCount][];
            for (int i = 0; i < this.m_tileLineCount; i++)
            {
                this.m_debugTileSize[i] = new int?[this.m_tileLineCount];
            }
            this.m_extendedBaseOBB = new MyOrientedBoundingBoxD(this.m_navmeshOBBs.BaseOBB.Center, new Vector3D(this.m_navmeshOBBs.BaseOBB.HalfExtent.X, (double)this.m_tileHeight, this.m_navmeshOBBs.BaseOBB.HalfExtent.Z), this.m_navmeshOBBs.BaseOBB.Orientation);
            this.m_navInputMesh    = new MyNavigationInputMesh(rdPathfinding, this.Planet, center);
        }
コード例 #23
0
 private Vector3D GetPositionAtDistanceFromPlanetCenter(Vector3D position, double distance)
 {
     (position - this.Planet.PositionComp.WorldAABB.Center).Length();
     return((-Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(position)) * distance) + this.Planet.PositionComp.WorldAABB.Center);
 }
コード例 #24
0
        private MatrixD LocalNavmeshPositionToWorldPositionTransform(MyOrientedBoundingBoxD obb, Vector3D center)
        {
            Vector3D v = -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(center));

            return(MatrixD.CreateFromQuaternion(Quaternion.CreateFromForwardUp((Vector3)Vector3D.CalculatePerpendicularVector(v), (Vector3)v)));
        }
コード例 #25
0
        private Vector3D LocalPositionToWorldPosition(Vector3D position)
        {
            Vector3D center = position;

            if (this.m_navmeshOBBs != null)
            {
                center = this.m_meshCenter;
            }
            return(this.LocalNavmeshPositionToWorldPosition(this.m_navmeshOBBs.CenterOBB, position, center, (Vector3D)(0.5 * -Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(center)))));
        }
コード例 #26
0
        public void InitializeNavmesh(Vector3D center)
        {
            this.m_isNavmeshInitialized = true;
            float cellSize = 0.2f;

            this.m_singleTileSize   = 20;
            this.m_tileLineCount    = 50;
            this.m_singleTileHeight = 70;
            MyRecastOptions options1 = new MyRecastOptions();

            options1.cellHeight           = 0.2f;
            options1.agentHeight          = 1.5f;
            options1.agentRadius          = 0.5f;
            options1.agentMaxClimb        = 0.5f;
            options1.agentMaxSlope        = 50f;
            options1.regionMinSize        = 1f;
            options1.regionMergeSize      = 10f;
            options1.edgeMaxLen           = 50f;
            options1.edgeMaxError         = 3f;
            options1.vertsPerPoly         = 6f;
            options1.detailSampleDist     = 6f;
            options1.detailSampleMaxError = 1f;
            options1.partitionType        = 1;
            this.m_recastOptions          = options1;
            float num2 = (this.m_singleTileSize * 0.5f) + (this.m_singleTileSize * ((float)Math.Floor((double)(this.m_tileLineCount * 0.5f))));
            float num3 = this.m_singleTileHeight * 0.5f;

            this.m_border = this.m_recastOptions.agentRadius + (3f * cellSize);
            float[] bMin = new float[] { -num2, -num3, -num2 };
            float[] bMax = new float[] { num2, num3, num2 };
            this.rdWrapper = new MyRDWrapper();
            this.rdWrapper.Init(cellSize, (float)this.m_singleTileSize, bMin, bMax);
            Vector3D forwardDirection = Vector3D.CalculatePerpendicularVector(-Vector3D.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(center)));

            this.UnloadData();
            this.m_navmeshOBBs = new MyNavmeshOBBs(this.GetPlanet(center), center, forwardDirection, this.m_tileLineCount, this.m_singleTileSize, this.m_singleTileHeight);
            this.m_meshCenter  = center;
            this.m_visualNavmesh.Clear();
        }
コード例 #27
0
        protected void Init_GotoRandomLocation()
        {
            // generate position and set navigation
            var position          = Bot.AgentEntity.PositionComp.GetPosition();
            var up                = MyPerGameSettings.NavmeshPresumesDownwardGravity ? Vector3D.UnitY : (Vector3D)MyGravityProviderSystem.CalculateTotalGravityInPoint(position);
            var randomDir         = MyUtils.GetRandomPerpendicularVector(ref up);
            var correctedPosition = position - randomDir * 15;

            AiTargetBase.SetTargetPosition(position + randomDir * 30);
            m_locationSphere.Init(ref correctedPosition, 30, randomDir);
            Bot.Navigation.Goto(m_locationSphere);
        }
コード例 #28
0
        private void Simulate()
        {
            var root = Entity;

            while (root != null && root.Physics == null)
            {
                root = root.Parent;
            }
            if (root?.Physics == null || root.Physics.IsStatic)
            {
                if (!RailConstants.Debug.DrawBogiePhysics)
                {
                    return;
                }

                var drawPivot   = Entity.GetPosition() + 4 * Entity.PositionComp.WorldMatrix.Up;
                var colorTarget = new Vector4(1, 1, 0, 1);
                MySimpleObjectDraw.DrawLine(Entity.GetPosition(), drawPivot, DebugMtl, ref colorTarget,
                                            .01f);
                return;
            }

            // Clean good controllers
            {
                _goodControllers.Clear();
                FindAttachedAnimControllers(Entity, _goodControllers);

                _removedControllers.Clear();
                foreach (var k in _activeControllers)
                {
                    if (!_goodControllers.Contains(k))
                    {
                        _removedControllers.Add(k);
                    }
                }

                foreach (var k in _removedControllers)
                {
                    _activeControllers.Remove(k);
                }
                _removedControllers.Clear();

                var sync = false;
                foreach (var k in _goodControllers)
                {
                    if (_activeControllers.Add(k))
                    {
                        sync = true;
                    }
                }

                if (sync)
                {
                    AddScheduledCallback(ControllerSync, 30);
                }
            }


            var physics    = root.Physics;
            var pivotWorld = Entity.PositionComp.WorldMatrix.Translation;

            var  best        = double.MaxValue;
            var  bestTangent = Vector3.Zero;
            Edge bestEdge    = null;
            RailSegmentComponent bestEdgeSegment;

            RailSegmentDefinition.RailSegmentCaps?bestEdgeCaps = null;
            float bestTime = 0;

            using (var e = Graph.Edges.SortedByDistance(pivotWorld))
                while (e.MoveNext())
                {
                    if (Math.Sqrt(e.Current.DistanceSquared) - TotalBias > best)
                    {
                        break;
                    }
                    var edge = (Edge)e.Current.UserData;
                    if (edge.Curve == null)
                    {
                        continue;
                    }
                    var edgeSegment = edge.Owner.Entity.Components.Get <RailSegmentComponent>();
                    var edgeCaps    = edgeSegment?.Definition.CapabilitiesFor(edge.Owner.Entity.GetBuildRatio());
                    if (edgeSegment == null || !edgeCaps.HasValue)
                    {
                        continue; // no capabilities at this stage
                    }
                    float t0 = 0, t1 = 1;
                    CurveExtensions.NearestPoint(edge.Curve, pivotWorld, 16, ref t0, ref t1);
                    var p0     = edge.Curve.Sample(t0);
                    var p1     = edge.Curve.Sample(t1);
                    var dir    = p1 - p0;
                    var factor = (float)MathHelper.Clamp(dir.Dot(pivotWorld - p0) / dir.LengthSquared(), 0, 1);
                    var t      = t0 + (t1 - t0) * factor;
                    var pos    = edge.Curve.Sample(t);
                    var dist   = Vector3D.Distance(pos, pivotWorld);
                    if (dist - TotalBias > best)
                    {
                        continue;
                    }
                    var tangent = (Vector3)edge.Curve.SampleDerivative(t);
                    tangent.Normalize();

                    const float switchingEpsilon = 0.25f;
                    var         switched         = false;
                    if (t < switchingEpsilon)
                    {
                        switched = edge.From.IsSwitchedTo(edge.To);
                    }
                    else if (t >= 1 - switchingEpsilon)
                    {
                        switched = edge.To.IsSwitchedTo(edge.From);
                    }
                    if (switched)
                    {
                        dist -= SwitchingDistanceBias + AlignmentTangentBias;
                    }
                    else
                    {
                        dist -= AlignmentTangentBias * Math.Abs(Entity.PositionComp.WorldMatrix.Forward.Dot(tangent));
                    }

                    if (RailConstants.Debug.DrawBogieEdges)
                    {
                        edge.Draw(0, 1, switched ? new Vector4(0, 1, 0, 1) : new Vector4(1, 0, 1, 1), 2);
                    }

                    // ReSharper disable once InvertIf
                    if (dist < best)
                    {
                        best            = dist;
                        bestTangent     = tangent;
                        bestEdge        = edge;
                        bestEdgeSegment = edgeSegment;
                        bestEdgeCaps    = edgeCaps;
                        bestTime        = t;
                    }
                }

            var selfVelocity = physics.GetVelocityAtPoint(pivotWorld);

            SetAnimVar(SpeedZVar, selfVelocity.Dot((Vector3)Entity.PositionComp.WorldMatrix.Forward));
            if (bestEdge == null)
            {
                if (!RailConstants.Debug.DrawBogiePhysics)
                {
                    return;
                }

                var drawPivot   = pivotWorld + 4 * Entity.PositionComp.WorldMatrix.Up;
                var colorTarget = new Vector4(1, 0, 0, 1);
                MySimpleObjectDraw.DrawLine(pivotWorld, drawPivot, DebugMtl, ref colorTarget,
                                            .01f);
                return;
            }

            if (best > Definition.DetachDistance)
            {
                if (!RailConstants.Debug.DrawBogiePhysics)
                {
                    return;
                }

                var drawPivot   = pivotWorld + 4 * Entity.PositionComp.WorldMatrix.Up;
                var colorTarget = new Vector4(1, 0, 1, 1);
                MySimpleObjectDraw.DrawLine(pivotWorld, drawPivot, DebugMtl, ref colorTarget,
                                            .01f);
                return;
            }

            var up = (Vector3)Vector3D.Lerp(bestEdge.From.Up, bestEdge.To.Up, bestTime);

            // Not aligned vertically, abort
            if (Entity.PositionComp.WorldMatrix.Up.Dot(up) < 0.5)
            {
                return;
            }

            if (Entity.PositionComp.WorldMatrix.Forward.Dot(bestTangent) < 0)
            {
                bestTangent = -bestTangent;
            }
            var curvePosition = bestEdge.Curve.Sample(bestTime) + up * Definition.VerticalOffset;
            var normal        = Vector3.Cross(bestTangent, up);

            normal.Normalize();

            up = Vector3.Cross(normal, bestTangent);
            up.Normalize();

            var impulse           = Vector3.Zero;
            var allowDeactivation = true;
            var effectiveMass     = root.Physics.Mass;
            var inertiaTensor     = root.Physics.InertiaTensor;

            var qCurrent            = Quaternion.CreateFromRotationMatrix(Entity.PositionComp.WorldMatrix);
            var qDesired            = Quaternion.CreateFromRotationMatrix(Matrix.CreateWorld(Vector3.Zero, bestTangent, up));
            var qConj               = Quaternion.Multiply(Quaternion.Conjugate(qCurrent), qDesired);
            var localAngularDesired = 2 * qConj.W * new Vector3(qConj.X, qConj.Y, qConj.Z);

            if (localAngularDesired.LengthSquared() > .01f)
            {
                allowDeactivation = false;
            }
            var desiredAngular = Vector3.Transform(localAngularDesired, qCurrent) * 2;
            var rotApply       = desiredAngular;
            var angularImpulse = Vector3.TransformNormal(desiredAngular - 0.25f * physics.AngularVelocity, inertiaTensor) *
                                 Definition.OrientationConvergenceFactor /
                                 MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
            var com = physics.GetCenterOfMassWorld();

            // a) spring joint along normal to get dot(normal, (pivot*matrix - position)) == 0
            var err = (Vector3)(curvePosition - pivotWorld);

            // preemptive up force to counteract gravity.
            var gravityHere = MyGravityProviderSystem.CalculateTotalGravityInPoint(pivotWorld);

            impulse += Vector3.Dot(gravityHere, up) * up * physics.Mass * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

            impulse += SolveImpulse(err, normal, physics.LinearVelocity, effectiveMass);

            // b) half spring joint along up to get dot(up, (pivot*matrix - position)) >= 0
            impulse += SolveImpulse(err, up, physics.LinearVelocity, effectiveMass, 1); // only up force

            if (err.LengthSquared() > .01f)
            {
                allowDeactivation = false;
            }

            var braking = false;

            // Hack until I fix EquinoxCore
            if (Definition.MaxVelocity > 0 && (_powerObserver.IsPowered || Definition.NeedsPower == PowerObserver.RequiredPowerEnum.None))
            {
                var cvel        = physics.LinearVelocity.Dot(bestTangent);
                var velocityMod = 0f;

                // get nearest character
                var totalControl = 0f;
                var controllers  = 0;
                var sprinters    = 0;
                foreach (var player in _activeControllers)
                {
                    var component = player?.Get <MyCharacterMovementComponent>();
                    if (component == null)
                    {
                        continue;
                    }
                    var control = Vector3.TransformNormal(component.MoveIndicator, player.WorldMatrix).Dot(bestTangent);
                    totalControl += control;
                    controllers++;

                    var speed = new MyMovementSpeed {
                        Forward = 1f
                    };
                    var speedMod = component.ApplyMovementSpeedEffects(speed);
                    velocityMod = Math.Max(velocityMod, speedMod.Forward);

                    if (!component.WantsSprint)
                    {
                        continue;
                    }
                    var stats = component.Container?.Get <MyEntityStatComponent>();
                    stats?.AddEffect(SprintingEffect);
                    sprinters++;
                }

                if (controllers > 0)
                {
                    braking |= Math.Sign(cvel) != Math.Sign(totalControl) && Math.Abs(cvel) > 0.01 &&
                               Math.Abs(totalControl) > 0.01;
                    SetAnimVar(BrakingVar, braking ? 1 : 0);
                    _powerFactor = MathHelper.Clamp(_powerFactor * (1 - PowerSmooth) + totalControl * PowerSmooth, -1, 1);
                    if (Math.Abs(totalControl) < .01f)
                    {
                        _powerFactor = 0;
                    }

                    var velocityLimit = Definition.MaxVelocity * velocityMod;
                    velocityLimit = Math.Min(velocityLimit, bestEdgeCaps.Value.MaxSpeed);

                    var forceFactorBase    = MathHelper.Clamp(1 - Math.Abs(cvel) / velocityLimit, 0, 1);
                    var forceFactorControl = Math.Abs(_powerFactor);
                    if (sprinters > 0)
                    {
                        forceFactorControl *= 5 * ((float)sprinters) / controllers;
                    }
                    forceFactorControl *= .9f + controllers * .1f;

                    var dir = Math.Sign(_powerFactor);
                    if (dir != Math.Sign(cvel))
                    {
                        forceFactorBase = 1;
                    }

                    var force = Definition.MaxForce * forceFactorControl * forceFactorBase * dir * bestTangent *
                                MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
                    physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, force, com,
                                     Vector3.Zero);
                }
            }


            Vector3 frictiveImpulse;

            {
                var frictiveNormalForce = Math.Max(0, impulse.Dot(up) / MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS);

                var frictiveCoefficient = Math.Max(Definition.CoefficientOfFriction, braking ? Definition.BrakingCoefficientOfFriction : 0);
                if (physics.LinearVelocity.LengthSquared() > .01f)
                {
                    frictiveCoefficient *= 0.75f;
                }
                var frictiveForce = frictiveCoefficient * (bestEdgeCaps?.Friction ?? 1) * frictiveNormalForce;

                // clamp frictive impulse to at-max stopping.
                var tangentMomentumAfterUpdate =
                    (physics.Mass * (physics.LinearVelocity + gravityHere * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) + impulse).Dot(bestTangent);

                var frictiveFloatImpulse = frictiveForce * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                if (frictiveFloatImpulse > Math.Abs(tangentMomentumAfterUpdate))
                {
                    // Stationary, allow deactivation
                    frictiveImpulse = -tangentMomentumAfterUpdate * bestTangent;
                }
                else
                {
                    frictiveImpulse   = -Math.Sign(tangentMomentumAfterUpdate) * frictiveFloatImpulse * bestTangent;
                    allowDeactivation = false;
                }

                impulse += frictiveImpulse;
            }

            if (!MyAPIGateway.Utilities.IsDedicated && RailConstants.Debug.DrawBogiePhysics)
            {
                var drawPivot   = pivotWorld + 4 * up;
                var colorTarget = Vector4.One;
                MySimpleObjectDraw.DrawLine(pivotWorld, curvePosition, DebugMtl, ref colorTarget,
                                            .01f);

                var colorMarker = new Vector4(0, 1, 0, 1);
                MySimpleObjectDraw.DrawLine(drawPivot, drawPivot + frictiveImpulse * 10, DebugMtl, ref colorMarker,
                                            .01f);

                var colorImpulse = new Vector4(1, 0, 0, 1);
                MySimpleObjectDraw.DrawLine(drawPivot, drawPivot + impulse, DebugMtl, ref colorImpulse,
                                            .01f);

                var colorAngImpulse = new Vector4(0, 0, 1, 1);
                MySimpleObjectDraw.DrawLine(drawPivot, drawPivot + rotApply, DebugMtl, ref colorAngImpulse,
                                            .01f);
            }

            if (allowDeactivation)
            {
//                physics.Sleep();
//                if (!physics.IsActive)
//                    return;
            }

            physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, impulse, com, Vector3.Zero);
            physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, Vector3.Zero, pivotWorld, angularImpulse);
        }
コード例 #29
0
        internal void ChangeSlotInternal(EquiPlayerAttachmentComponent.Slot slot, float randSeed)
        {
            this.GetLogger().Debug($"Changing slot for {Entity} to {slot?.Controllable?.Entity}#{slot?.Definition.Name}");
            var old = _controlledSlot;

            _controlledSlot = slot;

            var oldAnimData = old?.Definition.ByIndex(_saveData.AnimationId);

            EquiPlayerAttachmentComponentDefinition.AnimationDesc?newAnimData = null;
            if (slot != null && _saveData.ControlledSlot == slot.Definition.Name)
            {
                newAnimData = slot.Definition.ByIndex(_saveData.AnimationId);
            }
            if (!newAnimData.HasValue)
            {
                newAnimData = slot?.Definition.SelectAnimation(Entity.DefinitionId ?? default(MyDefinitionId), randSeed, out _saveData.AnimationId);
            }

            // Handles animation controller switching
            var animController = Entity.Components.Get <MyAnimationControllerComponent>();

            if (animController != null)
            {
                if (oldAnimData.HasValue)
                {
                    animController.TriggerAction(oldAnimData.Value.Stop);
                }
                if (newAnimData.HasValue)
                {
                    AddScheduledCallback(CommitAnimationStart);
                }
            }

            // Handle restoring character's position
            if (slot == null && old?.Controllable?.Entity != null && old.Controllable.Entity.InScene)
            {
                var relMatrix = _saveData.RelativeOrientation.GetMatrix();
                if (relMatrix.Scale.AbsMax() < 1)
                {
                    relMatrix = MatrixD.Identity;
                }
                var outPos            = relMatrix * old.AttachMatrix;
                var transformedCenter = Vector3.TransformNormal(Entity.PositionComp.LocalAABB.Center, outPos);
                var orientation       = Quaternion.CreateFromRotationMatrix(Entity.PositionComp.WorldMatrix.GetOrientation());
                var halfExtents       = Entity.PositionComp.LocalAABB.HalfExtents;
                halfExtents.X *= 0.25f;
                halfExtents.Z *= 0.25f;
                var translate = MyEntities.FindFreePlace(outPos.Translation + transformedCenter, orientation,
                                                         halfExtents, 200, 20, 0.1f, false);
                if (translate.HasValue)
                {
                    outPos.Translation = translate.Value - transformedCenter;
                }
                else
                {
                    outPos = old.AttachMatrix;
                }
                var gravity = Vector3.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(outPos.Translation));
                if (MyAPIGateway.Physics.CastRay(outPos.Translation - gravity, outPos.Translation + 10 * gravity, out var hit))
                {
                    outPos.Translation = hit.Position;
                }

                Entity.PositionComp.SetWorldMatrix(outPos, Entity.Parent, true);
            }

            // Handles storing the character's position when attaching
            if (slot != null)
            {
                _saveData.RelativeOrientation = new MyPositionAndOrientation(MatrixD.Normalize(Entity.WorldMatrix * MatrixD.Invert(slot.AttachMatrix)));
            }


            // Handle keeping the physics in check
            if (Entity.Physics != null)
            {
                var wantsPhysicsEnabled = slot == null;
                if (wantsPhysicsEnabled && !Entity.Physics.Enabled)
                {
                    Entity.Physics.Activate();
                }
                else if (!wantsPhysicsEnabled && Entity.Physics.Enabled)
                {
                    Entity.Physics.Deactivate();
                }
                if (slot == null)
                {
                    var oldPhys = old?.Controllable?.Entity.ParentedPhysics();
                    if (oldPhys != null)
                    {
                        Entity.Physics.LinearVelocity = oldPhys.GetVelocityAtPoint(old.Controllable.Entity.WorldMatrix.Translation);
                    }
                }
            }

            _saveData.ControlledEntity = slot?.Controllable.Entity.EntityId ?? 0;
            _saveData.ControlledSlot   = slot?.Definition.Name;
            if (slot == null)
            {
                _tracker.Unlink(Entity.EntityId);
            }
            else
            {
                _tracker.Link(Entity.EntityId, new ControlledId(slot));
            }

            if (old?.Controllable != null)
            {
                RemoveFixedUpdate(FixPosition);
            }

            if (slot?.Controllable != null)
            {
                AddFixedUpdate(FixPosition, PriorityOverride);
            }

            FixPosition();

            if (old != null)
            {
                old.AttachedCharacter = null;
            }
            if (slot != null)
            {
                slot.AttachedCharacter = Entity;
            }
            ControlledChanged?.Invoke(this, old, slot);
            _tracker.RaiseControlledChange(this, old, slot);
        }
コード例 #30
0
        public static bool AttemptPhysicsSleep(MyEntity start)
        {
            var relativeTo = start.Get <MyPhysicsComponentBase>();

            using (PoolManager.Get(out HashSet <MyGroup> visitedGroups))
                using (PoolManager.Get(out HashSet <MyEntity> visitedEntities))
                    using (PoolManager.Get(out List <MyEntity> pruningEntities))
                        using (PoolManager.Get(out Queue <MyEntity> queue))
                        {
                            visitedEntities.Clear();
                            visitedGroups.Clear();
                            queue.Clear();

                            queue.Enqueue(start);
                            visitedEntities.Add(start);
                            while (queue.Count > 0)
                            {
                                var e = queue.Dequeue();
                                if (e.Components.TryGet(out MyBlockComponent block))
                                {
                                    if (visitedEntities.Add(block.GridData.Entity))
                                    {
                                        queue.Enqueue(block.GridData.Entity);
                                    }
                                    continue;
                                }

                                if (!e.Components.TryGet <MyPhysicsComponentBase>(out var physicsComponent) || physicsComponent.IsStatic || !physicsComponent.Enabled)
                                {
                                    continue;
                                }
                                if (e.Components.TryGet <MyCharacterPhysics>(out var characterPhysics) && characterPhysics.Enabled)
                                {
                                    return(false);
                                }
                                if (relativeTo != physicsComponent && !CanSleepPhysics(physicsComponent, relativeTo))
                                {
                                    return(false);
                                }

                                foreach (var group in MySession.Static.Scene.GetEntityGroups(e.Id))
                                {
                                    if (visitedGroups.Add(@group))
                                    {
                                        foreach (var entity in @group.Entities)
                                        {
                                            if (visitedEntities.Add(entity))
                                            {
                                                queue.Enqueue(entity);
                                            }
                                        }
                                    }
                                }

                                var queryVol = e.PositionComp.WorldVolume;
                                queryVol.Radius += 1;
                                pruningEntities.Clear();
                                MyGamePruningStructure.GetTopMostEntitiesInSphere(in queryVol, pruningEntities, MyEntityQueryType.Dynamic);
                                foreach (var nearby in pruningEntities)
                                {
                                    if (visitedEntities.Add(nearby) && nearby.PositionComp.WorldVolume.Intersects(queryVol))
                                    {
                                        queue.Enqueue(nearby);
                                    }
                                }
                            }

                            foreach (var ent in visitedEntities)
                            {
                                var gridPhysics = ent.Get <MyGridRigidBodyComponent>();
                                if (gridPhysics == null)
                                {
                                    continue;
                                }
                                gridPhysics.Gravity = MyGravityProviderSystem.CalculateTotalGravityInPoint(ent.PositionComp.GetPosition());
                                gridPhysics.Sleep();
                            }

                            return(true);
                        }
        }