27f4870de108ab7d2d79a5c2500cf000e33dab45
[blender.git] / source / gameengine / Ketsji / KX_CameraActuator.cpp
1 /**
2  * KX_CameraActuator.cpp
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  *
31  */
32
33 #include "KX_CameraActuator.h"
34 #include <iostream>
35 #include <math.h>
36 #include "KX_GameObject.h"
37
38 STR_String KX_CameraActuator::X_AXIS_STRING = "x";
39 STR_String KX_CameraActuator::Y_AXIS_STRING = "y";
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45
46 /* ------------------------------------------------------------------------- */
47 /* Native functions                                                          */
48 /* ------------------------------------------------------------------------- */
49
50 KX_CameraActuator::KX_CameraActuator(
51         SCA_IObject* gameobj, 
52         CValue *obj,
53         MT_Scalar hght,
54         MT_Scalar minhght,
55         MT_Scalar maxhght,
56         bool  xytog,
57         PyTypeObject* T
58 ): 
59         SCA_IActuator(gameobj, T),
60         m_ob (obj),
61         m_height (hght),
62         m_minHeight (minhght),
63         m_maxHeight (maxhght),
64         m_x (xytog)
65 {
66 }
67
68 KX_CameraActuator::~KX_CameraActuator()
69 {
70         //nothing to do
71 }
72
73         CValue* 
74 KX_CameraActuator::
75 GetReplica(
76 ) {
77         KX_CameraActuator* replica = new KX_CameraActuator(*this);
78         replica->ProcessReplica();
79         // this will copy properties and so on...
80         CValue::AddDataToReplica(replica);
81         return replica;
82 };
83
84
85
86
87 /* three functions copied from blender arith... don't know if there's an equivalent */
88
89 static float Kx_Normalize(float *n)
90 {
91         float d;
92         
93         d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
94         /* FLT_EPSILON is too large! A larger value causes normalize errors in a scaled down utah teapot */
95         if(d>0.0000000000001) {
96                 d= sqrt(d);
97
98                 n[0]/=d; 
99                 n[1]/=d; 
100                 n[2]/=d;
101         } else {
102                 n[0]=n[1]=n[2]= 0.0;
103                 d= 0.0;
104         }
105         return d;
106 }
107
108 static void Kx_Crossf(float *c, float *a, float *b)
109 {
110         c[0] = a[1] * b[2] - a[2] * b[1];
111         c[1] = a[2] * b[0] - a[0] * b[2];
112         c[2] = a[0] * b[1] - a[1] * b[0];
113 }
114
115
116 static void Kx_VecUpMat3(float *vec, float mat[][3], short axis)
117 {
118
119         // Construct a camera matrix s.t. the specified axis
120
121         // maps to the given vector (*vec). Also defines the rotation
122
123         // about this axis by mapping one of the other axis to the y-axis.
124
125
126         float inp;
127         short cox = 0, coy = 0, coz = 0;
128         
129         /* up varieeren heeft geen zin, is eigenlijk helemaal geen up!
130          * zie VecUpMat3old
131          */
132
133         if(axis==0) {
134                 cox= 0; coy= 1; coz= 2;         /* Y up Z tr */
135         }
136         if(axis==1) {
137                 cox= 1; coy= 2; coz= 0;         /* Z up X tr */
138         }
139         if(axis==2) {
140                 cox= 2; coy= 0; coz= 1;         /* X up Y tr */
141         }
142         if(axis==3) {
143                 cox= 0; coy= 1; coz= 2;         /* Y op -Z tr */
144                 vec[0]= -vec[0];
145                 vec[1]= -vec[1];
146                 vec[2]= -vec[2];
147         }
148         if(axis==4) {
149                 cox= 1; coy= 0; coz= 2;         /*  */
150         }
151         if(axis==5) {
152                 cox= 2; coy= 1; coz= 0;         /* Y up X tr */
153         }
154
155         mat[coz][0]= vec[0];
156         mat[coz][1]= vec[1];
157         mat[coz][2]= vec[2];
158         if (Kx_Normalize((float *)mat[coz]) == 0.f) {
159                 /* this is a very abnormal situation: the camera has reach the object center exactly
160                    We will choose a completely arbitrary direction */
161                 mat[coz][0] = 1.0f;
162                 mat[coz][1] = 0.0f;
163                 mat[coz][2] = 0.0f;
164         }
165         
166         inp= mat[coz][2];
167         mat[coy][0]= - inp*mat[coz][0];
168         mat[coy][1]= - inp*mat[coz][1];
169         mat[coy][2]= 1.0 - inp*mat[coz][2];
170
171         if (Kx_Normalize((float *)mat[coy]) == 0.f) {
172                 /* the camera is vertical, chose the y axis arbitrary */
173                 mat[coy][0] = 0.f;
174                 mat[coy][1] = 1.f;
175                 mat[coy][2] = 0.f;
176         }
177         
178         Kx_Crossf(mat[cox], mat[coy], mat[coz]);
179         
180 }
181
182 bool KX_CameraActuator::Update(double curtime, bool frame)
183 {
184         bool result = true;
185
186         KX_GameObject *obj = (KX_GameObject*) GetParent();
187         MT_Point3 from = obj->NodeGetWorldPosition();
188         MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation();
189         /* These casts are _very_ dangerous!!! */
190         MT_Point3 lookat = ((KX_GameObject*)m_ob)->NodeGetWorldPosition();
191         MT_Matrix3x3 actormat = ((KX_GameObject*)m_ob)->NodeGetWorldOrientation();
192
193         float fp1[3], fp2[3], rc[3];
194         float inp, fac; //, factor = 0.0; /* some factor...                                    */
195         float mindistsq, maxdistsq, distsq;
196         float mat[3][3];
197         
198         /* wondering... is it really neccesary/desirable to suppress negative    */
199         /* events here?                                                          */
200         bool bNegativeEvent = IsNegativeEvent();
201         RemoveAllEvents();
202
203         if (bNegativeEvent) return false;
204         
205         /* The rules:                                                            */
206         /* CONSTRAINT 1: not implemented */
207         /* CONSTRAINT 2: can camera see actor?              */
208         /* CONSTRAINT 3: fixed height relative to floor below actor.             */
209         /* CONSTRAINT 4: camera rotates behind actor                              */
210         /* CONSTRAINT 5: minimum / maximum distance                             */
211         /* CONSTRAINT 6: again: fixed height relative to floor below actor        */
212         /* CONSTRAINT 7: track to floor below actor                               */
213         /* CONSTRAINT 8: look a little bit left or right, depending on how the
214
215            character is looking (horizontal x)
216  */
217
218         /* ...and then set the camera position. Since we assume the parent of    */
219         /* this actuator is always a camera, just set the parent position and    */
220         /* rotation. We do not check whether we really have a camera as parent.  */
221         /* It may be better to turn this into a general tracking actuator later  */
222         /* on, since lots of plausible relations can be filled in here.          */
223
224         /* ... set up some parameters ...                                        */
225         /* missing here: the 'floorloc' of the actor's shadow */
226
227         mindistsq= m_minHeight*m_minHeight;
228         maxdistsq= m_maxHeight*m_maxHeight;
229
230         /* C1: not checked... is a future option                                 */
231
232         /* C2: blender test_visibility function. Can this be a ray-test?         */
233
234         /* C3: fixed height  */
235         from[2] = (15.0*from[2] + lookat[2] + m_height)/16.0;
236
237
238         /* C4: camera behind actor   */
239         if (m_x) {
240                 fp1[0] = actormat[0][0];
241                 fp1[1] = actormat[1][0];
242                 fp1[2] = actormat[2][0];
243
244                 fp2[0] = frommat[0][0];
245                 fp2[1] = frommat[1][0];
246                 fp2[2] = frommat[2][0];
247         } 
248         else {
249                 fp1[0] = actormat[0][1];
250                 fp1[1] = actormat[1][1];
251                 fp1[2] = actormat[2][1];
252
253                 fp2[0] = frommat[0][1];
254                 fp2[1] = frommat[1][1];
255                 fp2[2] = frommat[2][1];
256         }
257         
258         inp= fp1[0]*fp2[0] + fp1[1]*fp2[1] + fp1[2]*fp2[2];
259         fac= (-1.0 + inp)/32.0;
260
261         from[0]+= fac*fp1[0];
262         from[1]+= fac*fp1[1];
263         from[2]+= fac*fp1[2];
264         
265         /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */
266         if(inp<0.0) {
267                 if(fp1[0]*fp2[1] - fp1[1]*fp2[0] > 0.0) {
268                         from[0]-= fac*fp1[1];
269                         from[1]+= fac*fp1[0];
270                 }
271                 else {
272                         from[0]+= fac*fp1[1];
273                         from[1]-= fac*fp1[0];
274                 }
275         }
276
277         /* CONSTRAINT 5: minimum / maximum afstand */
278
279         rc[0]= (lookat[0]-from[0]);
280         rc[1]= (lookat[1]-from[1]);
281         rc[2]= (lookat[2]-from[2]);
282         distsq= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2];
283
284         if(distsq > maxdistsq) {
285                 distsq = 0.15*(distsq-maxdistsq)/distsq;
286                 
287                 from[0] += distsq*rc[0];
288                 from[1] += distsq*rc[1];
289                 from[2] += distsq*rc[2];
290         }
291         else if(distsq < mindistsq) {
292                 distsq = 0.15*(mindistsq-distsq)/mindistsq;
293                 
294                 from[0] -= distsq*rc[0];
295                 from[1] -= distsq*rc[1];
296                 from[2] -= distsq*rc[2];
297         }
298
299
300         /* CONSTRAINT 7: track to schaduw */
301         rc[0]= (lookat[0]-from[0]);
302         rc[1]= (lookat[1]-from[1]);
303         rc[2]= (lookat[2]-from[2]);
304         Kx_VecUpMat3(rc, mat, 3);       /* y up Track -z */
305         
306
307
308
309         /* now set the camera position and rotation */
310         
311         obj->NodeSetLocalPosition(from);
312         
313         actormat[0][0]= mat[0][0]; actormat[0][1]= mat[1][0]; actormat[0][2]= mat[2][0];
314         actormat[1][0]= mat[0][1]; actormat[1][1]= mat[1][1]; actormat[1][2]= mat[2][1];
315         actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2];
316         obj->NodeSetLocalOrientation(actormat);
317
318         return result;
319 }
320
321 CValue *KX_CameraActuator::findObject(char *obName) 
322 {
323         /* hook to object system */
324         return NULL;
325 }
326
327 bool KX_CameraActuator::string2axischoice(const char *axisString) 
328 {
329         bool res = true;
330
331         res = !(axisString == Y_AXIS_STRING);
332
333         return res;
334 }
335
336 /* ------------------------------------------------------------------------- */
337 /* Python functions                                                          */
338 /* ------------------------------------------------------------------------- */
339
340 /* Integration hooks ------------------------------------------------------- */
341 PyTypeObject KX_CameraActuator::Type = {
342         PyObject_HEAD_INIT(&PyType_Type)
343         0,
344         "KX_CameraActuator",
345         sizeof(KX_CameraActuator),
346         0,
347         PyDestructor,
348         0,
349         __getattr,
350         __setattr,
351         0, //&MyPyCompare,
352         __repr,
353         0, //&cvalue_as_number,
354         0,
355         0,
356         0,
357         0
358 };
359
360 PyParentObject KX_CameraActuator::Parents[] = {
361         &KX_CameraActuator::Type,
362         &SCA_IActuator::Type,
363         &SCA_ILogicBrick::Type,
364         &CValue::Type,
365         NULL
366 };
367
368 PyMethodDef KX_CameraActuator::Methods[] = {
369         {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_VARARGS,       SetObject_doc},
370         {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_NOARGS,        GetObject_doc},
371         {"setMin"       ,(PyCFunction) KX_CameraActuator::sPySetMin,    METH_VARARGS,   SetMin_doc},
372         {"getMin"       ,(PyCFunction) KX_CameraActuator::sPyGetMin,    METH_NOARGS,    GetMin_doc},
373         {"setMax"       ,(PyCFunction) KX_CameraActuator::sPySetMax,    METH_VARARGS,   SetMax_doc},
374         {"getMax"       ,(PyCFunction) KX_CameraActuator::sPyGetMax,    METH_NOARGS,    GetMax_doc},
375         {"setHeight",(PyCFunction) KX_CameraActuator::sPySetHeight,     METH_VARARGS,   SetHeight_doc},
376         {"getHeight",(PyCFunction) KX_CameraActuator::sPyGetHeight,     METH_NOARGS,    GetHeight_doc},
377         {"setXY"        ,(PyCFunction) KX_CameraActuator::sPySetXY,             METH_VARARGS,   SetXY_doc},
378         {"getXY"        ,(PyCFunction) KX_CameraActuator::sPyGetXY,     METH_VARARGS,   GetXY_doc},
379         {NULL,NULL,NULL,NULL} //Sentinel
380 };
381
382 PyObject* KX_CameraActuator::_getattr(const STR_String& attr) {
383         _getattr_up(SCA_IActuator);
384 }
385 /* get obj  ---------------------------------------------------------- */
386 char KX_CameraActuator::GetObject_doc[] = 
387 "getObject\n"
388 "\tReturns the object this sensor reacts to.\n";
389 PyObject* KX_CameraActuator::PyGetObject(PyObject* self, 
390                                                                                 PyObject* args, 
391                                                                                 PyObject* kwds)
392 {
393         return PyString_FromString(m_ob->GetName());
394 }
395 /* set obj  ---------------------------------------------------------- */
396 char KX_CameraActuator::SetObject_doc[] = 
397 "setObject\n"
398 "\tSets the object this sensor reacts to.\n";
399 PyObject* KX_CameraActuator::PySetObject(PyObject* self, 
400                                                                                 PyObject* args, 
401                                                                                 PyObject* kwds)
402 {
403     
404         PyObject* gameobj;
405         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
406         {
407                 m_ob = (CValue*)gameobj;
408                 Py_Return;
409         }
410         PyErr_Clear();
411         
412         char* objectname;
413         if (PyArg_ParseTuple(args, "s", &objectname))
414         {
415                 CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
416                 if(object)
417                 {
418                         m_ob = object;
419                         Py_Return;
420                 }
421         }
422         
423         return NULL;
424 }
425
426 /* get min  ---------------------------------------------------------- */
427 char KX_CameraActuator::GetMin_doc[] = 
428 "getMin\n"
429 "\tReturns the minimum value set in the Min: field.\n";
430 PyObject* KX_CameraActuator::PyGetMin(PyObject* self, 
431                                                                                 PyObject* args, 
432                                                                                 PyObject* kwds)
433 {
434         return PyFloat_FromDouble(m_minHeight);
435 }
436 /* set min  ---------------------------------------------------------- */
437 char KX_CameraActuator::SetMin_doc[] = 
438 "setMin\n"
439 "\tSets the minimum value.\n";
440 PyObject* KX_CameraActuator::PySetMin(PyObject* self, 
441                                                                                 PyObject* args, 
442                                                                                 PyObject* kwds)
443 {
444         float min;
445         if(PyArg_ParseTuple(args,"f", &min))
446         {
447                 m_minHeight = min;
448                 Py_Return;
449         }
450         return NULL;
451 }
452 /* get min  ---------------------------------------------------------- */
453 char KX_CameraActuator::GetMax_doc[] = 
454 "getMax\n"
455 "\tReturns the maximum value set in the Max: field.\n";
456 PyObject* KX_CameraActuator::PyGetMax(PyObject* self, 
457                                                                                 PyObject* args, 
458                                                                                 PyObject* kwds)
459 {
460         return PyFloat_FromDouble(m_maxHeight);
461 }
462 /* set min  ---------------------------------------------------------- */
463 char KX_CameraActuator::SetMax_doc[] = 
464 "setMax\n"
465 "\tSets the maximum value.\n";
466 PyObject* KX_CameraActuator::PySetMax(PyObject* self, 
467                                                                                 PyObject* args, 
468                                                                                 PyObject* kwds)
469 {
470         float max;
471         if(PyArg_ParseTuple(args,"f", &max))
472         {
473                 m_maxHeight = max;
474                 Py_Return;
475         }
476         return NULL;
477 }
478 /* get height  ---------------------------------------------------------- */
479 char KX_CameraActuator::GetHeight_doc[] = 
480 "getHeight\n"
481 "\tReturns the height value set in the height: field.\n";
482 PyObject* KX_CameraActuator::PyGetHeight(PyObject* self, 
483                                                                                 PyObject* args, 
484                                                                                 PyObject* kwds)
485 {
486         return PyFloat_FromDouble(m_height);
487 }
488 /* set height  ---------------------------------------------------------- */
489 char KX_CameraActuator::SetHeight_doc[] = 
490 "setHeight\n"
491 "\tSets the height value.\n";
492 PyObject* KX_CameraActuator::PySetHeight(PyObject* self, 
493                                                                                 PyObject* args, 
494                                                                                 PyObject* kwds)
495 {
496         float height;
497         if(PyArg_ParseTuple(args,"f", &height))
498         {
499                 m_height = height;
500                 Py_Return;
501         }
502         return NULL;
503 }
504 /* set XY  ---------------------------------------------------------- */
505 char KX_CameraActuator::SetXY_doc[] = 
506 "setXY\n"
507 "\tSets axis the camera tries to get behind.\n"
508 "\t1=x, 0=y\n";
509 PyObject* KX_CameraActuator::PySetXY(PyObject* self, 
510                                                                                 PyObject* args, 
511                                                                                 PyObject* kwds)
512 {
513         int value;
514         if(PyArg_ParseTuple(args,"i", &value))
515         {
516                 m_x = value != 0;
517                 Py_Return;
518         }
519         return NULL;
520 }
521
522 /* get XY -------------------------------------------------------------*/
523 char KX_CameraActuator::GetXY_doc[] =
524 "getXY\n"
525 "\tGets the axis the camera tries to get behind.\n"
526 "\tTrue = X, False = Y\n";
527 PyObject* KX_CameraActuator::PyGetXY(PyObject* self,
528                                                                                 PyObject* args, 
529                                                                                 PyObject* kwds)
530 {
531         return PyInt_FromLong(m_x);
532 }
533
534 /* eof */