public static void CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List <HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren, string fallSound = "") { bool containsFixedChildren = false; if (canContainFixedChildren) { foreach (var shapeInst in shapeList) { shapeInst.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); var t = worldMatrix.Translation + worldMatrix.Up * 1.5f; var o = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(shapeInst.Shape.GetShape(), ref t, ref o, m_tmpResults, MyPhysics.CollisionLayers.DefaultCollisionLayer); bool flagSet = false; foreach (var res in m_tmpResults) { var entity = res.GetCollisionEntity(); if (entity is MyVoxelMap) { shapeInst.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); containsFixedChildren = true; flagSet = true; break; } if (flagSet) { break; } } m_tmpResults.Clear(); } } HkdBreakableShape compound = new HkdCompoundBreakableShape(oldBreakableShape, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); //compound.SetMassRecursively(500); //compound.SetStrenghtRecursively(5000, 0.7f); var fp = MyDestructionHelper.CreateFracturePiece(compound, MyPhysics.SingleWorld.DestructionWorld, ref worldMatrix, containsFixedChildren, itemDefinition.Id, true); if (fp != null && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref compound, fp, forceMultiplier); fp.Physics.ForceActivate(); if (fallSound.Length > 0) { fp.StartFallSound(fallSound); } } }
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 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(); }
/// <summary> /// Searches for blocks which will create fracture components from cached m_fracturedSlimBlocksShapes /// </summary> private void FindFractureComponentBlocks() { Debug.Assert(MyFakes.ENABLE_FRACTURE_COMPONENT); foreach (var pair in m_fracturedSlimBlocksShapes) { var slimBlock = pair.Key; var shapeList = pair.Value; if (slimBlock.FatBlock.Components.Has<MyFractureComponentBase>()) { // Block has fracture component - ignore continue; } else { int totalBreakableShapesCountForModel = slimBlock.GetTotalBreakableShapeChildrenCount(); Debug.Assert(shapeList.Count <= totalBreakableShapesCountForModel); // No removed pieces? Then ignore. if (slimBlock.BlockDefinition.CreateFracturedPieces && totalBreakableShapesCountForModel == shapeList.Count) continue; foreach (var s in shapeList) { s.SetTransform(ref Matrix.Identity); } ProfilerShort.Begin("CreateShapeComponent"); HkdBreakableShape compound = new HkdCompoundBreakableShape(null, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); HkdBreakableShape shape = compound; var sh = compound.GetShape(); shape = new HkdBreakableShape(sh, ref mp); //shape.SetMassProperties(mp); //important! pass mp to constructor foreach (var si in shapeList) { var siRef = si; shape.AddShape(ref siRef); } compound.RemoveReference(); ProfilerShort.BeginNextBlock("Connect"); //shape.SetChildrenParent(shape); ConnectPiecesInBlock(shape, shapeList); MyFractureComponentBase.Info info = new MyFractureComponentBase.Info() { Entity = slimBlock.FatBlock, Shape = shape, Compound = true }; m_fractureBlockComponentsCache.Add(info); ProfilerShort.End(); } } m_fracturedSlimBlocksShapes.Clear(); }
public static void CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List<HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren) { bool containsFixedChildren = false; if (canContainFixedChildren) { foreach (var shapeInst in shapeList) { shapeInst.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); var t = worldMatrix.Translation + worldMatrix.Up * 1.5f; var o = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(shapeInst.Shape.GetShape(), ref t, ref o, m_tmpResults, MyPhysics.DefaultCollisionLayer); bool flagSet = false; foreach (var res in m_tmpResults) { var entity = res.GetCollisionEntity(); if (entity is MyVoxelMap) { shapeInst.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); containsFixedChildren = true; flagSet = true; break; } if (flagSet) break; } m_tmpResults.Clear(); } } HkdBreakableShape compound = new HkdCompoundBreakableShape(oldBreakableShape, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); //compound.SetMassRecursively(500); //compound.SetStrenghtRecursively(5000, 0.7f); var fp = MyDestructionHelper.CreateFracturePiece(compound, MyPhysics.SingleWorld.DestructionWorld, ref worldMatrix, containsFixedChildren, itemDefinition.Id, true); if (fp != null && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref compound, fp, forceMultiplier); fp.Physics.ForceActivate(); } }
public override void Init(MyObjectBuilder_CubeBlock builder, MyCubeGrid cubeGrid) { base.Init(builder, cubeGrid); ProfilerShort.Begin("FP.Init"); CheckConnectionAllowed = true; var ob = builder as MyObjectBuilder_FracturedBlock; if (ob.Shapes.Count == 0) { ProfilerShort.End(); return; } OriginalBlocks = new List<MyDefinitionId>(); Orientations = new List<MyBlockOrientation>(); var lst = new List<HkdShapeInstanceInfo>(); foreach (var def in ob.BlockDefinitions) { var blockDef = MyDefinitionManager.Static.GetCubeBlockDefinition(def); if (MyModels.GetModelOnlyData(blockDef.Model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(blockDef, false, Vector3.One); } var shape = MyModels.GetModelOnlyData(blockDef.Model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); lst.Add(si); m_children.Add(si); shape.GetChildren(m_children); OriginalBlocks.Add(def); } foreach (var or in ob.BlockOrientations) { Orientations.Add(or); } m_shapes.AddRange(ob.Shapes); for (int i = 0; i < m_children.Count; i++) { var child = m_children[i]; Func<MyObjectBuilder_FracturedBlock.ShapeB, 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); m.Translation = child.GetTransform().Translation; var si = new HkdShapeInstanceInfo(child.Shape.Clone(), m); if(found.Fixed) si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); lst.Add(si); m_shapeInfos.Add(si); m_shapes.Remove(found); } else { child.GetChildren(m_children); } } if (m_shapeInfos.Count == 0) { m_children.Clear(); ProfilerShort.End(); Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed."); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } foreach (var shape in m_shapeInfos) { if(! string.IsNullOrEmpty(shape.Shape.Name)) Render.AddPiece(shape.Shape.Name, Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(shape.GetTransform().GetOrientation()))); } if (CubeGrid.CreatePhysics) { HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_shapeInfos); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); Shape = compound; var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); Shape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_shapeInfos) { var siRef = si; Shape.AddShape(ref siRef); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); CreateMountPoints(); } m_children.Clear(); foreach (var si in m_shapeInfos) si.Shape.RemoveReference(); foreach (var si in lst) si.RemoveReference(); m_shapeInfos.Clear(); ProfilerShort.End(); }
private void FindFracturedBlocks(HkdBreakableBodyInfo b) { ProfilerShort.Begin("DBHelper"); var dbHelper = new HkdBreakableBodyHelper(b); ProfilerShort.BeginNextBlock("GetRBMatrix"); var bodyMatrix = dbHelper.GetRigidBodyMatrix(); ProfilerShort.BeginNextBlock("SearchChildren"); dbHelper.GetChildren(m_children); foreach (var child in m_children) { if (!child.IsFracturePiece()) continue; //var blockPosWorld = ClusterToWorld(Vector3.Transform(child.GetTransform().Translation, bodyMatrix)); var bShape = child.Shape; HkVec3IProperty pProp = bShape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); var blockPos = pProp.Value; //Vector3I.Round(child.GetTransform().Translation / m_grid.GridSize); if (!m_grid.CubeExists(blockPos)) { //Debug.Fail("FindFracturedBlocks:Fracture piece missing block");//safe to ignore continue; } if (MyFakes.ENABLE_FRACTURE_COMPONENT) { var block = m_grid.GetCubeBlock(blockPos); if (block == null) continue; if (!FindFractureComponentBlocks(block, child)) continue; } else { if (!m_fracturedBlocksShapes.ContainsKey(blockPos)) m_fracturedBlocksShapes[blockPos] = new List<HkdShapeInstanceInfo>(); m_fracturedBlocksShapes[blockPos].Add(child); } } ProfilerShort.BeginNextBlock("CreateFreacturedBlocks"); if (!MyFakes.ENABLE_FRACTURE_COMPONENT) { foreach (var key in m_fracturedBlocksShapes.Keys) { HkdBreakableShape shape; var shapeList = m_fracturedBlocksShapes[key]; foreach (var s in shapeList) { var matrix = s.GetTransform(); matrix.Translation = Vector3.Zero; s.SetTransform(ref matrix); } ProfilerShort.Begin("CreateShape"); HkdBreakableShape compound = new HkdCompoundBreakableShape(null, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); shape = compound; var sh = compound.GetShape(); shape = new HkdBreakableShape(sh, ref mp); //shape.SetMassProperties(mp); //important! pass mp to constructor foreach (var si in shapeList) { var siRef = si; shape.AddShape(ref siRef); } compound.RemoveReference(); ProfilerShort.BeginNextBlock("Connect"); //shape.SetChildrenParent(shape); ConnectPiecesInBlock(shape, shapeList); ProfilerShort.End(); var info = new MyFracturedBlock.Info() { Shape = shape, Position = key, Compound = true, }; var originalBlock = m_grid.GetCubeBlock(key); if (originalBlock == null) { //Debug.Fail("Missing fracture piece original block.");//safe to ignore shape.RemoveReference(); continue; } Debug.Assert(originalBlock != null); if (originalBlock.FatBlock is MyFracturedBlock) { var fractured = originalBlock.FatBlock as MyFracturedBlock; info.OriginalBlocks = fractured.OriginalBlocks; info.Orientations = fractured.Orientations; info.MultiBlocks = fractured.MultiBlocks; } else if (originalBlock.FatBlock is MyCompoundCubeBlock) { info.OriginalBlocks = new List<MyDefinitionId>(); info.Orientations = new List<MyBlockOrientation>(); MyCompoundCubeBlock compoundBlock = originalBlock.FatBlock as MyCompoundCubeBlock; bool hasMultiBlockPart = false; var blocksInCompound = compoundBlock.GetBlocks(); foreach (var block in blocksInCompound) { info.OriginalBlocks.Add(block.BlockDefinition.Id); info.Orientations.Add(block.Orientation); hasMultiBlockPart = hasMultiBlockPart || block.IsMultiBlockPart; } if (hasMultiBlockPart) { info.MultiBlocks = new List<MyFracturedBlock.MultiBlockPartInfo>(); foreach (var block in blocksInCompound) { if (block.IsMultiBlockPart) info.MultiBlocks.Add(new MyFracturedBlock.MultiBlockPartInfo() { MultiBlockDefinition = block.MultiBlockDefinition.Id, MultiBlockId = block.MultiBlockId }); else info.MultiBlocks.Add(null); } } } else { info.OriginalBlocks = new List<MyDefinitionId>(); info.Orientations = new List<MyBlockOrientation>(); info.OriginalBlocks.Add(originalBlock.BlockDefinition.Id); info.Orientations.Add(originalBlock.Orientation); if (originalBlock.IsMultiBlockPart) { info.MultiBlocks = new List<MyFracturedBlock.MultiBlockPartInfo>(); info.MultiBlocks.Add(new MyFracturedBlock.MultiBlockPartInfo() { MultiBlockDefinition = originalBlock.MultiBlockDefinition.Id, MultiBlockId = originalBlock.MultiBlockId }); } } m_fractureBlocksCache.Add(info); } } m_fracturedBlocksShapes.Clear(); m_children.Clear(); ProfilerShort.End(); }
private HkdBreakableShape? CreateBlockShape(Sandbox.Game.Entities.Cube.MySlimBlock b, out Matrix blockTransform) { ProfilerShort.Begin("CreateBlockShape"); blockTransform = Matrix.Identity; if (b.FatBlock == null) { Debug.Fail("Armor blocks are not allowed in medieval"); ProfilerShort.End(); return null; } HkdBreakableShape breakableShape; Matrix compoundChildTransform = Matrix.Identity; if (b.FatBlock is MyCompoundCubeBlock) { ProfilerShort.Begin("Cmpnd"); blockTransform.Translation = b.FatBlock.PositionComp.LocalMatrix.Translation; var cb = b.FatBlock as MyCompoundCubeBlock; if (cb.GetBlocksCount() == 1) { ProfilerShort.Begin("SingleBlock"); var block = cb.GetBlocks()[0]; var defId = block.FatBlock.BlockDefinition; Matrix m; var model = block.CalculateCurrentModel(out m); if (MyFakes.LAZY_LOAD_DESTRUCTION || HasBreakableShape(model, defId)) { ProfilerShort.Begin("Clone"); breakableShape = GetBreakableShape(model, defId); ProfilerShort.End(); } block.Orientation.GetMatrix(out compoundChildTransform); blockTransform = compoundChildTransform * blockTransform; ProfilerShort.End(); } else { var pos = b.Position * m_grid.GridSize; float mass = 0; ProfilerShort.Begin("GetBlocks"); foreach (var block in cb.GetBlocks()) { block.Orientation.GetMatrix(out compoundChildTransform); compoundChildTransform.Translation = Vector3.Zero; var blockDef = block.BlockDefinition; Matrix m; var model = block.CalculateCurrentModel(out m); if (MyFakes.LAZY_LOAD_DESTRUCTION || HasBreakableShape(model, blockDef)) { ProfilerShort.Begin("Clone"); breakableShape = GetBreakableShape(model, blockDef); breakableShape.UserObject |= (uint)HkdBreakableShape.Flags.FRACTURE_PIECE; System.Diagnostics.Debug.Assert(breakableShape.IsValid(), "Invalid breakableShape"); ProfilerShort.End(); mass += blockDef.Mass; m_shapeInfosList2.Add(new HkdShapeInstanceInfo(breakableShape, compoundChildTransform)); } } if (m_shapeInfosList2.Count == 0) { ProfilerShort.End(); return null; } ProfilerShort.BeginNextBlock("CreateCompoundBlockShape"); //HkShape hkpShape = new HkListShape(m_khpShapeList.ToArray(), m_khpShapeList.Count, HkReferencePolicy.None); //m_khpShapeList.Clear(); HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_shapeInfosList2); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); breakableShape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_shapeInfosList2) { var siRef = si; breakableShape.AddShape(ref siRef); } ProfilerShort.BeginNextBlock("Connect"); //slow slow slow //breakableShape.AutoConnect(MyDestructionData.Static.TemporaryWorld); //slow wrong //breakableShape.ConnectSemiAccurate(MyDestructionData.Static.TemporaryWorld); //fast frong for (int i = 0; i < m_shapeInfosList2.Count; i++) { for (int j = 0; j < m_shapeInfosList2.Count; j++) { if (i != j) { ConnectShapesWithChildren(breakableShape, m_shapeInfosList2[i].Shape, m_shapeInfosList2[j].Shape); } } } ProfilerShort.BeginNextBlock("Cleanup"); foreach (var si in m_shapeInfosList2) { si.Shape.RemoveReference(); si.RemoveReference(); } m_shapeInfosList2.Clear(); ProfilerShort.End(); } ProfilerShort.End(); } else { ProfilerShort.Begin("SingleBlock"); b.Orientation.GetMatrix(out blockTransform); blockTransform.Translation = b.FatBlock.PositionComp.LocalMatrix.Translation; Matrix m; var model = b.CalculateCurrentModel(out m); if (b.FatBlock is MyFracturedBlock) { ProfilerShort.Begin("CloneFracture"); breakableShape = (b.FatBlock as MyFracturedBlock).Shape; if(!breakableShape.IsValid()) { Debug.Fail("Fractured block Breakable shape invalid!"); throw new Exception("Fractured block Breakable shape invalid!"); } breakableShape.AddReference(); ProfilerShort.End(); } else if (MyFakes.LAZY_LOAD_DESTRUCTION || HasBreakableShape(model, b.BlockDefinition)) { ProfilerShort.Begin("Clone"); breakableShape = GetBreakableShape(model, b.BlockDefinition); ProfilerShort.End(); } ProfilerShort.End(); } ProfilerShort.Begin("Property"); HkPropertyBase posProp = new HkVec3IProperty(b.Position); Debug.Assert(breakableShape.IsValid()); breakableShape.SetPropertyRecursively(HkdBreakableShape.PROPERTY_GRID_POSITION, posProp); posProp.RemoveReference(); ProfilerShort.End(); //breakableShape.DisableRefCountRecursively(); ProfilerShort.End(); return breakableShape; }
protected override void RecreateShape(List<MyObjectBuilder_FractureComponentBase.FracturedShape> shapeList) { Debug.Assert(m_tmpChildren.Count == 0); Debug.Assert(m_tmpShapeInfos.Count == 0); ProfilerShort.Begin("FractureComponent.RecreateShape"); if (Shape.IsValid()) { Shape.RemoveReference(); Shape = new HkdBreakableShape(); } var render = Block.FatBlock.Render as MyRenderComponentFracturedPiece; if (render != null) { render.ClearModels(); render.UpdateRenderObject(false); } else { Debug.Fail("Invalid render type"); } if (shapeList.Count == 0) { ProfilerShort.End(); return; } var removeRefsList = new List<HkdShapeInstanceInfo>(); { var blockDef = Block.BlockDefinition; var model = blockDef.Model; if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One); var shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); removeRefsList.Add(si); m_tmpChildren.Add(si); shape.GetChildren(m_tmpChildren); if (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); removeRefsList.Add(si); m_tmpChildren.Add(si); shape.GetChildren(m_tmpChildren); } } } Debug.Assert(m_tmpShapeListInit.Count == 0); m_tmpShapeListInit.Clear(); m_tmpShapeListInit.AddList(shapeList); for (int i = 0; i < m_tmpChildren.Count; i++) { var child = m_tmpChildren[i]; var result = m_tmpShapeListInit.Where(s => s.Name == child.ShapeName); if (result.Count() > 0) { var found = result.First(); var si = new HkdShapeInstanceInfo(child.Shape.Clone(), Matrix.Identity); if (found.Fixed) si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); removeRefsList.Add(si); m_tmpShapeInfos.Add(si); m_tmpShapeListInit.Remove(found); } else { child.GetChildren(m_tmpChildren); } } m_tmpShapeListInit.Clear(); if (shapeList.Count > 0 && m_tmpShapeInfos.Count == 0) { ProfilerShort.End(); m_tmpChildren.Clear(); Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed. Block definition: " + Block.BlockDefinition.Id.ToString()); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed. Block definition: " + Block.BlockDefinition.Id.ToString()); } if (render != null) { foreach (var shape in m_tmpShapeInfos) { if (!string.IsNullOrEmpty(shape.Shape.Name)) render.AddPiece(shape.Shape.Name, Matrix.Identity); } render.UpdateRenderObject(true); } m_tmpChildren.Clear(); if (Block.CubeGrid.CreatePhysics) { HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_tmpShapeInfos); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); Shape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_tmpShapeInfos) { var siRef = si; Shape.AddShape(ref siRef); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); CreateMountPoints(); // Update neighbours for parent block var blockOnPosition = Block.CubeGrid.GetCubeBlock(Block.Position); if (blockOnPosition != null) blockOnPosition.CubeGrid.UpdateBlockNeighbours(blockOnPosition); if (Block.CubeGrid.Physics != null) Block.CubeGrid.Physics.AddDirtyBlock(Block); } foreach (var si in m_tmpShapeInfos) si.Shape.RemoveReference(); m_tmpShapeInfos.Clear(); foreach (var si in removeRefsList) si.RemoveReference(); ProfilerShort.End(); }
private List<HkdConnection> m_connectionsToAddCache = new List<HkdConnection>(); //connections are created before they can be added so we cache them public HkdBreakableShape? CreateBreakableShape() { ProfilerShort.Begin("CreateBreakableShape"); ProfilerShort.Begin("CollectShapes"); m_blocksShapes.Clear(); foreach (var b in m_grid.GetBlocks()) { Matrix m; var bs = CreateBlockShape(b, out m); if (bs.HasValue) { var shapeInstance = new HkdShapeInstanceInfo(bs.Value, m); m_shapeInfosList.Add(shapeInstance); m_blocksShapes[b.Position] = shapeInstance; } } ProfilerShort.End(); if (m_blocksShapes.Count == 0) { Debug.Fail("No breakable shapes in grid!"); ProfilerShort.End(); return null; } ProfilerShort.Begin("Create"); if (BreakableShape.IsValid()) BreakableShape.RemoveReference(); BreakableShape = new HkdCompoundBreakableShape(null, m_shapeInfosList); BreakableShape.SetChildrenParent(BreakableShape); try { BreakableShape.SetStrenghtRecursively(Sandbox.MyDestructionConstants.STRENGTH, 0.7f); } catch (Exception e) { MyLog.Default.WriteLine(e); MyLog.Default.WriteLine("BS Valid: " + BreakableShape.IsValid()); MyLog.Default.WriteLine("BS Child count: " + BreakableShape.GetChildrenCount()); MyLog.Default.WriteLine("Grid shapes: " + m_shapeInfosList.Count); foreach (var child in m_shapeInfosList) { if (!child.Shape.IsValid()) MyLog.Default.WriteLine("Invalid child!"); else MyLog.Default.WriteLine("Child strength: " + child.Shape.GetStrenght()); } throw new InvalidOperationException(); } ProfilerShort.End(); ProfilerShort.Begin("Connect"); CreateConnectionsManually(BreakableShape); ProfilerShort.End(); FindConnectionsToWorld(m_grid.GetBlocks()); m_shapeInfosList.Clear(); ProfilerShort.End(); return BreakableShape; }
public void UpdateDirtyBlocks(HashSet<Vector3I> dirtyCubes, bool recreateShape = true) { ProfilerShort.Begin("Update physics"); if (dirtyCubes.Count > 0) { if (MyPerGameSettings.Destruction && BreakableShape.IsValid()) { ProfilerShort.Begin("UpdateShapeList"); int newShapes = 0; HashSet<MySlimBlock> newBlocks = new HashSet<MySlimBlock>(); ProfilerShort.Begin("Dirty"); foreach (var dirty in dirtyCubes) { UpdateConnections(dirty); BlocksConnectedToWorld.Remove(dirty); if (m_blocksShapes.ContainsKey(dirty)) { var toRemove = m_blocksShapes[dirty]; toRemove.Shape.RemoveReference(); toRemove.RemoveReference(); m_blocksShapes.Remove(dirty); } var b = m_grid.GetCubeBlock(dirty); if (b == null || newBlocks.Contains(b)) continue; newBlocks.Add(b); newShapes++; } ProfilerShort.BeginNextBlock("NewBlocks"); foreach (var b in newBlocks) { Matrix m; var breakableShape = CreateBlockShape(b, out m); if (breakableShape.HasValue) { Debug.Assert(!m_blocksShapes.ContainsKey(b.Position), "Shape for this block already exists!"); m_blocksShapes[b.Position] = new HkdShapeInstanceInfo(breakableShape.Value, m); } } foreach (var shapeInstance in m_blocksShapes.Values) m_shapeInfosList.Add(shapeInstance); ProfilerShort.BeginNextBlock("ConnectionsToWorld"); if (newBlocks.Count > 0) FindConnectionsToWorld(newBlocks); ProfilerShort.End(); ProfilerShort.End(); if (recreateShape) { ProfilerShort.Begin("CreateNewCompound"); BreakableShape.RemoveReference(); BreakableShape = new HkdCompoundBreakableShape(null, m_shapeInfosList); BreakableShape.SetChildrenParent(BreakableShape); BreakableShape.BuildMassProperties(ref m_massProperties); //(BreakableShape as HkdCompoundBreakableShape).RecalcMassPropsFromChildren(); BreakableShape.SetStrenghtRecursively(Sandbox.MyDestructionConstants.STRENGTH, 0.7f); ProfilerShort.End(); } ProfilerShort.Begin("CreateConnections"); //CreateConnectionsManually(BreakableShape); UpdateConnectionsManually(BreakableShape, m_updateConnections); m_updateConnections.Clear(); AddConnections(); Debug.Assert(m_connectionsToAddCache.Count == 0); ProfilerShort.End(); m_shapeInfosList.Clear(); } else { try { ProfilerShort.Begin("Expand to blocks"); foreach (var cubePos in dirtyCubes) { if (m_tmpRemovedCubes.Add(cubePos)) { ExpandBlock(cubePos, m_grid, m_tmpRemovedBlocks, m_tmpRemovedCubes); } } ProfilerShort.End(); ProfilerShort.Begin("Remove first"); Vector3I current; m_removalMins.Clear(); m_removalMaxes.Clear(); m_removalResults.Clear(); m_root.RemoveShapes(m_tmpRemovedCubes, m_removalMins, m_removalMaxes, m_removalResults); for (int i = 0; i < m_removalMins.Count; ++i) { if (m_removalResults[i]) { for (current.X = m_removalMins[i].X; current.X <= m_removalMaxes[i].X; ++current.X) for (current.Y = m_removalMins[i].Y; current.Y <= m_removalMaxes[i].Y; ++current.Y) for (current.Z = m_removalMins[i].Z; current.Z <= m_removalMaxes[i].Z; ++current.Z) { if (m_tmpRemovedCubes.Add(current)) // If it's new position, not already in dirty { // This has to be expanded to whole blocks and processed again ExpandBlock(current, m_grid, m_tmpRemovedBlocks, m_tmpRemovedCubes, m_tmpAdditionalCubes); } } } } ProfilerShort.End(); ProfilerShort.Begin("Remove additional"); while (m_tmpAdditionalCubes.Count > 0) { m_removalMins.Clear(); m_removalMaxes.Clear(); m_removalResults.Clear(); m_root.RemoveShapes(m_tmpAdditionalCubes, m_removalMins, m_removalMaxes, m_removalResults); m_tmpAdditionalCubes.Clear(); for (int i = 0; i < m_removalMins.Count; ++i) { if (m_removalResults[i]) { for (current.X = m_removalMins[i].X; current.X <= m_removalMaxes[i].X; ++current.X) for (current.Y = m_removalMins[i].Y; current.Y <= m_removalMaxes[i].Y; ++current.Y) for (current.Z = m_removalMins[i].Z; current.Z <= m_removalMaxes[i].Z; ++current.Z) { if (m_tmpRemovedCubes.Add(current)) // If it's new position, not already in dirty { // This has to be expanded to whole blocks and processed again ExpandBlock(current, m_grid, m_tmpRemovedBlocks, m_tmpRemovedCubes, m_tmpAdditionalCubes); } } } } } ProfilerShort.End(); ProfilerShort.Begin("Recollect"); m_blockCollector.CollectArea(m_grid, m_tmpRemovedCubes, m_segmenter, MyVoxelSegmentationType.Simple, m_massElements); ProfilerShort.End(); ProfilerShort.Begin("Debug-CheckPositions"); CheckShapePositions(m_blockCollector.ShapeInfos); ProfilerShort.End(); ProfilerShort.Begin("Add"); AddShapesFromCollector(); ProfilerShort.End(); } finally { m_blockCollector.Clear(); m_tmpRemovedBlocks.Clear(); m_tmpRemovedCubes.Clear(); m_tmpAdditionalCubes.Clear(); } } } ProfilerShort.End(); }
public override void Init(MyObjectBuilder_CubeBlock builder, MyCubeGrid cubeGrid) { base.Init(builder, cubeGrid); ProfilerShort.Begin("FP.Init"); CheckConnectionAllowed = true; var ob = builder as MyObjectBuilder_FracturedBlock; if (ob.Shapes.Count == 0) { ProfilerShort.End(); if (ob.CreatingFracturedBlock) { return; } Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed."); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } OriginalBlocks = new List <MyDefinitionId>(); Orientations = new List <MyBlockOrientation>(); var lst = new List <HkdShapeInstanceInfo>(); foreach (var def in ob.BlockDefinitions) { var blockDef = MyDefinitionManager.Static.GetCubeBlockDefinition(def); var model = blockDef.Model; if (MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One); } var shape = MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); lst.Add(si); m_children.Add(si); shape.GetChildren(m_children); if (blockDef.BuildProgressModels != null) { foreach (var progress in blockDef.BuildProgressModels) { model = progress.File; if (MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One); } shape = MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; si = new HkdShapeInstanceInfo(shape, null, null); lst.Add(si); m_children.Add(si); shape.GetChildren(m_children); } } OriginalBlocks.Add(def); } foreach (var or in ob.BlockOrientations) { Orientations.Add(or); } if (ob.MultiBlocks.Count > 0) { MultiBlocks = new List <MultiBlockPartInfo>(); foreach (var mbpart in ob.MultiBlocks) { if (mbpart != null) { MultiBlocks.Add(new MultiBlockPartInfo() { MultiBlockDefinition = mbpart.MultiBlockDefinition, MultiBlockId = mbpart.MultiBlockId }); } else { MultiBlocks.Add(null); } } } m_shapes.AddRange(ob.Shapes); for (int i = 0; i < m_children.Count; i++) { var child = m_children[i]; Func <MyObjectBuilder_FracturedBlock.ShapeB, 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); m.Translation = child.GetTransform().Translation; var si = new HkdShapeInstanceInfo(child.Shape.Clone(), m); if (found.Fixed) { si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); } lst.Add(si); m_shapeInfos.Add(si); m_shapes.Remove(found); } else { child.GetChildren(m_children); } } if (m_shapeInfos.Count == 0) { m_children.Clear(); ProfilerShort.End(); Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed."); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } foreach (var shape in m_shapeInfos) { if (!string.IsNullOrEmpty(shape.Shape.Name)) { Render.AddPiece(shape.Shape.Name, Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(shape.GetTransform().GetOrientation()))); } } if (CubeGrid.CreatePhysics) { HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_shapeInfos); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); Shape = compound; var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); Shape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_shapeInfos) { var siRef = si; Shape.AddShape(ref siRef); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); CreateMountPoints(); } m_children.Clear(); foreach (var si in m_shapeInfos) { si.Shape.RemoveReference(); } foreach (var si in lst) { si.RemoveReference(); } m_shapeInfos.Clear(); ProfilerShort.End(); }
protected override void RecreateShape(List <MyObjectBuilder_FractureComponentBase.FracturedShape> shapeList) { Debug.Assert(m_tmpChildren.Count == 0); Debug.Assert(m_tmpShapeInfos.Count == 0); ProfilerShort.Begin("FractureComponent.RecreateShape"); if (Shape.IsValid()) { Shape.RemoveReference(); Shape = new HkdBreakableShape(); } var render = Block.FatBlock.Render as MyRenderComponentFracturedPiece; if (render != null) { render.ClearModels(); render.UpdateRenderObject(false); } else { Debug.Fail("Invalid render type"); } if (shapeList.Count == 0) { ProfilerShort.End(); return; } var removeRefsList = new List <HkdShapeInstanceInfo>(); { var blockDef = Block.BlockDefinition; var model = blockDef.Model; if (VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, blockDef, Vector3.One); } var shape = VRage.Game.Models.MyModels.GetModelOnlyData(model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); removeRefsList.Add(si); m_tmpChildren.Add(si); shape.GetChildren(m_tmpChildren); if (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); removeRefsList.Add(si); m_tmpChildren.Add(si); shape.GetChildren(m_tmpChildren); } } } Debug.Assert(m_tmpShapeListInit.Count == 0); m_tmpShapeListInit.Clear(); m_tmpShapeListInit.AddList(shapeList); for (int i = 0; i < m_tmpChildren.Count; i++) { var child = m_tmpChildren[i]; var result = m_tmpShapeListInit.Where(s => s.Name == child.ShapeName); if (result.Count() > 0) { var found = result.First(); var si = new HkdShapeInstanceInfo(child.Shape.Clone(), Matrix.Identity); if (found.Fixed) { si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); } removeRefsList.Add(si); m_tmpShapeInfos.Add(si); m_tmpShapeListInit.Remove(found); } else { child.GetChildren(m_tmpChildren); } } m_tmpShapeListInit.Clear(); if (shapeList.Count > 0 && m_tmpShapeInfos.Count == 0) { ProfilerShort.End(); m_tmpChildren.Clear(); Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed. Block definition: " + Block.BlockDefinition.Id.ToString()); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed. Block definition: " + Block.BlockDefinition.Id.ToString()); } if (render != null) { foreach (var shape in m_tmpShapeInfos) { if (!string.IsNullOrEmpty(shape.Shape.Name)) { render.AddPiece(shape.Shape.Name, Matrix.Identity); } } render.UpdateRenderObject(true); } m_tmpChildren.Clear(); if (Block.CubeGrid.CreatePhysics) { HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_tmpShapeInfos); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); Shape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_tmpShapeInfos) { var siRef = si; Shape.AddShape(ref siRef); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); CreateMountPoints(); // Update neighbours for parent block var blockOnPosition = Block.CubeGrid.GetCubeBlock(Block.Position); if (blockOnPosition != null) { blockOnPosition.CubeGrid.UpdateBlockNeighbours(blockOnPosition); } if (Block.CubeGrid.Physics != null) { Block.CubeGrid.Physics.AddDirtyBlock(Block); } } foreach (var si in m_tmpShapeInfos) { si.Shape.RemoveReference(); } m_tmpShapeInfos.Clear(); foreach (var si in removeRefsList) { si.RemoveReference(); } ProfilerShort.End(); }
private List<HkdConnection> m_connectionsToAddCache = new List<HkdConnection>(); //connections are created before they can be added so we cache them public HkdBreakableShape? CreateBreakableShape() { ProfilerShort.Begin("CreateBreakableShape"); ProfilerShort.Begin("CollectShapes"); m_blocksShapes.Clear(); foreach (var b in m_grid.GetBlocks()) { Matrix m; var bs = CreateBlockShape(b, out m); if (bs.HasValue) { var shapeInstance = new HkdShapeInstanceInfo(bs.Value, m); m_shapeInfosList.Add(shapeInstance); m_blocksShapes[b.Position] = shapeInstance; } } ProfilerShort.End(); if (m_blocksShapes.Count == 0) { Debug.Fail("No breakable shapes in grid!"); ProfilerShort.End(); return null; } ProfilerShort.Begin("Create"); if (BreakableShape.IsValid()) BreakableShape.RemoveReference(); BreakableShape = new HkdCompoundBreakableShape(null, m_shapeInfosList); BreakableShape.SetChildrenParent(BreakableShape); try { BreakableShape.SetStrenghtRecursively(Sandbox.MyDestructionConstants.STRENGTH, 0.7f); } catch (Exception e) { MyLog.Default.WriteLine(e); MyLog.Default.WriteLine("BS Valid: " + BreakableShape.IsValid()); MyLog.Default.WriteLine("BS Child count: " + BreakableShape.GetChildrenCount()); MyLog.Default.WriteLine("Grid shapes: " + m_shapeInfosList.Count); foreach (var child in m_shapeInfosList) { if (!child.Shape.IsValid()) MyLog.Default.WriteLine("Invalid child!"); else MyLog.Default.WriteLine("Child strength: " + child.Shape.GetStrenght()); } MyLog.Default.WriteLine("Grid Blocks count: " + m_grid.GetBlocks().Count); MyLog.Default.WriteLine("Grid MarkedForClose: " + m_grid.MarkedForClose); HashSet<MyDefinitionId> blockDefinitions = new HashSet<MyDefinitionId>(); foreach (var block in m_grid.GetBlocks()) { if (block.FatBlock != null && block.FatBlock.MarkedForClose) MyLog.Default.WriteLine("Block marked for close: " + block.BlockDefinition.Id); if (blockDefinitions.Count >= 50) break; if (block.FatBlock is MyCompoundCubeBlock) { foreach (var blockInCompound in (block.FatBlock as MyCompoundCubeBlock).GetBlocks()) { blockDefinitions.Add(blockInCompound.BlockDefinition.Id); if (blockInCompound.FatBlock != null && blockInCompound.FatBlock.MarkedForClose) MyLog.Default.WriteLine("Block in compound marked for close: " + blockInCompound.BlockDefinition.Id); } } else blockDefinitions.Add(block.BlockDefinition.Id); } foreach (var def in blockDefinitions) MyLog.Default.WriteLine("Block definition: " + def); throw new InvalidOperationException(); } ProfilerShort.End(); ProfilerShort.Begin("Connect"); CreateConnectionsManually(BreakableShape); ProfilerShort.End(); m_shapeInfosList.Clear(); ProfilerShort.End(); return BreakableShape; }