// // Computergraphik II // Prof. Dr. Juergen Doellner // Wintersemester 2001/02 // // Rahmenprogramm zu Aufgabenzettel 1 // #include "cgillumination.h" #include typedef Vector Camera; typedef Vector Color; const MAXLIGHTSOURCES = 8; class Light { public: Light(const Vector& p, double i) : pos(p),intensity(i) { constant = 0.3; linear = 0.0; quadric = 0.0; } Vector pos; /* position, world coordinate system */ double intensity; /* light source intensity [0,1] */ static double ambient; /* ambient light contribution (global) */ double constant; /* constant attenuation */ double linear; /* linear attenuation */ double quadric; /* quadric attenuation */ }; double Light::ambient = 0.2; class Material { public: Material(double ka_,double kd_,double ks_,double n_, Color c) : ka(ka_), kd(kd_), ks(ks_), n(n_), color(c) {} double ka; /* ambient reflection coefficient */ double kd; /* diffuse reflection coefficient */ double ks; /* specular reflection coefficient */ double n; /* specular shininess */ Color color; /* specular color */ }; class Context { public: Light* light[MAXLIGHTSOURCES]; /* max. 8 light sources */ Camera* camera; Material* material; }; // // CGIllumination Application // CGIllumination::CGIllumination() { stop_=true; phong_=true; zoom_=0.3; rotate_=-30; // read triangle data ifstream s("triceratops.txt"); //ifstream s("triangle_small.txt"); s >> size_; tris_ = new Triangle[size_]; int i; for (i = 0; i < size_; i++) s >> tris_[i]; // init context ctx_= new Context(); ctx_->material = new Material(0.6, 0.4, 0.2, 32.0 , Color(0.4, 0.9, 0.4)); ctx_->camera = new Camera(0, 3, 7); ctx_->light[0] = new Light(Vector( -1, 2, 6), 0.7 ); ctx_->light[1] = new Light(Vector( 9, 4, 1), 1.0 ); ctx_->light[2] = 0; } CGIllumination::~CGIllumination() { } void CGIllumination::onInit() { // zu Beginn keine OpenGL Lichtquelle glDisable(GL_LIGHTING); const float specular[] = { 0, ctx_->light[0]->intensity, 0, 0 }; glMaterialfv(GL_FRONT, GL_SPECULAR, specular); glMaterialf (GL_FRONT, GL_SHININESS, ctx_->material->n); const float lightPosition0[] = { ctx_->light[0]->pos[0], ctx_->light[0]->pos[1], ctx_->light[0]->pos[2], 0 }; const float lightDiffuse0[] = { 0, ctx_->light[0]->intensity, 0, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0); glEnable(GL_LIGHT0); const float lightPosition1[] = { ctx_->light[1]->pos[0], ctx_->light[1]->pos[1], ctx_->light[1]->pos[2], 0 }; const float lightDiffuse1[] = { 0, ctx_->light[1]->intensity, 0, 0 }; glLightfv(GL_LIGHT1, GL_POSITION, lightPosition1); glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse1); glEnable(GL_LIGHT1); glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); // automatische Normalisierung // glEnable(GL_NORMALIZE); // Tiefen Test aktivieren glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glClearColor(1.0,1.0,1.0,1.0); // Smooth Schattierung aktivieren glShadeModel(GL_SMOOTH); // Culling glCullFace(GL_BACK); // Projection glMatrixMode(GL_PROJECTION); gluPerspective(40.0,1.0,1.0,10.0); // LookAt glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 3.0, 7.0, // from (0,3,7) 0.0, 0.0, 0.0, // to (0,0,0) 0.0, 1.0, 0.); // up } void CGIllumination::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 CGIllumination::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 '1' : { glEnable(GL_LIGHTING); phong_ = false; break; } case '2' : { glDisable(GL_LIGHTING); phong_ = true; break; } case 'c' : { if (glIsEnabled(GL_CULL_FACE)) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } break; } case ' ' : { stop_ = !stop_; break; } } onDraw(); } void CGIllumination::onIdle() { if (!stop_) { rotate_ -= 2; onDraw(); } } inline double max(double x, double y) { return (xlight[li]->constant+ ctx_->light[li]->linear* abs(punkt-licht)+ ctx_->light[li]->quadric*abs2(punkt-licht)); if (temp>1) {return 1;} else {return temp;}; } void CGIllumination::setPhongIllumination(const Vector& point, const Vector& normal) { // OpenGL's lighting ? if (!phong_) { const Color c = ctx_->material->color; glColor3f(c[0], c[1], c[2]); return; } // Phong Beleuchtungsmodell implementieren // NOW COMES DA REAL STUFF !!! // define intensity variables double dIntensityAmbient = 0; double dIntensityDiffuse = 0; double dIntensitySpecular = 0; // ambient intensity dIntensityAmbient = Light::ambient * ctx_->material->ka; // N = normal const Vector N_norm = normal.normalized(); // V = view vector const Vector V = *(ctx_->camera) - point; const Vector V_norm = V.normalized(); // process all light sources (at most 8) for (int nLight=0; nLight < MAXLIGHTSOURCES; nLight++) { // get a single light source Light* light = ctx_->light[nLight]; if (light == NULL) break; // L = light vector const Vector L = light->pos - point; const Vector L_norm = L.normalized(); // N*L const double NdotL = max(dotProduct(N_norm, L_norm), 0); // R*V = (2*N*(N*L)-L)*V const double RdotV = max(dotProduct((2*NdotL*N_norm - L_norm).normalized(), V_norm), 0); // attenuation const double dDistance = abs(L); double dAttenuation = 1 / (light->constant + dDistance*light->linear + dDistance*dDistance*light->quadric); if (dAttenuation > 1) dAttenuation = 1; // attenuation*I const double dAttI = dAttenuation * light->intensity; // diffuse intensity dIntensityDiffuse += dAttI * ctx_->material->kd * NdotL; // specular intensity dIntensitySpecular += dAttI * ctx_->material->ks * pow(RdotV, ctx_->material->n); } const double dIntensity = dIntensityAmbient + dIntensityDiffuse + dIntensitySpecular; // Material color Color c = ctx_->material->color; c *= dIntensity; // color per vertex glColor3f(min(c[0],1), min(c[1],1), min(c[2],1)); } inline Vector rotateYaxis(const Vector& vec, float angle) { Vector result; const float sinus = sin(angle/180*3.1415926); const float cosinus = cos(angle/180*3.1415926); result[0] = vec[0]*cosinus + vec[2]*sinus; result[1] = vec[1]; result[2] =-vec[0]*sinus + vec[2]*cosinus; return result; } void CGIllumination::onDraw() { // Loesche den Farb- und Tiefenspeicher glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); // glRotatef(rotate_,0,1,0); // glScaled(zoom_, zoom_, zoom_); glBegin(GL_TRIANGLES); for (int i=0; i