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