void CreateBreakableShapeFromCollisionShapes(MyModel model, Vector3 defaultSize, MyPhysicalModelDefinition modelDef) { // Make box half edge length of the grid so fractured block is smaller than not fractured, also good for compounds HkShape shape; if (model.HavokCollisionShapes != null && model.HavokCollisionShapes.Length > 0) { if (model.HavokCollisionShapes.Length > 1) { shape = HkListShape.Create(model.HavokCollisionShapes, model.HavokCollisionShapes.Length, HkReferencePolicy.None); } else { shape = model.HavokCollisionShapes[0]; shape.AddReference(); } } else { //modelDef.Size * (modelDef.CubeSize == MyCubeSize.Large ? 2.5f : 0.25f) shape = new HkBoxShape(defaultSize * 0.5f, MyPerGameSettings.PhysicsConvexRadius); } var boxBreakable = new HkdBreakableShape(shape); boxBreakable.Name = model.AssetName; boxBreakable.SetMass(modelDef.Mass); model.HavokBreakableShapes = new HkdBreakableShape[] { boxBreakable }; shape.RemoveReference(); }
/// <summary> /// Sets model from havok to render component of this entity. /// </summary> public void SetDataFromHavok(HkdBreakableShape shape) { ProfilerShort.Begin("FP.SetDataFromHavok"); Shape = shape; Shape.AddReference(); if (Render != null) { if (shape.IsCompound() || string.IsNullOrEmpty(shape.Name)) { shape.GetChildren(m_shapeInfos); Debug.Assert(m_shapeInfos.Count > 0); foreach (var shapeInstanceInfo in m_shapeInfos) { //System.Diagnostics.Debug.Assert(shapeInstanceInfo.IsValid(), "Invalid shapeInstanceInfo!"); if (shapeInstanceInfo.IsValid()) { Render.AddPiece(shapeInstanceInfo.ShapeName, shapeInstanceInfo.GetTransform()); } } m_shapeInfos.Clear(); } else { Render.AddPiece(shape.Name, Matrix.Identity); } } ProfilerShort.End(); m_hitPoints = Shape.Volume * 100; }
public static bool IsFixed(HkdBreakableShape breakableShape) { System.Diagnostics.Debug.Assert(m_tmpInfos.Count == 0, ""); if (!breakableShape.IsValid()) return false; if ((breakableShape.UserObject & (uint)HkdBreakableShape.Flags.IS_FIXED) != 0) { return true; } else { Debug.Assert(m_tmpInfos.Count == 0); breakableShape.GetChildren(m_tmpInfos); foreach (var child in m_tmpInfos) { if ((child.Shape.UserObject & (uint)HkdBreakableShape.Flags.IS_FIXED) != 0) { m_tmpInfos.Clear(); return true; } } m_tmpInfos.Clear(); } return false; }
public static bool IsFixed(HkdBreakableShape breakableShape) { System.Diagnostics.Debug.Assert(m_tmpInfos.Count == 0, ""); if (!breakableShape.IsValid()) { return(false); } if ((breakableShape.UserObject & (uint)HkdBreakableShape.Flags.IS_FIXED) != 0) { return(true); } else { Debug.Assert(m_tmpInfos.Count == 0); breakableShape.GetChildren(m_tmpInfos); foreach (var child in m_tmpInfos) { if ((child.Shape.UserObject & (uint)HkdBreakableShape.Flags.IS_FIXED) != 0) { m_tmpInfos.Clear(); return(true); } } m_tmpInfos.Clear(); } return(false); }
private HkdBreakableShape AddMountForShape(HkdBreakableShape shape, Matrix transform, ref BoundingBox blockBB) { Vector4 min; Vector4 max; shape.GetShape().GetLocalAABB(0.01f, out min, out max);//.Transform(CubeGrid.PositionComp.WorldMatrix); var bb = new BoundingBox(new Vector3(min), new Vector3(max)); bb = bb.Transform(transform); bb.Min /= CubeGrid.GridSize; //normalize for mount point bb.Max /= CubeGrid.GridSize; bb.Inflate(0.04f);//add tolerance (fracture shapes are smaller than block) bb.Min += blockBB.HalfExtents; bb.Max += blockBB.HalfExtents; if (blockBB.Contains(bb) == ContainmentType.Intersects) { bb.Inflate(-0.04f); foreach (var directionEnum in Base6Directions.EnumDirections) { int dirEnum = (int)directionEnum; Vector3 direction = Base6Directions.Directions[dirEnum]; Vector3 absDir = Vector3.Abs(direction); var mp = new MyCubeBlockDefinition.MountPoint(); mp.Start = bb.Min; mp.End = bb.Max; var start = mp.Start * absDir / (blockBB.HalfExtents * 2) - absDir * 0.04f; var end = mp.End * absDir / (blockBB.HalfExtents * 2) + absDir * 0.04f; bool add = false; bool one = false; if (start.Max() < 1 && end.Max() > 1 && direction.Max() > 0) { add = true; one = true; } else if (start.Min() < 0 && end.Max() > 0 && direction.Min() < 0) { add = true; } if (!add) { continue; } mp.Start -= mp.Start * absDir - absDir * 0.04f; mp.End -= mp.End * absDir + absDir * 0.04f; if (one) { mp.Start += absDir * blockBB.HalfExtents * 2; mp.End += absDir * blockBB.HalfExtents * 2; } mp.Start -= blockBB.HalfExtents - Vector3.One / 2; mp.End -= blockBB.HalfExtents - Vector3.One / 2; mp.Normal = new Vector3I(direction); MountPoints.Add(mp); } } return(shape); }
private static bool DontCreateFracture(HkdBreakableShape breakableShape) { if (!breakableShape.IsValid()) { return(false); } return((breakableShape.UserObject & (uint)HkdBreakableShape.Flags.DONT_CREATE_FRACTURE_PIECE) != 0); }
private void CreateBreakableShape(MyEnvironmentItemDefinition itemDefinition, ref MyEnvironmentItems.MyEnvironmentItemData itemData, ref Vector3D hitWorldPosition, Vector3 hitNormal, float forceMultiplier, string fallSound = "") { HkdBreakableShape oldBreakableShape = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes[0].Clone(); MatrixD transformMatrix = itemData.Transform.TransformMatrix; oldBreakableShape.SetMassRecursively(500f); oldBreakableShape.SetStrenghtRecursively(5000f, 0.7f); oldBreakableShape.GetChildren(base.m_childrenTmp); HkdBreakableShape[] havokBreakableShapes = MyModels.GetModelOnlyData(itemDefinition.Model).HavokBreakableShapes; Vector3D.Transform(hitWorldPosition, MatrixD.Normalize(MatrixD.Invert(transformMatrix))); float num = (float)(hitWorldPosition.Y - itemData.Transform.Position.Y); List <HkdShapeInstanceInfo> shapeList = new List <HkdShapeInstanceInfo>(); List <HkdShapeInstanceInfo> list2 = new List <HkdShapeInstanceInfo>(); HkdShapeInstanceInfo? nullable = null; foreach (HkdShapeInstanceInfo info in base.m_childrenTmp) { if ((nullable == null) || (info.CoM.Y < nullable.Value.CoM.Y)) { nullable = new HkdShapeInstanceInfo?(info); } if (info.CoM.Y > num) { list2.Add(info); } else { shapeList.Add(info); } } if (shapeList.Count != 2) { if ((shapeList.Count == 0) && list2.Remove(nullable.Value)) { shapeList.Add(nullable.Value); } } else if ((shapeList[0].CoM.Y < shapeList[1].CoM.Y) && (num < (shapeList[1].CoM.Y + 1.25f))) { list2.Insert(0, shapeList[1]); shapeList.RemoveAt(1); } else if ((shapeList[0].CoM.Y > shapeList[1].CoM.Y) && (num < (shapeList[0].CoM.Y + 1.25f))) { list2.Insert(0, shapeList[0]); shapeList.RemoveAt(0); } if (shapeList.Count > 0) { CreateFracturePiece(itemDefinition, oldBreakableShape, transformMatrix, hitNormal, shapeList, forceMultiplier, true, ""); } if (list2.Count > 0) { CreateFracturePiece(itemDefinition, oldBreakableShape, transformMatrix, hitNormal, list2, forceMultiplier, false, fallSound); } base.m_childrenTmp.Clear(); }
private bool GetCurrentFracturedShapeList(HkdBreakableShape breakableShape, List <MyObjectBuilder_FractureComponentBase.FracturedShape> shapeList, string[] excludeShapeNames = null) { var shapeName = breakableShape.Name; bool shapeNameEmpty = string.IsNullOrEmpty(shapeName); if (excludeShapeNames != null && !shapeNameEmpty) { foreach (var shapeNameToRemove in excludeShapeNames) { if (shapeName == shapeNameToRemove) { return(false); } } } if (breakableShape.GetChildrenCount() > 0) { List <HkdShapeInstanceInfo> shapeInst = new List <HkdShapeInstanceInfo>(); breakableShape.GetChildren(shapeInst); bool allChildrenAdded = true; foreach (var inst in shapeInst) { allChildrenAdded &= GetCurrentFracturedShapeList(inst.Shape, shapeList, excludeShapeNames: excludeShapeNames); } if (!shapeNameEmpty && allChildrenAdded) { foreach (var inst in shapeInst) { shapeList.RemoveAll(s => s.Name == inst.ShapeName); } shapeList.Add(new MyObjectBuilder_FractureComponentBase.FracturedShape() { Name = shapeName, Fixed = breakableShape.IsFixed() }); } return(allChildrenAdded); } else { if (!shapeNameEmpty) { shapeList.Add(new MyObjectBuilder_FractureComponentBase.FracturedShape() { Name = shapeName, Fixed = breakableShape.IsFixed() }); return(true); } } return(false); }
private void DisableRefCountRec(HkdBreakableShape bShape) { bShape.DisableRefCount(); var lst = new List <HkdShapeInstanceInfo>(); bShape.GetChildren(lst); foreach (var child in lst) { DisableRefCountRec(child.Shape); } }
private static void RenameShapesRecursive(HkdBreakableShape shape, string shapeSuffix) { shape.Name += shapeSuffix; using (PoolManager.Get(out List <HkdShapeInstanceInfo> shapes)) { shape.GetChildren(shapes); foreach (var child in shapes) { RenameShapesRecursive(child.Shape, shapeSuffix); } } }
private static void CollectShapeNamesRecursive(HkdBreakableShape shape, HashSet <string> shapeName) { shapeName.Add(shape.Name); using (PoolManager.Get(out List <HkdShapeInstanceInfo> shapes)) { shape.GetChildren(shapes); foreach (var child in shapes) { CollectShapeNamesRecursive(child.Shape, shapeName); } } }
internal void SetDataFromHavok(HkdBreakableShape shape, bool compound) { this.Shape = shape; if (compound) { this.SetDataFromCompound(shape); } else { this.Render.AddPiece(shape.Name, Matrix.Identity); } this.CreateMountPoints(); }
public void EnqueShape(string model, MyDefinitionId id, HkdBreakableShape shape) { using (m_poolLock.AcquireExclusiveUsing()) { if (!m_pools.ContainsKey(id)) m_pools[id] = new Dictionary<string, ConcurrentQueue<HkdBreakableShape>>(); if (!m_pools[id].ContainsKey(model)) m_pools[id][model] = new ConcurrentQueue<HkdBreakableShape>(); } m_pools[id][model].Enqueue(shape); m_missing--; }
public void EnqueShape(string model, MyDefinitionId id, HkdBreakableShape shape) { if (!m_pools.ContainsKey(id)) { m_pools[id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!m_pools[id].ContainsKey(model)) { m_pools[id][model] = new ConcurrentQueue <HkdBreakableShape>(); } m_pools[id][model].Enqueue(shape); m_missing--; }
internal void SetDataFromHavok(HkdBreakableShape shape, bool compound) { Shape = shape; if (compound) { SetDataFromCompound(shape); } else { var render = this.Render as MyRenderComponentFracturedPiece; render.AddPiece(shape.Name, Matrix.Identity); } CreateMountPoints(); }
private static void ConvertAllShapesToFractureComponentShapeBuilder(HkdBreakableShape shape, ref Matrix shapeRotation, MyBlockOrientation blockOrientation, HashSet <Tuple <string, float> > namesAndBuildProgress, MyObjectBuilder_FractureComponentCubeBlock fractureComponentBuilder, out float buildProgress) { buildProgress = 1f; var name = shape.Name; Tuple <string, float> foundTuple = null; foreach (var tuple in namesAndBuildProgress) { if (tuple.Item1 == name) { foundTuple = tuple; break; } } if (foundTuple != null) { MyBlockOrientation shapeOrientation = new MyBlockOrientation(ref shapeRotation); if (shapeOrientation == blockOrientation) { MyObjectBuilder_FractureComponentCubeBlock.FracturedShape builderShape = new MyObjectBuilder_FractureComponentBase.FracturedShape(); builderShape.Name = name; builderShape.Fixed = MyDestructionHelper.IsFixed(shape); fractureComponentBuilder.Shapes.Add(builderShape); buildProgress = foundTuple.Item2; } } if (shape.GetChildrenCount() > 0) { List <HkdShapeInstanceInfo> children = new List <HkdShapeInstanceInfo>(); shape.GetChildren(children); foreach (var child in children) { var childShapeRotation = child.GetTransform(); float localBuildProgress; ConvertAllShapesToFractureComponentShapeBuilder(child.Shape, ref childShapeRotation, blockOrientation, namesAndBuildProgress, fractureComponentBuilder, out localBuildProgress); if (foundTuple == null) { buildProgress = localBuildProgress; } } } }
public static void CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List <HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren, string fallSound = "") { bool isStatic = false; if (canContainFixedChildren) { foreach (HkdShapeInstanceInfo info in shapeList) { info.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); Vector3D translation = worldMatrix.Translation + (worldMatrix.Up * 1.5); Quaternion rotation = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(info.Shape.GetShape(), ref translation, ref rotation, MyEnvironmentItems.m_tmpResults, 15); bool flag2 = false; using (List <HkBodyCollision> .Enumerator enumerator2 = MyEnvironmentItems.m_tmpResults.GetEnumerator()) { while (enumerator2.MoveNext()) { if (enumerator2.Current.GetCollisionEntity() is MyVoxelMap) { info.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); isStatic = true; flag2 = true; } else if (!flag2) { continue; } break; } } MyEnvironmentItems.m_tmpResults.Clear(); } } HkdBreakableShape shape = (HkdBreakableShape) new HkdCompoundBreakableShape(new HkdBreakableShape?(oldBreakableShape), shapeList); shape.RecalcMassPropsFromChildren(); MyFracturedPiece fp = MyDestructionHelper.CreateFracturePiece(shape, ref worldMatrix, isStatic, new MyDefinitionId?(itemDefinition.Id), true); if ((fp != null) && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref shape, fp, forceMultiplier); fp.Physics.ForceActivate(); if (fallSound.Length > 0) { fp.StartFallSound(fallSound); } } }
public void EnqueShape(string model, MyDefinitionId id, HkdBreakableShape shape) { using (this.m_poolLock.AcquireExclusiveUsing()) { if (!this.m_pools.ContainsKey(id)) { this.m_pools[id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!this.m_pools[id].ContainsKey(model)) { this.m_pools[id][model] = new ConcurrentQueue <HkdBreakableShape>(); } } this.m_pools[id][model].Enqueue(shape); this.m_missing--; }
public void SetDataFromCompound(HkdBreakableShape compound) { MyRenderComponentFracturedPiece render = this.Render; if (render != null) { compound.GetChildren(m_shapeInfos); foreach (HkdShapeInstanceInfo info in m_shapeInfos) { if (info.IsValid()) { render.AddPiece(info.ShapeName, info.GetTransform()); } } m_shapeInfos.Clear(); } }
public static void GetAllBlockBreakableShapeNames(HkdBreakableShape shape, HashSet <Tuple <string, float> > outNamesAndBuildProgress, float buildProgress) { string name = shape.Name; if (!string.IsNullOrEmpty(name)) { outNamesAndBuildProgress.Add(new Tuple <string, float>(name, buildProgress)); } if (shape.GetChildrenCount() > 0) { List <HkdShapeInstanceInfo> list = new List <HkdShapeInstanceInfo>(); shape.GetChildren(list); foreach (HkdShapeInstanceInfo info in list) { GetAllBlockBreakableShapeNames(info.Shape, outNamesAndBuildProgress, buildProgress); } } }
public virtual void SetShape(HkdBreakableShape shape, bool compound) { Debug.Assert(shape.IsValid()); if (Shape.IsValid()) { Shape.RemoveReference(); } Shape = shape; var render = Entity.Render as MyRenderComponentFracturedPiece; Debug.Assert(render != null); if (render != null) { render.ClearModels(); if (compound) { Debug.Assert(m_tmpChildren.Count == 0); shape.GetChildren(m_tmpChildren); foreach (var shapeInstanceInfo in m_tmpChildren) { System.Diagnostics.Debug.Assert(shapeInstanceInfo.IsValid(), "Invalid shapeInstanceInfo!"); if (shapeInstanceInfo.IsValid()) { render.AddPiece(shapeInstanceInfo.ShapeName, Matrix.Identity); } } m_tmpChildren.Clear(); } else { render.AddPiece(shape.Name, Matrix.Identity); } render.UpdateRenderObject(true); } }
private static void GetAllBlockBreakableShapeNames(HkdBreakableShape shape, HashSet <string> outNames) { var name = shape.Name; if (!string.IsNullOrEmpty(name)) { outNames.Add(name); } if (shape.GetChildrenCount() > 0) { List <HkdShapeInstanceInfo> children = new List <HkdShapeInstanceInfo>(); shape.GetChildren(children); foreach (var child in children) { GetAllBlockBreakableShapeNames(child.Shape, outNames); } } }
public override void SetShape(HkdBreakableShape shape, bool compound) { base.SetShape(shape, compound); 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); } }
public void AllocateForDefinition(string model, MyPhysicalModelDefinition definition, int count) { if (!string.IsNullOrEmpty(model)) { MyModel modelOnlyData = MyModels.GetModelOnlyData(model); if (modelOnlyData.HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(model, definition, modelOnlyData.BoundingBoxSize, true, false); } if ((modelOnlyData.HavokBreakableShapes != null) && (modelOnlyData.HavokBreakableShapes.Length != 0)) { ConcurrentQueue <HkdBreakableShape> queue; using (this.m_poolLock.AcquireExclusiveUsing()) { if (!this.m_pools.ContainsKey(definition.Id)) { this.m_pools[definition.Id] = new Dictionary <string, ConcurrentQueue <HkdBreakableShape> >(); } if (!this.m_pools[definition.Id].ContainsKey(model)) { this.m_pools[definition.Id][model] = new ConcurrentQueue <HkdBreakableShape>(); } queue = this.m_pools[definition.Id][model]; } for (int i = 0; i < count; i++) { HkdBreakableShape item = modelOnlyData.HavokBreakableShapes[0].Clone(); queue.Enqueue(item); if (i == 0) { HkMassProperties massProperties = new HkMassProperties(); item.BuildMassProperties(ref massProperties); if (!massProperties.InertiaTensor.IsValid()) { MyLog.Default.WriteLine($"Block with wrong destruction! (q.isOk): {definition.Model}"); return; } } } } } }
private static MyFracturedPiece CreateFracturePiece(ref HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic) { Debug.Assert(shape.IsValid()); ProfilerShort.Begin("CreateFracturePiece"); var fracturedPiece = MyFracturedPiecesManager.Static.GetPieceFromPool(0);//new MyFracturedPiece(); fracturedPiece.PositionComp.WorldMatrix = worldMatrix; fracturedPiece.Physics.Flags = isStatic ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS; var physicsBody = fracturedPiece.Physics as MyPhysicsBody;//new MyPhysicsBody(fracturedPiece,isFixed ?RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS); HkMassProperties mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); physicsBody.InitialSolverDeactivation = HkSolverDeactivation.High; physicsBody.CreateFromCollisionObject(shape.GetShape(), Vector3.Zero, worldMatrix, mp); physicsBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; physicsBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; System.Diagnostics.Debug.Assert(physicsBody.BreakableBody == null, "physicsBody.DestructionBody == null"); physicsBody.BreakableBody = new HkdBreakableBody(shape, physicsBody.RigidBody, world, worldMatrix); physicsBody.BreakableBody.AfterReplaceBody += physicsBody.FracturedBody_AfterReplaceBody; ProfilerShort.End(); ProfilerShort.Begin("Sync"); if (fracturedPiece.SyncFlag) { fracturedPiece.CreateSync(); } ProfilerShort.End(); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; //physicsBody.RigidBody.ContactPointCallbackDelay = 0; //physicsBody.RigidBody.ContactPointCallbackEnabled = true; fracturedPiece.Physics = physicsBody; //FixPosition(fracturedPiece); fracturedPiece.SetDataFromHavok(shape); ProfilerShort.Begin("AddToWorld"); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; shape.RemoveReference(); ProfilerShort.End(); return(fracturedPiece); }
public void SetDataFromCompound(HkdBreakableShape compound) { var render = this.Render as MyRenderComponentFracturedPiece; if (render != null) { compound.GetChildren(m_shapeInfos); foreach (var shapeInstanceInfo in m_shapeInfos) { System.Diagnostics.Debug.Assert(shapeInstanceInfo.IsValid(), "Invalid shapeInstanceInfo!"); if (shapeInstanceInfo.IsValid()) { render.AddPiece(shapeInstanceInfo.ShapeName, shapeInstanceInfo.GetTransform()); } } m_shapeInfos.Clear(); } }
private static void DrawBreakableShape(HkdBreakableShape breakableShape, MatrixD worldMatrix, float alpha, ref int shapeIndex, string customText = null, bool isPhantom = false) { object[] objArray1 = new object[] { breakableShape.Name, " Strength: ", breakableShape.GetStrenght(), " Static:", breakableShape.IsFixed().ToString() }; DrawCollisionShape(breakableShape.GetShape(), worldMatrix, alpha, ref shapeIndex, string.Concat(objArray1), false); if (!string.IsNullOrEmpty(breakableShape.Name) && (breakableShape.Name != "PineTree175m_v2_001")) { breakableShape.IsFixed(); } DebugShapesPositions[breakableShape.Name] = worldMatrix.Translation; List <HkdShapeInstanceInfo> list = new List <HkdShapeInstanceInfo>(); breakableShape.GetChildren(list); Vector3 coM = breakableShape.CoM; foreach (HkdShapeInstanceInfo info in list) { Matrix matrix = (info.GetTransform() * worldMatrix) * Matrix.CreateTranslation(Vector3.Right * 2f); DrawBreakableShape(info.Shape, matrix, alpha, ref shapeIndex, null, false); } }
private static void ConvertAllShapesToFractureComponentShapeBuilder(HkdBreakableShape shape, ref Matrix shapeRotation, MyBlockOrientation blockOrientation, HashSet <Tuple <string, float> > namesAndBuildProgress, MyObjectBuilder_FractureComponentCubeBlock fractureComponentBuilder, out float buildProgress) { buildProgress = 1f; string name = shape.Name; Tuple <string, float> tuple = null; foreach (Tuple <string, float> tuple2 in namesAndBuildProgress) { if (tuple2.Item1 == name) { tuple = tuple2; break; } } if ((tuple != null) && (new MyBlockOrientation(ref shapeRotation) == blockOrientation)) { MyObjectBuilder_FractureComponentBase.FracturedShape item = new MyObjectBuilder_FractureComponentBase.FracturedShape { Name = name, Fixed = MyDestructionHelper.IsFixed(shape) }; fractureComponentBuilder.Shapes.Add(item); buildProgress = tuple.Item2; } if (shape.GetChildrenCount() > 0) { List <HkdShapeInstanceInfo> list = new List <HkdShapeInstanceInfo>(); shape.GetChildren(list); foreach (HkdShapeInstanceInfo info in list) { float num; Matrix transform = info.GetTransform(); ConvertAllShapesToFractureComponentShapeBuilder(info.Shape, ref transform, blockOrientation, namesAndBuildProgress, fractureComponentBuilder, out num); if (tuple == null) { buildProgress = num; } } } }
/// <summary> /// /// </summary> /// <param name="shape">Piece takes ownership of shape so clone it first</param> /// <param name="worldMatrix"></param> /// <param name="definition"> without definition the piece wont save</param> /// <returns></returns> public static MyFracturedPiece CreateFracturePiece(HkdBreakableShape shape, ref MatrixD worldMatrix, bool isStatic, MyDefinitionId?definition, bool sync) { System.Diagnostics.Debug.Assert(Sync.IsServer, "Only on server"); var fracturedPiece = CreateFracturePiece(ref shape, ref worldMatrix, isStatic); if (definition.HasValue) { fracturedPiece.OriginalBlocks.Clear(); fracturedPiece.OriginalBlocks.Add(definition.Value); MyPhysicalModelDefinition def; if (MyDefinitionManager.Static.TryGetDefinition <MyPhysicalModelDefinition>(definition.Value, out def)) { fracturedPiece.Physics.MaterialType = def.PhysicalMaterial.Id.SubtypeId; } } else { fracturedPiece.Save = false; } // Check valid shapes from block definitions. if (fracturedPiece.Save && MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) { fracturedPiece.DebugCheckValidShapes(); } ProfilerShort.Begin("MyEntities.Add"); if (MyExternalReplicable.FindByObject(fracturedPiece) == null) { MyEntities.RaiseEntityCreated(fracturedPiece); } MyEntities.Add(fracturedPiece); ProfilerShort.End(); return(fracturedPiece); }
protected override void UnloadData() { Clusters.Dispose(); Clusters.OnClusterCreated -= OnClusterCreated; Clusters.OnClusterRemoved -= OnClusterRemoved; Clusters = null; if (MyFakes.ENABLE_HAVOK_MULTITHREADING) { m_threadPool.RemoveReference(); m_threadPool = null; m_jobQueue.Dispose(); m_jobQueue = null; } m_destructionQueue.Clear(); if (MyPerGameSettings.Destruction) { //Dispose material otherwise memory is corrupted on DS service and memory leaks HkdBreakableShape.DisposeSharedMaterial(); } }
private bool CheckVolumeMassRec(HkdBreakableShape bShape, float minVolume, float minMass) { if (bShape.Name.Contains("Fake")) return true; if (bShape.Volume <= minVolume) return false; HkMassProperties mp = new HkMassProperties(); bShape.BuildMassProperties(ref mp); if (mp.Mass <= minMass) return false; if (mp.InertiaTensor.M11 == 0 || mp.InertiaTensor.M22 == 0 || mp.InertiaTensor.M33 == 0) return false; for (int i = 0; i < bShape.GetChildrenCount(); i++) { if (!CheckVolumeMassRec(bShape.GetChildShape(i), minVolume, minMass)) return false; } return true; }
private void SetConvexRadius(HkdBreakableShape bShape, float radius) { var sh = bShape.GetShape(); if (sh.IsConvex) { var convex = (HkConvexShape)sh; if(convex.ConvexRadius > radius) convex.ConvexRadius = radius; return; } if (sh.IsContainer()) { HkShapeContainerIterator container = sh.GetContainer(); while (container.IsValid) { if (container.CurrentValue.IsConvex) { var convex = (HkConvexShape)container.CurrentValue; if (convex.ConvexRadius > radius) convex.ConvexRadius = radius; } container.Next(); } } }
private static bool DontCreateFracture(HkdBreakableShape breakableShape) { if (!breakableShape.IsValid()) return false; return (breakableShape.UserObject & (uint)HkdBreakableShape.Flags.DONT_CREATE_FRACTURE_PIECE) != 0; }
void FractureBreakableShape(HkdBreakableShape bShape, MyModelFractures modelFractures, string modPath) { HkdFracture fracture = null; HkReferenceObject geometry = null; if (modelFractures.Fractures[0] is RandomSplitFractureSettings) { var settings = (RandomSplitFractureSettings)modelFractures.Fractures[0]; fracture = new HkdRandomSplitFracture() { NumObjectsOnLevel1 = settings.NumObjectsOnLevel1, NumObjectsOnLevel2 = settings.NumObjectsOnLevel2, RandomRange = settings.RandomRange, RandomSeed1 = settings.RandomSeed1, RandomSeed2 = settings.RandomSeed2, SplitGeometryScale = Vector4.One }; if (!string.IsNullOrEmpty(settings.SplitPlane)) { var splitPlane = settings.SplitPlane; if (!string.IsNullOrEmpty(modPath)) splitPlane = Path.Combine(modPath, settings.SplitPlane); geometry = CreateGeometryFromSplitPlane(splitPlane); if (geometry != null) { ((HkdRandomSplitFracture)fracture).SetGeometry(geometry); VRageRender.MyRenderProxy.PreloadMaterials(splitPlane); } } } if (modelFractures.Fractures[0] is VoronoiFractureSettings) { var settings = (VoronoiFractureSettings)modelFractures.Fractures[0]; fracture = new HkdVoronoiFracture() { Seed = settings.Seed, NumSitesToGenerate = settings.NumSitesToGenerate, NumIterations = settings.NumIterations }; if (!string.IsNullOrEmpty(settings.SplitPlane)) { var splitPlane = settings.SplitPlane; if (!string.IsNullOrEmpty(modPath)) splitPlane = Path.Combine(modPath, settings.SplitPlane); geometry = CreateGeometryFromSplitPlane(splitPlane); var pspm = MyModels.GetModel(splitPlane); if (geometry != null) { ((HkdVoronoiFracture)fracture).SetGeometry(geometry); VRageRender.MyRenderProxy.PreloadMaterials(splitPlane); } } } if (modelFractures.Fractures[0] is WoodFractureSettings) { //TODO: Apply wood fracture algorithm var settings = (WoodFractureSettings)modelFractures.Fractures[0]; fracture = new HkdWoodFracture() { //Seed = settings.Seed, //NumSitesToGenerate = settings.NumSitesToGenerate, //NumIterations = settings.NumIterations }; //if (!string.IsNullOrEmpty(settings.SplitPlane)) //{ // var splitPlane = settings.SplitPlane; // if (!string.IsNullOrEmpty(modPath)) // splitPlane = Path.Combine(modPath, settings.SplitPlane); // geometry = CreateGeometryFromSplitPlane(splitPlane); // var pspm = MyModels.GetModel(splitPlane); // if (geometry != null) // { // ((HkdWoodFracture)fracture).SetGeometry(geometry); // VRageRender.MyRenderProxy.PreloadMaterials(splitPlane); // } //} } //if (woodButton.IsChecked) //{ // fracture = new HkdWoodFracture() // { // RandomSeed = 123456, // BoardSplittingData = new HkdWoodFracture.SplittingData() // { // }, // SplinterSplittingData = new HkdWoodFracture.SplittingData() // { // } // }; //} if (fracture != null) { Storage.FractureShape(bShape, fracture); fracture.Dispose(); } if (geometry != null) geometry.Dispose(); }
private void DrawBreakableShape(HkdBreakableShape breakableShape, MatrixD worldMatrix, float alpha, ref int shapeIndex, string customText = null, bool isPhantom = false) { //VRageRender.MyRenderProxy.DebugDrawText3D(worldMatrix.Translation, , Color.White, 1, false); DrawCollisionShape(breakableShape.GetShape(), worldMatrix, alpha, ref shapeIndex, breakableShape.Name + " Strength: " + breakableShape.GetStrenght() + " Static:" + breakableShape.IsFixed()); if (!string.IsNullOrEmpty(breakableShape.Name) && breakableShape.Name != "PineTree175m_v2_001" && breakableShape.IsFixed()) { } DebugShapesPositions[breakableShape.Name] = worldMatrix.Translation; List<HkdShapeInstanceInfo> children = new List<HkdShapeInstanceInfo>(); breakableShape.GetChildren(children); Vector3 parentCom = breakableShape.CoM; foreach (var shapeInst in children) { Matrix transform = shapeInst.GetTransform(); // transform.Translation += (shapeInst.Shape.CoM - parentCom); Matrix trWorld = transform * worldMatrix * Matrix.CreateTranslation(Vector3.Right * 2); DrawBreakableShape(shapeInst.Shape, trWorld, alpha, ref shapeIndex); } }
public static void ApplyImpulseToTreeFracture(ref MatrixD worldMatrix, ref Vector3 hitNormal, List<HkdShapeInstanceInfo> shapeList, ref HkdBreakableShape compound, MyFracturedPiece fp, float forceMultiplier = 1.0f) { float mass = compound.GetMass(); Vector3 coMMaxY = Vector3.MinValue; shapeList.ForEach(s => coMMaxY = (s.CoM.Y > coMMaxY.Y) ? s.CoM : coMMaxY); Vector3 forceVector = hitNormal; forceVector.Y = 0; forceVector.Normalize(); Vector3 force = 0.3f * forceMultiplier * mass * forceVector; fp.Physics.Enabled = true;//so we get the body in world Vector3 worldForcePoint = fp.Physics.WorldToCluster(Vector3D.Transform(coMMaxY, worldMatrix)); fp.Physics.RigidBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; fp.Physics.RigidBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; fp.Physics.RigidBody.ApplyPointImpulse(force, worldForcePoint); }
public override void SetShape(HkdBreakableShape shape, bool compound) { base.SetShape(shape, compound); 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); }
private static void ConnectPiecesInBlock(HkdBreakableShape parent, List<HkdShapeInstanceInfo> shapeList) { for (int i = 0; i < shapeList.Count; i++) { for (int j = 0; j < shapeList.Count; j++) { if (i == j) continue; MyGridShape.ConnectShapesWithChildren(parent, shapeList[i].Shape, shapeList[j].Shape); } } }
public static void CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List<HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren) { bool containsFixedChildren = false; if (canContainFixedChildren) { foreach (var shapeInst in shapeList) { shapeInst.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); var t = worldMatrix.Translation + worldMatrix.Up * 1.5f; var o = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(shapeInst.Shape.GetShape(), ref t, ref o, m_tmpResults, MyPhysics.DefaultCollisionLayer); bool flagSet = false; foreach (var res in m_tmpResults) { var entity = res.GetCollisionEntity(); if (entity is MyVoxelMap) { shapeInst.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); containsFixedChildren = true; flagSet = true; break; } if (flagSet) break; } m_tmpResults.Clear(); } } HkdBreakableShape compound = new HkdCompoundBreakableShape(oldBreakableShape, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); //compound.SetMassRecursively(500); //compound.SetStrenghtRecursively(5000, 0.7f); var fp = MyDestructionHelper.CreateFracturePiece(compound, MyPhysics.SingleWorld.DestructionWorld, ref worldMatrix, containsFixedChildren, itemDefinition.Id, true); if (fp != null && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref compound, fp, forceMultiplier); fp.Physics.ForceActivate(); } }
/// <summary> /// Searches for blocks which will create fracture components from cached m_fracturedSlimBlocksShapes /// </summary> private void FindFractureComponentBlocks() { Debug.Assert(MyFakes.ENABLE_FRACTURE_COMPONENT); foreach (var pair in m_fracturedSlimBlocksShapes) { var slimBlock = pair.Key; var shapeList = pair.Value; if (slimBlock.FatBlock.Components.Has<MyFractureComponentBase>()) { // Block has fracture component - ignore continue; } else { int totalBreakableShapesCountForModel = slimBlock.GetTotalBreakableShapeChildrenCount(); Debug.Assert(shapeList.Count <= totalBreakableShapesCountForModel); // No removed pieces? Then ignore. if (slimBlock.BlockDefinition.CreateFracturedPieces && totalBreakableShapesCountForModel == shapeList.Count) continue; foreach (var s in shapeList) { s.SetTransform(ref Matrix.Identity); } ProfilerShort.Begin("CreateShapeComponent"); HkdBreakableShape compound = new HkdCompoundBreakableShape(null, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); HkdBreakableShape shape = compound; var sh = compound.GetShape(); shape = new HkdBreakableShape(sh, ref mp); //shape.SetMassProperties(mp); //important! pass mp to constructor foreach (var si in shapeList) { var siRef = si; shape.AddShape(ref siRef); } compound.RemoveReference(); ProfilerShort.BeginNextBlock("Connect"); //shape.SetChildrenParent(shape); ConnectPiecesInBlock(shape, shapeList); MyFractureComponentBase.Info info = new MyFractureComponentBase.Info() { Entity = slimBlock.FatBlock, Shape = shape, Compound = true }; m_fractureBlockComponentsCache.Add(info); ProfilerShort.End(); } } m_fracturedSlimBlocksShapes.Clear(); }
private void FindFracturedBlocks(HkdBreakableBodyInfo b) { ProfilerShort.Begin("DBHelper"); var dbHelper = new HkdBreakableBodyHelper(b); ProfilerShort.BeginNextBlock("GetRBMatrix"); var bodyMatrix = dbHelper.GetRigidBodyMatrix(); ProfilerShort.BeginNextBlock("SearchChildren"); dbHelper.GetChildren(m_children); foreach (var child in m_children) { if (!child.IsFracturePiece()) continue; //var blockPosWorld = ClusterToWorld(Vector3.Transform(child.GetTransform().Translation, bodyMatrix)); var bShape = child.Shape; HkVec3IProperty pProp = bShape.GetProperty(HkdBreakableShape.PROPERTY_GRID_POSITION); var blockPos = pProp.Value; //Vector3I.Round(child.GetTransform().Translation / m_grid.GridSize); if (!m_grid.CubeExists(blockPos)) { //Debug.Fail("FindFracturedBlocks:Fracture piece missing block");//safe to ignore continue; } if (MyFakes.ENABLE_FRACTURE_COMPONENT) { var block = m_grid.GetCubeBlock(blockPos); if (block == null) continue; if (!FindFractureComponentBlocks(block, child)) continue; } else { if (!m_fracturedBlocksShapes.ContainsKey(blockPos)) m_fracturedBlocksShapes[blockPos] = new List<HkdShapeInstanceInfo>(); m_fracturedBlocksShapes[blockPos].Add(child); } } ProfilerShort.BeginNextBlock("CreateFreacturedBlocks"); if (!MyFakes.ENABLE_FRACTURE_COMPONENT) { foreach (var key in m_fracturedBlocksShapes.Keys) { HkdBreakableShape shape; var shapeList = m_fracturedBlocksShapes[key]; foreach (var s in shapeList) { var matrix = s.GetTransform(); matrix.Translation = Vector3.Zero; s.SetTransform(ref matrix); } ProfilerShort.Begin("CreateShape"); HkdBreakableShape compound = new HkdCompoundBreakableShape(null, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); shape = compound; var sh = compound.GetShape(); shape = new HkdBreakableShape(sh, ref mp); //shape.SetMassProperties(mp); //important! pass mp to constructor foreach (var si in shapeList) { var siRef = si; shape.AddShape(ref siRef); } compound.RemoveReference(); ProfilerShort.BeginNextBlock("Connect"); //shape.SetChildrenParent(shape); ConnectPiecesInBlock(shape, shapeList); ProfilerShort.End(); var info = new MyFracturedBlock.Info() { Shape = shape, Position = key, Compound = true, }; var originalBlock = m_grid.GetCubeBlock(key); if (originalBlock == null) { //Debug.Fail("Missing fracture piece original block.");//safe to ignore shape.RemoveReference(); continue; } Debug.Assert(originalBlock != null); if (originalBlock.FatBlock is MyFracturedBlock) { var fractured = originalBlock.FatBlock as MyFracturedBlock; info.OriginalBlocks = fractured.OriginalBlocks; info.Orientations = fractured.Orientations; info.MultiBlocks = fractured.MultiBlocks; } else if (originalBlock.FatBlock is MyCompoundCubeBlock) { info.OriginalBlocks = new List<MyDefinitionId>(); info.Orientations = new List<MyBlockOrientation>(); MyCompoundCubeBlock compoundBlock = originalBlock.FatBlock as MyCompoundCubeBlock; bool hasMultiBlockPart = false; var blocksInCompound = compoundBlock.GetBlocks(); foreach (var block in blocksInCompound) { info.OriginalBlocks.Add(block.BlockDefinition.Id); info.Orientations.Add(block.Orientation); hasMultiBlockPart = hasMultiBlockPart || block.IsMultiBlockPart; } if (hasMultiBlockPart) { info.MultiBlocks = new List<MyFracturedBlock.MultiBlockPartInfo>(); foreach (var block in blocksInCompound) { if (block.IsMultiBlockPart) info.MultiBlocks.Add(new MyFracturedBlock.MultiBlockPartInfo() { MultiBlockDefinition = block.MultiBlockDefinition.Id, MultiBlockId = block.MultiBlockId }); else info.MultiBlocks.Add(null); } } } else { info.OriginalBlocks = new List<MyDefinitionId>(); info.Orientations = new List<MyBlockOrientation>(); info.OriginalBlocks.Add(originalBlock.BlockDefinition.Id); info.Orientations.Add(originalBlock.Orientation); if (originalBlock.IsMultiBlockPart) { info.MultiBlocks = new List<MyFracturedBlock.MultiBlockPartInfo>(); info.MultiBlocks.Add(new MyFracturedBlock.MultiBlockPartInfo() { MultiBlockDefinition = originalBlock.MultiBlockDefinition.Id, MultiBlockId = originalBlock.MultiBlockId }); } } m_fractureBlocksCache.Add(info); } } m_fracturedBlocksShapes.Clear(); m_children.Clear(); ProfilerShort.End(); }
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 DisableRefCountRec(HkdBreakableShape bShape) { bShape.DisableRefCount(); var lst = new List<HkdShapeInstanceInfo>(); bShape.GetChildren(lst); foreach (var child in lst) DisableRefCountRec(child.Shape); }
private HkdBreakableShape AddMountForShape(HkdBreakableShape shape, Matrix transform, ref BoundingBox blockBB) { Vector4 min; Vector4 max; shape.GetShape().GetLocalAABB(0.01f, out min, out max);//.Transform(CubeGrid.PositionComp.WorldMatrix); var bb = new BoundingBox(new Vector3(min), new Vector3(max)); bb = bb.Transform(transform); bb.Min /= CubeGrid.GridSize; //normalize for mount point bb.Max /= CubeGrid.GridSize; bb.Inflate(0.04f);//add tolerance (fracture shapes are smaller than block) bb.Min += blockBB.HalfExtents; bb.Max += blockBB.HalfExtents; if (blockBB.Contains(bb) == ContainmentType.Intersects) { bb.Inflate(-0.04f); foreach (var directionEnum in Base6Directions.EnumDirections) { int dirEnum = (int)directionEnum; Vector3 direction = Base6Directions.Directions[dirEnum]; Vector3 absDir = Vector3.Abs(direction); var mp = new MyCubeBlockDefinition.MountPoint(); mp.Start = bb.Min; mp.End = bb.Max; var start = mp.Start * absDir / (blockBB.HalfExtents * 2) - absDir * 0.04f; var end = mp.End * absDir / (blockBB.HalfExtents * 2) + absDir * 0.04f; bool add = false; bool one = false; if (start.Max() < 1 && end.Max() > 1 && direction.Max() > 0) { add = true; one = true; } else if (start.Min() < 0 && end.Max() > 0 && direction.Min() < 0) { add = true; } if (!add) { continue; } mp.Start -= mp.Start * absDir - absDir * 0.04f; mp.End -= mp.End * absDir + absDir * 0.04f; if (one) { mp.Start += absDir * blockBB.HalfExtents * 2; mp.End += absDir * blockBB.HalfExtents * 2; } mp.Start -= blockBB.HalfExtents - Vector3.One / 2; mp.End -= blockBB.HalfExtents - Vector3.One / 2; mp.Normal = new Vector3I(direction); MountPoints.Add(mp); } } return shape; }
private void CreatePieceData(MyModel model, HkdBreakableShape breakableShape) { //Root shape for fractured compound blocks { var msg = VRageRender.MyRenderProxy.PrepareAddRuntimeModel(); ProfilerShort.Begin("GetDataFromShape"); m_tmpMesh.Data = msg.ModelData; MyDestructionData.Static.Storage.GetDataFromShape(breakableShape, m_tmpMesh); System.Diagnostics.Debug.Assert(msg.ModelData.Sections.Count > 0, "Invalid data"); if (msg.ModelData.Sections.Count > 0) { if(MyFakes.USE_HAVOK_MODELS) msg.ReplacedModel = model.AssetName; VRageRender.MyRenderProxy.AddRuntimeModel(breakableShape.ShapeName, msg); } ProfilerShort.End(); } using (m_tmpChildrenList.GetClearToken()) { breakableShape.GetChildren(m_tmpChildrenList); LoadChildrenShapes(m_tmpChildrenList); } }
private void DrawConnections(HkdBreakableShape breakableShape, MatrixD worldMatrix, float alpha, ref int shapeIndex, string customText = null, bool isPhantom = false) { List<HkdConnection> connections = new List<HkdConnection>(); breakableShape.GetConnectionList(connections); List<HkdShapeInstanceInfo> children = new List<HkdShapeInstanceInfo>(); breakableShape.GetChildren(children); foreach (var conn in connections) { var posA = DebugShapesPositions[conn.ShapeAName]; var posB = DebugShapesPositions[conn.ShapeBName]; bool cont = false; foreach (var child in children) { if ((child.ShapeName == conn.ShapeAName) || (child.ShapeName == conn.ShapeBName)) cont = true; } if (cont) VRageRender.MyRenderProxy.DebugDrawLine3D(posA, posB, Color.White, Color.White, false); } }
/// <summary> /// /// </summary> /// <param name="shape">Piece takes ownership of shape so clone it first</param> /// <param name="worldMatrix"></param> /// <param name="definition"> without definition the piece wont save</param> /// <returns></returns> public static MyFracturedPiece CreateFracturePiece(HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic, MyDefinitionId? definition, bool sync) { System.Diagnostics.Debug.Assert(Sync.IsServer, "Only on server"); var fracturedPiece = CreateFracturePiece(ref shape, world, ref worldMatrix, isStatic); if (definition.HasValue) { fracturedPiece.OriginalBlocks.Clear(); fracturedPiece.OriginalBlocks.Add(definition.Value); MyPhysicalModelDefinition def; if (MyDefinitionManager.Static.TryGetDefinition<MyPhysicalModelDefinition>(definition.Value, out def)) fracturedPiece.Physics.MaterialType = def.PhysicalMaterial.Id.SubtypeId; } else fracturedPiece.Save = false; if (sync) MySyncDestructions.CreateFracturePiece((Sandbox.Common.ObjectBuilders.MyObjectBuilder_FracturedPiece)fracturedPiece.GetObjectBuilder()); return fracturedPiece; }
public static void CreateFracturePiece(MyEnvironmentItemDefinition itemDefinition, HkdBreakableShape oldBreakableShape, MatrixD worldMatrix, Vector3 hitNormal, List <HkdShapeInstanceInfo> shapeList, float forceMultiplier, bool canContainFixedChildren, string fallSound = "") { bool containsFixedChildren = false; if (canContainFixedChildren) { foreach (var shapeInst in shapeList) { shapeInst.Shape.SetMotionQualityRecursively(HkdBreakableShape.BodyQualityType.QUALITY_DEBRIS); var t = worldMatrix.Translation + worldMatrix.Up * 1.5f; var o = Quaternion.CreateFromRotationMatrix(worldMatrix.GetOrientation()); MyPhysics.GetPenetrationsShape(shapeInst.Shape.GetShape(), ref t, ref o, m_tmpResults, MyPhysics.CollisionLayers.DefaultCollisionLayer); bool flagSet = false; foreach (var res in m_tmpResults) { var entity = res.GetCollisionEntity(); if (entity is MyVoxelMap) { shapeInst.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); containsFixedChildren = true; flagSet = true; break; } if (flagSet) { break; } } m_tmpResults.Clear(); } } HkdBreakableShape compound = new HkdCompoundBreakableShape(oldBreakableShape, shapeList); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); //compound.SetMassRecursively(500); //compound.SetStrenghtRecursively(5000, 0.7f); var fp = MyDestructionHelper.CreateFracturePiece(compound, MyPhysics.SingleWorld.DestructionWorld, ref worldMatrix, containsFixedChildren, itemDefinition.Id, true); if (fp != null && !canContainFixedChildren) { ApplyImpulseToTreeFracture(ref worldMatrix, ref hitNormal, shapeList, ref compound, fp, forceMultiplier); fp.Physics.ForceActivate(); if (fallSound.Length > 0) { fp.StartFallSound(fallSound); } } }
/// <summary> /// /// </summary> /// <param name="shape">Piece takes ownership of shape so clone it first</param> /// <param name="worldMatrix"></param> /// <param name="definition"> without definition the piece wont save</param> /// <returns></returns> public static MyFracturedPiece CreateFracturePiece(HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic, MyDefinitionId? definition, bool sync) { System.Diagnostics.Debug.Assert(Sync.IsServer, "Only on server"); var fracturedPiece = CreateFracturePiece(ref shape, world, ref worldMatrix, isStatic); if (definition.HasValue) { fracturedPiece.OriginalBlocks.Clear(); fracturedPiece.OriginalBlocks.Add(definition.Value); MyPhysicalModelDefinition def; if (MyDefinitionManager.Static.TryGetDefinition<MyPhysicalModelDefinition>(definition.Value, out def)) fracturedPiece.Physics.MaterialType = def.PhysicalMaterial.Id.SubtypeId; } else fracturedPiece.Save = false; // Check valid shapes from block definitions. if (fracturedPiece.Save && MyFakes.ENABLE_FRACTURE_PIECE_SHAPE_CHECK) fracturedPiece.DebugCheckValidShapes(); ProfilerShort.Begin("MyEntities.Add"); MyEntities.RaiseEntityCreated(fracturedPiece); MyEntities.Add(fracturedPiece); ProfilerShort.End(); return fracturedPiece; }
private static void GetAllBlockBreakableShapeNames(HkdBreakableShape shape, HashSet<string> outNames) { var name = shape.Name; if (!string.IsNullOrEmpty(name)) outNames.Add(name); if (shape.GetChildrenCount() > 0) { List<HkdShapeInstanceInfo> children = new List<HkdShapeInstanceInfo>(); shape.GetChildren(children); foreach (var child in children) GetAllBlockBreakableShapeNames(child.Shape, outNames); } }
private static void ConvertAllShapesToFractureComponentShapeBuilder(HkdBreakableShape shape, ref Matrix shapeRotation, MyBlockOrientation blockOrientation, HashSet<string> names, MyObjectBuilder_FractureComponentCubeBlock fractureComponentBuilder) { var name = shape.Name; if (names.Contains(name)) { MyBlockOrientation shapeOrientation = new MyBlockOrientation(ref shapeRotation); if (shapeOrientation == blockOrientation) { MyObjectBuilder_FractureComponentCubeBlock.FracturedShape builderShape = new MyObjectBuilder_FractureComponentBase.FracturedShape(); builderShape.Name = name; builderShape.Fixed = MyDestructionHelper.IsFixed(shape); fractureComponentBuilder.Shapes.Add(builderShape); } } if (shape.GetChildrenCount() > 0) { List<HkdShapeInstanceInfo> children = new List<HkdShapeInstanceInfo>(); shape.GetChildren(children); foreach (var child in children) { var childShapeRotation = child.GetTransform(); ConvertAllShapesToFractureComponentShapeBuilder(child.Shape, ref childShapeRotation, blockOrientation, names, fractureComponentBuilder); } } }
public static void ApplyImpulseToTreeFracture(ref MatrixD worldMatrix, ref Vector3 hitNormal, List <HkdShapeInstanceInfo> shapeList, ref HkdBreakableShape compound, MyFracturedPiece fp, float forceMultiplier = 1.0f) { float mass = compound.GetMass(); Vector3 coMMaxY = Vector3.MinValue; shapeList.ForEach(s => coMMaxY = (s.CoM.Y > coMMaxY.Y) ? s.CoM : coMMaxY); Vector3 forceVector = hitNormal; forceVector.Y = 0; forceVector.Normalize(); Vector3 force = 0.3f * forceMultiplier * mass * forceVector; fp.Physics.Enabled = true;//so we get the body in world Vector3 worldForcePoint = fp.Physics.WorldToCluster(Vector3D.Transform(coMMaxY, worldMatrix)); fp.Physics.RigidBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; fp.Physics.RigidBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; fp.Physics.RigidBody.ApplyPointImpulse(force, worldForcePoint); }
protected override void CreateBody(ref HkShape shape, HkMassProperties? massProperties) { if (MyPerGameSettings.Destruction)// && shape.ShapeType == HkShapeType.StaticCompound) { ProfilerShort.Begin("CreateGridBody"); HkdBreakableShape breakable; HkMassProperties massProps = massProperties.HasValue ? massProperties.Value : new HkMassProperties(); if (!Shape.BreakableShape.IsValid()) Shape.CreateBreakableShape(); breakable = Shape.BreakableShape; if (!breakable.IsValid()) { breakable = new HkdBreakableShape(shape); if (massProperties.HasValue) { var mp = massProperties.Value; breakable.SetMassProperties(ref mp); } else breakable.SetMassRecursively(50); } else breakable.BuildMassProperties(ref massProps); shape = breakable.GetShape(); //doesnt add reference HkRigidBodyCinfo rbInfo = new HkRigidBodyCinfo(); rbInfo.AngularDamping = m_angularDamping; rbInfo.LinearDamping = m_linearDamping; rbInfo.SolverDeactivation = m_grid.IsStatic ? InitialSolverDeactivation : HkSolverDeactivation.Low; rbInfo.ContactPointCallbackDelay = ContactPointDelay; rbInfo.Shape = shape; rbInfo.SetMassProperties(massProps); //rbInfo.Position = Entity.PositionComp.GetPosition(); //obsolete with large worlds? GetInfoFromFlags(rbInfo, Flags); HkRigidBody rb = new HkRigidBody(rbInfo); rb.EnableDeactivation = true; BreakableBody = new HkdBreakableBody(breakable, rb, MyPhysics.SingleWorld.DestructionWorld, Matrix.Identity); //DestructionBody.ConnectToWorld(HavokWorld, 0.05f); BreakableBody.AfterReplaceBody += FracturedBody_AfterReplaceBody; //RigidBody.SetWorldMatrix(Entity.PositionComp.WorldMatrix); //breakable.Dispose(); ProfilerShort.End(); } else { base.CreateBody(ref shape, massProperties); } }
private static MyFracturedPiece CreateFracturePiece(ref HkdBreakableShape shape, HkdWorld world, ref MatrixD worldMatrix, bool isStatic) { Debug.Assert(shape.IsValid()); ProfilerShort.Begin("CreateFracturePiece"); var fracturedPiece = MyFracturedPiecesManager.Static.GetPieceFromPool(0);//new MyFracturedPiece(); fracturedPiece.PositionComp.WorldMatrix = worldMatrix; fracturedPiece.Physics.Flags = isStatic ? RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS; var physicsBody = fracturedPiece.Physics as MyPhysicsBody;//new MyPhysicsBody(fracturedPiece,isFixed ?RigidBodyFlag.RBF_STATIC : RigidBodyFlag.RBF_DEBRIS); HkMassProperties mp = new HkMassProperties(); shape.BuildMassProperties(ref mp); physicsBody.InitialSolverDeactivation = HkSolverDeactivation.High; physicsBody.CreateFromCollisionObject(shape.GetShape(), Vector3.Zero, worldMatrix, mp); physicsBody.LinearDamping = MyPerGameSettings.DefaultLinearDamping; physicsBody.AngularDamping = MyPerGameSettings.DefaultAngularDamping; System.Diagnostics.Debug.Assert(physicsBody.BreakableBody == null, "physicsBody.DestructionBody == null"); physicsBody.BreakableBody = new HkdBreakableBody(shape, physicsBody.RigidBody, world, worldMatrix); physicsBody.BreakableBody.AfterReplaceBody += physicsBody.FracturedBody_AfterReplaceBody; ProfilerShort.End(); ProfilerShort.Begin("Sync"); if (fracturedPiece.SyncFlag) { fracturedPiece.CreateSync(); } ProfilerShort.End(); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; //physicsBody.RigidBody.ContactPointCallbackDelay = 0; //physicsBody.RigidBody.ContactPointCallbackEnabled = true; fracturedPiece.Physics = physicsBody; //FixPosition(fracturedPiece); fracturedPiece.SetDataFromHavok(shape); ProfilerShort.Begin("AddToWorld"); fracturedPiece.NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; shape.RemoveReference(); ProfilerShort.End(); return fracturedPiece; }
private static bool IsBreakableShapeCompound(HkdBreakableShape shape) { return (string.IsNullOrEmpty(shape.Name) || shape.IsCompound() || shape.GetChildrenCount() > 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(); return; } OriginalBlocks = new List<MyDefinitionId>(); Orientations = new List<MyBlockOrientation>(); var lst = new List<HkdShapeInstanceInfo>(); foreach (var def in ob.BlockDefinitions) { var blockDef = MyDefinitionManager.Static.GetCubeBlockDefinition(def); if (MyModels.GetModelOnlyData(blockDef.Model).HavokBreakableShapes == null) { MyDestructionData.Static.LoadModelDestruction(blockDef, false, Vector3.One); } var shape = MyModels.GetModelOnlyData(blockDef.Model).HavokBreakableShapes[0]; var si = new HkdShapeInstanceInfo(shape, null, null); lst.Add(si); m_children.Add(si); shape.GetChildren(m_children); OriginalBlocks.Add(def); } foreach (var or in ob.BlockOrientations) { Orientations.Add(or); } m_shapes.AddRange(ob.Shapes); for (int i = 0; i < m_children.Count; i++) { var child = m_children[i]; Func<MyObjectBuilder_FracturedBlock.ShapeB, bool> x = s => s.Name == child.ShapeName; var result = m_shapes.Where(x); if (result.Count() > 0) { var found = result.First(); var m = Matrix.CreateFromQuaternion(found.Orientation); m.Translation = child.GetTransform().Translation; var si = new HkdShapeInstanceInfo(child.Shape.Clone(), m); if(found.Fixed) si.Shape.SetFlagRecursively(HkdBreakableShape.Flags.IS_FIXED); lst.Add(si); m_shapeInfos.Add(si); m_shapes.Remove(found); } else { child.GetChildren(m_children); } } if (m_shapeInfos.Count == 0) { m_children.Clear(); ProfilerShort.End(); Debug.Fail("No relevant shape was found for fractured block. It was probably reexported and names changed."); throw new Exception("No relevant shape was found for fractured block. It was probably reexported and names changed."); } foreach (var shape in m_shapeInfos) { if(! string.IsNullOrEmpty(shape.Shape.Name)) Render.AddPiece(shape.Shape.Name, Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(shape.GetTransform().GetOrientation()))); } if (CubeGrid.CreatePhysics) { HkdBreakableShape compound = new HkdCompoundBreakableShape(null, m_shapeInfos); ((HkdCompoundBreakableShape)compound).RecalcMassPropsFromChildren(); Shape = compound; var mp = new HkMassProperties(); compound.BuildMassProperties(ref mp); Shape = new HkdBreakableShape(compound.GetShape(), ref mp); compound.RemoveReference(); foreach (var si in m_shapeInfos) { var siRef = si; Shape.AddShape(ref siRef); } Shape.SetStrenght(MyDestructionConstants.STRENGTH); CreateMountPoints(); } m_children.Clear(); foreach (var si in m_shapeInfos) si.Shape.RemoveReference(); foreach (var si in lst) si.RemoveReference(); m_shapeInfos.Clear(); ProfilerShort.End(); }
private HkShape CreateBreakableBody(HkShape shape, HkMassProperties? massProperties) { ProfilerShort.Begin("CreateGridBody"); HkdBreakableShape breakable; HkMassProperties massProps = massProperties.HasValue ? massProperties.Value : new HkMassProperties(); if (!Shape.BreakableShape.IsValid()) Shape.CreateBreakableShape(); breakable = Shape.BreakableShape; if (!breakable.IsValid()) { breakable = new HkdBreakableShape(shape); if (massProperties.HasValue) { var mp = massProperties.Value; breakable.SetMassProperties(ref mp); } else breakable.SetMassRecursively(50); } else breakable.BuildMassProperties(ref massProps); shape = breakable.GetShape(); //doesnt add reference HkRigidBodyCinfo rbInfo = new HkRigidBodyCinfo(); rbInfo.AngularDamping = m_angularDamping; rbInfo.LinearDamping = m_linearDamping; rbInfo.SolverDeactivation = m_grid.IsStatic ? InitialSolverDeactivation : HkSolverDeactivation.Low; rbInfo.ContactPointCallbackDelay = ContactPointDelay; rbInfo.Shape = shape; rbInfo.SetMassProperties(massProps); //rbInfo.Position = Entity.PositionComp.GetPosition(); //obsolete with large worlds? GetInfoFromFlags(rbInfo, Flags); if (m_grid.IsStatic) { rbInfo.MotionType = HkMotionType.Dynamic; rbInfo.QualityType = HkCollidableQualityType.Moving; } HkRigidBody rb = new HkRigidBody(rbInfo); if (m_grid.IsStatic) { rb.UpdateMotionType(HkMotionType.Fixed); } rb.EnableDeactivation = true; BreakableBody = new HkdBreakableBody(breakable, rb, null, Matrix.Identity); //DestructionBody.ConnectToWorld(HavokWorld, 0.05f); BreakableBody.AfterReplaceBody += FracturedBody_AfterReplaceBody; //RigidBody.SetWorldMatrix(Entity.PositionComp.WorldMatrix); //breakable.Dispose(); ProfilerShort.End(); return shape; }