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