00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <PVLE/Input/HumanMatrixGetter.h>
00028 #include <PVLE/Input/Control.h>
00029 #include <PVLE/Util/Assert.h>
00030 #include <math.h>
00031
00032 const osg::Vec3::value_type HumanMatrixGetter::AlphaMin = 0.008;
00033
00034
00035 void HumanMatrixGetter::handleFrame(double elapsed) {
00036 ASSERT(pControler);
00037
00038
00039 for(ControlEventList::const_iterator it = pControler->getEventBegin(), itEnd = pControler->getEventEnd(); it!=itEnd; ++it) {
00040 if (it->getType() == ControlEvent::SWITCH_DOWN) {
00041 if (it->getSwitchId() == ControlState::FASTER) MovingSpeed *= 2;
00042 else if (it->getSwitchId() == ControlState::SLOWER) MovingSpeed /= 2;
00043 }
00044 }
00045
00046
00047 pControler->clearEvents();
00048
00049
00050
00051 ControlState & cs = pControler->getControlState();
00052
00053 osg::Vec3 SpeedVec, Right;
00054 Right = Dir ^ Up;
00055 Right.normalize();
00056
00057 if (cs[ControlState::FORWARD]) SpeedVec += Dir * MovingSpeed;
00058 else if (cs[ControlState::BACKWARD]) SpeedVec += Dir * -MovingSpeed;
00059
00060 if (cs[ControlState::STRAFE_RIGHT]) SpeedVec += Right * MovingSpeed;
00061 else if (cs[ControlState::STRAFE_LEFT]) SpeedVec += Right * -MovingSpeed;
00062
00063 if (cs[ControlState::UP] || cs[ControlState::JUMP]) SpeedVec += Up * MovingSpeed;
00064 else if (cs[ControlState::DOWN] || cs[ControlState::CROUCH]) SpeedVec += Up * -MovingSpeed;
00065
00066 osg::Vec3::value_type Speed = SpeedVec.length();
00067 if (Speed > MovingSpeed) SpeedVec *= (MovingSpeed / Speed);
00068
00069 if (cs[ControlState::FAST_TOGGLE]) SpeedVec /= 25;
00070
00071
00072 EyePos += SpeedVec * elapsed;
00073
00074
00075
00076 Dir = Dir * yawPitchRoll(cs.getAxis(ControlState::AXIS_X) * elapsed, cs.getAxis(ControlState::AXIS_Y) * elapsed, 0);
00077 Dir.normalize();
00078 }
00079
00080
00081 osg::Matrix HumanMatrixGetter::yawPitchRoll(osg::Vec3::value_type yaw, osg::Vec3::value_type pitch, osg::Vec3::value_type roll) const {
00082 osg::Matrix Mx;
00083
00084
00085
00086
00087
00088 if (pitch) {
00089
00090 ASSERT(Dir.length2() > 0.99 && Dir.length2() < 1.01 && Up.length2() > 0.99 && Up.length2() < 1.01);
00091 osg::Vec3::value_type CosAlpha = Dir * Up;
00092 osg::Vec3::value_type Alpha = acos(CosAlpha);
00093
00094
00095 if (Alpha < osg::PI_2 && pitch<0) {
00096 if ((Alpha + pitch) <= AlphaMin) {
00097 pitch = AlphaMin - Alpha;
00098 if (pitch>0) pitch = 0;
00099 }
00100 }
00101 if (Alpha > osg::PI_2 && pitch>0) {
00102 if ((Alpha + pitch) >= (osg::PI - AlphaMin)) {
00103 pitch = (osg::PI - AlphaMin) - Alpha;
00104 if (pitch<0) pitch = 0;
00105 }
00106 }
00107 }
00108
00109
00110 osg::Vec3 Right = Dir ^ Up;
00111 Right.normalize();
00112
00113
00114 return osg::Matrix::rotate(
00115 -yaw, Up,
00116 -pitch, Right,
00117 -roll, Dir
00118 );
00119 }