1 //
2 // Computergraphik II
3 // Prof. Dr. Juergen Doellner
4 // Wintersemester 2001/02
5 //
6 // Rahmenprogramm zu Aufgabenzettel 9
7 //
8
9 #include "cgprojtexture.h"
10 #include "vector.h"
11 #include <fstream.h>
12 #include <stdlib.h>
13
14 #ifndef M_PI
15 const double M_PI = 3.14159265358979323846;
16 #endif
17
18 const unsigned int BUF_SIZE = 1024;
19
20 CGProjTexture::CGProjTexture(char* filename) {
21 filename_ = filename;
22
23 run_ = false;
24 zoom_ = 0.16;
25
26 angle_ = 15.0;
27 radius_ = 4.0;
28 theta_ = 0.0;
29 phi_ = 0.0;
30 }
31
32 CGProjTexture::~CGProjTexture() {
33 }
34
35 void CGProjTexture::drawScene() {
36
37 // texture coordinate generation
38 static const GLfloat Splane[] = { 1, 0, 0, 0 };
39 static const GLfloat Tplane[] = { 0, 1, 0, 0 };
40 static const GLfloat Rplane[] = { 0, 0, 1, 0 };
41 static const GLfloat Qplane[] = { 0, 0, 0, 1 };
42 glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
43 glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
44 glTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
45 glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
46 glTexGenfv(GL_S, GL_EYE_PLANE, Splane);
47 glTexGenfv(GL_T, GL_EYE_PLANE, Tplane);
48 glTexGenfv(GL_R, GL_EYE_PLANE, Rplane);
49 glTexGenfv(GL_Q, GL_EYE_PLANE, Qplane);
50
51 // switch it on
52 glEnable(GL_TEXTURE_GEN_S);
53 glEnable(GL_TEXTURE_GEN_T);
54 glEnable(GL_TEXTURE_GEN_R);
55 glEnable(GL_TEXTURE_GEN_Q);
56
57 // Texturmatrix für projektive Textur einstellen
58 glMatrixMode(GL_TEXTURE);
59
60 // texture coordinates must be within [0,1]^2
61 glLoadIdentity();
62 glTranslatef(0.5, 0.5, 0.0);
63 glScalef (0.5,-0.5, 1.0);
64
65 // perspective projection
66 gluPerspective(angle_, 1, 1, 2*radius_);
67
68 // convert angles to radiant
69 const double theta = theta_ / 180*M_PI;
70 const double phi = phi_ / 180*M_PI;
71 // select view
72 gluLookAt(radius_*sin(theta)*cos(phi), radius_*sin(phi), radius_*cos(theta)*cos(phi), // from
73 0.0, 0.0, 0.0, // to
74 0.0, 1.0, 0.0);// up
75
76 // Texturierung einschalten
77 glEnable(GL_TEXTURE_2D);
78
79 glMatrixMode(GL_MODELVIEW);
80
81 // draw dino
82 glPushMatrix();
83 glScaled(zoom_, zoom_, zoom_);
84 drawObject();
85 glPopMatrix();
86
87 // gray cube
88 static float material_diffuse[] = {0.7, 0.8, 1.0, 1.0};
89 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_diffuse);
90 glCullFace(GL_FRONT);
91 glutSolidCube(3.0);
92 glCullFace(GL_BACK);
93 }
94
95 void CGProjTexture::drawObject() {
96 static float material_diffuse[] = {1.0, 0.6, 0.7, 1.0};
97 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_diffuse);
98
99 // create display list (done only once)
100 static GLuint cache = 0;
101 if (cache == 0) {
102 cache = glGenLists(1);
103 glNewList(cache, GL_COMPILE);
104 glMatrixMode(GL_MODELVIEW);
105 glPushMatrix();
106
107 ifstream s("triceratops.txt");
108 char buf[BUF_SIZE];
109
110 glBegin(GL_TRIANGLES);
111 Vector v[3];
112 while (!s.eof()) {
113 s >> buf;
114
115 while (s.good()) {
116 s >> v[0] >> v[1] >> v[2];
117 Vector n = (v[1]-v[0])*(v[2]-v[0]);
118 glNormal3dv(n.rep());
119 glVertex3dv(v[0].rep());
120 glVertex3dv(v[1].rep());
121 glVertex3dv(v[2].rep());
122 }
123 if (s.rdstate() & ios::failbit) {
124 s.clear(s.rdstate() & ~ios::failbit);
125 }
126 }
127 glEnd();
128 glPopMatrix();
129 glEndList();
130 }
131
132 // execute display list
133 glCallList(cache);
134 }
135
136 void CGProjTexture::readImage() {
137
138 char buf[BUF_SIZE];
139
140 // create input stream
141 ifstream in(filename_);
142 if(!in) {
143 cerr << "no ppm image" << endl;
144 exit(-1);
145 }
146
147 cout << "Reading image from file \"" << filename_ << "===>\<===" " << endl;
148
149 // PPM header
150 #ifdef _MSC_VER
151 in >> binary;
152 #endif
153
154 // Read "P6"
155 char ppm;
156 in >> ppm; if(!in.good() || ppm != 'P') { cerr << "ppm format error" << endl; }
157 in >> ppm; if(!in.good() || ppm != '6') { cerr << "ppm format error" << endl; }
158
159 // forward to next line
160 in.getline(buf, BUF_SIZE);
161
162 // normally read comments, but we assume that no comments are there
163 // in.getline(buf, BUF_SIZE);
164 // while (buf[0] == '#')
165 // in.getline(buf, BUF_SIZE);
166
167 // Read width and height
168 in >> texWidth_; if(!in.good()) { cerr << "ppm format error" << endl; }
169 in >> texHeight_; if(!in.good()) { cerr << "ppm format error" << endl; }
170
171 // Read 255
172 unsigned int res;
173 in >> res; if(!in.good() || res != 255) { cerr << "ppm format error" << endl; }
174
175 // forward to next line
176 in.getline(buf, BUF_SIZE);
177
178 image_ = new GLubyte [3 * texWidth_ * texHeight_];
179 in.read(image_, 3 * texWidth_ * texHeight_);
180 if(!in.good()) { cerr << "ppm format error" << endl; }
181
182 in.close();
183 }
184
185 void CGProjTexture::onInit() {
186
187 // Tiefen Test aktivieren
188 glEnable(GL_DEPTH_TEST);
189
190 // Smooth Schattierung aktivieren
191 glShadeModel(GL_SMOOTH);
192
193 // Culling aktivieren
194 glCullFace(GL_BACK);
195 glEnable(GL_CULL_FACE);
196
197 // Projection
198 glMatrixMode(GL_PROJECTION);
199 gluPerspective(40.0, 1.0, 1.0, 20.0);
200
201 // LookAt
202 glMatrixMode(GL_MODELVIEW);
203 gluLookAt(
204 0.0, 0.0, 4.0, // from (0,0,4)
205 0.0, 0.0, 0.0, // to (0,0,0)
206 0.0, 1.0, 0.); // up
207
208 glClearColor(0.9,0.9,0.9,1.0);
209
210 // Textur einlesen
211 readImage();
212 // Texturobjekt anlegen, Grundeinstellungen für projektive Textur festlegen
213
214 //////////////////////////////////
215 // create texture
216
217 // generate a unique ID
218 glGenTextures(1, &texName_);
219 // use this texture ID
220 glBindTexture(GL_TEXTURE_2D, texName_);
221
222 // don't repeat texture
223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
225 // use filter "linear" both for magnification and minification
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
228
229 // bind image to texture object
230 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth_, texHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, image_);
231
232 // texture blending
233 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
234
235 // OpenGL Lichtquellen
236 static GLfloat light_diffuse[] = {0.7, 0.7, 0.7, 1.0};
237 static GLfloat light_position1[] = {1.0, 0.5, 1.0, 0.0};
238 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
239 glLightfv(GL_LIGHT0, GL_POSITION, light_position1);
240 glEnable(GL_LIGHT0);
241
242 static GLfloat light_position2[] = {-0.5, -0.4, -1.0, 0.0};
243 glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
244 glLightfv(GL_LIGHT1, GL_POSITION, light_position2);
245 glEnable(GL_LIGHT1);
246 glEnable(GL_LIGHTING);
247 }
248
249 void CGProjTexture::onSize(unsigned int newWidth,unsigned int newHeight) {
250 width_ = newWidth;
251 height_ = newHeight;
252 glMatrixMode(GL_PROJECTION);
253 glViewport(0, 0, width_ - 1, height_ - 1);
254 glLoadIdentity();
255 gluPerspective(40.0,float(width_)/float(height_),1.0, 20.0);
256 glMatrixMode(GL_MODELVIEW);
257 }
258
259 void CGProjTexture::onKey(unsigned char key) {
260 switch (key) {
261 case 27: { exit(0); break; }
262 case '+': { zoom_*= 1.1; break; }
263 case '-': { zoom_/= 1.1; break; }
264 case ' ': { run_ = !run_; break; }
265 case 'w': { if (angle_ < 180) angle_ *= 1.05; break; }
266 case 'q': { if (angle_ > 0.001) angle_ /= 1.05; break; }
267 case 's': { theta_ += 2; if (theta_>=360) theta_-=360; break; }
268 case 'a': { theta_ -= 2; if (theta_<=0) theta_+=360; break; }
269 case 'x': { phi_ += 2; if (phi_>=90) phi_=90; break; }
270 case 'y': { phi_ -= 2; if (phi_<=-90) phi_=-90;break; }
271 }
272 onDraw();
273 }
274
275 void CGProjTexture::onIdle() {
276
277 if (run_) {
278 glRotatef(.5, 0.0, 1.0, 0.0);
279 }
280 onDraw();
281 }
282
283 void CGProjTexture::onDraw() {
284 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
285
286 drawScene();
287
288 swapBuffers();
289 }
290
291 // Hauptprogramm
292 int main(int argc, char* argv[]) {
293 // Erzeuge eine Instanz der Beispiel-Anwendung:
294 CGProjTexture sample("smily.ppm");
295
296 cout << "Tastenbelegung:" << endl
<< "ESC Programm beenden" << endl
<< "Leertaste Objekt drehen" << endl
<< "+ Hineinzoomen" << endl
<< "- Herauszoomen" << endl
<< "q Textur verkleinern" << endl
<< "w Textur vergroessern" << endl
<< "a Textur nach rechts schwenken" << endl
<< "s Textur nach links schwenken" << endl
<< "y Textur nach oben schwenken" << endl
<< "x Textur nach unten schwenken" << endl;
297
298 // Starte die Beispiel-Anwendung:
299 sample.start("Stephan Brumme, 702544", true, 512, 512);
300 return(0);
301 }
302