private bool CheckVolumeMassRec(HkdBreakableShape bShape, float minVolume, float minMass) { if (bShape.Name.Contains("Fake")) { return(true); } if (bShape.Volume <= minVolume) { return(false); } HkMassProperties mp = new HkMassProperties(); bShape.BuildMassProperties(ref mp); if (mp.Mass <= minMass) { return(false); } if (mp.InertiaTensor.M11 == 0 || mp.InertiaTensor.M22 == 0 || mp.InertiaTensor.M33 == 0) { return(false); } for (int i = 0; i < bShape.GetChildrenCount(); i++) { if (!CheckVolumeMassRec(bShape.GetChildShape(i), minVolume, minMass)) { return(false); } } return(true); }
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 static MyFracturedPiece CreateFracturePiece(ref HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic) { Debug.Assert(shape.IsValid()); ProfilerShort.Begin("CreateFracturePiece"); var fracturedPiece = MyFracturedPiecesManager.Static.GetPieceFromPool(0);//new MyFracturedPiece(); fracturedPiece.PositionComp.WorldMatrix = worldMatrix; fracturedPiece.Physics.Flags = isStatic ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS; var physicsBody = fracturedPiece.Physics as MyPhysicsBody;//new MyPhysicsBody(fracturedPiece,isFixed ?RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS); HkMassProperties mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); physicsBody.InitialSolverDeactivation = HkSolverDeactivation.High; physicsBody.CreateFromCollisionObject(shape.GetShape(), Vector3.Zero, worldMatrix, mp); physicsBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; physicsBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; System.Diagnostics.Debug.Assert(physicsBody.BreakableBody == null, "physicsBody.DestructionBody == null"); physicsBody.BreakableBody = new HkdBreakableBody(shape, physicsBody.RigidBody, world, worldMatrix); physicsBody.BreakableBody.AfterReplaceBody += physicsBody.FracturedBody_AfterReplaceBody; ProfilerShort.End(); ProfilerShort.Begin("Sync"); if (fracturedPiece.SyncFlag) { fracturedPiece.CreateSync(); } ProfilerShort.End(); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; //physicsBody.RigidBody.ContactPointCallbackDelay = 0; //physicsBody.RigidBody.ContactPointCallbackEnabled = true; fracturedPiece.Physics = physicsBody; //FixPosition(fracturedPiece); fracturedPiece.SetDataFromHavok(shape); ProfilerShort.Begin("AddToWorld"); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; shape.RemoveReference(); ProfilerShort.End(); return(fracturedPiece); }
public void AllocateForDefinition(string model, MyPhysicalModelDefinition definition, int count) { if (!string.IsNullOrEmpty(model)) { MyModel modelOnlyData = MyModels.GetModelOnlyData(model); if (modelOnlyData.HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, definition, modelOnlyData.BoundingBoxSize, true, false); } if ((modelOnlyData.HavokBreakableShapes != null) && (modelOnlyData.HavokBreakableShapes.Length != 0)) { ConcurrentQueue <HkdBreakableShape> queue; using (this.m_poolLock.AcquireExclusiveUsing()) { if (!this.m_pools.ContainsKey(definition.Id)) { this.m_pools[definition.Id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!this.m_pools[definition.Id].ContainsKey(model)) { this.m_pools[definition.Id][model] = new ConcurrentQueue <HkdBreakableShape>(); } queue = this.m_pools[definition.Id][model]; } for (int i = 0; i < count; i++) { HkdBreakableShape item = modelOnlyData.HavokBreakableShapes[0].Clone(); queue.Enqueue(item); if (i == 0) { HkMassProperties massProperties = new HkMassProperties(); item.BuildMassProperties(ref massProperties); if (!massProperties.InertiaTensor.IsValid()) { MyLog.Default.WriteLine($"Block with wrong destruction! (q.isOk): {definition.Model}"); return; } } } } } }
private static MyFracturedPiece CreateFracturePiece(ref HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic) { Debug.Assert(shape.IsValid()); ProfilerShort.Begin("CreateFracturePiece"); var fracturedPiece = MyFracturedPiecesManager.Static.GetPieceFromPool(0);//new MyFracturedPiece(); fracturedPiece.PositionComp.WorldMatrix = worldMatrix; fracturedPiece.Physics.Flags = isStatic ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS; var physicsBody = fracturedPiece.Physics as MyPhysicsBody;//new MyPhysicsBody(fracturedPiece,isFixed ?RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS); HkMassProperties mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); physicsBody.InitialSolverDeactivation = HkSolverDeactivation.High; physicsBody.CreateFromCollisionObject(shape.GetShape(), Vector3.Zero, worldMatrix, mp); physicsBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; physicsBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; System.Diagnostics.Debug.Assert(physicsBody.BreakableBody == null, "physicsBody.DestructionBody == null"); physicsBody.BreakableBody = new HkdBreakableBody(shape, physicsBody.RigidBody, world, worldMatrix); physicsBody.BreakableBody.AfterReplaceBody += physicsBody.FracturedBody_AfterReplaceBody; ProfilerShort.End(); ProfilerShort.Begin("Sync"); if (fracturedPiece.SyncFlag) { fracturedPiece.CreateSync(); } ProfilerShort.End(); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; //physicsBody.RigidBody.ContactPointCallbackDelay = 0; //physicsBody.RigidBody.ContactPointCallbackEnabled = true; fracturedPiece.Physics = physicsBody; //FixPosition(fracturedPiece); fracturedPiece.SetDataFromHavok(shape); ProfilerShort.Begin("AddToWorld"); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; shape.RemoveReference(); ProfilerShort.End(); return fracturedPiece; }
public override void Init(MyObjectBuilder_CubeBlock builder, MyCubeGrid cubeGrid) { base.Init(builder, cubeGrid); base.CheckConnectionAllowed = true; MyObjectBuilder_FracturedBlock block = builder as MyObjectBuilder_FracturedBlock; if (block.Shapes.Count == 0) { if (!block.CreatingFracturedBlock) { throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } } else { this.OriginalBlocks = new List <MyDefinitionId>(); this.Orientations = new List <MyBlockOrientation>(); List <HkdShapeInstanceInfo> list = new List <HkdShapeInstanceInfo>(); foreach (SerializableDefinitionId id in block.BlockDefinitions) { MyCubeBlockDefinition cubeBlockDefinition = MyDefinitionManager.Static.GetCubeBlockDefinition(id); string model = cubeBlockDefinition.Model; if (MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, cubeBlockDefinition, Vector3.One, true, false); } HkdBreakableShape shape = MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; Quaternion? rotation = null; Vector3? translation = null; HkdShapeInstanceInfo item = new HkdShapeInstanceInfo(shape, rotation, translation); list.Add(item); m_children.Add(item); shape.GetChildren(m_children); if (cubeBlockDefinition.BuildProgressModels != null) { MyCubeBlockDefinition.BuildProgressModel[] buildProgressModels = cubeBlockDefinition.BuildProgressModels; for (int j = 0; j < buildProgressModels.Length; j++) { model = buildProgressModels[j].File; if (MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, cubeBlockDefinition, Vector3.One, true, false); } shape = MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; rotation = null; translation = null; item = new HkdShapeInstanceInfo(shape, rotation, translation); list.Add(item); m_children.Add(item); shape.GetChildren(m_children); } } this.OriginalBlocks.Add(id); } foreach (SerializableBlockOrientation orientation in block.BlockOrientations) { this.Orientations.Add((MyBlockOrientation)orientation); } if (block.MultiBlocks.Count > 0) { this.MultiBlocks = new List <MultiBlockPartInfo>(); foreach (MyObjectBuilder_FracturedBlock.MyMultiBlockPart part in block.MultiBlocks) { if (part == null) { this.MultiBlocks.Add(null); continue; } MultiBlockPartInfo item = new MultiBlockPartInfo(); item.MultiBlockDefinition = part.MultiBlockDefinition; item.MultiBlockId = part.MultiBlockId; this.MultiBlocks.Add(item); } } this.m_shapes.AddRange(block.Shapes); for (int i = 0; i < m_children.Count; i++) { HkdShapeInstanceInfo child = m_children[i]; Func <MyObjectBuilder_FracturedBlock.ShapeB, bool> predicate = s => s.Name == child.ShapeName; IEnumerable <MyObjectBuilder_FracturedBlock.ShapeB> source = this.m_shapes.Where <MyObjectBuilder_FracturedBlock.ShapeB>(predicate); if (source.Count <MyObjectBuilder_FracturedBlock.ShapeB>() <= 0) { child.GetChildren(m_children); } else { MyObjectBuilder_FracturedBlock.ShapeB item = source.First <MyObjectBuilder_FracturedBlock.ShapeB>(); Matrix transform = Matrix.CreateFromQuaternion((Quaternion)item.Orientation); transform.Translation = child.GetTransform().Translation; HkdShapeInstanceInfo info2 = new HkdShapeInstanceInfo(child.Shape.Clone(), transform); if (item.Fixed) { info2.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); } list.Add(info2); m_shapeInfos.Add(info2); this.m_shapes.Remove(item); } } if (m_shapeInfos.Count == 0) { m_children.Clear(); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } foreach (HkdShapeInstanceInfo info3 in m_shapeInfos) { HkdBreakableShape shape = info3.Shape; if (!string.IsNullOrEmpty(shape.Name)) { this.Render.AddPiece(info3.Shape.Name, Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(info3.GetTransform().GetOrientation()))); } } if (base.CubeGrid.CreatePhysics) { HkdBreakableShape?oldParent = null; HkdBreakableShape shape3 = (HkdBreakableShape) new HkdCompoundBreakableShape(oldParent, m_shapeInfos); shape3.RecalcMassPropsFromChildren(); this.Shape = shape3; HkMassProperties massProperties = new HkMassProperties(); shape3.BuildMassProperties(ref massProperties); this.Shape = new HkdBreakableShape(shape3.GetShape(), ref massProperties); shape3.RemoveReference(); foreach (HkdShapeInstanceInfo info4 in m_shapeInfos) { this.Shape.AddShape(ref info4); } this.Shape.SetStrenght(MyDestructionConstants.STRENGTH); this.CreateMountPoints(); } m_children.Clear(); foreach (HkdShapeInstanceInfo info5 in m_shapeInfos) { info5.Shape.RemoveReference(); } foreach (HkdShapeInstanceInfo info6 in list) { info6.RemoveReference(); } m_shapeInfos.Clear(); } }
private bool CheckVolumeMassRec(HkdBreakableShape bShape, float minVolume, float minMass) { if (bShape.Name.Contains("Fake")) return true; if (bShape.Volume <= minVolume) return false; HkMassProperties mp = new HkMassProperties(); bShape.BuildMassProperties(ref mp); if (mp.Mass <= minMass) return false; if (mp.InertiaTensor.M11 == 0 || mp.InertiaTensor.M22 == 0 || mp.InertiaTensor.M33 == 0) return false; for (int i = 0; i < bShape.GetChildrenCount(); i++) { if (!CheckVolumeMassRec(bShape.GetChildShape(i), minVolume, minMass)) return false; } return true; }
public override void Init(MyObjectBuilder_EntityBase objectBuilder) { base.Init(objectBuilder); var ob = objectBuilder as MyObjectBuilder_FracturedPiece; if (ob.Shapes.Count == 0) { Debug.Fail("Invalid fracture piece! Dont call init without valid OB. Use pool/noinit."); throw new Exception("Fracture piece has no shapes."); //throwing exception, otherwise there is fp with null physics which can mess up somwhere else } foreach (var shape in ob.Shapes) { Render.AddPiece(shape.Name, Matrix.CreateFromQuaternion(shape.Orientation)); } OriginalBlocks.Clear(); foreach (var def in ob.BlockDefinitions) { string model = null; MyPhysicalModelDefinition mdef; if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(def, out mdef)) { model = mdef.Model; } MyCubeBlockDefinition blockDef = null; MyDefinitionManager.Static.TryGetDefinition <MyCubeBlockDefinition>(def, out blockDef); if (model == null) { Debug.Fail("Fracture piece Definition not found"); continue; } model = mdef.Model; if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, mdef, Vector3.One); } var shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); m_children.Add(si); shape.GetChildren(m_children); if (blockDef != null && blockDef.BuildProgressModels != null) { foreach (var progress in blockDef.BuildProgressModels) { model = progress.File; if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One); } shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; si = new HkdShapeInstanceInfo(shape, null, null); m_children.Add(si); shape.GetChildren(m_children); } } OriginalBlocks.Add(def); } m_shapes.AddRange(ob.Shapes); Vector3?offset = null; int shapeAtZero = 0; for (int i = 0; i < m_children.Count; i++) { var child = m_children[i]; Func <MyObjectBuilder_FracturedPiece.Shape, bool> x = s => s.Name == child.ShapeName; var result = m_shapes.Where(x); if (result.Count() > 0) { var found = result.First(); var m = Matrix.CreateFromQuaternion(found.Orientation); if (!offset.HasValue && found.Name == m_shapes[0].Name) { offset = child.GetTransform().Translation; shapeAtZero = m_shapeInfos.Count; } m.Translation = child.GetTransform().Translation; var si = new HkdShapeInstanceInfo(child.Shape.Clone(), m); if (found.Fixed) { si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); } m_shapeInfos.Add(si); m_shapes.Remove(found); } else { child.GetChildren(m_children); } } if (m_shapeInfos.Count == 0) { List <string> shapesToLoad = new List <string>(); foreach (var obShape in ob.Shapes) { shapesToLoad.Add(obShape.Name); } var shapesStr = shapesToLoad.Aggregate((str1, str2) => str1 + ", " + str2); var blocksStr = OriginalBlocks.Aggregate("", (str, defId) => str + ", " + defId.ToString()); var failMsg = "No relevant shape was found for fractured piece. It was probably reexported and names changed. Shapes: " + shapesStr + ". Original blocks: " + shapesStr; Debug.Fail(failMsg); //HkdShapeInstanceInfo si = new HkdShapeInstanceInfo(new HkdBreakableShape((HkShape)new HkBoxShape(Vector3.One)), Matrix.Identity); //m_shapeInfos.Add(si); throw new Exception(failMsg); } if (offset.HasValue) { for (int i = 0; i < m_shapeInfos.Count; i++) { var m = m_shapeInfos[i].GetTransform(); m.Translation -= offset.Value; m_shapeInfos[i].SetTransform(ref m); } { var m = m_shapeInfos[shapeAtZero].GetTransform(); m.Translation = Vector3.Zero; m_shapeInfos[shapeAtZero].SetTransform(ref m); } } if (m_shapeInfos.Count > 0) { if (m_shapeInfos.Count == 1) { Shape = m_shapeInfos[0].Shape; } else { Shape = new HkdCompoundBreakableShape(null, m_shapeInfos); ((HkdCompoundBreakableShape)Shape).RecalcMassPropsFromChildren(); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); var mp = new HkMassProperties(); Shape.BuildMassProperties(ref mp); Shape.SetChildrenParent(Shape); Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); Physics.CanUpdateAccelerations = true; Physics.InitialSolverDeactivation = HkSolverDeactivation.High; Physics.CreateFromCollisionObject(Shape.GetShape(), Vector3.Zero, PositionComp.WorldMatrix, mp); Physics.BreakableBody = new HkdBreakableBody(Shape, Physics.RigidBody, MyPhysics.SingleWorld.DestructionWorld, (Matrix)PositionComp.WorldMatrix); Physics.BreakableBody.AfterReplaceBody += Physics.FracturedBody_AfterReplaceBody; if (OriginalBlocks.Count > 0) { MyPhysicalModelDefinition def; if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(OriginalBlocks[0], out def)) { Physics.MaterialType = def.PhysicalMaterial.Id.SubtypeId; } } var rigidBody = Physics.RigidBody; bool isFixed = MyDestructionHelper.IsFixed(Physics.BreakableBody.BreakableShape); if (isFixed) { rigidBody.UpdateMotionType(HkMotionType.Fixed); rigidBody.LinearVelocity = Vector3.Zero; rigidBody.AngularVelocity = Vector3.Zero; } Physics.Enabled = true; } m_children.Clear(); m_shapeInfos.Clear(); }