sources:


website:
more info here


screenshot:
studies/grafik2/Computergrafik-Code8/Aufgabe22/cgtwopart.cpp
download file

  1 //
  2 // Computergraphik II
  3 // Prof. Dr. Juergen Doellner
  4 // Wintersemester 2001/02
  5 //
  6 // Rahmenprogramm zu Aufgabenzettel 8
  7 //
  8
  9 #include "cgtwopart.h"
 10 #include <fstream.h>
 11
 12 typedef Vector Camera;
 13 typedef Vector Color;
 14
 15 #ifndef PI
 16 const double PI = 3.14159265358979323846;
 17 #endif
 18
 19 const unsigned int BUF_SIZE = 1024;
 20
 21 //
 22 // Application
 23 //
 24
 25 CGTwoPart::CGTwoPart(char* filename) {
 26     filename_ = filename;
 27    
 28     stop_=true;
 29     zoom_= 1.5;
 30     mapping_ = SPHERE_INTERSECTION;
 31    
 32     // read triangle data
 33     ifstream s("triceratops.txt");   
 34     // ifstream s("triangle_small.txt");
 35     s >> size_;
 36    
 37     tris_ = new Triangle[size_];
 38     center_ = Vector(0,0,0);
 39
 40     int i;
 41     for (i = 0; i < size_; i++) {
 42         s >> tris_[i];
 43
 44         // just scale object
 45         tris_[i].setVertex(0, tris_[i].getVertex(0) * 0.1);
 46         tris_[i].setVertex(1, tris_[i].getVertex(1) * 0.1);
 47         tris_[i].setVertex(2, tris_[i].getVertex(2) * 0.1);
 48
 49         // add up all vectors
 50         center_ += tris_[i].getVertex(0);
 51         center_ += tris_[i].getVertex(1);
 52         center_ += tris_[i].getVertex(2);
 53     }       
 54
 55     center_ *= 1/(3.0*size_);
 56 }
 57
 58
 59 CGTwoPart::~CGTwoPart() {   
 60 }
 61
 62
 63
 64 void CGTwoPart::onInit() {
 65    
 66     // Tiefen Test aktivieren
 67     glEnable(GL_DEPTH_TEST);
 68    
 69     // Smooth Schattierung aktivieren
 70     glShadeModel(GL_SMOOTH);
 71    
 72     // Projection
 73     glMatrixMode(GL_PROJECTION);
 74     gluPerspective(60.0, 1.0, 2.0, 50.0);   
 75    
 76     // LookAt
 77     glMatrixMode(GL_MODELVIEW);
 78     gluLookAt(
 79         0.0, 0.0, 4.0,  // from (0,0,4)
 80         0.0, 0.0, 0.0,  // to (0,0,0)
 81         0.0, 1.0, 0.)
// up
 82    
 83     glClearColor(0.9,0.9,0.9,1.0);
 84
 85     // Import texture from file
 86     readImage();
 87
 88     glGenTextures(1, &texName_);
 89     glBindTexture(GL_TEXTURE_2D, texName_);
 90
 91     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 92     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 93     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 94     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 95     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth_, texHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, image_);
 96 }
 97
 98 void CGTwoPart::onSize(unsigned int newWidth,unsigned int newHeight) {     
 99     if((newWidth > 0) && (newHeight > 0)) {
100         // Passe den OpenGL-Viewport an die neue Fenstergroesse an:
101         glViewport(0, 0, newWidth - 1, newHeight - 1);
102        
103         // Passe die OpenGL-Projektionsmatrix an die neue
104         // Fenstergroesse an:
105         glMatrixMode(GL_PROJECTION);
106         glLoadIdentity();
107         gluPerspective(40.0,float(newWidth)/float(newHeight),1.0, 10.0);       
108        
109         // Schalte zurueck auf die Modelview-Matrix
110         glMatrixMode(GL_MODELVIEW);   
111     }
112 }
113
114 void CGTwoPart::onKey(unsigned char key) {
115     static GLfloat z = 3.;
116     switch (key) {
117     case 27: { exit(0); break; }               
118     case '+': { zoom_*= 1.1; break; }
119     case '-': { zoom_*= 0.9; break; }
120     case 'l' : { glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; }
121     case 'f' : { glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; }
122     case 'c' : { if (glIsEnabled(GL_CULL_FACE)) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } break; }
123     case 'q' : { mapping_ = SPHERE_INTERSECTION; break; }
124     case 'w' : { mapping_ = SPHERE_NORMAL; break; }
125     case 'e' : { mapping_ = CYLINDER_INTERSECTION; break; }
126     case 'r' : { mapping_ = CYLINDER_NORMAL; break; }
127     case ' ' : { stop_ = !stop_; break; } 
128     }
129     onDraw();
130 }
131
132 void CGTwoPart::onIdle() {
133     if (!stop_) {
134         glRotatef(-2.0f,0,1,0.1);
135         onDraw();
136     }
137 }
138
139 inline double max(double x, double y) {
140     return (x<y) ? y : x;
141 }
142 inline double min(double x, double y) {
143     return (x>y) ? y : x;
144 }
145
146 Vector CGTwoPart::SphereIntersection(const Vector& point) const {
147     // code taken from ray-sphere intersection of my raytracer
148
149     // ray origin
150     const Vector origin(center_);
151     const double x = origin[0];
152     const double y = origin[1];
153     const double z = origin[2];
154
155     // ray direction
156     const Vector direction(point-center_);
157     const double i = direction[0];
158     const double j = direction[1];
159     const double k = direction[2];
160
161     // sphere's center
162     const double r = 1.0;
163
164     // compute parameters a,b,c for at^2+bt+c=0
165     const double a = i*i + j*j + k*k;
166     const double b = 2*(i*x + j*y + k*z);
167     const double c = x*x+y*y+z*z - r*r;
168
169     // solve at^2+bt+c=0
170     // D = b^2-4ac
171     const double D = b*b-4*a*c;
172
173
174     // no intersection
175     if (D < 0)
176         return Vector(0,0,0);
177
178     // nearest ray intersection
179     double t;
180
181     if (D > 0)
182     {
183         // two intersections
184         // ray parameter
185         const double t1 = (-b + sqrt(D))/(2*a);
186         const double t2 = (-b - sqrt(D))/(2*a);
187         t = min(t1,t2);
188         if (t < 0)
189             t = max(t1,t2);
190     }
191     else         // only one intersection
192         t = -b/(2*a);
193
194     return SphereSurfaceToTexture(origin + t*direction);
195 }
196
197 Vector CGTwoPart::SphereNormal(const Vector& point) const {
198     return SphereSurfaceToTexture(point.normalized());
199 }
200
201 Vector CGTwoPart::SphereSurfaceToTexture(const Vector& surface) const {
202     const double x_distortion = sin(acos(surface[1]));
203
204     // first texture coordinate
205     double s = 1.0;
206     if (x_distortion != 0.0)
207     {
208         s = acos(surface[0] / x_distortion) / (2*PI);
209         if (surface[2] > 0.0)
210             s = 1-s;
211     }
212
213     // rotate by 180°
214     s += 0.5;
215     if (s > 1)
216         s -= 1;
217
218     // second texture coordinate
219     double t = acos(surface[1]) / PI;
220    
221     return Vector(s,t);
222 }
223
224 Vector CGTwoPart::CylinderIntersection(const Vector& point) const {
225     // radius
226     const double r = 0.5;
227
228     // origin of line
229     const double x = center_[0];
230     const double z = center_[2];
231
232     // direction
233     const double i = point[0]    - x;
234     const double j = point[2]    - z;
235
236     // no degenerated lines
237     if (i==0 && j==0)
238         return Vector(0,0,0);
239
240     // 0 = tē+pt+q
241     const double p = 2*(i*x+j*z) / (i*i+j*j);
242     const double q = (x*x+z*z-r*r) / (i*i+j*j);
243    
244     // square root
245     const double D = (p*p/4)-q;
246     // no solution
247     if (D < 0)
248         return Vector(0,0,0);
249
250     // t1 may be equal to t2 but that doesn't matter
251     const double t1 = -p/2 + sqrt(D);
252     const double t2 = -p/2 - sqrt(D);
253
254     // nearest intersetion
255     double intersect = min(t1,t2);
256     if (intersect < 0)
257         intersect = max(t1,t2);
258
259     // move point to the cylinder's surface and get texture coordinates
260     return CylinderSurfaceToTexture(center_ + intersect*(point-center_));
261 }
262
263 Vector CGTwoPart::CylinderNormal(const Vector& point) const {
264     // distance to y axis
265     const double distance_to_y_axis = sqrt(point[0]*point[0] + point[2]*point[2]);
266     const double radius = 0.5;
267
268     // move point to the cylinder's surface
269     const Vector surface(point[0] / (distance_to_y_axis/radius),
270                          point[1],
271                          point[2] / (distance_to_y_axis/radius))
;
272
273     // get texture s,t
274     return CylinderSurfaceToTexture(surface);
275 }
276
277 Vector CGTwoPart::CylinderSurfaceToTexture(const Vector& surface) const {
278     const double radius = 0.5;
279     // determine rotation angle
280     double s = acos(surface[0]/radius) / (2*PI);
281     if (surface[2] > 0.0)
282         s = 1-s;
283
284     // rotate again by 180°
285     s += 0.5;
286     if (s > 1)
287         s -= 1;
288
289     // t comes from da height
290     double t = 1 - (surface[1] + 0.5);
291     if (t < 0)
292         t = 0;
293     if (t > 1)
294         t = 1;
295
296     return Vector(s,t);
297 }
298
299 void CGTwoPart::handleVertex(const Vector& v) const{
300     // texturing ...
301     Vector texCoord;
302
303     switch (mapping_)
304     {
305     case SPHERE_INTERSECTION:   texCoord = SphereIntersection(v);
306                                 break;
307     case SPHERE_NORMAL:            texCoord = SphereNormal(v);
308                                 break;
309     case CYLINDER_INTERSECTION: texCoord = CylinderIntersection(v);
310                                 break;
311     case CYLINDER_NORMAL:        texCoord = CylinderNormal(v);
312                                 break;
313     }
314     glTexCoord2d(texCoord[0], texCoord[1]);
315
316     glVertex3dv(v.rep());
317 }
318
319 void CGTwoPart::onDraw() {
320     // Loesche den Farb- und Tiefenspeicher
321     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
322    
323    
324     glPushMatrix();
325     // glRotatef(-30,0,1,0);
326     glScaled(zoom_, zoom_, zoom_);
327
328     glEnable(GL_TEXTURE_2D);
329     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
330     glBindTexture(GL_TEXTURE_2D, texName_);
331
332     glBegin(GL_TRIANGLES);
333     for (int i=0; i<size_; i++) {           
334         for (int k = 0; k < 3; k++) {
335             handleVertex(tris_[i].getVertex(k));
336         }       
337     }
338     glEnd();
339     glDisable(GL_TEXTURE_2D);
340    
341     glPopMatrix();   
342    
343     // Nicht vergessen! Front- und Back-Buffer tauschen:
344     swapBuffers();
345 }
346
347 void CGTwoPart::readImage() {
348
349     char buf[BUF_SIZE];
350
351     // create input stream
352     ifstream in(filename_);
353     if(!in) {
354         cerr << "no ppm image" << endl;
355         exit(-1);
356     }
357
358     cout << "Reading image from file \"" << filename_ << "===>\<===" " << endl;
359
360     // PPM header
361 #ifdef _MSC_VER
362     in >> binary;
363 #endif
364
365     // Read "P6"
366     char ppm;
367     in >> ppm; if(!in.good() || ppm != 'P') { cerr << "ppm format error" << endl; }
368     in >> ppm; if(!in.good() || ppm != '6') { cerr << "ppm format error" << endl; }
369
370     // forward to next line
371     in.getline(buf, BUF_SIZE);
372
373     // normally read comments, but we assume that no comments are there
374     // in.getline(buf, BUF_SIZE);
375     // while (buf[0] == '#')
376     // in.getline(buf, BUF_SIZE);
377
378     // Read width and height
379     in >> texWidth_; if(!in.good()) { cerr << "ppm format error" << endl; }
380     in >> texHeight_; if(!in.good()) { cerr << "ppm format error" << endl; }
381
382     // Read 255
383     unsigned int res;
384     in >> res; if(!in.good() || res != 255) { cerr << "ppm format error" << endl; }
385
386     // forward to next line
387     in.getline(buf, BUF_SIZE);
388    
389     image_ = new GLubyte [3 * texWidth_ * texHeight_];
390     in.read(image_, 3 * texWidth_ * texHeight_);
391     if(!in.good()) { cerr << "ppm format error" << endl; }
392
393     // for creating an image with an alpha channel - but we don't need this?
394 /* unsigned char rgba[4]; rgba[3] = 255; // alpha value for(int i=0; i<texWidth_; i++) for(int j=0; j<texHeight_; j++) { in.read(rgba, 3); if(!in.good()) { cerr << "ppm format error" << endl; } for (int k=0; k<4; k++) { image_[k + j*4 + i*(4*texHeight_)] = rgba[k]; } } */
395     in.close();
396 }
397
398 // Hauptprogramm
399 int main(int argc, char* argv[]) {
400     // Erzeuge eine Instanz der Beispiel-Anwendung:
401     CGTwoPart sample("map.ppm");
402     // CGTwoPart sample("church_spiral.ppm");
403    
404     cout << "Tastenbelegung:" << endl          << "ESC Programm beenden" << endl          << "Leertaste Objekt drehen" << endl          << "+ Hineinzoomen" << endl          << "- Herauszoomen" << endl          << "q Kugel-Intersektions-Mapping" << endl          << "w Kugel-Normalen-Mapping" << endl          << "e Zylinder-Intersektions-Mapping" << endl          << "r Zylinder-Normalen-Mapping" << endl          << "l Drahtgittermodell" << endl          << "f Texturieren" << endl          << "c Verdeckte Flaechen zeichnen an/aus" << endl;
405
406     // Starte die Beispiel-Anwendung:
407     sample.start("Stephan Brumme, 702544", true, 512, 512);
408     return(0);
409 }
410