History

PhysicsEngine doesn't need AvatarData

MyAvatar now owns its CharacterController fix for bug of phantom collision obj when avatar's physics are disabled

Andrew Meadows committed 11 years ago

Commit 44eca081 parent 49f5de28 files · +194 −137Browse files

Showing the changes to libraries/physics/src/CharacterController.cpp (1 of 8 files). Show all

Unified · Split

libraries/physics/src/CharacterController.cpp+142−81
@@ -21,6 +21,12 @@ subject to the following restrictions: · 20 unmodified lines
2121 #include "BulletUtil.h"
2222 #include "CharacterController.h"
2323
24+const uint32_t PENDING_FLAG_ADD_TO_SIMULATION = 1U << 0;
25+const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1;
26+//const uint32_t PENDING_FLAG_ENABLE = 1U << 0;
27+//const uint32_t PENDING_FLAG_DISABLE = 1U << 1;
28+const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2;
29+const uint32_t PENDING_FLAG_JUMP = 1U << 4;
2430
2531 // static helper method
2632 static btVector3 getNormalizedVector(const btVector3& v) {
@@ -223,11 +229,10 @@ CharacterController::CharacterController(AvatarData* avatarData) { · 196 unmodified lines
223229 _avatarData = avatarData;
224230
225231 // cache the "PhysicsEnabled" state of _avatarData
226− _avatarData->lockForRead();
227− _enabled = _avatarData->isPhysicsEnabled();
228− _avatarData->unlock();
232+ _enabled = false;
229233
230− createShapeAndGhost();
234+ _ghostObject = NULL;
235+ _convexShape = NULL;
231236
232237 _addedMargin = 0.02f;
233238 _walkDirection.setValue(0.0f,0.0f,0.0f);
@@ -242,6 +247,7 @@ CharacterController::CharacterController(AvatarData* avatarData) { · 8 unmodified lines
242247 _wasJumping = false;
243248 setMaxSlope(btRadians(45.0f));
244249 _lastStepUp = 0.0f;
250+ _pendingFlags = 0;
245251 }
246252
247253 CharacterController::~CharacterController() {
@@ -349,7 +355,7 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl · 101 unmodified lines
349355 return penetration;
350356 }
351357
352−void CharacterController::stepUp( btCollisionWorld* world) {
358+void CharacterController::stepUp(btCollisionWorld* world) {
353359 // phase 1: up
354360
355361 // compute start and end
@@ -416,7 +422,7 @@ void CharacterController::updateTargetPositionBasedOnCollision(const btVector3& · 60 unmodified lines
416422 }
417423 }
418424
419−void CharacterController::stepForward( btCollisionWorld* collisionWorld, const btVector3& movement) {
425+void CharacterController::stepForward(btCollisionWorld* collisionWorld, const btVector3& movement) {
420426 // phase 2: forward
421427 _targetPosition = _currentPosition + movement;
422428
@@ -472,7 +478,7 @@ void CharacterController::stepForward( btCollisionWorld* collisionWorld, const b · 49 unmodified lines
472478 _convexShape->setMargin(margin);
473479 }
474480
475−void CharacterController::stepDown( btCollisionWorld* collisionWorld, btScalar dt) {
481+void CharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt) {
476482 // phase 3: down
477483 //
478484 // The "stepDown" phase first makes a normal sweep down that cancels the lift from the "stepUp" phase.
@@ -558,7 +564,7 @@ void CharacterController::setVelocityForTimeInterval(const btVector3& velocity, · 79 unmodified lines
558564 _velocityTimeInterval += timeInterval;
559565 }
560566
561−void CharacterController::reset( btCollisionWorld* collisionWorld ) {
567+void CharacterController::reset(btCollisionWorld* collisionWorld) {
562568 _verticalVelocity = 0.0;
563569 _verticalOffset = 0.0;
564570 _wasOnGround = false;
@@ -583,7 +589,7 @@ void CharacterController::warp(const btVector3& origin) { · 18 unmodified lines
583589 }
584590
585591
586−void CharacterController::preStep( btCollisionWorld* collisionWorld) {
592+void CharacterController::preStep(btCollisionWorld* collisionWorld) {
587593 if (!_enabled) {
588594 return;
589595 }
@@ -603,7 +609,7 @@ void CharacterController::preStep( btCollisionWorld* collisionWorld) { · 13 unmodified lines
603609 _targetPosition = _currentPosition;
604610 }
605611
606−void CharacterController::playerStep( btCollisionWorld* collisionWorld, btScalar dt) {
612+void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt) {
607613 if (!_enabled || (!_useWalkDirection && _velocityTimeInterval <= 0.0)) {
608614 return; // no motion
609615 }
@@ -710,106 +716,163 @@ void CharacterController::setUpInterpolate(bool value) { · 100 unmodified lines
710716 // (interpolate = true, and now default behavior) or happily penetrate objects above the avatar.
711717 }
712718
719+/*
713720 // protected
714721 void CharacterController::createShapeAndGhost() {
715722 // get new dimensions from avatar
716− _avatarData->lockForRead();
717− AABox box = _avatarData->getLocalAABox();
718−
719− // create new ghost
720− _ghostObject = new btPairCachingGhostObject();
721− _ghostObject->setWorldTransform(btTransform(glmToBullet(_avatarData->getOrientation()),
722− glmToBullet(_avatarData->getPosition())));
723− _avatarData->unlock();
724−
725− const glm::vec3& diagonal = box.getScale();
726− _radius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
727− _halfHeight = 0.5f * diagonal.y - _radius;
723+ float x = _boxScale.x;
724+ float z = _boxScale.z;
725+ _radius = 0.5f * sqrtf(0.5f * (x * x + z * z));
726+ _halfHeight = 0.5f * _boxScale.y - _radius;
728727 float MIN_HALF_HEIGHT = 0.1f;
729728 if (_halfHeight < MIN_HALF_HEIGHT) {
730729 _halfHeight = MIN_HALF_HEIGHT;
731730 }
732− glm::vec3 offset = box.getCorner() + 0.5f * diagonal;
733− _shapeLocalOffset = offset;
734−
735− // stepHeight affects the heights of ledges that the character can ascend
736− // however the actual ledge height is some function of _stepHeight
737− // due to character shape and this CharacterController algorithm
738− // (the function is approximately 2*_stepHeight)
739− _stepHeight = 0.1f * (_radius + _halfHeight) + 0.1f;
740−
741− // create new shape
742− _convexShape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
743− _ghostObject->setCollisionShape(_convexShape);
744− _ghostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
731+ // NOTE: _shapeLocalOffset is already computed
732+
733+ if (_radius > 0.0f) {
734+ // create new ghost
735+ _ghostObject = new btPairCachingGhostObject();
736+ _ghostObject->setWorldTransform(btTransform(glmToBullet(_avatarData->getOrientation()),
737+ glmToBullet(_avatarData->getPosition())));
738+ // stepHeight affects the heights of ledges that the character can ascend
739+ // however the actual ledge height is some function of _stepHeight
740+ // due to character shape and this CharacterController algorithm
741+ // (the function is approximately 2*_stepHeight)
742+ _stepHeight = 0.1f * (_radius + _halfHeight) + 0.1f;
743+
744+ // create new shape
745+ _convexShape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
746+ _ghostObject->setCollisionShape(_convexShape);
747+ _ghostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
748+ } else {
749+ // TODO: handle this failure case
750+ }
751+ _pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE;
745752 }
753+*/
746754
747−bool CharacterController::needsShapeUpdate() {
748− // get new dimensions from avatar
749− _avatarData->lockForRead();
750− AABox box = _avatarData->getLocalAABox();
751− _avatarData->unlock();
755+void CharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) {
756+ _boxScale = scale;
752757
753− const glm::vec3& diagonal = box.getScale();
754− float radius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
755− float halfHeight = 0.5f * diagonal.y - radius;
758+ float x = _boxScale.x;
759+ float z = _boxScale.z;
760+ float radius = 0.5f * sqrtf(0.5f * (x * x + z * z));
761+ float halfHeight = 0.5f * _boxScale.y - radius;
756762 float MIN_HALF_HEIGHT = 0.1f;
757763 if (halfHeight < MIN_HALF_HEIGHT) {
758764 halfHeight = MIN_HALF_HEIGHT;
759765 }
760− glm::vec3 offset = box.getCorner() + 0.5f * diagonal;
761766
762− // compare dimensions (and offset)
767+ // compare dimensions
763768 float radiusDelta = glm::abs(radius - _radius);
764769 float heightDelta = glm::abs(halfHeight - _halfHeight);
765770 if (radiusDelta < FLT_EPSILON && heightDelta < FLT_EPSILON) {
766771 // shape hasn't changed --> nothing to do
767− float offsetDelta = glm::distance(offset, _shapeLocalOffset);
768− if (offsetDelta > FLT_EPSILON) {
769− // if only the offset changes then we can update it --> no need to rebuild shape
770− _shapeLocalOffset = offset;
771− }
772− return false;
772+ } else {
773+ // we need to: remove, update, add
774+ _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION
775+ | PENDING_FLAG_UPDATE_SHAPE
776+ | PENDING_FLAG_ADD_TO_SIMULATION;
773777 }
774− return true;
775−}
776778
777−void CharacterController::updateShape() {
778− // DANGER: make sure this CharacterController and its GhostShape have been removed from
779− // the PhysicsEngine before calling this.
779+ // it's ok to change offset immediately -- there are no thread safety issues here
780+ _shapeLocalOffset = corner + 0.5f * _boxScale;
781+}
780782
781− // delete shape and GhostObject
782− delete _ghostObject;
783− _ghostObject = NULL;
784− delete _convexShape;
785− _convexShape = NULL;
786−
787− createShapeAndGhost();
783+bool CharacterController::needsAddition() const {
784+ return (bool)(_pendingFlags & PENDING_FLAG_ADD_TO_SIMULATION);
788785 }
789786
790−void CharacterController::preSimulation(btScalar timeStep) {
791− bool wasEnabled = _enabled;
787+bool CharacterController::needsRemoval() const {
788+ return (bool)(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION);
789+}
792790
793− // lock avatarData, get everything we need from it ASAP, then unlock
794− _avatarData->lockForRead();
795− _enabled = _avatarData->isPhysicsEnabled();
796− glm::quat rotation = _avatarData->getOrientation();
797− glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset;
798− // TODO: Andrew to implement: harvest jump event here
799− btVector3 walkVelocity = glmToBullet(_avatarData->getVelocity());
791+void CharacterController::setEnabled(bool enabled) {
792+ if (enabled != _enabled) {
793+ if (enabled) {
794+ _pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION;
795+ } else {
796+ _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION;
797+ _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
798+ }
799+ _enabled = enabled;
800+ }
801+}
800802
801− _avatarData->unlock();
803+void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
804+ if (_dynamicsWorld != world) {
805+ if (_dynamicsWorld) {
806+ _dynamicsWorld->removeCollisionObject(getGhostObject());
807+ _dynamicsWorld->removeAction(this);
808+ }
809+ _dynamicsWorld = world;
810+ if (_dynamicsWorld) {
811+ _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION;
812+ _dynamicsWorld->addCollisionObject(getGhostObject(),
813+ btBroadphaseProxy::CharacterFilter,
814+ btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
815+ _dynamicsWorld->addAction(this);
816+ reset(_dynamicsWorld);
817+ } else {
818+ _pendingFlags &= ~ PENDING_FLAG_REMOVE_FROM_SIMULATION;
819+ }
820+ } else {
821+ _pendingFlags &= ~ (PENDING_FLAG_REMOVE_FROM_SIMULATION | PENDING_FLAG_ADD_TO_SIMULATION);
822+ }
823+}
802824
803− if (wasEnabled != _enabled) {
804− if (_enabled) {
805− // TODO: Andrew to implement: add collision shape back into world
825+void CharacterController::updateShape() {
826+ if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
827+ assert(!(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION));
828+ _pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE;
829+ // make sure there is NO pending removal from simulation at this point
830+ // (don't want to delete _ghostObject out from under the simulation)
831+ // delete shape and GhostObject
832+ delete _ghostObject;
833+ _ghostObject = NULL;
834+ delete _convexShape;
835+ _convexShape = NULL;
836+
837+ // compute new dimensions from avatar's bounding box
838+ float x = _boxScale.x;
839+ float z = _boxScale.z;
840+ _radius = 0.5f * sqrtf(0.5f * (x * x + z * z));
841+ _halfHeight = 0.5f * _boxScale.y - _radius;
842+ float MIN_HALF_HEIGHT = 0.1f;
843+ if (_halfHeight < MIN_HALF_HEIGHT) {
844+ _halfHeight = MIN_HALF_HEIGHT;
845+ }
846+ // NOTE: _shapeLocalOffset is already computed
847+
848+ if (_radius > 0.0f) {
849+ // create new ghost
850+ _ghostObject = new btPairCachingGhostObject();
851+ _ghostObject->setWorldTransform(btTransform(glmToBullet(_avatarData->getOrientation()),
852+ glmToBullet(_avatarData->getPosition())));
853+ // stepHeight affects the heights of ledges that the character can ascend
854+ // however the actual ledge height is some function of _stepHeight
855+ // due to character shape and this CharacterController algorithm
856+ // (the function is approximately 2*_stepHeight)
857+ _stepHeight = 0.1f * (_radius + _halfHeight) + 0.1f;
858+
859+ // create new shape
860+ _convexShape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
861+ _ghostObject->setCollisionShape(_convexShape);
862+ _ghostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
806863 } else {
807− // TODO: Andrew to implement: remove collision shape from world,
808− // otherwise things will continue to collide with it
864+ // TODO: handle this failure case
809865 }
810866 }
867+}
868+
869+void CharacterController::preSimulation(btScalar timeStep) {
870+ if (_enabled && _dynamicsWorld) {
871+ glm::quat rotation = _avatarData->getOrientation();
872+ glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset;
873+ // TODO: harvest jump event here
874+ btVector3 walkVelocity = glmToBullet(_avatarData->getVelocity());
811875
812− if (_enabled) {
813876 _ghostObject->setWorldTransform(btTransform(glmToBullet(rotation), glmToBullet(position)));
814877 setVelocityForTimeInterval(walkVelocity, timeStep);
815878 }
@@ -817,13 +880,11 @@ void CharacterController::preSimulation(btScalar timeStep) { · 1 unmodified line
817880
818881 void CharacterController::postSimulation() {
819882 if (_enabled) {
820− _avatarData->lockForWrite();
821883 const btTransform& avatarTransform = _ghostObject->getWorldTransform();
822884 glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
823885 glm::vec3 offset = rotation * _shapeLocalOffset;
824886 _avatarData->setOrientation(rotation);
825887 _avatarData->setPosition(bulletToGLM(avatarTransform.getOrigin()) - offset);
826− _avatarData->unlock();
827888 }
828889 }
829890

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t