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(); }
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; }
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; }