1 /*
2  * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
3  * Applied Mathematics, Norway.
4  *
5  * Contact information: E-mail: tor.dokken@sintef.no
6  * SINTEF ICT, Department of Applied Mathematics,
7  * P.O. Box 124 Blindern,
8  * 0314 Oslo, Norway.
9  *
10  * This file is part of SISL.
11  *
12  * SISL is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * SISL is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public
23  * License along with SISL. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  * In accordance with Section 7(b) of the GNU Affero General Public
27  * License, a covered work must retain the producer line in every data
28  * file that is created or manipulated using SISL.
29  *
30  * Other Usage
31  * You can be released from the requirements of the license by purchasing
32  * a commercial license. Buying such a license is mandatory as soon as you
33  * develop commercial activities involving the SISL library without
34  * disclosing the source code of your own applications.
35  *
36  * This file may be used in accordance with the terms contained in a
37  * written agreement between you and SINTEF ICT.
38  */
39 
40 #include <math.h>
41 #include <stdlib.h>
42 #include <cstring>
43 
44 #include "aux2.h"
45 #include "gl_aux.h"
46 
47 
48 
49 #ifndef PI
50 #  define PI 3.1415926536	// Where should it *really* be defined?
51 #endif
52 
53 
54 const int predefined_colours=24;
55 const double predef_col_table[3*predefined_colours]
56 ={1.0, 0.0, 0.0,
57   0.0, 1.0, 0.0,
58   0.0, 0.0, 1.0,
59   1.0, 1.0, 0.0,
60   0.0, 1.0, 1.0,
61   1.0, 0.0, 1.0,
62   0.7, 0.0, 0.0,
63   0.0, 0.7, 0.0,
64   0.0, 0.0, 0.7,
65   0.7, 0.7, 0.0,
66   0.0, 0.7, 0.7,
67   0.7, 0.0, 0.7,
68   0.3, 0.8, 0.8,
69   0.8, 0.3, 0.8,
70   0.8, 0.8, 0.3,
71   0.3, 0.3, 0.8,
72   0.8, 0.3, 0.3,
73   0.3, 0.8, 0.3,
74   0.5, 0.8, 0.8,
75   0.8, 0.5, 0.8,
76   0.8, 0.8, 0.5,
77   0.5, 0.5, 0.8,
78   0.8, 0.5, 0.5,
79   0.5, 0.8, 0.5};
80 
81 
82 
83 
84 
85 //----------------------------------------------------------------------
86 //
87 // Drawing a cylinder, or possibly a cone.
88 //
89 //----------------------------------------------------------------------
90 
draw_cylinder(double x0,double y0,double z0,double x1,double y1,double z1,double radius,double radius2,int n)91 void draw_cylinder(double x0, double y0, double z0,
92 		   double x1, double y1, double z1,
93 		   double radius, double radius2, int n)
94 {
95   int i;
96   double y, z, r;
97 
98   glPushMatrix();
99   glTranslatef(x0, y0, z0);
100   /*
101     Now, we have to move P=(x1-x0, y1-y0, z1-z0) to (r, 0, 0) where
102     r=length(x1-x0, y1-y0, z1-z0). First, rotate P to Q in the xy-plane:
103   */
104   /* Hvorfor blir det ikke riktig med neg. rotasjon her? */
105   glRotatef(atan2(x1-x0, z1-z0)/PI*180.0-90.0,
106 	    0.0, 1.0, 0.0);
107 /*  printf("%f %f %f\t",
108 	 x1-x0,
109 	 z1-z0,
110 	 atan2(x1-x0, z1-z0)/PI*180.0);*/
111   /*
112     Now, we have to move Q=(sqrt((x1-x0)^2+(z1-z0)^2), y1-y0, 0) to
113     (r, 0, 0).
114   */
115   r=sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)+(z1-z0)*(z1-z0));
116   /* Hvorfor blir det ikke riktig med neg. rotasjon her? */
117   glRotatef(atan2(y1-y0, sqrt((x1-x0)*(x1-x0)+(z1-z0)*(z1-z0)))/PI*180.0,
118 	    0.0, 0.0, 1.0);
119 /*  printf("%f %f %f\n",
120 	 y1-y0,
121 	 sqrt((x1-x0)*(x1-x0)+(z1-z0)*(z1-z0)),
122 	 atan2(y1-y0, sqrt((x1-x0)*(x1-x0)+(z1-z0)*(z1-z0)))/PI*180.0);*/
123   /*
124     The next step is to draw the cylinder. Or cone. Normals not perfect for
125     the cone. Impossible at pointy end with tri-fan?
126   */
127   if (radius==radius2)
128     {
129       glBegin(GL_QUAD_STRIP);
130       for (i=0; i<=n; i++)
131 	{
132 	  y=radius*cos((2.0*PI*i)/n);
133 	  z=radius*sin((2.0*PI*i)/n);
134 	  glNormal3f(0.0, y, z);
135 	  glVertex3f(0.0, y, z);
136 	  glNormal3f(0.0, y, z);
137 	  glVertex3f(  r, y, z);
138 	}
139       glEnd();
140     }
141   else
142     {
143       glBegin(GL_TRIANGLE_FAN);
144       glNormal3f(1.0, 0.0, 0.0);
145       glVertex3f(r, 0.0, 0.0);
146       for (i=0; i<=n; i++)
147 	{
148 	  y=radius*cos((2.0*PI*i)/n);
149 	  z=radius*sin((2.0*PI*i)/n);
150 	  glNormal3f(0.0, y, z);
151 	  glVertex3f(0.0, y, z);
152 	}
153       glEnd();
154     }
155   /*
156     Finally, we restore the transformation stack.
157   */
158   glPopMatrix();
159 }
160 
161 
162 
163 
164 
165 
166 //----------------------------------------------------------------------
167 //
168 // Drawing a set of axes.
169 //
170 // 021203: Actually, this is newer. Fix!!!!
171 //
172 //----------------------------------------------------------------------
173 
draw_gl_axes_old(int n,double r,double radius,double rim,double l)174 void draw_gl_axes_old(int n, double r, double radius, double rim, double l)
175 {
176   // int n=10;
177   // double r=0.7;
178   // double radius=0.01, rim=0.04, l=0.1;
179 
180   const double vertex_red=1.0, vertex_green=1.0, vertex_blue=1.0;
181 
182   glColor3f(vertex_red, vertex_green, vertex_blue);
183 
184   draw_cylinder(0.0, 0.0, -r, 0.0, 0.0, r, radius, radius, n);
185   draw_cylinder(0.0, 0.0, r-0.1, 0.0, 0.0, r+0.3, rim, 0.0, n);
186   draw_cylinder(-0.5*l, l, r+0.3, 0.5*l, l, r+0.3,
187 		radius, radius, n);
188   draw_cylinder(-0.5*l, l*2.0, r+0.3, 0.5*l, l*2.0, r+0.3,
189 		radius, radius, n);
190   draw_cylinder(-0.5*l, l, r+0.3, 0.5*l, l*2.0, r+0.3,
191 		radius, radius, n);
192 
193   draw_cylinder(-r, 0.0, 0.0, r, 0.0, 0.0, radius, radius, n);
194   draw_cylinder(r-0.1, 0.0, 0.0, r+0.3, 0.0, 0.0, rim, 0.0, n);
195   draw_cylinder(r+0.3, l, 0.5*l, r+0.3, 2*l, -0.5*l,
196 		radius, radius, n);
197   draw_cylinder(r+0.3, l, -0.5*l, r+0.3, 2*l, 0.5*l,
198 		radius, radius, n);
199 
200   draw_cylinder(0.0, -r, 0.0, 0.0, r, 0.0, radius, radius, n);
201   draw_cylinder(0.0, r-0.1, 0.0, 0.0, r+0.3, 0.0, rim, 0.0, n);
202   draw_cylinder(0.0, r+0.3, 2.0*l, 0.0, r+0.3, 1.5*l,
203 		radius, radius, n);
204   draw_cylinder(0.0, r+0.3, 1.5*l, -0.5*l, r+0.3, l,
205 		radius, radius, n);
206   draw_cylinder(0.0, r+0.3, 1.5*l, 0.5*l, r+0.3, l,
207 		radius, radius, n);
208 
209   glColor3f(1.0, 1.0, 1.0);
210 }
211 
212 
213 
214 
215 
216 
217 //----------------------------------------------------------------------
218 //
219 // Draw gridlines to visualize cells.
220 //
221 //----------------------------------------------------------------------
222 
draw_grid(const int n1,const int n2,const int n3)223 void draw_grid(const int n1, const int n2, const int n3)
224 {
225   int i, j, k;
226 
227   glBegin(GL_LINES);
228   for (i=0; i<n1; i++)
229     for (j=0; j<n2; j++)
230       {
231 	const double x=2.0*(i/(n1-1.0)-0.5);
232 	const double y=2.0*(j/(n2-1.0)-0.5);
233 
234 	glColor3f(  1.0, 0.0,  0.0);
235 	glVertex3f(   x,   y, -1.0);
236 	glColor3f(  1.0, 0.0,  0.0);
237 	glVertex3f(   x,   y,  1.0);
238       }
239   for (j=0; j<n2; j++)
240     for (k=0; k<n3; k++)
241       {
242 	const double y=2.0*(j/(n2-1.0)-0.5);
243 	const double z=2.0*(k/(n3-1.0)-0.5);
244 
245 	glColor3f(  0.0, 1.0, 0.0);
246 	glVertex3f(-1.0,   y,   z);
247 	glColor3f(  0.0, 1.0, 0.0);
248 	glVertex3f( 1.0,   y,   z);
249       }
250   for (k=0; k<n3; k++)
251     for (i=0; i<n1; i++)
252       {
253 	const double z=2.0*(k/(n3-1.0)-0.5);
254 	const double x=2.0*(i/(n1-1.0)-0.5);
255 
256 	glColor3f(  0.0,  0.0, 1.0);
257 	glVertex3f(   x, -1.0,   z);
258 	glColor3f(  0.0,  0.0, 1.0);
259 	glVertex3f(   x,  1.0,   z);
260       }
261   glEnd();
262 }
263 
264 
265 
266 
267 
268 
269 //
270 // 020505: Adding transparent planes.
271 //
272 
draw_grid_planes(const int n1,const int n2,const int n3)273 void draw_grid_planes(const int n1, const int n2, const int n3)
274 {
275   int i, j, k;
276 
277   glDisable(GL_LIGHTING); // must be turned on by the caller...
278 
279   glBlendFunc(GL_ONE, GL_ONE);
280   glEnable(GL_BLEND);
281   glDisable(GL_DEPTH_TEST);
282   glBegin(GL_QUADS);
283   for (k=0; k<n3; k++)
284     {
285       const double z=2.0*(k/(n3-1.0)-0.5);
286 
287       glColor3f(  0.0,  0.0, 0.2);
288       glVertex3f(-1.0, -1.0,   z);
289       glVertex3f( 1.0, -1.0,   z);
290       glVertex3f( 1.0,  1.0,   z);
291       glVertex3f(-1.0,  1.0,   z);
292     }
293   for (j=0; j<n2; j++)
294     {
295       const double y=2.0*(j/(n2-1.0)-0.5);
296 
297       glColor3f(  0.0,  0.2,  0.0);
298       glVertex3f(-1.0,    y, -1.0);
299       glVertex3f( 1.0,    y, -1.0);
300       glVertex3f( 1.0,    y,  1.0);
301       glVertex3f(-1.0,    y,  1.0);
302     }
303   for (i=0; i<n1; i++)
304     {
305       const double x=2.0*(i/(n1-1.0)-0.5);
306 
307       glColor3f(  0.2,  0.0,  0.0);
308       glVertex3f(   x, -1.0, -1.0);
309       glVertex3f(   x,  1.0, -1.0);
310       glVertex3f(   x,  1.0,  1.0);
311       glVertex3f(   x, -1.0,  1.0);
312     }
313   glEnd();
314   glEnable(GL_DEPTH_TEST);
315   glDisable(GL_BLEND);
316 }
317 
318 
319 
320 
321 
322 
323 //----------------------------------------------------------------------
324 //
325 // Initializing glut and gl.
326 //
327 //----------------------------------------------------------------------
328 
gl_init(int argc,char * argv[],const int xs,const int ys,const int x0,const int y0,const int doubleBuffer,const int two_sided,const int lighting,const int normalize,const int smooth,const double xtrans,const double ytrans,const double ztrans,const double xscale,const double yscale,const double zscale,int & tx,int & ty,const int texture_mode,const char * const texfile)329 void gl_init(int argc, char *argv[],
330 	     const int xs, const int ys,
331 	     const int x0, const int y0,
332 	     const int doubleBuffer,
333 	     const int two_sided,
334 	     const int lighting,
335 	     const int normalize,
336 	     const int smooth,
337 	     const double xtrans,
338 	     const double ytrans,
339 	     const double ztrans,
340 	     const double xscale,
341 	     const double yscale,
342 	     const double zscale,
343 	     int &tx,
344 	     int &ty,
345 	     const int texture_mode,
346 	     const char * const texfile /* =NULL */)
347 {
348   int i;
349   const int use_accum=0;
350 
351   //
352   // 020430: NB! Note that the really confusing name 'GLUT_RGBA' hides the
353   //         fact that this setting does not induce an alpha buffer being set
354   //         up! One must in fact specify GLUT_ALPHA explicitly!
355   //         (But I'm not sure how important this is... Perhaps this alpha is
356   //         not actually needed for the *window* for OpenGL for instance to
357   //         be able to do alpha blending?!)
358   // 020501: Seems that we get accum buffer even without specifying it?!
359   // 020502: GLUT_ALPHA seems not to be available on smaug.
360   //         But we don't actually need it for alpha-blending, anyway. For
361   //         that we only need alpha for the textures.
362   //         Ok, it's there when we go to 24 bpp mode in X.
363   //
364 #ifndef QTMODE
365   glutInitDisplayMode(GLUT_RGBA | // GLUT_ALPHA |
366 		      (use_accum ? GLUT_ACCUM : 0) |
367 		      ((doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE) |
368 		      GLUT_DEPTH);
369   glutInitWindowSize(xs, ys);
370   glutInitWindowPosition(x0, y0);
371   glutInit(&argc, argv);
372   glutCreateWindow(argv[0]);
373 #endif
374 
375   glClearColor(0.0, 0.0, 0.0, 0.0);
376   if (use_accum)
377     glClearAccum(0.0, 0.0, 0.0, 0.0);
378   if (smooth)
379     glShadeModel(GL_SMOOTH);
380   else
381     glShadeModel(GL_FLAT);
382   glEnable(GL_DEPTH_TEST);
383   glDepthFunc(GL_LESS);			/* GL_LESS is default. */
384 /*  glDepthRange(100.0, -100.0);*/	/* What is default value? */
385 /*  glClearDepth(0.0); */		/* What is default value? */
386 
387   /* Initialize materials */
388 
389   {
390     static float ambient[] = {0.1, 0.1, 0.1, 1.0};
391     static float diffuse[] = {0.4, 0.4, 0.4, 1.0};
392 
393     static float position0[] = { 5.0, 5.0, 200.0, 0.0};
394     static float position1[] = {-5.0, -5.0, 200.0, 0.0};
395 
396     static float front_mat_shininess[] = {50.0};
397     // static float front_mat_specular[] = {0.9, 0.9, 0.9, 1.0};
398     static float front_mat_specular[] = {0.0, 0.0, 0.0, 1.0};
399     static float front_mat_diffuse[] = {0.7, 0.7, 0.7, 1.0};
400     // static float front_mat_diffuse[] = {0, 0, 0, 1.0};
401     static float front_mat_ambient[] = {0.3, 0.3, 0.3, 1.0};
402     static float front_mat_emission[] = {0.3, 0.0, 0.0, 1.0};
403 
404     static float back_mat_shininess[] = {128.0};
405     // static float back_mat_specular[] = {0.4, 0.4, 0.4, 1.0};
406     static float back_mat_specular[] = {0.0, 0.0, 0.0, 1.0};
407     static float back_mat_diffuse[] = {0.7, 0.7, 0.7, 1.0};
408     static float back_mat_ambient[] = {0.3, 0.3, 0.3, 1.0};
409     static float back_mat_emission[] = {0.0, 0.3, 0.0, 1.0};
410 
411     static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
412     static float lmodel_twoside[] = {GL_TRUE};
413 
414     if (two_sided)
415       lmodel_twoside[0]=GL_TRUE;
416     else
417       lmodel_twoside[0]=GL_FALSE;
418 
419     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
420     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
421     glLightfv(GL_LIGHT0, GL_POSITION, position0);
422 
423     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
424     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
425     glLightfv(GL_LIGHT1, GL_POSITION, position1);
426 
427     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
428     glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
429 
430     // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
431 
432     glMaterialfv(GL_FRONT, GL_SHININESS, front_mat_shininess);
433     glMaterialfv(GL_FRONT, GL_SPECULAR,  front_mat_specular);
434     glMaterialfv(GL_FRONT, GL_DIFFUSE,   front_mat_diffuse);
435     glMaterialfv(GL_FRONT, GL_AMBIENT,   front_mat_ambient);
436     glMaterialfv(GL_FRONT, GL_EMISSION,  front_mat_emission);
437 
438     glMaterialfv(GL_BACK, GL_SHININESS, back_mat_shininess);
439     glMaterialfv(GL_BACK, GL_SPECULAR,  back_mat_specular);
440     glMaterialfv(GL_BACK, GL_DIFFUSE,   back_mat_diffuse);
441     glMaterialfv(GL_BACK, GL_AMBIENT,   back_mat_ambient);
442     glMaterialfv(GL_BACK, GL_EMISSION,  back_mat_emission);
443 
444     glEnable(GL_LIGHT0);
445     glEnable(GL_LIGHT1);
446     if (lighting)
447       glEnable(GL_LIGHTING);
448     else
449       glDisable(GL_LIGHTING);
450     if (normalize)
451       glEnable(GL_NORMALIZE);
452     else
453       glDisable(GL_NORMALIZE);
454   }
455 
456   glMatrixMode(GL_PROJECTION);
457   glLoadIdentity();
458 /*  glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 ); */
459 /*  glFrustum( -1.0, 1.0, -1.0, 1.0, 2, 4 ); */
460 /*  glFrustum( -1.0, 1.0, -1.0, 1.0, 100, 102 ); */
461 /*  glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 7 );*/
462   /*
463     Note that the far clipping plane distance doesn't influence on
464     the projection, but that the distance between near and far should be
465     as close to one as possible to best utilise the z-buffer. Or something
466     like this...
467   */
468   //
469   // 000304: Was near=5, near clipping plane to far from viewer.
470   //         6-0.5*sqrt(3) should make a 1x1x1 cube never intersect the near
471   //         plane regardless of rotation... Making it even closer will
472   //         make it possible to expand things more before being clipped...
473   //
474   //glFrustum(-1.0, 1.0, -1.0, 1.0, 6-0.5*sqrt(3), 20);
475 
476   //
477   // 020214: This one seems to be rather good, we can zoom in quite a lot
478   //         without stuff hitting the near clipping plane.
479   //
480   glFrustum(-1.0, 1.0, -1.0, 1.0, 3, 20); // cmt out 020201
481 
482   // 020410 experimenting
483   glLoadIdentity();
484   glFrustum(-1.0, 1.0, -1.0, 1.0, 3, 20);
485 
486   //
487   // 020214: The next one let's us see inside more easily, because the near
488   //         clipping plane is further away from us.
489   //
490   //glFrustum(-1.0, 1.0, -1.0, 1.0, 5, 20);
491 
492   //
493   // 021206: Trying to get the near clipping plane closer to us.
494   //         I've lost track of the actual numbers here...
495   //         Should be dealt with...
496   //
497   glLoadIdentity();
498   glFrustum(-1.0, 1.0, -1.0, 1.0, 2.0, 20);
499 
500   //
501   // 020627: Trying to reduce the "perspective" effect.
502   //
503   //glFrustum(-1.0, 1.0, -1.0, 1.0, 5+100, 20+100);
504 
505   glMatrixMode(GL_MODELVIEW);
506   glLoadIdentity();
507 /*  glTranslated( 0.0, 0.0, -6.0 ); */
508 /*  glTranslated( 0.0, 0.0, -3.0 ); */
509 /*  glTranslated( 0.0, 0.0, -101.0 ); */
510   glTranslated(xtrans, ytrans, ztrans);
511   glScaled(xscale, yscale, zscale);
512 
513   /*
514     Why did I do this? To clear both buffers? Is this necessary here?
515   */
516   for (i=0; i<2; i++)
517     {
518       glDrawBuffer(GL_BACK);
519       glReadBuffer(GL_BACK);
520       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
521       glClear(GL_COLOR_BUFFER_BIT | (use_accum ? GL_ACCUM_BUFFER_BIT : 0));
522 #ifndef QTMODE
523       glutSwapBuffers();
524 #endif
525     }
526 
527   //
528   // Note that after the texture has been inserted into the GL engine, it
529   // is lost/deallocated from the application.
530   // (But (for some reason) the size is returned...)
531   //
532   unsigned char *texture=NULL;
533   if (texfile==NULL)
534     {
535       if (tx!=ty)
536 	CRIT_ERR(printf("tx=%d, ty=%d, not implemented.\n", tx, ty));
537 
538       if ((texture=new unsigned char[3*SQR(tx)])==NULL)
539 	CRIT_ERR(puts("Couldn't allocate space for texture."));
540 
541       int i;
542       const unsigned char a=255, b=0;
543 
544       for (i=0; i<3*SQR(tx); i++)
545 	texture[i]=a;
546       for (i=0; i<tx; i++)
547 	{
548 	  texture[3*(i*tx+0)+0]=b;
549 	  texture[3*(i*tx+0)+1]=b;
550 	  texture[3*(i*tx+0)+2]=b;
551 	  texture[3*(i*tx+(tx-1))+0]=b;
552 	  texture[3*(i*tx+(tx-1))+1]=b;
553 	  texture[3*(i*tx+(tx-1))+2]=b;
554 	  texture[3*(0*tx+i)+0]=b;
555 	  texture[3*(0*tx+i)+1]=b;
556 	  texture[3*(0*tx+i)+2]=b;
557 	  texture[3*((tx-1)*tx+i)+0]=b;
558 	  texture[3*((tx-1)*tx+i)+1]=b;
559 	  texture[3*((tx-1)*tx+i)+2]=b;
560 	}
561     }
562   else
563     //
564     // Read texture from file...
565     //
566     {
567       puts("texture code not compiled in!");
568       exit(0);
569 #if 0
570       unsigned char *texture_tmp=read_ppm_file(texfile, &tx, &ty);
571       puts("Leste pgm-fil.");
572       if (tx!=ty)
573 	CRIT_ERR(puts("Not implemented."));
574       if ((tx!=1) && (tx!=2) && (tx!=4) && (tx!=8) && (tx!=16) && (tx!=32) &&
575 	  (tx!=64) && (tx!=128) && (tx!=256) && (tx!=512) && (tx!=1024) &&
576 	  (tx!=2048) && (tx!=4096))
577 	CRIT_ERR(puts("Texture size not ok."));
578 
579       printf("Texture size is %dx%d.\n", tx, ty);
580 
581       if ((texture=new unsigned char[3*SQR(tx)])==NULL)
582 	CRIT_ERR(puts("Couldn't allocate space for texture."));
583 
584       int i;
585 
586       for (i=0; i<SQR(tx); i++)
587 	{
588 	  texture[3*i+0]=texture_tmp[i];
589 	  texture[3*i+1]=texture_tmp[i];
590 	  texture[3*i+2]=texture_tmp[i];
591 	  // printf("%5d - %3d %3d %3d\n", i,
592 	  // texture[i+0], texture[i+1], texture[i+2]);
593 	}
594 
595       delete texture_tmp;
596 #endif
597     }
598 
599   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tx, ty,
600 	       0, GL_RGB, GL_UNSIGNED_BYTE, texture);
601   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texture_mode);
602   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
603   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
604   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
605   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
606 
607   delete texture;
608 
609   //glPolygonOffset(0.0, 20.0);
610   //
611   // 020430: PolygonOffset(factor, units) produces an offset o, where
612   //         o = max depth slope * factor + impl. dep. const. r * units.
613   //         0.0, 20.0 worked just perfect for GeForce 2 and  Matrox Mystique,
614   //         but not for GeForce 3.
615   //         Perhaps it was strange that it worked? Or maybe it enough now
616   //         just use a factor slightly greater than 0.0?
617   //         A good idea would perhaps be to make a tool to adjust these
618   //         empirically during runtime?!
619   //         Seems that it is not enough to just increase factor slightly,
620   //         perhaps the GF3 has another definition for 'units'? Increasing
621   //         it somewhat seems to make the problem go away...
622   //         Don't want to increase it too much though.
623   //         Perhaps a way to do this: Increase the 'factor' until very
624   //         slanted surfaces turns out ok, and increase 'units' until
625   //         flat (parallel to near plane) surfaces are ok?! Will do it
626   //         like this but opposite order.
627   //         Hmm!!! (1.0, 1.0) seems to be just fine!
628   //
629   glPolygonOffset(1.0, 1.0);
630   glEnable(GL_POLYGON_OFFSET_POINT);
631   glEnable(GL_POLYGON_OFFSET_LINE);
632   glEnable(GL_POLYGON_OFFSET_FILL);
633 
634 }
635 
636 
637 
638 
639 
640 
transpose_matrix(double * const d)641 void transpose_matrix(double * const d)
642 {
643   int i, j;
644 
645   for (i=0; i<4; i++)
646     for (j=0; j<i; j++)
647       {
648 	double tmp=d[i*4+j];
649 	d[i*4+j]=d[j*4+i];
650 	d[j*4+i]=tmp;
651       }
652 }
653 
654 
655 
656 
657 
658 
print_gl_matrix(const int m)659 void print_gl_matrix(const int m)
660 {
661   int i;
662   double p[16], p2[16];
663 
664   switch (m)
665     {
666     case GL_PROJECTION_MATRIX:
667 
668     case GL_MODELVIEW_MATRIX:
669       glGetDoublev((GLenum)m, p);
670       break;
671 
672 #if 0
673     case GL_MODELVIEW_MATRIX + GL_PROJECTION_MATRIX:
674       glMatrixMode(GL_MODELVIEW);
675       glPushMatrix();
676       glGetDoublev(GL_PROJECTION_MATRIX, p);
677       glMultMatrixd(p);
678       glGetDoublev(GL_MODELVIEW_MATRIX, p);
679       glPopMatrix();
680       break;
681 #endif
682 
683     case GL_MODELVIEW_MATRIX + GL_PROJECTION_MATRIX:
684       glMatrixMode(GL_MODELVIEW);
685       glGetDoublev(GL_MODELVIEW_MATRIX, p2);
686       glPushMatrix();
687       glLoadIdentity();
688       glGetDoublev(GL_PROJECTION_MATRIX, p);
689       glMultMatrixd(p);
690       glMultMatrixd(p2);
691       glGetDoublev(GL_MODELVIEW_MATRIX, p);
692       glPopMatrix();
693       break;
694     }
695 
696   //
697   // 000320: BUG was here! GL uses column-order...
698   //
699   transpose_matrix(p);
700 
701   printf("{");
702   for (i=0; i<15; )
703     {
704       printf("%g, ", p[i]);
705       i++;
706       if (i%4==0)
707 	printf("\n");
708     }
709   printf("%g}\n\n", p[15]);
710 
711   printf("For Mathematica:\n\n");
712   printf("{");
713   for (i=0; i<15; )
714     {
715       if (i%4==0)
716 	printf("{");
717       printf("%f", p[i]);
718       i++;
719       if (i%4==0)
720 	printf("}, ");
721       else
722 	printf(", ");
723     }
724   printf("%f}}\n\n", p[15]);
725 
726 
727 }
728 
729 
730 
731 
732 
733 
734 
735 //----------------------------------------------------------------------
736 //
737 // This callback is called when the window is reshaped.
738 //
739 //----------------------------------------------------------------------
740 
reshape_window(int width,int height)741 void reshape_window(int width, int height)
742 {
743   glViewport(0, 0, (GLint)width, (GLint)height);
744 /*
745   glutPostRedisplay();
746 */
747 }
748 
749 
750 
751 
752 
753 
754 //----------------------------------------------------------------------
755 //
756 // Writing and reading the GL transformation matrices to and from
757 // files.
758 //
759 //----------------------------------------------------------------------
760 
write_gl_matrices(FILE * f)761 void write_gl_matrices(FILE *f)
762 {
763   int i, current_mode;
764   double p[16];
765 
766   glGetIntegerv(GL_MATRIX_MODE, &current_mode);
767 
768   fprintf(f, "GL_PROJECTION_MATRIX\n");
769   glGetDoublev(GL_PROJECTION_MATRIX, p);
770   for (i=0; i<16; i++)
771     fprintf(f, "%.15e\n", p[i]);
772 
773   fprintf(f, "GL_MODELVIEW_MATRIX\n");
774   glGetDoublev(GL_MODELVIEW_MATRIX, p);
775   for (i=0; i<16; i++)
776     fprintf(f, "%.15e\n", p[i]);
777 
778   glMatrixMode(current_mode);
779 }
780 
read_gl_matrices(FILE * f)781 void read_gl_matrices(FILE *f)
782 {
783   int i, current_mode;
784   double p[16];
785   char s[1000];
786 
787   glGetIntegerv(GL_MATRIX_MODE, &current_mode);
788 
789   fgets(s, 1000, f);
790   if (strcmp(s, "GL_PROJECTION_MATRIX\n")!=0)
791     CRIT_ERR(printf("Corrupt file contents? Read '%s'.\n", s));
792   for (i=0; i<16; i++)
793     fscanf(f, "%lf\n", p+i);
794   glMatrixMode(GL_PROJECTION_MATRIX);
795   glLoadMatrixd(p);
796 
797   fgets(s, 1000, f);
798   if (strcmp(s, "GL_MODELVIEW_MATRIX\n")!=0)
799     CRIT_ERR(printf("Corrupt file contents? Read '%s'.\n", s));
800   for (i=0; i<16; i++)
801     fscanf(f, "%lf\n", p+i);
802   glMatrixMode(GL_MODELVIEW_MATRIX);
803   glLoadMatrixd(p);
804 
805   glMatrixMode(current_mode);
806 }
807