Reverted incorrect merge (missing files)
[blender.git] / source / gameengine / Physics / Sumo / Fuzzics / sample / particle.cpp
1 //#define FAKE_IT
2 #define USE_COMPLEX
3 #define QUADS
4
5 #include <algorithm>
6 #include <new>
7 #include <GL/glut.h>
8
9 #include "MT_MinMax.h"
10 #include "MT_Point3.h"
11 #include "MT_Vector3.h"
12 #include "MT_Quaternion.h"
13 #include "MT_Matrix3x3.h"
14 #include "MT_Transform.h"
15
16 #include "SM_Object.h"
17 #include "SM_FhObject.h"
18 #include "SM_Scene.h"
19
20 #include <SOLID/SOLID.h>
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 const MT_Scalar bowl_curv = 0.10;
27 const MT_Scalar timeStep = 0.02;
28 const MT_Scalar ground_margin = 0.0;
29 const MT_Scalar sphere_radius = 0.5;
30
31 const MT_Vector3 gravity(0, -9.8, 0);
32
33 static MT_Scalar DISTANCE = 5; 
34
35 static MT_Scalar ele = 0, azi = 0;
36 static MT_Point3 eye(0, 0, DISTANCE);
37 static MT_Point3 center(0, 0, 0);
38
39 inline double irnd() { return 2 * MT_random() - 1; }  
40
41 static const double SCALE_BOTTOM = 0.5;
42 static const double SCALE_FACTOR = 2.0;
43
44 SM_ShapeProps g_shapeProps = {
45         1.0,    // mass
46         1.0,    // inertia 
47         0.1,    // linear drag
48         0.1,    // angular drag
49         { 1.0, 0.0, 0.0 }, // anisotropic friction
50         false,   // do anisotropic friction?
51         true,   // do fh?
52         true    // do rot fh?
53 };
54
55 SM_MaterialProps g_materialProps = {
56         0.7,    // restitution
57         0.0,    // friction 
58         10.0,    // Fh spring constant
59         1.0,    // Fh damping
60         0.5,    // Fh distance 
61         true    // Fh leveling 
62 };
63  
64
65 void toggleIdle();
66
67
68 void newRandom();
69
70 void coordSystem() {
71     glDisable(GL_LIGHTING);
72     glBegin(GL_LINES);
73     glColor3f(1, 0, 0);
74     glVertex3d(0, 0, 0);
75     glVertex3d(10, 0, 0);
76     glColor3f(0, 1, 0);
77     glVertex3d(0, 0, 0);
78     glVertex3d(0, 10, 0);
79     glColor3f(0, 0, 1);
80     glVertex3d(0, 0, 0);
81     glVertex3d(0, 0, 10);
82     glEnd();
83     glEnable(GL_LIGHTING);
84 }
85
86
87 void display_bbox(const MT_Point3& min, const MT_Point3& max) {
88     glDisable(GL_DEPTH_TEST);
89     glDisable(GL_LIGHTING);
90     glColor3f(0, 1, 1);
91     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
92     glBegin(GL_QUAD_STRIP);
93     glVertex3d(min[0], min[1], min[2]);
94     glVertex3d(min[0], min[1], max[2]);
95     glVertex3d(max[0], min[1], min[2]);
96     glVertex3d(max[0], min[1], max[2]);
97     glVertex3d(max[0], max[1], min[2]);
98     glVertex3d(max[0], max[1], max[2]);
99     glVertex3d(min[0], max[1], min[2]);
100     glVertex3d(min[0], max[1], max[2]);
101     glVertex3d(min[0], min[1], min[2]);
102     glVertex3d(min[0], min[1], max[2]);
103     glEnd();  
104     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
105     glEnable(GL_LIGHTING);
106     glEnable(GL_DEPTH_TEST);
107 }
108
109
110
111
112 class GLShape {
113 public:
114     virtual void paint(GLdouble *m) const = 0;
115 };
116
117
118 class GLSphere : public GLShape {
119     MT_Scalar radius;
120 public:
121     GLSphere(MT_Scalar r) : radius(r) {}
122
123     void paint(GLdouble *m) const {
124         glPushMatrix(); 
125         glLoadMatrixd(m);
126         coordSystem();
127         glutSolidSphere(radius, 20, 20);
128         glPopMatrix();
129     }
130 };
131
132
133 class GLBox : public GLShape {
134     MT_Vector3 extent;
135 public:
136     GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) : 
137         extent(x, y, z) {}
138
139     void paint(GLdouble *m) const {
140         glPushMatrix(); 
141         glLoadMatrixd(m);
142         coordSystem();
143         glPushMatrix();
144         glScaled(extent[0], extent[1], extent[2]);
145         glutSolidCube(1.0);
146         glPopMatrix();
147         glPopMatrix();
148     }
149 };
150
151
152 class GLCone : public GLShape {
153     MT_Scalar bottomRadius;
154     MT_Scalar height;
155     mutable GLuint displayList;
156
157 public:
158     GLCone(MT_Scalar r, MT_Scalar h) :  
159         bottomRadius(r), 
160         height(h), 
161         displayList(0) {}
162   
163     void paint(GLdouble *m) const { 
164         glPushMatrix(); 
165         glLoadMatrixd(m);
166         coordSystem();
167         if (displayList) glCallList(displayList); 
168         else {
169             GLUquadricObj *quadObj = gluNewQuadric();
170             displayList = glGenLists(1);
171             glNewList(displayList, GL_COMPILE_AND_EXECUTE);
172             glPushMatrix();
173             glRotatef(-90.0, 1.0, 0.0, 0.0);
174             glTranslatef(0.0, 0.0, -1.0);
175             gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
176             gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
177             gluCylinder(quadObj, bottomRadius, 0, height, 15, 10);
178             glPopMatrix();
179             glEndList();
180         }
181         glPopMatrix();
182     }
183 };
184
185 class GLCylinder : public GLShape {
186     MT_Scalar radius;
187     MT_Scalar height;
188     mutable GLuint displayList;
189
190 public:
191     GLCylinder(MT_Scalar r, MT_Scalar h) : 
192         radius(r), 
193         height(h), 
194         displayList(0) {}
195
196     void paint(GLdouble *m) const { 
197         glPushMatrix(); 
198         glLoadMatrixd(m);
199         coordSystem();
200         if (displayList) glCallList(displayList); 
201         else {
202             GLUquadricObj *quadObj = gluNewQuadric();
203             displayList = glGenLists(1);
204             glNewList(displayList, GL_COMPILE_AND_EXECUTE);
205             glPushMatrix();
206             glRotatef(-90.0, 1.0, 0.0, 0.0);
207             glTranslatef(0.0, 0.0, -1.0);
208             gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL);
209             gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH);
210             gluCylinder(quadObj, radius, radius, height, 15, 10);
211             glPopMatrix ();
212             glEndList();
213         }
214         glPopMatrix();
215     }
216 };
217
218 class Object;
219
220 class Callback : public SM_Callback {
221 public:
222         Callback(Object& object) : m_object(object) {}
223
224         virtual void do_me();
225
226 private:
227         Object& m_object;
228 };
229
230
231 class Object {
232 public:
233     Object(GLShape *gl_shape, SM_Object& object) :
234         m_gl_shape(gl_shape),
235         m_object(object),
236                 m_callback(*this)
237         {
238                         m_object.registerCallback(m_callback);
239                 }
240         
241     ~Object() {}
242
243     void paint() {
244                 if (m_gl_shape) {
245                         m_gl_shape->paint(m);
246                         //      display_bbox(m_bbox.lower(), m_bbox.upper());
247                 }
248         }
249
250         void print_reaction_force() const { 
251                 std::cout << m_object.getReactionForce() << std::endl; 
252         }
253         
254         MT_Vector3 getAhead() {
255                 return MT_Vector3(&m[4]);
256         }
257
258         MT_Vector3 getUp() {
259                 return MT_Vector3(&m[8]);
260         }
261
262     void clearMomentum() {
263                 m_object.clearMomentum();
264     }
265         
266     void setMargin(MT_Scalar margin) {
267         m_object.setMargin(margin);
268     }
269         
270     void setScaling(const MT_Vector3& scaling) {
271         m_object.setScaling(scaling); 
272     }
273
274     const MT_Point3& getPosition() {
275                 return m_object.getPosition();
276     }
277
278     void setPosition(const MT_Point3& pos) {
279                 m_object.setPosition(pos);
280     }
281
282     void setOrientation(const MT_Quaternion& orn) {
283         m_object.setOrientation(orn);
284     }
285
286     void applyCenterForce(const MT_Vector3& force) {
287                 m_object.applyCenterForce(force);
288     }
289
290     void applyTorque(const MT_Vector3& torque) {
291                 m_object.applyTorque(torque);
292     }
293
294     MT_Point3 getWorldCoord(const MT_Point3& local) const {
295         return m_object.getWorldCoord(local);
296     }
297
298     MT_Vector3 getLinearVelocity() const {
299         return m_object.getLinearVelocity();
300     }
301
302     MT_Vector3 getAngularVelocity() const {
303         return m_object.getAngularVelocity();
304     }
305
306     void setMatrix() {
307                 m_object.calcXform();
308                 m_object.getMatrix(m);
309     }
310
311     const double *getMatrix() {
312                 m_object.calcXform();
313                 return m_object.getMatrix();
314     }
315
316 private:
317     GLShape        *m_gl_shape;
318     SM_Object&      m_object;
319         DT_Scalar       m[16];
320         Callback        m_callback;
321 };
322
323
324
325 const MT_Scalar SPACE_SIZE = 2;
326
327 static GLSphere gl_sphere(sphere_radius);
328 static GLBox gl_ground(50.0, 0.0, 50.0);
329
330
331
332 #ifdef USE_COMPLEX
333
334 const int GRID_SCALE = 10;
335 const MT_Scalar GRID_UNIT  = 25.0 / GRID_SCALE;
336
337 DT_ShapeHandle createComplex() {
338     DT_ShapeHandle shape = DT_NewComplexShape();
339     for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) {
340         for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) {
341             int i1 = i0 + 1;
342             int j1 = j0 + 1;
343 #ifdef QUADS
344             DT_Begin();
345             DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0);
346             DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1);
347             DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1);
348             DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0);
349             DT_End();
350 #else
351             DT_Begin();
352             DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0);
353             DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
354             DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
355             DT_End();
356
357             DT_Begin();
358             DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1);
359             DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1);
360             DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0);
361             DT_End();
362 #endif
363
364         }
365     }
366     DT_EndComplexShape();
367     return shape;
368 }
369
370
371 static DT_ShapeHandle ground_shape = createComplex();
372
373 #else 
374
375 static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50);
376
377 #endif
378
379 static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0);
380 static Object    ground(&gl_ground, sm_ground);
381
382 static SM_Object   sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0);
383 static Object      object(&gl_sphere, sm_sphere);
384
385
386 static SM_Scene   g_scene;
387
388
389 bool g_hit = false;
390 MT_Point3 g_spot;
391 MT_Vector3 g_normal;
392
393
394 void Callback::do_me()
395 {
396         m_object.setMatrix();
397         m_object.print_reaction_force();
398 }
399
400 void myinit(void) {
401
402     GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
403     GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
404     GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
405
406     /*  light_position is NOT default value     */
407     GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 };
408     GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 };
409   
410     glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
411     glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
412     glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
413     glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
414   
415     glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
416     glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
417     glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
418     glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
419   
420
421     glEnable(GL_LIGHTING);
422     glEnable(GL_LIGHT0);
423     glEnable(GL_LIGHT1);
424   
425     glShadeModel(GL_SMOOTH);
426   
427     glEnable(GL_DEPTH_TEST);
428     glDepthFunc(GL_LESS);
429   
430     //  glEnable(GL_CULL_FACE);
431     //  glCullFace(GL_BACK);
432
433     ground.setPosition(MT_Point3(0, -10, 0));
434     ground.setOrientation(MT_Quaternion(0, 0, 0, 1));
435     ground.setMatrix();
436     center.setValue(0.0, 0.0, 0.0);
437         sm_ground.setMargin(ground_margin);
438
439         g_scene.setForceField(gravity);
440     g_scene.add(sm_ground);
441
442         object.setMargin(sphere_radius);
443         
444     g_scene.add(sm_sphere);
445
446
447     newRandom();
448 }
449
450
451 //MT_Point3 cp1, cp2;
452 //bool intersection;
453
454 void display(void) {
455     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
456
457     ground.paint();
458         object.paint();
459         
460         if (g_hit) {
461                 glDisable(GL_LIGHTING);
462                 glColor3f(1, 0, 0);
463
464                 glPointSize(5);
465                 glBegin(GL_POINTS);
466                 glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
467                 glEnd();
468                 glPointSize(1);
469
470                 glColor3f(1, 1, 0);
471         glBegin(GL_LINES); 
472                 glVertex3d(g_spot[0], g_spot[1], g_spot[2]);
473                 glVertex3d(g_spot[0] + g_normal[0], 
474                                    g_spot[1] + g_normal[1],
475                                    g_spot[2] + g_normal[2]);
476         glEnd();
477                 glEnable(GL_LIGHTING);
478         }
479
480         
481
482 #ifdef COLLISION
483     glDisable(GL_DEPTH_TEST);
484     glDisable(GL_LIGHTING);
485     glColor3f(1, 1, 0);
486     if (intersection) {
487         glPointSize(5);
488         glBegin(GL_POINTS);
489         glVertex3d(cp1[0], cp1[1], cp1[2]);
490         glEnd();
491         glPointSize(1);
492     }
493     else {
494         glBegin(GL_LINES); 
495         glVertex3d(cp1[0], cp1[1], cp1[2]);
496         glVertex3d(cp2[0], cp2[1], cp2[2]);
497         glEnd();
498     }
499     glEnable(GL_LIGHTING);
500     glEnable(GL_DEPTH_TEST);
501 #endif
502
503     glFlush();
504     glutSwapBuffers();
505 }
506
507
508
509
510
511 void newRandom() {
512         object.setPosition(MT_Point3(0, 0, 0));
513         object.setOrientation(MT_Quaternion::random());
514         object.clearMomentum();
515         object.setMatrix();
516         
517     display();
518 }
519
520 void moveAndDisplay() {
521         g_scene.proceed(timeStep, 0.01);
522
523     display();
524         g_hit = false;
525 }
526
527
528 void turn_left() {
529         object.applyTorque(5.0 * object.getUp());
530 }
531
532 void turn_right() {
533         object.applyTorque(-5.0 * object.getUp());
534 }
535
536 void forward() {
537         object.applyCenterForce(10.0 * object.getAhead());
538 }
539
540 void backward() {
541         object.applyCenterForce(-10.0 * object.getAhead());
542 }
543
544 void jump() {
545         object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0));
546 }
547
548
549 void toggleIdle() {
550     static bool idle = true;
551     if (idle) {
552         glutIdleFunc(moveAndDisplay);
553         idle = false;
554     }
555     else {
556         glutIdleFunc(NULL);
557         idle = true;
558     }
559 }
560
561
562 void setCamera() {
563     glMatrixMode(GL_PROJECTION);
564     glLoadIdentity();
565     glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0);
566     MT_Scalar rele = MT_radians(ele);
567     MT_Scalar razi = MT_radians(azi);
568     eye.setValue(DISTANCE * sin(razi) * cos(rele), 
569                  DISTANCE * sin(rele),
570                  DISTANCE * cos(razi) * cos(rele));
571     gluLookAt(eye[0], eye[1], eye[2], 
572               center[0], center[1], center[2], 
573               0, 1, 0);
574     glMatrixMode(GL_MODELVIEW);
575     display();
576 }
577
578 const MT_Scalar STEPSIZE = 5;
579
580 void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
581 void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
582 void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); }
583 void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); }
584 void zoomIn() { DISTANCE -= 1; setCamera(); }
585 void zoomOut() { DISTANCE += 1; setCamera(); }
586
587
588 void myReshape(int w, int h) {
589     glViewport(0, 0, w, h);
590     setCamera();
591 }
592
593 void myKeyboard(unsigned char key, int x, int y)
594 {
595     switch (key) 
596     {
597         case 'w': forward();    break;
598         case 's': backward();   break;
599         case 'a': turn_left();  break;
600         case 'd': turn_right(); break;
601         case 'e': jump(); break;        
602     case 'l' : stepLeft(); break;
603     case 'r' : stepRight(); break;
604     case 'f' : stepFront(); break;
605     case 'b' : stepBack(); break;
606     case 'z' : zoomIn(); break;
607     case 'x' : zoomOut(); break;
608     case 'i' : toggleIdle(); break;
609     case ' ' : newRandom(); break;
610     default:
611 //        std::cout << "unused key : " << key << std::endl;
612         break;
613     }
614 }
615
616 void mySpecial(int key, int x, int y)
617 {
618     switch (key) 
619     {
620     case GLUT_KEY_LEFT : stepLeft(); break;
621     case GLUT_KEY_RIGHT : stepRight(); break;
622     case GLUT_KEY_UP : stepFront(); break;
623     case GLUT_KEY_DOWN : stepBack(); break;
624     case GLUT_KEY_PAGE_UP : zoomIn(); break;
625     case GLUT_KEY_PAGE_DOWN : zoomOut(); break;
626     case GLUT_KEY_HOME : toggleIdle(); break;
627     default:
628 //        std::cout << "unused (special) key : " << key << std::endl;
629         break;
630     }
631 }
632
633 void goodbye( void)
634 {
635         g_scene.remove(sm_ground);
636         g_scene.remove(sm_sphere);
637
638     std::cout << "goodbye ..." << std::endl;
639     exit(0);
640 }
641
642 void menu(int choice)
643 {
644
645     static int fullScreen = 0;
646     static int px, py, sx, sy;
647  
648     switch(choice) {
649     case 1:
650         if (fullScreen == 1) {
651             glutPositionWindow(px,py);
652             glutReshapeWindow(sx,sy);
653             glutChangeToMenuEntry(1,"Full Screen",1);
654             fullScreen = 0;
655         } else {
656             px=glutGet((GLenum)GLUT_WINDOW_X);
657             py=glutGet((GLenum)GLUT_WINDOW_Y);
658             sx=glutGet((GLenum)GLUT_WINDOW_WIDTH);
659             sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT);
660             glutFullScreen();
661             glutChangeToMenuEntry(1,"Close Full Screen",1);
662             fullScreen = 1;
663         }
664         break;
665     case 2:
666         toggleIdle();
667         break;
668     case 3:
669         goodbye();
670         break;
671     default:
672         break;
673     }
674 }
675
676 void createMenu()
677 {
678     glutCreateMenu(menu);
679     glutAddMenuEntry("Full Screen", 1);
680     glutAddMenuEntry("Toggle Idle (Start/Stop)", 2);
681     glutAddMenuEntry("Quit", 3);
682     glutAttachMenu(GLUT_RIGHT_BUTTON);
683 }
684
685 int main(int argc, char **argv) {
686     glutInit(&argc, argv);
687     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
688     glutInitWindowPosition(0, 0);
689     glutInitWindowSize(500, 500);
690     glutCreateWindow("Physics demo");
691
692     myinit();
693     glutKeyboardFunc(myKeyboard);
694     glutSpecialFunc(mySpecial);
695     glutReshapeFunc(myReshape);
696     createMenu();
697     glutIdleFunc(NULL);
698
699     glutDisplayFunc(display);
700     glutMainLoop();
701     return 0;
702 }
703
704
705
706
707
708
709