aboutsummaryrefslogtreecommitdiffstats
path: root/Samples/OculusWorldDemo/Player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Samples/OculusWorldDemo/Player.cpp')
-rw-r--r--Samples/OculusWorldDemo/Player.cpp226
1 files changed, 127 insertions, 99 deletions
diff --git a/Samples/OculusWorldDemo/Player.cpp b/Samples/OculusWorldDemo/Player.cpp
index b910307..b2bf00e 100644
--- a/Samples/OculusWorldDemo/Player.cpp
+++ b/Samples/OculusWorldDemo/Player.cpp
@@ -23,135 +23,138 @@ limitations under the License.
#include "Player.h"
#include <Kernel/OVR_Alg.h>
-Player::Player(void)
- : UserEyeHeight(1.8f),
- EyePos(7.7f, 1.8f, -1.0f),
- EyeYaw(YawInitial), EyePitch(0), EyeRoll(0),
- LastSensorYaw(0)
+Player::Player()
+ : UserEyeHeight(1.76f - 0.15f), // 1.76 meters height (ave US male, Wikipedia), less 15 centimeters (TomF's top-of-head-to-eye distance).
+ BodyPos(7.7f, 1.76f - 0.15f, -1.0f),
+ BodyYaw(YawInitial)
{
MoveForward = MoveBack = MoveLeft = MoveRight = 0;
GamepadMove = Vector3f(0);
GamepadRotate = Vector3f(0);
}
+Player::~Player()
+{
+}
+
+Vector3f Player::GetPosition()
+{
+ return BodyPos + Quatf(Vector3f(0,1,0), BodyYaw.Get()).Rotate(HeadPose.Position);
+}
+
+Quatf Player::GetOrientation(bool baseOnly)
+{
+ Quatf baseQ = Quatf(Vector3f(0,1,0), BodyYaw.Get());
+ return baseOnly ? baseQ : baseQ * HeadPose.Orientation;
+}
-Player::~Player(void)
+Posef Player::VirtualWorldPoseFromRealPose(const Posef &sensorHeadPose)
{
+ Quatf baseQ = Quatf(Vector3f(0,1,0), BodyYaw.Get());
+
+ return Posef(baseQ * sensorHeadPose.Orientation,
+ BodyPos + baseQ.Rotate(sensorHeadPose.Position));
}
-void Player::HandleCollision(double dt, Array<Ptr<CollisionModel> >* collisionModels,
- Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown)
+
+void Player::HandleMovement(double dt, Array<Ptr<CollisionModel> >* collisionModels,
+ Array<Ptr<CollisionModel> >* groundCollisionModels, bool shiftDown)
{
- if(MoveForward || MoveBack || MoveLeft || MoveRight || GamepadMove.LengthSq() > 0)
+ // Handle keyboard movement.
+ // This translates BasePos based on the orientation and keys pressed.
+ // Note that Pitch and Roll do not affect movement (they only affect view).
+ Vector3f controllerMove;
+ if(MoveForward || MoveBack || MoveLeft || MoveRight)
{
- Vector3f orientationVector;
- // Handle keyboard movement.
- // This translates EyePos based on Yaw vector direction and keys pressed.
- // Note that Pitch and Roll do not affect movement (they only affect view).
- if(MoveForward || MoveBack || MoveLeft || MoveRight)
+ if (MoveForward)
{
- Vector3f localMoveVector(0, 0, 0);
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
-
- if (MoveForward)
- {
- localMoveVector = ForwardVector;
- }
- else if (MoveBack)
- {
- localMoveVector = -ForwardVector;
- }
-
- if (MoveRight)
- {
- localMoveVector += RightVector;
- }
- else if (MoveLeft)
- {
- localMoveVector -= RightVector;
- }
+ controllerMove += ForwardVector;
+ }
+ else if (MoveBack)
+ {
+ controllerMove -= ForwardVector;
+ }
- // Normalize vector so we don't move faster diagonally.
- localMoveVector.Normalize();
- orientationVector = yawRotate.Transform(localMoveVector);
+ if (MoveRight)
+ {
+ controllerMove += RightVector;
}
- else if (GamepadMove.LengthSq() > 0)
+ else if (MoveLeft)
{
- Matrix4f yawRotate = Matrix4f::RotationY(EyeYaw);
- GamepadMove.Normalize();
- orientationVector = yawRotate.Transform(GamepadMove);
+ controllerMove -= RightVector;
}
+ }
+ else if (GamepadMove.LengthSq() > 0)
+ {
+ controllerMove = GamepadMove;
+ }
+ controllerMove = GetOrientation(bMotionRelativeToBody).Rotate(controllerMove);
+ controllerMove.y = 0; // Project to the horizontal plane
+ if (controllerMove.LengthSq() > 0)
+ {
+ // Normalize vector so we don't move faster diagonally.
+ controllerMove.Normalize();
+ controllerMove *= OVR::Alg::Min<float>(MoveSpeed * (float)dt * (shiftDown ? 3.0f : 1.0f), 1.0f);
+ }
- float moveLength = OVR::Alg::Min<float>(MoveSpeed * (float)dt * (shiftDown ? 3.0f : 1.0f), 1.0f);
+ // Compute total move direction vector and move length
+ Vector3f orientationVector = controllerMove;
+ float moveLength = orientationVector.Length();
+ if (moveLength > 0)
+ orientationVector.Normalize();
+
+ float checkLengthForward = moveLength;
+ Planef collisionPlaneForward;
+ bool gotCollision = false;
+
+ for(unsigned int i = 0; i < collisionModels->GetSize(); ++i)
+ {
+ // Checks for collisions at model base level, which should prevent us from
+ // slipping under walls
+ if (collisionModels->At(i)->TestRay(BodyPos, orientationVector, checkLengthForward,
+ &collisionPlaneForward))
+ {
+ gotCollision = true;
+ break;
+ }
+ }
- float checkLengthForward = moveLength;
- Planef collisionPlaneForward;
- float checkLengthLeft = moveLength;
- Planef collisionPlaneLeft;
- float checkLengthRight = moveLength;
- Planef collisionPlaneRight;
- bool gotCollision = false;
- bool gotCollisionLeft = false;
- bool gotCollisionRight = false;
+ if (gotCollision)
+ {
+ // Project orientationVector onto the plane
+ Vector3f slideVector = orientationVector - collisionPlaneForward.N
+ * (orientationVector.Dot(collisionPlaneForward.N));
- for(unsigned int i = 0; i < collisionModels->GetSize(); ++i)
+ // Make sure we aren't in a corner
+ for(unsigned int j = 0; j < collisionModels->GetSize(); ++j)
{
- // Checks for collisions at eye level, which should prevent us from
- // slipping under walls
- if (collisionModels->At(i)->TestRay(EyePos, orientationVector, checkLengthForward,
- &collisionPlaneForward))
- {
- gotCollision = true;
- }
-
- Matrix4f leftRotation = Matrix4f::RotationY(45 * (Math<float>::Pi / 180.0f));
- Vector3f leftVector = leftRotation.Transform(orientationVector);
- if (collisionModels->At(i)->TestRay(EyePos, leftVector, checkLengthLeft,
- &collisionPlaneLeft))
- {
- gotCollisionLeft = true;
- }
- Matrix4f rightRotation = Matrix4f::RotationY(-45 * (Math<float>::Pi / 180.0f));
- Vector3f rightVector = rightRotation.Transform(orientationVector);
- if (collisionModels->At(i)->TestRay(EyePos, rightVector, checkLengthRight,
- &collisionPlaneRight))
+ if (collisionModels->At(j)->TestPoint(BodyPos - Vector3f(0.0f, RailHeight, 0.0f) +
+ (slideVector * (moveLength))) )
{
- gotCollisionRight = true;
+ moveLength = 0;
+ break;
}
}
-
- if (gotCollision)
+ if (moveLength != 0)
{
- // Project orientationVector onto the plane
- Vector3f slideVector = orientationVector - collisionPlaneForward.N
- * (orientationVector.Dot(collisionPlaneForward.N));
-
- // Make sure we aren't in a corner
- for(unsigned int j = 0; j < collisionModels->GetSize(); ++j)
- {
- if (collisionModels->At(j)->TestPoint(EyePos - Vector3f(0.0f, RailHeight, 0.0f) +
- (slideVector * (moveLength))) )
- {
- moveLength = 0;
- }
- }
- if (moveLength != 0)
- {
- orientationVector = slideVector;
- }
+ orientationVector = slideVector;
}
- // Checks for collisions at foot level, which allows us to follow terrain
- orientationVector *= moveLength;
- EyePos += orientationVector;
+ }
+ // Checks for collisions at foot level, which allows us to follow terrain
+ orientationVector *= moveLength;
+ BodyPos += orientationVector;
- Planef collisionPlaneDown;
- float finalDistanceDown = 10;
+ Planef collisionPlaneDown;
+ float finalDistanceDown = 10;
+ // Only apply down if there is collision model (otherwise we get jitter).
+ if (groundCollisionModels->GetSize())
+ {
for(unsigned int i = 0; i < groundCollisionModels->GetSize(); ++i)
{
float checkLengthDown = 10;
- if (groundCollisionModels->At(i)->TestRay(EyePos, Vector3f(0.0f, -1.0f, 0.0f),
- checkLengthDown, &collisionPlaneDown))
+ if (groundCollisionModels->At(i)->TestRay(BodyPos, Vector3f(0.0f, -1.0f, 0.0f),
+ checkLengthDown, &collisionPlaneDown))
{
finalDistanceDown = Alg::Min(finalDistanceDown, checkLengthDown);
}
@@ -160,7 +163,32 @@ void Player::HandleCollision(double dt, Array<Ptr<CollisionModel> >* collisionMo
// Maintain the minimum camera height
if (UserEyeHeight - finalDistanceDown < 1.0f)
{
- EyePos.y += UserEyeHeight - finalDistanceDown;
+ BodyPos.y += UserEyeHeight - finalDistanceDown;
}
}
+
+}
+
+
+
+// Handle directional movement. Returns 'true' if movement was processed.
+bool Player::HandleMoveKey(OVR::KeyCode key, bool down)
+{
+ switch(key)
+ {
+ // Handle player movement keys.
+ // We just update movement state here, while the actual translation is done in OnIdle()
+ // based on time.
+ case OVR::Key_W: MoveForward = down ? (MoveForward | 1) : (MoveForward & ~1); return true;
+ case OVR::Key_S: MoveBack = down ? (MoveBack | 1) : (MoveBack & ~1); return true;
+ case OVR::Key_A: MoveLeft = down ? (MoveLeft | 1) : (MoveLeft & ~1); return true;
+ case OVR::Key_D: MoveRight = down ? (MoveRight | 1) : (MoveRight & ~1); return true;
+ case OVR::Key_Up: MoveForward = down ? (MoveForward | 2) : (MoveForward & ~2); return true;
+ case OVR::Key_Down: MoveBack = down ? (MoveBack | 2) : (MoveBack & ~2); return true;
+ case OVR::Key_Left: MoveLeft = down ? (MoveLeft | 2) : (MoveLeft & ~2); return true;
+ case OVR::Key_Right: MoveRight = down ? (MoveRight | 2) : (MoveRight & ~2); return true;
+ }
+ return false;
}
+
+