sources:
cgapplication.cpp (3.2k)
cgapplication.h (3.5k)
cgtexture.cpp (15.9k)
cgtexture.h (1.1k)
glext.h (143.4k)
noise.cpp (3.9k)
noise.h (414 bytes)
vector.cpp (1.4k)
vector.h (4.9k)


binaries:
Release/texture.exe (30.0k)


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