Example #1
0
 public static bool IsFixed(HkdBreakableShape breakableShape)
 {
     if (breakableShape.IsValid())
     {
         if ((breakableShape.UserObject & 4) != 0)
         {
             return(true);
         }
         breakableShape.GetChildren(m_tmpInfos);
         using (List <HkdShapeInstanceInfo> .Enumerator enumerator = m_tmpInfos.GetEnumerator())
         {
             while (true)
             {
                 if (!enumerator.MoveNext())
                 {
                     break;
                 }
                 HkdShapeInstanceInfo current = enumerator.Current;
                 HkdBreakableShape    shape   = current.Shape;
                 if ((shape.UserObject & 4) != 0)
                 {
                     m_tmpInfos.Clear();
                     return(true);
                 }
             }
         }
         m_tmpInfos.Clear();
     }
     return(false);
 }
Example #2
0
 private static bool IsBodyWithoutGeneratedFracturedPieces(HkdBreakableBody b, MyCubeBlock block)
 {
     if (MyFakes.REMOVE_GENERATED_BLOCK_FRACTURES && ((block == null) || ContainsBlockWithoutGeneratedFracturedPieces(block)))
     {
         if (!b.BreakableShape.IsCompound())
         {
             return(DontCreateFracture(b.BreakableShape));
         }
         b.BreakableShape.GetChildren(m_tmpInfos);
         int index = m_tmpInfos.Count - 1;
         while (true)
         {
             if (index >= 0)
             {
                 HkdShapeInstanceInfo info = m_tmpInfos[index];
                 if (DontCreateFracture(info.Shape))
                 {
                     m_tmpInfos.RemoveAt(index);
                     index--;
                     continue;
                 }
             }
             if (m_tmpInfos.Count == 0)
             {
                 return(true);
             }
             m_tmpInfos.Clear();
             break;
         }
     }
     return(false);
 }
Example #3
0
 public static bool IsFixed(HkdBreakableBodyInfo breakableBodyInfo)
 {
     new HkdBreakableBodyHelper(breakableBodyInfo).GetChildren(m_tmpInfos2);
     using (List <HkdShapeInstanceInfo> .Enumerator enumerator = m_tmpInfos2.GetEnumerator())
     {
         while (true)
         {
             if (!enumerator.MoveNext())
             {
                 break;
             }
             HkdShapeInstanceInfo current = enumerator.Current;
             if (IsFixed(current.Shape))
             {
                 m_tmpInfos2.Clear();
                 return(true);
             }
         }
     }
     m_tmpInfos2.Clear();
     return(false);
 }
Example #4
0
        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();
            }
        }
Example #5
0
        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();
        }
        private void RecreateBreakableBody()
        {
            ProfilerShort.Begin("RecreateBody");
            bool wasfixed = RigidBody.IsFixedOrKeyframed;
            var layer = RigidBody.Layer;

            var world = ((MyGridPhysics) m_grid.Physics).HavokWorld;

            if (false)//m_newBreakableBodies.Count == 1) //jn: keeps crashing now, putting aside for release
            {
                ProfilerShort.Begin("NewReplace");
                ProfilerShort.Begin("Close");
                BreakableBody.BreakableShape.ClearConnectionsRecursive();
                BreakableBody.BreakableShape.RemoveReference();
                CloseRigidBody();
                ProfilerShort.BeginNextBlock("2");
                BreakableBody = m_newBreakableBodies[0];
                Debug.Assert(RigidBody.Layer == layer, "New body has different layer!!");
                RigidBody.UserObject = this;
                RigidBody.ContactPointCallbackEnabled = true;
                RigidBody.ContactSoundCallbackEnabled = true;
                RigidBody.ContactPointCallback += RigidBody_ContactPointCallback_Destruction;
                BreakableBody.AfterReplaceBody += FracturedBody_AfterReplaceBody;
                BreakableBody.BreakableShape.AddReference();
                ProfilerShort.BeginNextBlock("ReplaceFractures");
                BreakableBody.BreakableShape.GetChildren(m_childList);
                for (int i = 0; i < m_childList.Count; i++) //remove fractures
                {
                    var child = m_childList[i];
                    Debug.Assert(((HkVec3IProperty)child.Shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION)).IsValid());
                    if (child.Shape.IsFracturePiece())
                    {
                        //int j = 0;
                        //for (; j < BreakableBody.BreakableShape.GetChildrenCount(); j++)
                        //    if (BreakableBody.BreakableShape.GetChild(j).Shape == child.Shape)
                        //        break;
                        //Debug.Assert(child.Shape == BreakableBody.BreakableShape.GetChild(j).Shape && j >= i);
                        //child.Shape.SetFlagRecursively(HkdBreakableShape.Flags.DONT_CREATE_FRACTURE_PIECE);

                        //BreakableBody.BreakableShape.RemoveChild(j);

                        //child.Shape.RemoveReference();
                        //m_childList[i].Shape.RemoveReference();
                        //m_childList[i].RemoveReference();
                        m_childList.RemoveAt(i);
                        i--;
                    }
                }
                foreach (var fb in m_fractureBlocksCache) //add fractures grouped by block
                {
                    Debug.Assert(fb.Shape.IsValid() && !((HkVec3IProperty)fb.Shape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION)).IsValid());
                    fb.Shape.SetPropertyRecursively(HkdBreakableShape.PROPERTY_GRID_POSITION, new HkVec3IProperty(fb.Position));
                    Matrix m = Matrix.Identity;
                    m.Translation = fb.Position * m_grid.GridSize;
                    fb.Shape.SetChildrenParent(fb.Shape);
                    var si = new HkdShapeInstanceInfo(fb.Shape, m);
                    //BreakableBody.BreakableShape.AddShape(ref si);
                    //si.RemoveReference();
                    m_childList.Add(si);
                }
                BreakableBody.BreakableShape.ReplaceChildren(m_childList);
                for (int i = m_childList.Count - m_fractureBlocksCache.Count; i < m_childList.Count; i++)
                    m_childList[i].RemoveReference();
                m_childList.Clear();
                ProfilerShort.BeginNextBlock("Connections");
                BreakableBody.BreakableShape.SetChildrenParent(BreakableBody.BreakableShape);
                Shape.BreakableShape = BreakableBody.BreakableShape;
                Shape.UpdateDirtyBlocks(m_dirtyCubesInfo.DirtyBlocks, false);
                Shape.CreateConnectionToWorld(BreakableBody, world);
                if (wasfixed && m_grid.GridSizeEnum == MyCubeSize.Small)
                {
                    if (MyCubeGridSmallToLargeConnection.Static.TestGridSmallToLargeConnection(m_grid))
                    {
                        RigidBody.UpdateMotionType(HkMotionType.Fixed);
                        RigidBody.Quality = HkCollidableQualityType.Fixed;
                    }
                }
                ProfilerShort.BeginNextBlock("Add");
                HavokWorld.DestructionWorld.AddBreakableBody(BreakableBody);
                ProfilerShort.End();
                ProfilerShort.End();
            }
            else
            { //Old body is removed so create new one (should use matching one from new bodies in final version)
                foreach (var b in m_newBreakableBodies)
                {
                    MyFracturedPiecesManager.Static.ReturnToPool(b);
                }
                ProfilerShort.Begin("OldReplace");
                ProfilerShort.Begin("GetPhysicsBody");
                var ph = BreakableBody.GetRigidBody();
                var linVel = ph.LinearVelocity;
                var angVel = ph.AngularVelocity;
                ph = null;
                ProfilerShort.End();
                if (m_grid.BlocksCount > 0)
                {
                    ProfilerShort.Begin("Refresh");
                    Shape.RefreshBlocks(RigidBody, RigidBody2, m_dirtyCubesInfo, BreakableBody);
                    ProfilerShort.BeginNextBlock("NewGridBody");
                    CloseRigidBody();
                    var s = (HkShape)m_shape;
                    CreateBody(ref s, null);
                    RigidBody.Layer = layer;
                    RigidBody.ContactPointCallbackEnabled = true;
                    RigidBody.ContactSoundCallbackEnabled = true;
                    RigidBody.ContactPointCallback += RigidBody_ContactPointCallback_Destruction;
                    BreakableBody.BeforeControllerOperation += BreakableBody_BeforeControllerOperation;
                    BreakableBody.AfterControllerOperation += BreakableBody_AfterControllerOperation;
                    Matrix m = Entity.PositionComp.WorldMatrix;
                    m.Translation = WorldToCluster(Entity.PositionComp.GetPosition());
                    RigidBody.SetWorldMatrix(m);
                    RigidBody.UserObject = this;
                    Entity.Physics.LinearVelocity = m_oldLinVel;
                    Entity.Physics.AngularVelocity = m_oldAngVel;
                    m_grid.DetectDisconnectsAfterFrame();
                    Shape.CreateConnectionToWorld(BreakableBody, world);
                    HavokWorld.DestructionWorld.AddBreakableBody(BreakableBody);
                    ProfilerShort.End();
                }
                else
                {
                    ProfilerShort.Begin("GridClose");
                    m_grid.Close();
                    ProfilerShort.End();
                }
                ProfilerShort.End();
            }
            m_newBreakableBodies.Clear();
            m_fractureBlocksCache.Clear();
            ProfilerShort.End();
        }
        /// <summary>
        /// Searches for all children shapes of the block (or block inside compound block). The given block is always the block from grid (not from compound block).
        /// </summary>
        /// <param name="block">grid block</param>
        /// <param name="shapeInst">shape instnce for the block</param>
        /// <returns></returns>
        private bool FindFractureComponentBlocks(MySlimBlock block, HkdShapeInstanceInfo shapeInst)
        {
            Debug.Assert(MyFakes.ENABLE_FRACTURE_COMPONENT);

            var bShape = shapeInst.Shape;
            if (IsBreakableShapeCompound(bShape))
            {
                bool anyAdded = false;
                List<HkdShapeInstanceInfo> children = new List<HkdShapeInstanceInfo>();
                bShape.GetChildren(children);

                foreach (var child in children)
                    anyAdded |= FindFractureComponentBlocks(block, child);

                return anyAdded;
            }

            ushort? blockIdInCompound = null;
            if (bShape.HasProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID))
            {
                HkSimpleValueProperty blockIdInCompoundProperty = bShape.GetProperty(HkdBreakableShape.PROPERTY_BLOCK_COMPOUND_ID);
                blockIdInCompound = (ushort)blockIdInCompoundProperty.ValueUInt;
            }

            var compoundBlock = block.FatBlock as MyCompoundCubeBlock;
            if (compoundBlock != null)
            {
                if (blockIdInCompound != null)
                {
                    var blockInCompound = compoundBlock.GetBlock(blockIdInCompound.Value);
                    if (blockInCompound != null)
                    {
                        block = blockInCompound;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    Debug.Fail("Breakable shape has no compoundId");
                    return false;
                }
            }

            if (!m_fracturedSlimBlocksShapes.ContainsKey(block))
                m_fracturedSlimBlocksShapes[block] = new List<HkdShapeInstanceInfo>();
            m_fracturedSlimBlocksShapes[block].Add(shapeInst);

            return true;
        }
        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();
        }
        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();
        }
Example #10
0
        public override void Init(MyObjectBuilder_EntityBase objectBuilder)
        {
            base.Init(objectBuilder);
            var ob = objectBuilder as MyObjectBuilder_FracturedPiece;
            if (ob.Shapes.Count == 0)
            {
                return;
                //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, null, (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();
        }
Example #11
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());
                }
                throw new InvalidOperationException();
            }
            ProfilerShort.End();
            ProfilerShort.Begin("Connect");
            CreateConnectionsManually(BreakableShape);
            ProfilerShort.End();
            FindConnectionsToWorld(m_grid.GetBlocks());

            m_shapeInfosList.Clear();
            ProfilerShort.End();
            return BreakableShape;
        }
Example #12
0
        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 void RecreateBreakableBody()
 {
     ProfilerShort.Begin("RecreateBody");
     bool wasfixed = RigidBody.IsFixedOrKeyframed;
     if (m_newBreakableBodies.Count == 1)
     {
         ProfilerShort.Begin("NewReplace");
         ProfilerShort.Begin("Close");
         BreakableBody.BreakableShape.ClearConnectionsRecursive();
         BreakableBody.BreakableShape.RemoveReference();
         CloseRigidBody();
         ProfilerShort.BeginNextBlock("2");
         BreakableBody = m_newBreakableBodies[0];
         RigidBody.UserObject = this;
         RigidBody.ContactPointCallbackEnabled = true;
         RigidBody.ContactSoundCallbackEnabled = true;
         RigidBody.ContactPointCallback += RigidBody_ContactPointCallback_Destruction;
         BreakableBody.AfterReplaceBody += FracturedBody_AfterReplaceBody;
         BreakableBody.BreakableShape.AddReference();
         ProfilerShort.BeginNextBlock("ReplaceFractures");
         BreakableBody.BreakableShape.GetChildren(m_childList);
         for (int i = 0; i < m_childList.Count; i++) //remove fractures
         {
             var child = m_childList[i];
             if (child.Shape.IsFracturePiece())
             {
                 BreakableBody.BreakableShape.RemoveChild(i);
                 m_childList.RemoveAt(i);
                 i--;
             }
         }
         m_childList.Clear();
         foreach (var fb in m_grid.m_fractureBlocksCache) //add fractures grouped by block
         {
             Matrix m = Matrix.Identity;
             m.Translation = fb.Position * m_grid.GridSize;
             var si = new HkdShapeInstanceInfo(fb.Shape, m);
             BreakableBody.BreakableShape.AddShape(ref si);
             si.RemoveReference();
         }
         ProfilerShort.BeginNextBlock("Connections");
         BreakableBody.BreakableShape.SetChildrenParent(BreakableBody.BreakableShape);
         Shape.BreakableShape = BreakableBody.BreakableShape;
         Shape.UpdateDirtyBlocks(m_dirtyCubesInfo.DirtyBlocks, false);
         Shape.CreateConnectionToWorld(BreakableBody);
         if(wasfixed)
         {
             if(MyCubeGridSmallToLargeConnection.Static.CheckGridSmallToLargeConnect(m_grid));
             {
                 RigidBody.Quality = HkCollidableQualityType.Fixed;
                 RigidBody.UpdateMotionType(HkMotionType.Fixed);
             }
         }
         ProfilerShort.BeginNextBlock("Add");
         HavokWorld.DestructionWorld.AddBreakableBody(BreakableBody);
         ProfilerShort.End();
         ProfilerShort.End();
     }
     else
     { //Old body is removed so create new one (should use matching one from new bodies in final version)
         foreach (var b in m_newBreakableBodies)
         {
             HavokWorld.DestructionWorld.RemoveBreakableBody(b);
             MyFracturedPiecesManager.Static.ReturnToPool(b);
         }
         ProfilerShort.Begin("OldReplace");
         ProfilerShort.Begin("GetPhysicsBody");
         var ph = BreakableBody.GetRigidBody();
         var linVel = ph.LinearVelocity;
         var angVel = ph.AngularVelocity;
         ph = null;
         ProfilerShort.End();
         if (m_grid.BlocksCount > 0)
         {
             ProfilerShort.Begin("Refresh");
             Shape.RefreshBlocks(RigidBody, RigidBody2, m_dirtyCubesInfo, BreakableBody);
             ProfilerShort.BeginNextBlock("NewGridBody");
             CloseRigidBody();
             var s = (HkShape)m_shape;
             CreateBody(ref s, null);
             RigidBody.ContactPointCallbackEnabled = true;
             RigidBody.ContactSoundCallbackEnabled = true;
             RigidBody.ContactPointCallback += RigidBody_ContactPointCallback_Destruction;
             Matrix m = Entity.PositionComp.WorldMatrix;
             m.Translation = WorldToCluster(Entity.PositionComp.GetPosition());
             RigidBody.SetWorldMatrix(m);
             RigidBody.UserObject = this;
             Entity.Physics.LinearVelocity = m_oldLinVel;
             Entity.Physics.AngularVelocity = m_oldAngVel;
             m_grid.DetectDisconnectsAfterFrame();
             Shape.CreateConnectionToWorld(BreakableBody);
             HavokWorld.DestructionWorld.AddBreakableBody(BreakableBody);
             ProfilerShort.End();
         }
         else
         {
             ProfilerShort.Begin("GridClose");
             m_grid.Close();
             ProfilerShort.End();
         }
         ProfilerShort.End();
     }
     m_newBreakableBodies.Clear();
     ProfilerShort.End();
 }
Example #15
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;
        }
        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;

                if (model == null)
                {
                    Debug.Fail("Fracture piece Definition not found");
                    continue;
                }
                if (MyModels.GetModelOnlyData(model).HavokBreakableShapes == null)
                {
                    MyDestructionData.Static.LoadModelDestruction(mdef, false, Vector3.One);
                }
                var shape = MyModels.GetModelOnlyData(model).HavokBreakableShapes[0];
                var 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)
            {
                Debug.Fail("No relevant shape was found for fractured piece. It was probably reexported and names changed.");
                //HkdShapeInstanceInfo si = new HkdShapeInstanceInfo(new HkdBreakableShape((HkShape)new HkBoxShape(Vector3.One)), Matrix.Identity);
                //m_shapeInfos.Add(si);
                throw new Exception("No relevant shape was found for fractured piece. It was probably reexported and names changed.");
            }

            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.InitialSolverDeactivation = HkSolverDeactivation.Medium;
                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;

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

                //Cannot set keyframed in constructor, because Havok does not allow set CoM on kinematic object..
                if(!Sync.IsServer)
                    Physics.RigidBody.UpdateMotionType(HkMotionType.Keyframed);
                Physics.Enabled = true;
            }
            m_children.Clear();
            m_shapeInfos.Clear();
        }