~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to extern/eltopo/common/gluvi.cpp

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
#include <cmath>
3
 
#include <cstdarg>
4
 
#include <cstdlib>
5
 
#include <fstream>
6
 
#include <gluvi.h>
7
 
#include <limits>
8
 
#include <vec.h>
9
 
 
10
 
#ifdef __APPLE__
11
 
#include <OpenGL/OpenGL.h>
12
 
#else
13
 
#include <GL/gl.h>
14
 
#include <GL/glu.h>
15
 
#include <GL/glut.h>
16
 
#include <GL/glext.h>
17
 
#endif
18
 
 
19
 
#ifndef M_PI
20
 
#define M_PI 3.14159265358979323846f
21
 
#endif
22
 
 
23
 
using namespace std;
24
 
 
25
 
namespace Gluvi{
26
 
    
27
 
    bool taking_screenshot = false;
28
 
    GLuint screenshot_fbo;
29
 
    
30
 
    
31
 
    Target3D::
32
 
    Target3D(float target_[3], float dist_, float heading_, float pitch_, float fovy_, float near_clip_factor_, float far_clip_factor_)
33
 
    : dist(dist_), heading(heading_), pitch(pitch_),
34
 
    default_dist(dist_), default_heading(heading_), default_pitch(pitch_),
35
 
    fovy(fovy_), 
36
 
    near_clip_factor(near_clip_factor_), far_clip_factor(far_clip_factor_),
37
 
    action_mode(INACTIVE),
38
 
    oldmousex(0), oldmousey(0)
39
 
    {
40
 
        if(target_){
41
 
            target[0]=target_[0];
42
 
            target[1]=target_[1];
43
 
            target[2]=target_[2];
44
 
        }else{
45
 
            target[0]=0;
46
 
            target[1]=0;
47
 
            target[2]=0;
48
 
        }
49
 
        default_target[0]=target[0];
50
 
        default_target[1]=target[1];
51
 
        default_target[2]=target[2];
52
 
    }
53
 
    
54
 
    void Target3D::
55
 
    click(int button, int state, int x, int y)
56
 
    {
57
 
        if(state==GLUT_UP)
58
 
            action_mode=INACTIVE;
59
 
        else if(button==GLUT_LEFT_BUTTON)
60
 
            action_mode=ROTATE;
61
 
        else if(button==GLUT_MIDDLE_BUTTON)
62
 
            action_mode=TRUCK;
63
 
        else if(button==GLUT_RIGHT_BUTTON)
64
 
            action_mode=DOLLY;
65
 
        oldmousex=x;
66
 
        oldmousey=y;
67
 
    }
68
 
    
69
 
    void Target3D::
70
 
    drag(int x, int y)
71
 
    {
72
 
        switch(action_mode){
73
 
            case INACTIVE:
74
 
                return; // nothing to do
75
 
            case ROTATE:
76
 
                heading+=0.007f*(oldmousex-x);
77
 
                if(heading<-M_PI) heading+=2.0f*(float)M_PI;
78
 
                else if(heading>M_PI) heading-=2.0f*(float)M_PI;
79
 
                pitch+=0.007f*(oldmousey-y);
80
 
                if(pitch<-0.5*M_PI) pitch=-0.5f*(float)M_PI;
81
 
                else if(pitch>0.5*M_PI) pitch=0.5f*(float)M_PI;
82
 
                break;
83
 
            case TRUCK:
84
 
                target[0]+=(0.002f*dist)*cos(heading)*(oldmousex-x);
85
 
                target[1]-=(0.002f*dist)*(oldmousey-y);
86
 
                target[2]-=(0.002f*dist)*sin(heading)*(oldmousex-x);
87
 
                break;
88
 
            case DOLLY:
89
 
                dist*=pow(1.01f, oldmousey-y + x-oldmousex);
90
 
                break;
91
 
        }
92
 
        oldmousex=x;
93
 
        oldmousey=y;
94
 
        glutPostRedisplay();
95
 
    }
96
 
    
97
 
    void Target3D::
98
 
    return_to_default(void)
99
 
    {
100
 
        target[0]=default_target[0];
101
 
        target[1]=default_target[1];
102
 
        target[2]=default_target[2];
103
 
        dist=default_dist;
104
 
        heading=default_heading;
105
 
        pitch=default_pitch;
106
 
    }
107
 
    
108
 
    void Target3D::
109
 
    transform_mouse(int x, int y, float ray_origin[3], float ray_direction[3])
110
 
    {
111
 
        float ch=cos(heading), sh=sin(heading);
112
 
        float cp=cos(pitch), sp=sin(pitch);
113
 
        
114
 
        ray_origin[0]=target[0]+dist*sh*cp;
115
 
        ray_origin[1]=target[1]-dist*sp;
116
 
        ray_origin[2]=target[2]+dist*ch*cp;
117
 
        
118
 
        float scale=0.5f*tan(fovy)/winheight;
119
 
        float camx=(x-0.5f*winwidth)*scale, camy=(0.5f*winheight-y)*scale, camz=-1.0f; // in camera coordinates, this is ray_direction (but not normalized)
120
 
        // now need to rotate into world space from camera space
121
 
        float px=camx, py=camy*cp-camz*sp, pz=camy*sp+camz*cp;
122
 
        ray_direction[0]=px*ch+pz*sh;
123
 
        ray_direction[1]=py;
124
 
        ray_direction[2]=-px*sh+pz*ch;
125
 
        
126
 
        //@@@ is this right to get us to the near clipping plane?
127
 
        ray_origin[0]+=near_clip_factor*dist*ray_direction[0];
128
 
        ray_origin[1]+=near_clip_factor*dist*ray_direction[1];
129
 
        ray_origin[2]+=near_clip_factor*dist*ray_direction[2];
130
 
        
131
 
        // normalize direction vector
132
 
        float mag=sqrt(ray_direction[0]*ray_direction[0]
133
 
                       + ray_direction[1]*ray_direction[1]
134
 
                       + ray_direction[2]*ray_direction[2]);
135
 
        ray_direction[0]/=mag;
136
 
        ray_direction[1]/=mag;
137
 
        ray_direction[2]/=mag;
138
 
    }
139
 
    
140
 
    void Target3D::
141
 
    get_viewing_direction(float direction[3])
142
 
    {
143
 
        float ch=cos(heading), sh=sin(heading);
144
 
        float cp=cos(pitch), sp=sin(pitch);
145
 
        direction[0]=-sh*cp;
146
 
        direction[1]=sp;
147
 
        direction[2]=-ch*cp;
148
 
    }
149
 
    
150
 
    void Target3D::get_up_vector(float up[3])
151
 
    {
152
 
        // Rotate the y-coordinate vector about the x-axis by pitch, then the y-axis by heading
153
 
        // up = R_y(h) * R_x(p) * <0,1,0>
154
 
        
155
 
        float ch=cos(heading), sh=sin(heading);
156
 
        float cp=cos(pitch), sp=sin(pitch);
157
 
        up[0] = sh*sp;
158
 
        up[1] = cp;
159
 
        up[2] = ch*sp;   
160
 
    }
161
 
    
162
 
    void Target3D::
163
 
    gl_transform(void)
164
 
    {
165
 
        glViewport(0, 0, (GLsizei)winwidth, (GLsizei)winheight);
166
 
        
167
 
        glMatrixMode(GL_PROJECTION);
168
 
        glLoadIdentity();
169
 
        //gluPerspective(fovy, winwidth/(float)winheight, near_clip_factor*dist, far_clip_factor*dist);
170
 
        
171
 
        gluPerspective(fovy, winwidth/(float)winheight, near_clip_factor, far_clip_factor);
172
 
        
173
 
        glMatrixMode(GL_MODELVIEW);
174
 
        glLoadIdentity();
175
 
        //   GLfloat pos[3];
176
 
        //   pos[0]=target[0]-dist*sin(heading)*cos(pitch);
177
 
        //   pos[1]=target[1]-dist*sin(pitch);
178
 
        //   pos[2]=target[2]-dist*cos(heading)*cos(pitch);
179
 
        glTranslatef(0, 0, -dist); // translate target dist away in the z direction
180
 
        glRotatef(-180.0f/(float)M_PI*pitch, 1.0f, 0.0f, 0.0f); // rotate pitch in the yz plane
181
 
        glRotatef(-180.0f/(float)M_PI*heading, 0.0f, 1.0f, 0.0f); // rotate heading in the xz plane
182
 
        glTranslatef(-target[0], -target[1], -target[2]); // translate target to origin
183
 
    }
184
 
    
185
 
    void Target3D::
186
 
    export_rib(ostream &output)
187
 
    {
188
 
        output<<"Clipping "<<near_clip_factor*dist<<" "<<far_clip_factor*dist<<endl; // could be more generous here!
189
 
        output<<"Projection \"perspective\" \"fov\" "<<fovy<<endl;
190
 
        output<<"ReverseOrientation"<<endl;  // RenderMan has a different handedness from OpenGL's default
191
 
        output<<"Scale 1 1 -1"<<endl;        // so we need to correct for that here
192
 
        output<<"Translate 0 0 "<<-dist<<endl;
193
 
        output<<"Rotate "<<-180/M_PI*pitch<<" 1 0 0"<<endl;
194
 
        output<<"Rotate "<<-180/M_PI*heading<<" 0 1 0"<<endl;
195
 
        output<<"Translate "<<-target[0]<<" "<<-target[1]<<" "<<-target[2]<<endl;
196
 
    }
197
 
    
198
 
    //=================================================================================
199
 
    
200
 
    TargetOrtho3D::
201
 
    TargetOrtho3D(float target_[3], float dist_, float heading_, float pitch_, float height_factor_, float near_clip_factor_, float far_clip_factor_)
202
 
    : dist(dist_), heading(heading_), pitch(pitch_),
203
 
    default_dist(dist_), default_heading(heading_), default_pitch(pitch_),
204
 
    height_factor(height_factor_),
205
 
    near_clip_factor(near_clip_factor_), far_clip_factor(far_clip_factor_), action_mode(INACTIVE),   
206
 
    oldmousex(0), oldmousey(0)
207
 
    {
208
 
        if(target_){
209
 
            target[0]=target_[0];
210
 
            target[1]=target_[1];
211
 
            target[2]=target_[2];
212
 
        }else{
213
 
            target[0]=0;
214
 
            target[1]=0;
215
 
            target[2]=0;
216
 
        }
217
 
        default_target[0]=target[0];
218
 
        default_target[1]=target[1];
219
 
        default_target[2]=target[2];
220
 
        default_dist=dist;
221
 
        default_heading=heading;
222
 
        default_pitch=pitch;
223
 
    }
224
 
    
225
 
    void TargetOrtho3D::
226
 
    click(int button, int state, int x, int y)
227
 
    {
228
 
        if(state==GLUT_UP)
229
 
            action_mode=INACTIVE;
230
 
        else if(button==GLUT_LEFT_BUTTON)
231
 
            action_mode=ROTATE;
232
 
        else if(button==GLUT_MIDDLE_BUTTON)
233
 
            action_mode=TRUCK;
234
 
        else if(button==GLUT_RIGHT_BUTTON)
235
 
            action_mode=DOLLY;
236
 
        oldmousex=x;
237
 
        oldmousey=y;
238
 
    }
239
 
    
240
 
    void TargetOrtho3D::
241
 
    drag(int x, int y)
242
 
    {
243
 
        switch(action_mode){
244
 
            case INACTIVE:
245
 
                return; // nothing to do
246
 
            case ROTATE:
247
 
                heading+=0.007f*(oldmousex-x);
248
 
                if(heading<-M_PI) heading+=2.0f*(float)M_PI;
249
 
                else if(heading>M_PI) heading-=2.0f*(float)M_PI;
250
 
                pitch+=0.007f*(oldmousey-y);
251
 
                if(pitch<-0.5f*(float)M_PI) pitch=-0.5f*(float)M_PI;
252
 
                else if(pitch>0.5f*(float)M_PI) pitch=0.5f*(float)M_PI;
253
 
                break;
254
 
            case TRUCK:
255
 
                target[0]+=(0.002f*dist)*cos(heading)*(oldmousex-x);
256
 
                target[1]-=(0.002f*dist)*(oldmousey-y);
257
 
                target[2]-=(0.002f*dist)*sin(heading)*(oldmousex-x);
258
 
                break;
259
 
            case DOLLY:
260
 
                dist*=pow(1.01f, oldmousey-y + x-oldmousex);
261
 
                break;
262
 
        }
263
 
        oldmousex=x;
264
 
        oldmousey=y;
265
 
        glutPostRedisplay();
266
 
    }
267
 
    
268
 
    void TargetOrtho3D::
269
 
    return_to_default(void)
270
 
    {
271
 
        target[0]=default_target[0];
272
 
        target[1]=default_target[1];
273
 
        target[2]=default_target[2];
274
 
        dist=default_dist;
275
 
        heading=default_heading;
276
 
        pitch=default_pitch;
277
 
    }
278
 
    
279
 
    void TargetOrtho3D::
280
 
    transform_mouse(int, int, float* /*ray_origin[3]*/, float* /*ray_direction[3]*/ )
281
 
    {
282
 
        // @@@ unimplemented
283
 
    }
284
 
    
285
 
    void TargetOrtho3D::
286
 
    get_viewing_direction(float direction[3])
287
 
    {
288
 
        float ch=cos(heading), sh=sin(heading);
289
 
        float cp=cos(pitch), sp=sin(pitch);
290
 
        direction[0]=-sh*cp;
291
 
        direction[1]=sp;
292
 
        direction[2]=-ch*cp;
293
 
    }
294
 
    
295
 
    void TargetOrtho3D::
296
 
    gl_transform(void)
297
 
    {
298
 
        glViewport(0, 0, (GLsizei)winwidth, (GLsizei)winheight);
299
 
        
300
 
        glMatrixMode(GL_PROJECTION);
301
 
        glLoadIdentity();
302
 
        float halfheight=0.5f*height_factor*dist, halfwidth=halfheight*winwidth/(float)winheight;
303
 
        glOrtho(-halfwidth, halfwidth, -halfheight, halfheight, near_clip_factor*dist, far_clip_factor*dist);
304
 
        
305
 
        glMatrixMode(GL_MODELVIEW);
306
 
        glLoadIdentity();
307
 
        glTranslatef(0, 0, -dist); // translate target dist away in the z direction
308
 
        glRotatef(-180.0f/(float)M_PI*pitch, 1.0f, 0.0f, 0.0f); // rotate pitch in the yz plane
309
 
        glRotatef(-180.0f/(float)M_PI*heading, 0.0f, 1.0f, 0.0f); // rotate heading in the xz plane
310
 
        glTranslatef(-target[0], -target[1], -target[2]); // translate target to origin
311
 
    }
312
 
    
313
 
    void TargetOrtho3D::
314
 
    export_rib(ostream &output)
315
 
    {
316
 
        output<<"Clipping "<<near_clip_factor*dist<<" "<<far_clip_factor*dist<<endl; // could be more generous here!
317
 
        output<<"Projection \"orthographic\""<<endl;
318
 
        //@@@ incomplete: need a scaling according to height_factor*dist somewhere in here
319
 
        output<<"ReverseOrientation"<<endl;  // RenderMan has a different handedness from OpenGL's default
320
 
        output<<"Scale 1 1 -1"<<endl;        // so we need to correct for that here
321
 
        output<<"Translate 0 0 "<<-dist<<endl;
322
 
        output<<"Rotate "<<-180/M_PI*pitch<<" 1 0 0"<<endl;
323
 
        output<<"Rotate "<<-180/M_PI*heading<<" 0 1 0"<<endl;
324
 
        output<<"Translate "<<-target[0]<<" "<<-target[1]<<" "<<-target[2]<<endl;
325
 
    }
326
 
    
327
 
    //=================================================================================
328
 
    
329
 
    PanZoom2D::
330
 
    PanZoom2D(float bottom_, float left_, float height_)
331
 
    : bottom(bottom_), left(left_), height(height_), 
332
 
    default_bottom(bottom_), default_left(left_), default_height(height_), action_mode(INACTIVE),
333
 
    oldmousex(0), oldmousey(0), moved_since_mouse_down(false),
334
 
    clickx(~0), clicky(~0)
335
 
    {}
336
 
    
337
 
    void PanZoom2D::
338
 
    click(int button, int state, int x, int y)
339
 
    {
340
 
        if(state==GLUT_UP){
341
 
            float r=height/winheight;
342
 
            switch(action_mode){
343
 
                case PAN:
344
 
                    if(!moved_since_mouse_down){
345
 
                        // make mouse click the centre of the window
346
 
                        left+=r*(x-0.5f*winwidth);
347
 
                        bottom+=r*(0.5f*winheight-y);
348
 
                        glutPostRedisplay();
349
 
                    }
350
 
                    break;
351
 
                case ZOOM_IN:
352
 
                    if(moved_since_mouse_down){
353
 
                        // zoom in to selection
354
 
                        float desired_width=fabs((x-clickx)*height/winheight);
355
 
                        float desired_height=fabs((y-clicky)*height/winheight);
356
 
                        if(desired_height==0) desired_height=height/winheight;
357
 
                        if(desired_width*winheight > desired_height*winwidth)
358
 
                            desired_height=winheight*desired_width/winwidth;
359
 
                        else
360
 
                            desired_width=winwidth*desired_height/winheight;
361
 
                        left+=0.5f*(x+clickx)*height/winheight-0.5f*desired_width;
362
 
                        bottom+=(winheight-0.5f*(y+clicky))*height/winheight-0.5f*desired_height;
363
 
                        height=desired_height;
364
 
                        
365
 
                    }else{
366
 
                        // zoom in by some constant factor on the mouse click
367
 
                        float factor=0.70710678118654752440084f;
368
 
                        left+=(1-factor)*height*(x/(float)winheight);
369
 
                        bottom+=(1-factor)*height*(1-y/(float)winheight);
370
 
                        height*=factor;
371
 
                    }
372
 
                    glutPostRedisplay();
373
 
                    break;
374
 
                case ZOOM_OUT:
375
 
                    // zoom out by some constant factor
376
 
                {
377
 
                    float factor=1.41421356237309504880168f;
378
 
                    left-=0.5f*(factor-1)*height;
379
 
                    bottom-=0.5f*(factor-1)*winwidth*height/winheight;
380
 
                    height*=factor;
381
 
                }
382
 
                    glutPostRedisplay();
383
 
                    break;
384
 
                default:
385
 
                    ;// nothing to do
386
 
            }
387
 
            action_mode=INACTIVE;
388
 
            
389
 
        }else if(button==GLUT_LEFT_BUTTON)
390
 
        {
391
 
            action_mode=PAN;
392
 
        }
393
 
        else if(button==GLUT_MIDDLE_BUTTON){
394
 
            clickx=x;
395
 
            clicky=y;
396
 
            action_mode=ZOOM_IN;
397
 
        }else if(button==GLUT_RIGHT_BUTTON)
398
 
            action_mode=ZOOM_OUT;
399
 
        moved_since_mouse_down=false;
400
 
        oldmousex=x;
401
 
        oldmousey=y;
402
 
    }
403
 
    
404
 
    void PanZoom2D::
405
 
    drag(int x, int y)
406
 
    {
407
 
        if(x!=oldmousex || y!=oldmousey){
408
 
            moved_since_mouse_down=true;
409
 
            if(action_mode==PAN){
410
 
                float r=height/winheight;
411
 
                left-=r*(x-oldmousex);
412
 
                bottom+=r*(y-oldmousey);
413
 
                glutPostRedisplay();
414
 
            }else if(action_mode==ZOOM_IN)
415
 
                glutPostRedisplay();
416
 
            
417
 
            glutPostRedisplay();
418
 
            oldmousex=x;
419
 
            oldmousey=y;
420
 
        }
421
 
    }
422
 
    
423
 
    void PanZoom2D::
424
 
    return_to_default(void)
425
 
    {
426
 
        bottom=default_bottom;
427
 
        left=default_left;
428
 
        height=default_height;
429
 
    }
430
 
    
431
 
    void PanZoom2D::
432
 
    transform_mouse(int x, int y, float coords[2])
433
 
    {
434
 
        float r=height/winheight;
435
 
        coords[0]=x*r+left;
436
 
        coords[1]=(winheight-y)*r+bottom;
437
 
    }
438
 
    
439
 
    void PanZoom2D::
440
 
    gl_transform(void)
441
 
    {
442
 
        glViewport(0, 0, (GLsizei)winwidth, (GLsizei)winheight);
443
 
        glMatrixMode(GL_PROJECTION);
444
 
        glLoadIdentity();
445
 
        glOrtho(left, left+(height*winwidth)/winheight, bottom, bottom+height, 0, 1);
446
 
        glMatrixMode(GL_MODELVIEW);
447
 
        glLoadIdentity();
448
 
    }
449
 
    
450
 
    void PanZoom2D::
451
 
    export_rib(ostream &output)
452
 
    {
453
 
        // no projection matrix
454
 
        output<<"Clipping 1 2000"<<endl; // somewhat arbitrary - hopefully this is plenty of space
455
 
        output<<"ReverseOrientation"<<endl;  // RenderMan has a different handedness from OpenGL's default
456
 
        output<<"Scale 1 1 -1"<<endl;        // so we need to correct for that here
457
 
        // scale so that smaller dimension gets scaled to size 2
458
 
        float scalefactor;
459
 
        if(winwidth>winheight) scalefactor=2.0f/height;
460
 
        else scalefactor=2.0f/(winwidth*height/winheight);
461
 
        output<<"Scale "<<scalefactor<<" "<<scalefactor<<" 1"<<endl;
462
 
        // translate so centre of view gets mapped to (0,0,1000)
463
 
        output<<"Translate "<<-(left+0.5*winwidth*height/winheight)<<" "<<-(bottom+0.5*height)<< " 1000"<<endl;
464
 
    }
465
 
    
466
 
    void PanZoom2D::
467
 
    display_screen(void)
468
 
    {
469
 
        if(action_mode==ZOOM_IN && moved_since_mouse_down){
470
 
            glColor3f(1,1,1);
471
 
            glBegin(GL_LINE_STRIP);
472
 
            glVertex2i(clickx, winheight-clicky);
473
 
            glVertex2i(oldmousex, winheight-clicky);
474
 
            glVertex2i(oldmousex, winheight-oldmousey);
475
 
            glVertex2i(clickx, winheight-oldmousey);
476
 
            glVertex2i(clickx, winheight-clicky);
477
 
            glEnd();
478
 
        }
479
 
    }
480
 
    
481
 
    //=================================================================================
482
 
    
483
 
    StaticText::
484
 
    StaticText(const char *text_)
485
 
    : text(text_)
486
 
    {}
487
 
    
488
 
    void StaticText::
489
 
    display(int x, int y)
490
 
    {
491
 
        dispx=x;
492
 
        dispy=y;
493
 
        width=glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)text)+1;
494
 
        height=15;
495
 
        glColor3f(0.3f, 0.3f, 0.3f);
496
 
        glRasterPos2i(x, y-height+2);
497
 
        for(int i=0; text[i]!=0; ++i)
498
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
499
 
        glColor3f(1, 1, 1);
500
 
        glRasterPos2i(x+1, y-height+3);
501
 
        for(int i=0; text[i]!=0; ++i)
502
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
503
 
    }
504
 
    
505
 
    //=================================================================================
506
 
    
507
 
    DynamicText::DynamicText( const std::string& text_ )
508
 
    : 
509
 
    text(text_)
510
 
    {
511
 
        color[0] = 0.0f;
512
 
        color[1] = 0.0f;
513
 
        color[2] = 0.0f;
514
 
    }
515
 
    
516
 
    void DynamicText::set_color( float r, float g, float b )
517
 
    {
518
 
        color[0] = r;
519
 
        color[1] = g;
520
 
        color[2] = b;
521
 
    }
522
 
    
523
 
    void DynamicText::display( int x, int y )
524
 
    {
525
 
        dispx=x;
526
 
        dispy=y;
527
 
        width=glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)text.c_str())+1;
528
 
        height=15;
529
 
        
530
 
        //   glColor3f(0.3f, 0.3f, 0.3f);
531
 
        //   glRasterPos2i(x, y-height+2);
532
 
        //   for(int i=0; text[i]!=0; ++i)
533
 
        //      glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
534
 
        
535
 
        glColor3f( color[0], color[1], color[2] );
536
 
        
537
 
        glRasterPos2i(x+1, y-height+3);
538
 
        for(int i=0; text[i]!=0; ++i)
539
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);   
540
 
    }
541
 
    
542
 
    
543
 
    //=================================================================================
544
 
    
545
 
    Button::
546
 
    Button(const char *text_, int minwidth_)
547
 
    : status(UNINVOLVED), text(text_), minwidth(minwidth_)
548
 
    {}
549
 
    
550
 
    void Button::
551
 
    display(int x, int y)
552
 
    {
553
 
        dispx=x;
554
 
        dispy=y;
555
 
        int textwidth=glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)text);
556
 
        if(textwidth<minwidth) width=minwidth+24;
557
 
        else width=textwidth+24;
558
 
        height=17;
559
 
        if(status==UNINVOLVED){
560
 
            glColor3f(0.7f, 0.7f, 0.7f);
561
 
            glBegin(GL_QUADS);
562
 
            glVertex2i(x+1, y-1);
563
 
            glVertex2i(x+width, y-1);
564
 
            glVertex2i(x+width, y-height+1);
565
 
            glVertex2i(x+1, y-height+1);
566
 
            glEnd();
567
 
            glColor3f(0.3f, 0.3f, 0.3f);
568
 
            glLineWidth(1);
569
 
            glBegin(GL_LINE_STRIP);
570
 
            glVertex2i(x, y-2);
571
 
            glVertex2i(x, y-height);
572
 
            glVertex2i(x+width-1, y-height);
573
 
            glEnd();
574
 
            glColor3f(0.3f, 0.3f, 0.3f);
575
 
        }else{
576
 
            if(status==SELECTED) glColor3f(0.8f, 0.8f, 0.8f);
577
 
            else                 glColor3f(1, 1, 1);
578
 
            glBegin(GL_QUADS);
579
 
            glVertex2i(x, y-1);
580
 
            glVertex2i(x+width, y-1);
581
 
            glVertex2i(x+width, y-height);
582
 
            glVertex2i(x, y-height);
583
 
            glEnd();
584
 
            glColor3f(0, 0, 0);
585
 
        }
586
 
        glRasterPos2i(x+(width-textwidth)/2, y-height+5);
587
 
        for(int i=0; text[i]!=0; ++i)
588
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
589
 
    }
590
 
    
591
 
    bool Button::
592
 
    click(int state, int x, int y)
593
 
    {
594
 
        if(state==GLUT_DOWN && x>dispx && x<=dispx+width && y<dispy-2 && y>=dispy-height){
595
 
            status=HIGHLIGHTED;
596
 
            glutPostRedisplay();
597
 
            return true;
598
 
        }else if(state==GLUT_UP && status!=UNINVOLVED){
599
 
            status=UNINVOLVED;
600
 
            glutPostRedisplay();
601
 
            if(x>=dispx && x<dispx+width && y<dispy-2 && y>=dispy-height)
602
 
                action();
603
 
            return true;
604
 
        }else
605
 
            return false;
606
 
    }
607
 
    
608
 
    void Button::
609
 
    drag(int x, int y)
610
 
    {
611
 
        // needs to control highlighting (SELECTED vs. HIGHLIGHTED)
612
 
        if(status==SELECTED && x>=dispx && x<dispx+width && y<dispy-2 && y>=dispy-height){
613
 
            status=HIGHLIGHTED;
614
 
            glutPostRedisplay();
615
 
        }else if(status==HIGHLIGHTED && !(x>=dispx && x<dispx+width && y<dispy-2 && y>=dispy-height)){
616
 
            status=SELECTED;
617
 
            glutPostRedisplay();
618
 
        }
619
 
    }
620
 
    
621
 
    //=================================================================================
622
 
    
623
 
    Slider::
624
 
    Slider(const char *text_, int length_, int position_, int justify_)
625
 
    : status(UNINVOLVED), text(text_), length(length_), justify(justify_), position(position_),
626
 
    scrollxmin(~0), scrollxmax(~0), scrollymin(~0), scrollymax(~0), clickx(~0) 
627
 
    {}
628
 
    
629
 
    void Slider::
630
 
    display(int x, int y)
631
 
    {
632
 
        dispx=x;
633
 
        dispy=y;
634
 
        width=glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)text);
635
 
        if(width<justify) width=justify;
636
 
        width+=11+6+length+1;
637
 
        height=15;
638
 
        glColor3f(0.3f, 0.3f, 0.3f);
639
 
        glRasterPos2i(x, y-height+2);
640
 
        for(int i=0; text[i]!=0; ++i)
641
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
642
 
        glColor3f(1, 1, 1);
643
 
        glRasterPos2i(x+1, y-height+3);
644
 
        for(int i=0; text[i]!=0; ++i)
645
 
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text[i]);
646
 
        scrollxmin=x+width-length-12;
647
 
        scrollxmax=x+width;
648
 
        scrollymin=y-height+1;
649
 
        scrollymax=y-2;
650
 
        glColor3f(0.3f, 0.3f, 0.3f);
651
 
        glLineWidth(1);
652
 
        glBegin(GL_LINE_STRIP);
653
 
        glVertex2i(scrollxmin, scrollymax-1);
654
 
        glVertex2i(scrollxmin, scrollymin);
655
 
        glVertex2i(scrollxmax-1, scrollymin);
656
 
        glVertex2i(scrollxmax-1, scrollymax-1);
657
 
        glEnd();
658
 
        glColor3f(0.7f, 0.7f, 0.7f);
659
 
        glBegin(GL_LINE_STRIP);
660
 
        glVertex2i(scrollxmin+1, scrollymax);
661
 
        glVertex2i(scrollxmin+1, scrollymin+1);
662
 
        glVertex2i(scrollxmax, scrollymin+1);
663
 
        glVertex2i(scrollxmax, scrollymax);
664
 
        glEnd();
665
 
        if(status==UNINVOLVED){
666
 
            glColor3f(0.3f, 0.3f, 0.3f);
667
 
            glBegin(GL_LINE_STRIP);
668
 
            glVertex2i(scrollxmin+position+2, scrollymax-2);
669
 
            glVertex2i(scrollxmin+position+2, scrollymin+2);
670
 
            glVertex2i(scrollxmin+position+10, scrollymin+2);
671
 
            glEnd();
672
 
            glColor3f(0.7f, 0.7f, 0.7f);
673
 
            glBegin(GL_QUADS);
674
 
            glVertex2i(scrollxmin+position+3, scrollymin+3);
675
 
            glVertex2i(scrollxmin+position+11, scrollymin+3);
676
 
            glVertex2i(scrollxmin+position+11, scrollymax);
677
 
            glVertex2i(scrollxmin+position+3, scrollymax);
678
 
            glEnd();
679
 
        }else{ // SELECTED
680
 
            glColor3f(1, 1, 1);
681
 
            glBegin(GL_QUADS);
682
 
            glVertex2i(scrollxmin+position+2, scrollymin+2);
683
 
            glVertex2i(scrollxmin+position+11, scrollymin+2);
684
 
            glVertex2i(scrollxmin+position+11, scrollymax);
685
 
            glVertex2i(scrollxmin+position+2, scrollymax);
686
 
            glEnd();
687
 
        }
688
 
    }
689
 
    
690
 
    bool Slider::
691
 
    click(int state, int x, int y)
692
 
    {
693
 
        if(state==GLUT_DOWN && x>scrollxmin+position+2 && x<=scrollxmin+position+11 && y<scrollymax-1 && y>=scrollymin+2){
694
 
            status=SELECTED;
695
 
            clickx=x;
696
 
            glutPostRedisplay();
697
 
            return true;
698
 
        }else if(status!=UNINVOLVED && state==GLUT_UP){
699
 
            status=UNINVOLVED;
700
 
            glutPostRedisplay();
701
 
            return true;
702
 
        }else
703
 
            return false;
704
 
    }
705
 
    
706
 
    void Slider::
707
 
    drag(int x, int /*y*/ )
708
 
    {
709
 
        if(status==SELECTED){
710
 
            glutPostRedisplay();
711
 
            int newposition=position+(x-clickx);
712
 
            clickx=x;
713
 
            if(newposition<0){
714
 
                clickx+=(0-newposition);
715
 
                newposition=0;
716
 
            }else if(newposition>length){
717
 
                clickx+=(length-newposition);
718
 
                newposition=length;
719
 
            }
720
 
            if(newposition!=position){
721
 
                position=newposition;
722
 
                action();
723
 
                glutPostRedisplay();
724
 
            }
725
 
        }
726
 
    }
727
 
    
728
 
    //=================================================================================
729
 
    
730
 
    WidgetList::
731
 
    WidgetList(int indent_, bool hidden_)
732
 
    : indent(indent_), hidden(hidden_), list(), downclicked_member(-1)
733
 
    {
734
 
    }
735
 
    
736
 
    void WidgetList::
737
 
    display(int x, int y)
738
 
    {
739
 
        dispx=x;
740
 
        dispy=y;
741
 
        if(hidden){
742
 
            width=height=0;
743
 
        }else{
744
 
            height=0;
745
 
            for(unsigned int i=0; i<list.size(); ++i){
746
 
                list[i]->display(x+indent, y-height);
747
 
                height+=list[i]->height;
748
 
                width=(width<indent+list[i]->width) ? indent+list[i]->width : width;
749
 
            }
750
 
        }
751
 
    }
752
 
    
753
 
    bool WidgetList::
754
 
    click(int state, int x, int y)
755
 
    {
756
 
        //if(hidden || x<dispx || x>=dispx+width || y>=dispy || y<dispy-height) return false; // early exit
757
 
        if(state==GLUT_DOWN){ // search for correct widget
758
 
            for(unsigned int i=0; i<list.size(); ++i){
759
 
                if(list[i]->click(state, x, y)){
760
 
                    downclicked_member=i;
761
 
                    return true;
762
 
                }
763
 
            }
764
 
        }else if(state==GLUT_UP && downclicked_member>=0){
765
 
            list[downclicked_member]->click(state, x, y);
766
 
            downclicked_member=-1;
767
 
        }
768
 
        return false;
769
 
    }
770
 
    
771
 
    void WidgetList::
772
 
    drag(int x, int y)
773
 
    {
774
 
        if(downclicked_member>=0)
775
 
            list[downclicked_member]->drag(x, y);
776
 
    }
777
 
    
778
 
    
779
 
    //=================================================================================
780
 
    
781
 
    typedef enum {NOBODY, CAMERA, WIDGETS, USER} MouseOwnerType;
782
 
    
783
 
    MouseOwnerType mouse_owner = NOBODY;
784
 
    
785
 
    //
786
 
    // Local ("static") functions
787
 
    //
788
 
    
789
 
    namespace {
790
 
        
791
 
        //=================================================================================
792
 
        
793
 
        void gluviReshape(int w, int h)
794
 
        {
795
 
            winwidth=w;
796
 
            winheight=h;
797
 
            glutPostRedisplay(); // triggers the camera to adjust itself to the new dimensions
798
 
        }
799
 
        
800
 
        //=================================================================================
801
 
        
802
 
        void gluviDisplay()
803
 
        {
804
 
            
805
 
            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
806
 
            
807
 
            // draw the scene
808
 
            if(camera) camera->gl_transform();
809
 
            if(userDisplayFunc) userDisplayFunc();
810
 
            
811
 
            // now draw widgets on top
812
 
            glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT|GL_LINE_BIT);
813
 
            glDisable(GL_DEPTH_TEST);
814
 
            glDisable(GL_LIGHTING);
815
 
            glLineWidth(1);
816
 
            // and probably more needs setting before widgets
817
 
            
818
 
            glMatrixMode(GL_MODELVIEW);
819
 
            glLoadIdentity();
820
 
            glMatrixMode(GL_PROJECTION);
821
 
            glLoadIdentity();
822
 
            gluOrtho2D(0, winwidth, 0, winheight);
823
 
            
824
 
            root.display(0, winheight);
825
 
            
826
 
            // and allow the camera to draw something on screen (e.g. for zooming extent)
827
 
            if(camera) camera->display_screen();
828
 
            
829
 
            glPopAttrib();
830
 
            
831
 
            glutSwapBuffers();
832
 
        }
833
 
        
834
 
        void gluviMouse(int button, int state, int x, int y)
835
 
        {
836
 
            if(state==GLUT_DOWN){
837
 
                int mods=glutGetModifiers();
838
 
                if(camera && mods==GLUT_ACTIVE_SHIFT){
839
 
                    camera->click(button, state, x, y);
840
 
                    mouse_owner=CAMERA;
841
 
                    //}else if(button==GLUT_LEFT_BUTTON && root.click(state, x, winheight-y)){
842
 
                    //   mouse_owner=WIDGETS;
843
 
                }else if(userMouseFunc){
844
 
                    userMouseFunc(button, state, x, y);
845
 
                    mouse_owner=USER;
846
 
                }
847
 
            }else{ // mouse up - send event to whoever got the mouse down
848
 
                switch(mouse_owner){
849
 
                    case CAMERA:
850
 
                        camera->click(button, state, x, y);
851
 
                        break;
852
 
                    case WIDGETS:
853
 
                        //root.click(state, x, winheight-y);
854
 
                        break;
855
 
                    case USER:
856
 
                        if(userMouseFunc) userMouseFunc(button, state, x, y);
857
 
                        break;
858
 
                    default:
859
 
                        ;// nothing to do
860
 
                }
861
 
                mouse_owner=NOBODY;
862
 
            }
863
 
        }
864
 
        
865
 
        //=================================================================================
866
 
        
867
 
        void gluviDrag(int x, int y)
868
 
        {
869
 
            switch(mouse_owner){
870
 
                case CAMERA:
871
 
                    camera->drag(x, y);
872
 
                    break;
873
 
                case WIDGETS:
874
 
                    //root.drag(x, winheight-y);
875
 
                    break;
876
 
                case USER:
877
 
                    if(userDragFunc) userDragFunc(x, y);
878
 
                    break;
879
 
                default:
880
 
                    ;// nothing to do
881
 
            }
882
 
        }
883
 
        
884
 
        
885
 
    }  // namespace
886
 
    
887
 
    
888
 
    //=================================================================================
889
 
    
890
 
    void ppm_screenshot(const char *filename_format, ...)
891
 
    {
892
 
        va_list ap;
893
 
        va_start(ap, filename_format);
894
 
#ifdef _MSC_VER
895
 
#define FILENAMELENGTH 256
896
 
        char filename[FILENAMELENGTH];
897
 
        _vsnprintf(filename, FILENAMELENGTH, filename_format, ap);
898
 
        ofstream out(filename, ofstream::binary);
899
 
#else
900
 
        char *filename;
901
 
        vasprintf(&filename, filename_format, ap);
902
 
        ofstream out(filename, ofstream::binary);
903
 
        free(filename);
904
 
#endif
905
 
        if(!out) return;
906
 
        GLubyte *image_buffer=new GLubyte[3*winwidth*winheight];
907
 
        glReadBuffer(GL_FRONT);
908
 
        glReadPixels(0, 0, winwidth, winheight, GL_RGB, GL_UNSIGNED_BYTE, image_buffer);
909
 
        out<<"P6\n"<<winwidth<<' '<<winheight<<" 255\n";
910
 
        for(int i=1; i<=winheight; ++i)
911
 
            out.write((const char*)image_buffer+3*winwidth*(winheight-i), 3*winwidth);
912
 
        delete[] image_buffer;
913
 
    }
914
 
    
915
 
    namespace { 
916
 
        
917
 
        void write_big_endian_ushort(std::ostream &output, unsigned short v)
918
 
        {
919
 
            output.put( static_cast<char>((v>>8)%256) );
920
 
            output.put( static_cast<char>(v%256) );
921
 
        }
922
 
        
923
 
        void write_big_endian_uint(std::ostream &output, unsigned int v)
924
 
        {
925
 
            output.put(static_cast<char>((v>>24)%256));
926
 
            output.put(static_cast<char>((v>>16)%256));
927
 
            output.put(static_cast<char>((v>>8)%256));
928
 
            output.put(static_cast<char>(v%256));
929
 
        }
930
 
        
931
 
    }  // unnamed namespace
932
 
    
933
 
    void sgi_screenshot(const char *filename_format, ...)
934
 
    {
935
 
        va_list ap;
936
 
        va_start(ap, filename_format);
937
 
#ifdef _MSC_VER
938
 
#define FILENAMELENGTH 256
939
 
        char filename[FILENAMELENGTH];
940
 
        _vsnprintf(filename, FILENAMELENGTH, filename_format, ap);
941
 
        ofstream output(filename, ofstream::binary);
942
 
#else
943
 
        char *filename;
944
 
        vasprintf(&filename, filename_format, ap);
945
 
        ofstream output(filename, ofstream::binary);
946
 
#endif
947
 
        if(!output) return;
948
 
        
949
 
        const int mipmap_level = 1;
950
 
        const int size_scale = 1 << (mipmap_level);
951
 
        
952
 
        winwidth = size_scale * winwidth;
953
 
        winheight = size_scale * winheight;
954
 
        
955
 
        glGenFramebuffers(1, &screenshot_fbo);
956
 
        glBindFramebuffer(GL_FRAMEBUFFER, screenshot_fbo);
957
 
        
958
 
        GLuint textureId;
959
 
        glGenTextures(1, &textureId);
960
 
        glBindTexture(GL_TEXTURE_2D, textureId);
961
 
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
962
 
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
963
 
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
964
 
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
965
 
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
966
 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmap_level);
967
 
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, winwidth, winheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
968
 
        
969
 
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);
970
 
        
971
 
        //
972
 
        // Depth/stencil buffer
973
 
        //
974
 
        
975
 
        GLuint depthRenderbuffer;
976
 
        glGenRenderbuffers(1, &depthRenderbuffer);
977
 
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
978
 
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, winwidth, winheight);
979
 
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
980
 
        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
981
 
        
982
 
        if (status != GL_FRAMEBUFFER_COMPLETE) 
983
 
        {
984
 
            std::cout << "Problem with OpenGL framebuffer after specifying depth/stencil render buffer: " << hex << status << std::endl;
985
 
            assert(0);
986
 
        }
987
 
        
988
 
        glPixelStorei(GL_PACK_ALIGNMENT, 1);
989
 
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);   
990
 
        glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE);
991
 
        
992
 
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
993
 
        
994
 
        // draw the scene
995
 
        
996
 
        taking_screenshot = true;
997
 
        
998
 
        if(camera) camera->gl_transform();
999
 
        if(userDisplayFunc) userDisplayFunc();
1000
 
        
1001
 
        taking_screenshot = false;
1002
 
        
1003
 
        glEnable(GL_TEXTURE_2D);
1004
 
        glGenerateMipmapEXT(GL_TEXTURE_2D);
1005
 
        
1006
 
        GLint file_width, file_height;
1007
 
        glGetTexLevelParameteriv( GL_TEXTURE_2D, mipmap_level, GL_TEXTURE_WIDTH, &file_width );
1008
 
        glGetTexLevelParameteriv( GL_TEXTURE_2D, mipmap_level, GL_TEXTURE_HEIGHT, &file_height );
1009
 
        
1010
 
        GLubyte *buffer = new GLubyte[ 4 * file_width * file_height ]; 
1011
 
        
1012
 
        glGetTexImage( GL_TEXTURE_2D, mipmap_level, GL_RGBA, GL_UNSIGNED_BYTE, buffer );
1013
 
        
1014
 
        
1015
 
        GLubyte* r_buffer = new GLubyte[file_width*file_height];            
1016
 
        GLubyte* g_buffer = new GLubyte[file_width*file_height];            
1017
 
        GLubyte* b_buffer = new GLubyte[file_width*file_height];            
1018
 
        
1019
 
        for(int y = 0; y < file_height; y++)
1020
 
            for(int x = 0; x < file_width; x++)
1021
 
            {
1022
 
                int startAddressOfPixel = ((y*file_width) + x)*4;
1023
 
                
1024
 
                r_buffer[ ((y*file_width) + x) ] = buffer[startAddressOfPixel+0];
1025
 
                g_buffer[ ((y*file_width) + x) ] = buffer[startAddressOfPixel+1];
1026
 
                b_buffer[ ((y*file_width) + x) ] = buffer[startAddressOfPixel+2];
1027
 
            }
1028
 
        
1029
 
        
1030
 
        // first write the SGI header
1031
 
        
1032
 
        write_big_endian_ushort(output, 474); // magic number to identify this as an SGI image file
1033
 
        output.put(0); // uncompressed
1034
 
        output.put(1); // use 8-bit colour depth
1035
 
        write_big_endian_ushort(output, 3); // number of dimensions
1036
 
        assert( file_width < std::numeric_limits<unsigned short>::max() );
1037
 
        assert( file_height < std::numeric_limits<unsigned short>::max() );   
1038
 
        write_big_endian_ushort(output, static_cast<unsigned short>(file_width) ); // x size
1039
 
        write_big_endian_ushort(output, static_cast<unsigned short>(file_height) ); // y size
1040
 
        write_big_endian_ushort(output, 3); // three colour channels (z size)
1041
 
        write_big_endian_uint(output, 0); // minimum pixel value
1042
 
        write_big_endian_uint(output, 255); // maximum pixel value
1043
 
        write_big_endian_uint(output, 0); // dummy spacing
1044
 
        // image name
1045
 
        int i;
1046
 
        for(i=0; i<80 && filename[i]; ++i)
1047
 
            output.put(filename[i]);
1048
 
        for(; i<80; ++i)
1049
 
            output.put(0);
1050
 
        write_big_endian_uint(output, 0); // colormap is normal
1051
 
        for(i=0; i<404; ++i) output.put(0); // filler to complete header
1052
 
        
1053
 
        // now write the SGI image data
1054
 
        
1055
 
        output.write((const char*)r_buffer, file_width*file_height);
1056
 
        output.write((const char*)g_buffer, file_width*file_height);
1057
 
        output.write((const char*)b_buffer, file_width*file_height);
1058
 
        
1059
 
        delete[] r_buffer;
1060
 
        delete[] g_buffer;
1061
 
        delete[] b_buffer;
1062
 
        delete[] buffer;
1063
 
        
1064
 
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
1065
 
        glBindTexture(GL_TEXTURE_2D, 0);
1066
 
        
1067
 
        winwidth /= size_scale;
1068
 
        winheight /= size_scale;
1069
 
        if(camera) camera->gl_transform();
1070
 
        
1071
 
        glDeleteTextures( 1, &textureId );
1072
 
        glDeleteRenderbuffers( 1, &depthRenderbuffer );
1073
 
        glDeleteFramebuffers(1, &screenshot_fbo);
1074
 
        
1075
 
#ifndef _MSC_VER
1076
 
        free(filename);
1077
 
#endif
1078
 
    }
1079
 
    
1080
 
    void set_generic_lights(void)
1081
 
    {
1082
 
        glEnable(GL_LIGHTING);
1083
 
        {
1084
 
            GLfloat ambient[4] = {.3f, .3f, .3f, 1.0f};
1085
 
            glLightModelfv (GL_LIGHT_MODEL_AMBIENT,ambient);
1086
 
        }
1087
 
        {
1088
 
            GLfloat color[4] = {.4f, .4f, .4f, 1.0f};
1089
 
            glLightfv (GL_LIGHT0, GL_DIFFUSE, color);
1090
 
            glLightfv (GL_LIGHT0, GL_SPECULAR, color);
1091
 
            glEnable (GL_LIGHT0);
1092
 
        }
1093
 
        {
1094
 
            GLfloat color[4] = {.4f, .4f, .4f, 1.0f};
1095
 
            glLightfv (GL_LIGHT1, GL_DIFFUSE, color);
1096
 
            glLightfv (GL_LIGHT1, GL_SPECULAR, color);
1097
 
            glEnable (GL_LIGHT1);
1098
 
        }
1099
 
        {
1100
 
            GLfloat color[4] = {.2f, .2f, .2f, 1.0f};
1101
 
            glLightfv (GL_LIGHT2, GL_DIFFUSE, color);
1102
 
            glLightfv (GL_LIGHT2, GL_SPECULAR, color);
1103
 
            glEnable (GL_LIGHT2);
1104
 
        }
1105
 
    }
1106
 
    
1107
 
    void set_generic_material(float r, float g, float b, GLenum face)
1108
 
    {
1109
 
        GLfloat ambient[4], diffuse[4], specular[4];
1110
 
        ambient[0]=0.1f*r+0.03f; ambient[1]=0.1f*g+0.03f; ambient[2]=0.1f*b+0.03f; ambient[3]=1.0f;
1111
 
        diffuse[0]=0.7f*r;      diffuse[1]=0.7f*g;      diffuse[2]=0.7f*b;      diffuse[3]=1.0f;
1112
 
        specular[0]=0.1f*r+0.1f; specular[1]=0.1f*g+0.1f; specular[2]=0.1f*b+0.1f; specular[3]=1.0f;
1113
 
        glMaterialfv(face, GL_AMBIENT, ambient);
1114
 
        glMaterialfv(face, GL_DIFFUSE, diffuse);
1115
 
        glMaterialfv(face, GL_SPECULAR, specular);
1116
 
        glMaterialf(face, GL_SHININESS, 32);
1117
 
    }
1118
 
    
1119
 
    void set_matte_material(float r, float g, float b, GLenum face)
1120
 
    {
1121
 
        GLfloat ambient[4], diffuse[4], specular[4];
1122
 
        ambient[0]=0.1f*r+0.03f; ambient[1]=0.1f*g+0.03f; ambient[2]=0.1f*b+0.03f; ambient[3]=1.0f;
1123
 
        diffuse[0]=0.9f*r;      diffuse[1]=0.9f*g;      diffuse[2]=0.9f*b;      diffuse[3]=1.0f;
1124
 
        specular[0]=0;         specular[1]=0;         specular[2]=0;         specular[3]=1;
1125
 
        glMaterialfv(face, GL_AMBIENT, ambient);
1126
 
        glMaterialfv(face, GL_DIFFUSE, diffuse);
1127
 
        glMaterialfv(face, GL_SPECULAR, specular);
1128
 
    }
1129
 
    
1130
 
    /** 
1131
 
     * Draw a vector in 3D.  If arrow_head_length not specified, set it to 10% of vector length.
1132
 
     * Mar 29, 2006
1133
 
     */
1134
 
    void draw_3d_arrow(const float base[3], const float point[3], float arrow_head_length)
1135
 
    {
1136
 
        //glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT|GL_LINE_BIT);
1137
 
        //glDisable(GL_LIGHTING);
1138
 
        glLineWidth(1);
1139
 
        glColor3f(0.5f,0.5f,0.5f);
1140
 
        
1141
 
        Vec3f w(point[0]-base[0], point[1]-base[1], point[2]-base[2]);
1142
 
        float len = mag(w);
1143
 
        w = w / len;    // normalize to build coordinate system
1144
 
        
1145
 
        // create a coordinate system from the vector:
1146
 
        // get a vector perp to w and y-axis
1147
 
        Vec3f u = cross(w, Vec3f(0,1,0));
1148
 
        
1149
 
        // If vector is parallel to the y-axis, use the x-axis
1150
 
        if (mag(u) == 0)
1151
 
            u = cross(w, Vec3f(1,0,0));
1152
 
        
1153
 
        // get a vector perp to w and u
1154
 
        Vec3f v = cross(w, u/mag(u));
1155
 
        v = v/mag(v);
1156
 
        
1157
 
        if (!arrow_head_length)
1158
 
            arrow_head_length = 0.1f * len;
1159
 
        
1160
 
        // arrow head points
1161
 
        //@@@@@@@ POSSIBILITY: CREATE FOUR ARROW HEAD SEGMENTS INSTEAD OF TWO
1162
 
        Vec3f arrow1, arrow2;
1163
 
        arrow1[0] = point[0] + arrow_head_length * (v[0] - w[0]);
1164
 
        arrow1[1] = point[1] + arrow_head_length * (v[1] - w[1]);
1165
 
        arrow1[2] = point[2] + arrow_head_length * (v[2] - w[2]);
1166
 
        arrow2[0] = point[0] + arrow_head_length * (-v[0] - w[0]);
1167
 
        arrow2[1] = point[1] + arrow_head_length * (-v[1] - w[1]);
1168
 
        arrow2[2] = point[2] + arrow_head_length * (-v[2] - w[2]);
1169
 
        
1170
 
        glBegin(GL_LINES);
1171
 
        glVertex3f(base[0],   base[1],   base[2]);
1172
 
        glVertex3f(point[0],  point[1],  point[2]);
1173
 
        glVertex3f(point[0],  point[1],  point[2]);
1174
 
        glVertex3f(arrow1[0], arrow1[1], arrow1[2]);
1175
 
        glVertex3f(point[0],  point[1],  point[2]);
1176
 
        glVertex3f(arrow2[0], arrow2[1], arrow2[2]);
1177
 
        glEnd();
1178
 
        
1179
 
        //glPopAttrib();
1180
 
    }
1181
 
    
1182
 
    // draw_2d_arrow assumptions: 
1183
 
    // line width, point size, and color are set by the user prior to calling the routine
1184
 
    /*
1185
 
     void draw_2d_arrow(const Vec2f base, const Vec2f point, float arrow_head_length)
1186
 
     {
1187
 
     //glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT|GL_LINE_BIT);
1188
 
     //glDisable(GL_LIGHTING);
1189
 
     
1190
 
     Vec2f w = point-base;
1191
 
     float len = mag(w);
1192
 
     
1193
 
     if (len==0) {
1194
 
     glBegin(GL_POINTS);
1195
 
     glVertex2f(base[0], base[1]);
1196
 
     glEnd();
1197
 
     return;
1198
 
     }
1199
 
     
1200
 
     w = w / len;    // normalize to build coordinate system
1201
 
     
1202
 
     // u = w + 90 
1203
 
     // using rotation matrix  0  1
1204
 
     //                      -1  0
1205
 
     Vec2f u = Vec2f(1*w[1], -1*w[0]);
1206
 
     u = u/mag(u);
1207
 
     
1208
 
     // v = w - 90 (in fact v=-u)
1209
 
     Vec2f v = Vec2f(-1*w[1], 1*w[0]);
1210
 
     v = v/mag(v);
1211
 
     
1212
 
     if (!arrow_head_length) {
1213
 
     arrow_head_length = 0.1f * len;
1214
 
     }
1215
 
     
1216
 
     // arrow head points
1217
 
     Vec2f arrow1, arrow2;
1218
 
     arrow1 = point + arrow_head_length * (v-w);
1219
 
     arrow2 = point + arrow_head_length * (u-w);
1220
 
     
1221
 
     glBegin(GL_LINES);
1222
 
     glVertex2f(base[0], base[1]);
1223
 
     glVertex2f(point[0], point[1]);
1224
 
     glVertex2f(point[0], point[1]);
1225
 
     glVertex2f(arrow1[0], arrow1[1]);
1226
 
     glVertex2f(point[0], point[1]);
1227
 
     glVertex2f(arrow2[0], arrow2[1]);
1228
 
     glEnd();
1229
 
     
1230
 
     //glPopAttrib();
1231
 
     }
1232
 
     */
1233
 
    
1234
 
    void draw_coordinate_grid(float size, int spacing)
1235
 
    {
1236
 
        glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT|GL_LINE_BIT);
1237
 
        glDisable(GL_LIGHTING);
1238
 
        glLineWidth(1);
1239
 
        
1240
 
        glBegin(GL_LINES);
1241
 
        glColor3f(0.5f,0.5f,0.5f);
1242
 
        for(int i=-spacing; i<=spacing; ++i){
1243
 
            glVertex3f(-size,0,i*size/spacing);
1244
 
            glVertex3f((i!=0)*size,0,i*size/spacing);
1245
 
            glVertex3f(i*size/spacing,0,-size);
1246
 
            glVertex3f(i*size/spacing,0,(i!=0)*size);
1247
 
        }
1248
 
        glColor3f(1,0,0);
1249
 
        glVertex3f(0,0,0);
1250
 
        glVertex3f(size,0,0);
1251
 
        glColor3f(0,1,0);
1252
 
        glVertex3f(0,0,0);
1253
 
        glVertex3f(0,size,0);
1254
 
        glColor3f(0,0,1);
1255
 
        glVertex3f(0,0,0);
1256
 
        glVertex3f(0,0,size);
1257
 
        glEnd();
1258
 
        
1259
 
        glPopAttrib();
1260
 
    }
1261
 
    
1262
 
    void draw_text( const float* /*point[3]*/, const char* /*text*/, int /*fontsize*/ )
1263
 
    {
1264
 
        // please implement me!
1265
 
    }
1266
 
    
1267
 
    int windowID = 0;
1268
 
    
1269
 
    //=================================================================================
1270
 
    
1271
 
    void init(const char *windowtitle, int *argc, char **argv)
1272
 
    {
1273
 
        glutInit(argc, argv);
1274
 
        glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_ALPHA|GLUT_DEPTH|GLUT_STENCIL);
1275
 
        glutInitWindowSize(winwidth, winheight);
1276
 
        windowID = glutCreateWindow(windowtitle);
1277
 
        glutReshapeFunc(gluviReshape);
1278
 
        glutDisplayFunc(gluviDisplay);
1279
 
        glutMouseFunc(gluviMouse);
1280
 
        glutMotionFunc(gluviDrag);
1281
 
        glEnable(GL_DEPTH_TEST);
1282
 
        glClearDepth(1);
1283
 
        glPixelStorei(GL_PACK_ALIGNMENT, 1);
1284
 
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1285
 
        
1286
 
        glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE);
1287
 
        glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
1288
 
    }
1289
 
    
1290
 
    //=================================================================================
1291
 
    
1292
 
    void (*userDisplayFunc)(void)=0; 
1293
 
    void (*userMouseFunc)(int button, int state, int x, int y)=0;
1294
 
    void (*userDragFunc)(int x, int y)=0;
1295
 
    Camera *camera=0;
1296
 
    WidgetList root(0);
1297
 
    int winwidth=720, winheight=480;
1298
 
    
1299
 
    //=================================================================================
1300
 
    
1301
 
    void run(void)
1302
 
    {
1303
 
        glutMainLoop();
1304
 
    }
1305
 
    
1306
 
}     // namespace Gluvi
1307