public override void CreatePhysicsShape(out HkShape shape, out HkMassProperties massProperties, float mass) { HkSphereShape shape2 = new HkSphereShape((0.5f * ((MyEntity)base.Entity).Render.GetModel().BoundingSphere.Radius) * base.Entity.PositionComp.Scale.Value); shape = (HkShape)shape2; massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(shape2.Radius * 0.5f, mass); }
static MyEntityPhysicsStateGroup SphereCast(MyEntity entity, float radius, float distance) { if (DEBUG_DRAW) { VRageRender.MyRenderProxy.DebugDrawCapsule(entity.WorldMatrix.Translation, entity.PositionComp.GetPosition() + entity.WorldMatrix.Down * distance, radius, Color.Red, false, false); } // Sphere cast under character Vector3D target = entity.PositionComp.GetPosition() + entity.WorldMatrix.Down * distance; HkSphereShape shape = new HkSphereShape(radius); MatrixD transform = entity.WorldMatrix; var dist = MyPhysics.CastShapeReturnContactBodyData(target, shape, ref transform, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter, 0); if (dist.HasValue) { var hitEntity = dist.Value.HkHitInfo.GetHitEntity(); if (!IsValid(hitEntity, false)) { return(null); } return(FindPhysics(hitEntity)); } return(null); }
public override void CreatePhysicsShape(out HkShape shape, ref HkMassProperties massProperties) { var sphereShape = new HkSphereShape(((MyEntity)Entity).Render.GetModel().BoundingSphere.Radius * Entity.PositionComp.Scale.Value); shape = sphereShape; var mass = SphereMass(sphereShape.Radius, VoxelDensity); massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(sphereShape.Radius, mass); }
public void GetFracturesInSphere(ref BoundingSphereD searchSphere, ref List <MyFracturedPiece> output) { var activeFractures = m_piecesTimesOfDeath.Keys; HkShape shape = new HkSphereShape((float)searchSphere.Radius); try { MyPhysics.GetPenetrationsShape(shape, ref searchSphere.Center, ref Quaternion.Identity, m_rigidList, MyPhysics.CollisionLayers.NotCollideWithStaticLayer); foreach (var rigidBody in m_rigidList) { var fracture = rigidBody.GetCollisionEntity() as MyFracturedPiece; if (fracture != null) { output.Add(fracture); } } } finally { m_rigidList.Clear(); shape.RemoveReference(); } }
public static HkShape CreateCharacterShape(float height, float width, float headHeight, float headSize, float headForwardOffset, float downOffset = 0, bool capsuleForHead = false) { HkCapsuleShape capsule = new HkCapsuleShape(Vector3.Up * (height - downOffset) / 2.0f, Vector3.Down * (height) / 2.0f, width / 2.0f); if (headSize > 0) { HkConvexShape headShape; if (capsuleForHead) { headShape = new HkCapsuleShape(new Vector3(0, 0, -0.3f), new Vector3(0, 0, 0.3f), headSize); } else { headShape = new HkSphereShape(headSize); } //headShape = new HkCapsuleShape(new Vector3(0, 0, -0.05f), new Vector3(0, 0, 0.05f), headSize); HkShape[] shapes = new HkShape[] { capsule, new HkConvexTranslateShape(headShape, Vector3.Up * (headHeight - downOffset) / 2.0f + Vector3.Forward * headForwardOffset, HkReferencePolicy.TakeOwnership), }; return(new HkListShape(shapes, shapes.Length, HkReferencePolicy.TakeOwnership)); } else { return(capsule); } }
private void RefreshPhysicsBody() { if (CubeGrid.CreatePhysics) { if (Physics != null) { Physics.Close(); } var detectorShape = new HkSphereShape(CubeGrid.GridSize * 0.5f); var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(detectorShape.Radius, VirtualMass != 0 ? VirtualMass : 0.01f); Physics = new Engine.Physics.MyPhysicsBody(this, RigidBodyFlag.RBF_KEYFRAMED_REPORTING); Physics.IsPhantom = false; Physics.CreateFromCollisionObject(detectorShape, Vector3.Zero, WorldMatrix, massProperties, MyPhysics.CollisionLayers.VirtualMassLayer); UpdateIsWorking(); Physics.Enabled = IsWorking && CubeGrid.Physics != null && CubeGrid.Physics.Enabled; Physics.RigidBody.Activate(); detectorShape.Base.RemoveReference(); if (CubeGrid != null && CubeGrid.Physics != null && !CubeGrid.IsStatic) { CubeGrid.Physics.UpdateMass(); } } }
public override void CreatePhysicsShape(out HkShape shape, ref HkMassProperties massProperties) { var sphereShape = new HkSphereShape(((MyEntity)Entity).Render.GetModel().BoundingSphere.Radius *Entity.PositionComp.Scale.Value); shape = sphereShape; massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(sphereShape.Radius, 1); }
protected override bool CanPlaceRotor(MyMotorRotor rotorBlock, long builtBy) { BoundingSphereD sphere = rotorBlock.Model.BoundingSphere; sphere.Center = Vector3D.Transform(sphere.Center, rotorBlock.WorldMatrix); CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); HkSphereShape spShape = new HkSphereShape((float)sphere.Radius); Quaternion q = Quaternion.Identity;//Quaternion.CreateFromForwardUp(rotorBlock.WorldMatrix.Forward, rotorBlock.WorldMatrix.Up); var position = rotorBlock.WorldMatrix.Translation; MyPhysics.GetPenetrationsShape(spShape, ref position, ref q, m_tmpList, MyPhysics.CharacterNetworkCollisionLayer); if (m_tmpSet.Count > 1 || m_tmpList.Count > 0) { m_tmpList.Clear(); m_tmpSet.Clear(); if (builtBy == MySession.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); } return(false); } m_tmpList.Clear(); m_tmpSet.Clear(); return(true); }
private void LoadDummies() { var finalModel = Engine.Models.MyModels.GetModelOnlyDummies(BlockDefinition.Model); foreach (var dummy in finalModel.Dummies) { if (dummy.Key.ToLower().Contains("detector_shiptool")) { var matrix = dummy.Value.Matrix; float radius = matrix.Scale.AbsMin(); Matrix blockMatrix = this.PositionComp.LocalMatrix; Vector3 gridDetectorPosition = Vector3.Transform(matrix.Translation, blockMatrix); m_detectorSphere = new BoundingSphere(gridDetectorPosition, radius); var phantom = new HkPhantomCallbackShape(phantom_Enter, phantom_Leave); var sphereShape = new HkSphereShape(radius); var detectorShape = new HkBvShape(sphereShape, phantom, HkReferencePolicy.TakeOwnership); Physics = new Engine.Physics.MyPhysicsBody(this, RigidBodyFlag.RBF_DEFAULT); Physics.IsPhantom = true; Physics.CreateFromCollisionObject(detectorShape, matrix.Translation, WorldMatrix, null, MyPhysics.ObjectDetectionCollisionLayer); detectorShape.Base.RemoveReference(); break; } } }
public static HkShape CreateCharacterShape(float height, float width, float headHeight, float headSize, float headForwardOffset, float downOffset = 0, bool capsuleForHead = false) { HkCapsuleShape capsule = new HkCapsuleShape(Vector3.Up * (height - downOffset) / 2.0f, Vector3.Down * (height) / 2.0f, width / 2.0f); if (headSize > 0) { HkConvexShape headShape; if (capsuleForHead) { headShape = new HkCapsuleShape(new Vector3(0, 0, -0.3f), new Vector3(0, 0, 0.3f), headSize); } else { headShape = new HkSphereShape(headSize); } //headShape = new HkCapsuleShape(new Vector3(0, 0, -0.05f), new Vector3(0, 0, 0.05f), headSize); HkShape[] shapes = new HkShape[] { capsule, new HkConvexTranslateShape(headShape, Vector3.Up * (headHeight - downOffset) / 2.0f + Vector3.Forward * headForwardOffset, HkReferencePolicy.TakeOwnership), }; return new HkListShape(shapes, shapes.Length, HkReferencePolicy.TakeOwnership); } else { return capsule; } }
protected virtual bool CanPlaceTop(MyAttachableTopBlockBase topBlock, long builtBy) { // Compute the rough actual position for the head, this improves the detection if it can be placed float topDistance = (Subpart3.Model.BoundingBoxSize.Y); Vector3D topPosition = this.Subpart3.WorldMatrix.Translation + this.WorldMatrix.Up * topDistance; float topRadius = topBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = topBlock.Model.BoundingSphere; sphere.Center = topPosition; sphere.Radius = topRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because top sometimes intersects piston), don't add top if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); } return(false); } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(topRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(topBlock.ModelCollision.HavokCollisionShapes[0], ref topPosition, ref q, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the head // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_penetrations.Count; i++) { MyCubeGrid grid = m_penetrations[i].GetCollisionEntity().GetTopMostParent() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_penetrations.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); } return(false); } } m_penetrations.Clear(); return(true); }
protected override bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { // Compute the rough actual position for the wheel, this improves the detection if it can be placed float wheelDistance = BlockDefinition.Size.Y * CubeGrid.GridSize - 0.2f * CubeGrid.GridSize; Vector3D wheelPosition = this.WorldMatrix.Translation + this.WorldMatrix.Up * wheelDistance; float wheelRadius = rotorBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = rotorBlock.Model.BoundingSphere; sphere.Center = wheelPosition; sphere.Radius = wheelRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because wheel sometimes intersects suspension), don't add wheel if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); } return(false); } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(wheelRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(rotorBlock.ModelCollision.HavokCollisionShapes[0], ref wheelPosition, ref q, m_tmpList, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the wheel // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_tmpList.Count; i++) { MyCubeGrid grid = m_tmpList[i].GetCollisionEntity() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_tmpList.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); } return(false); } } m_tmpList.Clear(); return(true); }
public override void ScalePhysicsShape(ref HkMassProperties massProperties) { HkSphereShape shape = (HkSphereShape)this.RigidBody.GetShape(); shape.Radius = ((MyEntity)base.Entity).Render.GetModel().BoundingSphere.Radius *base.Entity.PositionComp.Scale.Value; float mass = this.SphereMass(shape.Radius, 260f); massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(shape.Radius, mass); this.RigidBody.SetShape((HkShape)shape); this.RigidBody.SetMassProperties(ref massProperties); this.RigidBody.UpdateShape(); }
public static Vector3D?FindFreePlace(Vector3D basePos, float radius, int maxTestCount = 40, int testsPerDistance = 6, float stepSize = 1f, float radiusIncrement = 10f, MyEntity ignoreEnt = null) { Vector3D position = basePos; Quaternion rotation = Quaternion.Identity; HkShape shape = new HkSphereShape(radius); try { if (MyEntities.IsInsideWorld(position) && !MyEntities.IsShapePenetrating(shape, ref position, ref rotation, 15, ignoreEnt)) { BoundingSphereD sphere = new BoundingSphereD(position, radius); MyVoxelBase overlappingWithSphere = MySession.Static.VoxelMaps.GetOverlappingWithSphere(ref sphere); if (overlappingWithSphere == null) { return(position); } if (overlappingWithSphere is MyPlanet) { (overlappingWithSphere as MyPlanet).CorrectSpawnLocation(ref basePos, radius); } return(basePos); } int num = (int)Math.Ceiling((float)maxTestCount / (float)testsPerDistance); float num2 = 0f; for (int i = 0; i < num; i++) { num2 += radius * stepSize + radiusIncrement; for (int j = 0; j < testsPerDistance; j++) { position = basePos + MyUtils.GetRandomVector3Normalized() * num2; if (MyEntities.IsInsideWorld(position) && !MyEntities.IsShapePenetrating(shape, ref position, ref rotation, 15, ignoreEnt)) { BoundingSphereD sphere2 = new BoundingSphereD(position, radius); MyVoxelBase overlappingWithSphere2 = MySession.Static.VoxelMaps.GetOverlappingWithSphere(ref sphere2); if (overlappingWithSphere2 == null) { return(position); } if (overlappingWithSphere2 is MyPlanet) { (overlappingWithSphere2 as MyPlanet).CorrectSpawnLocation(ref basePos, radius); } } } } return(null); } finally { shape.RemoveReference(); } }
private void DamageGrid(FlameInfo flameInfo, LineD l, MyCubeGrid grid) { HkSphereShape sph = new HkSphereShape(flameInfo.Radius * BlockDefinition.FlameDamageLengthScale); var transform = MatrixD.CreateWorld(l.From, Vector3.Forward, Vector3.Up); var hit = MyPhysics.CastShapeReturnPoint(l.To, sph, ref transform, (int)MyPhysics.CollisionLayers.DefaultCollisionLayer, 0.05f); sph.Base.RemoveReference(); if (hit.HasValue) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); MyPhysics.CastRay(hit.Value - l.Direction * 0.1f, hit.Value + l.Direction * 0.1f, m_gridRayCastLst, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_gridRayCastLst.Count == 0 || m_gridRayCastLst[0].HkHitInfo.GetHitEntity() != grid) //If you found something other than the targeted grid do nothing { m_gridRayCastLst.Clear(); return; } Vector3D offsetHit = hit.Value + l.Direction * 0.1; m_gridRayCastLst.Clear(); var block = grid.GetCubeBlock(grid.WorldToGridInteger(offsetHit)); //if (block != this.SlimBlock) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); var invWorld = grid.PositionComp.WorldMatrixNormalizedInv; var gridPos = Vector3D.Transform(offsetHit, invWorld); var gridDir = Vector3D.TransformNormal(l.Direction, invWorld); if (block != null) { //We dont want to damage thruster itself //We dont want smallship thruster to damage heavy armors because of landing if (block.FatBlock != this && (CubeGrid.GridSizeEnum == MyCubeSize.Large || block.BlockDefinition.DeformationRatio > 0.25)) { block.DoDamage(30 * BlockDefinition.FlameDamage, MyDamageType.Environment, attackerId: EntityId); } } if (block == null || block.FatBlock != this) { var areaPlanar = 0.5f * flameInfo.Radius * CubeGrid.GridSize; var areaVertical = 0.5f * CubeGrid.GridSize; grid.Physics.ApplyDeformation(BlockDefinition.FlameDamage, areaPlanar, areaVertical, gridPos, gridDir, MyDamageType.Environment, CubeGrid.GridSizeEnum == MyCubeSize.Small ? 0.1f : 0, attackerId: EntityId); } } } }
public static void InitSpherePhysics(this IMyEntity entity, MyStringHash materialType, Vector3 sphereCenter, float sphereRadius, float mass, float linearDamping, float angularDamping, ushort collisionLayer, RigidBodyFlag rbFlag) { float single1 = mass; mass = ((rbFlag & RigidBodyFlag.RBF_STATIC) != RigidBodyFlag.RBF_DEFAULT) ? 0f : single1; MyPhysicsBody body1 = new MyPhysicsBody(entity, rbFlag); body1.MaterialType = materialType; body1.AngularDamping = angularDamping; body1.LinearDamping = linearDamping; MyPhysicsBody body = body1; HkMassProperties properties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(sphereRadius, mass); HkSphereShape shape = new HkSphereShape(sphereRadius); body.CreateFromCollisionObject((HkShape)shape, sphereCenter, entity.PositionComp.WorldMatrix, new HkMassProperties?(properties), 15); shape.Base.RemoveReference(); entity.Physics = body; }
public static void InitSpherePhysics(this IMyEntity entity, MyStringHash materialType, Vector3 sphereCenter, float sphereRadius, float mass, float linearDamping, float angularDamping, ushort collisionLayer, RigidBodyFlag rbFlag) { mass = (rbFlag & RigidBodyFlag.RBF_STATIC) != 0 ? 0 : mass; var physics = new Sandbox.Engine.Physics.MyPhysicsBody(entity, rbFlag) { MaterialType = materialType, AngularDamping = angularDamping, LinearDamping = linearDamping }; var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(sphereRadius, mass); HkSphereShape shape = new HkSphereShape(sphereRadius); physics.CreateFromCollisionObject((HkShape)shape, sphereCenter, entity.PositionComp.WorldMatrix, massProperties); shape.Base.RemoveReference(); entity.Physics = physics; }
public static void InitSpherePhysics(this IMyEntity entity, MyStringHash materialType, Vector3 sphereCenter, float sphereRadius, float mass, float linearDamping, float angularDamping, ushort collisionLayer, RigidBodyFlag rbFlag) { mass = (rbFlag & RigidBodyFlag.RBF_STATIC) != 0 ? 0 : mass; var physics = new Sandbox.Engine.Physics.MyPhysicsBody(entity, rbFlag) { MaterialType = materialType, AngularDamping = angularDamping, LinearDamping = linearDamping }; var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(sphereRadius, mass); HkSphereShape shape = new HkSphereShape(sphereRadius); physics.CreateFromCollisionObject((HkShape)shape, sphereCenter, entity.PositionComp.WorldMatrix, massProperties); shape.Base.RemoveReference(); entity.Physics = physics; }
private void DamageGrid(FlameInfo flameInfo, LineD l, MyCubeGrid grid) { HkSphereShape sph = new HkSphereShape(flameInfo.Radius * m_thrustDefinition.FlameDamageLengthScale); var transform = MatrixD.CreateWorld(l.From, Vector3.Forward, Vector3.Up); var hit = MyPhysics.CastShapeReturnPoint(l.To, sph, ref transform, (int)MyPhysics.DefaultCollisionLayer, 0.05f); sph.Base.RemoveReference(); if (hit.HasValue) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); MyPhysics.CastRay(hit.Value - l.Direction * 0.1f, hit.Value + l.Direction * 0.1f, m_gridRayCastLst, MyPhysics.ObjectDetectionCollisionLayer); if ((m_gridRayCastLst.Count == 0 || m_gridRayCastLst[0].HkHitInfo.Body.GetEntity() != grid) && grid == CubeGrid) { m_gridRayCastLst.Clear(); return; } m_gridRayCastLst.Clear(); var block = grid.GetCubeBlock(grid.WorldToGridInteger(hit.Value)); //if (block != this.SlimBlock) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); var invWorld = grid.PositionComp.GetWorldMatrixNormalizedInv(); var gridPos = Vector3D.Transform(hit.Value, invWorld); var gridDir = Vector3D.TransformNormal(l.Direction, invWorld); if (block != null) { if (block.FatBlock != this && (CubeGrid.GridSizeEnum == MyCubeSize.Large || block.BlockDefinition.DeformationRatio > 0.25)) { block.DoDamage(30 * m_thrustDefinition.FlameDamage, MyDamageType.Environment, attackerId: EntityId); } } var areaPlanar = 0.5f * flameInfo.Radius * CubeGrid.GridSize; var areaVertical = 0.5f * CubeGrid.GridSize; grid.Physics.ApplyDeformation(m_thrustDefinition.FlameDamage, areaPlanar, areaVertical, gridPos, gridDir, MyDamageType.Environment, CubeGrid.GridSizeEnum == MyCubeSize.Small ? 0.1f : 0, attackerId: EntityId); } } }
static MyEntityPhysicsStateGroup SphereCast(MyEntity entity, float radius, float distance) { if (DEBUG_DRAW) { VRageRender.MyRenderProxy.DebugDrawCapsule(entity.WorldMatrix.Translation, entity.PositionComp.GetPosition() + entity.WorldMatrix.Down * distance, radius, Color.Red, false, false); } // Sphere cast under character Vector3D target = entity.PositionComp.GetPosition() + entity.WorldMatrix.Down * distance; HkSphereShape shape = new HkSphereShape(radius); MatrixD transform = entity.WorldMatrix; var dist = MyPhysics.CastShapeReturnContactBodyData(target, shape, ref transform, MyPhysics.CollisionLayers.CollisionLayerWithoutCharacter, 0); if (dist.HasValue) { var hitEntity = dist.Value.HkHitInfo.GetHitEntity(); if (!IsValid(hitEntity, false)) return null; return FindPhysics(hitEntity); } return null; }
private bool CreateOwnerVirtualPhysics() { if (Owner == null) { return(false); } OwnerVirtualPhysics = new MyCharacterVirtualPhysicsBody(Owner, RigidBodyFlag.RBF_KINEMATIC); var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(0.1f, MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(Owner.Definition.Mass) : Owner.Definition.Mass); HkShape sh = new HkSphereShape(0.1f); OwnerVirtualPhysics.InitialSolverDeactivation = HkSolverDeactivation.Off; MatrixD headWorldMatrix = Owner.GetHeadMatrix(false, forceHeadBone: true); OwnerVirtualPhysics.CreateFromCollisionObject(sh, Vector3.Zero, headWorldMatrix, massProperties, Sandbox.Engine.Physics.MyPhysics.NoCollisionLayer); OwnerVirtualPhysics.RigidBody.EnableDeactivation = false; // Character ray casts includes also NoCollision layer shapes so setup property for ignoring the body OwnerVirtualPhysics.RigidBody.SetProperty(HkCharacterRigidBody.MANIPULATED_OBJECT, 0); sh.RemoveReference(); OwnerVirtualPhysics.Enabled = true; return(true); }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <param name="controlledEntity"></param> /// <param name="shakeActive"></param> /// <param name="headPosition"></param> /// <param name="headDirection"></param> /// <returns>False if no correct position was found</returns> private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection) { var line = new LineD(m_target, m_position); var safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length()); Vector3D castStartSafe; { MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation); double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); if (!safeIntersection.HasValue) safeIntersection = safeOBB.HalfExtent.Length(); double safeDistance = safeIntersection.Value; castStartSafe = line.From + line.Direction * safeDistance; } { double? unsafeIntersection = safeOBB.Intersects(ref safeOBBLine); if (!requireRaycast && unsafeIntersection.HasValue) { var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value; var castEndUnsafe = castStartSafe + line.Direction; // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.DefaultCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return false; } } } if (requireRaycast) { // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.DefaultCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return false; } } HkShape shape = new HkSphereShape(CAMERA_RADIUS); try { // small shape, not causing problems with asteroids generating geometry Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, 15); if (m_rigidList.Count > 0) { bool sameGrid = false; if (MySession.ControlledEntity != null && m_rigidList[0].Body != null) { sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.ControlledEntity; } if (sameGrid) castStartSafe += line.Direction; } var shapeCastLine = new LineD(castStartSafe, m_position); uint steps = 1; uint stepIdx = 0; if (shapeCastLine.Length > SHAPE_CAST_STEP) { steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP); if (steps >= SHAPE_CAST_MAX_STEP_COUNT) steps = SHAPE_CAST_MAX_STEP_COUNT - 1; stepIdx = m_updateCount % steps; m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps); shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step); } if (false) { BoundingBoxD bbox = BoundingBoxD.CreateInvalid(); bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS)); bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS)); VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true); } var matrix = MatrixD.CreateTranslation(shapeCastLine.From); HkContactPointData? cpd; if (controlledEntity.Physics != null && controlledEntity.Physics.CharacterProxy != null) cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, controlledEntity.Physics.CharacterCollisionFilter, 0.0f); else cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, HkGroupFilter.CalcFilterInfo(MyPhysics.DefaultCollisionLayer,0), 0.0f); if (cpd.HasValue) { var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction; m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length(); } else { m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; } float? dist = null; for (int i = 0; i < steps; ++i) { if (m_lastShapeCastDistance[i] != float.PositiveInfinity) dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity); } if (dist.HasValue) { if (dist == 0.0f) { return false; } else { m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value; } } else { m_positionSafe = m_position; } return true; } finally { shape.RemoveReference(); } }
/// <summary> /// Spawns bag around position given by "baseTransform", checks all 4 directions around - forwards (forward, right, backward, left) and on each such direction moves test sphere /// in 3 directions forward (frontChecks), sides (perpendicular to forward direction - rights) and up. If spawn position is not found then position above "worldAabbTopPosition" /// is selected. /// </summary> private static MyEntity SpawnBagAround(MyEntity itemOwner, MyContainerDefinition bagDefinition, int sideCheckCount = 3, int frontCheckCount = 2, int upCheckCount = 5, float stepSize = 1f) { Debug.Assert(Sandbox.Game.Multiplayer.Sync.IsServer); Vector3D?finalPos = null; // Model sphere MyModel bagModel = null; foreach (var componentDef in bagDefinition.DefaultComponents) { if (typeof(MyObjectBuilder_ModelComponent).IsAssignableFrom(componentDef.BuilderType)) { MyComponentDefinitionBase componentDefinition = null; var componentSubtype = bagDefinition.Id.SubtypeId; if (componentDef.SubtypeId.HasValue) { componentSubtype = componentDef.SubtypeId.Value; } if (MyComponentContainerExtension.TryGetComponentDefinition(componentDef.BuilderType, componentSubtype, out componentDefinition)) { var modelComponentDef = componentDefinition as MyModelComponentDefinition; Debug.Assert(modelComponentDef != null); if (modelComponentDef != null) { bagModel = MyModels.GetModelOnlyData(modelComponentDef.Model); } } break; } } Debug.Assert(bagModel != null); if (bagModel == null) { return(null); } float bagBoxRadius = bagModel.BoundingBox.HalfExtents.Max(); HkShape sphere = new HkSphereShape(bagBoxRadius); try { Vector3D basePos = itemOwner.PositionComp.WorldMatrix.Translation; float step = bagBoxRadius * stepSize; // Calculate right, up and forward vectors from gravity Vector3 upDir = -MyGravityProviderSystem.CalculateNaturalGravityInPoint(itemOwner.PositionComp.WorldMatrix.Translation); if (upDir == Vector3.Zero) { upDir = Vector3.Up; } else { upDir.Normalize(); } Vector3 forwardDir; upDir.CalculatePerpendicularVector(out forwardDir); Vector3 rightDir = Vector3.Cross(forwardDir, upDir); rightDir.Normalize(); Vector3D currentPos; Quaternion rot = Quaternion.Identity; Vector3[] forwards = new Vector3[] { forwardDir, rightDir, -forwardDir, -rightDir }; Vector3[] rights = new Vector3[] { rightDir, -forwardDir, -rightDir, forwardDir }; // All sides for (int i = 0; i < forwards.Length && finalPos == null; ++i) { var forward = forwards[i]; var right = rights[i]; // Move forward for (int frontMove = 0; frontMove < frontCheckCount && finalPos == null; ++frontMove) { Vector3D sidePosBase = basePos + 0.25f * forward + bagBoxRadius * forward + frontMove * step * forward - 0.5f * (sideCheckCount - 1) * step * right; // Move perp to forward for (int sideMove = 0; sideMove < sideCheckCount && finalPos == null; ++sideMove) { // Move up for (int upMove = 0; upMove < upCheckCount && finalPos == null; ++upMove) { currentPos = sidePosBase + sideMove * step * right + upMove * step * upDir; if (MyEntities.IsInsideWorld(currentPos) && !MyEntities.IsShapePenetrating(sphere, ref currentPos, ref rot)) { BoundingSphereD boundingSphere = new BoundingSphereD(currentPos, bagBoxRadius); MyVoxelBase overlappedVoxelmap = MySession.Static.VoxelMaps.GetOverlappingWithSphere(ref boundingSphere); if (overlappedVoxelmap == null) { finalPos = currentPos; break; } } } } } } // If not found position then select position above aabb's top. if (finalPos == null) { MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD((BoundingBoxD)itemOwner.PositionComp.LocalAABB, itemOwner.PositionComp.WorldMatrix); Vector3D[] corners = new Vector3D[8]; obb.GetCorners(corners, 0); float dotUp = float.MinValue; foreach (var corner in corners) { var localDot = Vector3.Dot(corner - obb.Center, upDir); dotUp = Math.Max(dotUp, localDot); } finalPos = itemOwner.PositionComp.WorldMatrix.Translation; Debug.Assert(dotUp > 0); if (dotUp > 0) { finalPos = obb.Center + dotUp * upDir; } } } finally { sphere.RemoveReference(); } Debug.Assert(finalPos != null); MatrixD transform = itemOwner.PositionComp.WorldMatrix; transform.Translation = finalPos.Value; MyEntity bagEntity = MyEntities.CreateFromComponentContainerDefinitionAndAdd(bagDefinition.Id); if (bagEntity == null) { return(null); } bagEntity.PositionComp.SetWorldMatrix(transform); bagEntity.Physics.LinearVelocity = Vector3.Zero; bagEntity.Physics.AngularVelocity = Vector3.Zero; return(bagEntity); }
private void RefreshPhysicsBody() { if (CubeGrid.CreatePhysics) { if (Physics != null) { Physics.Close(); } var detectorShape = new HkSphereShape(CubeGrid.GridSize * 0.5f); var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(detectorShape.Radius, VirtualMass != 0 ? VirtualMass : 0.01f); Physics = new Engine.Physics.MyPhysicsBody(this, RigidBodyFlag.RBF_KEYFRAMED_REPORTING); Physics.IsPhantom = false; Physics.CreateFromCollisionObject(detectorShape, Vector3.Zero, WorldMatrix, massProperties, MyPhysics.CollisionLayers.VirtualMassLayer); UpdateIsWorking(); Physics.Enabled = IsWorking && CubeGrid.Physics != null && CubeGrid.Physics.Enabled; Physics.RigidBody.Activate(); detectorShape.Base.RemoveReference(); if (CubeGrid != null && CubeGrid.Physics != null && !CubeGrid.IsStatic) CubeGrid.Physics.UpdateMass(); } }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <returns>False if no correct position was found</returns> private void HandleIntersection(MyEntity controlledEntity) { Debug.Assert(controlledEntity != null); MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity; // line from target to eye LineD line = new LineD(m_target, m_position); // oriented bb of the entity MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity); // oriented bb of the entity + camera radius MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation); // start = target, end = eye // find safe start... LineD safeOBBLine = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From); double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); Vector3D castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; if (controlledEntity.Parent != null && safeIntersection != null) { HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2); //var hitInfo = MyPhysics.CastRay(castStartSafe, m_target); MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe); var hitInfo = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0); MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null; MyEntity entity = controlledEntity; var hitEntityWeldingGroup = hitEntity != null?MyWeldingGroups.Static.GetGroup(hitEntity) : null; bool weldingGroupEquals = false; while (entity != null && !weldingGroupEquals) { if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity)) { weldingGroupEquals = true; } entity = entity.Parent; } if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals) { castStartSafe = hitInfo.Value.Position + line.Direction; } else { safeObb = GetEntitySafeOBB(controlledEntity); safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation); safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; } hkSphere.RemoveReference(); } // raycast against occluders Vector3D safePositionCandidate; //double lastSafeMinimumDistance = m_safeMinimumDistance; m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE); //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance) //{ // castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance; // m_safeMinimumDistance = lastSafeMinimumDistance; //} Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe; MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position, ref castStartSafe, out safePositionCandidate); // visual debugging :) if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true); VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false); VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true); } switch (raycastResult) { case MyCameraRaycastResult.Ok: case MyCameraRaycastResult.FoundOccluder: m_positionCurrentIsSafe = true; { double distFromCandidateToTarget = (safePositionCandidate - m_target).Length(); if ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance) || raycastResult == MyCameraRaycastResult.Ok) { // now we need it from the other side double newDist = (safePositionCandidate - m_position).Length(); // new safe position is further from target => change over time (zoom out) if (m_positionSafeZoomingOutTimeout <= 0) { float distDiffZoomSpeed = 1 - MathHelper.Clamp((float)Math.Abs(m_lastRaycastDist - newDist), 0.0f, 1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_positionSafeZoomingOutSpeed += distDiffZoomSpeed; m_positionSafeZoomingOutSpeed = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f, 1.0f); Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); Vector3D rotatedPositionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate, m_positionSafeZoomingOutSpeed); } else { m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS; Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; } } else { // new safe position is closer or closer than safe distance => instant change m_positionSafeZoomingOutSpeed = 0.0f; // set zooming out speed to zero for next time m_positionSafe = safePositionCandidate; m_positionSafeZoomingOutTimeout = 0; // controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0; m_disableSpringThisFrame = true; } } break; //case MyCameraRaycastResult.FoundOccluderNoSpace: default: m_positionSafeZoomingOutSpeed = 1.0f; // we're in first person, change instantly to third if possible m_positionCurrentIsSafe = false; break; } m_lastRaycastDist = (float)(m_positionSafe - m_position).Length(); if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false); VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false); } }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <returns>False if no correct position was found</returns> private void HandleIntersection(MyEntity controlledEntity) { Debug.Assert(controlledEntity != null); MyEntity parentEntity = controlledEntity.GetTopMostParent() ?? controlledEntity; var parentEntityAsCubeGrid = parentEntity as MyCubeGrid; if (parentEntityAsCubeGrid != null && parentEntityAsCubeGrid.IsStatic) parentEntity = controlledEntity; // cancel previous assignment, topmost parent is a station, we need smaller bounding box // line from target to eye LineD line = new LineD(m_target, m_position); // oriented bb of the entity MyOrientedBoundingBoxD safeObb = GetEntitySafeOBB(parentEntity); // oriented bb of the entity + camera radius MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + (controlledEntity.Parent == null ? 0.5 : 2.0) * CAMERA_RADIUS, safeObb.Orientation); // start = target, end = eye // find safe start... LineD safeOBBLine = new LineD(line.From + line.Direction * 2 * safeObb.HalfExtent.Length(), line.From); double? safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); Vector3D castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; if (controlledEntity.Parent != null && safeIntersection != null) { MatrixD shapeCastStart = MatrixD.CreateTranslation(castStartSafe); HkShape hkSphere = new HkSphereShape(CAMERA_RADIUS * 2); var hitInfo = MyPhysics.CastShapeReturnContactBodyData(m_target, hkSphere, ref shapeCastStart, 0, 0); //VRageRender.MyRenderProxy.DebugDrawCapsule(castStartSafe, m_target, CAMERA_RADIUS * 2, Color.Orange, false); MyEntity hitEntity = hitInfo.HasValue ? hitInfo.Value.HkHitInfo.GetHitEntity() as MyEntity : null; MyEntity entity = controlledEntity; var hitEntityWeldingGroup = hitEntity != null ? MyWeldingGroups.Static.GetGroup(hitEntity) : null; bool weldingGroupEquals = false; while (entity != null && !weldingGroupEquals) { if (hitEntityWeldingGroup == MyWeldingGroups.Static.GetGroup(entity)) weldingGroupEquals = true; entity = entity.Parent; } if (hitInfo.HasValue && hitEntityWeldingGroup != null && weldingGroupEquals) { castStartSafe = castStartSafe + hitInfo.Value.HkHitInfo.HitFraction * (m_target - castStartSafe); } else { safeObb = GetEntitySafeOBB(controlledEntity); safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeObb.Center, safeObb.HalfExtent + 0.5f * CAMERA_RADIUS, safeObb.Orientation); safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); castStartSafe = safeIntersection != null ? (safeOBBLine.From + safeOBBLine.Direction * safeIntersection.Value) : m_target; } hkSphere.RemoveReference(); } // raycast against occluders Vector3D safePositionCandidate; //double lastSafeMinimumDistance = m_safeMinimumDistance; m_safeMinimumDistance = controlledEntity is MyCharacter ? 0 : (castStartSafe - m_target).Length(); // store current safe minimum dist m_safeMinimumDistance = Math.Max(m_safeMinimumDistance, MIN_VIEWER_DISTANCE); //if (lastSafeMinimumDistance + 30.0f < m_safeMinimumDistance) //{ // castStartSafe = m_target + (castStartSafe - m_target) / m_safeMinimumDistance * lastSafeMinimumDistance; // m_safeMinimumDistance = lastSafeMinimumDistance; //} Vector3D raycastOrigin = (controlledEntity is MyCharacter) ? m_target : castStartSafe; MyCameraRaycastResult raycastResult = RaycastOccludingObjects(controlledEntity, ref raycastOrigin, ref m_position, ref castStartSafe, out safePositionCandidate); // visual debugging :) if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawOBB(safeObb, Color.Red, 0.1f, false, true); VRageRender.MyRenderProxy.DebugDrawOBB(safeObbWithCollisionExtents, Color.Yellow, 0.0f, false, true); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, safeOBBLine.To, Color.White, Color.Purple, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(safeOBBLine.From, castStartSafe, Color.White, Color.Red, false); VRageRender.MyRenderProxy.DebugDrawArrow3D(castStartSafe, m_position, Color.White, Color.Orange, false); VRageRender.MyRenderProxy.DebugDrawSphere(castStartSafe, 0.2f, Color.Green, 1.0f, false, true); VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 1.0f, Color.LightPink, 1, false); } switch (raycastResult) { case MyCameraRaycastResult.Ok: case MyCameraRaycastResult.FoundOccluder: m_positionCurrentIsSafe = true; { double distFromCandidateToTarget = (safePositionCandidate - m_target).Length(); if (m_disableSpringThisFrame) { m_lastRaycastDist = (float) distFromCandidateToTarget; } if (!m_disableSpringThisFrame && ((distFromCandidateToTarget > m_lastRaycastDist + CAMERA_RADIUS && distFromCandidateToTarget > m_safeMinimumDistance) || raycastResult == MyCameraRaycastResult.Ok)) { // now we need it from the other side double newDist = (safePositionCandidate - m_position).Length(); // new safe position is further from target => change over time (zoom out) if (m_positionSafeZoomingOutTimeout <= 0) { float distDiffZoomSpeed = 1 - MathHelper.Clamp((float) Math.Abs(m_lastRaycastDist - newDist), 0.0f, 1.0f - MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_positionSafeZoomingOutSpeed += distDiffZoomSpeed; m_positionSafeZoomingOutSpeed = MathHelper.Clamp(m_positionSafeZoomingOutSpeed, 0.0f, 1.0f); Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); Vector3D rotatedPositionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; m_positionSafe = Vector3D.Lerp(rotatedPositionSafe, safePositionCandidate, m_positionSafeZoomingOutSpeed); } else { m_positionSafeZoomingOutTimeout -= MyEngineConstants.UPDATE_STEP_SIZE_IN_MILLISECONDS; Vector3D targetToPosSafe = m_positionSafe - m_target; double lenTargetToPosSafe = targetToPosSafe.Length(); m_positionSafe = m_target + Vector3D.Normalize(safePositionCandidate - m_target) * lenTargetToPosSafe; } } else { // new safe position is closer or closer than safe distance => instant change m_positionSafeZoomingOutSpeed = 0.0f; // set zooming out speed to zero for next time m_positionSafeZoomingOutTimeout = 0;// controlledEntity.Parent != null ? m_positionSafeZoomingOutDefaultTimeoutMs : 0; m_positionSafe = safePositionCandidate; m_disableSpringThisFrame = true; m_positionCurrentIsSafe = distFromCandidateToTarget >= m_safeMinimumDistance; } } break; //case MyCameraRaycastResult.FoundOccluderNoSpace: default: m_positionSafeZoomingOutSpeed = 1.0f; // we're in first person, change instantly to third if possible m_positionCurrentIsSafe = false; break; } m_lastRaycastDist = (float)(m_positionSafe - m_position).Length(); if (m_debugDraw) { VRageRender.MyRenderProxy.DebugDrawSphere(m_positionSafe, 0.225f, Color.Purple, 1, false); VRageRender.MyRenderProxy.DebugDrawSphere(safePositionCandidate, 0.2f, Color.Azure, 1, false); } }
private HkBvShape CreateDetectorShape(Vector3 extents, Mode mode) { if (mode == Mode.Ejector) { var phantom = new HkPhantomCallbackShape(phantom_EnterEjector, phantom_LeaveEjector); var detectorShape = new HkBoxShape(extents); return new HkBvShape(detectorShape, phantom, HkReferencePolicy.TakeOwnership); } else { var phantom = new HkPhantomCallbackShape(phantom_EnterConnector, phantom_LeaveConnector); var detectorShape = new HkSphereShape(extents.AbsMax()); return new HkBvShape(detectorShape, phantom, HkReferencePolicy.TakeOwnership); } }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) MyHud.SelectedObjectHighlight.Visible = false; var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(SHAPE_RADIUS); IMyEntity hitEntity = null; int shapeKey = -1; Vector3D hitPosition = Vector3D.Zero; m_hits.Clear(); try { MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].Body == null || m_hits[index].Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].Body.UserObject == Character.VirtualPhysics) || m_hits[index].Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].Body.GetEntity(); shapeKey = m_hits[index].ShapeKey; hitPosition = m_hits[index].HitPosition; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(shapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, hitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) UseObject.OnSelectionLost(); UseObject = null; } }
private unsafe void AddPhysicalShape(HkShape shape, Matrix rdWorldMatrix) { switch (shape.ShapeType) { case HkShapeType.Sphere: { HkSphereShape shape7 = (HkSphereShape)shape; m_icosphereMesh.AddTrianglesToWorldVertices(rdWorldMatrix.Translation, shape7.Radius); return; } case HkShapeType.Cylinder: case HkShapeType.Triangle: case HkShapeType.TriSampledHeightFieldCollection: case HkShapeType.TriSampledHeightFieldBvTree: break; case HkShapeType.Box: { HkBoxShape shape2 = (HkBoxShape)shape; Vector3D min = new Vector3D((double)-shape2.HalfExtents.X, (double)-shape2.HalfExtents.Y, (double)-shape2.HalfExtents.Z); Vector3D max = new Vector3D((double)shape2.HalfExtents.X, (double)shape2.HalfExtents.Y, (double)shape2.HalfExtents.Z); BoundingBoxD bbox = new BoundingBoxD(min, max); this.BoundingBoxToTranslatedTriangles(bbox, rdWorldMatrix); return; } case HkShapeType.Capsule: return; case HkShapeType.ConvexVertices: { Vector3 vector; HkConvexVerticesShape shape9 = (HkConvexVerticesShape)shape; HkGeometry geometry = new HkGeometry(); shape9.GetGeometry(geometry, out vector); int triangleIndex = 0; while (true) { int num2; int num3; int num4; int num5; if (triangleIndex >= geometry.TriangleCount) { int vertexIndex = 0; while (true) { if (vertexIndex >= geometry.VertexCount) { WorldVerticesInfo worldVertices = m_worldVertices; worldVertices.VerticesMaxValue += geometry.VertexCount; break; } Vector3 vertex = geometry.GetVertex(vertexIndex); Vector3 *vectorPtr1 = (Vector3 *)ref vertex; Vector3.Transform(ref (Vector3) ref vectorPtr1, ref rdWorldMatrix, out vertex); m_worldVertices.Vertices.Add(vertex); vertexIndex++; } break; } geometry.GetTriangle(triangleIndex, out num2, out num3, out num4, out num5); m_worldVertices.Triangles.Add(m_worldVertices.VerticesMaxValue + num2); m_worldVertices.Triangles.Add(m_worldVertices.VerticesMaxValue + num3); m_worldVertices.Triangles.Add(m_worldVertices.VerticesMaxValue + num4); triangleIndex++; } break; } case HkShapeType.List: { HkShapeContainerIterator iterator = ((HkListShape)shape).GetIterator(); while (iterator.IsValid) { this.AddPhysicalShape(iterator.CurrentValue, rdWorldMatrix); iterator.Next(); } return; } case HkShapeType.Mopp: { HkMoppBvTreeShape shape4 = (HkMoppBvTreeShape)shape; this.AddPhysicalShape((HkShape)shape4.ShapeCollection, rdWorldMatrix); return; } case HkShapeType.ConvexTranslate: { HkConvexTranslateShape shape6 = (HkConvexTranslateShape)shape; Matrix matrix = Matrix.CreateTranslation(shape6.Translation); this.AddPhysicalShape((HkShape)shape6.ChildShape, matrix * rdWorldMatrix); return; } case HkShapeType.ConvexTransform: { HkConvexTransformShape shape5 = (HkConvexTransformShape)shape; this.AddPhysicalShape((HkShape)shape5.ChildShape, shape5.Transform * rdWorldMatrix); return; } default: return; } }
/// <summary> /// Spawns bag around position given by "baseTransform", checks all 4 directions around - forwards (forward, right, backward, left) and on each such direction moves test sphere /// in 3 directions forward (frontChecks), sides (perpendicular to forward direction - rights) and up. If spawn position is not found then position above "worldAabbTopPosition" /// is selected. /// </summary> private static MyEntity SpawnBagAround(MyEntity itemOwner, MyContainerDefinition bagDefinition, int sideCheckCount = 3, int frontCheckCount = 2, int upCheckCount = 5, float stepSize = 1f) { Debug.Assert(Sandbox.Game.Multiplayer.Sync.IsServer); Vector3D? finalPos = null; // Model sphere MyModel bagModel = null; foreach (var componentDef in bagDefinition.DefaultComponents) { if (typeof(MyObjectBuilder_ModelComponent).IsAssignableFrom(componentDef.BuilderType)) { MyComponentDefinitionBase componentDefinition = null; var componentSubtype = bagDefinition.Id.SubtypeId; if (componentDef.SubtypeId.HasValue) componentSubtype = componentDef.SubtypeId.Value; if (MyComponentContainerExtension.TryGetComponentDefinition(componentDef.BuilderType, componentSubtype, out componentDefinition)) { var modelComponentDef = componentDefinition as MyModelComponentDefinition; Debug.Assert(modelComponentDef != null); if (modelComponentDef != null) bagModel = MyModels.GetModelOnlyData(modelComponentDef.Model); } break; } } Debug.Assert(bagModel != null); if (bagModel == null) return null; float bagBoxRadius = bagModel.BoundingBox.HalfExtents.Max(); HkShape sphere = new HkSphereShape(bagBoxRadius); try { Vector3D basePos = itemOwner.PositionComp.WorldMatrix.Translation; float step = bagBoxRadius * stepSize; // Calculate right, up and forward vectors from gravity Vector3 upDir = -MyGravityProviderSystem.CalculateNaturalGravityInPoint(itemOwner.PositionComp.WorldMatrix.Translation); if (upDir == Vector3.Zero) upDir = Vector3.Up; else upDir.Normalize(); Vector3 forwardDir; upDir.CalculatePerpendicularVector(out forwardDir); Vector3 rightDir = Vector3.Cross(forwardDir, upDir); rightDir.Normalize(); Vector3D currentPos; Quaternion rot = Quaternion.Identity; Vector3[] forwards = new Vector3[] { forwardDir, rightDir, -forwardDir, -rightDir }; Vector3[] rights = new Vector3[] { rightDir, -forwardDir, -rightDir, forwardDir }; // All sides for (int i = 0; i < forwards.Length && finalPos == null; ++i) { var forward = forwards[i]; var right = rights[i]; // Move forward for (int frontMove = 0; frontMove < frontCheckCount && finalPos == null; ++frontMove) { Vector3D sidePosBase = basePos + 0.25f * forward + bagBoxRadius * forward + frontMove * step * forward - 0.5f * (sideCheckCount - 1) * step * right; // Move perp to forward for (int sideMove = 0; sideMove < sideCheckCount && finalPos == null; ++sideMove) { // Move up for (int upMove = 0; upMove < upCheckCount && finalPos == null; ++upMove) { currentPos = sidePosBase + sideMove * step * right + upMove * step * upDir; if (MyEntities.IsInsideWorld(currentPos) && !MyEntities.IsShapePenetrating(sphere, ref currentPos, ref rot)) { BoundingSphereD boundingSphere = new BoundingSphereD(currentPos, bagBoxRadius); MyVoxelBase overlappedVoxelmap = MySession.Static.VoxelMaps.GetOverlappingWithSphere(ref boundingSphere); if (overlappedVoxelmap == null) { finalPos = currentPos; break; } } } } } } // If not found position then select position above aabb's top. if (finalPos == null) { MyOrientedBoundingBoxD obb = new MyOrientedBoundingBoxD((BoundingBoxD)itemOwner.PositionComp.LocalAABB, itemOwner.PositionComp.WorldMatrix); Vector3D[] corners = new Vector3D[8]; obb.GetCorners(corners, 0); float dotUp = float.MinValue; foreach (var corner in corners) { var localDot = Vector3.Dot(corner - obb.Center, upDir); dotUp = Math.Max(dotUp, localDot); } finalPos = itemOwner.PositionComp.WorldMatrix.Translation; Debug.Assert(dotUp > 0); if (dotUp > 0) finalPos = obb.Center + dotUp * upDir; } } finally { sphere.RemoveReference(); } Debug.Assert(finalPos != null); MatrixD transform = itemOwner.PositionComp.WorldMatrix; transform.Translation = finalPos.Value; MyEntity bagEntity = MyEntities.CreateFromComponentContainerDefinitionAndAdd(bagDefinition.Id); if (bagEntity == null) return null; bagEntity.PositionComp.SetWorldMatrix(transform); bagEntity.Physics.LinearVelocity = Vector3.Zero; bagEntity.Physics.AngularVelocity = Vector3.Zero; return bagEntity; }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_hits.Sort(delegate(MyPhysics.HitInfo info1, MyPhysics.HitInfo info2) { float dot1 = Vector3.Dot(head.Forward, Vector3.Normalize(info1.Position - StartPosition)); float dot2 = Vector3.Dot(head.Forward, Vector3.Normalize(info2.Position - StartPosition)); return(dot1.CompareTo(dot2)); }); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override bool CanPlaceRotor(MyMotorRotor rotorBlock, long builtBy) { BoundingSphereD sphere = rotorBlock.Model.BoundingSphere; sphere.Center = Vector3D.Transform(sphere.Center, rotorBlock.WorldMatrix); CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); HkSphereShape spShape = new HkSphereShape((float)sphere.Radius); Quaternion q = Quaternion.Identity;//Quaternion.CreateFromForwardUp(rotorBlock.WorldMatrix.Forward, rotorBlock.WorldMatrix.Up); var position = rotorBlock.WorldMatrix.Translation; MyPhysics.GetPenetrationsShape(spShape, ref position, ref q, m_tmpList, MyPhysics.CharacterNetworkCollisionLayer); if (m_tmpSet.Count > 1 || m_tmpList.Count > 0) { m_tmpList.Clear(); m_tmpSet.Clear(); if (builtBy == MySession.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); return false; } m_tmpList.Clear(); m_tmpSet.Clear(); return true; }
public void GetFracturesInSphere(ref BoundingSphereD searchSphere, ref List<MyFracturedPiece> output) { var activeFractures = m_piecesTimesOfDeath.Keys; HkShape shape = new HkSphereShape((float)searchSphere.Radius); try { MyPhysics.GetPenetrationsShape(shape, ref searchSphere.Center, ref Quaternion.Identity, m_rigidList, MyPhysics.NotCollideWithStaticLayer); foreach(var rigidBody in m_rigidList) { var fracture = rigidBody.GetCollisionEntity() as MyFracturedPiece; if (fracture != null) output.Add(fracture); } } finally { m_rigidList.Clear(); shape.RemoveReference(); } }
private void ThrustDamage() { if (m_flames.Count > 0 && MySession.Static.ThrusterDamage && Sync.IsServer && IsWorking && CubeGrid.InScene && CubeGrid.Physics != null && CubeGrid.Physics.Enabled) { if (CurrentStrength == 0 && !MyFakes.INACTIVE_THRUSTER_DMG) return; UpdateThrustFlame(); foreach (var flameInfo in m_flames) { var l = GetDamageCapsuleLine(flameInfo); HkShape shape; if (l.Length != 0) shape = new HkCapsuleShape(Vector3.Zero, l.To - l.From, flameInfo.Radius * BlockDefinition.FlameDamageLengthScale); else shape = new HkSphereShape(flameInfo.Radius * BlockDefinition.FlameDamageLengthScale); MyPhysics.GetPenetrationsShape(shape, ref l.From, ref Quaternion.Identity, m_flameCollisionsList, 0); shape.RemoveReference(); foreach (var obj in m_flameCollisionsList) { var ent = obj.GetCollisionEntity(); if (ent == null || ent.Equals(this)) continue; if (!(ent is MyCharacter)) ent = ent.GetTopMostParent(); if (m_damagedEntities.Contains(ent)) continue; else m_damagedEntities.Add(ent); if (ent is IMyDestroyableObject) (ent as IMyDestroyableObject).DoDamage(flameInfo.Radius * BlockDefinition.FlameDamage * 10, MyDamageType.Environment, true, attackerId: EntityId); else if (ent is MyCubeGrid) { var grid = ent as MyCubeGrid; if (grid.BlocksDestructionEnabled) { DamageGrid(flameInfo, l, grid); } } } m_damagedEntities.Clear(); m_flameCollisionsList.Clear(); } } }
protected override void DoDetection(bool useHead) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; //var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { isValidBlock = m_hits[index].HkHitInfo.Body != null && m_hits[index].HkHitInfo.GetHitEntity() != Character && m_hits[index].HkHitInfo.GetHitEntity() != null && !m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = m_hits[index].HkHitInfo.GetHitEntity() != null && m_hits[index].HkHitInfo.GetHitEntity().Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(SHAPE_RADIUS); IMyEntity hitEntity = null; int shapeKey = -1; Vector3D hitPosition = Vector3D.Zero; m_hits.Clear(); try { MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].Body == null || m_hits[index].Body.UserObject == Character.Physics || (Character.VirtualPhysics != null && m_hits[index].Body.UserObject == Character.VirtualPhysics) || m_hits[index].Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].Body.GetEntity(); shapeKey = m_hits[index].ShapeKey; hitPosition = m_hits[index].HitPosition; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(shapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, hitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = 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); var ore = Item.Content as MyObjectBuilder_Ore; string model = physicalItem.Model; float scale = 1.0f; VoxelMaterial = null; if (ore != null) { foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if (mat.MinedOre == ore.SubtypeName) { VoxelMaterial = mat; model = MyDebris.GetRandomDebrisVoxel(); scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); break; } } } if (scale < 0.15f) { scale = 0.15f; } var voxelRender = (Entity.Render as MyRenderComponentDebrisVoxel); voxelRender.VoxelMaterialIndex = VoxelMaterial.Index; voxelRender.TexCoordOffset = 5; voxelRender.TexCoordScale = 8; Entity.Init(new StringBuilder("Meteor"), model, null, null, null); Entity.PositionComp.Scale = scale; // Must be set after init var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(Entity.PositionComp.LocalVolume.Radius, (float)(4 / 3f * Math.PI * Math.Pow(Entity.PositionComp.LocalVolume.Radius, 3)) * 3.7f); HkSphereShape transform = new HkSphereShape(Entity.PositionComp.LocalVolume.Radius); if (Entity.Physics != null) { Entity.Physics.Close(); } Entity.Physics = new MyPhysicsBody(Entity, RigidBodyFlag.RBF_BULLET); Entity.Physics.ReportAllContacts = true; Entity.GetPhysicsBody().CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.CollisionLayers.DefaultCollisionLayer); Entity.Physics.Enabled = true; Entity.Physics.RigidBody.ContactPointCallbackEnabled = true; Entity.GetPhysicsBody().ContactPointCallback += RigidBody_ContactPointCallback; transform.Base.RemoveReference(); Entity.Physics.PlayCollisionCueEnabled = true; m_timeCreated = MySandboxGame.TotalGamePlayTimeInMilliseconds; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME | MyEntityUpdateEnum.EACH_100TH_FRAME; StartLoopSound(); }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) MyHud.SelectedObjectHighlight.RemoveHighlight(); var head = Character.GetHeadMatrix(false); Vector3D from = head.Translation; Vector3D dir = head.Forward; if (!useHead) { var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) if (Character == MySession.Static.LocalCharacter) { from = MySector.MainCamera.WorldMatrix.Translation; dir = MySector.MainCamera.WorldMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, from, (Vector3)dir); } else { from = headPos; dir = head.Forward; } } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_rayOrigin = from; m_rayDirection = dir; m_hits.Sort(CompareHits); if (m_hits.Count > 0) { bool isValidBlock = false; bool isPhysicalBlock = false; for (int index = 0; index < m_hits.Count; index++) { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); // Ignore self-interaction if (entity == Character) continue; if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // If hit-entity is a grid, raycast it to see which block we hit first if (entity is MyCubeGrid) { MyCubeGrid grid = entity as MyCubeGrid; List<MyCube> cubeList = grid.RayCastBlocksAllOrdered(from, to); if (cubeList != null && cubeList.Count > 0) { var slimblock = cubeList[0].CubeBlock; if (slimblock.FatBlock != null) { entity = slimblock.FatBlock; isPhysicalBlock = true; hitEntity = entity; ShapeKey = 0; } } } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; break; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); break; } index++; } } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx? result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) UseObject.OnSelectionLost(); UseObject = null; } DisableDetectors(); }
protected virtual bool CanPlaceTop(MyAttachableTopBlockBase topBlock, long builtBy) { // Compute the rough actual position for the head, this improves the detection if it can be placed float topDistance = (Subpart3.Model.BoundingBoxSize.Y); Vector3D topPosition = this.Subpart3.WorldMatrix.Translation + this.WorldMatrix.Up * topDistance; float topRadius = topBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = topBlock.Model.BoundingSphere; sphere.Center = topPosition; sphere.Radius = topRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because top sometimes intersects piston), don't add top if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); return false; } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(topRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(topBlock.ModelCollision.HavokCollisionShapes[0], ref topPosition, ref q, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the head // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_penetrations.Count; i++) { MyCubeGrid grid = m_penetrations[i].GetCollisionEntity().GetTopMostParent() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_penetrations.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); return false; } } m_penetrations.Clear(); return true; }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) MyHud.SelectedObjectHighlight.Visible = false; var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5f; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; m_hits.Clear(); try { MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); HitBody = m_hits[index].HkHitInfo.Body; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) UseObject.OnSelectionLost(); UseObject = null; } }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) MyHud.SelectedObjectHighlight.RemoveHighlight(); var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_hits.Sort(delegate(MyPhysics.HitInfo info1, MyPhysics.HitInfo info2) { float dot1 = Vector3.Dot(head.Forward, Vector3.Normalize(info1.Position - StartPosition)); float dot2 = Vector3.Dot(head.Forward, Vector3.Normalize(info2.Position - StartPosition)); return dot1.CompareTo(dot2); }); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx? result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) UseObject.OnSelectionLost(); UseObject = null; } DisableDetectors(); }
/// <summary> /// Processes previously acquired raycast results. /// Returns safe camera eye position (As far from target as possible, but not colliding, best case = desired eye pos). /// </summary> private MyCameraRaycastResult RaycastOccludingObjects(MyEntity controlledEntity, ref Vector3D raycastOrigin, ref Vector3D raycastEnd, ref Vector3D raycastSafeCameraStart, out Vector3D outSafePosition) { Vector3D rayDirection = raycastEnd - raycastOrigin; rayDirection.Normalize(); outSafePosition = m_position; double closestDistanceSquared = double.PositiveInfinity; bool positionChanged = false; // ray cast - very close objects MyPhysics.CastRay(raycastOrigin, raycastOrigin + CAMERA_RADIUS * rayDirection, m_raycastList); foreach (MyPhysics.HitInfo rb in m_raycastList) { if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody) || rb.HkHitInfo.GetHitEntity() == controlledEntity) { continue; } if (rb.HkHitInfo.GetHitEntity() is IMyHandheldGunObject <Game.Weapons.MyDeviceBase> ) // ignore player weapons { continue; } double distSq = Vector3D.DistanceSquared(rb.Position, raycastOrigin); if (distSq < closestDistanceSquared) { closestDistanceSquared = distSq; float dist = (float)Math.Sqrt(distSq) - CAMERA_RADIUS; outSafePosition = raycastOrigin + rayDirection * dist; positionChanged = true; } } if (m_debugDraw) { foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawPoint(raycastResult.Position, Color.Red, false); } } // shape cast - further objects if ((raycastEnd - raycastOrigin).LengthSquared() > CAMERA_RADIUS * CAMERA_RADIUS) { HkShape shapeSphere = new HkSphereShape(CAMERA_RADIUS); MatrixD raycastOriginTransform = MatrixD.Identity; raycastOriginTransform.Translation = raycastOrigin + CAMERA_RADIUS * rayDirection; MyPhysics.CastShapeReturnContactBodyDatas(raycastEnd, shapeSphere, ref raycastOriginTransform, 0, 0, m_raycastList); //MyPhysics.CastRay(raycastOrigin + CAMERA_RADIUS * rayDirection, raycastEnd, m_raycastList, 0); foreach (MyPhysics.HitInfo rb in m_raycastList) { IMyEntity hitEntity = rb.HkHitInfo.GetHitEntity(); if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || hitEntity == controlledEntity || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody)) { continue; } if (hitEntity is IMyHandheldGunObject <Game.Weapons.MyDeviceBase> ) { // ignore player weapons continue; } double distSq = Vector3D.DistanceSquared(rb.Position, raycastOrigin); if (distSq < closestDistanceSquared) { closestDistanceSquared = distSq; float dist = (float)Math.Sqrt(distSq); outSafePosition = raycastOrigin + rayDirection * dist; positionChanged = true; } } shapeSphere.RemoveReference(); } if (m_debugDraw) { foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawSphere(raycastResult.Position, CAMERA_RADIUS, Color.Red, 1, false); } } if (closestDistanceSquared < (raycastSafeCameraStart - raycastOrigin).LengthSquared() + CAMERA_RADIUS) { return(MyCameraRaycastResult.FoundOccluderNoSpace); // obstacle too close, switch to first person } // last check - isn't there voxel between safe pos and entity pos if (!positionChanged) { //Vector3D entityPos = controlledEntity.PositionComp.GetPosition(); MyPhysics.CastRay(m_target, raycastSafeCameraStart, m_raycastList); if (m_debugDraw) { BoundingBoxD bb = new BoundingBoxD(m_target, raycastSafeCameraStart); VRageRender.MyRenderProxy.DebugDrawAABB(bb, Color.Magenta); } foreach (var collision in m_raycastList) { if (collision.HkHitInfo.GetHitEntity() is MyVoxelBase) { return(MyCameraRaycastResult.FoundOccluderNoSpace); } } } return(positionChanged ? MyCameraRaycastResult.FoundOccluder : MyCameraRaycastResult.Ok); }
protected override bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { // Compute the rough actual position for the wheel, this improves the detection if it can be placed float wheelDistance = BlockDefinition.Size.Y * CubeGrid.GridSize - 0.2f * CubeGrid.GridSize; Vector3D wheelPosition = this.WorldMatrix.Translation + this.WorldMatrix.Up * wheelDistance; float wheelRadius = rotorBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = rotorBlock.Model.BoundingSphere; sphere.Center = wheelPosition; sphere.Radius = wheelRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because wheel sometimes intersects suspension), don't add wheel if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); return false; } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(wheelRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(rotorBlock.ModelCollision.HavokCollisionShapes[0], ref wheelPosition, ref q, m_tmpList, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the wheel // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_tmpList.Count; i++) { MyCubeGrid grid = m_tmpList[i].GetCollisionEntity() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_tmpList.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); return false; } } m_tmpList.Clear(); return true; }
private void DoDetection(bool useHead, bool doModelIntersection) { if (Character == MySession.Static.ControlledEntity) { MyHud.SelectedObjectHighlight.RemoveHighlight(); } var head = Character.GetHeadMatrix(false); Vector3D from = head.Translation; Vector3D dir = head.Forward; if (!useHead) { var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) if (Character == MySession.Static.LocalCharacter) { from = MySector.MainCamera.WorldMatrix.Translation; dir = MySector.MainCamera.WorldMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, from, (Vector3)dir); } else { from = headPos; dir = head.Forward; } } Vector3D to = from + dir * 2.5;//MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; HitTag = null; m_hits.Clear(); Vector3 interactivePosition = Vector3D.Zero; try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); m_rayOrigin = from; m_rayDirection = dir; m_hits.Sort(CompareHits); if (m_hits.Count > 0) { bool isValidBlock = false; bool isPhysicalBlock = false; for (int index = 0; index < m_hits.Count; index++) { HkRigidBody body = m_hits[index].HkHitInfo.Body; IMyEntity entity = m_hits[index].HkHitInfo.GetHitEntity(); // Ignore self-interaction if (entity == Character) { continue; } if (entity is VRage.Game.Entity.MyEntitySubpart) { entity = entity.Parent; } isValidBlock = body != null && entity != null && entity != Character && !body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = entity != null && entity.Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = entity; ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // If hit-entity is a grid, raycast it to see which block we hit first if (entity is MyCubeGrid) { MyCubeGrid grid = entity as MyCubeGrid; List <MyCube> cubeList = grid.RayCastBlocksAllOrdered(from, to); if (cubeList != null && cubeList.Count > 0) { var slimblock = cubeList[0].CubeBlock; if (slimblock.FatBlock != null) { entity = slimblock.FatBlock; isPhysicalBlock = true; hitEntity = entity; ShapeKey = 0; } } } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = body; HitNormal = m_hits[index].HkHitInfo.Normal; HitPosition = m_hits[index].GetFixedPosition(); HitMaterial = body.GetBody().GetMaterialAt(HitPosition); interactivePosition = HitPosition; break; } else if (body != null) { interactivePosition = m_hits[index].GetFixedPosition(); break; } index++; } } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } // Do accurate collision checking on model if (doModelIntersection) { LineD line = new LineD(from, to); var character = hitEntity as MyCharacter; if (character == null) { MyIntersectionResultLineTriangleEx?result; bool success = hitEntity.GetIntersectionWithLine(ref line, out result, IntersectionFlags.ALL_TRIANGLES); if (success) { HitPosition = result.Value.IntersectionPointInWorldSpace; HitNormal = result.Value.NormalInWorldSpace; } } else { bool success = character.GetIntersectionWithLine(ref line, ref CharHitInfo); if (success) { HitPosition = CharHitInfo.Triangle.IntersectionPointInWorldSpace; HitNormal = CharHitInfo.Triangle.NormalInWorldSpace; HitTag = CharHitInfo; } } } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, interactivePosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
/// <summary> /// Processes previously acquired raycast results. /// Returns safe camera eye position (As far from target as possible, but not colliding, best case = desired eye pos). /// </summary> private MyCameraRaycastResult RaycastOccludingObjects(MyEntity controlledEntity, ref Vector3D raycastOrigin, ref Vector3D raycastEnd, ref Vector3D raycastSafeCameraStart, out Vector3D outSafePosition) { Vector3D rayDirection = raycastEnd - raycastOrigin; rayDirection.Normalize(); outSafePosition = m_position; double closestDistanceSquared = double.PositiveInfinity; bool positionChanged = false; // ray cast - very close objects MyPhysics.CastRay(raycastOrigin, raycastOrigin + CAMERA_RADIUS * rayDirection, m_raycastList); foreach (MyPhysics.HitInfo rb in m_raycastList) { if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody) || rb.HkHitInfo.GetHitEntity() == controlledEntity) continue; if (rb.HkHitInfo.GetHitEntity() is IMyHandheldGunObject<Game.Weapons.MyDeviceBase>) // ignore player weapons continue; double distSq = Vector3D.DistanceSquared(rb.Position, raycastOrigin); if (distSq < closestDistanceSquared) { closestDistanceSquared = distSq; double dist = Math.Sqrt(distSq) - CAMERA_RADIUS; outSafePosition = raycastOrigin + rayDirection * dist; positionChanged = true; } } if (m_debugDraw) foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawPoint(raycastResult.Position, Color.Red, false); } // shape cast - further objects if ((raycastEnd - raycastOrigin).LengthSquared() > CAMERA_RADIUS * CAMERA_RADIUS) { HkShape shapeSphere = new HkSphereShape(CAMERA_RADIUS); MatrixD raycastOriginTransform = MatrixD.Identity; raycastOriginTransform.Translation = raycastOrigin + CAMERA_RADIUS * rayDirection; MyPhysics.CastShapeReturnContactBodyDatas(raycastEnd, shapeSphere, ref raycastOriginTransform, 0, 0, m_raycastList); //MyPhysics.CastRay(raycastOrigin + CAMERA_RADIUS * rayDirection, raycastEnd, m_raycastList, 0); float closestFraction = 1; foreach (MyPhysics.HitInfo rb in m_raycastList) { IMyEntity hitEntity = rb.HkHitInfo.GetHitEntity(); if (rb.HkHitInfo.Body == null || rb.HkHitInfo.Body.UserObject == null || hitEntity == controlledEntity || !(rb.HkHitInfo.Body.UserObject is MyPhysicsBody)) continue; if (hitEntity is IMyHandheldGunObject<Game.Weapons.MyDeviceBase>) // ignore player weapons continue; Vector3D safePos = Vector3D.Lerp(raycastOrigin, raycastEnd - CAMERA_RADIUS * rayDirection, Math.Max(rb.HkHitInfo.HitFraction, 0.0001)); double distSq = Vector3D.DistanceSquared(raycastOrigin, outSafePosition); if (rb.HkHitInfo.HitFraction < closestFraction && distSq < closestDistanceSquared) { outSafePosition = safePos; closestDistanceSquared = distSq; positionChanged = true; closestFraction = rb.HkHitInfo.HitFraction; } } shapeSphere.RemoveReference(); } if (m_debugDraw) foreach (var raycastResult in m_raycastList) { VRageRender.MyRenderProxy.DebugDrawSphere(raycastResult.Position, CAMERA_RADIUS, Color.Red, 1, false); } if (closestDistanceSquared < (raycastSafeCameraStart - raycastOrigin).LengthSquared() + CAMERA_RADIUS) { return MyCameraRaycastResult.FoundOccluderNoSpace; // obstacle too close, switch to first person } // last check - isn't there voxel between safe pos and entity pos if (!positionChanged) { //Vector3D entityPos = controlledEntity.PositionComp.GetPosition(); MyPhysics.CastRay(m_target, raycastSafeCameraStart, m_raycastList); if (m_debugDraw) { BoundingBoxD bb = new BoundingBoxD(m_target, raycastSafeCameraStart); VRageRender.MyRenderProxy.DebugDrawAABB(bb, Color.Magenta); } foreach (var collision in m_raycastList) { if (collision.HkHitInfo.GetHitEntity() is MyVoxelBase) { return MyCameraRaycastResult.FoundOccluderNoSpace; } } } return positionChanged ? MyCameraRaycastResult.FoundOccluder : MyCameraRaycastResult.Ok; }
private void ThrustDamage() { if (m_flames.Count > 0 && MySession.Static.ThrusterDamage && Sync.IsServer && IsWorking && CubeGrid.InScene && CubeGrid.Physics != null && CubeGrid.Physics.Enabled) { if (CurrentStrength == 0 && !MyFakes.INACTIVE_THRUSTER_DMG) { return; } UpdateThrustFlame(); foreach (var flameInfo in m_flames) { var l = GetDamageCapsuleLine(flameInfo); HkShape shape; if (l.Length != 0) { shape = new HkCapsuleShape(Vector3.Zero, l.To - l.From, flameInfo.Radius * m_thrustDefinition.FlameDamageLengthScale); } else { shape = new HkSphereShape(flameInfo.Radius * m_thrustDefinition.FlameDamageLengthScale); } MyPhysics.GetPenetrationsShape(shape, ref l.From, ref Quaternion.Identity, m_flameCollisionsList, 0); shape.RemoveReference(); foreach (var obj in m_flameCollisionsList) { var entity = obj.GetEntity(); if (entity == null) { continue; } if (entity.Equals(this)) { continue; } if (!(entity is MyCharacter)) { entity = entity.GetTopMostParent(); } if (m_damagedEntities.Contains(entity)) { continue; } else { m_damagedEntities.Add(entity); } if (entity is IMyDestroyableObject) { (entity as IMyDestroyableObject).DoDamage(flameInfo.Radius * m_thrustDefinition.FlameDamage * 10, MyDamageType.Environment, true); } else if (entity is MyCubeGrid && MySession.Static.DestructibleBlocks) { DamageGrid(flameInfo, l, entity as MyCubeGrid); } } m_damagedEntities.Clear(); m_flameCollisionsList.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; }
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); var ore = Item.Content as MyObjectBuilder_Ore; string model = physicalItem.Model; float scale = 1.0f; VoxelMaterial = null; if (ore != null) { foreach (var mat in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if (mat.MinedOre == ore.SubtypeName) { VoxelMaterial = mat; model = MyDebris.GetRandomDebrisVoxel(); scale = (float)Math.Pow((float)Item.Amount * physicalItem.Volume / MyDebris.VoxelDebrisModelVolume, 0.333f); break; } } } if (scale < 0.15f) scale = 0.15f; var voxelRender = (Entity.Render as MyRenderComponentDebrisVoxel); voxelRender.VoxelMaterialIndex = VoxelMaterial.Index; voxelRender.TexCoordOffset = 5; voxelRender.TexCoordScale = 8; Entity.Init(new StringBuilder("Meteor"), model, null, null, null); Entity.PositionComp.Scale = scale; // Must be set after init var massProperties = HkInertiaTensorComputer.ComputeSphereVolumeMassProperties(Entity.PositionComp.LocalVolume.Radius, (float)(4 / 3f * Math.PI * Math.Pow(Entity.PositionComp.LocalVolume.Radius, 3)) * 3.7f); HkSphereShape transform = new HkSphereShape(Entity.PositionComp.LocalVolume.Radius); if (Entity.Physics != null) Entity.Physics.Close(); Entity.Physics = new MyPhysicsBody(Entity, RigidBodyFlag.RBF_BULLET); Entity.Physics.ReportAllContacts = true; Entity.GetPhysicsBody().CreateFromCollisionObject(transform, Vector3.Zero, MatrixD.Identity, massProperties, MyPhysics.CollisionLayers.DefaultCollisionLayer); Entity.Physics.Enabled = true; Entity.Physics.RigidBody.ContactPointCallbackEnabled = true; Entity.GetPhysicsBody().ContactPointCallback += RigidBody_ContactPointCallback; transform.Base.RemoveReference(); Entity.Physics.PlayCollisionCueEnabled = true; m_timeCreated = MySandboxGame.TotalGamePlayTimeInMilliseconds; NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME | MyEntityUpdateEnum.EACH_100TH_FRAME; StartLoopSound(); }
protected override void DoDetection(bool useHead) { if (Character == MySession.Static.ControlledEntity) MyHud.SelectedObjectHighlight.RemoveHighlight(); var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; //var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; HitMaterial = MyStringHash.NullOrEmpty; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); if (m_hits.Count > 0) { int index = 0; bool isValidBlock = false; bool isPhysicalBlock = false; do { isValidBlock = m_hits[index].HkHitInfo.Body != null && m_hits[index].HkHitInfo.GetHitEntity() != Character && m_hits[index].HkHitInfo.GetHitEntity() != null && !m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT); isPhysicalBlock = m_hits[index].HkHitInfo.GetHitEntity() != null && m_hits[index].HkHitInfo.GetHitEntity().Physics != null; if (hitEntity == null && isValidBlock) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); } // Set hit material etc. only for object's that have physical representation in the world, this exclude detectors if (HitMaterial.Equals(MyStringHash.NullOrEmpty) && isValidBlock && isPhysicalBlock) { HitBody = m_hits[index].HkHitInfo.Body; HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); } index++; } while (index < m_hits.Count && (!isValidBlock || !isPhysicalBlock)); } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) UseObject.OnSelectionLost(); UseObject = null; } DisableDetectors(); }
private void DamageGrid(FlameInfo flameInfo, LineD l, MyCubeGrid grid) { HkSphereShape sph = new HkSphereShape(flameInfo.Radius * BlockDefinition.FlameDamageLengthScale); var transform = MatrixD.CreateWorld(l.From, Vector3.Forward, Vector3.Up); var hit = MyPhysics.CastShapeReturnPoint(l.To, sph, ref transform, (int)MyPhysics.DefaultCollisionLayer, 0.05f); sph.Base.RemoveReference(); if (hit.HasValue) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); MyPhysics.CastRay(hit.Value - l.Direction * 0.1f, hit.Value + l.Direction * 0.1f, m_gridRayCastLst, MyPhysics.ObjectDetectionCollisionLayer); if ((m_gridRayCastLst.Count == 0 || m_gridRayCastLst[0].HkHitInfo.GetHitEntity() != grid) && grid == CubeGrid) { m_gridRayCastLst.Clear(); return; } m_gridRayCastLst.Clear(); var block = grid.GetCubeBlock(grid.WorldToGridInteger(hit.Value)); //if (block != this.SlimBlock) { //MyRenderProxy.DebugDrawSphere(hit.Value, 0.1f, Color.Green.ToVector3(), 1, true); var invWorld = grid.PositionComp.GetWorldMatrixNormalizedInv(); var gridPos = Vector3D.Transform(hit.Value, invWorld); var gridDir = Vector3D.TransformNormal(l.Direction, invWorld); if (block != null) if (block.FatBlock != this && (CubeGrid.GridSizeEnum == MyCubeSize.Large || block.BlockDefinition.DeformationRatio > 0.25)) { block.DoDamage(30 * BlockDefinition.FlameDamage, MyDamageType.Environment, attackerId: EntityId); } var areaPlanar = 0.5f * flameInfo.Radius * CubeGrid.GridSize; var areaVertical = 0.5f * CubeGrid.GridSize; grid.Physics.ApplyDeformation(BlockDefinition.FlameDamage, areaPlanar, areaVertical, gridPos, gridDir, MyDamageType.Environment, CubeGrid.GridSizeEnum == MyCubeSize.Small ? 0.1f : 0, attackerId: EntityId); } } }
protected override void DoDetection(bool useHead) { if (Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = false; } var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version //var cameraMatrix = MySector.MainCamera.WorldMatrix; var cameraMatrix = Character.Get3rdBoneMatrix(true, true); dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * 2.5f; StartPosition = from; MatrixD matrix = MatrixD.CreateTranslation(from); HkShape shape = new HkSphereShape(ShapeRadius); IMyEntity hitEntity = null; ShapeKey = uint.MaxValue; HitPosition = Vector3D.Zero; HitNormal = Vector3.Zero; m_hits.Clear(); try { EnableDetectorsInArea(from); MyPhysics.CastShapeReturnContactBodyDatas(to, shape, ref matrix, 0, 0f, m_hits); int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT))) // Skip invalid hits and self character { index++; } if (index < m_hits.Count) { hitEntity = m_hits[index].HkHitInfo.GetHitEntity(); ShapeKey = m_hits[index].HkHitInfo.GetShapeKey(0); HitPosition = m_hits[index].Position; HitNormal = m_hits[index].HkHitInfo.Normal; HitMaterial = m_hits[index].HkHitInfo.Body.GetBody().GetMaterialAt(HitPosition + HitNormal * 0.1f); HitBody = m_hits[index].HkHitInfo.Body; } } finally { shape.RemoveReference(); } bool hasInteractive = false; var interactive = hitEntity as IMyUseObject; DetectedEntity = hitEntity; if (hitEntity != null) { MyUseObjectsComponentBase useObject = null; hitEntity.Components.TryGet <MyUseObjectsComponentBase>(out useObject); if (useObject != null) { interactive = useObject.GetInteractiveObject(ShapeKey); } } if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, HitPosition)) < interactive.InteractiveDistance && Character == MySession.ControlledEntity) { MyHud.SelectedObjectHighlight.Visible = true; MyHud.SelectedObjectHighlight.InteractiveObject = interactive; UseObject = interactive; hasInteractive = true; } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } DisableDetectors(); }
/// <summary> /// Handles camera collisions with environment /// </summary> /// <param name="controlledEntity"></param> /// <param name="shakeActive"></param> /// <param name="headPosition"></param> /// <param name="headDirection"></param> /// <returns>False if no correct position was found</returns> private bool HandleIntersection(MyEntity controlledEntity, MyOrientedBoundingBoxD safeOBB, bool requireRaycast, bool shakeActive, Vector3D headPosition, Vector3 headDirection) { var line = new LineD(m_target, m_position); var safeOBBLine = new LineD(line.From, line.From + line.Direction * 2 * safeOBB.HalfExtent.Length()); Vector3D castStartSafe; { MyOrientedBoundingBoxD safeObbWithCollisionExtents = new MyOrientedBoundingBoxD(safeOBB.Center, safeOBB.HalfExtent + 2 * CAMERA_RADIUS, safeOBB.Orientation); double?safeIntersection = safeObbWithCollisionExtents.Intersects(ref safeOBBLine); if (!safeIntersection.HasValue) { safeIntersection = safeOBB.HalfExtent.Length(); } double safeDistance = safeIntersection.Value; castStartSafe = line.From + line.Direction * safeDistance; } { double?unsafeIntersection = safeOBB.Intersects(ref safeOBBLine); if (!requireRaycast && unsafeIntersection.HasValue) { var castStartUnsafe = line.From + line.Direction * unsafeIntersection.Value; var castEndUnsafe = castStartSafe + line.Direction; // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(castStartUnsafe, castEndUnsafe, m_raycastList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return(false); } } } if (requireRaycast) { // short raycast, not causing problems with asteroids generating geometry Physics.MyPhysics.CastRay(line.From, castStartSafe + line.Direction, m_raycastList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (!IsRaycastOK(m_raycastList)) { return(false); } } HkShape shape = new HkSphereShape(CAMERA_RADIUS); try { // small shape, not causing problems with asteroids generating geometry Physics.MyPhysics.GetPenetrationsShape(shape, ref castStartSafe, ref Quaternion.Identity, m_rigidList, MyPhysics.CollisionLayers.CharacterCollisionLayer); if (m_rigidList.Count > 0) { bool sameGrid = false; if (MySession.Static.ControlledEntity != null && m_rigidList[0].Body != null) { sameGrid = m_rigidList[0].GetCollisionEntity() == MySession.Static.ControlledEntity; } if (sameGrid) { castStartSafe += line.Direction; } } var shapeCastLine = new LineD(castStartSafe, m_position); uint steps = 1; uint stepIdx = 0; if (shapeCastLine.Length > SHAPE_CAST_STEP) { steps = (uint)Math.Ceiling(shapeCastLine.Length / SHAPE_CAST_STEP); if (steps >= SHAPE_CAST_MAX_STEP_COUNT) { steps = SHAPE_CAST_MAX_STEP_COUNT - 1; } stepIdx = m_updateCount % steps; m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; Vector3D step = shapeCastLine.Direction * (shapeCastLine.Length / steps); shapeCastLine = new LineD(castStartSafe + stepIdx * step, castStartSafe + (stepIdx + 1) * step); } if (false) { BoundingBoxD bbox = BoundingBoxD.CreateInvalid(); bbox.Include(new BoundingSphereD(shapeCastLine.From, CAMERA_RADIUS)); bbox.Include(new BoundingSphereD(shapeCastLine.To, CAMERA_RADIUS)); VRageRender.MyRenderProxy.DebugDrawAABB(bbox, Color.Crimson, 1f, 1f, true); } var matrix = MatrixD.CreateTranslation(shapeCastLine.From); HkContactPointData?cpd; if (controlledEntity.Physics != null && controlledEntity.GetPhysicsBody().CharacterProxy != null) { cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.CharacterCollisionLayer, 0.0f); } else { cpd = MyPhysics.CastShapeReturnContactData(shapeCastLine.To, shape, ref matrix, MyPhysics.CollisionLayers.DefaultCollisionLayer, 0.0f); } if (cpd.HasValue) { var point = shapeCastLine.From + shapeCastLine.Direction * shapeCastLine.Length * cpd.Value.DistanceFraction; m_lastShapeCastDistance[stepIdx] = (float)(castStartSafe - point).Length(); } else { m_lastShapeCastDistance[stepIdx] = float.PositiveInfinity; } float?dist = null; for (int i = 0; i < steps; ++i) { if (m_lastShapeCastDistance[i] != float.PositiveInfinity) { dist = Math.Min(m_lastShapeCastDistance[i], dist ?? float.PositiveInfinity); } } if (dist.HasValue) { if (dist == 0.0f) { return(false); } else { m_positionSafe = castStartSafe + shapeCastLine.Direction * dist.Value; } } else { m_positionSafe = m_position; } return(true); } finally { shape.RemoveReference(); } }
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; }