Esempio n. 1
0
        public static bool FindRandomFracturedTreeInPlaceArea(Vector3D fromPosition, long entityId, out EntityInfo result)
        {
            result = default(EntityInfo);

            MyPlaceArea area = MyPlaceArea.FromEntity(entityId);

            if (area == null)
            {
                return(false);
            }

            var             areaBB       = area.WorldAABB;
            BoundingSphereD searchSphere = new BoundingSphereD(areaBB.Center, (double)areaBB.HalfExtents.Length());

            m_tmpFracturePieceList.Clear();
            FindFracturedTreesInternal(fromPosition, area, searchSphere);

            if (m_tmpFracturePieceList.Count == 0)
            {
                m_tmpFracturePieceList.Clear();
                return(false);
            }

            int fractureIndex = (int)Math.Round(MyRandom.Instance.NextFloat() * (m_tmpFracturePieceList.Count - 1));
            MyFracturedPiece selectedTarget = m_tmpFracturePieceList[fractureIndex];

            m_tmpFracturePieceList.Clear();

            result.EntityId = selectedTarget.EntityId;
            result.Target   = selectedTarget.PositionComp.GetPosition();
            return(true);
        }
Esempio n. 2
0
        private static bool FindClosestFracturedTreeInternal(Vector3D fromPosition, Vector3D searchCenter, double searchRadius, MyPlaceArea area, out EntityInfo result)
        {
            result = default(EntityInfo);

            double           closestDistanceSq = double.MaxValue;
            MyFracturedPiece closestTarget     = null;
            Vector3D         closestPoint      = default(Vector3D);

            BoundingSphereD searchSphere = new BoundingSphereD(searchCenter, searchRadius);

            m_tmpFracturePieceList.Clear();
            MyFracturedPiecesManager.Static.GetFracturesInSphere(ref searchSphere, ref m_tmpFracturePieceList);
            for (int i = 0; i < m_tmpFracturePieceList.Count; ++i)
            {
                var fracture = m_tmpFracturePieceList[i];

                // Skip non-tree fractures
                if (!MyTrees.IsEntityFracturedTree(fracture))
                {
                    continue;
                }

                if (IsFracturedTreeStump(fracture))
                {
                    continue;
                }

                Vector3D positionInTrunkLocal = Vector3D.Transform(fromPosition, fracture.PositionComp.WorldMatrixNormalizedInv);
                Vector3D closestPointOnTrunk;

                if (!FindClosestPointOnFracturedTree(positionInTrunkLocal, fracture, out closestPointOnTrunk))
                {
                    continue;
                }

                if (area == null || area.TestPoint(closestPointOnTrunk))
                {
                    double distanceSq = Vector3D.DistanceSquared(closestPointOnTrunk, fromPosition);

                    if (distanceSq < closestDistanceSq)
                    {
                        closestDistanceSq = distanceSq;
                        closestTarget     = fracture;
                        closestPoint      = closestPointOnTrunk;
                    }
                }
            }
            m_tmpFracturePieceList.Clear();

            if (closestTarget == null)
            {
                return(false);
            }

            result.EntityId = closestTarget.EntityId;
            result.Target   = closestPoint;
            return(true);
        }
        private MyFracturedPiece AllocatePiece()
        {
            ProfilerShort.Begin("AllocCounter");
            m_allocatedThisFrame++;

            var fp = new MyFracturedPiece();
            fp.Physics = new MyPhysicsBody(fp, RigidBodyFlag.RBF_DEBRIS);
            ProfilerShort.End();
            return fp;
        }
Esempio n. 4
0
        private static bool IsFracturedTreeStump(MyFracturedPiece fracture)
        {
            Vector4 minFour, maxFour;

            fracture.Shape.GetShape().GetLocalAABB(0, out minFour, out maxFour);
            if (maxFour.Y - minFour.Y < 3.5 * (maxFour.X - minFour.X)) // HACK: find stumps
            {
                return(true);
            }

            return(false);
        }
Esempio n. 5
0
        private static void FindFracturedTreesInternal(Vector3D fromPosition, MyPlaceArea area, BoundingSphereD sphere)
        {
            Debug.Assert(m_tmpFracturePieceList.Count == 0, "m_tmpFracturePieceList was not cleared after last use!");

            MyFracturedPiecesManager.Static.GetFracturesInSphere(ref sphere, ref m_tmpFracturePieceList);

            for (int i = m_tmpFracturePieceList.Count - 1; i >= 0; i--)
            {
                MyFracturedPiece fracture = m_tmpFracturePieceList[i];

                if (!MyTrees.IsEntityFracturedTree(fracture))
                {
                    m_tmpFracturePieceList.RemoveAtFast(i);
                    continue;
                }

                if (IsFracturedTreeStump(fracture))
                {
                    m_tmpFracturePieceList.RemoveAtFast(i);
                    continue;
                }

                Vector3D positionInTrunkLocal = Vector3D.Transform(fromPosition, fracture.PositionComp.WorldMatrixNormalizedInv);
                Vector3D closestPointOnTrunk;

                if (!FindClosestPointOnFracturedTree(positionInTrunkLocal, fracture, out closestPointOnTrunk))
                {
                    m_tmpFracturePieceList.RemoveAtFast(i);
                    continue;
                }

                if (!area.TestPoint(closestPointOnTrunk))
                {
                    m_tmpFracturePieceList.RemoveAtFast(i);
                    continue;
                }
            }
        }
        MyTimeSpan GetPieceAgeLength(MyFracturedPiece piece)
        {
            if (piece.Physics == null || piece.Physics.BreakableBody == null)
                return MyTimeSpan.Zero;

            if (piece.Physics.RigidBody.Layer == FakePieceLayer)
                return MyTimeSpan.FromSeconds(8 + MyRandom.Instance.NextFloat(0, 4));

            float volume = piece.Physics.BreakableBody.BreakableShape.Volume;
            float proposedAgeInSecs = volume * LIFE_OF_CUBIC_PIECE;

            return MyTimeSpan.FromSeconds(proposedAgeInSecs);
        }
Esempio n. 7
0
 public MyFracturedPieceDebugDraw(MyFracturedPiece piece)
 {
     m_piece = piece;
 }
Esempio n. 8
0
        public static void ApplyImpulseToTreeFracture(ref MatrixD worldMatrix, ref Vector3 hitNormal, List<HkdShapeInstanceInfo> shapeList, ref HkdBreakableShape compound, MyFracturedPiece fp, float forceMultiplier = 1.0f)
        {
            float mass = compound.GetMass();
            Vector3 coMMaxY = Vector3.MinValue;
            shapeList.ForEach(s => coMMaxY = (s.CoM.Y > coMMaxY.Y) ? s.CoM : coMMaxY);

            Vector3 forceVector = hitNormal;
            forceVector.Y = 0;
            forceVector.Normalize();

            Vector3 force = 0.3f * forceMultiplier * mass * forceVector;
            fp.Physics.Enabled = true;//so we get the body in world
            Vector3 worldForcePoint = fp.Physics.WorldToCluster(Vector3D.Transform(coMMaxY, worldMatrix));

            fp.Physics.RigidBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping;
            fp.Physics.RigidBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping;

            fp.Physics.RigidBody.ApplyPointImpulse(force, worldForcePoint);
        }
        public static void PlayDestructionSound(MyFracturedPiece fp)
        {
            var bDef = MyDefinitionManager.Static.GetCubeBlockDefinition(fp.OriginalBlocks[0]);

            if (bDef == null)
                return;
            MyPhysicalMaterialDefinition def = bDef.PhysicalMaterial;

            MySoundPair destructionCue;
            if (def.GeneralSounds.TryGetValue(m_destructionSound, out destructionCue) && !destructionCue.SoundId.IsNull)
            {
                var emmiter = MyAudioComponent.TryGetSoundEmitter();
                if (emmiter == null)
                    return;
                Vector3D pos = fp.PositionComp.GetPosition();
                emmiter.SetPosition(pos);
                emmiter.PlaySound(destructionCue);
            }
        }
        public void RemoveFracturePiece(MyFracturedPiece piece, float blendTimeSeconds, bool fromServer = false, bool sync = true)
        {
            System.Diagnostics.Debug.Assert(Sync.IsServer || fromServer, "Clients cannot remove pieces by themselves");
            System.Diagnostics.Debug.Assert((sync && Sync.IsServer) ^ (fromServer && !sync), "Sync must be called on server.");
            if (blendTimeSeconds == 0)
            {
                Debug.Assert((Sync.IsServer && sync) || fromServer, "Server must sync Fracture Piece removal!");
                if (sync)
                {
                    Debug.Assert(m_piecesTimesOfDeath.ContainsKey(piece), "Double removing Fracture Piece!");
                    MySyncDestructions.RemoveFracturePiece(piece.EntityId, blendTimeSeconds);
                }
                RemoveInternal(piece);
                return;
            }

            MyTimeSpan newDeath = MySandboxGame.Static.UpdateTime + MyTimeSpan.FromSeconds(blendTimeSeconds);
            if (m_blendingPieces.Add(piece))
            {
                if (sync)
                    MySyncDestructions.RemoveFracturePiece(piece.EntityId, blendTimeSeconds);

                if (!m_piecesTimesOfDeath.ContainsKey(piece))
                {
                    Debug.Assert(fromServer, "Fracture piece missing time of death on server!");
                    m_piecesTimesOfDeath.Add(piece, newDeath);
                }

                MyTimeSpan currentDeath;
                if (m_piecesTimesOfDeath.TryGetValue(piece, out currentDeath))
                {
                    if (currentDeath > newDeath)
                    {
                        m_piecesTimesOfDeath[piece] = newDeath;
                    }
                }
                else
                    Debug.Fail("Fracture Piece missing time of death!");
            }
            else
            {
                MyTimeSpan currentDeath;
                if (m_piecesTimesOfDeath.TryGetValue(piece, out currentDeath))
                {
                    if (currentDeath > newDeath)
                    {
                        m_piecesTimesOfDeath[piece] = newDeath;

                        if (sync)
                            MySyncDestructions.RemoveFracturePiece(piece.EntityId, blendTimeSeconds);
                    }
                }
                else
                {
                    Debug.Assert(false, "Shouldnt get here");
                }
            }
        }
Esempio n. 11
0
 public MyFracturedPieceDebugDraw(MyFracturedPiece piece)
 {
     m_piece = piece;
 }
Esempio n. 12
0
        private static bool FindClosestPointOnFracturedTree(Vector3D fromPositionFractureLocal, MyFracturedPiece fracture, out Vector3D closestPoint)
        {
            // Marko: HACK: skip stumps     
            closestPoint = default(Vector3D);
            if (fracture == null)
                return false;

            Vector4 minFour, maxFour;
            fracture.Shape.GetShape().GetLocalAABB(0, out minFour, out maxFour);
            var min = new Vector3D(minFour);
            var max = new Vector3D(maxFour);

            closestPoint = Vector3D.Clamp(fromPositionFractureLocal, min, max);

            closestPoint.X = (closestPoint.X + 2 * (max.X + min.X) / 2) / 3;
            closestPoint.Y = MathHelper.Clamp(closestPoint.Y + 0.25f * (closestPoint.Y - min.Y < max.Y - closestPoint.Y ? 1 : -1), min.Y, max.Y);
            closestPoint.Z = (closestPoint.Z + 2 * (max.Z + min.Z) / 2) / 3;

            closestPoint = Vector3D.Transform(closestPoint, fracture.PositionComp.WorldMatrix);

            return true;
        }
Esempio n. 13
0
        private static bool IsFracturedTreeStump(MyFracturedPiece fracture)
        {
            Vector4 minFour, maxFour;
            fracture.Shape.GetShape().GetLocalAABB(0, out minFour, out maxFour);
            if (maxFour.Y - minFour.Y < 3.5 * (maxFour.X - minFour.X)) // HACK: find stumps
                return true;

            return false;
        }
Esempio n. 14
0
        private static bool FindClosestPointOnFracturedTree(Vector3D fromPositionFractureLocal, MyFracturedPiece fracture, out Vector3D closestPoint)
        {
            // Marko: HACK: skip stumps
            closestPoint = default(Vector3D);
            if (fracture == null)
            {
                return(false);
            }

            Vector4 minFour, maxFour;

            fracture.Shape.GetShape().GetLocalAABB(0, out minFour, out maxFour);
            var min = new Vector3D(minFour);
            var max = new Vector3D(maxFour);

            closestPoint = Vector3D.Clamp(fromPositionFractureLocal, min, max);

            closestPoint.X = (closestPoint.X + 2 * (max.X + min.X) / 2) / 3;
            closestPoint.Y = MathHelper.Clamp(closestPoint.Y + 0.25f * (closestPoint.Y - min.Y < max.Y - closestPoint.Y ? 1 : -1), min.Y, max.Y);
            closestPoint.Z = (closestPoint.Z + 2 * (max.Z + min.Z) / 2) / 3;

            closestPoint = Vector3D.Transform(closestPoint, fracture.PositionComp.WorldMatrix);

            return(true);
        }
        private void RemoveInternal(MyFracturedPiece fp)
        {
            if (fp.Physics != null && fp.Physics.RigidBody != null)
            {
                Debug.Assert(!fp.Physics.RigidBody.IsDisposed, "Disposed piece rigid body!!");
                if (fp.Physics.RigidBody.IsDisposed)
                {
                    var rb = fp.Physics.BreakableBody.GetRigidBody();
                    fp.Physics.BreakableBody = fp.Physics.BreakableBody;
                }
            }
            bool a = m_piecesTimesOfDeath.Remove(fp);
            bool b = m_blendingPieces.Remove(fp);
            bool c = m_inactivePieces.Remove(fp);

            if (fp.Physics == null || fp.Physics.RigidBody == null || fp.Physics.RigidBody.IsDisposed)
            {
                Debug.Fail("Should not get here!");
                MyEntities.Remove(fp);
                return;
            }

            fp.Physics.RigidBody.Activated -= RigidBody_Activated;
            fp.Physics.RigidBody.Deactivated -= RigidBody_Deactivated;

            //Let objects staying on this fp to fall
            if (!fp.Physics.RigidBody.IsActive)
                fp.Physics.RigidBody.Activate();

            MyPhysics.RemoveDestructions(fp.Physics.RigidBody);


            var bb = fp.Physics.BreakableBody;
            bb.AfterReplaceBody -= fp.Physics.FracturedBody_AfterReplaceBody;

            MyEntities.Remove(fp);
            fp.Physics.Enabled = false;
            fp.Physics.BreakableBody = null;
            //fp.Shape.RemoveReference();
            //System.Diagnostics.Debug.Assert(bb.ReferenceCount == 1);//not true anymore, since FP can be removed from callback immediately

            MyFracturedPiecesManager.Static.ReturnToPool(bb);
            fp.Render.ClearModels();
            fp.OriginalBlocks.Clear();
            if (Sync.IsServer)
                Debug.Assert(m_dbgRemoved.Add(fp.EntityId));
            else
                MySyncDestructions.FPManagerDbgMessage(0, fp.EntityId);
            fp.EntityId = 0;
            m_piecesPool.Enqueue(fp);

        }
		public bool TryGetFractureById(long entityId, out MyFracturedPiece outFracture)
		{
			outFracture = null;
			var activeFractures = m_piecesTimesOfDeath.Keys;

			foreach(var fracture in activeFractures)
			{
				if (fracture.EntityId == entityId)
				{
					outFracture = fracture;
					return true;
				}
			}


			return false;
		}
        private void RemoveInternal(MyFracturedPiece fp,bool fromServer = false)
        {
            if (fp.Physics != null && fp.Physics.RigidBody != null)
            {
                Debug.Assert(!fp.Physics.RigidBody.IsDisposed, "Disposed piece rigid body!!");
                if (fp.Physics.RigidBody.IsDisposed)
                {
                    fp.Physics.BreakableBody = fp.Physics.BreakableBody;
                }
            }

            if (fp.Physics == null || fp.Physics.RigidBody == null || fp.Physics.RigidBody.IsDisposed)
            {
                Debug.Fail("Should not get here!");
                MyEntities.Remove(fp);
                return;
            }

            //Let objects staying on this fp to fall
            if (!fp.Physics.RigidBody.IsActive)
                fp.Physics.RigidBody.Activate();

            MyPhysics.RemoveDestructions(fp.Physics.RigidBody);


            var bb = fp.Physics.BreakableBody;
            bb.AfterReplaceBody -= fp.Physics.FracturedBody_AfterReplaceBody;
            this.ReturnToPool(bb);
            
            fp.Physics.Enabled = false;
            MyEntities.Remove(fp);
            fp.Physics.BreakableBody = null;
            fp.Render.ClearModels();
            fp.OriginalBlocks.Clear();
            if (Sync.IsServer)
                Debug.Assert(m_dbgRemoved.Add(fp.EntityId));
            else
                MySyncDestructions.FPManagerDbgMessage(0, fp.EntityId);
            fp.EntityId = 0;
            fp.Physics.BreakableBody = null;
            m_piecesPool.Enqueue(fp);

        }
        public static void FixPosition(MyFracturedPiece fp)
        {
            //return;
            ProfilerShort.Begin("FixPosition");
            var shape = fp.Physics.BreakableBody.BreakableShape;
            if (shape.GetChildrenCount() == 0)
            {
                ProfilerShort.End();
                return;
            }
            shape.GetChildren(m_tmpInfos);
            var offset = m_tmpInfos[0].GetTransform().Translation;
            if (offset.LengthSquared() < 1)
            {
                m_tmpInfos.Clear();
                ProfilerShort.End();
                return;
            }
            var lst = new List<HkdConnection>();
            var set = new HashSet<HkdBreakableShape>();
            var set2 = new HashSet<HkdBreakableShape>();
            set.Add(shape);
            shape.GetConnectionList(lst);
            fp.PositionComp.SetPosition(Vector3D.Transform(offset, fp.PositionComp.WorldMatrix));
            foreach (var child in m_tmpInfos)
            {
                var m = child.GetTransform();
                m.Translation -= offset;
                child.SetTransform(ref m);
                m_tmpInfos2.Add(child);
                HkdBreakableShape par = child.Shape;
                par.GetConnectionList(lst);
                while (par.HasParent)
                {
                    par = par.GetParent();
                    if (set.Add(par))
                        par.GetConnectionList(lst);
                    else
                    {

                    }
                }
                set2.Add(child.Shape);
            }
            m_tmpInfos.Clear();
            HkdBreakableShape compound = new HkdCompoundBreakableShape(shape, m_tmpInfos2);
            //HkMassProperties mp = new HkMassProperties();
            ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren();
            compound.SetChildrenParent(compound);
            foreach (var c in lst) 
            {
                HkBaseSystem.EnableAssert(390435339, true);
                if (!set2.Contains(c.ShapeA) || !set2.Contains(c.ShapeB))
                    continue;
                var cref = c;
                compound.AddConnection(ref cref);
            }
            fp.Physics.BreakableBody.BreakableShape = compound;
            m_tmpInfos2.Clear();

            ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren();

            ProfilerShort.End();
        }
        public void RemoveFracturePiece(MyFracturedPiece piece, float blendTimeSeconds, bool fromServer = false, bool sync = true)
        {
            System.Diagnostics.Debug.Assert(Sync.IsServer || fromServer, "Clients cannot remove pieces by themselves");
            System.Diagnostics.Debug.Assert((sync && Sync.IsServer) ^ (fromServer && !sync), "Sync must be called on server.");
            if (blendTimeSeconds == 0)
            {
                Debug.Assert((Sync.IsServer && sync) || fromServer, "Server must sync Fracture Piece removal!");

                RemoveInternal(piece, fromServer);
                return;
            }
        }