// // Computergraphik II // Prof. Dr. Juergen Doellner // Wintersemester 2001/02 // // Rahmenprogramm zu Aufgabenzettel 8 // #include "cgtwopart.h" #include typedef Vector Camera; typedef Vector Color; #ifndef PI const double PI = 3.14159265358979323846; #endif const unsigned int BUF_SIZE = 1024; // // Application // CGTwoPart::CGTwoPart(char* filename) { filename_ = filename; stop_=true; zoom_= 1.5; mapping_ = SPHERE_INTERSECTION; // read triangle data ifstream s("triceratops.txt"); // ifstream s("triangle_small.txt"); s >> size_; tris_ = new Triangle[size_]; center_ = Vector(0,0,0); int i; for (i = 0; i < size_; i++) { s >> tris_[i]; // just scale object tris_[i].setVertex(0, tris_[i].getVertex(0) * 0.1); tris_[i].setVertex(1, tris_[i].getVertex(1) * 0.1); tris_[i].setVertex(2, tris_[i].getVertex(2) * 0.1); // add up all vectors center_ += tris_[i].getVertex(0); center_ += tris_[i].getVertex(1); center_ += tris_[i].getVertex(2); } center_ *= 1/(3.0*size_); } CGTwoPart::~CGTwoPart() { } void CGTwoPart::onInit() { // Tiefen Test aktivieren glEnable(GL_DEPTH_TEST); // Smooth Schattierung aktivieren glShadeModel(GL_SMOOTH); // Projection glMatrixMode(GL_PROJECTION); gluPerspective(60.0, 1.0, 2.0, 50.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); // Import texture from file readImage(); glGenTextures(1, &texName_); glBindTexture(GL_TEXTURE_2D, texName_); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth_, texHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, image_); } void CGTwoPart::onSize(unsigned int newWidth,unsigned int newHeight) { if((newWidth > 0) && (newHeight > 0)) { // Passe den OpenGL-Viewport an die neue Fenstergroesse an: glViewport(0, 0, newWidth - 1, newHeight - 1); // Passe die OpenGL-Projektionsmatrix an die neue // Fenstergroesse an: glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,float(newWidth)/float(newHeight),1.0, 10.0); // Schalte zurueck auf die Modelview-Matrix glMatrixMode(GL_MODELVIEW); } } void CGTwoPart::onKey(unsigned char key) { static GLfloat z = 3.; switch (key) { case 27: { exit(0); break; } case '+': { zoom_*= 1.1; break; } case '-': { zoom_*= 0.9; break; } case 'l' : { glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; } case 'f' : { glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; } case 'c' : { if (glIsEnabled(GL_CULL_FACE)) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } break; } case 'q' : { mapping_ = SPHERE_INTERSECTION; break; } case 'w' : { mapping_ = SPHERE_NORMAL; break; } case 'e' : { mapping_ = CYLINDER_INTERSECTION; break; } case 'r' : { mapping_ = CYLINDER_NORMAL; break; } case ' ' : { stop_ = !stop_; break; } } onDraw(); } void CGTwoPart::onIdle() { if (!stop_) { glRotatef(-2.0f,0,1,0.1); onDraw(); } } inline double max(double x, double y) { return (xy) ? y : x; } Vector CGTwoPart::SphereIntersection(const Vector& point) const { // code taken from ray-sphere intersection of my raytracer // ray origin const Vector origin(center_); const double x = origin[0]; const double y = origin[1]; const double z = origin[2]; // ray direction const Vector direction(point-center_); const double i = direction[0]; const double j = direction[1]; const double k = direction[2]; // sphere's center const double r = 1.0; // compute parameters a,b,c for at^2+bt+c=0 const double a = i*i + j*j + k*k; const double b = 2*(i*x + j*y + k*z); const double c = x*x+y*y+z*z - r*r; // solve at^2+bt+c=0 // D = b^2-4ac const double D = b*b-4*a*c; // no intersection if (D < 0) return Vector(0,0,0); // nearest ray intersection double t; if (D > 0) { // two intersections // ray parameter const double t1 = (-b + sqrt(D))/(2*a); const double t2 = (-b - sqrt(D))/(2*a); t = min(t1,t2); if (t < 0) t = max(t1,t2); } else // only one intersection t = -b/(2*a); return SphereSurfaceToTexture(origin + t*direction); } Vector CGTwoPart::SphereNormal(const Vector& point) const { return SphereSurfaceToTexture(point.normalized()); } Vector CGTwoPart::SphereSurfaceToTexture(const Vector& surface) const { const double x_distortion = sin(acos(surface[1])); // first texture coordinate double s = 1.0; if (x_distortion != 0.0) { s = acos(surface[0] / x_distortion) / (2*PI); if (surface[2] > 0.0) s = 1-s; } // rotate by 180° s += 0.5; if (s > 1) s -= 1; // second texture coordinate double t = acos(surface[1]) / PI; return Vector(s,t); } Vector CGTwoPart::CylinderIntersection(const Vector& point) const { // radius const double r = 0.5; // origin of line const double x = center_[0]; const double z = center_[2]; // direction const double i = point[0] - x; const double j = point[2] - z; // no degenerated lines if (i==0 && j==0) return Vector(0,0,0); // 0 = tē+pt+q const double p = 2*(i*x+j*z) / (i*i+j*j); const double q = (x*x+z*z-r*r) / (i*i+j*j); // square root const double D = (p*p/4)-q; // no solution if (D < 0) return Vector(0,0,0); // t1 may be equal to t2 but that doesn't matter const double t1 = -p/2 + sqrt(D); const double t2 = -p/2 - sqrt(D); // nearest intersetion double intersect = min(t1,t2); if (intersect < 0) intersect = max(t1,t2); // move point to the cylinder's surface and get texture coordinates return CylinderSurfaceToTexture(center_ + intersect*(point-center_)); } Vector CGTwoPart::CylinderNormal(const Vector& point) const { // distance to y axis const double distance_to_y_axis = sqrt(point[0]*point[0] + point[2]*point[2]); const double radius = 0.5; // move point to the cylinder's surface const Vector surface(point[0] / (distance_to_y_axis/radius), point[1], point[2] / (distance_to_y_axis/radius)); // get texture s,t return CylinderSurfaceToTexture(surface); } Vector CGTwoPart::CylinderSurfaceToTexture(const Vector& surface) const { const double radius = 0.5; // determine rotation angle double s = acos(surface[0]/radius) / (2*PI); if (surface[2] > 0.0) s = 1-s; // rotate again by 180° s += 0.5; if (s > 1) s -= 1; // t comes from da height double t = 1 - (surface[1] + 0.5); if (t < 0) t = 0; if (t > 1) t = 1; return Vector(s,t); } void CGTwoPart::handleVertex(const Vector& v) const{ // texturing ... Vector texCoord; switch (mapping_) { case SPHERE_INTERSECTION: texCoord = SphereIntersection(v); break; case SPHERE_NORMAL: texCoord = SphereNormal(v); break; case CYLINDER_INTERSECTION: texCoord = CylinderIntersection(v); break; case CYLINDER_NORMAL: texCoord = CylinderNormal(v); break; } glTexCoord2d(texCoord[0], texCoord[1]); glVertex3dv(v.rep()); } void CGTwoPart::onDraw() { // Loesche den Farb- und Tiefenspeicher glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); // glRotatef(-30,0,1,0); glScaled(zoom_, zoom_, zoom_); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBindTexture(GL_TEXTURE_2D, texName_); glBegin(GL_TRIANGLES); for (int i=0; i> 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; } // for creating an image with an alpha channel - but we don't need this? /* unsigned char rgba[4]; rgba[3] = 255; // alpha value for(int i=0; i