sources:


website:
more info here


screenshot:
studies/grafik2/Computergrafik-Code9/Aufgabe23/cgcontour.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 "cgcontour.h"
 10 #include "vector.h"
 11
 12
 13 // degree of tessellation
 14 const int    PATCHSIZE =  100;
 15 // range of x,z
 16 const double MINIMUM   = -2.0;
 17 const double MAXIMUM   = +2.0;
 18 const double SPAN      = MAXIMUM - MINIMUM;
 19 const double DELTA     = SPAN/(PATCHSIZE-1);
 20
 21 // store values of the function
 22 bool calculationdone = false;
 23 double arPatch[PATCHSIZE][PATCHSIZE];
 24 // correspending normals
 25 Vector arNormals[PATCHSIZE][PATCHSIZE];
 26
 27
 28
 29 CGContour::CGContour() {
 30     run_ = false;
 31     normals_ = false;
 32     zoom_ = 0.4;
 33 }
 34
 35 CGContour::~CGContour() {
 36
 37
 38 void CGContour::drawScene() {
 39
 40     glPushMatrix();
 41
 42         glRotated(30, 1.0, 0.0, 0.0);
 43         glScaled(zoom_, zoom_, zoom_);
 44
 45         // Achsen
 46         glLineWidth(3.0);
 47         glColor3f(0.0, 0.0, 0.0);
 48        
 49         glDisable(GL_LIGHTING);
 50         glBegin(GL_LINES);
 51         glVertex3f( 0.0, 0.0, 0.0);
 52         glVertex3f( 3.0, 0.0, 0.0);
 53         glVertex3f( 0.0, 0.0, 0.0);
 54         glVertex3f( 0.0, 6.0, 0.0);
 55         glVertex3f( 0.0, 0.0, 0.0);
 56         glVertex3f( 0.0, 0.0, 3.0);
 57         glEnd();
 58         glEnable(GL_LIGHTING);
 59
 60         // Licht 1
 61         static GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};      // diffuse light
 62         static GLfloat light_position[]= {0.0, 1.0, 0.0, 0.0};      // infinite light location
 63            
 64         glLightfv(GL_LIGHT1, GL_DIFFUSE,  light_diffuse );
 65         glLightfv(GL_LIGHT1, GL_POSITION, light_position);
 66
 67         // Funktion
 68         drawFunction();
 69
 70     glPopMatrix();
 71 }
 72
 73 void CGContour::drawFunction() {
 74     // Hier die Funktion zeichnen.
 75
 76     // perform calculation only once
 77     if (!calculationdone)
 78     {
 79         for (int x=0; x<PATCHSIZE; x++)
 80             for (int z=0; z<PATCHSIZE; z++)
 81             {
 82                 const double x_coord = MINIMUM + x*DELTA;
 83                 const double z_coord = MINIMUM + z*DELTA;
 84
 85                 // f(x,z) = x^2 - z^2
 86                 arPatch[x][z]   = x_coord*x_coord - z_coord*z_coord;
 87
 88                 // f(x,z)/dx = 2x-z^2
 89                 // f(x,z)/dz = x^2-2z
 90                 // normal = crossproduct((0,f/dz,1), (1,f/dx,0))
 91                 arNormals[x][z] = (Vector(0, x_coord*x_coord-2*z_coord, 1) *
 92                                    Vector(1, 2*x_coord-z_coord*z_coord, 0))
.normalized();
 93             }
 94
 95         // function doesn't change
 96         calculationdone = true;
 97     }
 98
 99     // define texture projection plane (object space !)
100     static GLfloat xz_plane[] = { 0.0, 1.0, 0.0, 0.0 };
101     glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
102     glTexGenfv(GL_S, GL_OBJECT_PLANE, xz_plane);
103    
104     // enable automatic 1D texturing
105     glEnable(GL_TEXTURE_GEN_S);
106     glEnable(GL_TEXTURE_1D);
107
108     // display function
109     for (int x=1; x<PATCHSIZE; x++)
110     {
111         // one triangle strip per row
112         glBegin(GL_TRIANGLE_STRIP);
113
114         // draw one row (as a triangle strip)
115         for (int z=0; z<PATCHSIZE; z++)
116         {
117             const double x_coord = MINIMUM + x*DELTA;
118             const double z_coord = MINIMUM + z*DELTA;
119
120             // left border of the row
121             glNormal3dv(arNormals[x-1][z].rep());
122             glVertex3d(x_coord-DELTA, arPatch[x-1][z], z_coord);
123
124             // right border of the row
125             glNormal3dv(arNormals[x  ][z].rep());
126             glVertex3d(x_coord      , arPatch[x  ][z], z_coord);
127         }
128
129         glEnd();
130     }
131     glDisable(GL_TEXTURE_1D);
132
133     // draw normals if necessary
134     if (normals_)
135     {
136         // no lighting
137         glDisable(GL_LIGHTING);
138
139         // draw all normals
140         for (x=1; x<PATCHSIZE; x++)
141         {
142             glLineWidth(1);
143             glColor3f(1,0,0);
144             glBegin(GL_LINES);
145
146             for (int z=0; z<PATCHSIZE; z++)
147             {
148                 const double x_coord = MINIMUM + x*DELTA;
149                 const double z_coord = MINIMUM + z*DELTA;
150
151                 // short normals for better visualization
152                 Vector normal = arNormals[x][z] * 0.2;
153
154                 glVertex3d(x_coord, arPatch[x][z], z_coord);
155                 glVertex3d(x_coord+normal[0], arPatch[x][z]+normal[1], z_coord+normal[2]);
156             }
157
158             glEnd();
159         }
160         glEnable(GL_LIGHTING);
161     }
162 }
163
164 void CGContour::createTexture() {
165     // prozedural eine Textur erzeugen
166     for (int i=0; i<TEXTURE_SIZE; i++)
167     {
168         image_[i*3+0] = 100;
169         image_[i*3+1] = (i*255)/TEXTURE_SIZE;
170         image_[i*3+2] = 100;
171     }
172
173     // represents y = -2, -1, 0, +1, +2 etc.
174     image_[0] = image_[1] = image_[2] = 255;
175
176
177     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
178
179     // generate a unique ID
180     glGenTextures  (1, &texName_);
181     // use this texture ID
182     glBindTexture  (GL_TEXTURE_1D, texName_);
183
184     // repeat texture if necessary
185     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
186     // use filter "linear" both for magnification and minification
187     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
188     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
189     glTexEnvf      (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,  GL_MODULATE);
190     // bind image to texture object
191     glTexImage1D   (GL_TEXTURE_1D, 0, GL_RGB, TEXTURE_SIZE,
192                                    0, GL_RGB, GL_UNSIGNED_BYTE, image_)
;
193 }
194
195 void CGContour::onInit() {
196    
197     // Tiefen Test aktivieren
198     glEnable(GL_DEPTH_TEST);
199    
200     // Smooth Schattierung aktivieren
201     glShadeModel(GL_SMOOTH);
202    
203     // Projection
204     glMatrixMode(GL_PROJECTION);
205     gluPerspective(40.0, 1.0, 1.0, 20.0);   
206    
207     // LookAt
208     glMatrixMode(GL_MODELVIEW);
209     gluLookAt(
210         0.0, 0.0, 4.0,  // from (0,0,4)
211         0.0, 0.0, 0.0,  // to (0,0,0)
212         0.0, 1.0, 0.)
// up
213    
214     glClearColor(0.8, 0.9, 1.0, 0.0);
215
216     createTexture();
217
218     // set lights
219     static GLfloat light_position[]= {0.0, 0.0, 1.0, 0.0};
220     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
221
222     glEnable(GL_LIGHT0); light0_ = true;
223     glEnable(GL_LIGHT1); light1_ = true;
224
225     glEnable(GL_LIGHTING);
226
227     static float material_diffuse[]= {0.6, 0.6, 0.6, 1.0};
228     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_diffuse);
229 }
230
231 void CGContour::onSize(unsigned int newWidth,unsigned int newHeight) {         
232     width_ = newWidth;
233     height_ = newHeight;           
234     glMatrixMode(GL_PROJECTION);
235     glViewport(0, 0, width_ - 1, height_ - 1);       
236     glLoadIdentity();
237     gluPerspective(40.0,float(width_)/float(height_),2.0, 100.0);
238     glMatrixMode(GL_MODELVIEW);     
239 }
240
241 void CGContour::onKey(unsigned char key) {
242     switch (key) {
243     case 27: { exit(0); break; }                       
244     case '+': { zoom_*= 1.1; break; }
245     case '-': { zoom_/= 1.1; break; }
246     case ' ': { run_ = !run_; break; }
247     case '1': { if (light0_) glDisable(GL_LIGHT0);
248                 else         glEnable (GL_LIGHT0);
249                 light0_ = !light0_;
250                 break; };
251     case '2': { if (light1_) glDisable(GL_LIGHT1);
252                 else         glEnable (GL_LIGHT1);
253                 light1_ = !light1_;
254                 break; };
255     case 'n': { normals_ = !normals_; break; }
256     }
257     onDraw();
258 }
259
260 void CGContour::onIdle() {
261
262     if (run_) {
263         glRotatef(.5, 0.0, 1.0, 0.0);
264     }
265     onDraw();
266 }
267
268 void CGContour::onDraw() {
269     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
270
271     drawScene();
272
273     swapBuffers();
274 }
275
276 // Hauptprogramm
277 int main(int argc, char* argv[]) {
278     // Erzeuge eine Instanz der Beispiel-Anwendung:
279     CGContour sample;
280    
281     cout << "Tastenbelegung:" << endl          << "ESC Programm beenden" << endl          << "Leertaste Objekt drehen" << endl          << "1 starre Lichtquelle an/aus" << endl          << "2 rotierende Lichtquelle an/aus" << endl          << "+ Hineinzoomen" << endl          << "- Herauszoomen" << endl          << "n Normalen zeichnen an/aus" << endl;
282
283     // Starte die Beispiel-Anwendung:
284     sample.start("Stephan Brumme, 702544", true, 512, 512);
285     return(0);
286 }
287