|
Blender
V2.59
|
00001 00004 // 00005 // Replace the mesh for this actuator's parent 00006 // 00007 // $Id: KX_TrackToActuator.cpp 36523 2011-05-06 20:18:42Z blendix $ 00008 // 00009 // ***** BEGIN GPL LICENSE BLOCK ***** 00010 // 00011 // This program is free software; you can redistribute it and/or 00012 // modify it under the terms of the GNU General Public License 00013 // as published by the Free Software Foundation; either version 2 00014 // of the License, or (at your option) any later version. 00015 // 00016 // This program is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU General Public License 00022 // along with this program; if not, write to the Free Software Foundation, 00023 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 // 00025 // The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00026 // All rights reserved. 00027 // 00028 // The Original Code is: all of this file. 00029 // 00030 // Contributor(s): none yet. 00031 // 00032 // ***** END GPL LICENSE BLOCK ***** 00033 00034 // todo: not all trackflags / upflags are implemented/tested ! 00035 // m_trackflag is used to determine the forward tracking direction 00036 // m_upflag for the up direction 00037 // normal situation is +y for forward, +z for up 00038 00039 #include "MT_Scalar.h" 00040 #include "SCA_IActuator.h" 00041 #include "KX_TrackToActuator.h" 00042 #include "SCA_IScene.h" 00043 #include "SCA_LogicManager.h" 00044 #include <math.h> 00045 #include <iostream> 00046 #include "KX_GameObject.h" 00047 00048 #include "PyObjectPlus.h" 00049 00050 /* ------------------------------------------------------------------------- */ 00051 /* Native functions */ 00052 /* ------------------------------------------------------------------------- */ 00053 00054 00055 00056 KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, 00057 SCA_IObject *ob, 00058 int time, 00059 bool allow3D, 00060 int trackflag, 00061 int upflag) 00062 : SCA_IActuator(gameobj, KX_ACT_TRACKTO) 00063 { 00064 m_time = time; 00065 m_allow3D = allow3D; 00066 m_object = ob; 00067 m_trackflag = trackflag; 00068 m_upflag = upflag; 00069 m_parentobj = 0; 00070 00071 if (m_object) 00072 m_object->RegisterActuator(this); 00073 00074 { 00075 // if the object is vertex parented, don't check parent orientation as the link is broken 00076 if (!((KX_GameObject*)gameobj)->IsVertexParent()){ 00077 m_parentobj = ((KX_GameObject*)gameobj)->GetParent(); // check if the object is parented 00078 if (m_parentobj) { 00079 // if so, store the initial local rotation 00080 // this is needed to revert the effect of the parent inverse node (TBC) 00081 m_parentlocalmat = m_parentobj->GetSGNode()->GetLocalOrientation(); 00082 // use registration mechanism rather than AddRef, it creates zombie objects 00083 m_parentobj->RegisterActuator(this); 00084 // GetParent did AddRef, undo here 00085 m_parentobj->Release(); 00086 } 00087 } 00088 } 00089 00090 } /* End of constructor */ 00091 00092 00093 00094 /* old function from Blender */ 00095 MT_Matrix3x3 EulToMat3(float *eul) 00096 { 00097 MT_Matrix3x3 mat; 00098 float ci, cj, ch, si, sj, sh, cc, cs, sc, ss; 00099 00100 ci = cos(eul[0]); 00101 cj = cos(eul[1]); 00102 ch = cos(eul[2]); 00103 si = sin(eul[0]); 00104 sj = sin(eul[1]); 00105 sh = sin(eul[2]); 00106 cc = ci*ch; 00107 cs = ci*sh; 00108 sc = si*ch; 00109 ss = si*sh; 00110 00111 mat[0][0] = cj*ch; 00112 mat[1][0] = sj*sc-cs; 00113 mat[2][0] = sj*cc+ss; 00114 mat[0][1] = cj*sh; 00115 mat[1][1] = sj*ss+cc; 00116 mat[2][1] = sj*cs-sc; 00117 mat[0][2] = -sj; 00118 mat[1][2] = cj*si; 00119 mat[2][2] = cj*ci; 00120 00121 return mat; 00122 } 00123 00124 00125 00126 /* old function from Blender */ 00127 void Mat3ToEulOld(MT_Matrix3x3 mat, float *eul) 00128 { 00129 MT_Scalar cy; 00130 00131 cy = sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]); 00132 00133 if (cy > 16.0*FLT_EPSILON) { 00134 eul[0] = atan2(mat[1][2], mat[2][2]); 00135 eul[1] = atan2(-mat[0][2], cy); 00136 eul[2] = atan2(mat[0][1], mat[0][0]); 00137 } else { 00138 eul[0] = atan2(-mat[2][1], mat[1][1]); 00139 eul[1] = atan2(-mat[0][2], cy); 00140 eul[2] = 0.0; 00141 } 00142 } 00143 00144 00145 00146 /* old function from Blender */ 00147 void compatible_eulFast(float *eul, float *oldrot) 00148 { 00149 float dx, dy, dz; 00150 00151 /* angular difference of 360 degrees */ 00152 00153 dx= eul[0] - oldrot[0]; 00154 dy= eul[1] - oldrot[1]; 00155 dz= eul[2] - oldrot[2]; 00156 00157 if( fabs(dx) > MT_PI) { 00158 if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI; 00159 } 00160 if( fabs(dy) > MT_PI) { 00161 if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI; 00162 } 00163 if( fabs(dz) > MT_PI ) { 00164 if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI; 00165 } 00166 } 00167 00168 00169 00170 MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time) 00171 { 00172 float eul[3], oldeul[3]; 00173 00174 Mat3ToEulOld(oldmat, oldeul); 00175 Mat3ToEulOld(mat, eul); 00176 compatible_eulFast(eul, oldeul); 00177 00178 eul[0]= (m_time*oldeul[0] + eul[0])/(1.0+m_time); 00179 eul[1]= (m_time*oldeul[1] + eul[1])/(1.0+m_time); 00180 eul[2]= (m_time*oldeul[2] + eul[2])/(1.0+m_time); 00181 00182 return EulToMat3(eul); 00183 } 00184 00185 00186 00187 KX_TrackToActuator::~KX_TrackToActuator() 00188 { 00189 if (m_object) 00190 m_object->UnregisterActuator(this); 00191 if (m_parentobj) 00192 m_parentobj->UnregisterActuator(this); 00193 } /* end of destructor */ 00194 00195 void KX_TrackToActuator::ProcessReplica() 00196 { 00197 // the replica is tracking the same object => register it 00198 if (m_object) 00199 m_object->RegisterActuator(this); 00200 if (m_parentobj) 00201 m_parentobj->RegisterActuator(this); 00202 SCA_IActuator::ProcessReplica(); 00203 } 00204 00205 00206 bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj) 00207 { 00208 if (clientobj == m_object) 00209 { 00210 // this object is being deleted, we cannot continue to track it. 00211 m_object = NULL; 00212 return true; 00213 } 00214 if (clientobj == m_parentobj) 00215 { 00216 m_parentobj = NULL; 00217 return true; 00218 } 00219 return false; 00220 } 00221 00222 void KX_TrackToActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map) 00223 { 00224 void **h_obj = (*obj_map)[m_object]; 00225 if (h_obj) { 00226 if (m_object) 00227 m_object->UnregisterActuator(this); 00228 m_object = (SCA_IObject*)(*h_obj); 00229 m_object->RegisterActuator(this); 00230 } 00231 00232 void **h_parobj = (*obj_map)[m_parentobj]; 00233 if (h_parobj) { 00234 if (m_parentobj) 00235 m_parentobj->UnregisterActuator(this); 00236 m_parentobj= (KX_GameObject*)(*h_parobj); 00237 m_parentobj->RegisterActuator(this); 00238 } 00239 } 00240 00241 00242 bool KX_TrackToActuator::Update(double curtime, bool frame) 00243 { 00244 bool result = false; 00245 bool bNegativeEvent = IsNegativeEvent(); 00246 RemoveAllEvents(); 00247 00248 if (bNegativeEvent) 00249 { 00250 // do nothing on negative events 00251 } 00252 else if (m_object) 00253 { 00254 KX_GameObject* curobj = (KX_GameObject*) GetParent(); 00255 MT_Vector3 dir = ((KX_GameObject*)m_object)->NodeGetWorldPosition() - curobj->NodeGetWorldPosition(); 00256 if (dir.length2()) 00257 dir.normalize(); 00258 MT_Vector3 up(0,0,1); 00259 00260 00261 #ifdef DSADSA 00262 switch (m_upflag) 00263 { 00264 case 0: 00265 { 00266 up.setValue(1.0,0,0); 00267 break; 00268 } 00269 case 1: 00270 { 00271 up.setValue(0,1.0,0); 00272 break; 00273 } 00274 case 2: 00275 default: 00276 { 00277 up.setValue(0,0,1.0); 00278 } 00279 } 00280 #endif 00281 if (m_allow3D) 00282 { 00283 up = (up - up.dot(dir) * dir).safe_normalized(); 00284 00285 } 00286 else 00287 { 00288 dir = (dir - up.dot(dir)*up).safe_normalized(); 00289 } 00290 00291 MT_Vector3 left; 00292 MT_Matrix3x3 mat; 00293 00294 switch (m_trackflag) 00295 { 00296 case 0: // TRACK X 00297 { 00298 // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up 00299 left = dir.safe_normalized(); 00300 dir = (left.cross(up)).safe_normalized(); 00301 mat.setValue ( 00302 left[0], dir[0],up[0], 00303 left[1], dir[1],up[1], 00304 left[2], dir[2],up[2] 00305 ); 00306 00307 break; 00308 }; 00309 case 1: // TRACK Y 00310 { 00311 // (0.0 , 1.0 , 0.0 ) y direction is forward, z (0.0 , 0.0 , 1.0 ) up 00312 left = (dir.cross(up)).safe_normalized(); 00313 mat.setValue ( 00314 left[0], dir[0],up[0], 00315 left[1], dir[1],up[1], 00316 left[2], dir[2],up[2] 00317 ); 00318 00319 break; 00320 } 00321 00322 case 2: // track Z 00323 { 00324 left = up.safe_normalized(); 00325 up = dir.safe_normalized(); 00326 dir = left; 00327 left = (dir.cross(up)).safe_normalized(); 00328 mat.setValue ( 00329 left[0], dir[0],up[0], 00330 left[1], dir[1],up[1], 00331 left[2], dir[2],up[2] 00332 ); 00333 break; 00334 } 00335 00336 case 3: // TRACK -X 00337 { 00338 // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up 00339 left = -dir.safe_normalized(); 00340 dir = -(left.cross(up)).safe_normalized(); 00341 mat.setValue ( 00342 left[0], dir[0],up[0], 00343 left[1], dir[1],up[1], 00344 left[2], dir[2],up[2] 00345 ); 00346 00347 break; 00348 }; 00349 case 4: // TRACK -Y 00350 { 00351 // (0.0 , -1.0 , 0.0 ) -y direction is forward, z (0.0 , 0.0 , 1.0 ) up 00352 left = (-dir.cross(up)).safe_normalized(); 00353 mat.setValue ( 00354 left[0], -dir[0],up[0], 00355 left[1], -dir[1],up[1], 00356 left[2], -dir[2],up[2] 00357 ); 00358 break; 00359 } 00360 case 5: // track -Z 00361 { 00362 left = up.safe_normalized(); 00363 up = -dir.safe_normalized(); 00364 dir = left; 00365 left = (dir.cross(up)).safe_normalized(); 00366 mat.setValue ( 00367 left[0], dir[0],up[0], 00368 left[1], dir[1],up[1], 00369 left[2], dir[2],up[2] 00370 ); 00371 00372 break; 00373 } 00374 00375 default: 00376 { 00377 // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up 00378 left = -dir.safe_normalized(); 00379 dir = -(left.cross(up)).safe_normalized(); 00380 mat.setValue ( 00381 left[0], dir[0],up[0], 00382 left[1], dir[1],up[1], 00383 left[2], dir[2],up[2] 00384 ); 00385 } 00386 } 00387 00388 MT_Matrix3x3 oldmat; 00389 oldmat= curobj->NodeGetWorldOrientation(); 00390 00391 /* erwin should rewrite this! */ 00392 mat= matrix3x3_interpol(oldmat, mat, m_time); 00393 00394 00395 if(m_parentobj){ // check if the model is parented and calculate the child transform 00396 00397 MT_Point3 localpos; 00398 localpos = curobj->GetSGNode()->GetLocalPosition(); 00399 // Get the inverse of the parent matrix 00400 MT_Matrix3x3 parentmatinv; 00401 parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse (); 00402 // transform the local coordinate system into the parents system 00403 mat = parentmatinv * mat; 00404 // append the initial parent local rotation matrix 00405 mat = m_parentlocalmat * mat; 00406 00407 // set the models tranformation properties 00408 curobj->NodeSetLocalOrientation(mat); 00409 curobj->NodeSetLocalPosition(localpos); 00410 //curobj->UpdateTransform(); 00411 } 00412 else 00413 { 00414 curobj->NodeSetLocalOrientation(mat); 00415 } 00416 00417 result = true; 00418 } 00419 00420 return result; 00421 } 00422 00423 #ifdef WITH_PYTHON 00424 00425 /* ------------------------------------------------------------------------- */ 00426 /* Python functions */ 00427 /* ------------------------------------------------------------------------- */ 00428 00429 /* Integration hooks ------------------------------------------------------- */ 00430 PyTypeObject KX_TrackToActuator::Type = { 00431 PyVarObject_HEAD_INIT(NULL, 0) 00432 "KX_TrackToActuator", 00433 sizeof(PyObjectPlus_Proxy), 00434 0, 00435 py_base_dealloc, 00436 0, 00437 0, 00438 0, 00439 0, 00440 py_base_repr, 00441 0,0,0,0,0,0,0,0,0, 00442 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00443 0,0,0,0,0,0,0, 00444 Methods, 00445 0, 00446 0, 00447 &SCA_IActuator::Type, 00448 0,0,0,0,0,0, 00449 py_base_new 00450 }; 00451 00452 PyMethodDef KX_TrackToActuator::Methods[] = { 00453 {NULL,NULL} //Sentinel 00454 }; 00455 00456 PyAttributeDef KX_TrackToActuator::Attributes[] = { 00457 KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_TrackToActuator,m_time), 00458 KX_PYATTRIBUTE_BOOL_RW("use3D",KX_TrackToActuator,m_allow3D), 00459 KX_PYATTRIBUTE_RW_FUNCTION("object", KX_TrackToActuator, pyattr_get_object, pyattr_set_object), 00460 00461 { NULL } //Sentinel 00462 }; 00463 00464 PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) 00465 { 00466 KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self); 00467 if (!actuator->m_object) 00468 Py_RETURN_NONE; 00469 else 00470 return actuator->m_object->GetProxy(); 00471 } 00472 00473 int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00474 { 00475 KX_TrackToActuator* actuator = static_cast<KX_TrackToActuator*>(self); 00476 KX_GameObject *gameobj; 00477 00478 if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_TrackToActuator")) 00479 return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error 00480 00481 if (actuator->m_object != NULL) 00482 actuator->m_object->UnregisterActuator(actuator); 00483 00484 actuator->m_object = (SCA_IObject*) gameobj; 00485 00486 if (actuator->m_object) 00487 actuator->m_object->RegisterActuator(actuator); 00488 00489 return PY_SET_ATTR_SUCCESS; 00490 } 00491 00492 #endif // WITH_PYTHON 00493 00494 /* eof */