private bool SteeringLogic() { Vector3 vector2; Color? nullable; if (!base.IsFunctional) { return(false); } MyGridPhysics physics = base.CubeGrid.Physics; if (physics == null) { return(false); } if ((base.Stator != null) && MyFixedGrids.IsRooted(base.Stator.CubeGrid)) { return(false); } if (this.m_slipCountdown > 0) { this.m_slipCountdown--; } if (this.m_staticHitCount == 0) { if (this.m_contactCountdown <= 0) { return(false); } this.m_contactCountdown--; if (this.m_contactCountdown == 0) { this.m_frictionCollector = 0f; this.m_contactNormals.Clear(); return(false); } } Vector3 linearVelocity = physics.LinearVelocity; if (MyUtils.IsZero(ref linearVelocity, 1E-05f) || !physics.IsActive) { return(false); } MatrixD worldMatrix = base.WorldMatrix; Vector3D centerOfMassWorld = physics.CenterOfMassWorld; if (!this.m_contactNormals.GetAvgNormal(out vector2)) { return(false); } this.LastUsedGroundNormal = vector2; Vector3 up = (Vector3)worldMatrix.Up; Vector3 guideVector = Vector3.Cross(vector2, up); linearVelocity = Vector3.ProjectOnPlane(ref linearVelocity, ref vector2); Vector3 direction = Vector3.ProjectOnVector(ref linearVelocity, ref guideVector); Vector3 vector6 = direction - linearVelocity; if (MyUtils.IsZero(ref vector6, 1E-05f)) { return(false); } bool flag = false; bool flag2 = false; float num = 6f * this.m_frictionCollector; Vector3 vec = Vector3.ProjectOnVector(ref vector6, ref up); float num2 = vec.Length(); bool flag3 = num2 > num; if (!flag3 && (this.m_slipCountdown == 0)) { if (num2 < 0.1) { flag2 = true; } } else { flag = true; vec = (vec * ((1f / num2) * num)) * (1f - MyPhysicsConfig.WheelSlipCutAwayRatio); if (flag3) { this.m_slipCountdown = MyPhysicsConfig.WheelSlipCountdown; } } if (!flag2) { vec *= 1f - ((1f - this.m_frictionCollector) * MyPhysicsConfig.WheelSurfaceMaterialSteerRatio); Vector3 vector9 = Vector3.ProjectOnPlane(ref vec, ref vector2); MyMechanicalConnectionBlockBase stator = base.Stator; MyPhysicsBody body = null; if (stator != null) { body = base.Stator.CubeGrid.Physics; } vector9 *= 0.1f; if (body == null) { physics.ApplyImpulse(vector9 * physics.Mass, centerOfMassWorld); } else { Vector3D zero = Vector3D.Zero; MyMotorSuspension suspension = stator as MyMotorSuspension; if (suspension != null) { Vector3 vector10; vector9 *= MyMath.Clamp(suspension.Friction * 2f, 0f, 1f); suspension.GetCoMVectors(out vector10); zero = Vector3D.TransformNormal(-vector10, stator.CubeGrid.WorldMatrix); } Vector3D pos = centerOfMassWorld + zero; float wheelImpulseBlending = MyPhysicsConfig.WheelImpulseBlending; vector9 = (this.m_lastFrameImpuse * wheelImpulseBlending) + (vector9 * (1f - wheelImpulseBlending)); this.m_lastFrameImpuse = vector9; body.ApplyImpulse(vector9 * body.Mass, pos); if (MyDebugDrawSettings.DEBUG_DRAW_WHEEL_PHYSICS) { nullable = null; MyRenderProxy.DebugDrawArrow3DDir(pos, -zero, Color.Red, nullable, false, 0.1, null, 0.5f, false); MyRenderProxy.DebugDrawSphere(pos, 0.1f, Color.Yellow, 1f, false, false, true, false); } } } if (MyDebugDrawSettings.DEBUG_DRAW_WHEEL_PHYSICS) { nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld, linearVelocity, Color.Yellow, nullable, false, 0.1, null, 0.5f, false); nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld, direction, Color.Blue, nullable, false, 0.1, null, 0.5f, false); nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld, vec, Color.MediumPurple, nullable, false, 0.1, null, 0.5f, false); nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld + linearVelocity, vector6, Color.Red, nullable, false, 0.1, null, 0.5f, false); nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld + up, vector2, Color.AliceBlue, nullable, false, 0.1, null, 0.5f, false); nullable = null; MyRenderProxy.DebugDrawArrow3DDir(centerOfMassWorld, Vector3.ProjectOnPlane(ref vec, ref vector2), flag ? Color.DarkRed : Color.IndianRed, nullable, false, 0.1, null, 0.5f, false); if (this.m_slipCountdown > 0) { MyRenderProxy.DebugDrawText3D(centerOfMassWorld + (up * 2f), "Drift", Color.Red, 1f, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, -1, false); } MyRenderProxy.DebugDrawText3D(centerOfMassWorld + (up * 1.2f), this.m_staticHitCount.ToString(), Color.Red, 1f, false, MyGuiDrawAlignEnum.HORISONTAL_LEFT_AND_VERTICAL_TOP, -1, false); } return(!flag2); }
private MyAttachableTopBlockBase FindMatchingTop() { Debug.Assert(CubeGrid != null); Debug.Assert(m_penetrations != null); Debug.Assert(CubeGrid.Physics != null); if (CubeGrid == null) { MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): Cube grid == null!"); return(null); } if (m_penetrations == null) { MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): penetrations cache == null!"); return(null); } if (CubeGrid.Physics == null) { MySandboxGame.Log.WriteLine("MyPistonBase.FindMatchingTop(): Cube grid physics == null!"); return(null); } Quaternion orientation; Vector3D pos; Vector3 halfExtents; ComputeTopQueryBox(out pos, out halfExtents, out orientation); try { MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref orientation, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); foreach (var obj in m_penetrations) { var entity = obj.GetCollisionEntity(); if (entity == null || entity == CubeGrid) { continue; } MyAttachableTopBlockBase top = FindTopInGrid(entity, pos); if (top != null) { return(top); } MyPhysicsBody body = entity.Physics as MyPhysicsBody; if (body != null) { foreach (var child in body.WeldInfo.Children) { top = FindTopInGrid(child.Entity, pos); if (top != null) { return(top); } } } } } catch (Exception ex) { } finally { m_penetrations.Clear(); } return(null); }
private void InitInternal() { // TODO: This will be fixed and made much more simple once ore models are done // https://app.asana.com/0/6594565324126/10473934569658 var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content); string model = physicalItem.Model; VoxelMaterial = null; float scale = 1.0f; if (Item.Content is MyObjectBuilder_Ore) { string oreSubTypeId = physicalItem.Id.SubtypeId.ToString(); foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if (oreSubTypeId == mat.MinedOre) { VoxelMaterial = mat; model = MyDebris.GetRandomDebrisVoxel(); scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); break; } } scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); } if (scale < 0.05f) { Close(); } else if (scale < 0.15f) { scale = 0.15f; } FormatDisplayName(m_displayedText, Item); Init(m_displayedText, model, null, null, null); PositionComp.Scale = scale; // Must be set after init var massProperties = new HkMassProperties(); HkShape shape = GetPhysicsShape(physicalItem.Mass * (float)Item.Amount, scale, out massProperties); var scaleMatrix = Matrix.CreateScale(scale); HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None); if (Physics != null) { Physics.Close(); } Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.FloatingObjectCollisionLayer); Physics.MaterialType = VoxelMaterial != null ? MyMaterialType.ROCK : MyMaterialType.METAL; Physics.Enabled = true; transform.Base.RemoveReference(); Physics.PlayCollisionCueEnabled = true; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; }
private void InitInternal() { // TODO: This will be fixed and made much more simple once ore models are done // https://app.asana.com/0/6594565324126/10473934569658 var itemDefinition = MyDefinitionManager.Static.GetPhysicalItemDefinition(Item.Content); m_health = itemDefinition.Health; // Setting voxel material (if applicable) VoxelMaterial = null; if (itemDefinition.VoxelMaterial != MyStringHash.NullOrEmpty) { VoxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(itemDefinition.VoxelMaterial.String); } else if (Item.Content is MyObjectBuilder_Ore) { string oreSubTypeId = itemDefinition.Id.SubtypeName; string materialName = (Item.Content as MyObjectBuilder_Ore).GetMaterialName(); bool hasMaterialName = (Item.Content as MyObjectBuilder_Ore).HasMaterialName(); foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if ((hasMaterialName && materialName == mat.Id.SubtypeName) || (hasMaterialName == false && oreSubTypeId == mat.MinedOre)) { VoxelMaterial = mat; break; } } } // Setting the item's model string model = itemDefinition.Model; if (itemDefinition.HasModelVariants) { int modelNum = itemDefinition.Models.Length; Debug.Assert(m_modelVariant >= 0 && m_modelVariant < modelNum, "Model variant overflow. This can happen if model variants changed"); m_modelVariant = m_modelVariant % modelNum; model = itemDefinition.Models[m_modelVariant]; } else if (Item.Content is MyObjectBuilder_Ore && VoxelMaterial != null) { // Only ores without found voxel material use the defined model (otherwise, the scrap metal does not work) model = MyDebris.GetRandomDebrisVoxel(); } // Setting the scale float scale = this.Item.Scale; if (Item.Content is MyObjectBuilder_Ore) { scale *= (float)Math.Pow((float)Item.Amount * itemDefinition.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); } else { scale *= (float)Math.Pow(itemDefinition.Volume / itemDefinition.ModelVolume, 0.333f); } if (scale < 0.05f) { Close(); } else if (scale < 0.15f) { scale = 0.15f; } FormatDisplayName(m_displayedText, Item); Debug.Assert(model != null, "Floating object model is null"); Init(m_displayedText, model, null, null, null); PositionComp.Scale = scale; // Must be set after init var massProperties = new HkMassProperties(); var mass = MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(itemDefinition.Mass) : itemDefinition.Mass; mass = mass * (float)Item.Amount; HkShape shape = GetPhysicsShape(mass, scale, out massProperties); var scaleMatrix = Matrix.CreateScale(scale); if (Physics != null) { Physics.Close(); } Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); int layer = mass > MyPerGameSettings.MinimumLargeShipCollidableMass ? MyPhysics.CollisionLayers.FloatingObjectCollisionLayer : MyPhysics.CollisionLayers.LightFloatingObjectCollisionLayer; if (VoxelMaterial != null || (shape.IsConvex && scale != 1f)) { HkConvexTransformShape transform = new HkConvexTransformShape((HkConvexShape)shape, ref scaleMatrix, HkReferencePolicy.None); Physics.CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, layer); Physics.Enabled = true; transform.Base.RemoveReference(); } else { Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, massProperties, layer); Physics.Enabled = true; } Physics.MaterialType = this.EvaluatePhysicsMaterial(itemDefinition.PhysicalMaterial); Physics.PlayCollisionCueEnabled = true; Physics.RigidBody.ContactSoundCallbackEnabled = true; m_easeCollisionForce = new HkEasePenetrationAction(Physics.RigidBody, 2f); m_massChangeForCollisions = 0.010f; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; }
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(); }
public static bool PrefixUpdateMassFromInventories(List <MyCubeBlock> blocks, MyPhysicsBody rb, MyGridShape __instance) { RefTimeSpan time; if (!lastUpdateTimestamp.TryGetValue(__instance, out time)) { lastUpdateTimestamp.Add(__instance, new RefTimeSpan(MySession.Static.ElapsedGameTime)); return(true); } if ((MySession.Static.ElapsedGameTime - time.timespan).TotalMilliseconds < 1000) { return(false); } lastUpdateTimestamp.Remove(__instance); lastUpdateTimestamp.Add(__instance, new RefTimeSpan(MySession.Static.ElapsedGameTime)); return(true); }
/// <summary> /// precise collision detection based on data from broadphase. Collision detection runs multithreaded. /// </summary> protected void NearPhaseUpdate(float timeStep) { m_InteractionsList = m_BroadPhase.GetRBElementInteractionList(); if (MyFakes.DEBUG_DRAW_COLLIDING_ENTITIES) { bool logToConsole = false; bool debugDraw = true; bool drawText = true; float textSize = 0.7f; Vector2 screenPos = new Vector2(100, 100); if (logToConsole) { Console.WriteLine("-----------------------------"); } Vector4 color = new Vector4(1, 0, 0, 1); foreach (MyRBElementInteraction i in m_InteractionsList) { object obj = i.GetRigidBody1().m_UserData; if (obj is MyPhysicsBody) { MyPhysicsBody rb = (MyPhysicsBody)obj; string name = rb.Entity.ToString() + " " + i.GetRigidBody1().GUID; if (debugDraw) { MyDebugDrawCachedLines.AddAABB(rb.Entity.WorldAABB, Color.Red); } if (drawText) { System.Text.StringBuilder sb0 = new System.Text.StringBuilder(100); sb0.Append(ParseLastElement(i.ToString())); MyDebugDraw.TextBatch.AddText(screenPos, sb0, Color.Red, textSize); screenPos.Y += 20 * textSize; System.Text.StringBuilder sb = new System.Text.StringBuilder(100); sb.Append(ParseLastElement(name)); MyDebugDraw.TextBatch.AddText(screenPos, sb, Color.YellowGreen, textSize); screenPos.Y += 20 * textSize; } if (logToConsole) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(name); Console.ForegroundColor = ConsoleColor.Gray; } } object obj2 = i.GetRigidBody2().m_UserData; if (obj2 is MyPhysicsBody) { MyPhysicsBody rb2 = (MyPhysicsBody)obj2; string name2 = rb2.Entity.ToString() + " " + i.GetRigidBody2().GUID; if (debugDraw) { MyDebugDrawCachedLines.AddAABB(rb2.Entity.WorldAABB, Color.Red); } if (drawText) { System.Text.StringBuilder sb2 = new System.Text.StringBuilder(100); sb2.Append(ParseLastElement(name2)); MyDebugDraw.TextBatch.AddText(screenPos, sb2, Color.LightBlue, textSize); screenPos.Y += 20 * textSize; } if (logToConsole) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(name2); Console.ForegroundColor = ConsoleColor.Gray; } } if (drawText) { screenPos.Y += 10 * textSize; } } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Processing interactions"); #if RENDER_PROFILING foreach (MyRBElementInteraction i in m_InteractionsList) { i.DoWork(); } //Parallel.For(0, m_InteractionsList.Count, m_InteractionAction, 1); #else /*foreach (MyRBElementInteraction i in m_InteractionsList) * { * i.DoWork(); * } */ //Peaks //System.Threading.Tasks.Parallel.For(0, m_InteractionsList.Count, m_InteractionAction); Parallel.For(0, m_InteractionsList.Count, m_InteractionAction, 1); #endif /* * Dictionary<MinerWars.AppCode.Game.Entities.MyEntity, HashSet<MinerWars.AppCode.Game.Entities.MyEntity>> test = new Dictionary<Game.Managers.EntityManager.Entities.MyEntity, HashSet<Game.Managers.EntityManager.Entities.MyEntity>>(); * * foreach (MyRBElementInteraction i in m_InteractionsList) * { * MinerWars.AppCode.Game.Entities.MyEntity e1 = ((MyPhysicsBody)i.GetRigidBody1().m_UserData).Entity; * MinerWars.AppCode.Game.Entities.MyEntity e2 = ((MyPhysicsBody)i.GetRigidBody2().m_UserData).Entity; * * if (test.ContainsKey(e1)) * { * if (!test[e1].Add(e2)) * { * } * } * else * { * HashSet<Game.Managers.EntityManager.Entities.MyEntity> hs = new HashSet<Game.Managers.EntityManager.Entities.MyEntity>(); * hs.Add(e2); * test.Add(e1, hs); * } * if (test.ContainsKey(e2)) * { * if (!test[e2].Add(e1)) * { * } * } * else * { * HashSet<Game.Managers.EntityManager.Entities.MyEntity> hs = new HashSet<Game.Managers.EntityManager.Entities.MyEntity>(); * hs.Add(e1); * test.Add(e2, hs); * * } * } */ MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); m_InteractionsList.Clear(); }
public override void AccumulateCorrection(ref VRageMath.Vector3 correction, ref float weight) { // Don't do any correction if we're not moving if (Parent.Speed < 0.01) { return; } Vector3D position = Parent.PositionAndOrientation.Translation; // Find trees Quaternion rotation = Quaternion.Identity; HkShape sphereShape = new HkSphereShape(6); MyPhysics.GetPenetrationsShape(sphereShape, ref position, ref rotation, m_trees, MyPhysics.CollisionLayers.NoVoxelCollisionLayer); foreach (var tree in m_trees) { // Make sure the tree is actually a tree if (tree.Body == null) { continue; } MyPhysicsBody physicsBody = tree.Body.UserObject as MyPhysicsBody; if (physicsBody == null) { continue; } HkShape bodyShape = tree.Body.GetShape(); if (bodyShape.ShapeType != HkShapeType.StaticCompound) { continue; } // Get the static compound shape HkStaticCompoundShape staticCompoundShape = (HkStaticCompoundShape)bodyShape; int instanceId; uint childKey; staticCompoundShape.DecomposeShapeKey(tree.ShapeKey, out instanceId, out childKey); // Get the local shape position, and add entity world position Vector3D item = staticCompoundShape.GetInstanceTransform(instanceId).Translation; item += physicsBody.GetWorldMatrix().Translation; // Avoid tree Vector3D dir = item - position; var dist = dir.Normalize(); dir = Vector3D.Reject(Parent.ForwardVector, dir); dir.Y = 0.0f; if (dir.Z * dir.Z + dir.X * dir.X < 0.1) { Vector3D dirLocal = Vector3D.TransformNormal(dir, Parent.PositionAndOrientationInverted); dir = position - item; dir = Vector3D.Cross(Vector3D.Up, dir); if (dirLocal.X < 0) { dir = -dir; } } dir.Normalize(); correction += (6f - dist) * Weight * dir; if (!correction.IsValid()) { System.Diagnostics.Debugger.Break(); } } m_trees.Clear(); weight += Weight; }
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(); }
public void ReloadDetectors(bool refreshNetworks = true) { m_detectors.Clear(); m_detectorInteractiveObjects.Clear(); if (DetectorPhysics != null) { DetectorPhysics.Close(); } List <HkShape> shapes = new List <HkShape>(); BoundingBox aabb = new BoundingBox(-Vector3.One / 2, Vector3.One / 2); if (Render.GetModel() != null) { foreach (var dummy in Render.GetModel().Dummies) { var dummyLowerCaseKey = dummy.Key.ToLower(); const string DETECTOR_PREFIX = "detector_"; if (dummyLowerCaseKey.StartsWith(DETECTOR_PREFIX) && dummyLowerCaseKey.Length > DETECTOR_PREFIX.Length) { String[] parts = dummyLowerCaseKey.Split('_'); if (parts.Length < 2) { continue; } var dummyData = dummy.Value; List <Matrix> matrices; if (!m_detectors.TryGetValue(parts[1], out matrices)) { matrices = new List <Matrix>(); m_detectors[parts[1]] = matrices; } matrices.Add(Matrix.Invert(dummyData.Matrix)); // TODO: this should be nicer int shapeKey = shapes.Count; var interactiveObject = CreateInteractiveObject(parts[1], dummyLowerCaseKey, dummyData, shapeKey); if (interactiveObject != null) { unsafe { fixed(Vector3 *corner = m_detectorVertices) aabb.GetCornersUnsafe(corner); } for (int i = 0; i < BoundingBox.CornerCount; i++) { m_detectorVertices[i] = Vector3.Transform(m_detectorVertices[i], dummyData.Matrix); } shapes.Add(new HkConvexVerticesShape(m_detectorVertices, BoundingBox.CornerCount, false, 0)); m_detectorInteractiveObjects.Add(shapeKey, interactiveObject); } } } } if (shapes.Count > 0) { var listShape = new HkListShape(shapes.GetInternalArray(), shapes.Count, HkReferencePolicy.TakeOwnership); DetectorPhysics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DISABLE_COLLISION_RESPONSE); DetectorPhysics.CreateFromCollisionObject((HkShape)listShape, Vector3.Zero, WorldMatrix); DetectorPhysics.Enabled = true; listShape.Base.RemoveReference(); } /* * var inventoryBlock = this as IMyInventoryOwner; * if (refreshNetworks && inventoryBlock != null) * { * CubeGrid.ConveyorSystem.Remove(inventoryBlock); * CubeGrid.ConveyorSystem.Add(inventoryBlock); * }*/ }
internal void UpdateAfterSimulation10() { this.UpdateRigidBodyShape(); if (this.m_voxelMap.Storage != null) { foreach (IMyEntity entity in this.m_nearbyEntities) { if (entity != null) { bool flag = false; MyPhysicsBody physics = entity.Physics as MyPhysicsBody; if (((physics != null) && (physics.RigidBody != null)) && ((physics.RigidBody.Layer == 0x17) || (physics.RigidBody.Layer == 10))) { flag = true; } if ((((entity is MyCubeGrid) || flag) && !entity.MarkedForClose) && (entity.Physics != null)) { BoundingBoxD xd; this.GetPrediction(entity, out xd); if (xd.Intersects(this.m_voxelMap.PositionComp.WorldAABB)) { Vector3I vectori; Vector3I vectori2; HkUniformGridShape shape; int num1; if (flag || !UseLod1VoxelPhysics) { num1 = 0; } else { num1 = 1; } int lod = num1; int num2 = 1 << (lod & 0x1f); BoundingBoxD xd2 = xd.TransformFast(this.m_voxelMap.PositionComp.WorldMatrixInvScaled); xd2.Translate(this.m_voxelMap.SizeInMetresHalf); Vector3 max = (Vector3)xd2.Max; Vector3 min = (Vector3)xd2.Min; this.ClampVoxelCoords(ref min, ref max, out vectori, out vectori2); vectori = vectori >> lod; vectori2 = vectori2 >> lod; int size = ((vectori2 - vectori) + 1).Size; if (size >= m_cellsToGenerateBuffer.Length) { m_cellsToGenerateBuffer = new Vector3I[MathHelper.GetNearestBiggerPowerOfTwo(size)]; } if (this.GetShape(lod, out shape)) { if (shape.Base.IsZero) { MyAnalyticsHelper.ReportBug("Null voxel shape", "SE-7366", true, @"E:\Repo1\Sources\Sandbox.Game\Engine\Voxels\MyVoxelPhysicsBody.cs", 680); } else { int requiredCellsCount = shape.GetMissingCellsInRange(ref vectori, ref vectori2, m_cellsToGenerateBuffer); if (requiredCellsCount != 0) { BoundingBoxI box = new BoundingBoxI((vectori * 8) * num2, (Vector3I)(((vectori2 + 1) * 8) * num2)); box.Translate(this.m_voxelMap.StorageMin); if ((requiredCellsCount > 0) && (this.m_voxelMap.Storage.Intersect(ref box, lod, true) != ContainmentType.Intersects)) { this.SetEmptyShapes(lod, ref shape, requiredCellsCount); } else { for (int i = 0; i < requiredCellsCount; i++) { this.StartPrecalcJobPhysicsIfNeeded(lod, i); } } } } } } } } } this.ScheduleBatchJobs(); if (this.m_bodiesInitialized) { this.CheckAndDiscardShapes(); } } }
protected MyMotorRotor FindMatchingRotor() { Debug.Assert(CubeGrid != null); Debug.Assert(m_penetrations != null); Debug.Assert(CubeGrid.Physics != null); if (CubeGrid == null) { MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): Cube grid == null!"); return(null); } if (m_penetrations == null) { MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): penetrations cache == null!"); return(null); } if (CubeGrid.Physics == null) { MySandboxGame.Log.WriteLine("MyMotorStator.FindMatchingRotor(): Cube grid physics == null!"); return(null); } Quaternion orientation; Vector3D pos; Vector3 halfExtents; ComputeRotorQueryBox(out pos, out halfExtents, out orientation); try { MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref orientation, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); foreach (var obj in m_penetrations) { var entity = obj.GetCollisionEntity(); if (entity == null || entity == CubeGrid) { continue; } MyMotorRotor rotor = FindRotorInGrid(entity); if (rotor != null) { return(rotor); } MyPhysicsBody body = entity.Physics as MyPhysicsBody; if (body != null) { foreach (var child in body.WeldInfo.Children) { rotor = FindRotorInGrid(child.Entity); if (rotor != null) { return(rotor); } } } } } finally { m_penetrations.Clear(); } return(null); }
/// <summary> /// Reveals this group to game and physics logic. /// </summary> public void Reveal() { foreach (var entity in Grids) { if (entity.Parent == null) { MyGamePruningStructure.Add(entity); } } foreach (var body in Grids) { var world = body.Physics?.HavokWorld; if (world == null || body.Physics.IsWelded) { continue; } try { world.LockCriticalOperations(); ActivateRigidBody(body, world, body.Physics.RigidBody); ActivateRigidBody(body, world, body.Physics.RigidBody2); foreach (var constraint in body.Physics.Constraints) { if (MyPhysicsBody.IsConstraintValid(constraint)) { world.AddConstraint(constraint); } } } finally { world.UnlockCriticalOperations(); } } foreach (var entity in Grids) { if (entity.Parent == null) { RegisterRecursive(entity); } } void RegisterRecursive(IMyEntity e) { MyEntities.RegisterForUpdate((MyEntity)e); if (e.Hierarchy == null) { return; } foreach (var child in e.Hierarchy.Children) { RegisterRecursive(child.Container.Entity); } } void ActivateRigidBody(MyCubeGrid grid, HkWorld world, HkRigidBody body) { if (body == null) { return; } // make it dynamic if (body.GetMotionType() != HkMotionType.Dynamic && !grid.IsStatic) { body.UpdateMotionType(HkMotionType.Dynamic); } // wake it up body.Activate(); // restore velocity? } }
/// <summary> /// Conceals this group from game and physics logic. /// </summary> public void Conceal() { foreach (var body in Grids) { if (body.Parent == null) { UnregisterRecursive(body); } } foreach (var body in Grids) { var world = body.Physics?.HavokWorld; if (world == null || body.Physics.IsWelded) { continue; } try { world.LockCriticalOperations(); foreach (var constraint in body.Physics.Constraints) { if (MyPhysicsBody.IsConstraintValid(constraint)) { world.RemoveConstraint(constraint); } } DeactivateRigidBody(body, world, body.Physics.RigidBody); DeactivateRigidBody(body, world, body.Physics.RigidBody2); } finally { world.UnlockCriticalOperations(); } } foreach (var entity in Grids) { if (entity.Parent == null) { MyGamePruningStructure.Remove(entity); } } void DeactivateRigidBody(MyCubeGrid grid, HkWorld world, HkRigidBody body) { if (world == null || body == null) { return; } // stop it body.LinearVelocity = Vector3.Zero; body.AngularVelocity = Vector3.Zero; // put it to sleep body.Deactivate(); // make it static if (body.GetMotionType() != HkMotionType.Fixed) { body.UpdateMotionType(HkMotionType.Fixed); } // Remove from collision // Cache velocity? } void UnregisterRecursive(IMyEntity e) { MyEntities.UnregisterForUpdate((MyEntity)e); if (e.Hierarchy == null) { return; } foreach (var child in e.Hierarchy.Children) { UnregisterRecursive(child.Container.Entity); } } }