// // Computergraphik II // Prof. Dr. Juergen Doellner // Wintersemester 2001/02 // // Rahmenprogramm zu Aufgabenzettel 9 // #include "cgprojtexture.h" #include "vector.h" #include #include #ifndef M_PI const double M_PI = 3.14159265358979323846; #endif const unsigned int BUF_SIZE = 1024; CGProjTexture::CGProjTexture(char* filename) { filename_ = filename; run_ = false; zoom_ = 0.16; angle_ = 15.0; radius_ = 4.0; theta_ = 0.0; phi_ = 0.0; } CGProjTexture::~CGProjTexture() { } void CGProjTexture::drawScene() { // texture coordinate generation static const GLfloat Splane[] = { 1, 0, 0, 0 }; static const GLfloat Tplane[] = { 0, 1, 0, 0 }; static const GLfloat Rplane[] = { 0, 0, 1, 0 }; static const GLfloat Qplane[] = { 0, 0, 0, 1 }; glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni (GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_S, GL_EYE_PLANE, Splane); glTexGenfv(GL_T, GL_EYE_PLANE, Tplane); glTexGenfv(GL_R, GL_EYE_PLANE, Rplane); glTexGenfv(GL_Q, GL_EYE_PLANE, Qplane); // switch it on glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q); // Texturmatrix für projektive Textur einstellen glMatrixMode(GL_TEXTURE); // texture coordinates must be within [0,1]^2 glLoadIdentity(); glTranslatef(0.5, 0.5, 0.0); glScalef (0.5,-0.5, 1.0); // perspective projection gluPerspective(angle_, 1, 1, 2*radius_); // convert angles to radiant const double theta = theta_ / 180*M_PI; const double phi = phi_ / 180*M_PI; // select view gluLookAt(radius_*sin(theta)*cos(phi), radius_*sin(phi), radius_*cos(theta)*cos(phi), // from 0.0, 0.0, 0.0, // to 0.0, 1.0, 0.0);// up // Texturierung einschalten glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); // draw dino glPushMatrix(); glScaled(zoom_, zoom_, zoom_); drawObject(); glPopMatrix(); // gray cube static float material_diffuse[] = {0.7, 0.8, 1.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_diffuse); glCullFace(GL_FRONT); glutSolidCube(3.0); glCullFace(GL_BACK); } void CGProjTexture::drawObject() { static float material_diffuse[] = {1.0, 0.6, 0.7, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_diffuse); // create display list (done only once) static GLuint cache = 0; if (cache == 0) { cache = glGenLists(1); glNewList(cache, GL_COMPILE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); ifstream s("triceratops.txt"); char buf[BUF_SIZE]; glBegin(GL_TRIANGLES); Vector v[3]; while (!s.eof()) { s >> buf; while (s.good()) { s >> v[0] >> v[1] >> v[2]; Vector n = (v[1]-v[0])*(v[2]-v[0]); glNormal3dv(n.rep()); glVertex3dv(v[0].rep()); glVertex3dv(v[1].rep()); glVertex3dv(v[2].rep()); } if (s.rdstate() & ios::failbit) { s.clear(s.rdstate() & ~ios::failbit); } } glEnd(); glPopMatrix(); glEndList(); } // execute display list glCallList(cache); } void CGProjTexture::readImage() { char buf[BUF_SIZE]; // create input stream ifstream in(filename_); if(!in) { cerr << "no ppm image" << endl; exit(-1); } cout << "Reading image from file \"" << filename_ << "\" " << endl; // PPM header #ifdef _MSC_VER in >> binary; #endif // Read "P6" char ppm; in >> ppm; if(!in.good() || ppm != 'P') { cerr << "ppm format error" << endl; } in >> ppm; if(!in.good() || ppm != '6') { cerr << "ppm format error" << endl; } // forward to next line in.getline(buf, BUF_SIZE); // normally read comments, but we assume that no comments are there // in.getline(buf, BUF_SIZE); // while (buf[0] == '#') // in.getline(buf, BUF_SIZE); // Read width and height in >> texWidth_; if(!in.good()) { cerr << "ppm format error" << endl; } in >> texHeight_; if(!in.good()) { cerr << "ppm format error" << endl; } // Read 255 unsigned int res; in >> res; if(!in.good() || res != 255) { cerr << "ppm format error" << endl; } // forward to next line in.getline(buf, BUF_SIZE); image_ = new GLubyte [3 * texWidth_ * texHeight_]; in.read(image_, 3 * texWidth_ * texHeight_); if(!in.good()) { cerr << "ppm format error" << endl; } in.close(); } void CGProjTexture::onInit() { // Tiefen Test aktivieren glEnable(GL_DEPTH_TEST); // Smooth Schattierung aktivieren glShadeModel(GL_SMOOTH); // Culling aktivieren glCullFace(GL_BACK); glEnable(GL_CULL_FACE); // Projection glMatrixMode(GL_PROJECTION); gluPerspective(40.0, 1.0, 1.0, 20.0); // LookAt glMatrixMode(GL_MODELVIEW); gluLookAt( 0.0, 0.0, 4.0, // from (0,0,4) 0.0, 0.0, 0.0, // to (0,0,0) 0.0, 1.0, 0.); // up glClearColor(0.9,0.9,0.9,1.0); // Textur einlesen readImage(); // Texturobjekt anlegen, Grundeinstellungen für projektive Textur festlegen ////////////////////////////////// // create texture // generate a unique ID glGenTextures(1, &texName_); // use this texture ID glBindTexture(GL_TEXTURE_2D, texName_); // don't repeat texture glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // use filter "linear" both for magnification and minification glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // bind image to texture object glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth_, texHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, image_); // texture blending glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // OpenGL Lichtquellen static GLfloat light_diffuse[] = {0.7, 0.7, 0.7, 1.0}; static GLfloat light_position1[] = {1.0, 0.5, 1.0, 0.0}; glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light_position1); glEnable(GL_LIGHT0); static GLfloat light_position2[] = {-0.5, -0.4, -1.0, 0.0}; glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_POSITION, light_position2); glEnable(GL_LIGHT1); glEnable(GL_LIGHTING); } void CGProjTexture::onSize(unsigned int newWidth,unsigned int newHeight) { width_ = newWidth; height_ = newHeight; glMatrixMode(GL_PROJECTION); glViewport(0, 0, width_ - 1, height_ - 1); glLoadIdentity(); gluPerspective(40.0,float(width_)/float(height_),1.0, 20.0); glMatrixMode(GL_MODELVIEW); } void CGProjTexture::onKey(unsigned char key) { switch (key) { case 27: { exit(0); break; } case '+': { zoom_*= 1.1; break; } case '-': { zoom_/= 1.1; break; } case ' ': { run_ = !run_; break; } case 'w': { if (angle_ < 180) angle_ *= 1.05; break; } case 'q': { if (angle_ > 0.001) angle_ /= 1.05; break; } case 's': { theta_ += 2; if (theta_>=360) theta_-=360; break; } case 'a': { theta_ -= 2; if (theta_<=0) theta_+=360; break; } case 'x': { phi_ += 2; if (phi_>=90) phi_=90; break; } case 'y': { phi_ -= 2; if (phi_<=-90) phi_=-90;break; } } onDraw(); } void CGProjTexture::onIdle() { if (run_) { glRotatef(.5, 0.0, 1.0, 0.0); } onDraw(); } void CGProjTexture::onDraw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawScene(); swapBuffers(); } // Hauptprogramm int main(int argc, char* argv[]) { // Erzeuge eine Instanz der Beispiel-Anwendung: CGProjTexture sample("smily.ppm"); 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; // Starte die Beispiel-Anwendung: sample.start("Stephan Brumme, 702544", true, 512, 512); return(0); }