Computer graphics -- 2007-2008 -- info.uvt.ro/Laboratory 5

Important! These pages are somehow outdated and it is recommended to consult the newer version at Computer graphics -- 2008-2009 -- info.uvt.ro (by Marc Frâncu).

Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, 6, 7, 8, evaluation, tools, repository.


Texture handling

edit

Discussion points

edit
  • what is a texture;
  • texture image size;
  • texture objects;
  • texture coordinate mapping;
  • texture coordinate matrix;
  • texture application modes;
  • repeating and clamping;
  • texture parameters;
  • mipmapping;

Steps

edit
  1. create a texture object -- glGenTextures;
  2. specify a texture for the texture object:
    1. load the texture image from a file (or generate it on the fly);
    2. bind the texture image to the texture object -- glTexImage2D;
  3. specify texture parameters -- glTexParameter;
  4. use the texture object:
    1. enable texture mapping -- glEnable(GL_TEXTURE_2D);
    2. bind the texture object to the context -- glBindTexture;
    3. draw the scene and map the texture to vertices -- glTexCoord;

References

edit

Java API

edit

Usage

edit

The following code can be found in the SVN repository, in the examples folder as example-08.

  • Creating and loading the texture:
[...]
	public void init(GLAutoDrawable canvas)
	{
		[...]
		
		try {
			this.texture = TextureIO.newTexture (new File ("./data/grass.png"), true);
		} catch (IOException exception) {
			exception.printStackTrace();
		}
		
		[...]
	}
[...]
	
	private Texture texture;
	
[...]
  • Binding, enabling, and mapping vertices:
[...]
	public void display(GLAutoDrawable canvas)
	{
		[...]
		
		this.texture.bind();
		this.texture.enable();
		
		gl.glBegin(GL.GL_QUADS);
		
		gl.glTexCoord2d(0, 1);
		gl.glVertex3d(-1, -1, 0);
		
		gl.glTexCoord2d(1, 1);
		gl.glVertex3d(+1, -1, 0);
		
		gl.glTexCoord2d(1, 0);
		gl.glVertex3d(+1, +1, 0);
		
		gl.glTexCoord2d(0, 0);
		gl.glVertex3d(-1, +1, 0);
		
		gl.glEnd();
		
		this.texture.disable();
		
		[...]
	}
[...]

Mapping a texture onto a sphere

edit

More details on how to programmatic build a sphere and how texture coordinates are binded can be found here: [Parametric Equation of a Sphere and Texture Mapping (broken link)]

The following code can be found in the SVN repository, in the examples folder as example-09.

[...]
	gl.glPushMatrix();
		gl.glRotated(90, 1, 0, 0);
		gl.glEnable(GL.GL_TEXTURE_2D);
		this.texture.bind();
		GLUquadric ground = glu.gluNewQuadric();
                //enabling texturing on the quadric
		glu.gluQuadricTexture(ground, true);
		glu.gluSphere(ground, 0.5, 64, 64);
		glu.gluDeleteQuadric(ground);
	gl.glPopMatrix();
[...]

While this technique is general and can be used to load all sorts of textures, there are cases in which it is not sufficient. One example is related to sphere mapping. Let's say we have a sphere representing a planet on which we want to apply a texture representing the planet's surface.

However when applying a texture on a sphere in this way, you will notice that the sphere is lighted in the same way anywhere. In order to produce the correct light effects one needs to enable sphere mapping by using GL_SPHERE_MAP:

[...]
	public void init(GLAutoDrawable canvas)
	{
                [...]
                // Set The Texture Generation Mode For S To Sphere Mapping (NEW)
                gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP);                
                // Set The Texture Generation Mode For T To Sphere Mapping (NEW) 
                gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP);
        }

	public void display(GLAutoDrawable canvas)
	{
                [...]
                // Enable Texture Coord Generation For S (NEW)
	        gl.glEnable(GL.GL_TEXTURE_GEN_S); 		                
	        // Enable Texture Coord Generation For T (NEW)        
	        gl.glEnable(GL.GL_TEXTURE_GEN_T);
                //draw the object
        }

When applying sphere mapping, however, the texture will be drawn so that its center will always face the camera, prohibiting the rotation of the texture on the sphere.

Model loading

edit

Sometimes it is useful to create objects outside the OpenGL environment, but to be able to use them afterwards in our applications.

One way to accomplish this is to create our models with 3D Studio Max and export them as .3ds files. (Or to create them using any other application that can export such files.) And in order to import them we must write a parser that understands the .3ds files, and transforms them into a stream of OpenGL primitives -- points, lines, and simple surfaces.

Another way is to just use an existing .3ds parser, like the one provided in the project JOGL Utils.

JOGL Utils

edit

Installation

edit
  1. Download the .jar file from the project site:
  2. Copy the .jar file inside your project lib folder.
  3. Add it to the class-path:
    • in Eclipse, right-click the .jar file, select Build path -> Add to buildpath;

Usage

edit

The following code can be found in the SVN repository, in the examples folder as example-07.

  • Creating a Model3DS instance and loading the model:
[...]
	public void init(GLAutoDrawable canvas)
	{
		[...]
		
		gl.glEnable(GL.GL_NORMALIZE);
		
		this.model = new Model3DS();
		this.model.load("./data/screw.3ds");
		
		[...]
	}
	
[...]
	
	private Model3DS model;
[...]
  • Rendering the model:
[...]
	public void display(GLAutoDrawable canvas)
	{
		GL gl = canvas.getGL();
		
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
		
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
		
		gl.glTranslated(0, 0, -4);
		
		gl.glPushMatrix();
			
			gl.glScaled(1.0 / 300, 1.0 / 300, 1.0 / 300);
			
			gl.glRotated(this.angle * 1.1, 1, 0, 0);
			gl.glRotated(this.angle * 1.2, 0, 1, 0);
			gl.glRotated(this.angle * 1.3, 0, 0, 1);
			
			
			for (int objectI = 0; objectI < this.model.getNumberOfObjects(); objectI++) {
				Obj object = this.model.getObject(objectI);
				
				gl.glBegin(GL.GL_TRIANGLES);
				
				for (int faceI = 0; faceI < object.numOfFaces; faceI++) {
					
					Face face = object.faces[faceI];
					
					for (int vertexI = 0; vertexI < 3; vertexI++) {
						
						Vec3 vertex = object.verts[face.vertIndex[vertexI]];
						Vec3 normal = object.normals[face.vertIndex[vertexI]];
						
						gl.glNormal3f(normal.x, normal.y, normal.z);
						gl.glVertex3f(vertex.x, vertex.y, vertex.z);
					}	
				}
				
				gl.glEnd();
			}
			
			
		gl.glPopMatrix();
		
		gl.glFlush();
		
		this.angle += 1;
	}
[...]

Models

edit

You could find .3ds files on the internet by a simple search query: http://www.google.com/search?hl=en&q=free+3ds+models

Assignment

edit

This is the fifth assignment, so please commit it to the folder assignment-05.

Create a simple OpenGL application that creates a cube and adds one texture for each of the faces (each face should use a different texture).