eScience Lectures Notes : Texture Mapping in Java3D


Slide 1 : 1 / 25 : Texture Mapping : Java3D

Texture Mapping : Java3D

Introduction

Recipe

Appearance content

Using texture appearance attributes

Texture class hierarchy

Texture2D example code

Preparing for texture mapping

Texture coordinates

Using a texture coordinate system

Specifying texture coordinates

Texture coordinates example code

Texture coordinates Second example code

Transforming texture coordinates

Texture rotation example code

Texture Generation Format

Using texture boundary modes

Controlling the appearance of textures

Combining texture and shape colors

Using texture modes

Texture modes Typical Use

Using texture mip-map modes

Using texture minification filters

Using texture magnification filters

Texture class methods


Slide 2 : 2 / 25 : Texture Mapping : Java3D

Texture Mapping : Java3D

You could model every detail of every 3D shape in your scene

This requires an enormous amount of modeling effort

More shapes means more to draw and worse interactivity

Instead, create the illusion of detail:

Not every aspect of texture mapping are availaible in Java3D, but the main one

Texture Image : 128 x 128

 


Slide 3 : 3 / 25 : Simple Texturing Recipe

Simple Texturing Recipe

  1. Prepare texture images

  2. Load the texture

  3. Set the texture in Appearance bundle

  4. Specify TextureCoordinates of Geometry


Slide 4 : 4 / 25 : Appearance content

Appearance content...

Recall that Appearance is a container for multiple visual attributes for a shape

Color and transparency control (discussed earlier)

Rendering control (discussed earlier)

Texture control


Slide 5 : 5 / 25 : Using texture appearance attributes

Using texture appearance attributes

Texture control attributes are divided among a few node components

Texture

Select a texture image and control basic mapping attributes

TextureAttributes

Control advanced mapping attributes

TexCoordGeneration

Automatically generate texture coordinates if you do not provide your own (most people provide their own)


Slide 6 : 6 / 25 : Texture class hierarchy

Texture class hierarchy

Texture is the base class for two node components that select the image to use

Methods on Texture and Texture2D select the image, and turn texture mapping on and off

Method


Slide 7 : 12 / 25 : Texture2D example code

Texture2D example code

Load a texture image

TextureLoader myLoader = new TextureLoader( "brick.jpg", this );
ImageComponent2D myImage = myLoader.getImage( );

or without the util classes

Toolkit tk = Toolkit.getDefaultToolkit();
   
img = tk.getImage("AnyImage.gif");
   
try {
	MediaTracker tracker = new MediaTracker(this);
	tracker.addImage(img, 0);
	tracker.waitForID(0);
	}
catch ( Exception e ) {}

ImageComponent2D image = 
	new ImageComponent2D(ImageComponent2D.FORMAT_RGB, img);

Create a Texture2D using the image (ImageComponent2D), and turn it on

Texture2D myTex = new Texture2D( );
myTex.setImage( 0, myImage );
myTex.setEnable( true );

Create an Appearance and set the texture in it

Appearance myAppear = new Appearance( );
myAppear.setTexture( myTex );

Assemble the shape

Shape3D myShape = new Shape3D( myText, myAppear );


Slide 8 : 8 / 25 : Preparing for texture mapping

Preparing for texture mapping

Getting a texture requires:

A file to load from disk or the Web

A TextureLoader to load that file or directly a BufferedImage or a RenderedImage

The TextureLoader utility loads an image from a file or URL, and returns an ImageComponent or Texture

An ImageComponent to hold the loaded image

Which in turn uses a standard BufferedImage

What is really important is to get an ImageComponent

ImageComponent is the base class for two image containers:

Methods on ImageComponent2D set the image it is holding

Methods


Slide 9 : 9 / 25 : Texture coordinates

Texture coordinates

We need a mapping from parts of a texture to parts of a shape


Slide 10 : 10 / 25 : Using a texture coordinate system

Using a texture coordinate system

Texture images have a true size and a logical size

True size is the width and height of the image in pixels

Must be powers of 2

Logical size is a generic treatment of image dimensions

Like the Alpha of Animations

Textures can be visualized as in a 2D texture coordinate system

Creating and editing texture images is something that is normally done external to Java 3D programs. In fact, most texture images are prepared before the program is begun. There are two essential tasks in texture image preparation:
1. ensuring the images are of acceptable dimensions, and
2. ensuring the images are saved in a file format which can be read.

Of course the image could be edited to achieve the desired color, transparency, and tiling characteristics.

For rendering efficiency, Java 3D requires the size of the texture image to be a mathematical power of two (1, 2, 4, 8, 16, ) in each dimension. Failing to meet this restriction will result in a runtime exception. If an image is not of acceptable dimensions, it must be modified (scaled or cropped) to meet the dimension requirements before it is used.

Image editing can be done in a wide variety of programs including the Java Advanced Imaging API 2 . In Figure, the two smaller images are 128 by 128, the tree is 256 by 128, and the earth is 256 by 256.

As far as the file formats are concerned, any file format can be used provided there is a method to load it.

 


Slide 11 : 11 / 25 : Specifying texture coordinates

Specifying texture coordinates

Texture coordinates define a 2D shape atop the texture image

Give texture coordinates to GeometryArray, and texture coordinate indices to IndexedGeometryArray

Methods on GeometryArray set texture coordinates (GeometryArray class methods)

void setTextureCoordinates( int index, * texCoord ) 

Method variants accept float, Point2f, and Point3f

Methods on IndexedGeometryArray set texture coordinate indices

void setTextureCoordinateIndices( int index, int[] value ) 

A 3D Shape with vertices

A 2D Shape with other vertices as an extract of the texture

A matching between the to set of vertices


Slide 12 : 12 / 25 : Texture2D example code

Texture2D example code

Load a texture image

TextureLoader myLoader = new TextureLoader( "brick.jpg", this );
ImageComponent2D myImage = myLoader.getImage( );

or without the util classes

Toolkit tk = Toolkit.getDefaultToolkit();
   
img = tk.getImage("AnyImage.gif");
   
try {
	MediaTracker tracker = new MediaTracker(this);
	tracker.addImage(img, 0);
	tracker.waitForID(0);
	}
catch ( Exception e ) {}

ImageComponent2D image = 
	new ImageComponent2D(ImageComponent2D.FORMAT_RGB, img);

Create a Texture2D using the image (ImageComponent2D), and turn it on

Texture2D myTex = new Texture2D( );
myTex.setImage( 0, myImage );
myTex.setEnable( true );

Create an Appearance and set the texture in it

Appearance myAppear = new Appearance( );
myAppear.setTexture( myTex );

Assemble the shape

Shape3D myShape = new Shape3D( myText, myAppear );


Slide 13 : 13 / 25 : Texture coordinates Second example codet

Texture coordinates Second example code


/** 
 * This defines the appearance with a texture.
 * The texture is loaded from an external file.
 * @return Appearance that uses the texture.
 */
 protected Appearance DefineAppearance() {
	//Load the texture from the external image file
	TextureLoader textLoad = new TextureLoader("housebrick.jpg", this);
	//Access the image from the loaded texture
	ImageComponent2D textImage = textLoad.getImage();
	//Create a two dimensional texture 
	Texture2D texture = new Texture2D(Texture2D.BASE_LEVEL, Texture.RGB, 
							textImage.getWidth(), textImage.getHeight());
	//Set the texture from the image loaded
	texture.setImage(0, textImage);
	//Create the appearance that will use the texture
	Appearance app = new Appearance();
	app.setTexture(texture);
	//Define how the texture will be mapped onto the surface
	//by creating the appropriate texture attributes
	TextureAttributes textAttr = new TextureAttributes();
	textAttr.setTextureMode(TextureAttributes.REPLACE);
	app.setTextureAttributes(textAttr);
	app.setMaterial(new Material());
	return app;
}
/**
 * Build a cube from an IndexedQuadArray.  This method creates
 * the vertices as a set of eight points and the normals as a set of 
 * six vectors (one for each face).  The data is then defined such
 * that each vertex has a different normal associated with it when 
 * it is being used for a different face.  The shape is created with
 * texture coordinates so that when the appearance is set it will
 * use the appearance texture on the surface.
 * @return Node that is the shape.
 */
 protected Node buildShape() {
	IndexedQuadArray indexedCube = new IndexedQuadArray(8,
										 IndexedQuadArray.COORDINATES|
										 IndexedQuadArray.NORMALS|
										 IndexedQuadArray.TEXTURE_COORDINATE_2, 24);
	Point3f[] cubeCoordinates = { new Point3f( 1.0f, 1.0f, 1.0f),
						new Point3f(-1.0f, 1.0f, 1.0f),
						new Point3f(-1.0f,-1.0f, 1.0f),
						new Point3f( 1.0f,-1.0f, 1.0f),
						new Point3f( 1.0f, 1.0f,-1.0f),
						new Point3f(-1.0f, 1.0f,-1.0f),
						new Point3f(-1.0f,-1.0f,-1.0f),
						new Point3f( 1.0f,-1.0f,-1.0f)};
	Vector3f[] normals= {new Vector3f( 0.0f, 0.0f, 1.0f),
				   new Vector3f( 0.0f, 0.0f,-1.0f),
				   new Vector3f( 1.0f, 0.0f, 0.0f),
				   new Vector3f(-1.0f, 0.0f, 0.0f),
				   new Vector3f( 0.0f, 1.0f, 0.0f),
				   new Vector3f( 0.0f,-1.0f, 0.0f)};
	//Define the texture coordinates.  These are defined
	//as floating point pairs of values that are used to 
	//map the corners of the texture image onto the vertices
	//of the face.  We then define the indices into this
	//array of values in a similar way to that used for
	//the vertices and normals.
	TexCoord2f[] textCoord = {	new TexCoord2f(1.0f,1.0f),
						new TexCoord2f(0.0f,1.0f),
						new TexCoord2f(0.0f,0.0f),
						new TexCoord2f(1.0f,0.0f)};
	int coordIndices[] =  {0,1,2,3,7,6,5,4,0,3,7,4,5,6,2,1,0,4,5,1,6,7,3,2};
	int normalIndices[] = {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5};
	int textIndices[] =   {0,1,2,3,3,0,1,2,1,2,3,0,1,2,3,0,3,0,1,2,1,2,3,0};
	indexedCube.setCoordinates(0, cubeCoordinates);
	indexedCube.setCoordinateIndices(0, coordIndices);
	indexedCube.setNormals(0,normals);
	indexedCube.setNormalIndices(0, normalIndices);
	indexedCube.setTextureCoordinates(0,0,textCoord);
	indexedCube.setTextureCoordinateIndices(0,0,textIndices);
	return new Shape3D(indexedCube, DefineAppearance());
}


 


Slide 14 : 14 / 25 : Transforming texture coordinates

Transforming texture coordinates

Methods on TextureAttributes set a Transform3D to transform texture coordinates


Slide 15 : 15 / 25 : Texture rotation example code

Texture rotation example code

Create TextureAttributes

TextureAttributes myTA = new TextureAttributes( );

Create a rotation transform (Z sticks out of the ST plane)

Transform3D myTrans = new Transform3D( );
myTrans.rotZ( Math.PI/4.0 ); // 45 degrees
myTA.setTextureTransform( myTrans );

Set the texture attributes on an Appearance

Appearance myAppear = new Appearance( );
myAppear.setTextureAttributes( myTA );

Assemble the shape

Shape3D myShape = new Shape3D( myText, myAppear );


Slide 16 : 16 / 25 : Texture Generation Format

Texture Generation Format

This setting simply specifies if the texture coordinates will be generated for a two or three dimensional texture. The possible settings are TEXTURE_COORDINATE_2 and TEXTURE_COORDINATE_3 which generates 2D texture coordinates (S and T) and 3D texture coordinates (S, T, and R), respectively.

Texture Generation Mode

There are two basic texture generation approaches: linear projection or sphere mapping.

Linear Projection

With linear projection, the texture coordinates are specified with planes. For texture coordinates of two dimensions (s,t), two planes are used. The distance from a vertex to one plane is the texture coordinate in one dimension; distance to the other plane to a vertex is the texture coordinate in the other dimension. For three dimensional textures, three planes are used. The three possible plane parameters are named planeS, planeT, and planeR, where the name corresponds to the dimension for which it is used.
Each plane is specified as a 4-tuple (plane equation). The first three values are the surface normal vector for the plane. The fourth value specifies the distance from the origin to the plane along a vector parallel to the plane's surface normal vector.

There are two variations on this automatic texture coordinate generation method. The first, called object linear, produces static texture coordinates. With object linear generated texture coordinates, if the visual object moves, the texture coordinates do not change. The second option, called eye linear, produces texture coordinates relative to the eye coordinates resulting in variable texture coordinates for the object. With eye linear texture coordinates moving objects appear to move through the texture.

DEMO Texture Generation

subdirectory of the examples jar distributed with this tutorial. This is one application you should run to see the difference. The example program is written with the Generation Mode set to EYE_LINEAR. Line 100 is the place to change to OBJECT_LINEAR generation mode.

Sphere Map

If a shiny object is in the middle of a real room, the shiny object would likely reflect the image of many of the other objects in the room. The reflections would depend on the shape of the object and orientation of things in the room. The sphere map coordinate generation mode is designed to assign texture coordinates to approximate the reflections of other objects onto the visual object as would happen for the shiny object in the example real world. When a TexCoordGeneration object is used in sphere map generation mode the texture coordinates are calculated based on the surface normals and the viewing direction. The texture used for this effect must be specially prepared. If the virtual environment of the shiny object exists in the real world, a photograph of the scene taken with a fisheye lens will create a suitable texture image. If the scene does not exist, then the texture must be created to look like the image is a photograph taken with a fisheye lens.

 


Slide 17 : 17 / 25 : Using texture boundary modes

Using texture boundary modes

void setBoundaryModeS( int mode )
void setBoundaryModeT( int mode ) 
void setBoundaryColor( Color4f color ) 


Slide 18 : 18 / 25 : Controlling the appearance of textures

Controlling the appearance of textures


Slide 19 : 19 / 25 : Combining texture and shape colors

Combining texture and shape colors

A texture image may contain:

Typically, image color modulates shape color

Blending textures using alpha

 


Slide 20 : 20 / 25 : Using texture modes

Using texture modes

The Texture mode in TextureAttributes controls how texture pixels affect shape color

REPLACE

Texture color completely replaces the shape's material color

DECAL

Texture color is blended as a decal on top of the shape's material color

MODULATE

Texture color modulates (filters) the shape's material color

BLEND

Texture color blends the shape's material color with an arbitrary blend color

 

Mode

Result color

Result transparency

REPLACE

Trgb

Ta

DECAL

Srgb*(1-Ta)+Trgb*Ta

Sa

MODULATE

Srgb*Trgb

Sa*Ta

BLEND

Srgb*(1-Trgb)+Brgb*Trgb

Sa*Ta

Where:


Slide 21 : 21 / 25 : Texture modes Typical Use Document

Texture modes Typical Use

REPLACE DECAL
   
MODULATE with white BLEND with green


Slide 22 : 22 / 25 : Using texture mip-map modes

Using texture mip-map modes


Slide 23 : 23 / 25 : Using texture minification filters

Using texture minification filters

A Minification filter controls how a texture is interpolated when a scene pixel maps to multiple texture pixels (texels)

FASTEST Use fastest method
NICEST Use best looking method
BASE_LEVEL_POINT Use nearest texel in level 0 map
BASE_LEVEL_LINEAR Bilinearly interpolate 4 nearest texels in level 0 map
MULTI_LEVEL_POINT Use nearest texel in mip-mapped maps
MULTI_LEVEL_LINEAR Bilinearly interpolate 4 nearest texels in mip-mapped maps


Slide 24 : 24 / 25 : Using texture magnification filters

Using texture magnification filters

A Magnification filter controls how a texture is interpolated when a scene pixel maps to less than one texel

FASTEST Use fastest method
NICESET Use best looking method
BASE_LEVEL_POINT Use nearest texel in level 0 map
BASE_LEVEL_LINEAR Bilinearly interpolate 4 nearest texels in level 0 map


Slide 25 : 25 / 25 : Texture class methods

Texture class methods

Methods on Texture control mip-mapping and filtering

BASE_LEVEL is the default mip-map mode
BASE_LEVEL_POINT is the default filter

void setMipMapMode( int mode )
void setMinFilter( int minFilter )
void setMagFilter( int maxFilter )

BASE_LEVEL_POINT
No interpolation

BASE_LEVEL_LINEAR
Linear interpolation of 4 nearest neighbors