Difference between revisions of "Project6Fall13"

From Immersive Visualization Lab Wiki
Jump to: navigation, search
(Created page with "=Project 6: Surface of Revolution Editor= In this project you will need to build a simple editor for surfaces of revolution. This project is due on <b>Friday, November 15th</...")
 
Line 23: Line 23:
 
h) Allow the user to move the control points with the mouse by clicking on them with the left mouse button and dragging them to a new location. Don't allow moving them across the axis of symmetry. Regenerate the surface of revolution for the new set of control points every time the mouse button is released.
 
h) Allow the user to move the control points with the mouse by clicking on them with the left mouse button and dragging them to a new location. Don't allow moving them across the axis of symmetry. Regenerate the surface of revolution for the new set of control points every time the mouse button is released.
  
==2. Texture your object==
+
==2. Texture Your Object ('''40 Points''')==
  
 +
Take a photograph or find one on-line and drape it onto your surface of revolution. It needs to stretch across its entire surface area, from top to bottom and all the way around, but only on the outside, not the inside of the object.
  
 +
a) Convert the photograph to the PPM format. The free IrfanView image processing tool will do this for you.
  
You can compute normals as follows: Given the generatrix curve (x(t),y(t),0) in the x/y plane, you first compute the tangent vector (x'(t),y'(t),0). The corresponding 3D normal vector is then (-y'(t),x'(t),0), which you rotate around the y axis similar to the vertices. Don't forget to normalize the normal vectors. For the texture coordinates u/v, you can use the curve parameter t at each vertex as the u parameter. The v parameter at each vertex is proportional to the rotation angle around the y axis you applied to get the vertex.
+
b) Read the PPM image with this code.
  
Your function to produce the surface of revolution should have the following input and output parameters:
+
c) For each vertex of the outwards facing quads, set its color to bright white (<tt>glColor3f(1.0, 1.0, 1.0)</tt>). This is necessary because the texel colors will get multiplied with the surface color. Then calculate the vertex's texture coordinates, ranging from 0 to 1 in both dimensions, and set them with <tt>glTexCoord2f</tt>. Make sure the image gets mapped right side up.
  
<b>Input:</b>
+
d) Render the surface of revolution with the texture.
* Number n of Bezier segments
+
* Array of Bezier control points in the x/y plane, i.e. (xi, yi, 0). For n cubic segments, you will need (n-1)*3+4 control points.
+
* Number of points to evaluate along the curve.
+
* Angle increment for a full 360 degree rotation.
+
  
<b>Output:</b>
+
e) Make sure your control points still work as before and allow changing the shape of the object.
* Array of vertices
+
* Array of normal vectors
+
* Array of texture coordinates
+
* Index array for triangle/quad vertices
+
  
 +
'''Tips:'''
  
 +
To familiarize yourself with texture mapping in OpenGL, we provide a [[texture.cpp | sample program]] which loads a PPM file and uses it as a texture for a quad. You can cut and paste code from it into your homework project.
  
 
+
Use the following settings for your texture after your first <tt>glBindTexture</tt> for correct lighting, filtering, and texture repeat mode settings:
 
+
 
+
 
+
 
+
 
+
Use the following settings for your texture after your first <tt>glBindTexture</tt> for correct lighting, filtering, and to enable texture repeat mode:
+
  
 
<pre>
 
<pre>
// Select GL_MODULATE to mix texture with color for shading:
+
  // Make sure no bytes are padded:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  
// Use bilinear filtering:
+
  // Select GL_MODULATE to mix texture with quad color for shading:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
  
// Wrap texture over at the edges:
+
  // Use bilinear interpolation:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
</pre>
 
</pre>
  
Place at least one directional light source in world coordinates, and integrate your trackball rotation function to spin the tower around. Rotations of the tower should not rotate the light source.
+
You can compute normals as follows: Given the Bezier curve (x(t),y(t),0) in the x/y plane, you first compute the tangent vector (x'(t),y'(t),0). The corresponding 3D normal vector is then (-y'(t),x'(t),0), which you rotate around the y axis similar to the vertices. Don't forget to normalize the normal vectors. For the texture coordinates u/v, you can use the curve parameter t at each vertex as the u parameter. The v parameter at each vertex is proportional to the rotation angle around the y axis you applied to get the vertex.
 
+
<b>Note:</b>Do not use any of the curve generating OpenGL routines for this assignment (i.e., glMap, glEvalCoord, glMapGrid, glEvalMesh, gluNurbsCurve).
+
 
+
===Instructions for Creating a Surface of Revolution with Bezier Curves===
+
 
+
You will need to create a function which generates a surface of revolution with a set of Bezier curves. You can read up on surfaces of revolution at [http://mathworld.wolfram.com/SurfaceofRevolution.html | Mathworld] or at [http://en.wikipedia.org/wiki/Surface_of_revolution | Wikipedia]. The main idea to generate a surface of revolution is to define a 2D curve in the x/y plane, called the <i>generatrix</i>, which is then rotated around the y axis to produce the surface. You should use a piecewise cubic Bezier curve as the generatrix, with at least three pieces.
+
 
+
To produce a mesh of triangles or quads:
+
 
+
* Create a set of control points for the cubic Bezier generatrix which will create the object outline. The curve should be C1 continuous between its pieces. (<b>15 points</b>)
+
* Evaluate a number of sample points along the curve in the x/y plane. (<b>15 points</b>)
+
* Rotate the points around the y axis at a set of angles, and connect the resulting points to a mesh of triangles or quads (<b>10 points</b>). The mesh needs to be closed (no gaps) (<b>5 points</b>).
+
* Generate normals and texture coordinates at the mesh vertices. The texture coordinates should cover a range much greater than 0 to 1 so that the texture gets repeated several times to create the effect of a higher resolution texture. (<b>15 points</b>)
+
 
+
You can compute normals as follows: Given the generatrix curve (x(t),y(t),0) in the x/y plane, you first compute the tangent vector (x'(t),y'(t),0). The corresponding 3D normal vector is then (-y'(t),x'(t),0), which you rotate around the y axis similar to the vertices. Don't forget to normalize the normal vectors. For the texture coordinates u/v, you can use the curve parameter t at each vertex as the u parameter. The v parameter at each vertex is proportional to the rotation angle around the y axis you applied to get the vertex.
+
 
+
Your function to produce the surface of revolution should have the following input and output parameters:
+
 
+
<b>Input:</b>
+
* Number n of Bezier segments
+
* Array of Bezier control points in the x/y plane, i.e. (xi, yi, 0). For n cubic segments, you will need (n-1)*3+4 control points.
+
* Number of points to evaluate along the curve.
+
* Angle increment for a full 360 degree rotation.
+
 
+
<b>Output:</b>
+
* Array of vertices
+
* Array of normal vectors
+
* Array of texture coordinates
+
* Index array for triangle/quad vertices
+
 
+
<b>Tip:</b> This [http://www.cs.princeton.edu/~min/cs426/jar/bezier.html interactive Java applet] will let you visually set control points and show the curves they generate.  You can turn on the C1 continuity hint to see where your next control point should go to have C1 continuity (i.e., a smooth connection between two curves). The app conveniently displays the control point coordinates numerically so that you can copy them right into your code. Note: some web browsers do not allow you to copy the values directly from the web page, so please try this out before you design the perfect curve.
+
 
+
==2. Add a Flag (<b>40 points</b>)==
+
 
+
You decide that your TV tower proposal would have better chances at winning if there was a flag with the [[Media:ucsd-logo.ppm | UCSD logo]] attached to its antenna mast, above the observation deck(s). You can use a different flag texture if you choose.
+
 
+
===Approach===
+
 
+
Create a textured cubic Bezier surface patch for the flag:
+
 
+
* Create a cubic Bezier patch with a roughly square surface area and uniform tessellation to produce a triangle mesh of sufficiently high resolution for the expected curvature. [http://www.nbb.cornell.edu/neurobio/land/OldStudentProjects/cs490-96to97/anson/BezierPatchApplet/ This Java app] might help, but unfortunately does not display the control points numerically. (<b>15 points</b>)
+
* Compute the normals as the cross product of the partial derivatives at each vertex. (<b>10 points</b>)
+
* Assign texture coordinates to the mesh vertices using the parameter values and map the texture to the Bezier patch. (<b>10 points</b>)
+
* Tweak the control points and the position of the light source(s), so that the curvature of the patch is clearly visible. (<b>5 points</b>)
+
 
+
Note: The texture for the flag will be in addition to that of the tower. In order to distinguish between the two textures at rendering time you are going to need to use the <tt>glBindTexture(GL_TEXTURE_2D, texture_id)</tt> command. <tt>texture_id</tt> is a unique ID for each texture, generated by the <tt>glGenTextures</tt> command.
+
 
+
==3. Optional: Wind (<b>10 points</b>)==
+
 
+
You are invited to give a live demonstration of your 3D model to the selection committee and decide that it would look great if the flag looked like it was waving in the wind. In order to achieve this effect, you need to take the following steps:
+
 
+
* Add another Bezier patch to one side (horizontally or vertically) of the previous one and connect it seamlessly to the first, to allow for more interesting waving patterns. (<b>3 points</b>)
+
* Use a custom flag texture which is wider/taller than the given one to match the new aspect ratio of the two connected Bezier patches. (<b>2 points</b>)
+
* Wave the flag in the wind: Use smooth mathematical functions (e.g., sin, cos) to move the control points in order to make the flag appear to wave in wind. Use [http://www.cplusplus.com/reference/clibrary/cstdlib/rand/ random numbers] where appropriate to make the motion less repetitive. Do not move the two interpolating control points at the end where the flag is attached to the antenna mast. (<b>3 points</b>)
+
* Support the number keys 1 through 9 to change the wind speed from slow to fast, which should speed up the waving, but could even change your waving function to create an increasingly more dramatic effect with increasing wind speed. (<b>2 points</b>)
+

Revision as of 20:43, 6 November 2013

Project 6: Surface of Revolution Editor

In this project you will need to build a simple editor for surfaces of revolution. This project is due on Friday, November 15th. The assignment will be discussed on November 8th at 4pm, the location is TBD.

1. Build an Editor for Surfaces of Revolution (60 points)

A surface of revolution is an object that is rotationally symmetrical around a central axis.

a) Start by drawing a vertical GL_LINE from top to bottom in the center of your OpenGL window. This is your axis of symmetry.

b) Generate control points for two connected cubic Bezier curves, and display the control points as GL_POINTS - you can create larger points with the glPointSize(size) command. If your points still aren't big enough, use glutSolidSphere. All control points need to be located to the right of the axis of symmetry. Make the interpolating control points red and the approximating ones green.

c) Draw the cubic Bezier curve the control points describe in the color blue.

d) Calculate the vertices for the surface of revolution by rotating the Bezier curve around the axis of symmetry in steps of about 10 degrees (make this a variable that can be changed upon request). Evaluate about 10 sample points (again, this needs to be a variable that can be changed upon request) along each Bezier curve segment. The two curves need to be C0 continuous at the junction point, but higher level continuity is not required for now.

e) Connect the vertices with GL_QUADS to form a surface. Choose a nice color for the surface.

f) Render each GL_QUAD twice, and calculate correct (normalized!) normals: render the quads once in clockwise vertex order and once counter-clockwise, so that both inside and outside of your surface of revolution are rendered correctly. Make sure backface culling is turned on with glEnable(GL_CULL_FACE), or else your surface will flicker.

g) Enable at least one directional light source and position it so that it nicely illuminates the object. Use a light direction from above and behind the camera and slightly offset to the left.

h) Allow the user to move the control points with the mouse by clicking on them with the left mouse button and dragging them to a new location. Don't allow moving them across the axis of symmetry. Regenerate the surface of revolution for the new set of control points every time the mouse button is released.

2. Texture Your Object (40 Points)

Take a photograph or find one on-line and drape it onto your surface of revolution. It needs to stretch across its entire surface area, from top to bottom and all the way around, but only on the outside, not the inside of the object.

a) Convert the photograph to the PPM format. The free IrfanView image processing tool will do this for you.

b) Read the PPM image with this code.

c) For each vertex of the outwards facing quads, set its color to bright white (glColor3f(1.0, 1.0, 1.0)). This is necessary because the texel colors will get multiplied with the surface color. Then calculate the vertex's texture coordinates, ranging from 0 to 1 in both dimensions, and set them with glTexCoord2f. Make sure the image gets mapped right side up.

d) Render the surface of revolution with the texture.

e) Make sure your control points still work as before and allow changing the shape of the object.

Tips:

To familiarize yourself with texture mapping in OpenGL, we provide a sample program which loads a PPM file and uses it as a texture for a quad. You can cut and paste code from it into your homework project.

Use the following settings for your texture after your first glBindTexture for correct lighting, filtering, and texture repeat mode settings:

  // Make sure no bytes are padded:
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

  // Select GL_MODULATE to mix texture with quad color for shading:
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  // Use bilinear interpolation:
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

You can compute normals as follows: Given the Bezier curve (x(t),y(t),0) in the x/y plane, you first compute the tangent vector (x'(t),y'(t),0). The corresponding 3D normal vector is then (-y'(t),x'(t),0), which you rotate around the y axis similar to the vertices. Don't forget to normalize the normal vectors. For the texture coordinates u/v, you can use the curve parameter t at each vertex as the u parameter. The v parameter at each vertex is proportional to the rotation angle around the y axis you applied to get the vertex.