CMotionController.cpp
Go to the documentation of this file.00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "stdpch.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <nel/misc/vectord.h>
00039 #include <nel/misc/common.h>
00040 #include <nel/misc/hierarchical_timer.h>
00041
00042
00043
00044
00045 #include "wwcommon/CMotionController.h"
00046 #include "wwcommon/IBaseSimulation.h"
00047 #include "wwcommon/CClientMotionHandler.h"
00048 #include "wwcommon/general.h"
00049 #include "wwcommon/CGameEventServer.h"
00050 #include "wwcommon/CStateManager.h"
00051
00052
00053
00054
00055
00056 namespace WWCOMMON {
00057
00058 const char* CMotionController::m_Name = "motion";
00059
00060 #define ODE_STEP_DT 0.0001
00061
00062 CMotionController::CMotionController(CPerformer* subject)
00063 : m_CorrectionDt(0), m_Subject(subject), m_VCE(NULL), m_VCM(NULL), Duration(0) {
00064 }
00065
00066 CMotionController::~CMotionController() {
00067 if(m_VCE && m_VCM) {
00068 m_VCM->deleteEntity(m_VCE);
00069 }
00070 }
00071
00072 void CMotionController::setVisualCollisionEntity(NL3D::UVisualCollisionManager* vcm) {
00073 if(!vcm)
00074 return;
00075 m_Subject->getMovePrimitive()->setDontSnapToGround(true);
00076 m_VCM = vcm;
00077 m_VCE = vcm->createEntity();
00078 }
00079
00080 void CMotionController::update() {
00081 move(::getSimulation()->deltaTime() - m_CorrectionDt, false);
00082 m_CorrectionDt = 0;
00083 setKey();
00084 }
00085
00086 void CMotionController::update(double dt) {
00087 move(dt, true);
00088 setKey();
00089 m_CorrectionDt = dt;
00090 }
00091
00092 const char* CMotionController::getControllerName() {
00093 return m_Name;
00094 }
00095
00096 void CMotionController::ODE(float dt, float& yaw, float& vYaw, NLMISC::CVector& pos, NLMISC::CVector& sPos, NLMISC::CVector& vPos) {
00097 H_AUTO(CMotionController_ODE);
00098
00099 ISimulationState* orientState = m_Subject->getState(CStateFactory::ST_ORIENTATION);
00100 ISimulationState* moveState = m_Subject->getState(CStateFactory::ST_MOVEMENT);
00101 NLMISC::CMatrix rotMat;
00102 rotMat.rotateZ(yaw);
00103 float t = 0;
00104 for(; t < dt; t += (float)ODE_STEP_DT) {
00105 ODEStep((float)ODE_STEP_DT, yaw, vYaw, pos, sPos, vPos, moveState, orientState, rotMat);
00106 }
00107
00108 t = dt - t;
00109 ODEStep(t, yaw, vYaw, pos, sPos, vPos, moveState, orientState, rotMat);
00110 }
00111
00112 void CMotionController::ODEStep(float dt, float& yaw, float& vYaw, NLMISC::CVector& pos, NLMISC::CVector& sPos, NLMISC::CVector& vPos, ISimulationState* moveState, ISimulationState* orientState, NLMISC::CMatrix &rotMat) {
00113 H_AUTO(CMotionController_ODEStep);
00114 float dYaw = (float)dt*vYaw;
00115 yaw += dYaw;
00116 if(orientState == NULL || orientState->getStateId() == CStateFactory::ST_OR_IDLE) {
00117 if(vYaw != 0) {
00118 vYaw += (float)dt*-vYaw*40;
00119 }
00120 } else {
00121 vYaw += (float)dt*m_Subject->getRotAcceleration();
00122 }
00123 NLMISC::clamp(vYaw, -(m_Subject->getMaxRotSpeed()), m_Subject->getMaxRotSpeed());
00124 if(moveState != NULL && moveState->getStateId() != CStateFactory::ST_MV_IDLE) {
00125 if(dYaw != 0) {
00126 rotMat.rotateZ(dYaw);
00127 vPos = rotMat.mulVector(sPos);
00128 }
00129 pos += vPos*(float)dt;
00130 }
00131 }
00132
00133 #define PACS_ERROR_TOLERANCE_PER_S 10
00134
00135 void CMotionController::move(double dt, bool correction) {
00136 H_AUTO(CMotionController_Move);
00137 if(dt < 0)
00138 nlinfo("ATTENTION!!!!! Moving with negative dt %.6f", dt);
00139 Duration += dt;
00140
00141 CPerformer::CPerformerInterpKey* key = m_Subject->getCurrentKey();
00142 float elapsed = (float)dt;
00143
00144 float vYaw = key->getYawSpeed();
00145 float yaw = key->getYaw();
00146 NLMISC::CVector topos(key->getPosition());
00147 NLMISC::CVector pacsPos(m_Subject->getMovePrimitive()->getFinalPosition(0));
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 NLMISC::CVector veloc(key->getVelocity());
00164 NLMISC::CVector speed(key->getSpeed());
00165
00166 if(m_Subject->useCorrection()) {
00167 if(m_Subject->getCorrectionInterp()->getNumKeys() > 1) {
00168 CPerformer::CorrectInterpKey& ckey = m_Subject->getCorrectionInterp()->getLastKey();
00169
00170 if(!ckey.isHandled() && (ckey.getTime() < (key->getTime()+elapsed))) {
00171
00172 vYaw = ckey.getYawVelocity();
00173 yaw = ckey.getYaw();
00174 topos = ckey.getPosition();
00175 elapsed = key->getTime() + elapsed - ckey.getTime();
00176 pacsPos = ckey.getPosition();
00177 m_Subject->setGlobalPosition(pacsPos);
00178 ckey.setHandled(true);
00179 }
00180 }
00181 }
00182 ODE(elapsed, yaw, vYaw, topos, speed, veloc);
00183
00184 topos = snapToGround(topos);
00185
00186
00187
00188
00189
00190
00191 key->setTime(getSimulation()->adjustedTime());
00192 key->setYawSpeed(vYaw);
00193 key->setYaw(yaw);
00194 key->setSpeed(speed);
00195 key->setPosition(topos);
00196 }
00197
00198 NLMISC::CVector CMotionController::snapToGround(NLMISC::CVector pos) {
00199 if(m_VCE != NULL) {
00200 NLPACS::UGlobalPosition gPos = ::getSimulation()->getGlobalRetriever().retrievePosition(pos);
00201 gPos.LocalPosition.Estimation.z = 0.0f;
00202 pos.z = ::getSimulation()->getGlobalRetriever().getMeanHeight(gPos);
00203 if (!::getSimulation()->getGlobalRetriever().isInterior(gPos)) {
00204 m_VCE->snapToGround(pos);
00205 }
00206 }
00207 return pos;
00208 }
00209
00210 void CMotionController::setKey() {
00211 CPerformer::CPerformerInterpKey* key = m_Subject->getCurrentKey();
00212 m_Subject->getInterpolator()->addKey(*key);
00213 }
00214
00215 };