sources:


website:
more info here


screenshot:
studies/grafik2/Computergrafik-Code9/Aufgabe25/cgtexture.cpp
download file

  1 //
  2 // Computergraphik II
  3 // Prof. Dr. Juergen Doellner
  4 // Wintersemester 2001/02
  5 //
  6 // Rahmenprogramm zu Aufgabenzettel 9
  7 //
  8
  9 #include "cgtexture.h"
 10 #include "vector.h"
 11 #include "noise.h"
 12
 13 #include <fstream.h>
 14 #include <stdio.h>
 15 #include "glext.h"
 16
 17 #ifndef APIENTRY
 18 #define WIN32_LEAN_AND_MEAN 1
 19 #include <windows.h>
 20 #endif /*APIENTRY*/
 21
 22 #ifdef _WIN32
 23
 24 /* This has already been done by glext.h */
 25 /*typedef void (APIENTRY* PFNGLTEXIMAGE3DEXTPROC)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *image);*/
 26
 27 PFNGLTEXIMAGE3DPROC glTexImage3D;
 28
 29 #endif _WIN32*/
 30
 31 int isExtensionSupported(const char *extension) {
 32     const GLubyte *extensions = NULL;
 33     const GLubyte *start;
 34     GLubyte *where, *terminator;
 35
 36     /* Extension names should not have spaces. */
 37     where = (GLubyte*) strchr(extension, ' ');
 38     if (where || *extension == '\0')
 39         return 0;
 40
 41     extensions = glGetString(GL_EXTENSIONS);
 42     /* It takes a bit of care to bew fol-proof about parsing the OpenGL extensions string. Donn't be fooled by sub-strings, etc. */
 43     start = extensions;
 44     for(;;) {
 45         where = (GLubyte*) strstr((const char*) start, extension);
 46         if (!where)
 47             break;
 48         terminator = where + strlen(extension);
 49         if (where == start ||*(where-1)==' ')
 50             if (*terminator == ' ' || *terminator == '\0')
 51                 return 1;
 52         start = terminator;
 53     }
 54     return 0;
 55 }
 56
 57 void buildAvailableExtensions() {
 58     // Beispiel zum Abfragen des Extensionstrings ing OpenGL:
 59     // int hasImaging = isExtensionSupported("GL_ARB_imaging");
 60     #ifdef _WIN32
 61         glTexImage3D = (PFNGLTEXIMAGE3DPROC)
 62         wglGetProcAddress("glTexImage3D");
 63     #endif
 64 };
 65
 66
 67 #ifndef PI
 68 const double PI = 3.14159265358979323846;
 69 #endif
 70
 71
 72 CGTexture::CGTexture() {
 73     run_ = false;
 74     zoom_ = 1.0;
 75     usetorus_ = true;
 76    
 77     texWidth_ = texHeight_ = texDepth_ = 64;
 78 }
 79
 80 CGTexture::~CGTexture() {
 81 }
 82
 83 void CGTexture::drawScene() {
 84
 85     glPushMatrix();
 86     glRotatef(200, 0.0, 1.0, 0.0);
 87     glRotatef(55,1,0,0);
 88     glScaled(zoom_, zoom_, zoom_);
 89
 90     glEnable(GL_TEXTURE_3D);
 91
 92     if (usetorus_)
 93     {
 94         // our oopy-doopy torus
 95         drawObject();
 96     }
 97     else     {
 98         // a simple quad to test the 3D texture
 99         static float depth = 0;
100         static float increment = 0.01;
101         glDisable(GL_LIGHTING);
102         glBegin(GL_QUADS);
103         glTexCoord3f(0,0,depth); glVertex3f(-1,-1,0);
104         glTexCoord3f(1,0,depth); glVertex3f(+1,-1,0);
105         glTexCoord3f(1,1,depth); glVertex3f(+1,+1,0);
106         glTexCoord3f(0,1,depth); glVertex3f(-1,+1,0);
107         glEnd();
108         glEnable(GL_LIGHTING);
109        
110         depth += increment;
111         if (depth < 0 || depth > 1)
112         {
113             increment = -increment;
114             depth += increment;
115         }
116     }
117    
118     glDisable(GL_TEXTURE_3D);
119     glPopMatrix();
120 }
121
122 void CGTexture::drawObject() {
123     // draw torus
124     glCallList(torus_);
125 }
126
127 void CGTexture::buildPatch(int detail) {
128     if (glIsList(torus_)) glDeleteLists(torus_, 1);
129     GLint i, j;
130     float theta1, phi1, theta2, phi2, rings, sides;
131     float v0[03], v1[3], v2[3], v3[3];
132     float t0[03], t1[3], t2[3], t3[3];
133     float n0[3], n1[3], n2[3], n3[3];
134     float innerRadius=0.4;
135     float outerRadius=0.8;
136     float scalFac;
137
138     rings = detail;
139     sides = 10;
140     scalFac=1/((outerRadius+innerRadius)*2);
141
142     glNewList(torus_, GL_COMPILE);
143     glBegin(GL_QUADS);
144    
145     for (i = 0; i < rings; i++) {
146         theta1 = (float)i * 2.0 * PI / rings;
147         theta2 = (float)(i + 1) * 2.0 * PI / rings;
148         for (j = 0; j < sides; j++) {
149             phi1 = (float)j * 2.0 * PI / sides;
150             phi2 = (float)(j + 1) * 2.0 * PI / sides;
151
152             v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1));
153             v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1));
154             v0[2] = innerRadius * sin(phi1);
155
156             v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1));
157             v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1));
158             v1[2] = innerRadius * sin(phi1);
159             v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2));
160             v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2));
161             v2[2] = innerRadius * sin(phi2);
162
163             v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2));
164             v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2));
165             v3[2] = innerRadius * sin(phi2);
166
167             n0[0] = cos(theta1) * (cos(phi1));
168             n0[1] = -sin(theta1) * (cos(phi1));
169             n0[2] = sin(phi1);
170
171             n1[0] = cos(theta2) * (cos(phi1));
172             n1[1] = -sin(theta2) * (cos(phi1));
173             n1[2] = sin(phi1);
174
175             n2[0] = cos(theta2) * (cos(phi2));
176             n2[1] = -sin(theta2) * (cos(phi2));
177             n2[2] = sin(phi2);
178
179             n3[0] = cos(theta1) * (cos(phi2));
180             n3[1] = -sin(theta1) * (cos(phi2));
181             n3[2] = sin(phi2);
182
183             t0[0] = v0[0]*scalFac + 0.5;
184             t0[1] = v0[1]*scalFac + 0.5;
185             t0[2] = v0[2]*scalFac + 0.5;
186
187             t1[0] = v1[0]*scalFac + 0.5;
188             t1[1] = v1[1]*scalFac + 0.5;
189             t1[2] = v1[2]*scalFac + 0.5;
190
191             t2[0] = v2[0]*scalFac + 0.5;
192             t2[1] = v2[1]*scalFac + 0.5;
193             t2[2] = v2[2]*scalFac + 0.5;
194
195             t3[0] = v3[0]*scalFac + 0.5;
196             t3[1] = v3[1]*scalFac + 0.5;
197             t3[2] = v3[2]*scalFac + 0.5;
198
199                 glNormal3fv(n3); glTexCoord3fv(t3); glVertex3fv(v3);
200                 glNormal3fv(n2); glTexCoord3fv(t2); glVertex3fv(v2);
201                 glNormal3fv(n1); glTexCoord3fv(t1); glVertex3fv(v1);
202                 glNormal3fv(n0); glTexCoord3fv(t0); glVertex3fv(v0);
203         }
204     }
205     glEnd();
206     glEndList();
207 }
208
209 //
210 // Einige nützliche Funktionen:
211 //
212
213 // distance from a point
214 inline float distance(float x, float y, float z, float cx, float cy, float cz) {
215   float dx = x-cx;
216   float dy = y-cy;
217   float dz = y-cz;
218   return sqrt(dx*dx + dy*dy + dz*dz);
219 }
220
221 // clamp x to be between a and b
222 inline float clamp(float x, float a, float b) {
223     return (x < a ? a : (x > b ? b : x));
224 }
225
226 inline float smoothstep(float a, float b, float x) {
227   if(x<=a) return 0.0;
228   if(x>=b) return 1.0;
229   x = (x-a)/(b-a); // normalized interval [0,1]
230   return x*x*(3-2*x);
231 }
232
233 // Spline Interpolation
234 Vector spline(float x, int nknots, Vector* knot) {
235     int span;
236     int nspans = nknots-3;
237
238     Vector c0,c1,c2,c3;
239
240     if(nspans<1) {
241         cout << "Error in spline function" << endl;
242         return NULL;
243     }
244
245     x=clamp(x,0,1)*nspans;
246     span = (int) x;
247     if(span >= nknots-3) span = nknots-3;
248     x-=span;
249    
250     // Horner
251     c3 = -0.5 * knot[span] + 1.5 * knot[1+span] - 1.5 * knot[2+span] + 0.5 * knot[3+span];
252     c2 =  1.0 * knot[span] - 2.5 * knot[1+span] + 2.0 * knot[2+span] - 0.5 * knot[3+span];
253     c1 = -0.5 * knot[span] + 0.0 * knot[1+span] + 0.5 * knot[2+span] + 0.0 * knot[3+span];
254     c0 =  0.0 * knot[span] + 1.0 * knot[1+span] + 0.0 * knot[2+span] + 0.0 * knot[3+span];
255
256     return ((c3*x + c2)*x + c1)*x + c0;
257 }
258
259 Vector mix(const Vector& color1, const Vector& color2, const float alpha)
260 {
261     return (1-alpha)*color1 + alpha*color2;
262 }
263
264
265 static Vector dark       = Vector(0.10, 0.10, 0.15);
266 static Vector bright     = Vector(0.95, 0.95, 0.95);
267 static Vector brown      = Vector(0.80, 0.65, 0.35);
268
269 void CGTexture::createNoiseTexture3D() {
270
271     int w = texWidth_;
272     int h = texHeight_;
273     int d = texDepth_;
274
275     // Notwendiger Aufruf zur Initialisierung der Hashtable-Struktur:
276     Noise::init();
277
278     GLubyte *img1 = new GLubyte[w * h * d * 3]; // 3D Textur I
279     GLubyte *img2 = new GLubyte[w * h * d * 3]; // 3D Textur II
280     GLubyte *img3 = new GLubyte[w * h * d * 3]; // 3D Textur III
281
282     //
283     // Generieren Sie eine 3D-Textur, die Marmor oder eine Steinstruktur simuliert
284     //
285     // Benutzen Sie die Perlin-Noise-Funktion: Noise::noise3(point) (!)
286     // ...
287     //
288     // Lassen Sie Ihrer Kreativitaet freien Lauf!
289     //
290    
291     cout << endl
292          <<"3x 3D Textures ("<<w<<"x"<<h<<"x"<<d<<" Texels, "<<w*h*d*3*3/1024<<" KBytes) "
293          << endl;
294
295     for (int x=0; x<w; x++)
296     {
297         for (int y=0; y<h; y++)
298             for (int z=0; z<d; z++)
299             {
300                 // texture offset
301                 const int baseoffset = 3 * (x*h*d + y*d +z);
302
303                 // little noise
304                 float point1[3];
305                 point1[0] = (4.0*x)/w;
306                 point1[1] = (4.0*y)/h;
307                 point1[2] = (4.0*z)/d;
308
309                 // little noise (differs from first one)
310                 float point2[3];
311                 point2[1] = (4.0*x)/w;
312                 point2[2] = (4.0*y)/h;
313                 point2[0] = (4.0*z)/d;
314
315                 // really noisy
316                 float point3[3];
317                 point3[1] = (16.0*x)/w;
318                 point3[2] = (16.0*y)/h;
319                 point3[0] = (16.0*z)/d;
320
321                 float persistence1 = 0.25;
322                 float persistence2 = 0.25;
323                 float noise1 = 0.0;
324                 float noise2 = 0.0;
325
326                 // 4 octaves
327                 for (int octave = 0; octave<4; octave++)
328                 {
329                     // brown marble's noise
330                     // shift point
331                     point1[0] += 0.4*cos(noise1);
332                     point1[1] += 0.4*sin(noise1+PI/2);
333                     // get noise
334                     float currentnoise1 = (Noise::noise3(point1)+0.5) * persistence1;
335                     noise1 += currentnoise1;
336                     // add a bit of noisy noise (?!)
337                     noise1 += 0.2 * Noise::noise3(point3) * persistence1;
338
339                     // dark marble's noise
340                     point2[0] += 0.4*cos(noise2);
341                     point2[1] += 0.4*sin(noise2+PI/2);
342                     // get noise
343                     float currentnoise2 = (Noise::noise3(point2)+0.5) * persistence2;
344                     noise2 += currentnoise2;
345                     // add a bit of noisy noise (?!)
346                     noise2 += 0.2 * Noise::noise3(point3) * persistence2;
347                 }
348
349                 // clamp noises
350                 if (noise1 < 0) noise1 = 0;
351                 if (noise1 > 1) noise1 = 1;
352                 if (noise2 < 0) noise2 = 0;
353                 if (noise2 > 1) noise2 = 1;
354
355                 // color
356                 Vector color(0,0,0);
357                
358                 // brown marble
359                 color = mix(bright, brown,  smoothstep(0.55, 0.60, noise1));
360                 color = mix(color,  bright, smoothstep(0.65, 0.68, noise1));
361
362                 // texture III: brown marble
363                 img3[baseoffset+0] = color[0]*255;
364                 img3[baseoffset+1] = color[1]*255;
365                 img3[baseoffset+2] = color[2]*255;
366
367                 // dark marble
368                 if (noise2 <= 0.55)
369                     color = mix(color, dark,  smoothstep(0.50, 0.52, noise2));
370                 if (noise2 >= 0.52)
371                     color = mix(dark,  color, smoothstep(0.52, 0.55, noise2));
372                
373                 // texture I: combined
374                 img1[baseoffset+0] = color[0]*255;
375                 img1[baseoffset+1] = color[1]*255;
376                 img1[baseoffset+2] = color[2]*255;
377
378                 // dark marble (for texture II)
379                 color = mix(bright, dark,   smoothstep(0.50, 0.52, noise2));
380                 color = mix(color,  bright, smoothstep(0.52, 0.55, noise2));
381
382                 // texture II: dark marble
383                 img2[baseoffset+0] = color[0]*255;
384                 img2[baseoffset+1] = color[1]*255;
385                 img2[baseoffset+2] = color[2]*255;
386             }
387
388         // show progress (1 point = ca. 10%)
389         if (x % 7 == 0)
390         {
391             cout << ".";
392             cout.flush();
393         }
394     }
395
396     // Textur parameter
397      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
398
399     glGenTextures(1, &texName1_);
400     glGenTextures(2, &texName2_);
401     glGenTextures(3, &texName3_);
402
403     // texture I
404     glBindTexture(GL_TEXTURE_3D, texName1_);
405
406     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
407     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
408     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
409     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
410     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,     GL_REPEAT);
411     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
412
413     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, img1);
414
415     // texture II
416     glBindTexture(GL_TEXTURE_3D, texName2_);
417
418     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
419     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
420     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
421     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
422     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,     GL_REPEAT);
423     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
424
425     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, img2);
426
427     // texture III
428     glBindTexture(GL_TEXTURE_3D, texName3_);
429
430     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
431     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
432     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,     GL_REPEAT);
433     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,     GL_REPEAT);
434     glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,     GL_REPEAT);
435     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
436
437     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, img3);
438
439     // activate texture I
440     glBindTexture(GL_TEXTURE_3D, texName1_);
441
442     delete[] img1;
443     delete[] img2;
444     delete[] img3;
445 }
446
447 void CGTexture::onInit() {
448     buildAvailableExtensions();
449     torus_ = glGenLists(1);
450     buildPatch(32);
451
452     // Prozedurale 3D Textur
453     createNoiseTexture3D();
454
455    
456     /* init light */
457     GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
458     GLfloat mat_shininess[] = { 25.0 };
459     GLfloat gray[] = { 0.6, 0.6, 0.6, 0.0 };
460     GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
461     GLfloat light_position[] = { 0.0, 3.0, 3.0, 0.0 };
462
463     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
464     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
465     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
466     glLightfv(GL_LIGHT0, GL_AMBIENT, gray);
467     glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
468     glLightfv(GL_LIGHT0, GL_SPECULAR, white);
469     glColorMaterial(GL_FRONT, GL_DIFFUSE);
470     glEnable(GL_COLOR_MATERIAL);
471     glEnable(GL_LIGHTING);
472     glEnable(GL_LIGHT0);
473
474     // Tiefen Test aktivieren
475     glEnable(GL_DEPTH_TEST);
476    
477     // Smooth Schattierung aktivieren
478     glShadeModel(GL_SMOOTH);
479    
480     // Projection
481     glMatrixMode(GL_PROJECTION);
482     gluPerspective(60.0, 1.0, 2.0, 50.0);   
483    
484     // LookAt
485     glMatrixMode(GL_MODELVIEW);
486     gluLookAt(
487         0.0, 0.0, 4.0,  // from (0,0,4)
488         0.0, 0.0, 0.0,  // to (0,0,0)
489         0.0, 1.0, 0.)
// up
490
491     glClearColor(1, 1, 1, 1);
492 }
493
494 void CGTexture::onSize(unsigned int newWidth,unsigned int newHeight) {         
495     width_ = newWidth;
496     height_ = newHeight;           
497     glMatrixMode(GL_PROJECTION);
498     glViewport(0, 0, width_ - 1, height_ - 1);       
499     glLoadIdentity();
500     gluPerspective(40.0,float(width_)/float(height_),2.0, 100.0);
501     glMatrixMode(GL_MODELVIEW);     
502 }
503
504 void CGTexture::onKey(unsigned char key) {
505     switch (key) {
506     case 27: { exit(0); break; }                       
507     case '+': { zoom_*= 1.1; break; }
508     case '-': { zoom_*= 0.9; break; }
509     case ' ': { run_ = !run_; break; }
510     case '1': { buildPatch(4); break; }
511     case '2': { buildPatch(8); break; }
512     case '3': { buildPatch(16); break; }
513     case '4': { buildPatch(32); break; }
514     case '5': { buildPatch(64); break; }
515     case '6': { buildPatch(128); break; }
516     case 't': { usetorus_ = !usetorus_; break; }
517     case 'q': { glBindTexture(GL_TEXTURE_3D, texName1_); break; }
518     case 'w': { glBindTexture(GL_TEXTURE_3D, texName2_); break; }
519     case 'e': { glBindTexture(GL_TEXTURE_3D, texName3_); break; }
520     }
521
522     onDraw();
523 }
524
525 void CGTexture::onIdle() {
526     if (run_) {
527         glRotatef(.5, 0.0, 1.0, 0.0);
528     }
529     onDraw();
530 }
531
532 void CGTexture::onDraw() {
533     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
534
535     drawScene();
536     swapBuffers();
537 }
538
539 // Hauptprogramm
540 int main(int argc, char* argv[]) {
541     // Erzeuge eine Instanz der Beispiel-Anwendung:
542     CGTexture sample;
543    
544     cout << "Tastenbelegung:" << endl          << "ESC Programm beenden" << endl          << "Leertaste Objekt drehen" << endl          << "+ Hineinzoomen" << endl          << "- Herauszoomen" << endl          << "t Torus oder Quadrat zeichnen" << endl          << "q gemischter Marmor" << endl          << "w schwarzer Marmor" << endl          << "e brauner Marmor" << endl          << "1-6 Tessellationsgrad des Torus (max=6)" << endl;
545
546     // Starte die Beispiel-Anwendung:
547     sample.start("Stephan Brumme, 702544", true, 256, 256);
548     return(0);
549 }
550