bool GetPropertiesFromEntity(MyEntity entity, ref Vector3D position1, out Quaternion rotation2, out Vector3 posDiff, out HkShape?shape2)
        {
            rotation2 = new Quaternion();
            posDiff   = Vector3.Zero;
            shape2    = null;
            if (entity.Physics == null || !entity.Physics.Enabled)
            {
                return(false);
            }

            if (entity.Physics.RigidBody != null)
            {
                shape2 = entity.Physics.RigidBody.GetShape();

                var worldMatrix = entity.WorldMatrix;
                rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                posDiff   = entity.PositionComp.GetPosition() - position1;
                if (entity is MyVoxelBase)
                {
                    var voxel = entity as MyVoxelBase;
                    posDiff -= voxel.Size / 2;
                }
            }
            else if (entity.GetPhysicsBody().CharacterProxy != null)
            {
                shape2 = entity.GetPhysicsBody().CharacterProxy.GetShape();
                var worldMatrix = entity.WorldMatrix;
                rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                posDiff   = entity.PositionComp.GetPosition() - position1;
            }
            else
            {
                return(false);
            }

            return(true);
        }
Beispiel #2
0
        /// <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.CollisionLayers.CharacterCollisionLayer);
                    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.CollisionLayers.CharacterCollisionLayer);
                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, MyPhysics.CollisionLayers.CharacterCollisionLayer);
                if (m_rigidList.Count > 0)
                {
                    bool sameGrid = false;
                    if (MySession.Static.ControlledEntity != null && m_rigidList[0].Body != null)
                    {
                        sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.Static.ControlledEntity;
                    }

                    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 != null && controlledEntity.GetPhysicsBody().CharacterProxy != null)
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.CharacterCollisionLayer, 0.0f);
                }
                else
                {
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.DefaultCollisionLayer, 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();
            }
        }
            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.CollisionLayers.ObjectDetectionCollisionLayer);
                // Remove character hits.
                m_tmpHitList.RemoveAll(delegate(MyPhysics.HitInfo hit)
                {
                    return(hit.HkHitInfo.GetHitEntity() == MySession.Static.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.GetHitEntity() 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.GetPhysicsBody().HavokWorld.DestructionWorld != null)
                {
                    MyPhysics.FractureImpactDetails destruction = new MyPhysics.FractureImpactDetails();
                    destruction.Details = details;
                    destruction.World   = closestEntity.GetPhysicsBody().HavokWorld;
                    destruction.Entity  = closestEntity;
                    MyPhysics.EnqueueDestruction(destruction);
                    //closestGrid.GetPhysicsBody().HavokWorld.DestructionWorld.TriggerDestruction(ref details);
                }
                //details.RemoveReference();
            }
            private void DrawBodyInfo()
            {
                Vector2  pos       = new Vector2(400, 10);
                MyEntity hitEntity = null;

                HkRigidBody body = null;

                if (SelectedEntity != null && SelectedEntity.Physics != null)
                {
                    body = ((MyEntity)SelectedEntity).Physics.RigidBody;
                }

                if (MySector.MainCamera != null && body == 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)
                    {
                        body = hit.HkHitInfo.Body;
                        if (body == null || body.Layer == MyPhysics.CollisionLayers.NoCollisionLayer)
                        {
                            continue;
                        }
                        hitEntity = hit.HkHitInfo.GetHitEntity() as MyEntity;

                        var sb = new System.Text.StringBuilder("ShapeKeys: ");
                        for (int i = 0; i < HkWorld.HitInfo.ShapeKeyCount; i++)
                        {
                            var key = hit.HkHitInfo.GetShapeKey(i);
                            if (key == uint.MaxValue)
                            {
                                break;
                            }
                            sb.Append(string.Format("{0} ", key));
                        }
                        VRageRender.MyRenderProxy.DebugDrawText2D(pos, sb.ToString(), Color.White, 0.7f);
                        pos.Y += 20;
                        if (hitEntity != null)
                        {
                            VRageRender.MyRenderProxy.DebugDrawText2D(pos, string.Format("Weld: {0}", hitEntity.GetPhysicsBody().WeldInfo.Children.Count), Color.White, 0.7f);
                        }
                        pos.Y += 20;
                        break;
                    }
                }
                //if (MySector.MainCamera != null)
                //{
                //    LineD line = new LineD(MySector.MainCamera.Position, MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * 100);
                //    var intersect = MyEntities.GetIntersectionWithLine(ref line, MySession.ControlledEntity.Entity, null);
                //    if (intersect.HasValue)
                //    {
                //        VRageRender.MyRenderProxy.DebugDrawText2D(pos, intersect.Value.Entity.ToString() + " "
                //              , Color.White, 0.8f);
                //    }
                //}

                if (body != null && m_drawBodyInfo)
                {
                    //body.Activate();
                    //VRageRender.MyRenderProxy.DebugDrawText2D(pos, body.GetEntity(0).ToString() + " "
                    //       + MyDestructionHelper.MassFromHavok(body.Mass), Color.White, 0.8f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Layer: " + body.Layer, body.Layer == 0 ? Color.Red : Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, string.Format("Friction: {0}  Restitution: {1}", body.Friction, body.Restitution), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Lin: " + body.LinearVelocity.Length(), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Ang: " + body.AngularVelocity.Length(), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Act: " + (body.IsActive ? "true" : "false"), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Stat: " + (body.IsFixedOrKeyframed ? "true" : "false"), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Solver: " + (body.Motion.GetDeactivationClass()), Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Mass: " + body.Mass, Color.White, 0.7f);
                    pos.Y += 20;
                    //VRageRender.MyRenderProxy.DebugDrawText2D(pos, "SysID: " + body.GetBody().HavokCollisionSystemID, Color.White, 0.7f);
                    pos.Y += 20;
                    //VRageRender.MyRenderProxy.DebugDrawText2D(pos, "CharLin: " + MySession.ControlledEntity.Entity.Physics.LinearVelocity.Length(), Color.White, 0.7f);
                }

                if (SelectedEntity != null && m_drawUpdateInfo)
                {
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Updates: " + m_counter, Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "PositionUpd: " + dbgPosCounter, Color.White, 0.7f);
                    pos.Y += 20;
                    VRageRender.MyRenderProxy.DebugDrawText2D(pos, "Frames per update: " + m_counter / (float)dbgPosCounter, Color.White, 0.7f);
                    pos.Y += 20;
                }
            }
        void CubeGrid_OnPhysicsChanged(MyEntity obj)
        {
            if (m_subparts == null || m_subparts.Count == 0)
            {
                return;
            }

            if (m_subparts[0].Physics == null)
            {
                return;
            }
            if (obj.Physics != null && obj.GetPhysicsBody().HavokCollisionSystemID != m_subparts[0].GetPhysicsBody().HavokCollisionSystemID)
                UpdateHavokCollisionSystemID(obj.GetPhysicsBody().HavokCollisionSystemID);
            UpdateDoorPosition();
        }
        /// <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.CollisionLayers.CharacterCollisionLayer);
                    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.CollisionLayers.CharacterCollisionLayer);
                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, MyPhysics.CollisionLayers.CharacterCollisionLayer);
                if (m_rigidList.Count > 0)
                {
                    bool sameGrid = false;
                    if (MySession.Static.ControlledEntity != null && m_rigidList[0].Body != null)
                    {
                        sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.Static.ControlledEntity;
                    }

                    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 != null && controlledEntity.GetPhysicsBody().CharacterProxy != null)
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.CharacterCollisionLayer, 0.0f);
                else
                    cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.DefaultCollisionLayer, 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();
            }
        }