sources:
cgapplication.cpp (3.2k)
cgapplication.h (3.5k)
cgtwopart.cpp (10.9k)
cgtwopart.h (1.5k)
triangle.cpp (1.1k)
triangle.h (1.2k)
vector.cpp (1.7k)
vector.h (4.9k)


binaries:
Release/twopart.exe (32.5k)


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 {
148     // code taken from ray-sphere intersection of my raytracer
149
150     // ray origin
151     const Vector origin(center_);
152     const double x = origin[0];
153     const double y = origin[1];
154     const double z = origin[2];
155
156     // ray direction
157     const Vector direction(point-center_);
158     const double i = direction[0];
159     const double j = direction[1];
160     const double k = direction[2];
161
162     // sphere's center
163     const double r = 1.0;
164
165     // compute parameters a,b,c for at^2+bt+c=0
166     const double a = i*i + j*j + k*k;
167     const double b = 2*(i*x + j*y + k*z);
168     const double c = x*x+y*y+z*z - r*r;
169
170     // solve at^2+bt+c=0
171     // D = b^2-4ac
172     const double D = b*b-4*a*c;
173
174
175     // no intersection
176     if (D < 0)
177         return Vector(0,0,0);
178
179     // nearest ray intersection
180     double t;
181
182     if (D > 0)
183     {
184         // two intersections
185         // ray parameter
186         const double t1 = (-b + sqrt(D))/(2*a);
187         const double t2 = (-b - sqrt(D))/(2*a);
188         t = min(t1,t2);
189         if (t < 0)
190             t = max(t1,t2);
191     }
192     else
193         // only one intersection
194         t = -b/(2*a);
195
196     return SphereSurfaceToTexture(origin + t*direction);
197 }
198
199 Vector CGTwoPart::SphereNormal(const Vector& point) const
200 {
201     return SphereSurfaceToTexture(point.normalized());
202 }
203
204 Vector CGTwoPart::SphereSurfaceToTexture(const Vector& surface) const
205 {
206     const double x_distortion = sin(acos(surface[1]));
207
208     // first texture coordinate
209     double s = 1.0;
210     if (x_distortion != 0.0)
211     {
212         s = acos(surface[0] / x_distortion) / (2*PI);
213         if (surface[2] > 0.0)
214             s = 1-s;
215     }
216
217     // rotate by 180°
218     s += 0.5;
219     if (s > 1)
220         s -= 1;
221
222     // second texture coordinate
223     double t = acos(surface[1]) / PI;
224    
225     return Vector(s,t);
226 }
227
228 Vector CGTwoPart::CylinderIntersection(const Vector& point) const
229 {
230     // radius
231     const double r = 0.5;
232
233     // origin of line
234     const double x = center_[0];
235     const double z = center_[2];
236
237     // direction
238     const double i = point[0]    - x;
239     const double j = point[2]    - z;
240
241     // no degenerated lines
242     if (i==0 && j==0)
243         return Vector(0,0,0);
244
245     // 0 = tē+pt+q
246     const double p = 2*(i*x+j*z) / (i*i+j*j);
247     const double q = (x*x+z*z-r*r) / (i*i+j*j);
248    
249     // square root
250     const double D = (p*p/4)-q;
251     // no solution
252     if (D < 0)
253         return Vector(0,0,0);
254
255     // t1 may be equal to t2 but that doesn't matter
256     const double t1 = -p/2 + sqrt(D);
257     const double t2 = -p/2 - sqrt(D);
258
259     // nearest intersetion
260     double intersect = min(t1,t2);
261     if (intersect < 0)
262         intersect = max(t1,t2);
263
264     // move point to the cylinder's surface and get texture coordinates
265     return CylinderSurfaceToTexture(center_ + intersect*(point-center_));
266 }
267
268 Vector CGTwoPart::CylinderNormal(const Vector& point) const
269 {
270     // distance to y axis
271     const double distance_to_y_axis = sqrt(point[0]*point[0] + point[2]*point[2]);
272     const double radius = 0.5;
273
274     // move point to the cylinder's surface
275     const Vector surface(point[0] / (distance_to_y_axis/radius),
276                          point[1],
277                          point[2] / (distance_to_y_axis/radius))
;
278
279     // get texture s,t
280     return CylinderSurfaceToTexture(surface);
281 }
282
283 Vector CGTwoPart::CylinderSurfaceToTexture(const Vector& surface) const
284 {
285     const double radius = 0.5;
286     // determine rotation angle
287     double s = acos(surface[0]/radius) / (2*PI);
288     if (surface[2] > 0.0)
289         s = 1-s;
290
291     // rotate again by 180°
292     s += 0.5;
293     if (s > 1)
294         s -= 1;
295
296     // t comes from da height
297     double t = 1 - (surface[1] + 0.5);
298     if (t < 0)
299         t = 0;
300     if (t > 1)
301         t = 1;
302
303     return Vector(s,t);
304 }
305
306 void CGTwoPart::handleVertex(const Vector& v) const{
307     // texturing ...
308     Vector texCoord;
309
310     switch (mapping_)
311     {
312     case SPHERE_INTERSECTION:   texCoord = SphereIntersection(v);
313                                 break;
314     case SPHERE_NORMAL:            texCoord = SphereNormal(v);
315                                 break;
316     case CYLINDER_INTERSECTION: texCoord = CylinderIntersection(v);
317                                 break;
318     case CYLINDER_NORMAL:        texCoord = CylinderNormal(v);
319                                 break;
320     }
321     glTexCoord2d(texCoord[0], texCoord[1]);
322
323     glVertex3dv(v.rep());
324 }
325
326 void CGTwoPart::onDraw() {
327     // Loesche den Farb- und Tiefenspeicher
328     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
329    
330    
331     glPushMatrix();
332     // glRotatef(-30,0,1,0);
333     glScaled(zoom_, zoom_, zoom_);
334
335     glEnable(GL_TEXTURE_2D);
336     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
337     glBindTexture(GL_TEXTURE_2D, texName_);
338
339     glBegin(GL_TRIANGLES);
340     for (int i=0; i<size_; i++) {           
341         for (int k = 0; k < 3; k++) {
342             handleVertex(tris_[i].getVertex(k));
343         }       
344     }
345     glEnd();
346     glDisable(GL_TEXTURE_2D);
347    
348     glPopMatrix();   
349    
350     // Nicht vergessen! Front- und Back-Buffer tauschen:
351     swapBuffers();
352 }
353
354 void CGTwoPart::readImage() {
355
356     char buf[BUF_SIZE];
357
358     // create input stream
359     ifstream in(filename_);
360     if(!in) {
361         cerr << "no ppm image" << endl;
362         exit(-1);
363     }
364
365     cout << "Reading image from file \"" << filename_ << "\" " << endl;
366
367     // PPM header
368 #ifdef _MSC_VER
369     in >> binary;
370 #endif
371
372     // Read "P6"
373     char ppm;
374     in >> ppm; if(!in.good() || ppm != 'P') { cerr << "ppm format error" << endl; }
375     in >> ppm; if(!in.good() || ppm != '6') { cerr << "ppm format error" << endl; }
376
377     // forward to next line
378     in.getline(buf, BUF_SIZE);
379
380     // normally read comments, but we assume that no comments are there
381     // in.getline(buf, BUF_SIZE);
382     // while (buf[0] == '#')
383     // in.getline(buf, BUF_SIZE);
384
385     // Read width and height
386     in >> texWidth_; if(!in.good()) { cerr << "ppm format error" << endl; }
387     in >> texHeight_; if(!in.good()) { cerr << "ppm format error" << endl; }
388
389     // Read 255
390     unsigned int res;
391     in >> res; if(!in.good() || res != 255) { cerr << "ppm format error" << endl; }
392
393     // forward to next line
394     in.getline(buf, BUF_SIZE);
395    
396     image_ = new GLubyte [3 * texWidth_ * texHeight_];
397     in.read(image_, 3 * texWidth_ * texHeight_);
398     if(!in.good()) { cerr << "ppm format error" << endl; }
399
400     // for creating an image with an alpha channel - but we don't need this?
401 /* 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]; } } */
402     in.close();
403 }
404
405 // Hauptprogramm
406 int main(int argc, char* argv[]) {
407     // Erzeuge eine Instanz der Beispiel-Anwendung:
408     CGTwoPart sample("map.ppm");
409     // CGTwoPart sample("church_spiral.ppm");
410    
411     cout << "Tastenbelegung:" << endl
412          << "ESC Programm beenden" << endl
413          << "Leertaste Objekt drehen" << endl
414          << "+ Hineinzoomen" << endl
415          << "- Herauszoomen" << endl
416          << "q Kugel-Intersektions-Mapping" << endl
417          << "w Kugel-Normalen-Mapping" << endl
418          << "e Zylinder-Intersektions-Mapping" << endl
419          << "r Zylinder-Normalen-Mapping" << endl
420          << "l Drahtgittermodell" << endl
421          << "f Texturieren" << endl
422          << "c Verdeckte Flaechen zeichnen an/aus" << endl;
423
424     // Starte die Beispiel-Anwendung:
425     sample.start("Stephan Brumme, 702544", true, 512, 512);
426     return(0);
427 }
428