private static MyFracturedPiece CreateFracturePiece(ref HkdBreakableShape shape, ref MatrixD worldMatrix, bool isStatic) { MyFracturedPiece pieceFromPool = MyFracturedPiecesManager.Static.GetPieceFromPool(0L, false); pieceFromPool.PositionComp.WorldMatrix = worldMatrix; pieceFromPool.Physics.Flags = isStatic ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS; MyPhysicsBody physics = pieceFromPool.Physics; HkMassProperties massProperties = new HkMassProperties(); shape.BuildMassProperties(ref massProperties); physics.InitialSolverDeactivation = HkSolverDeactivation.High; physics.CreateFromCollisionObject(shape.GetShape(), Vector3.Zero, worldMatrix, new HkMassProperties?(massProperties), 15); physics.LinearDamping = MyPerGameSettings.DefaultLinearDamping; physics.AngularDamping = MyPerGameSettings.DefaultAngularDamping; physics.BreakableBody = new HkdBreakableBody(shape, physics.RigidBody, null, (Matrix)worldMatrix); physics.BreakableBody.AfterReplaceBody += new BreakableBodyReplaced(physics.FracturedBody_AfterReplaceBody); if (pieceFromPool.SyncFlag) { pieceFromPool.CreateSync(); } pieceFromPool.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; pieceFromPool.SetDataFromHavok(shape); pieceFromPool.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; shape.RemoveReference(); return(pieceFromPool); }
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; MyFracturedPiecesManager.Static.ReturnToPool(bb); fp.Physics.Enabled = false; MyEntities.Remove(fp); 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 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 MyFracturedPiece CreateFracturePiece(HkdBreakableShape shape, ref MatrixD worldMatrix, bool isStatic, MyDefinitionId?definition, bool sync) { MyFracturedPiece piece = CreateFracturePiece(ref shape, ref worldMatrix, isStatic); if (definition == null) { piece.Save = false; } else { MyPhysicalModelDefinition definition2; piece.OriginalBlocks.Clear(); piece.OriginalBlocks.Add(definition.Value); if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(definition.Value, out definition2)) { piece.Physics.MaterialType = definition2.PhysicalMaterial.Id.SubtypeId; } } if (piece.Save && MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) { piece.DebugCheckValidShapes(); } if (MyExternalReplicable.FindByObject(piece) == null) { Sandbox.Game.Entities.MyEntities.RaiseEntityCreated(piece); } Sandbox.Game.Entities.MyEntities.Add(piece, true); return(piece); }
public static MyFracturedPiece CreateFracturePiece(HkdBreakableBody b, ref MatrixD worldMatrix, List <MyDefinitionId> originalBlocks, MyCubeBlock block = null, bool sync = true) { if (IsBodyWithoutGeneratedFracturedPieces(b, block)) { return(null); } MyFracturedPiece pieceFromPool = MyFracturedPiecesManager.Static.GetPieceFromPool(0L, false); pieceFromPool.InitFromBreakableBody(b, worldMatrix, block); pieceFromPool.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; if ((originalBlocks != null) && (originalBlocks.Count != 0)) { MyPhysicalModelDefinition definition; pieceFromPool.OriginalBlocks.Clear(); pieceFromPool.OriginalBlocks.AddRange(originalBlocks); if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(originalBlocks[0], out definition)) { pieceFromPool.Physics.MaterialType = definition.PhysicalMaterial.Id.SubtypeId; } } if (MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) { pieceFromPool.DebugCheckValidShapes(); } if (MyExternalReplicable.FindByObject(pieceFromPool) == null) { Sandbox.Game.Entities.MyEntities.RaiseEntityCreated(pieceFromPool); } Sandbox.Game.Entities.MyEntities.Add(pieceFromPool, true); return(pieceFromPool); }
public static MyFracturedPiece CreateFracturePiece(MyFractureComponentCubeBlock fractureBlockComponent, bool sync) { MyPhysicalModelDefinition definition; if (!fractureBlockComponent.Block.BlockDefinition.CreateFracturedPieces) { return(null); } if (!fractureBlockComponent.Shape.IsValid()) { MyLog.Default.WriteLine("Invalid shape in fracture component, Id: " + fractureBlockComponent.Block.BlockDefinition.Id.ToString() + ", closed: " + fractureBlockComponent.Block.FatBlock.Closed.ToString()); return(null); } MatrixD worldMatrix = fractureBlockComponent.Block.FatBlock.WorldMatrix; MyFracturedPiece piece = CreateFracturePiece(ref fractureBlockComponent.Shape, ref worldMatrix, false); piece.OriginalBlocks.Add(fractureBlockComponent.Block.BlockDefinition.Id); if (MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) { piece.DebugCheckValidShapes(); } if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(piece.OriginalBlocks[0], out definition)) { piece.Physics.MaterialType = definition.PhysicalMaterial.Id.SubtypeId; } if (MyExternalReplicable.FindByObject(piece) == null) { Sandbox.Game.Entities.MyEntities.RaiseEntityCreated(piece); } Sandbox.Game.Entities.MyEntities.Add(piece, true); return(piece); }
private MyFracturedPiece AllocatePiece() { ProfilerShort.Begin("AllocCounter"); m_allocatedThisFrame++; var fp = new MyFracturedPiece(); fp.Physics = new MyPhysicsBody(fp, RigidBodyFlag.RBF_DEBRIS); ProfilerShort.End(); return(fp); }
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; } }
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); return; } MyTimeSpan newDeath = MySandboxGame.Static.UpdateTime + MyTimeSpan.FromSeconds(blendTimeSeconds); if (m_blendingPieces.Add(piece)) { 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; } } else { Debug.Assert(false, "Shouldnt get here"); } } }
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 CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List <HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren, string fallSound = "") { bool isStatic = false; if (canContainFixedChildren) { foreach (HkdShapeInstanceInfo info in shapeList) { info.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); Vector3D translation = worldMatrix.Translation + (worldMatrix.Up * 1.5); Quaternion rotation = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(info.Shape.GetShape(), ref translation, ref rotation, MyEnvironmentItems.m_tmpResults, 15); bool flag2 = false; using (List <HkBodyCollision> .Enumerator enumerator2 = MyEnvironmentItems.m_tmpResults.GetEnumerator()) { while (enumerator2.MoveNext()) { if (enumerator2.Current.GetCollisionEntity() is MyVoxelMap) { info.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); isStatic = true; flag2 = true; } else if (!flag2) { continue; } break; } } MyEnvironmentItems.m_tmpResults.Clear(); } } HkdBreakableShape shape = (HkdBreakableShape) new HkdCompoundBreakableShape(new HkdBreakableShape?(oldBreakableShape), shapeList); shape.RecalcMassPropsFromChildren(); MyFracturedPiece fp = MyDestructionHelper.CreateFracturePiece(shape, ref worldMatrix, isStatic, new MyDefinitionId?(itemDefinition.Id), true); if ((fp != null) && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref shape, fp, forceMultiplier); fp.Physics.ForceActivate(); if (fallSound.Length > 0) { fp.StartFallSound(fallSound); } } }
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)); }
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); }
int?GetPieceAgeLengthFromDefinition(MyFracturedPiece piece) { if (piece.OriginalBlocks == null || piece.OriginalBlocks.Count == 0) { return(null); } if (MyDefinitionManager.Static.DestructionDefinition == null || MyDefinitionManager.Static.DestructionDefinition.FracturedPieceDefinitions == null) { return(null); } MyDestructionDefinition.MyFracturedPieceDefinition fracDefDefault = null; MyDestructionDefinition.MyFracturedPieceDefinition fracDef = null; foreach (var fd in MyDefinitionManager.Static.DestructionDefinition.FracturedPieceDefinitions) { if (piece.OriginalBlocks[0].TypeId == fd.Id.TypeId) { if (fd.Id.SubtypeId == MyStringHash.NullOrEmpty) { fracDefDefault = fd; } else if (piece.OriginalBlocks[0].SubtypeId == fd.Id.SubtypeId) { fracDef = fd; } } } if (fracDef != null) { return(fracDef.Age); } else if (fracDefDefault != null) { return(fracDefDefault.Age); } return(null); }
public static MyFracturedPiece CreateFracturePiece(MyFracturedBlock fracturedBlock, bool sync) { MyPhysicalModelDefinition definition; MatrixD worldMatrix = fracturedBlock.CubeGrid.PositionComp.WorldMatrix; worldMatrix.Translation = fracturedBlock.CubeGrid.GridIntegerToWorld(fracturedBlock.Position); MyFracturedPiece piece = CreateFracturePiece(ref fracturedBlock.Shape, ref worldMatrix, false); piece.OriginalBlocks = fracturedBlock.OriginalBlocks; if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(piece.OriginalBlocks[0], out definition)) { piece.Physics.MaterialType = definition.PhysicalMaterial.Id.SubtypeId; } if (MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) { piece.DebugCheckValidShapes(); } if (MyExternalReplicable.FindByObject(piece) == null) { Sandbox.Game.Entities.MyEntities.RaiseEntityCreated(piece); } Sandbox.Game.Entities.MyEntities.Add(piece, true); return(piece); }
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 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 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 static unsafe void FixPosition(MyFracturedPiece fp) { HkdBreakableShape breakableShape = fp.Physics.BreakableBody.BreakableShape; if (breakableShape.GetChildrenCount() != 0) { breakableShape.GetChildren(m_tmpInfos); Vector3 translation = m_tmpInfos[0].GetTransform().Translation; if (translation.LengthSquared() < 1f) { m_tmpInfos.Clear(); } else { List <HkdConnection> resultList = new List <HkdConnection>(); HashSet <HkdBreakableShape> set = new HashSet <HkdBreakableShape>(); HashSet <HkdBreakableShape> set2 = new HashSet <HkdBreakableShape>(); set.Add(breakableShape); breakableShape.GetConnectionList(resultList); fp.PositionComp.SetPosition(Vector3D.Transform(translation, fp.PositionComp.WorldMatrix), null, false, true); foreach (HkdShapeInstanceInfo info2 in m_tmpInfos) { Matrix transform = info2.GetTransform(); Matrix *matrixPtr1 = (Matrix *)ref transform; matrixPtr1.Translation -= translation; info2.SetTransform(ref transform); m_tmpInfos2.Add(info2); HkdBreakableShape shape = info2.Shape; shape.GetConnectionList(resultList); while (true) { if (!shape.HasParent) { set2.Add(info2.Shape); break; } shape = shape.GetParent(); if (set.Add(shape)) { shape.GetConnectionList(resultList); } } } m_tmpInfos.Clear(); HkdBreakableShape parent = (HkdBreakableShape) new HkdCompoundBreakableShape(new HkdBreakableShape?(breakableShape), m_tmpInfos2); parent.RecalcMassPropsFromChildren(); ((HkdBreakableShape *)ref parent).SetChildrenParent(parent); foreach (HkdConnection connection in resultList) { HkBaseSystem.EnableAssert(0x1745920b, true); if (set2.Contains(connection.ShapeA) && set2.Contains(connection.ShapeB)) { HkdConnection connection2 = connection; parent.AddConnection(ref connection2); } } fp.Physics.BreakableBody.BreakableShape = parent; m_tmpInfos2.Clear(); parent.RecalcMassPropsFromChildren(); } } }