Blender V2.61 - r43446
|
00001 /* 00002 * KX_CameraActuator.cpp 00003 * 00004 * 00005 * ***** BEGIN GPL LICENSE BLOCK ***** 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 2 00010 * of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software Foundation, 00019 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 * 00021 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00022 * All rights reserved. 00023 * 00024 * The Original Code is: all of this file. 00025 * 00026 * Contributor(s): none yet. 00027 * 00028 * ***** END GPL LICENSE BLOCK ***** 00029 * 00030 */ 00031 00037 #include "KX_CameraActuator.h" 00038 #include <iostream> 00039 #include <math.h> 00040 #include <float.h> 00041 #include "KX_GameObject.h" 00042 00043 #include "PyObjectPlus.h" 00044 00045 00046 /* ------------------------------------------------------------------------- */ 00047 /* Native functions */ 00048 /* ------------------------------------------------------------------------- */ 00049 00050 KX_CameraActuator::KX_CameraActuator( 00051 SCA_IObject* gameobj, 00052 SCA_IObject *obj, 00053 float hght, 00054 float minhght, 00055 float maxhght, 00056 short axis, 00057 float damping 00058 ): 00059 SCA_IActuator(gameobj, KX_ACT_CAMERA), 00060 m_ob (obj), 00061 m_height (hght), 00062 m_minHeight (minhght), 00063 m_maxHeight (maxhght), 00064 m_axis(axis), 00065 m_damping (damping) 00066 { 00067 if (m_ob) 00068 m_ob->RegisterActuator(this); 00069 } 00070 00071 KX_CameraActuator::~KX_CameraActuator() 00072 { 00073 if (m_ob) 00074 m_ob->UnregisterActuator(this); 00075 } 00076 00077 CValue* 00078 KX_CameraActuator:: 00079 GetReplica( 00080 ) { 00081 KX_CameraActuator* replica = new KX_CameraActuator(*this); 00082 replica->ProcessReplica(); 00083 return replica; 00084 }; 00085 00086 void KX_CameraActuator::ProcessReplica() 00087 { 00088 if (m_ob) 00089 m_ob->RegisterActuator(this); 00090 SCA_IActuator::ProcessReplica(); 00091 } 00092 00093 bool KX_CameraActuator::UnlinkObject(SCA_IObject* clientobj) 00094 { 00095 if (clientobj == m_ob) 00096 { 00097 // this object is being deleted, we cannot continue to track it. 00098 m_ob = NULL; 00099 return true; 00100 } 00101 return false; 00102 } 00103 00104 00105 void KX_CameraActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map) 00106 { 00107 void **h_obj = (*obj_map)[m_ob]; 00108 if (h_obj) { 00109 if (m_ob) 00110 m_ob->UnregisterActuator(this); 00111 m_ob = (SCA_IObject*)(*h_obj); 00112 m_ob->RegisterActuator(this); 00113 } 00114 } 00115 00116 /* three functions copied from blender arith... don't know if there's an equivalent */ 00117 00118 static float Kx_Normalize(float *n) 00119 { 00120 float d; 00121 00122 d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; 00123 /* FLT_EPSILON is too large! A larger value causes normalize errors in a scaled down utah teapot */ 00124 if(d>0.0000000000001) { 00125 d= sqrt(d); 00126 00127 n[0]/=d; 00128 n[1]/=d; 00129 n[2]/=d; 00130 } else { 00131 n[0]=n[1]=n[2]= 0.0; 00132 d= 0.0; 00133 } 00134 return d; 00135 } 00136 00137 static void Kx_Crossf(float *c, float *a, float *b) 00138 { 00139 c[0] = a[1] * b[2] - a[2] * b[1]; 00140 c[1] = a[2] * b[0] - a[0] * b[2]; 00141 c[2] = a[0] * b[1] - a[1] * b[0]; 00142 } 00143 00144 00145 static void Kx_VecUpMat3(float *vec, float mat[][3], short axis) 00146 { 00147 00148 // Construct a camera matrix s.t. the specified axis 00149 00150 // maps to the given vector (*vec). Also defines the rotation 00151 00152 // about this axis by mapping one of the other axis to the y-axis. 00153 00154 00155 float inp; 00156 short cox = 0, coy = 0, coz = 0; 00157 00158 /* up varieeren heeft geen zin, is eigenlijk helemaal geen up! 00159 * zie VecUpMat3old 00160 */ 00161 00162 if(axis==0) { 00163 cox= 0; coy= 1; coz= 2; /* Y up Z tr */ 00164 } 00165 if(axis==1) { 00166 cox= 1; coy= 2; coz= 0; /* Z up X tr */ 00167 } 00168 if(axis==2) { 00169 cox= 2; coy= 0; coz= 1; /* X up Y tr */ 00170 } 00171 if(axis==3) { 00172 cox= 0; coy= 1; coz= 2; /* Y op -Z tr */ 00173 vec[0]= -vec[0]; 00174 vec[1]= -vec[1]; 00175 vec[2]= -vec[2]; 00176 } 00177 if(axis==4) { 00178 cox= 1; coy= 0; coz= 2; /* */ 00179 } 00180 if(axis==5) { 00181 cox= 2; coy= 1; coz= 0; /* Y up X tr */ 00182 } 00183 00184 mat[coz][0]= vec[0]; 00185 mat[coz][1]= vec[1]; 00186 mat[coz][2]= vec[2]; 00187 if (Kx_Normalize((float *)mat[coz]) == 0.f) { 00188 /* this is a very abnormal situation: the camera has reach the object center exactly 00189 We will choose a completely arbitrary direction */ 00190 mat[coz][0] = 1.0f; 00191 mat[coz][1] = 0.0f; 00192 mat[coz][2] = 0.0f; 00193 } 00194 00195 inp= mat[coz][2]; 00196 mat[coy][0]= - inp*mat[coz][0]; 00197 mat[coy][1]= - inp*mat[coz][1]; 00198 mat[coy][2]= 1.0 - inp*mat[coz][2]; 00199 00200 if (Kx_Normalize((float *)mat[coy]) == 0.f) { 00201 /* the camera is vertical, chose the y axis arbitrary */ 00202 mat[coy][0] = 0.f; 00203 mat[coy][1] = 1.f; 00204 mat[coy][2] = 0.f; 00205 } 00206 00207 Kx_Crossf(mat[cox], mat[coy], mat[coz]); 00208 00209 } 00210 00211 bool KX_CameraActuator::Update(double curtime, bool frame) 00212 { 00213 /* wondering... is it really neccesary/desirable to suppress negative */ 00214 /* events here? */ 00215 bool bNegativeEvent = IsNegativeEvent(); 00216 RemoveAllEvents(); 00217 00218 if (bNegativeEvent || !m_ob) 00219 return false; 00220 00221 KX_GameObject *obj = (KX_GameObject*) GetParent(); 00222 MT_Point3 from = obj->NodeGetWorldPosition(); 00223 MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation(); 00224 /* These casts are _very_ dangerous!!! */ 00225 MT_Point3 lookat = ((KX_GameObject*)m_ob)->NodeGetWorldPosition(); 00226 MT_Matrix3x3 actormat = ((KX_GameObject*)m_ob)->NodeGetWorldOrientation(); 00227 00228 float fp1[3], fp2[3], rc[3]; 00229 float inp, fac; //, factor = 0.0; /* some factor... */ 00230 float mindistsq, maxdistsq, distsq; 00231 float mat[3][3]; 00232 00233 /* The rules: */ 00234 /* CONSTRAINT 1: not implemented */ 00235 /* CONSTRAINT 2: can camera see actor? */ 00236 /* CONSTRAINT 3: fixed height relative to floor below actor. */ 00237 /* CONSTRAINT 4: camera rotates behind actor */ 00238 /* CONSTRAINT 5: minimum / maximum distance */ 00239 /* CONSTRAINT 6: again: fixed height relative to floor below actor */ 00240 /* CONSTRAINT 7: track to floor below actor */ 00241 /* CONSTRAINT 8: look a little bit left or right, depending on how the 00242 00243 character is looking (horizontal x) 00244 */ 00245 00246 /* ...and then set the camera position. Since we assume the parent of */ 00247 /* this actuator is always a camera, just set the parent position and */ 00248 /* rotation. We do not check whether we really have a camera as parent. */ 00249 /* It may be better to turn this into a general tracking actuator later */ 00250 /* on, since lots of plausible relations can be filled in here. */ 00251 00252 /* ... set up some parameters ... */ 00253 /* missing here: the 'floorloc' of the actor's shadow */ 00254 00255 mindistsq= m_minHeight*m_minHeight; 00256 maxdistsq= m_maxHeight*m_maxHeight; 00257 00258 /* C1: not checked... is a future option */ 00259 00260 /* C2: blender test_visibility function. Can this be a ray-test? */ 00261 00262 /* C3: fixed height */ 00263 from[2] = (15.0*from[2] + lookat[2] + m_height)/16.0; 00264 00265 00266 /* C4: camera behind actor */ 00267 switch (m_axis) { 00268 case OB_POSX: 00269 /* X */ 00270 fp1[0] = actormat[0][0]; 00271 fp1[1] = actormat[1][0]; 00272 fp1[2] = actormat[2][0]; 00273 00274 fp2[0] = frommat[0][0]; 00275 fp2[1] = frommat[1][0]; 00276 fp2[2] = frommat[2][0]; 00277 break; 00278 case OB_POSY: 00279 /* Y */ 00280 fp1[0] = actormat[0][1]; 00281 fp1[1] = actormat[1][1]; 00282 fp1[2] = actormat[2][1]; 00283 00284 fp2[0] = frommat[0][1]; 00285 fp2[1] = frommat[1][1]; 00286 fp2[2] = frommat[2][1]; 00287 break; 00288 case OB_NEGX: 00289 /* -X */ 00290 fp1[0] = -actormat[0][0]; 00291 fp1[1] = -actormat[1][0]; 00292 fp1[2] = -actormat[2][0]; 00293 00294 fp2[0] = frommat[0][0]; 00295 fp2[1] = frommat[1][0]; 00296 fp2[2] = frommat[2][0]; 00297 break; 00298 case OB_NEGY: 00299 /* -Y */ 00300 fp1[0] = -actormat[0][1]; 00301 fp1[1] = -actormat[1][1]; 00302 fp1[2] = -actormat[2][1]; 00303 00304 fp2[0] = frommat[0][1]; 00305 fp2[1] = frommat[1][1]; 00306 fp2[2] = frommat[2][1]; 00307 break; 00308 default: 00309 assert(0); 00310 break; 00311 } 00312 00313 inp= fp1[0]*fp2[0] + fp1[1]*fp2[1] + fp1[2]*fp2[2]; 00314 fac= (-1.0 + inp) * m_damping; 00315 00316 from[0]+= fac*fp1[0]; 00317 from[1]+= fac*fp1[1]; 00318 from[2]+= fac*fp1[2]; 00319 00320 /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */ 00321 if(inp<0.0) { 00322 if(fp1[0]*fp2[1] - fp1[1]*fp2[0] > 0.0) { 00323 from[0]-= fac*fp1[1]; 00324 from[1]+= fac*fp1[0]; 00325 } 00326 else { 00327 from[0]+= fac*fp1[1]; 00328 from[1]-= fac*fp1[0]; 00329 } 00330 } 00331 00332 /* CONSTRAINT 5: minimum / maximum afstand */ 00333 00334 rc[0]= (lookat[0]-from[0]); 00335 rc[1]= (lookat[1]-from[1]); 00336 rc[2]= (lookat[2]-from[2]); 00337 distsq= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2]; 00338 00339 if(distsq > maxdistsq) { 00340 distsq = 0.15*(distsq-maxdistsq)/distsq; 00341 00342 from[0] += distsq*rc[0]; 00343 from[1] += distsq*rc[1]; 00344 from[2] += distsq*rc[2]; 00345 } 00346 else if(distsq < mindistsq) { 00347 distsq = 0.15*(mindistsq-distsq)/mindistsq; 00348 00349 from[0] -= distsq*rc[0]; 00350 from[1] -= distsq*rc[1]; 00351 from[2] -= distsq*rc[2]; 00352 } 00353 00354 00355 /* CONSTRAINT 7: track to schaduw */ 00356 rc[0]= (lookat[0]-from[0]); 00357 rc[1]= (lookat[1]-from[1]); 00358 rc[2]= (lookat[2]-from[2]); 00359 Kx_VecUpMat3(rc, mat, 3); /* y up Track -z */ 00360 00361 00362 00363 00364 /* now set the camera position and rotation */ 00365 00366 obj->NodeSetLocalPosition(from); 00367 00368 actormat[0][0]= mat[0][0]; actormat[0][1]= mat[1][0]; actormat[0][2]= mat[2][0]; 00369 actormat[1][0]= mat[0][1]; actormat[1][1]= mat[1][1]; actormat[1][2]= mat[2][1]; 00370 actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2]; 00371 obj->NodeSetLocalOrientation(actormat); 00372 00373 return true; 00374 } 00375 00376 CValue *KX_CameraActuator::findObject(const char *obName) 00377 { 00378 /* hook to object system */ 00379 return NULL; 00380 } 00381 00382 #ifdef WITH_PYTHON 00383 00384 /* ------------------------------------------------------------------------- */ 00385 /* Python functions */ 00386 /* ------------------------------------------------------------------------- */ 00387 00388 /* Integration hooks ------------------------------------------------------- */ 00389 PyTypeObject KX_CameraActuator::Type = { 00390 PyVarObject_HEAD_INIT(NULL, 0) 00391 "KX_CameraActuator", 00392 sizeof(PyObjectPlus_Proxy), 00393 0, 00394 py_base_dealloc, 00395 0, 00396 0, 00397 0, 00398 0, 00399 py_base_repr, 00400 0,0,0,0,0,0,0,0,0, 00401 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 00402 0,0,0,0,0,0,0, 00403 Methods, 00404 0, 00405 0, 00406 &SCA_IActuator::Type, 00407 0,0,0,0,0,0, 00408 py_base_new 00409 }; 00410 00411 PyMethodDef KX_CameraActuator::Methods[] = { 00412 {NULL, NULL} //Sentinel 00413 }; 00414 00415 PyAttributeDef KX_CameraActuator::Attributes[] = { 00416 KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_minHeight), 00417 KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_maxHeight), 00418 KX_PYATTRIBUTE_FLOAT_RW("height",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_height), 00419 KX_PYATTRIBUTE_SHORT_RW("axis", 0, 3, true, KX_CameraActuator,m_axis), 00420 KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), 00421 KX_PYATTRIBUTE_FLOAT_RW("damping",0.f,10.f,KX_CameraActuator,m_damping), 00422 {NULL} 00423 }; 00424 00425 PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 00426 { 00427 KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v); 00428 if (self->m_ob==NULL) 00429 Py_RETURN_NONE; 00430 else 00431 return self->m_ob->GetProxy(); 00432 } 00433 00434 int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 00435 { 00436 KX_CameraActuator* self= static_cast<KX_CameraActuator*>(self_v); 00437 KX_GameObject *gameobj; 00438 00439 if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator")) 00440 return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error 00441 00442 if (self->m_ob) 00443 self->m_ob->UnregisterActuator(self); 00444 00445 if ((self->m_ob = (SCA_IObject*)gameobj)) 00446 self->m_ob->RegisterActuator(self); 00447 00448 return PY_SET_ATTR_SUCCESS; 00449 } 00450 00451 #endif // WITH_PYTHON 00452 00453 /* eof */