|   | 327 |  | 
                  
                          |   | 328 |  | 
                  
                          |   | 329 | == Interactivity == | 
                  
                          |   | 330 | [[Image(teapot.png,right)]] | 
                  
                          |   | 331 |  | 
                  
                          |   | 332 | Assemble the following Utah teapot model and attached virtual [attachment:trackball.h] and [attachment:trackball.c] sources from SGI. We use  | 
                  
                          |   | 333 | {{{ | 
                  
                          |   | 334 | #!c | 
                  
                          |   | 335 | #include <stdio.h> | 
                  
                          |   | 336 | #include <stdlib.h> | 
                  
                          |   | 337 | #include <string.h> | 
                  
                          |   | 338 |  | 
                  
                          |   | 339 | #include <GL/glew.h> | 
                  
                          |   | 340 | #include <GL/glut.h> | 
                  
                          |   | 341 | #include "trackball.h" | 
                  
                          |   | 342 |  | 
                  
                          |   | 343 | GLuint p; // program needs to be global! | 
                  
                          |   | 344 | float lpos[4] = {1, 0.5, 1, 0}; | 
                  
                          |   | 345 | GLfloat m[4][4]; // modelview rotation matrix | 
                  
                          |   | 346 | float last[4], cur[4]; // rotation tracking quaternions  | 
                  
                          |   | 347 | int width, height, beginx, beginy; | 
                  
                          |   | 348 | float p1x, p1y, p2x, p2y; | 
                  
                          |   | 349 |  | 
                  
                          |   | 350 | void display(void) { | 
                  
                          |   | 351 |   GLuint location = glGetUniformLocation(p, "RotationMatrix"); | 
                  
                          |   | 352 |   build_rotmatrix(m, cur);   | 
                  
                          |   | 353 |   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 
                  
                          |   | 354 |   glLightfv(GL_LIGHT0, GL_POSITION, lpos); | 
                  
                          |   | 355 |   if( location >= 0 ) | 
                  
                          |   | 356 |     glUniformMatrix4fv(location, 1, GL_FALSE, &m[0][0]); | 
                  
                          |   | 357 |   glutSolidTeapot(0.6); | 
                  
                          |   | 358 |   glutSwapBuffers(); | 
                  
                          |   | 359 | } | 
                  
                          |   | 360 |  | 
                  
                          |   | 361 |  | 
                  
                          |   | 362 | void processNormalKeys(unsigned char key, int x, int y) { | 
                  
                          |   | 363 |         if (key == 27)  | 
                  
                          |   | 364 |                 exit(0); | 
                  
                          |   | 365 | } | 
                  
                          |   | 366 |  | 
                  
                          |   | 367 | void mouse(int button,int state, int x, int y)    | 
                  
                          |   | 368 | { | 
                  
                          |   | 369 |   beginx = x; | 
                  
                          |   | 370 |   beginy = y; | 
                  
                          |   | 371 | } | 
                  
                          |   | 372 |  | 
                  
                          |   | 373 | void motion(int x,int y)    | 
                  
                          |   | 374 | { | 
                  
                          |   | 375 |   p1x = (2.0*beginx - width)/width; | 
                  
                          |   | 376 |   p1y = (height - 2.0*beginy)/height; | 
                  
                          |   | 377 |   p2x = (2.0 * x - width) / width; | 
                  
                          |   | 378 |   p2y = (height - 2.0 * y) / height; | 
                  
                          |   | 379 |   trackball(last, p1x, p1y, p2x, p2y);    | 
                  
                          |   | 380 |   add_quats(last, cur, cur);    | 
                  
                          |   | 381 |   beginx = x; | 
                  
                          |   | 382 |   beginy = y; | 
                  
                          |   | 383 |   glutPostRedisplay();    | 
                  
                          |   | 384 | } | 
                  
                          |   | 385 |  | 
                  
                          |   | 386 | void reshape (int w, int h) | 
                  
                          |   | 387 | { | 
                  
                          |   | 388 |   double l = 1; | 
                  
                          |   | 389 |   width=w;  height=h; | 
                  
                          |   | 390 |   glViewport (0, 0, w, h); | 
                  
                          |   | 391 |   glMatrixMode (GL_PROJECTION); | 
                  
                          |   | 392 |   glLoadIdentity(); | 
                  
                          |   | 393 |   glOrtho(-l, l, -l, l, -l, l); | 
                  
                          |   | 394 |   glMatrixMode(GL_MODELVIEW); | 
                  
                          |   | 395 |   glLoadIdentity(); | 
                  
                          |   | 396 | } | 
                  
                          |   | 397 |  | 
                  
                          |   | 398 | static const GLchar * vertex_shader[] ={"\ | 
                  
                          |   | 399 | varying vec3 normal, lightDir;\ | 
                  
                          |   | 400 | uniform mat4 RotationMatrix;\ | 
                  
                          |   | 401 | void main()\ | 
                  
                          |   | 402 | {          \ | 
                  
                          |   | 403 |   lightDir=normalize(vec3(gl_LightSource[0].position));\ | 
                  
                          |   | 404 |   normal=normalize(gl_NormalMatrix*gl_Normal);\ | 
                  
                          |   | 405 |   gl_Position = gl_ProjectionMatrix * \ | 
                  
                          |   | 406 |   RotationMatrix*gl_ModelViewMatrix*gl_Vertex;\ | 
                  
                          |   | 407 | }"}; | 
                  
                          |   | 408 |  | 
                  
                          |   | 409 | static const GLchar * fragment_shader[] ={"\ | 
                  
                          |   | 410 | /* simple toon fragment shader */\ | 
                  
                          |   | 411 | /* www.lighthouse3d.com        */\ | 
                  
                          |   | 412 | \ | 
                  
                          |   | 413 | varying vec3 normal, lightDir;\ | 
                  
                          |   | 414 | \ | 
                  
                          |   | 415 | void main()\ | 
                  
                          |   | 416 | {\ | 
                  
                          |   | 417 |         float intensity;\ | 
                  
                          |   | 418 |         vec3 n;\ | 
                  
                          |   | 419 |         vec4 color;\ | 
                  
                          |   | 420 | \ | 
                  
                          |   | 421 |         n = normalize(normal);\ | 
                  
                          |   | 422 |         intensity = max(dot(lightDir,n),0.0);\ | 
                  
                          |   | 423 |         if (intensity > 0.98)\ | 
                  
                          |   | 424 |                 color = vec4(0.8,0.8,0.8,1.0);\ | 
                  
                          |   | 425 |         else if (intensity > 0.5)\ | 
                  
                          |   | 426 |                 color = vec4(0.4,0.4,0.8,1.0);\ | 
                  
                          |   | 427 |         else if (intensity > 0.25)\ | 
                  
                          |   | 428 |                 color = vec4(0.2,0.2,0.4,1.0);\ | 
                  
                          |   | 429 |         else\ | 
                  
                          |   | 430 |                 color = vec4(0.1,0.1,0.1,1.0);\ | 
                  
                          |   | 431 |         gl_FragColor = color;\ | 
                  
                          |   | 432 | }"}; | 
                  
                          |   | 433 |  | 
                  
                          |   | 434 | void setShaders() | 
                  
                          |   | 435 | { | 
                  
                          |   | 436 |   GLuint v, f; | 
                  
                          |   | 437 |  | 
                  
                          |   | 438 |   v = glCreateShader(GL_VERTEX_SHADER); | 
                  
                          |   | 439 |   f = glCreateShader(GL_FRAGMENT_SHADER); | 
                  
                          |   | 440 |   glShaderSource(v, 1, vertex_shader, NULL); | 
                  
                          |   | 441 |   glShaderSource(f, 1, fragment_shader, NULL); | 
                  
                          |   | 442 |   glCompileShader(v); | 
                  
                          |   | 443 |   glCompileShader(f); | 
                  
                          |   | 444 |   p = glCreateProgram(); | 
                  
                          |   | 445 |   glAttachShader(p,f); | 
                  
                          |   | 446 |   glAttachShader(p,v); | 
                  
                          |   | 447 |   glLinkProgram(p); | 
                  
                          |   | 448 |   glUseProgram(p); | 
                  
                          |   | 449 | } | 
                  
                          |   | 450 |  | 
                  
                          |   | 451 | int main(int argc, char **argv) | 
                  
                          |   | 452 | { | 
                  
                          |   | 453 |   glutInit(&argc, argv); | 
                  
                          |   | 454 |   glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); | 
                  
                          |   | 455 |   glutInitWindowSize(512, 512); | 
                  
                          |   | 456 |   glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-512)/2, | 
                  
                          |   | 457 |                          (glutGet(GLUT_SCREEN_HEIGHT)-512)/2); | 
                  
                          |   | 458 |   glutCreateWindow("Use mouse to rotate"); |