CMotionController.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2006 Werewolf
00008  *
00009  * This file is part of Werewolf.
00010  * Werewolf is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * Werewolf is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with Werewolf; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 //
00027 // Standard Includes
00028 //
00029 #include "stdpch.h"
00030 
00031 //
00032 // System Includes
00033 //
00034 
00035 //
00036 // NeL Includes
00037 //
00038 #include <nel/misc/vectord.h>
00039 #include <nel/misc/common.h> // clamp() in here
00040 #include <nel/misc/hierarchical_timer.h>
00041 
00042 //
00043 // Werewolf Includes
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 // Namespaces
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     // TODO henri:henri get rid of hardcoded acceleration/decceleration values
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     // TODO henri:henri figure out some logic that thinks if it should use topos or pacsPos
00149 /*
00150     if(!correction) {
00151         NLMISC::CVector diff(pacsPos - topos);
00152         diff.z = 0;
00153         if(diff.norm() < (PACS_ERROR_TOLERANCE_PER_S*getSimulation()->deltaTime())) {
00154             m_Subject->setGlobalPosition(topos);
00155             pacsPos = topos;
00156         } else {
00157             nlinfo("USING PACS!!");
00158             topos = pacsPos;
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     //      if((ckey.getTime() < (key->getTime()+elapsed)) && (ckey.getTime() > key->getTime())) {
00170             if(!ckey.isHandled() && (ckey.getTime() < (key->getTime()+elapsed))) {
00171     //          nlinfo("ATTENTION: Doing DR correction at %.6f %.6f", ckey.getTime(), key->getTime()+elapsed);
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     if(!correction) {
00187         NLMISC::CVector vPos = (topos - pacsPos)/getSimulation()->deltaTime();
00188         m_Subject->getMovePrimitive()->move(vPos, 0);
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 }; // END OF NAMESPACE WWCOMMON

Generated on Mon Jan 11 12:03:39 2010 for Werewolf by  doxygen 1.6.1