From d723d3b850adf29df65e9f0f3197bcf2195308a7 Mon Sep 17 00:00:00 2001 From: AndresTraks Date: Wed, 26 Dec 2018 07:23:37 +0200 Subject: [PATCH] * Clean up the AlignedManifoldArray in KinematicCharacterController. * Keep StaticObject collision flag for ghost object to prevent an assert from firing. * Keep GhostPairCallback alive until collision pairs are cleared. * Adjust KinematicCharacterController construction in CharacterDemo. * Fix up axis assignment in KinematicCharacterController. --- BulletSharp/Collision/GhostObject.cs | 2 +- BulletSharp/Collision/OverlappingPairCache.cs | 2 +- BulletSharp/Dynamics/ICharacterController.cs | 20 +- .../Dynamics/KinematicCharacterController.cs | 240 +++++++++--------- BulletSharp/MathUtil.cs | 4 +- .../demos/CharacterDemo/CharacterDemo.cs | 9 +- BulletSharp/demos/DemoFramework/Demo.cs | 8 + .../Simulation/SimulationExtensions.cs | 8 - 8 files changed, 151 insertions(+), 142 deletions(-) diff --git a/BulletSharp/Collision/GhostObject.cs b/BulletSharp/Collision/GhostObject.cs index 32c6f602..6e28da97 100644 --- a/BulletSharp/Collision/GhostObject.cs +++ b/BulletSharp/Collision/GhostObject.cs @@ -106,7 +106,7 @@ namespace BulletSharp } } - public class GhostPairCallback : OverlappingPairCallback + public sealed class GhostPairCallback : OverlappingPairCallback { public GhostPairCallback() : base(ConstructionInfo.Null) diff --git a/BulletSharp/Collision/OverlappingPairCache.cs b/BulletSharp/Collision/OverlappingPairCache.cs index f35b1149..8c3539cd 100644 --- a/BulletSharp/Collision/OverlappingPairCache.cs +++ b/BulletSharp/Collision/OverlappingPairCache.cs @@ -90,7 +90,7 @@ namespace BulletSharp public void SetInternalGhostPairCallback(OverlappingPairCallback ghostPairCallback) { _ghostPairCallback = ghostPairCallback; - btOverlappingPairCache_setInternalGhostPairCallback(Native, ghostPairCallback.Native); + btOverlappingPairCache_setInternalGhostPairCallback(Native, ghostPairCallback?.Native ?? IntPtr.Zero); } public void SetOverlapFilterCallback(OverlapFilterCallback callback) diff --git a/BulletSharp/Dynamics/ICharacterController.cs b/BulletSharp/Dynamics/ICharacterController.cs index cf1ce375..af5a6b7b 100644 --- a/BulletSharp/Dynamics/ICharacterController.cs +++ b/BulletSharp/Dynamics/ICharacterController.cs @@ -2,19 +2,21 @@ using BulletSharp.Math; namespace BulletSharp { - public interface ICharacterController : IAction - { + public interface ICharacterController : IAction + { void SetWalkDirection(ref Vector3 walkDirection); void SetVelocityForTimeInterval(ref Vector3 velocity, float timeInterval); void Reset(CollisionWorld collisionWorld); void Warp(ref Vector3 origin); - - void PreStep(CollisionWorld collisionWorld); + + void PreStep(CollisionWorld collisionWorld); void PlayerStep(CollisionWorld collisionWorld, float deltaTime); - bool CanJump { get; } - void Jump(Vector3? dir = null); - - bool OnGround { get; } + void Jump(); + void Jump(ref Vector3 dir); + void SetUpInterpolate(bool value); - } + + bool OnGround { get; } + bool CanJump { get; } + } } diff --git a/BulletSharp/Dynamics/KinematicCharacterController.cs b/BulletSharp/Dynamics/KinematicCharacterController.cs index 1d470f98..eb22eea6 100644 --- a/BulletSharp/Dynamics/KinematicCharacterController.cs +++ b/BulletSharp/Dynamics/KinematicCharacterController.cs @@ -1,11 +1,10 @@ using BulletSharp.Math; +using System; namespace BulletSharp { - public class KinematicCharacterController : ICharacterController + public class KinematicCharacterController : ICharacterController, IDisposable { - #region PROTECTED - protected float m_halfHeight; protected PairCachingGhostObject m_ghostObject; @@ -65,9 +64,7 @@ namespace BulletSharp protected bool full_drop; protected bool bounce_fix; - protected static Vector3[] upAxisDirection = { new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1) }; - - public static Vector3 GetNormalizedVector(ref Vector3 v) + protected static Vector3 GetNormalizedVector(ref Vector3 v) { if (v.Length < MathUtil.SIMD_EPSILON) { @@ -75,6 +72,7 @@ namespace BulletSharp } return Vector3.Normalize(v); } + protected Vector3 ComputeReflectionDirection(ref Vector3 direction, ref Vector3 normal) { float dot; @@ -160,7 +158,7 @@ namespace BulletSharp } else { - //printf("touching %f\n", dist); + //System.Console.WriteLine("touching " + dist); } } @@ -170,7 +168,7 @@ namespace BulletSharp Matrix newTrans = m_ghostObject.WorldTransform; newTrans.Origin = m_currentPosition; m_ghostObject.WorldTransform = newTrans; - // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); + //System.Console.WriteLine("m_touchingNormal = " + m_touchingNormal); return penetration; } @@ -197,7 +195,7 @@ namespace BulletSharp start.SetRotation(m_currentOrientation, out start); end.SetRotation(m_targetOrientation, out end); - using(KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback( m_ghostObject, -m_up, m_maxSlopeCosine )) + using (KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback(m_ghostObject, -m_up, m_maxSlopeCosine)) { callback.CollisionFilterGroup = GhostObject.BroadphaseHandle.CollisionFilterGroup; callback.CollisionFilterMask = GhostObject.BroadphaseHandle.CollisionFilterMask; @@ -237,7 +235,7 @@ namespace BulletSharp m_touchingContact = true; if (numPenetrationLoops > 4) { - //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + //System.Console.WriteLine("character could not recover from penetration = " + numPenetrationLoops); break; } } @@ -275,42 +273,38 @@ namespace BulletSharp perpindicularDir = PerpindicularComponent(ref reflectDir, ref hitNormal); m_targetPosition = m_currentPosition; - /* - if (false) //tangentMag != 0.0) + if (false) //tangentMag != 0.0) { - Vector3 parComponent = parallelDir * (tangentMag * movementLength); - // printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]); - m_targetPosition += parComponent; + //Vector3 parComponent = parallelDir * (tangentMag * movementLength); + //System.Console.WriteLine("parComponent=" + parComponent); + //m_targetPosition += parComponent; } - */ + if (normalMag != 0.0f) { Vector3 perpComponent = perpindicularDir * (normalMag * movementLength); - // printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]); + //System.Console.WriteLine("perpComponent=" + perpComponent); m_targetPosition += perpComponent; } } else { - // printf("movementLength don't normalize a zero vector\n"); + //System.Console.WriteLine("movementLength don't normalize a zero vector"); } } protected void StepForwardAndStrafe(CollisionWorld collisionWorld, ref Vector3 walkMove) { - // printf("m_normalizedDirection=%f,%f,%f\n", - // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]); + //System.Console.WriteLine("m_normalizedDirection=" + m_normalizedDirection); // phase 2: forward and strafe - Matrix start, end; + Matrix start = Matrix.Identity; + Matrix end = Matrix.Identity; m_targetPosition = m_currentPosition + walkMove; - start = Matrix.Identity; - end = Matrix.Identity; - float fraction = 1.0f; float distance2 = (m_currentPosition - m_targetPosition).LengthSquared; - // printf("distance2=%f\n",distance2); + //System.Console.WriteLine("distance2=" + distance2); int maxIter = 10; @@ -323,7 +317,7 @@ namespace BulletSharp start.SetRotation(m_currentOrientation, out start); end.SetRotation(m_targetOrientation, out end); - using( KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback( m_ghostObject, sweepDirNegative, 0.0f ) ) + using (KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback(m_ghostObject, sweepDirNegative, 0.0f)) { callback.CollisionFilterGroup = GhostObject.BroadphaseHandle.CollisionFilterGroup; callback.CollisionFilterMask = GhostObject.BroadphaseHandle.CollisionFilterMask; @@ -331,7 +325,7 @@ namespace BulletSharp float margin = m_convexShape.Margin; m_convexShape.Margin = margin + m_addedMargin; - if (!(start == end)) + if (start != end) { if (m_useGhostObjectSweepTest) { @@ -349,12 +343,11 @@ namespace BulletSharp if (callback.HasHit && GhostObject.HasContactResponse && NeedsCollision(m_ghostObject, callback.HitCollisionObject)) { // we moved only a fraction - //btScalar hitDistance; - //hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); + //float hitDistance = (callback.HitPointWorld - m_currentPosition).Length; - // m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); - Vector3 v = callback.HitNormalWorld; - UpdateTargetPositionBasedOnCollision(ref v); + //Vector3.Lerp(ref m_currentPosition, ref m_targetPosition, callback.ClosestHitFraction, out m_currentPosition); + Vector3 hitNormalWorld = callback.HitNormalWorld; + UpdateTargetPositionBasedOnCollision(ref hitNormalWorld); Vector3 currentDir = m_targetPosition - m_currentPosition; distance2 = currentDir.LengthSquared; if (distance2 > MathUtil.SIMD_EPSILON) @@ -368,7 +361,7 @@ namespace BulletSharp } else { - // printf("currentDir: don't normalize a zero vector\n"); + //System.Console.WriteLine("currentDir: don't normalize a zero vector"); break; } } @@ -385,10 +378,10 @@ namespace BulletSharp bool runonce = false; // phase 3: down - /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0; - btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep); - btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt; - btVector3 gravity_drop = m_up * downVelocity; + /*float additionalDownStep = (m_wasOnGround && !OnGround) ? m_stepHeight : 0; + Vector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep); + float downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity < 0 ? -m_verticalVelocity : 0) * dt; + Vector3 gravity_drop = m_up * downVelocity; m_targetPosition -= (step_drop + gravity_drop);*/ Vector3 orig_position = m_targetPosition; @@ -404,8 +397,8 @@ namespace BulletSharp Vector3 step_drop = m_up * (m_currentStepOffset + downVelocity); m_targetPosition -= step_drop; - using( KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback( m_ghostObject, m_up, m_maxSlopeCosine ) ) - using( KinematicClosestNotMeConvexResultCallback callback2 = new KinematicClosestNotMeConvexResultCallback( m_ghostObject, m_up, m_maxSlopeCosine ) ) + using (KinematicClosestNotMeConvexResultCallback callback = new KinematicClosestNotMeConvexResultCallback(m_ghostObject, m_up, m_maxSlopeCosine)) + using (KinematicClosestNotMeConvexResultCallback callback2 = new KinematicClosestNotMeConvexResultCallback(m_ghostObject, m_up, m_maxSlopeCosine)) { callback.CollisionFilterGroup = GhostObject.BroadphaseHandle.CollisionFilterGroup; callback.CollisionFilterMask = GhostObject.BroadphaseHandle.CollisionFilterMask; @@ -415,19 +408,14 @@ namespace BulletSharp while (true) { - start = Matrix.Identity; - end = Matrix.Identity; - - end_double = Matrix.Identity; - - start.Origin = m_currentPosition; - end.Origin = m_targetPosition; + Matrix.Translation(ref m_currentPosition, out start); + Matrix.Translation(ref m_targetPosition, out end); start.SetRotation(m_currentOrientation, out start); end.SetRotation(m_targetOrientation, out end); //set double test for 2x the step drop, to check for a large drop vs small drop - end_double.Origin = m_targetPosition - step_drop; + end_double = Matrix.Translation(m_targetPosition - step_drop); if (m_useGhostObjectSweepTest) { @@ -482,7 +470,7 @@ namespace BulletSharp // we dropped a fraction of the height -> hit floor float fraction = (m_currentPosition.Y - callback.HitPointWorld.Y) / 2; - //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY()); + //System.Console.WriteLine("hitpoint: {0} - pos {1}", callback.HitPointWorld.Y, m_currentPosition.Y); if (bounce_fix == true) { @@ -518,21 +506,21 @@ namespace BulletSharp m_targetPosition -= step_drop; } } - //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY()); + //System.Console.WriteLine("full drop - {0}, {1}", m_currentPosition.Y, m_targetPosition.Y); m_currentPosition = m_targetPosition; } } } - protected virtual bool NeedsCollision( CollisionObject body0, CollisionObject body1 ) + protected virtual bool NeedsCollision(CollisionObject body0, CollisionObject body1) { bool collides = (body0.BroadphaseHandle.CollisionFilterGroup & body1.BroadphaseHandle.CollisionFilterMask) != 0; collides = collides && (body1.BroadphaseHandle.CollisionFilterGroup & body0.BroadphaseHandle.CollisionFilterMask) != 0; return collides; } - protected void SetUpVector( ref Vector3 up ) + protected void SetUpVector(ref Vector3 up) { if (m_up == up) return; @@ -566,70 +554,51 @@ namespace BulletSharp return MathUtil.ShortestArcQuat(ref v0, ref v1); } - #endregion // PROTECTED - - #region PUBLIC - public KinematicCharacterController(PairCachingGhostObject ghostObject, ConvexShape convexShape, float stepHeight, ref Vector3 up) { m_ghostObject = ghostObject; - m_up = new Vector3(0.0f, 0.0f, 1.0f); m_jumpAxis = new Vector3(0.0f, 0.0f, 1.0f); m_addedMargin = 0.02f; - m_walkDirection = new Vector3(0.0f, 0.0f, 0.0f); - m_AngVel = new Vector3(0.0f, 0.0f, 0.0f); m_useGhostObjectSweepTest = true; - m_turnAngle = 0.0f; m_convexShape = convexShape; m_useWalkDirection = true; // use walk direction by default, legacy behavior - m_velocityTimeInterval = 0.0f; - m_verticalVelocity = 0.0f; - m_verticalOffset = 0.0f; m_gravity = 9.8f * 3.0f; // 3G acceleration. m_fallSpeed = 55.0f; // Terminal velocity of a sky diver in m/s. m_jumpSpeed = 10.0f; // ? m_SetjumpSpeed = m_jumpSpeed; - m_wasOnGround = false; - m_wasJumping = false; m_interpolateUp = true; - m_currentStepOffset = 0.0f; m_maxPenetrationDepth = 0.2f; - full_drop = false; - bounce_fix = false; - m_linearDamping = 0.0f; - m_angularDamping = 0.0f; Up = up; StepHeight = stepHeight; MaxSlope = MathUtil.DegToRadians(45.0f); } - ///btActionInterface interface + // IAction interface public virtual void UpdateAction(CollisionWorld collisionWorld, float deltaTime) { PreStep(collisionWorld); PlayerStep(collisionWorld, deltaTime); } - ///btActionInterface interface + // IAction interface public void DebugDraw(DebugDraw debugDrawer) { } public Vector3 Up { + get => m_up; set { - Vector3 up = value; - if (up.LengthSquared > 0 && m_gravity > 0.0f) + if (value.LengthSquared > 0 && m_gravity > 0.0f) { - Gravity = -m_gravity * Vector3.Normalize(up); + Gravity = -m_gravity * Vector3.Normalize(value); return; } - SetUpVector(ref up); + SetUpVector(ref value); } - get => m_up; } /// @@ -640,6 +609,7 @@ namespace BulletSharp /// This call will reset any velocity set by setVelocityForTimeInterval(). /// public virtual void SetWalkDirection(Vector3 walkDirection) => SetWalkDirection(ref walkDirection); + public virtual void SetWalkDirection(ref Vector3 walkDirection) { m_useWalkDirection = true; @@ -655,27 +625,28 @@ namespace BulletSharp /// Negative time intervals will result in no motion. /// public void SetVelocityForTimeInterval(Vector3 velocity, float timeInterval) => SetVelocityForTimeInterval(ref velocity, timeInterval); + public virtual void SetVelocityForTimeInterval(ref Vector3 velocity, float timeInterval) { - // printf("setVelocity!\n"); - // printf(" interval: %f\n", timeInterval); - // printf(" velocity: (%f, %f, %f)\n", - // velocity.x(), velocity.y(), velocity.z()); + //System.Console.WriteLine("SetVelocity!"); + //System.Console.WriteLine(" interval: " + timeInterval); + //System.Console.WriteLine(" velocity: " + velocity); m_useWalkDirection = false; m_walkDirection = velocity; - m_normalizedDirection = GetNormalizedVector(ref m_walkDirection); + m_normalizedDirection = GetNormalizedVector(ref m_walkDirection); m_velocityTimeInterval = timeInterval; } public virtual Vector3 AngularVelocity { - set => m_AngVel = value; get => m_AngVel; + set => m_AngVel = value; } public virtual Vector3 LinearVelocity { + get => m_walkDirection + (m_verticalVelocity * m_up); set { Vector3 velocity = value; @@ -684,7 +655,7 @@ namespace BulletSharp // HACK: if we are moving in the direction of the up, treat it as a jump :( if (m_walkDirection.LengthSquared > 0) { - Vector3 w = Vector3.Normalize( velocity ); + Vector3 w = Vector3.Normalize(velocity); float c = w.Dot(m_up); if (c != 0) { @@ -703,18 +674,18 @@ namespace BulletSharp else m_verticalVelocity = 0.0f; } - get => m_walkDirection + (m_verticalVelocity * m_up); } public float LinearDamping { - set => m_linearDamping = value > 1f ? 1f : value < 0f ? 0f : value; get => m_linearDamping; + set => m_linearDamping = value > 1f ? 1f : value < 0f ? 0f : value; } + public float AngularDamping { - set => m_angularDamping = value > 1f ? 1f : value < 0f ? 0f : value; get => m_angularDamping; + set => m_angularDamping = value > 1f ? 1f : value < 0f ? 0f : value; } public void Reset(CollisionWorld collisionWorld) @@ -745,16 +716,17 @@ namespace BulletSharp public void PreStep(CollisionWorld collisionWorld) { m_currentPosition = m_ghostObject.WorldTransform.Origin; - m_targetPosition = m_currentPosition; + m_targetPosition = m_currentPosition; - m_ghostObject.WorldTransform.Decompose( out _, out m_currentOrientation, out _ ); - m_targetOrientation = m_currentOrientation; - // printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); + m_ghostObject.WorldTransform.Decompose(out _, out m_currentOrientation, out _); + m_targetOrientation = m_currentOrientation; + //System.Console.WriteLine("m_targetPosition=" + m_targetPosition); } + public void PlayerStep(CollisionWorld collisionWorld, float dt) { - // printf("playerStep(): "); - // printf(" dt = %f", dt); + //System.Console.WriteLine("PlayerStep():"); + //System.Console.WriteLine(" dt = " + dt); if (m_AngVel.LengthSquared > 0.0f) { @@ -783,7 +755,7 @@ namespace BulletSharp // quick check... if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) { - // printf("\n"); + //System.Console.WriteLine(); return; // no motion } @@ -814,8 +786,8 @@ namespace BulletSharp xform = m_ghostObject.WorldTransform; - // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); - // printf("walkSpeed=%f\n",walkSpeed); + //System.Console.WriteLine("walkDirection=" + m_walkDirection); + //System.Console.WriteLine("walkSpeed=" + walkSpeed); StepUp(collisionWorld); //todo: Experimenting with behavior of controller when it hits a ceiling.. @@ -842,7 +814,7 @@ namespace BulletSharp } else { - //printf(" time: %f", m_velocityTimeInterval); + //System.Console.WriteLine(" time: " + m_velocityTimeInterval); // still have some time left for moving! float dtMoving = (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval; @@ -851,7 +823,7 @@ namespace BulletSharp // how far will we move while we are moving? Vector3 move = m_walkDirection * dtMoving; - //printf(" dtMoving: %f", dtMoving); + //System.Console.WriteLine(" dtMoving: " + dtMoving); // okay, step StepForwardAndStrafe(collisionWorld, ref move); @@ -873,7 +845,7 @@ namespace BulletSharp // m_verticalVelocity = 0.0; // } //} - // printf("\n"); + //System.Console.WriteLine(); xform.Origin = m_currentPosition; m_ghostObject.WorldTransform = xform; @@ -886,7 +858,7 @@ namespace BulletSharp m_touchingContact = true; if (numPenetrationLoops > 4) { - //printf("character could not recover from penetration = %d\n", numPenetrationLoops); + //System.Console.WriteLine("character could not recover from penetration, numPenetrationLoops=" + numPenetrationLoops); break; } } @@ -894,48 +866,61 @@ namespace BulletSharp public float StepHeight { - set => m_stepHeight = value; get => m_stepHeight; + set => m_stepHeight = value; } + public float FallSpeed { - set => m_fallSpeed = value; get => m_fallSpeed; + set => m_fallSpeed = value; } + public float JumpSpeed { - set => m_SetjumpSpeed = m_jumpSpeed = value; get => m_jumpSpeed; + set => m_SetjumpSpeed = m_jumpSpeed = value; } + public void SetMaxJumpHeight(float maxJumpHeight) => m_maxJumpHeight = maxJumpHeight; public bool CanJump => OnGround; - public void Jump(Vector3? _temp = null) + public void Jump() { - Vector3 v = _temp ?? Vector3.Zero; - m_jumpSpeed = v.LengthSquared == 0 ? m_SetjumpSpeed : v.Length; + m_jumpSpeed = m_SetjumpSpeed; m_verticalVelocity = m_jumpSpeed; m_wasJumping = true; - m_jumpAxis = v.LengthSquared == 0 ? m_up : Vector3.Normalize(v); + m_jumpAxis = m_up; + + m_jumpPosition = m_ghostObject.WorldTransform.Origin; + } + + public void Jump(ref Vector3 dir) + { + m_jumpSpeed = dir.Length; + m_verticalVelocity = m_jumpSpeed; + m_wasJumping = true; + + m_jumpAxis = Vector3.Normalize(dir); m_jumpPosition = m_ghostObject.WorldTransform.Origin; - #if false - currently no jumping. - btTransform xform; - m_rigidBody->getMotionState()->getWorldTransform (xform); - btVector3 up = xform.getBasis()[1]; - up.normalize (); - btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0); +#if false + // currently no jumping. + Matrix xform; + m_rigidBody.getMotionState()->getWorldTransform (xform); + Vector3 up = xform.Basis[1]; + up.Normalize(); + float magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * 8.0f; m_rigidBody->applyCentralImpulse (up * magnitude); - #endif +#endif } /// /// Calls Jump() /// - public void ApplyImpulse( ref Vector3 v ) => Jump( v ); + public void ApplyImpulse(ref Vector3 dir) => Jump(ref dir); public Vector3 Gravity { @@ -962,7 +947,7 @@ namespace BulletSharp set { m_maxSlopeRadians = value; - m_maxSlopeCosine = (float)System.Math.Cos(value); + m_maxSlopeCosine = (float)System.Math.Cos(value); } } @@ -973,18 +958,37 @@ namespace BulletSharp } public PairCachingGhostObject GhostObject => m_ghostObject; + public void SetUseGhostSweepTest(bool useGhostObjectSweepTest) { m_useGhostObjectSweepTest = useGhostObjectSweepTest; } - public bool OnGround => ((m_verticalVelocity < 0 ? -m_verticalVelocity : m_verticalVelocity) < MathUtil.SIMD_EPSILON) && ((m_verticalOffset < 0 ? -m_verticalOffset : m_verticalOffset) < MathUtil.SIMD_EPSILON); + public bool OnGround => System.Math.Abs(m_verticalVelocity) < MathUtil.SIMD_EPSILON && System.Math.Abs(m_verticalOffset) < MathUtil.SIMD_EPSILON; + public void SetUpInterpolate(bool v) { m_interpolateUp = v; } - #endregion + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + m_manifoldArray.Dispose(); + } + } + + ~KinematicCharacterController() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } ///@todo Interact with dynamic objects, diff --git a/BulletSharp/MathUtil.cs b/BulletSharp/MathUtil.cs index b02c5628..641de8c1 100644 --- a/BulletSharp/MathUtil.cs +++ b/BulletSharp/MathUtil.cs @@ -1148,13 +1148,13 @@ namespace BulletSharp Vector3 ya = new Vector3(y.X, 0, y.Z); return (xa - ya).LengthSquared; } - + public static void SetRotation(this Matrix matrix, Quaternion newRotation, out Matrix result) { matrix.Decompose(out Vector3 scale, out _, out Vector3 translation); result = Matrix.Scaling(scale) * Matrix.RotationQuaternion(newRotation) * Matrix.Translation(translation); } - + public static Quaternion GetRotation(this Matrix matrix) { matrix.Decompose(out _, out Quaternion rot, out _); diff --git a/BulletSharp/demos/CharacterDemo/CharacterDemo.cs b/BulletSharp/demos/CharacterDemo/CharacterDemo.cs index d8d92907..9c06f405 100644 --- a/BulletSharp/demos/CharacterDemo/CharacterDemo.cs +++ b/BulletSharp/demos/CharacterDemo/CharacterDemo.cs @@ -144,11 +144,13 @@ namespace CharacterDemo public void Dispose() { - _ghostPairCallback.Dispose(); CameraSphere.Dispose(); ConvexResultCallback.Dispose(); + Character.Dispose(); this.StandardCleanup(); + + _ghostPairCallback.Dispose(); } private void CreateCharacter() @@ -162,13 +164,14 @@ namespace CharacterDemo GhostObject = new PairCachingGhostObject() { CollisionShape = capsule, - CollisionFlags = CollisionFlags.CharacterObject, WorldTransform = Matrix.Translation(10.210098f, -1.6433364f, 16.453260f) }; + GhostObject.CollisionFlags |= CollisionFlags.CharacterObject; World.AddCollisionObject(GhostObject, CollisionFilterGroups.CharacterFilter, CollisionFilterGroups.StaticFilter | CollisionFilterGroups.DefaultFilter); const float stepHeight = 0.35f; - Character = new KinematicCharacterController(GhostObject, capsule, stepHeight); + Vector3 up = Vector3.UnitY; + Character = new KinematicCharacterController(GhostObject, capsule, stepHeight, ref up); World.AddAction(Character); } } diff --git a/BulletSharp/demos/DemoFramework/Demo.cs b/BulletSharp/demos/DemoFramework/Demo.cs index e8e47aff..0e0a8167 100644 --- a/BulletSharp/demos/DemoFramework/Demo.cs +++ b/BulletSharp/demos/DemoFramework/Demo.cs @@ -154,6 +154,14 @@ namespace DemoFramework _bodyPicker.RemovePickingConstraint(); Simulation.Dispose(); _boxShooter.Dispose(); + + if (BulletObjectTracker.Current != null) + { + if (BulletObjectTracker.Current.UserOwnedObjects.Count != 0) + { + throw new Exception("Bullet has active objects that were not disposed."); + } + } } public void Run() diff --git a/BulletSharp/demos/DemoFramework/Simulation/SimulationExtensions.cs b/BulletSharp/demos/DemoFramework/Simulation/SimulationExtensions.cs index 55e3a131..ed648832 100644 --- a/BulletSharp/demos/DemoFramework/Simulation/SimulationExtensions.cs +++ b/BulletSharp/demos/DemoFramework/Simulation/SimulationExtensions.cs @@ -21,14 +21,6 @@ namespace DemoFramework simulation.Broadphase.Dispose(); simulation.Dispatcher.Dispose(); simulation.CollisionConfiguration.Dispose(); - - if (BulletObjectTracker.Current != null) - { - if (BulletObjectTracker.Current.UserOwnedObjects.Count != 0) - { - throw new Exception("Bullet has active objects that were not disposed."); - } - } } private static void CleanupConstraints(DynamicsWorld world)