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); }
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); }
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); }
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(); } }
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(); }
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(); }
private List<HkdConnection> m_connectionsToAddCache = new List<HkdConnection>(); //connections are created before they can be added so we cache them public HkdBreakableShape? CreateBreakableShape() { ProfilerShort.Begin("CreateBreakableShape"); ProfilerShort.Begin("CollectShapes"); m_blocksShapes.Clear(); foreach (var b in m_grid.GetBlocks()) { Matrix m; var bs = CreateBlockShape(b, out m); if (bs.HasValue) { var shapeInstance = new HkdShapeInstanceInfo(bs.Value, m); m_shapeInfosList.Add(shapeInstance); m_blocksShapes[b.Position] = shapeInstance; } } ProfilerShort.End(); if (m_blocksShapes.Count == 0) { Debug.Fail("No breakable shapes in grid!"); ProfilerShort.End(); return null; } ProfilerShort.Begin("Create"); if (BreakableShape.IsValid()) BreakableShape.RemoveReference(); BreakableShape = new HkdCompoundBreakableShape(null, m_shapeInfosList); BreakableShape.SetChildrenParent(BreakableShape); try { BreakableShape.SetStrenghtRecursively(Sandbox.MyDestructionConstants.STRENGTH, 0.7f); } catch (Exception e) { MyLog.Default.WriteLine(e); MyLog.Default.WriteLine("BS Valid: " + BreakableShape.IsValid()); MyLog.Default.WriteLine("BS Child count: " + BreakableShape.GetChildrenCount()); MyLog.Default.WriteLine("Grid shapes: " + m_shapeInfosList.Count); foreach (var child in m_shapeInfosList) { if (!child.Shape.IsValid()) MyLog.Default.WriteLine("Invalid child!"); else MyLog.Default.WriteLine("Child strength: " + child.Shape.GetStrenght()); } throw new InvalidOperationException(); } ProfilerShort.End(); ProfilerShort.Begin("Connect"); CreateConnectionsManually(BreakableShape); ProfilerShort.End(); FindConnectionsToWorld(m_grid.GetBlocks()); m_shapeInfosList.Clear(); ProfilerShort.End(); return BreakableShape; }
public 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(); }
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(); }