1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 // FIXME: not in use yet. 19990620 mortene.
34 
35 #include <math.h>
36 #include <limits.h>
37 #include <stdlib.h>
38 #include <assert.h>
39 
40 #include <GL/glaux.h>
41 
42 #include <Inventor/SbColor.h>
43 #include <Inventor/nodes/SoMaterial.h>
44 #include <Inventor/fields/SoMFColor.h>
45 
46 #include <soqtdefs.h>
47 #include <Inventor/Qt/editors/SoGLMaterialSphere.h>
48 
49 
50 #define NUM_POINTS 10000
51 #define BG_COLOR 0.5f, 0.5f, 0.5f, 0.0f
52 #define BG_COLOR2 0.4f, 0.4f, 0.4f, 1.0f
53 
54 #define FLAT_SHADING
55 
56 
57 #ifndef _GCC_
58 # define true TRUE
59 # define false FALSE
60 #endif
61 
62 #ifdef WIN32
63 #define random() rand()
64 #pragma warning(once: 4305)
65 #endif
66 
67 //
68 // first some data for a Icosahedron (sphere with 20 faces)
69 //
70 #define X .525731112119133606
71 #define Z .850650808352039932
72 
73 static float vdata[12][3] =
74 {
75   {-X, 0, Z}, {X, 0, Z}, {-X, 0, -Z}, {X, 0, -Z},
76   {0, Z, X}, {0, Z, -X}, {0, -Z, X}, {0, -Z, -X},
77   {Z, X, 0}, {-Z, X, 0}, {Z, -X, 0}, {-Z, -X, 0}
78 };
79 
80 static int tindices[20][3] = {
81   {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
82   {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
83   {7,10,3,}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
84   {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}};
85 
86 //
87 // normalize a vector
88 //
normalize(float * v)89 void normalize(float *v)
90 {
91   float d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
92   if (d == 0.0f) return;
93   d = 1.0f / d;
94   v[0] *= d;
95   v[1] *= d;
96   v[2] *= d;
97 }
98 
99 //
100 // the average of three vectors
101 //
average_vector(float * v,float * v1,float * v2,float * v3)102 void average_vector(float *v, float *v1, float *v2, float *v3)
103 {
104   for (int i = 0; i < 3; i++)
105     v[i] = v1[i] + v2[i] + v3[i];
106   normalize(v);
107 }
108 
109 //
110 // draws a triangle using OpenGL. Assumes glBegin(GL_TRIANGLES)
111 // has been called.
112 //
drawtriangle(float * v1,float * v2,float * v3)113 void drawtriangle(float *v1, float *v2, float *v3)
114 {
115 #if defined(FLATSHADING)
116   float v[3];
117   average_vector(v, v1, v2, v3);
118   glNormal3fv(v);
119   glVertex3fv(v1);
120   glVertex3fv(v2);
121   glVertex3fv(v3);
122 #else
123   glNormal3fv(v1); glVertex3fv(v1);
124   glNormal3fv(v2); glVertex3fv(v2);
125   glNormal3fv(v3); glVertex3fv(v3);
126 #endif
127 }
128 
129 //
130 // subdivide this triangle into smaller triangles until depth = 0
131 //
subdivide(float * v1,float * v2,float * v3,int depth)132 void subdivide(float *v1, float *v2, float *v3, int depth)
133 {
134   float v12[3], v23[3], v31[3];
135   int i;
136 
137   if (depth == 0) {
138     drawtriangle(v1, v2, v3);
139     return; // end recursion
140   }
141   for (i = 0; i < 3; i++) {
142     v12[i] = v1[i] + v2[i];
143     v23[i] = v2[i] + v3[i];
144     v31[i] = v3[i] + v1[i];
145   }
146   normalize(v12);
147   normalize(v23);
148   normalize(v31);
149 
150   // continue recursion
151   subdivide(v1, v12, v31, depth-1);
152   subdivide(v2, v23, v12, depth-1);
153   subdivide(v3, v31, v23, depth-1);
154   subdivide(v12, v23, v31, depth-1);
155 }
156 
157 //
158 // draws a sphere with resolution (number of subdivisions) depth.
159 //
draw_sphere(int depth)160 void draw_sphere(int depth)
161 {
162   glBegin(GL_TRIANGLES);
163   for (int i = 0; i < 20; i++) {
164     subdivide(&vdata[tindices[i][0]][0],
165               &vdata[tindices[i][1]][0],
166               &vdata[tindices[i][2]][0], depth);
167   }
168   glEnd();
169 }
170 
171 
SoGLMaterialSphere(QWidget * parent,const char * name)172 SoGLMaterialSphere::SoGLMaterialSphere(QWidget *parent, const char *name)
173 : QGLWidget(parent, name)
174 {
175   material = NULL;
176   doRepaint = true;
177   makeCurrent();
178   QGLFormat format;
179   format.setRgba(TRUE);
180   format.setDepth(TRUE);
181   this->setFormat(format);
182   initializeGL();
183 }
184 
paintGL()185 void SoGLMaterialSphere::paintGL()
186 {
187   glClearColor(BG_COLOR);
188   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
189   drawBackground();
190   drawSphere();
191 }
192 
resizeGL(int w,int h)193 void SoGLMaterialSphere::resizeGL(int w, int h)
194 {
195   printf("resizegl: %d %d\n", w, h);
196   glViewport(0, 0, w, h);
197   glMatrixMode(GL_PROJECTION);
198   glLoadIdentity();
199   if (w <= h)
200     glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
201             1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
202   else
203     glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
204             1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
205 
206   glMatrixMode(GL_MODELVIEW);
207   glLoadIdentity();
208   initializeGL();
209   paintGL();
210 }
211 
212 
initializeGL()213 void SoGLMaterialSphere::initializeGL()
214 {
215   printf("initGL\n");
216 #define SPOT_LIGHT
217 #ifdef SPOT_LIGHT
218   static float light0_pos[4] = { -1.0, 1.5, 1.5, 0.0 };
219   static float light1_pos[4] = { 1.0, 1.5, 1.5, 0.0 };
220 #else
221   static float light0_pos[4] = { -2.0, 0.5, 1.5, 1.0 };
222   static float light1_pos[4] = { 2.0, 0.5, 1.5, 1.0 };
223 #endif
224   static float specular[] = { 1.0, 1.0, 1.0, 1.0 };
225   static float spotDir0[] = { 0.9, -1.5, -1.5 , 1.0 };
226   static float spotDir1[] = { -0.9, -1.5, -1.5 , 1.0 };
227 
228 //  glColor3f(0.0, 0.0, 0.7);
229 //  glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, &0.5);
230 //  glLightfv(GL_LIGHT1, GL_AMBIENT, &0.0);
231 //  glEnable(GL_LIGHT1);
232   glEnable(GL_DEPTH_TEST);
233   glEnable(GL_NORMALIZE);
234   glEnable(GL_BLEND);
235 
236   glDepthFunc(GL_LEQUAL);
237   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
238   glEnable(GL_CULL_FACE);
239   glFrontFace(GL_CW);
240 
241   glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
242   glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
243 
244   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
245   glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
246 
247 #ifdef SPOT_LIGHT
248   glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 10.0f);
249   glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 100.0f);
250   glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 10.0f);
251   glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 100.0f);
252 
253   glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDir0);
254   glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spotDir1);
255 #endif
256 
257 
258   glEnable(GL_LIGHTING);
259   glEnable(GL_LIGHT0);
260   glEnable(GL_LIGHT1);
261 }
262 
drawBackground()263 void SoGLMaterialSphere::drawBackground()
264 {
265 
266   glColor4f(BG_COLOR2);
267   glDisable(GL_LIGHTING);
268   glBegin(GL_QUADS);
269         glVertex3f(-1.5,  1.5, -1.0);
270         glVertex3f(0.0,  1.5, -1.0);
271         glVertex3f(0.0,  0.0, -1.0);
272         glVertex3f(-1.5,  0.0, -1.0);
273         glVertex3f(0.0,  0.0, -1.0);
274         glVertex3f(1.5,  0.0, -1.0);
275         glVertex3f(1.5, -1.5, -1.0);
276         glVertex3f(0.0, -1.5, -1.0);
277   glEnd();
278   glEnable(GL_LIGHTING);
279 }
280 
drawSphere()281 void SoGLMaterialSphere::drawSphere()
282 {
283 #if 0
284   float *point;
285   point = new float[3 * NUM_POINTS];
286   calculateSpherePoints(point, NUM_POINTS);
287   glClearColor(0.0, 0.0, 0.0, 0.0);
288   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
289   glBegin(GL_POINTS);
290         for (int i = 0; i < NUM_POINTS; i++)
291                 glVertex3f(point[i*3],point[i*3+1],point[i*3+2]);
292   glEnd();
293   delete [] point;
294 #else
295   glLoadIdentity();
296   glTranslatef(0,0,-5);
297   draw_sphere(2);
298   glFlush();
299 #endif
300 }
301 
calculateSpherePoints(float * points,int max_points)302 void SoGLMaterialSphere::calculateSpherePoints(float *points, int max_points)
303 {
304   float theta, angle2;
305   int i, pos;
306   /*
307    * Generate random point on the surface of a sphere
308    */
309   for (i = 0, pos = 0;i < max_points; i++, pos+=3)
310   {
311     theta = acos(1.0 - 2.0*(float)random()/(float)LONG_MAX);
312     angle2 = 2.0*M_PI*(float)random()/(float)LONG_MAX;
313     points[pos]   = sin(theta)*cos(angle2);
314     points[pos+1] = sin(theta)*sin(angle2);
315     points[pos+2] = cos(theta);
316   }
317 }
318 
319 #if 1
320 #define CopyColor(color)                                                \
321         color##Light[0] = material->color##Color.getValues(0)[0].getValue()[0];                 \
322         color##Light[1] = material->color##Color.getValues(0)[0].getValue()[1];                 \
323         color##Light[2] = material->color##Color.getValues(0)[0].getValue()[2];                 \
324         color##Light[3] = material->transparency.getValues(0)[0];
325 #else
326 #define CopyColor(color)
327 #endif
328 
setAmbient(float val)329 void SoGLMaterialSphere::setAmbient(float val)
330 {
331   assert(material);
332   printf("setAmbient(%f)\n", val);
333 //  memcpy(ambientLight, material->ambientColor.values, 3 * sizeof(float));
334 //  ambientLight[0] = material->ambientColor;
335 
336 
337   CopyColor(ambient);
338 
339   fprintf(stderr, "ambientLight = [%f,%f,%f,%f]\n", ambientLight[0],ambientLight[1],ambientLight[2],ambientLight[3]);
340   ambientLight[0] *= val;
341   ambientLight[1] *= val;
342   ambientLight[2] *= val;
343 //  ambientLight[3] *= val;
344 
345 //  glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
346  // glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight);
347 
348   glMaterialfv(GL_FRONT, GL_AMBIENT, ambientLight);
349 
350   if (doRepaint) repaint(false);
351 }
352 
setDiffuse(float val)353 void SoGLMaterialSphere::setDiffuse(float val)
354 {
355   assert(material);
356 //  memcpy(diffuseLight, material->diffuseColor.values, 3 * sizeof(float));
357   CopyColor(diffuse);
358   diffuseLight[0] *= val;
359   diffuseLight[1] *= val;
360   diffuseLight[2] *= val;
361   printf("diffuseLight[] = %f, %f, %f, %f\n", diffuseLight[0], diffuseLight[1],
362         diffuseLight[2], diffuseLight[3]);
363 
364 //  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
365 //  glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight);
366   glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseLight);
367   if (doRepaint) repaint(false);
368 }
369 
setSpecular(float val)370 void SoGLMaterialSphere::setSpecular(float val)
371 {
372 
373   printf("setSpecular(%f)\n", val);
374   assert(material);
375 //  memcpy(specularLight, material->specularColor.values, 3 * sizeof(float));
376   CopyColor(specular);
377   specularLight[0] *= val;
378   specularLight[1] *= val;
379   specularLight[2] *= val;
380 
381 //  glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
382 //  glLightfv(GL_LIGHT1, GL_SPECULAR, specularLight);
383 
384   glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
385   if (doRepaint) repaint(false);
386 }
387 
setEmission(float val)388 void SoGLMaterialSphere::setEmission(float val)
389 {
390   /* */
391   printf("setEmission(%f)\n", val);
392   assert(material);
393   float emissiveLight[4];
394 //  memcpy(emission, material->emissiveColor.values, 3 * sizeof(float));
395   CopyColor(emissive);
396   emissiveLight[0] *= val;
397   emissiveLight[1] *= val;
398   emissiveLight[2] *= val;
399   glMaterialfv(GL_FRONT, GL_EMISSION, emissiveLight);
400   if (doRepaint) repaint(false);
401 }
402 
setShininess(float val)403 void SoGLMaterialSphere::setShininess(float val)
404 {
405   printf("setShininess %f (%f)\n", val, (1.0f - val) * 128.0f);
406   glMaterialf(GL_FRONT, GL_SHININESS, (1.0f - val) * 128.0f);
407   if (doRepaint) repaint(false);
408 }
409 
setTransparency(float val)410 void SoGLMaterialSphere::setTransparency(float val)
411 {
412   printf("setTransparency(%f)\n", val);
413   assert(material);
414 
415   material->transparency = /*.setValue*/ (1.0f - val);
416 
417   setDiffuse(1.0f);
418 
419 //  repaint(false);
420 }
421 
setMaterial(SoMaterial * mat)422 void SoGLMaterialSphere::setMaterial(SoMaterial *mat)
423 {
424   material = mat;
425   if (doRepaint) repaint(false);
426 }
427 
repaintSphere()428 void SoGLMaterialSphere::repaintSphere()
429 {
430   repaint(false);
431 }
432 
setRepaint(bool whatever)433 void SoGLMaterialSphere::setRepaint(bool whatever)
434 {
435   doRepaint = whatever;
436 }
437