public override void ContactPointCallback(ref MyGridContactInfo value) { //return; var prop = value.Event.ContactProperties; prop.Friction = Friction; prop.Restitution = 0.5f; value.EnableParticles = false; value.RubberDeformation = true; string particle = null; if (value.CollidingEntity is MyVoxelBase && MyFakes.ENABLE_DRIVING_PARTICLES) { MyVoxelBase voxel = value.CollidingEntity as MyVoxelBase; Vector3D contactPosition = value.ContactPosition; var vmat = voxel.GetMaterialAt(ref contactPosition); if (vmat == null) return; MyStringHash material = MyStringHash.GetOrCompute(vmat.MaterialTypeName); particle = MyMaterialPropertiesHelper.Static.GetCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material); } else if (value.CollidingEntity is MyCubeGrid && MyFakes.ENABLE_DRIVING_PARTICLES) { MyCubeGrid grid = value.CollidingEntity as MyCubeGrid; MyStringHash material = grid.Physics.GetMaterialAt(value.ContactPosition); particle = MyMaterialPropertiesHelper.Static.GetCollisionEffect(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material); } if (Render != null && particle != null) Render.TrySpawnParticle((Vector3)value.ContactPosition, value.Event.ContactPoint.Normal, particle); }
internal override void ContactPointCallback(ref MyGridContactInfo info) { if (info.CollidingEntity != null && m_attachedTo == info.CollidingEntity) { info.EnableDeformation = false; info.EnableParticles = false; } }
public override void ContactPointCallback(ref MyGridContactInfo value) { //return; var prop = value.Event.ContactProperties; prop.Friction = Friction; prop.Restitution = 0.5f; value.EnableParticles = false; value.RubberDeformation = true; }
public override void ContactPointCallback(ref MyGridContactInfo value) { base.ContactPointCallback(ref value); if (m_pistonBlock == null) return; //if (value.CollidingEntity == m_pistonBlock.CubeGrid || value.CollidingEntity == m_pistonBlock.Subpart3) if (value.CollidingEntity == m_pistonBlock.Subpart3) { value.EnableDeformation = false; value.EnableParticles = false; } }
internal override void ContactPointCallback(ref MyGridContactInfo value) { base.ContactPointCallback(ref value); if (value.CollidingEntity is MyDebrisBase) { return; } if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional) { if (MySession.Static.DestructibleBlocks) { Explode(); } } }
public override void ContactPointCallback(ref MyGridContactInfo value) { base.ContactPointCallback(ref value); if (value.CollidingEntity is MyDebrisBase) { return; } if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional) { if (CubeGrid.BlocksDestructionEnabled) { Explode(); } } }
public override void ContactPointCallback(ref MyGridContactInfo value) { //return; var prop = value.Event.ContactProperties; prop.Friction = Friction; prop.Restitution = 0.5f; value.EnableParticles = false; value.RubberDeformation = true; if (value.CollidingEntity is MyVoxelBase && MyFakes.ENABLE_DRIVING_PARTICLES) { MyVoxelBase voxel = value.CollidingEntity as MyVoxelBase; Vector3D contactPosition = value.ContactPosition; MyStringHash material = MyStringHash.GetOrCompute(voxel.GetMaterialAt(ref contactPosition).MaterialTypeName); MyTuple<int, ContactPropertyParticleProperties> particle = MyMaterialPropertiesHelper.Static.GetCollisionEffectAndProperties(MyMaterialPropertiesHelper.CollisionType.Start, m_wheelStringHash, material); if (Render != null && particle.Item1 > 0) Render.TrySpawnParticle(value.ContactPosition, particle); } }
void Physics_ContactPointCallback(ref Engine.Physics.MyPhysics.MyContactPointEvent e) { // RestoreDynamicMasses(); //if (m_frameCounter > DYNAMIC_UPDATE_DELAY) // m_frameCounter = 0; //else // return; if (m_lastFrameCollision != m_frameCounter) DynamicWeights.Clear(); MyGridContactInfo info = new MyGridContactInfo(ref e.ContactPointEvent, m_grid); if (info.CollidingEntity.Physics.IsStatic) return; float speed = info.CollidingEntity.Physics.LinearVelocity.Length(); if (speed < 0.1f) return; Vector3I blockPos = m_grid.WorldToGridInteger(info.ContactPosition + Vector3.Up * 0.25f); float dot = Vector3.Dot(Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity), Vector3.Down); float collidingMass = 0; m_constrainedGrid.Clear(); MyCubeGrid collidingGrid = info.CollidingEntity as MyCubeGrid; if (collidingGrid != null) { m_constrainedGrid.Add(collidingGrid); AddConstrainedGrids(collidingGrid); foreach (var grid in m_constrainedGrid) { collidingMass += grid.Physics.Mass; } } else { collidingMass = info.CollidingEntity.Physics.Mass; } collidingMass = info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter ? MassToSI(collidingMass) : MassToSI(MyDestructionHelper.MassFromHavok(collidingMass)); float siMass = collidingMass * MyPetaInputComponent.SI_DYNAMICS_MULTIPLIER; //if (dot < 0) //impact from downside // return; float impact = siMass * speed * dot + siMass; if (impact < 0) return; if (m_grid.GridSizeEnum == Common.ObjectBuilders.MyCubeSize.Large) { } DynamicWeights[blockPos] = impact; m_needsRecalc = true; m_lastFrameCollision = m_frameCounter; if (!m_collidingEntities.ContainsKey(info.CollidingEntity)) { m_collidingEntities.Add(info.CollidingEntity, new CollidingEntityInfo() { Position = blockPos, FrameTime = m_frameCounter }); info.CollidingEntity.PositionComp.OnPositionChanged += PositionComp_OnPositionChanged; } else m_collidingEntities[info.CollidingEntity].FrameTime = m_frameCounter; }
public override void ContactPointCallback(ref MyGridContactInfo value) { var prop = value.Event.ContactProperties; value.EnableDeformation = false; value.EnableParticles = false; value.RubberDeformation = false; if (MyPerGameSettings.BallFriendlyPhysics) { prop.Friction = Friction; prop.Restitution = Restitution > REAL_MAXIMUM_RESTITUTION ? REAL_MAXIMUM_RESTITUTION : Restitution; } }
private MyGridContactInfo ReduceVelocities(MyGridContactInfo info) { info.Event.AccessVelocities(0); info.Event.AccessVelocities(1); if (!info.CollidingEntity.Physics.IsStatic && info.CollidingEntity.Physics.Mass < 600) info.CollidingEntity.Physics.LinearVelocity /= 2; if (!this.IsStatic && MyDestructionHelper.MassFromHavok(Mass) < 600) LinearVelocity /= 2; info.Event.UpdateVelocities(0); info.Event.UpdateVelocities(1); return info; }
void RigidBody_ContactPointCallback_Destruction(ref HkContactPointEvent value) { ProfilerShort.Begin("Grid Contact counter"); ProfilerShort.End(); MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid); if (info.IsKnown) return; var myBody = info.CurrentEntity.Physics.RigidBody;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB; var myEntity = info.CurrentEntity;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA.GetEntity() : value.Base.BodyB.GetEntity(); // CH: DEBUG var entity1 = value.Base.BodyA.GetEntity(); var entity2 = value.Base.BodyB.GetEntity(); var rigidBody1 = value.Base.BodyA; var rigidBody2 = value.Base.BodyB; if (entity1 == null || entity2 == null || entity1.Physics == null || entity2.Physics == null) return; if (entity1 is MyFracturedPiece && entity2 is MyFracturedPiece) return; info.HandleEvents(); if (rigidBody1.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || rigidBody2.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT)) return; if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity == null || info.CollidingEntity.MarkedForClose) return; if (MyFakes.ENABLE_CHARACTER_VIRTUAL_PHYSICS) { MyCharacter character = MySession.ControlledEntity as MyCharacter; if (character != null && character.VirtualPhysics != null) { foreach (var constraint in character.VirtualPhysics.Constraints) { IMyEntity cstrEntityA = constraint.RigidBodyA.GetEntity(); IMyEntity cstrEntityB = constraint.RigidBodyB.GetEntity(); if (info.CurrentEntity == cstrEntityA || info.CurrentEntity == cstrEntityB || info.CollidingEntity == cstrEntityA || info.CollidingEntity == cstrEntityB) return; } } } var grid1 = entity1 as MyCubeGrid; var grid2 = entity2 as MyCubeGrid; if (grid1 != null && grid2 != null && (MyCubeGridGroups.Static.Physical.GetGroup(grid1) == MyCubeGridGroups.Static.Physical.GetGroup(grid2))) return; ProfilerShort.Begin("Grid contact point callback"); if (Sync.IsServer) { var vel = Math.Abs(value.SeparatingVelocity); bool enoughSpeed = vel > 3; //float dot = Vector3.Dot(Vector3.Normalize(LinearVelocity), Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity)); Vector3 velocity1 = rigidBody1.GetVelocityAtPoint(info.Event.ContactPoint.Position); Vector3 velocity2 = rigidBody2.GetVelocityAtPoint(info.Event.ContactPoint.Position); float speed1 = velocity1.Length(); float speed2 = velocity2.Length(); Vector3 dir1 = speed1 > 0 ? Vector3.Normalize(velocity1) : Vector3.Zero; Vector3 dir2 = speed2 > 0 ? Vector3.Normalize(velocity2) : Vector3.Zero; float mass1 = MyDestructionHelper.MassFromHavok(rigidBody1.Mass); float mass2 = MyDestructionHelper.MassFromHavok(rigidBody2.Mass); float impact1 = speed1 * mass1; float impact2 = speed2 * mass2; float dot1withNormal = speed1 > 0 ? Vector3.Dot(dir1, value.ContactPoint.Normal) : 0; float dot2withNormal = speed2 > 0 ? Vector3.Dot(dir2, value.ContactPoint.Normal) : 0; speed1 *= Math.Abs(dot1withNormal); speed2 *= Math.Abs(dot2withNormal); bool is1Static = mass1 == 0; bool is2Static = mass2 == 0; bool is1Small = entity1 is MyFracturedPiece || (grid1 != null && grid1.GridSizeEnum == MyCubeSize.Small); bool is2Small = entity2 is MyFracturedPiece || (grid2 != null && grid2.GridSizeEnum == MyCubeSize.Small); float dot = Vector3.Dot(dir1, dir2); float maxDestructionRadius = 0.5f; impact1 *= info.ImpulseMultiplier; impact2 *= info.ImpulseMultiplier; MyHitInfo hitInfo = new MyHitInfo(); var hitPos = info.ContactPosition; hitInfo.Normal = value.ContactPoint.Normal; //direct hit if (dot1withNormal < 0.0f) { if (entity1 is MyFracturedPiece) impact1 /= 10; impact1 *= Math.Abs(dot1withNormal); //respect angle of hit if (entity2 is MyFracturedPiece) { } if ((impact1 > 2000 && speed1 > 2 && !is2Small) || (impact1 > 500 && speed1 > 10)) //must be fast enought to destroy fracture piece (projectile) { //1 is big hitting if (is2Static || impact1 / impact2 > 10) { hitInfo.Position = hitPos + 0.1f * hitInfo.Normal; impact1 -= mass1; if (grid1 != null) { var blockPos = GetGridPosition(value, grid1, 0); grid1.DoDamage(impact1, hitInfo, blockPos); } else MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); hitInfo.Position = hitPos - 0.1f * hitInfo.Normal; if (grid2 != null) { var blockPos = GetGridPosition(value, grid2, 1); grid2.DoDamage(impact1, hitInfo, blockPos); } else MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); ReduceVelocities(info); } } } if (dot2withNormal < 0.0f) { if (entity2 is MyFracturedPiece) impact2 /= 10; impact2 *= Math.Abs(dot1withNormal); //respect angle of hit if (impact2 > 2000 && speed2 > 2 && !is1Small || (impact2 > 500 && speed2 > 10)) //must be fast enought to destroy fracture piece (projectile) { //2 is big hitting if (is1Static || impact2 / impact1 > 10) { hitInfo.Position = hitPos + 0.1f * hitInfo.Normal; impact2 -= mass2; if (grid1 != null) { var blockPos = GetGridPosition(value, grid1, 0); grid1.DoDamage(impact2, hitInfo, blockPos); } else MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); hitInfo.Position = hitPos - 0.1f * hitInfo.Normal; if (grid2 != null) { var blockPos = GetGridPosition(value, grid2, 1); grid2.DoDamage(impact2, hitInfo, blockPos); } else MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); ReduceVelocities(info); } } } //float destructionImpact = vel * (MyDestructionHelper.MassFromHavok(Mass) + MyDestructionHelper.MassFromHavok(info.CollidingEntity.Physics.Mass)); //destructionImpact *= info.ImpulseMultiplier; //if (destructionImpact > 2000 && enoughSpeed) //{ // CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, this, info, value.ContactPoint.Normal); // CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, info.CollidingEntity.Physics, info, value.ContactPoint.Normal); // ReduceVelocities(info); //} } ProfilerShort.End(); }
void RigidBody_ContactPointCallback(ref HkContactPointEvent value) { ProfilerShort.Begin("Grid Contact counter"); ProfilerShort.End(); var entity1 = value.Base.BodyA.GetEntity(); var entity2 = value.Base.BodyB.GetEntity(); if (entity1 == null || entity2 == null) return; //DA used to stop appliyng force when there is planet/ship collisions to increase performance after ship crashes on planet if ((Math.Abs(value.SeparatingVelocity) < 0.3f) && (entity1 is MyTrees || entity1 is MyVoxelPhysics || entity2 is MyVoxelPhysics || entity2 is MyTrees)) { return; } MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid); var myBody = value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB; // CH: DEBUG if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity.MarkedForClose) return; if (MyFakes.LANDING_GEAR_IGNORE_DAMAGE_CONTACTS && MyCubeGridGroups.Static.NoContactDamage.HasSameGroupAndIsGrid(entity1, entity2)) return; ProfilerShort.Begin("Grid contact point callback"); bool doSparks = MyPerGameSettings.EnableCollisionSparksEffect && (info.CollidingEntity is MyCubeGrid || info.CollidingEntity is MyVoxelMap); // According to Petr, WasUsed does not work everytime //if (value.ContactProperties.WasUsed) { // Handle callbacks here info.HandleEvents(); } bool deformationPerformed = false; if (Sync.IsServer && value.ContactProperties.ImpulseApplied > MyGridShape.BreakImpulse && info.CollidingEntity != null && info.EnableDeformation && m_grid.BlocksDestructionEnabled) { float deformation = value.SeparatingVelocity; if (info.RubberDeformation) { deformation /= 5; } HkBreakOffPointInfo breakInfo = CreateBreakOffPoint(value, info.ContactPosition, MyGridShape.BreakImpulse); PerformDeformation(ref breakInfo, false, value.SeparatingVelocity); deformationPerformed = true; } else if (doSparks && value.SeparatingVelocity > 2.0f && value.ContactProperties.WasUsed && !m_lastContacts.ContainsKey(value.ContactPointId) && info.EnableParticles) { m_lastContacts[value.ContactPointId] = MySandboxGame.TotalGamePlayTimeInMilliseconds; AddCollisionEffect(info.ContactPosition, value.ContactPoint.Normal); } // Large dynamic ships colliding with floating objects // When low separating velocity or deformation performed, disable contact point // Floating object will still collide with kinematic part of ship and won't push it if (m_grid.GridSizeEnum == MyCubeSize.Large && !myBody.IsFixedOrKeyframed && info.CollidingEntity is MyFloatingObject && (Math.Abs(value.SeparatingVelocity) < 0.2f || deformationPerformed)) { var prop = value.ContactProperties; prop.IsDisabled = true; } ProfilerShort.End(); }
private void DestroyGrid(ref MyPhysics.MyContactPointEvent value, MyCubeGrid grid) { MyGridContactInfo info = new MyGridContactInfo(ref value.ContactPointEvent, grid); info.EnableDeformation = false; info.EnableParticles = false; HkBreakOffPointInfo breakInfo = new HkBreakOffPointInfo() { ContactPoint = value.ContactPointEvent.ContactPoint, ContactPosition = info.ContactPosition, ContactPointProperties = value.ContactPointEvent.ContactProperties, IsContact = true, BreakingImpulse = grid.Physics.Shape.BreakImpulse, CollidingBody = value.ContactPointEvent.Base.BodyA == grid.Physics.RigidBody ? value.ContactPointEvent.Base.BodyB : value.ContactPointEvent.Base.BodyA, ContactPointDirection = value.ContactPointEvent.Base.BodyB == grid.Physics.RigidBody ? -1 : 1, }; grid.Physics.PerformMeteoritDeformation(ref breakInfo, value.ContactPointEvent.SeparatingVelocity); m_closeAfterSimulation = Sync.IsServer; }
void CreateDestructionFor(float destructionImpact, Vector3 contactVelocity, MyPhysicsBody body, MyGridContactInfo info, Vector3 normal, float maxDestructionRadius) { if (body.BreakableBody != null) { float collidingMass = body.Mass == 0 ? Mass : body.Mass; //fall on voxel float destructionRadius = Math.Min(destructionImpact / 8000, maxDestructionRadius); float destructionImpulse = MyDestructionConstants.STRENGTH + destructionImpact / 10000; float expandVelocity = Math.Min(destructionImpact / 10000, 3); MyPhysics.FractureImpactDetails destruction; HkdFractureImpactDetails details; details = HkdFractureImpactDetails.Create(); details.SetBreakingBody(body.RigidBody); details.SetContactPoint(WorldToCluster(info.ContactPosition)); details.SetDestructionRadius(destructionRadius); details.SetBreakingImpulse(destructionImpulse); details.SetParticleExpandVelocity(expandVelocity); details.SetParticleVelocity(contactVelocity); details.SetParticlePosition(WorldToCluster(info.ContactPosition - normal * 0.25f)); details.SetParticleMass(collidingMass); details.ZeroCollidingParticleVelocity(); details.Flag = details.Flag | HkdFractureImpactDetails.Flags.FLAG_DONT_RECURSE | HkdFractureImpactDetails.Flags.FLAG_TRIGGERED_DESTRUCTION; destruction = new MyPhysics.FractureImpactDetails(); destruction.Details = details; destruction.World = HavokWorld; destruction.ContactInWorld = info.ContactPosition; destruction.Entity = (MyEntity)body.Entity; MyPhysics.EnqueueDestruction(destruction); } }
void RigidBody_ContactPointCallback_Destruction(ref HkContactPointEvent value) { ProfilerShort.Begin("Grid Contact counter"); ProfilerShort.End(); MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid); if (info.IsKnown) return; var myEntity = info.CurrentEntity;//value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA.GetEntity() : value.Base.BodyB.GetEntity(); if (myEntity == null || myEntity.Physics == null || myEntity.Physics.RigidBody == null) { return; } var myBody = myEntity.Physics.RigidBody; // CH: DEBUG var physicsBody1 = value.GetPhysicsBody(0); var physicsBody2 = value.GetPhysicsBody(1); if (physicsBody1 == null || physicsBody2 == null) return; var entity1 = physicsBody1.Entity; var entity2 = physicsBody2.Entity; if (entity1 == null || entity2 == null || entity1.Physics == null || entity2.Physics == null) return; if (entity1 is MyFracturedPiece && entity2 is MyFracturedPiece) return; var rigidBody1 = value.Base.BodyA; var rigidBody2 = value.Base.BodyB; info.HandleEvents(); if (rigidBody1.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || rigidBody2.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT)) return; if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity == null || info.CollidingEntity.MarkedForClose) return; var grid1 = entity1 as MyCubeGrid; var grid2 = entity2 as MyCubeGrid; // CH: TODO: This is a hack Instead, the IMyDestroyableObject should be used and the subpart DoDamage code could delegate it to the grid // The thing is, this approach would probably need a rewrite of this whole method... if (grid2 == null && entity2 is MyEntitySubpart) { while (entity2 != null && !(entity2 is MyCubeGrid)) { entity2 = entity2.Parent; } if (entity2 != null) { physicsBody2 = entity2.Physics as MyPhysicsBody; rigidBody2 = physicsBody2.RigidBody; grid2 = entity2 as MyCubeGrid; } } if (grid1 != null && grid2 != null && (MyCubeGridGroups.Static.Physical.GetGroup(grid1) == MyCubeGridGroups.Static.Physical.GetGroup(grid2))) return; ProfilerShort.Begin("Grid contact point callback"); { var vel = Math.Abs(value.SeparatingVelocity); bool enoughSpeed = vel > 3; //float dot = Vector3.Dot(Vector3.Normalize(LinearVelocity), Vector3.Normalize(info.CollidingEntity.Physics.LinearVelocity)); Vector3 velocity1 = rigidBody1.GetVelocityAtPoint(info.Event.ContactPoint.Position); Vector3 velocity2 = rigidBody2.GetVelocityAtPoint(info.Event.ContactPoint.Position); float speed1 = velocity1.Length(); float speed2 = velocity2.Length(); Vector3 dir1 = speed1 > 0 ? Vector3.Normalize(velocity1) : Vector3.Zero; Vector3 dir2 = speed2 > 0 ? Vector3.Normalize(velocity2) : Vector3.Zero; float mass1 = MyDestructionHelper.MassFromHavok(rigidBody1.Mass); float mass2 = MyDestructionHelper.MassFromHavok(rigidBody2.Mass); float impact1 = speed1 * mass1; float impact2 = speed2 * mass2; float dot1withNormal = speed1 > 0 ? Vector3.Dot(dir1, value.ContactPoint.Normal) : 0; float dot2withNormal = speed2 > 0 ? Vector3.Dot(dir2, value.ContactPoint.Normal) : 0; speed1 *= Math.Abs(dot1withNormal); speed2 *= Math.Abs(dot2withNormal); bool is1Static = mass1 == 0; bool is2Static = mass2 == 0; bool is1Small = entity1 is MyFracturedPiece || (grid1 != null && grid1.GridSizeEnum == MyCubeSize.Small); bool is2Small = entity2 is MyFracturedPiece || (grid2 != null && grid2.GridSizeEnum == MyCubeSize.Small); float dot = Vector3.Dot(dir1, dir2); float maxDestructionRadius = 0.5f; impact1 *= info.ImpulseMultiplier; impact2 *= info.ImpulseMultiplier; MyHitInfo hitInfo = new MyHitInfo(); var hitPos = info.ContactPosition; hitInfo.Normal = value.ContactPoint.Normal; //direct hit if (dot1withNormal < 0.0f) { if (entity1 is MyFracturedPiece) impact1 /= 10; impact1 *= Math.Abs(dot1withNormal); //respect angle of hit if ((impact1 > 2000 && speed1 > 2 && !is2Small) || (impact1 > 500 && speed1 > 10)) //must be fast enought to destroy fracture piece (projectile) { //1 is big hitting if (is2Static || impact1 / impact2 > 10) { hitInfo.Position = hitPos + 0.1f * hitInfo.Normal; impact1 -= mass1; if (Sync.IsServer && impact1 > 0) { if (grid1 != null) { var blockPos = GetGridPosition(value.ContactPoint, rigidBody1, grid1, 0); grid1.DoDamage(impact1, hitInfo, blockPos, grid2 != null ? grid2.EntityId : 0); } else MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); hitInfo.Position = hitPos - 0.1f * hitInfo.Normal; if (grid2 != null) { var blockPos = GetGridPosition(value.ContactPoint, rigidBody2, grid2, 1); grid2.DoDamage(impact1, hitInfo, blockPos, grid1 != null ? grid1.EntityId : 0); } else MyDestructionHelper.TriggerDestruction(impact1, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); ReduceVelocities(info); } MyDecals.HandleAddDecal(entity1, hitInfo); MyDecals.HandleAddDecal(entity2, hitInfo); } } } if (dot2withNormal < 0.0f) { if (entity2 is MyFracturedPiece) impact2 /= 10; impact2 *= Math.Abs(dot2withNormal); //respect angle of hit if (impact2 > 2000 && speed2 > 2 && !is1Small || (impact2 > 500 && speed2 > 10)) //must be fast enought to destroy fracture piece (projectile) { //2 is big hitting if (is1Static || impact2 / impact1 > 10) { hitInfo.Position = hitPos + 0.1f * hitInfo.Normal; impact2 -= mass2; if (Sync.IsServer && impact2 > 0) { if (grid1 != null) { var blockPos = GetGridPosition(value.ContactPoint, rigidBody1, grid1, 0); grid1.DoDamage(impact2, hitInfo, blockPos, grid2 != null ? grid2.EntityId : 0); } else MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity1.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); hitInfo.Position = hitPos - 0.1f * hitInfo.Normal; if (grid2 != null) { var blockPos = GetGridPosition(value.ContactPoint, rigidBody2, grid2, 1); grid2.DoDamage(impact2, hitInfo, blockPos, grid1 != null ? grid1.EntityId : 0); } else MyDestructionHelper.TriggerDestruction(impact2, (MyPhysicsBody)entity2.Physics, info.ContactPosition, value.ContactPoint.Normal, maxDestructionRadius); ReduceVelocities(info); } MyDecals.HandleAddDecal(entity1, hitInfo); MyDecals.HandleAddDecal(entity2, hitInfo); } } } //float destructionImpact = vel * (MyDestructionHelper.MassFromHavok(Mass) + MyDestructionHelper.MassFromHavok(info.CollidingEntity.Physics.Mass)); //destructionImpact *= info.ImpulseMultiplier; //if (destructionImpact > 2000 && enoughSpeed) //{ // CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, this, info, value.ContactPoint.Normal); // CreateDestructionFor(destructionImpact, LinearVelocity + info.CollidingEntity.Physics.LinearVelocity, info.CollidingEntity.Physics, info, value.ContactPoint.Normal); // ReduceVelocities(info); //} } ProfilerShort.End(); }
void RigidBody_ContactPointCallback(ref HkContactPointEvent value) { ProfilerShort.Begin("Grid Contact counter"); ProfilerShort.End(); var otherEntity = value.GetOtherEntity(m_grid); var otherPhysicsBody = value.GetPhysicsBody(0); var thisEntity = m_grid; if (otherEntity == null || thisEntity == null) return; //DA used to stop appliyng force when there is planet/ship collisions to increase performance after ship crashes on planet if ((Math.Abs(value.SeparatingVelocity) < 0.3f) && (otherEntity is MyTrees || otherEntity is MyVoxelPhysics)) { return; } MyGridContactInfo info = new MyGridContactInfo(ref value, m_grid); var myBody = RigidBody;// value.Base.BodyA.GetEntity() == m_grid.Components ? value.Base.BodyA : value.Base.BodyB; if (info.CollidingEntity is Sandbox.Game.Entities.Character.MyCharacter || info.CollidingEntity.MarkedForClose) return; if (MyFakes.LANDING_GEAR_IGNORE_DAMAGE_CONTACTS && MyCubeGridGroups.Static.NoContactDamage.HasSameGroupAndIsGrid(otherEntity, thisEntity)) return; ProfilerShort.Begin("Grid contact point callback"); bool hitVoxel = info.CollidingEntity is MyVoxelMap || info.CollidingEntity is MyVoxelPhysics; if(hitVoxel && m_grid.Render != null) { m_grid.Render.ResetLastVoxelContactTimer(); } bool doSparks = MyPerGameSettings.EnableCollisionSparksEffect && (info.CollidingEntity is MyCubeGrid || hitVoxel); // According to Petr, WasUsed does not work everytime //if (value.ContactProperties.WasUsed) { // Handle callbacks here info.HandleEvents(); } if(MyDebugDrawSettings.DEBUG_DRAW_FRICTION) { var pos = ClusterToWorld(value.ContactPoint.Position); var vel = -GetVelocityAtPoint(pos); vel *= 0.1f; var fn = Math.Abs(Gravity.Dot(value.ContactPoint.Normal) * value.ContactProperties.Friction); if (vel.Length() > 0.5f) { vel.Normalize(); MyRenderProxy.DebugDrawArrow3D(pos, pos + fn * vel, Color.Gray, Color.Gray, false); } } if (doSparks && Math.Abs(value.SeparatingVelocity) > 2.0f && value.ContactProperties.WasUsed && !m_lastContacts.ContainsKey(value.ContactPointId) && info.EnableParticles) { ProfilerShort.Begin("AddCollisionEffect"); m_lastContacts[value.ContactPointId] = MySandboxGame.TotalGamePlayTimeInMilliseconds; AddCollisionEffect(info.ContactPosition, value.ContactPoint.Normal); ProfilerShort.End(); } ProfilerShort.Begin("Dust"); bool doDust = MyPerGameSettings.EnableCollisionSparksEffect && hitVoxel; float force = Math.Abs(value.SeparatingVelocity * (Mass / 100000)); if (doDust && force > 0.25f && info.EnableParticles) { float scale = MathHelper.Clamp(force / 10.0f, 0.2f, 4.0f); AddDustEffect(info.ContactPosition, scale); } ProfilerShort.End(); // Large dynamic ships colliding with floating objects // When low separating velocity or deformation performed, disable contact point // Floating object will still collide with kinematic part of ship and won't push it if (m_grid.GridSizeEnum == MyCubeSize.Large && !myBody.IsFixedOrKeyframed && info.CollidingEntity is MyFloatingObject && (Math.Abs(value.SeparatingVelocity) < 0.2f)) { var prop = value.ContactProperties; prop.IsDisabled = true; } ProfilerShort.End(); }
public override void ContactPointCallback(ref MyGridContactInfo value) { base.ContactPointCallback(ref value); if (value.CollidingEntity is MyDebrisBase) return; if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional) { if (CubeGrid.BlocksDestructionEnabled) Explode(); } }
internal override void ContactPointCallback(ref MyGridContactInfo value) { base.ContactPointCallback(ref value); if (value.CollidingEntity is MyDebrisBase) return; if (System.Math.Abs(value.Event.SeparatingVelocity) > 5 && IsFunctional) { if (MySession.Static.DestructibleBlocks) Explode(); } }