Difference between revisions of "Project5Fall14"

From Immersive Visualization Lab Wiki
Jump to: navigation, search
Line 1: Line 1:
 
=Project 5: Light and Shade=
 
=Project 5: Light and Shade=
 
'''THIS PAGE IS UNDER CONSTRUCTION - PLEASE DO NOT YET START WITH THIS PROJECT'''
 
  
 
This project is on OpenGL lighting and shading, and includes GLSL shader programs.  
 
This project is on OpenGL lighting and shading, and includes GLSL shader programs.  
Line 49: Line 47:
 
</pre>
 
</pre>
  
<!--
+
Once you loaded your model file, apply your full-screen algorithm from project 2.2 to scale the data sets up or down to match the screen size, and render the model. Use your rotation and scale routines to spin the model around and zoom in.  
==1. Mouse Control (20 Points)==
+
  
Start by reviving your application from assignment 2: you will need to be able to display the cube, as well as the following three 3D models into your application and display them at reasonable sizes (screen filling). The function keys should switch between the models.
+
==2. Mouse Control (30 Points)==
  
These are the models you need to be able to load, you will have to unzip them to get at the OBJ files. Note that some of them are different files than before, as we now need files with normals. The OBJ reader we gave you in project 2 already parses normals.
+
Now it is time to improve on those keyboard commands for rotations of your 3D model. Add a mouse control function, to allow rotating the model about the center of your OpenGL window, as well as scaling the model up and down. The '''left mouse button should be used for rotation''', the '''right mouse button should zoom in and out''' when the mouse is moved up or down while it is pressed.  
  
* [[Media:dragon.zip|Dragon ]]
+
[[Media:cube.mpg|This video]] shows how the trackball-like rotation should work.  
* [[Media:bunny_n.zip|Bunny ]]
+
* [[Media:sandal.zip|Sandal ]]
+
 
+
You are welcome but not required to support the keyboard commands from assignment 2 to move around the models. However, you will need to add mouse control, which will allow rotating the model about the center of your OpenGL window, as well as scaling the model up and down. The '''left mouse button should be used for rotation''', the '''right mouse button should zoom in and out''' when the mouse is moved up or down while it is pressed.
+
 
+
[[Media:cube.mpg|This video]] shows how the trackball-like rotation should work. We provide [[Media:trackball-code.txt|sample code for the trackball rotation.]] You will need to adapt it to the syntax of your matrix and vector classes and get it to work within your application.
+
 
+
If you cannot get the sample trackball code to work, the following description of the algorithm might help you.
+
  
The figure below illustrates how to translate mouse movement into a rotation axis and angle. m0 and m1 are consecutive 2D mouse positions. These positions define two locations v and w on a 3D virtual sphere that fills the rendering window. Use their cross product as the rotation axis a = v x w, and the angle between v and w as the rotation angle.
+
The figure below illustrates how to translate mouse movement into a rotation axis and angle. m0 and m1 are consecutive 2D mouse positions. These positions define two locations v and w on an invisible 3D sphere that fills the rendering window. Use their cross product as the rotation axis a = v x w, and the angle between v and w as the rotation angle.
  
 
[[Image:Trackball.jpg]]
 
[[Image:Trackball.jpg]]
Line 72: Line 61:
 
Horizontal mouse movement exactly in the middle of the window should result in a rotation just around the y-axis. Vertical mouse movement exactly in the middle of the window should result in a rotation just around the x-axis. Mouse movements in other areas and directions should result in rotations about an axis a which is not parallel to any single coordinate axis, and is determined by the direction the mouse is moved in.
 
Horizontal mouse movement exactly in the middle of the window should result in a rotation just around the y-axis. Vertical mouse movement exactly in the middle of the window should result in a rotation just around the x-axis. Mouse movements in other areas and directions should result in rotations about an axis a which is not parallel to any single coordinate axis, and is determined by the direction the mouse is moved in.
  
Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object to world transformation matrix for the model or the light source you are moving.
+
Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object to world transformation matrix for the cube.
  
 
To access the mouse x and y coordinates, you will need to use GLUT's callback functions [http://www.opengl.org/resources/libraries/glut/spec3/node50.html glutMouseFunc()], which gets called when you press a mouse button, and [http://www.opengl.org/resources/libraries/glut/spec3/node51.html glutMotionFunc()], which gets called constantly while you hold the button down and move the mouse. Note that successive trackball rotations must build on previous ones; at no point should the model snap back to a previous or default position.
 
To access the mouse x and y coordinates, you will need to use GLUT's callback functions [http://www.opengl.org/resources/libraries/glut/spec3/node50.html glutMouseFunc()], which gets called when you press a mouse button, and [http://www.opengl.org/resources/libraries/glut/spec3/node51.html glutMotionFunc()], which gets called constantly while you hold the button down and move the mouse. Note that successive trackball rotations must build on previous ones; at no point should the model snap back to a previous or default position.
  
==2. OpenGL Lighting and Shading (40 points)==
+
For step by step instructions, take a look at [http://web.cse.ohio-state.edu/~crawfis/Graphics/VirtualTrackball.html this tutorial]. Note that the tutorial was written for Windows messages, instead of GLUT mouse functions. This means that you'll need to replace the "CSierpinskiSolidsView::OnLButtonDown" function with "glutMouseFunc", "CSierpinskiSolidsView::OnMouseMove" with "glutMotionFunc", etc.
 +
To help you understand the code here is a line-by-line commented version of the trackBallMapping function:
 +
 
 +
Vec3f CSierpinskiSolidsView::trackBallMapping(CPoint point)    // The CPoint class is a specific Windows class. Either use separate x and y values for the mouse location, or use a Vector3 in which you ignore the z coordinate.
 +
{
 +
    Vec3f v;    // Vector v is the synthesized 3D position of the mouse location on the trackball
 +
    float d;    // this is the depth of the mouse location: the delta between the plane through the center of the trackball and the z position of the mouse
 +
    v.x = (2.0*point.x - windowSize.x) / windowSize.x;  // this calculates the mouse X position in trackball coordinates, which range from -1 to +1
 +
    v.y = (windowSize.y - 2.0*point.y) / windowSize.y;  // this does the equivalent to the above for the mouse Y position
 +
    v.z = 0.0;  // initially the mouse z position is set to zero, but this will change below
 +
    d = v.Length();    // this is the distance from the trackball's origin to the mouse location, without considering depth (=in the plane of the trackball's origin)
 +
    d = (d<1.0) ? d : 1.0;  // this limits d to values of 1.0 or less to avoid square roots of negative values in the following line
 +
    v.z = sqrtf(1.001 - d*d);  // this calculates the Z coordinate of the mouse position on the trackball, based on Pythagoras: v.z*v.z + d*d = 1*1
 +
    v.Normalize(); // Still need to normalize, since we only capped d, not v.
 +
    return v;  // return the mouse location on the surface of the trackball
 +
}
 +
 
 +
Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object-to-world transformation matrix of the object you are rotating.
 +
 
 +
<!--
 +
==3. OpenGL Lighting and Shading (40 points)==
  
 
Write classes to manage light and material properties (<tt>Light</tt> and <tt>Material</tt>). As a starting point, refer to the relevant sections in [http://www.glprogramming.com/red/chapter05.html Chapter 5 of the OpenGL Programming Guide], as well as the [http://www.opengl.org/archives/resources/faq/technical/lights.htm OpenGL Lighting FAQ].
 
Write classes to manage light and material properties (<tt>Light</tt> and <tt>Material</tt>). As a starting point, refer to the relevant sections in [http://www.glprogramming.com/red/chapter05.html Chapter 5 of the OpenGL Programming Guide], as well as the [http://www.opengl.org/archives/resources/faq/technical/lights.htm OpenGL Lighting FAQ].

Revision as of 01:13, 15 November 2014

Project 5: Light and Shade

This project is on OpenGL lighting and shading, and includes GLSL shader programs.

This project is due on Friday, November 21st at 3:30pm and will be discussed in CSB 001 on Monday, November 17th at 5pm.

Notes:

  • GLSL shaders will be covered in class on Tuesday, November 18th.
  • This project does not require a scene graph data structure. But we encourage you to use your scene graph for this and the remaining projects because it can make your code easier to write and debug.

1. 3D Model Loader

OBJ files are 3D model files which store the shape of an object with a number of vertices, associated vertex normals, and the required connectivity information to form triangles. Wikipedia has an excellent page on the OBJ file format. The file format is an ASCII text format, which means that the files can be viewed and edited with a text editor.

Here are three files for you to work with:

The files provided in this project only use the following three data types (other OBJ files may support more):

  • v: 'vertex': followed by six floating point numbers. The first three are for the vertex position (x,y,z coordinate), the next three are for the vertex color (red, green, blue) ranging from 0 to 1. Example:
    v 0.145852 0.104651 0.517576 0.2 0.8 0.4
  • vn: 'vertex normal': three floating point numbers, separated by white space. The numbers are for a vector which is used as the normal for a triangle. Example:
    vn -0.380694 3.839313 4.956321
  • f: 'face': lists three sets of indices to vertices and normals, which are the three corners of a triangle. Example:
    f 31514//31514 31465//31465 31464//31464

Lines starting with a '#' sign are comments and can safely be ignored.

Write your parser so that it goes through the OBJ file, line by line. It should read in the first character of each line and based on it decide how to proceed. Lines with parameters can be read with the fscanf command. Here is an example for vertices:

FILE* fp;     // file pointer
float x,y,z;  // vertex coordinates
float r,g,b;  // vertex color
int c1,c2;    // characters read from file

fp = fopen("bunny.obj","rb");
if (fp==NULL) { cerr << "error loading file" << endl; exit(-1); }

c1 = fgetc(fp);
c2 = fgetc(fp);
if (c1=='v') && (c2==' ')
  fscanf(fp, "%f %f %f %f %f %f", &x, &y, &z, &r, &g, &b);
// parse other cases and loop over lines of file

fclose(fp);   // make sure you don't forget to close the file when done

Once you loaded your model file, apply your full-screen algorithm from project 2.2 to scale the data sets up or down to match the screen size, and render the model. Use your rotation and scale routines to spin the model around and zoom in.

2. Mouse Control (30 Points)

Now it is time to improve on those keyboard commands for rotations of your 3D model. Add a mouse control function, to allow rotating the model about the center of your OpenGL window, as well as scaling the model up and down. The left mouse button should be used for rotation, the right mouse button should zoom in and out when the mouse is moved up or down while it is pressed.

This video shows how the trackball-like rotation should work.

The figure below illustrates how to translate mouse movement into a rotation axis and angle. m0 and m1 are consecutive 2D mouse positions. These positions define two locations v and w on an invisible 3D sphere that fills the rendering window. Use their cross product as the rotation axis a = v x w, and the angle between v and w as the rotation angle.

Trackball.jpg

Horizontal mouse movement exactly in the middle of the window should result in a rotation just around the y-axis. Vertical mouse movement exactly in the middle of the window should result in a rotation just around the x-axis. Mouse movements in other areas and directions should result in rotations about an axis a which is not parallel to any single coordinate axis, and is determined by the direction the mouse is moved in.

Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object to world transformation matrix for the cube.

To access the mouse x and y coordinates, you will need to use GLUT's callback functions glutMouseFunc(), which gets called when you press a mouse button, and glutMotionFunc(), which gets called constantly while you hold the button down and move the mouse. Note that successive trackball rotations must build on previous ones; at no point should the model snap back to a previous or default position.

For step by step instructions, take a look at this tutorial. Note that the tutorial was written for Windows messages, instead of GLUT mouse functions. This means that you'll need to replace the "CSierpinskiSolidsView::OnLButtonDown" function with "glutMouseFunc", "CSierpinskiSolidsView::OnMouseMove" with "glutMotionFunc", etc. To help you understand the code here is a line-by-line commented version of the trackBallMapping function:

Vec3f CSierpinskiSolidsView::trackBallMapping(CPoint point) // The CPoint class is a specific Windows class. Either use separate x and y values for the mouse location, or use a Vector3 in which you ignore the z coordinate. {

   Vec3f v;    // Vector v is the synthesized 3D position of the mouse location on the trackball
   float d;     // this is the depth of the mouse location: the delta between the plane through the center of the trackball and the z position of the mouse
   v.x = (2.0*point.x - windowSize.x) / windowSize.x;   // this calculates the mouse X position in trackball coordinates, which range from -1 to +1
   v.y = (windowSize.y - 2.0*point.y) / windowSize.y;   // this does the equivalent to the above for the mouse Y position
   v.z = 0.0;   // initially the mouse z position is set to zero, but this will change below
   d = v.Length();    // this is the distance from the trackball's origin to the mouse location, without considering depth (=in the plane of the trackball's origin)
   d = (d<1.0) ? d : 1.0;   // this limits d to values of 1.0 or less to avoid square roots of negative values in the following line
   v.z = sqrtf(1.001 - d*d);  // this calculates the Z coordinate of the mouse position on the trackball, based on Pythagoras: v.z*v.z + d*d = 1*1
   v.Normalize(); // Still need to normalize, since we only capped d, not v.
   return v;  // return the mouse location on the surface of the trackball

}

Once you have calculated the trackball rotation matrix for a mouse drag, you will need to multiply it with the object-to-world transformation matrix of the object you are rotating.