Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / glui / glui_rotation.cpp
1 /****************************************************************************
2   
3   GLUI User Interface Toolkit
4   ---------------------------
5
6      glui_rotation - GLUI_Rotation control class
7
8
9           --------------------------------------------------
10
11   Copyright (c) 1998 Paul Rademacher
12
13   WWW:    http://sourceforge.net/projects/glui/
14   Forums: http://sourceforge.net/forum/?group_id=92496
15
16   This library is free software; you can redistribute it and/or
17   modify it under the terms of the GNU Lesser General Public
18   License as published by the Free Software Foundation; either
19   version 2.1 of the License, or (at your option) any later version.
20
21   This library is distributed in the hope that it will be useful,
22   but WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   Lesser General Public License for more details.
25
26   You should have received a copy of the GNU Lesser General Public
27   License along with this library; if not, write to the Free Software
28   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
30 *****************************************************************************/
31
32 #include "GL/glui.h"
33 #include "arcball.h"
34 #include "algebra3.h"
35
36 /*************************** GLUI_Rotation::iaction_mouse_down_handler() ***/
37
38 int    GLUI_Rotation::iaction_mouse_down_handler( int local_x, int local_y )
39 {
40   copy_float_array_to_ball();
41
42   init_ball();
43
44   local_y = (int) floor(2.0 * ball->center[1] - local_y);
45
46   ball->mouse_down( local_x, local_y );
47
48   /*    printf( "%d %d - %f %f\n", local_x, local_y, ball->center[0], ball->center[1] );              */
49
50   copy_ball_to_float_array();
51
52   spinning = false;
53
54   return false;
55 }
56
57
58 /*********************** GLUI_Rotation::iaction_mouse_up_handler() **********/
59
60 int    GLUI_Rotation::iaction_mouse_up_handler( int local_x, int local_y, 
61                                                 bool inside )
62 {
63   copy_float_array_to_ball();
64
65   ball->mouse_up();
66
67   return false;
68 }
69
70
71 /******************* GLUI_Rotation::iaction_mouse_held_down_handler() ******/
72
73 int    GLUI_Rotation::iaction_mouse_held_down_handler( int local_x, int local_y,
74                                                        bool inside)
75 {  
76   if ( NOT glui )
77     return 0;
78
79   copy_float_array_to_ball();
80
81   local_y = (int) floor(2.0 * ball->center[1] - local_y);
82
83   /*    printf( "%d %d\n", local_x, local_y );              */
84
85   ball->mouse_motion( local_x, local_y, 0, 
86                      (glui->curr_modifiers & GLUT_ACTIVE_ALT) != 0, 
87                      (glui->curr_modifiers & GLUT_ACTIVE_CTRL) != 0 );
88  
89   copy_ball_to_float_array();
90
91   if ( can_spin )
92     spinning = true;
93
94   return false;
95 }
96
97
98 /******************** GLUI_Rotation::iaction_draw_active_area_persp() **************/
99
100 void    GLUI_Rotation::iaction_draw_active_area_persp( void )
101 {
102   /********** arcball *******/
103   copy_float_array_to_ball();
104
105   setup_texture();
106   setup_lights();
107         
108   glEnable(GL_CULL_FACE );
109
110   glMatrixMode( GL_MODELVIEW );
111   glPushMatrix();
112
113   mat4 tmp_rot = *ball->rot_ptr;
114   glMultMatrixf( (float*) &tmp_rot[0][0] ); 
115
116   /*** Draw the checkered box ***/
117   /*glDisable( GL_TEXTURE_2D );              */
118   draw_ball(1.35); // 1.96 );
119
120   glPopMatrix();
121
122   glBindTexture(GL_TEXTURE_2D,0); /* unhook our checkerboard texture */
123   glDisable( GL_TEXTURE_2D );
124   glDisable( GL_LIGHTING );
125   glDisable( GL_CULL_FACE );
126 }
127
128
129 /******************** GLUI_Rotation::iaction_draw_active_area_ortho() **********/
130
131 void    GLUI_Rotation::iaction_draw_active_area_ortho( void )
132 {
133   float radius;
134   radius = (float)(h-22)/2.0;  /*MIN((float)w/2.0, (float)h/2.0);  */
135
136   /********* Draw emboss circles around arcball control *********/
137   int k;     
138   glLineWidth( 1.0 );
139   glBegin( GL_LINE_LOOP);
140   for( k=0; k<60; k++ ) {
141     float phi = 2*M_PI*(float)k/60.0;
142     vec2 p( cos(phi) * (2.0 + radius), sin(phi) * (2.0 + radius));
143     if ( p[1] < -p[0] )                         glColor3ub( 128,128,128 );
144     else                                        glColor3ub( 255,255,255 );
145     glVertex2fv((float*)&p[0]);
146   }
147   glEnd();
148
149   glBegin( GL_LINE_LOOP);
150   for( k=0; k<60; k++ ) {
151     float phi = 2*M_PI*(float)k/60.0;
152     vec2 p( cos(phi) * (1.0 + radius), sin(phi) * (1.0 + radius));
153     if ( enabled ) {
154       if ( p[1] < -p[0] )                       glColor3ub( 0,0,0);
155       else                                      glColor3ub( 192,192,192);
156     }
157     else
158     {
159       if ( p[1] < -p[0] )                       glColor3ub( 180,180,180);
160       else                                      glColor3ub( 192,192,192);
161     }
162     glVertex2fv((float*)&p[0]);
163   }
164   glEnd();
165 }
166
167
168 /******************************** GLUI_Rotation::iaction_dump() **********/
169
170 void     GLUI_Rotation::iaction_dump( FILE *output )
171 {
172 }
173
174
175 /******************** GLUI_Rotation::iaction_special_handler() **********/
176
177 int    GLUI_Rotation::iaction_special_handler( int key,int modifiers )
178 {
179
180   return false;
181 }
182
183 /********************************** GLUI_Rotation::init_ball() **********/
184
185 void  GLUI_Rotation::init_ball( void )
186 {
187   /*printf( "%f %f %f", float( MIN(w/2,h/2)), (float) w/2, (float) h/2 );              */
188
189   ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)), 
190                    (float) 2.0*(h-18) );
191   /*ball->set_damping( .05 );              */
192   /*float( MIN(w/2,h/2))*2.0  );              */
193   /*    ball->reset_mouse();              */
194 }
195
196
197 /****************************** GLUI_Rotation::setup_texture() *********/
198
199 void GLUI_Rotation::setup_texture( void )
200 {
201   static GLuint tex=0u;
202   GLenum t=GL_TEXTURE_2D;
203   glEnable(t);
204   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
205   glColor3f( 1.0, 1.0, 1.0 );
206   if (tex!=0u) {
207   /* (OSL 2006/06) Just use glBindTexture to avoid having to re-upload the whole checkerboard every frame. */
208     glBindTexture(t,tex);
209     return;
210   } /* Else need to make a new checkerboard texture */
211   glGenTextures(1,&tex);
212   glBindTexture(t,tex);
213   glEnable(t);
214   
215   unsigned int i, j;
216   int dark, light;   /*** Dark and light colors for ball checkerboard  ***/
217
218 /* Note: you can change the number of checkers across there sphere in draw_ball */
219 #define CHECKBOARD_SIZE 64 /* pixels across whole texture */
220 #define CHECKBOARD_REPEAT 32u /* pixels across one black/white sector */
221   unsigned char texture_image[CHECKBOARD_SIZE] [CHECKBOARD_SIZE] [3];
222   unsigned char c;
223   for( i=0; i<CHECKBOARD_SIZE; i++ ) 
224   {
225     for( j=0; j<CHECKBOARD_SIZE; j++ ) 
226     {
227       dark = 110;
228       light = 220;
229
230       if ((((i/CHECKBOARD_REPEAT)&0x1)==0) ^ (((j/CHECKBOARD_REPEAT)&0x1)==0))
231         c = light;
232       else
233         c = dark;
234
235       texture_image[i][j][0] = c;
236       texture_image[i][j][1] = c;
237       texture_image[i][j][2] = c;
238     }    
239   }
240   
241   glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
242   glTexParameteri( t, GL_TEXTURE_WRAP_S, GL_REPEAT );
243   glTexParameteri( t, GL_TEXTURE_WRAP_T, GL_REPEAT );
244   glTexParameteri( t, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
245   glTexParameteri( t, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
246   gluBuild2DMipmaps(t, GL_RGB, CHECKBOARD_SIZE, CHECKBOARD_SIZE,
247         GL_RGB, GL_UNSIGNED_BYTE, texture_image);
248
249 /* Add some mipmapping LOD bias, to keep sphere texture sharp */
250   float bias=-0.5; 
251   /* glTexEnvf(TEXTURE_FILTER_CONTROL_EXT,TEXTURE_LOD_BIAS_EXT,bias); */
252   /* glTexParameteri( t, GL_TEXTURE_MAX_LEVEL,1);*/
253   glTexEnvf(0x8500,0x8501,bias); /* <- numeric version for older OpenGL headers */
254   /* Cap out the mipmap level, to prevent blurring on horizon */
255   glTexParameteri(t, 0x813D, 1);
256   if (glGetError()) {
257         /* Ignore errors in setting funky texture state-- go with defaults.
258           If somebody knows how to check OpenGL 1.2 before doing this, please do!
259         */
260   }
261 }
262
263 /****************************** GLUI_Rotation::setup_lights() ***********/
264
265 void    GLUI_Rotation::setup_lights( void )
266 {
267   glEnable( GL_LIGHTING );
268   /*  if ( enabled ) 
269       glEnable( GL_LIGHTING );
270       else
271       glDisable( GL_LIGHTING );*/
272   glEnable(GL_LIGHT0);
273   glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE );
274   glEnable(GL_COLOR_MATERIAL);
275   GLfloat light0_position[] = {-1.f, 1.f, 1.0f, 0.0f};
276   glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
277   if (enabled) { /* enabled colors */
278         GLfloat light0_ambient[] =  {0.2f, 0.2f, 0.2f, 1.0f};
279         GLfloat light0_diffuse[] =  {1.f, 1.f, 1.0f, 1.0f};
280         glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
281         glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
282   }
283   else { /* disabled colors */
284         GLfloat light0_ambient[] =  {0.6f, 0.6f, 0.6f, 1.0f};
285         GLfloat light0_diffuse[] =  {0.2f, 0.2f, 0.2f, 1.0f};
286         glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
287         glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
288   }
289   
290 }
291
292
293 /****************************** GLUI_Rotation::draw_ball() **************/
294
295 void    GLUI_Rotation::draw_ball( float radius )
296 {
297   if ( NOT can_draw() )
298     return;
299
300   if (quadObj == NULL)  quadObj = gluNewQuadric();
301   if (quadObj) {
302     gluQuadricDrawStyle(quadObj, GLU_FILL);
303     gluQuadricNormals(quadObj, GLU_SMOOTH);
304     gluQuadricTexture(quadObj, true );
305     glMatrixMode(GL_TEXTURE);
306     glLoadIdentity();
307     double checkerTiles=2.0; /* black-white checker tiles across whole sphere */
308     glScalef(checkerTiles,checkerTiles,1.0);
309     gluSphere(quadObj, radius, 32, 16);
310     glLoadIdentity();
311     glMatrixMode(GL_MODELVIEW);
312   }
313 }
314
315
316 /****************************** GLUI_Rotation::reset() **********/
317
318 void  GLUI_Rotation::reset( void )
319 {
320   ball->init(); /** reset quaternion, etc. **/
321   ball->set_params( vec2( (float)(w/2), (float)((h-18)/2)), 
322                    (float) 2.0*(h-18) );
323
324   set_spin( this->damping );    
325
326   copy_ball_to_float_array();
327
328   translate_and_draw_front();
329
330   output_live(true); /*** Output live and draw main grx window ***/
331 }
332
333
334 /****************************** GLUI_Rotation::needs_idle() *********/
335
336 bool GLUI_Rotation::needs_idle( void ) const
337 {
338   return can_spin;
339 }
340
341
342 /****************************** GLUI_Rotation::idle() ***************/
343
344 void        GLUI_Rotation::idle( void )
345 {
346   spinning = ball->is_spinning?true:false;
347
348   if ( can_spin AND spinning ) {
349     copy_float_array_to_ball();
350     ball->idle();
351
352     *ball->rot_ptr = *ball->rot_ptr * ball->rot_increment;
353
354     mat4 tmp_rot;
355     tmp_rot = *ball->rot_ptr;
356
357     copy_ball_to_float_array();
358
359     draw_active_area_only = true;
360     translate_and_draw_front();
361     draw_active_area_only = false;
362
363     output_live(true); /** output live and update gfx **/
364   }
365   else { 
366   }
367 }
368
369
370 /********************** GLUI_Rotation::copy_float_array_to_ball() *********/
371
372 void     GLUI_Rotation::copy_float_array_to_ball( void )
373 {
374   int i;
375   float *fp_src, *fp_dst;
376
377   fp_src = &float_array_val[0];
378   fp_dst = &((*ball->rot_ptr)[0][0]);
379
380   for( i=0; i<16; i++ ) {
381     *fp_dst = *fp_src;
382
383     fp_src++;
384     fp_dst++;
385   }
386 }
387
388
389 /********************** GLUI_Rotation::copy_ball_to_float_array() *********/
390
391 void     GLUI_Rotation::copy_ball_to_float_array( void )
392 {
393   mat4 tmp_rot;
394   tmp_rot = *ball->rot_ptr;
395
396   set_float_array_val( (float*) &tmp_rot[0][0] );
397 }
398
399
400 /************************ GLUI_Rotation::set_spin() **********************/
401
402 void   GLUI_Rotation::set_spin( float damp_factor )
403 {
404   if ( damp_factor == 0.0 ) 
405     can_spin = false;
406   else
407     can_spin = true;
408
409   ball->set_damping( 1.0 - damp_factor );
410
411   this->damping = damp_factor;
412 }
413
414
415 /************** GLUI_Rotation::GLUI_Rotation() ********************/
416
417 GLUI_Rotation::GLUI_Rotation( GLUI_Node *parent,
418                               const char *name, float *value_ptr,
419                               int id, 
420                               GLUI_CB cb )
421 {
422   common_init();
423   set_ptr_val( value_ptr );
424   user_id    = id;
425   set_name( name );
426   callback    = cb;
427   parent->add_control( this );
428   init_live();
429   
430   /*** Init the live 4x4 matrix.  This is different than the standard
431        live variable behavior, since the original value of the 4x4 matrix
432        is ignored and reset to Identity  ***/
433 /*
434 NO! WVB
435     if ( value_ptr != NULL ) {
436       int i, j, index;
437       for( i=0; i<4; i++ ) {
438         for( j=0; j<4; j++ ) {
439           index = i*4+j;
440           if ( i==j )
441             value_ptr[index] = 1.0;
442           else
443             value_ptr[index] = 0.0;
444         }
445       }
446     }
447 */
448     /*init_ball();              */
449                 
450
451 }
452
453
454 /************** GLUI_Rotation::common_init() ********************/
455
456 void GLUI_Rotation::common_init( void ) 
457 {
458   glui_format_str( name, "Rotation: %p", this );
459 //  type                = GLUI_CONTROL_ROTATION;
460   w                   = GLUI_ROTATION_WIDTH;
461   h                   = GLUI_ROTATION_HEIGHT;
462   can_activate        = true;
463   live_type           = GLUI_LIVE_FLOAT_ARRAY;
464   float_array_size    = 16;
465   quadObj             = NULL;
466   alignment           = GLUI_ALIGN_CENTER;
467   can_spin            = false;
468   spinning            = false;
469   damping             = 0.0;
470   ball                = new Arcball;
471
472   reset();
473 }