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;
        }
Beispiel #3
0
        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;
        }