1 //
2 // Computergraphik II
3 // Prof. Dr. Juergen Doellner
4 // Wintersemester 2001/02
5 //
6 // Rahmenprogramm zu Aufgabenzettel 1
7 //
8
9 #include "cgillumination.h"
10 #include <fstream.h>
11
12 typedef Vector Camera;
13 typedef Vector Color;
14
15 const MAXLIGHTSOURCES = 8;
16
17 class Light {
18 public:
19 Light(const Vector& p, double i) : pos(p),intensity(i) {
20 constant = 0.3;
21 linear = 0.0;
22 quadric = 0.0;
23 }
24
25 Vector pos; /* position, world coordinate system */
26 double intensity; /* light source intensity [0,1] */
27 static double ambient; /* ambient light contribution (global) */
28
29 double constant; /* constant attenuation */
30 double linear; /* linear attenuation */
31 double quadric; /* quadric attenuation */
32 };
33
34 double Light::ambient = 0.2;
35
36 class Material {
37 public:
38 Material(double ka_,double kd_,double ks_,double n_, Color c)
39 : ka(ka_), kd(kd_), ks(ks_), n(n_), color(c) {}
40
41 double ka; /* ambient reflection coefficient */
42 double kd; /* diffuse reflection coefficient */
43 double ks; /* specular reflection coefficient */
44 double n; /* specular shininess */
45 Color color; /* specular color */
46 };
47
48 class Context {
49 public:
50 Light* light[MAXLIGHTSOURCES]; /* max. 8 light sources */
51 Camera* camera;
52 Material* material;
53 };
54
55
56 //
57 // CGIllumination Application
58 //
59
60 CGIllumination::CGIllumination() {
61
62 stop_=true;
63 phong_=true;
64 zoom_=0.3;
65 rotate_=-30;
66
67 // read triangle data
68 ifstream s("triceratops.txt");
69 //ifstream s("triangle_small.txt");
70 s >> size_;
71
72 tris_ = new Triangle[size_];
73
74 int i;
75 for (i = 0; i < size_; i++)
76 s >> tris_[i];
77
78 // init context
79 ctx_= new Context();
80 ctx_->material = new Material(0.6, 0.4, 0.2, 32.0 , Color(0.4, 0.9, 0.4));
81 ctx_->camera = new Camera(0, 3, 7);
82 ctx_->light[0] = new Light(Vector( -1, 2, 6), 0.7 );
83 ctx_->light[1] = new Light(Vector( 9, 4, 1), 1.0 );
84 ctx_->light[2] = 0;
85 }
86
87
88 CGIllumination::~CGIllumination() {
89 }
90
91 void CGIllumination::onInit() {
92
93 // zu Beginn keine OpenGL Lichtquelle
94 glDisable(GL_LIGHTING);
95
96 const float specular[] = { 0, ctx_->light[0]->intensity, 0, 0 };
97 glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
98 glMaterialf (GL_FRONT, GL_SHININESS, ctx_->material->n);
99
100 const float lightPosition0[] = { ctx_->light[0]->pos[0],
101 ctx_->light[0]->pos[1],
102 ctx_->light[0]->pos[2], 0 };
103 const float lightDiffuse0[] = { 0, ctx_->light[0]->intensity, 0, 0 };
104 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0);
105 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0);
106 glEnable(GL_LIGHT0);
107
108 const float lightPosition1[] = { ctx_->light[1]->pos[0],
109 ctx_->light[1]->pos[1],
110 ctx_->light[1]->pos[2], 0 };
111 const float lightDiffuse1[] = { 0, ctx_->light[1]->intensity, 0, 0 };
112 glLightfv(GL_LIGHT1, GL_POSITION, lightPosition1);
113 glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse1);
114 glEnable(GL_LIGHT1);
115
116 glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
117 glEnable(GL_COLOR_MATERIAL);
118
119
120 // automatische Normalisierung
121 // glEnable(GL_NORMALIZE);
122
123 // Tiefen Test aktivieren
124 glEnable(GL_DEPTH_TEST);
125 glDepthFunc(GL_LESS);
126 glClearColor(1.0,1.0,1.0,1.0);
127
128 // Smooth Schattierung aktivieren
129 glShadeModel(GL_SMOOTH);
130
131 // Culling
132 glCullFace(GL_BACK);
133
134 // Projection
135 glMatrixMode(GL_PROJECTION);
136 gluPerspective(40.0,1.0,1.0,10.0);
137
138 // LookAt
139 glMatrixMode(GL_MODELVIEW);
140 gluLookAt(0.0, 3.0, 7.0, // from (0,3,7)
141 0.0, 0.0, 0.0, // to (0,0,0)
142 0.0, 1.0, 0.); // up
143
144 }
145 void CGIllumination::onSize(unsigned int newWidth,unsigned int newHeight) {
146 if((newWidth > 0) && (newHeight > 0)) {
147 // Passe den OpenGL-Viewport an die neue Fenstergroesse an:
148 glViewport(0, 0, newWidth - 1, newHeight - 1);
149
150 // Passe die OpenGL-Projektionsmatrix an die neue
151 // Fenstergroesse an:
152 glMatrixMode(GL_PROJECTION);
153 glLoadIdentity();
154 gluPerspective(40.0,float(newWidth)/float(newHeight),1.0, 10.0);
155
156 // Schalte zurueck auf die Modelview-Matrix
157 glMatrixMode(GL_MODELVIEW);
158 }
159 }
160
161 void CGIllumination::onKey(unsigned char key) {
162 static GLfloat z = 3.;
163 switch (key) {
164 case 27: { exit(0); break; }
165 case '+': { zoom_*= 1.1; break; }
166 case '-': { zoom_*= 0.9; break; }
167 case 'l' : { glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; }
168 case 'f' : { glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; }
169 case '1' : { glEnable(GL_LIGHTING); phong_ = false; break; }
170 case '2' : { glDisable(GL_LIGHTING); phong_ = true; break; }
171 case 'c' : { if (glIsEnabled(GL_CULL_FACE)) { glDisable(GL_CULL_FACE); } else { glEnable(GL_CULL_FACE); } break; }
172 case ' ' : { stop_ = !stop_; break; }
173 }
174 onDraw();
175 }
176
177 void CGIllumination::onIdle() {
178 if (!stop_) {
179 rotate_ -= 2;
180 onDraw();
181 }
182 }
183
184 inline double max(double x, double y) {
185 return (x<y) ? y : x;
186 }
187 inline double min(double x, double y) {
188 return (x<y) ? x : y;
189 }
190
191 double CGIllumination::fatt(const Vector& punkt, const Vector& licht, const int li) {
192 double temp = 1/(ctx_->light[li]->constant+
193 ctx_->light[li]->linear* abs(punkt-licht)+
194 ctx_->light[li]->quadric*abs2(punkt-licht));
195 if (temp>1) {return 1;} else {return temp;};
196 }
197
198
199 void CGIllumination::setPhongIllumination(const Vector& point, const Vector& normal) {
200 // OpenGL's lighting ?
201 if (!phong_)
202 {
203 const Color c = ctx_->material->color;
204 glColor3f(c[0], c[1], c[2]);
205 return;
206 }
207
208 // Phong Beleuchtungsmodell implementieren
209
210 // NOW COMES DA REAL STUFF !!!
211
212 // define intensity variables
213 double dIntensityAmbient = 0;
214 double dIntensityDiffuse = 0;
215 double dIntensitySpecular = 0;
216
217 // ambient intensity
218 dIntensityAmbient = Light::ambient * ctx_->material->ka;
219
220 // N = normal
221 const Vector N_norm = normal.normalized();
222 // V = view vector
223 const Vector V = *(ctx_->camera) - point;
224 const Vector V_norm = V.normalized();
225
226 // process all light sources (at most 8)
227 for (int nLight=0; nLight < MAXLIGHTSOURCES; nLight++)
228 {
229 // get a single light source
230 Light* light = ctx_->light[nLight];
231 if (light == NULL)
232 break;
233
234 // L = light vector
235 const Vector L = light->pos - point;
236 const Vector L_norm = L.normalized();
237
238 // N*L
239 const double NdotL = max(dotProduct(N_norm, L_norm), 0);
240 // R*V = (2*N*(N*L)-L)*V
241 const double RdotV = max(dotProduct((2*NdotL*N_norm - L_norm).normalized(), V_norm), 0);
242
243 // attenuation
244 const double dDistance = abs(L);
245 double dAttenuation = 1 / (light->constant + dDistance*light->linear
246 + dDistance*dDistance*light->quadric);
247 if (dAttenuation > 1)
248 dAttenuation = 1;
249 // attenuation*I
250 const double dAttI = dAttenuation * light->intensity;
251
252 // diffuse intensity
253 dIntensityDiffuse += dAttI * ctx_->material->kd * NdotL;
254 // specular intensity
255 dIntensitySpecular += dAttI * ctx_->material->ks * pow(RdotV, ctx_->material->n);
256 }
257
258 const double dIntensity = dIntensityAmbient + dIntensityDiffuse + dIntensitySpecular;
259
260 // Material color
261 Color c = ctx_->material->color;
262 c *= dIntensity;
263
264 // color per vertex
265 glColor3f(min(c[0],1), min(c[1],1), min(c[2],1));
266 }
267
268
269 inline Vector rotateYaxis(const Vector& vec, float angle)
270 {
271 Vector result;
272 const float sinus = sin(angle/180*3.1415926);
273 const float cosinus = cos(angle/180*3.1415926);
274 result[0] = vec[0]*cosinus + vec[2]*sinus;
275 result[1] = vec[1];
276 result[2] =-vec[0]*sinus + vec[2]*cosinus;
277 return result;
278 }
279
280 void CGIllumination::onDraw() {
281 // Loesche den Farb- und Tiefenspeicher
282 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
283
284
285 glPushMatrix();
286 // glRotatef(rotate_,0,1,0);
287 // glScaled(zoom_, zoom_, zoom_);
288
289 glBegin(GL_TRIANGLES);
290 for (int i=0; i<size_; i++)
291 {
292 const Vector n = rotateYaxis(tris_[i].triangleNormal(), rotate_).normalized();
293 glNormal3dv(n.rep());
294 for (int k = 0; k < 3; k++) {
295 const Vector v = rotateYaxis(tris_[i].getVertex(k), rotate_) * zoom_;
296 setPhongIllumination(v,n);
297 glVertex3dv(v.rep());
298 }
299 }
300 glEnd();
301
302 glPopMatrix();
303
304 // Nicht vergessen! Front- und Back-Buffer tauschen:
305 swapBuffers();
306 }
307
308 // Hauptprogramm
309 int main(int argc, char* argv[]) {
310 // Erzeuge eine Instanz der Beispiel-Anwendung:
311 CGIllumination sample;
312
313 cout << "Tastenbelegung:" << endl
<< "ESC Programm beenden" << endl
<< "Leertaste Objekt drehen" << endl
<< "+ Hineinzoomen" << endl
<< "- Herauszoomen" << endl
<< "l Drahtgittermodell" << endl
<< "f Oberflaechen zeichnen" << endl
<< "1 OpenGL-Beleuchtung (Blinn-Modell)" << endl
<< "2 eigene Phong-Beleuchtung" << endl
<< "c Rueckseiten zeichnen an/aus" << endl;
314
315 // Starte die Beispiel-Anwendung:
316 sample.start("Stephan Brumme, 702544");
317 return(0);
318 }
319