Difference between revisions of "Project3F18"

From Immersive Visualization Lab Wiki
Jump to: navigation, search
Line 1: Line 1:
 
=Project 3: Textures, Scene Graphs and Culling=
 
=Project 3: Textures, Scene Graphs and Culling=
  
To be posted Oct 20.
+
'''This page is currently under construction. It will be completed on Oct 20. Feel free to start working on it at any time.'''
 
+
<!--
+
  
 
In this project you will need to implement a scene graph to render an army of animated robots with textures on them.
 
In this project you will need to implement a scene graph to render an army of animated robots with textures on them.
Line 9: Line 7:
 
The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.
 
The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.
  
==1. Sky Box (25 Points)==
+
==1. Applying a Texture (25 Points)==
  
Start with code that uses your trackball code, and modify it to control the camera instead. (If you didn't get that to work, keyboard controls will suffice.)
+
The first step of the project is to texture a robot component so that you can later use it as part of your robot.
  
Create a sky box for your scene with the robots. A sky box is a large, square box which is drawn around your entire scene. The inside walls of the box have pictures of a sky and a horizon. Sky boxes are typically cubic, which means that they consist of six square textures for the six sides of a cube. [http://learnopengl.com/#!Advanced-OpenGL/Cubemaps Here] is a great tutorial for sky boxes in modern OpenGL.
+
Start with code that uses your trackball code, and modify it so that trackball rotations control the camera instead. (If you didn't get that to work, keyboard controls to rotate the camera will suffice.)
  
[http://www.f-lohmueller.de/pov_tut/skyboxer/skyboxer_3.htm Here is is a nice collection of textures for sky boxes], and [http://www.custommapmakers.org/skyboxes.php here is an even bigger one].  
+
Thanks to our tutors Weichen and former tutor Yining, you have the following robot parts to choose from: head, body, limb, eye, antenna. You will find the OBJ files in [[Media:Robot-parts-2018.zip |this ZIP file]]. Each vertex has not only a 3D coordinate and a normal associated with it, but also a texture coordinate. This allows you to map textures to the surfaces of the robot. Note that unlike the previous obj files in the course, each face has different indices for v/vt/vn. So you are going to need to update your parser accordingly, when you add texture support. One of ways to deal with the different indices is to re-order (and duplicate) the v/vt/vn data when parsing so that their indices align. The following code fragment from "OpenGLInsights" might be useful:
  
Draw a cubic sky box and make it extremely big. For instance, by giving it coordinates like -1000 and +1000.
+
<pre>
 +
// For each triangle
 +
for( unsigned int v=0; v<vertexIndices.size(); v+=3 )
 +
{
 +
    // For each vertex of the triangle
 +
    for ( unsigned int i=0; i<3; i+=1 )
 +
    {
 +
        unsigned int vertexIndex = vertexIndices[v+i];
 +
        glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
 +
       
 +
        unsigned int uvIndex = uvIndices[v+i];
 +
        glm::vec2 uv = temp_uvs[ uvIndex-1 ];
  
Make sure single-sided rendering (triangle culling) is enabled with these lines somewhere in your code to ensure that you will never see the outside of the box (this assumes that your sky box is defined with the triangles facing inward):
+
        unsigned int normalIndex = normalIndices[v+i];
 +
        glm::vec3 normal = temp_normals[ normalIndex-1 ];
  
<pre>
+
        out_vertices.push_back(vertex);
glEnable(GL_CULL_FACE);  
+
        out_uvs.push_back(uv);
glCullFace(GL_BACK);  
+
        out_normals.push_back(normal);
 +
    }
 +
}
 
</pre>
 
</pre>
 +
 +
Choose '''one''' of the robot parts to apply a texture to. Best candidates are the body and the head.
 +
 +
Choose a texture image for the robot part. You can use any non-offensive image you find on the internet through image search, for example, or use a picture from your own collection. Best is to trim and resize it to a size of roughly 512x512 pixels.
 +
 +
Load the image into your C++ code. We provide [[Media:project3s16-texture.cpp | sample code]] which loads a PPM image file and uses it as a texture for a quad. If you decide to use an image in a format other than PPM (eg, JPEG), you need to convert it to PPM first. The above mentioned image processing tool [http://www.irfanview.com IrfanView] for Windows will do this for you. Alternatively, you can use a third party library such as [http://lonesock.net/soil.html SOIL] to natively load JPEG images, or other image formats.
  
 
Use the following settings for your texture after your first <code>glBindTexture(GL_TEXTURE_CUBE_MAP, id)</code> for correct lighting and filtering settings:
 
Use the following settings for your texture after your first <code>glBindTexture(GL_TEXTURE_CUBE_MAP, id)</code> for correct lighting and filtering settings:
  
 
<pre>
 
<pre>
  // Make sure no bytes are padded:
+
   // Use bilinear interpolation for higher image quality:
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Deprecated in modern OpenGL - do not use!
+
 
+
  // Select GL_MODULATE to mix texture with polygon color for shading:
+
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Deprecated in modern OpenGL - do not use!
+
 
+
   // Use bilinear interpolation:
+
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
   // Use clamp to edge to hide skybox edges:
+
   // Use clamp to edge to hide avoid repeating the texture:
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Line 45: Line 57:
 
</pre>
 
</pre>
  
To familiarize yourself with texture mapping in OpenGL, we provide [[Media:project3s16-texture.cpp | sample code]], which loads a PPM file and uses it as a texture for a quad. If you decide to use one of the above referenced sky box images, you will have to convert them from JPEG to PPM format. The free image processing tool [http://www.irfanview.com IrfanView] for Windows will do this for you. Alternatively, you can use a third party library such as [http://lonesock.net/soil.html SOIL] to natively load JPEG images.
 
  
'''Grading:'''
+
<!--
* 5 points for functional camera controls with keyboard or mouse
+
* 5 points for the sky box without textures
+
* 5 points for the textures
+
* 5 points for correct rendering of edges and corners (seamless edges)
+
* 5 points for correct culling of the skybox
+
  
 
==2. Scene Graph Engine (20 Points)==
 
==2. Scene Graph Engine (20 Points)==
Line 76: Line 82:
 
Now that we have the scene graph classes, it is time to put them to work, and build a robot with them.  
 
Now that we have the scene graph classes, it is time to put them to work, and build a robot with them.  
  
Thanks to our tutor Weichen and former tutor Yining, you have the following robot parts to choose from: head, body, limb, eye, antenna. You will find the OBJ files in [[Media:Robot-parts-2018.zip |this ZIP file]]. Each vertex has not only a 3D coordinate and a normal associated with it, but also a texture coordinate. This allows you to map textures to the surfaces of the robot. Note that unlike the previous obj files in the course, each face has different indices for v/vt/vn. So you are going to need to update your parser accordingly, when you add texture support. One of ways to deal with the different indices is to re-order (and duplicate) the v/vt/vn data when parsing so that their indices align. The following code fragment from "OpenGLInsights" might be useful:
 
 
<pre>
 
// For each triangle
 
for( unsigned int v=0; v<vertexIndices.size(); v+=3 )
 
{
 
    // For each vertex of the triangle
 
    for ( unsigned int i=0; i<3; i+=1 )
 
    {
 
        unsigned int vertexIndex = vertexIndices[v+i];
 
        glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
 
       
 
        unsigned int uvIndex = uvIndices[v+i];
 
        glm::vec2 uv = temp_uvs[ uvIndex-1 ];
 
 
        unsigned int normalIndex = normalIndices[v+i];
 
        glm::vec3 normal = temp_normals[ normalIndex-1 ];
 
 
        out_vertices.push_back(vertex);
 
        out_uvs.push_back(uv);
 
        out_normals.push_back(normal);
 
    }
 
}
 
</pre>
 
  
 
Build your own robot using the <tt>addChild</tt> methods. Use at least 3 different types of parts for your robot (e.g., body, head and limb). In total, your robot needs to consist of at least 4 parts, 3 of which need to be moving independently from one another and they need to be connected to the 4th part. At least one of the parts needs to have a texture on it. The texture can be any image you can find on the internet. If you need to resize your image, we recommend the free [https://www.irfanview.com IrfanView] if you are using Windows. (15 points)
 
Build your own robot using the <tt>addChild</tt> methods. Use at least 3 different types of parts for your robot (e.g., body, head and limb). In total, your robot needs to consist of at least 4 parts, 3 of which need to be moving independently from one another and they need to be connected to the 4th part. At least one of the parts needs to have a texture on it. The texture can be any image you can find on the internet. If you need to resize your image, we recommend the free [https://www.irfanview.com IrfanView] if you are using Windows. (15 points)

Revision as of 14:20, 20 October 2018

Project 3: Textures, Scene Graphs and Culling

This page is currently under construction. It will be completed on Oct 20. Feel free to start working on it at any time.

In this project you will need to implement a scene graph to render an army of animated robots with textures on them.

The total score for this project is 100 points. Additionally, you can obtain up to 10 points of extra credit.

1. Applying a Texture (25 Points)

The first step of the project is to texture a robot component so that you can later use it as part of your robot.

Start with code that uses your trackball code, and modify it so that trackball rotations control the camera instead. (If you didn't get that to work, keyboard controls to rotate the camera will suffice.)

Thanks to our tutors Weichen and former tutor Yining, you have the following robot parts to choose from: head, body, limb, eye, antenna. You will find the OBJ files in this ZIP file. Each vertex has not only a 3D coordinate and a normal associated with it, but also a texture coordinate. This allows you to map textures to the surfaces of the robot. Note that unlike the previous obj files in the course, each face has different indices for v/vt/vn. So you are going to need to update your parser accordingly, when you add texture support. One of ways to deal with the different indices is to re-order (and duplicate) the v/vt/vn data when parsing so that their indices align. The following code fragment from "OpenGLInsights" might be useful:

// For each triangle
for( unsigned int v=0; v<vertexIndices.size(); v+=3 )
{
    // For each vertex of the triangle
    for ( unsigned int i=0; i<3; i+=1 )
    {
        unsigned int vertexIndex = vertexIndices[v+i];
        glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
        
        unsigned int uvIndex = uvIndices[v+i];
        glm::vec2 uv = temp_uvs[ uvIndex-1 ];

        unsigned int normalIndex = normalIndices[v+i];
        glm::vec3 normal = temp_normals[ normalIndex-1 ];

        out_vertices.push_back(vertex);
        out_uvs.push_back(uv);
        out_normals.push_back(normal);
    }
}

Choose one of the robot parts to apply a texture to. Best candidates are the body and the head.

Choose a texture image for the robot part. You can use any non-offensive image you find on the internet through image search, for example, or use a picture from your own collection. Best is to trim and resize it to a size of roughly 512x512 pixels.

Load the image into your C++ code. We provide sample code which loads a PPM image file and uses it as a texture for a quad. If you decide to use an image in a format other than PPM (eg, JPEG), you need to convert it to PPM first. The above mentioned image processing tool IrfanView for Windows will do this for you. Alternatively, you can use a third party library such as SOIL to natively load JPEG images, or other image formats.

Use the following settings for your texture after your first glBindTexture(GL_TEXTURE_CUBE_MAP, id) for correct lighting and filtering settings:

  // Use bilinear interpolation for higher image quality:
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  // Use clamp to edge to hide avoid repeating the texture:
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);