Ok, now that you know how to set up your own custom object in Papervision I’m going to show you how texture maps work.
In the preceding Post we omitted the texture map in our face. So if you want to apply a BitmapMaterial to your object you won’t see the texture. So we need a texture map.
The first thing we are going to do is adding another triangle and making our object a rectangle. Something like the Plane primitive. A rectangle consists of a minimum of 2 triangles. So if we want to draw another triangle we need one more vertex.
Ok, so the code will look like this:
public function CustomTriangle (triangleMaterial : MaterialObject3D)
{
super( triangleMaterial, new Array( ), new Array( ) );
var v1 : Vertex3D = new Vertex3D( -200, -200, 0 );
var v2 : Vertex3D = new Vertex3D( 200, -200, 0 );
var v3 : Vertex3D = new Vertex3D( 200, 200, 0 );
var v4 : Vertex3D = new Vertex3D( -200, 200, 0 );
geometry.vertices.push( v1, v2, v3, v4 );
var triangleVertices1 : Array = [ v1, v2, v3 ];
var triangleFace1 : Triangle3D = new Triangle3D( this, triangleVertices1, material );
geometry.faces.push( triangleFace1 );
var triangleVertices2 : Array = [ v1, v3, v4 ];
var triangleFace2 : Triangle3D = new Triangle3D( this, triangleVertices2, material );
geometry.faces.push( triangleFace2 );
geometry.ready = true;
}
We added another vertex and built another face. As you see we used the same vertices we used with our first face. That is pretty important to understand. The vertices are not bound to the triangles. We can use them with different triangles. They are just coordinates in our 3D space.
Ok, our new rectangle will look like this now. I applied a WireFrameMaterial to it because it is better to see the triangles we made:
Ok, now it is getting interesting. We have our object and we want to apply a BitmapMaterial to it. If you already tried that you would have realized that your object did not show the texture. That is because the texture maps were missing in our faces.
A texture map is basically the information about where to display which part of the texture in every face or triangle. So every triangle gets its own texture map. And because every triangle consists of 3 vertices our texture map will need 3 information about the position of the texture. The information is an instance of the NumberUV class which holds two properties. The u and the v. Which represent the horizontal and vertical axes of our texture. Think of them as x- and y-axes. Textures are always 2D so we don’t have a z-axis here.
The u and v are numbers which go from 0 to 1. u=0 means the most left pixel of our texture and u=1 is the most right pixel in our texture.
Ok, so we take our first triangle which consists of these three vertices:
var triangleVertices1 : Array = [ v1, v2, v3 ];
v1 is the vertex in the lower left corner. That means it should display the lower left corner of our texture. That represents u=0 and v=0. You might have noticed that the y-axis is flipped in Papervision.
v2 is in the lower right corner which represents u=1 and v=0. v3 is on the upper right corner and so it gets u=1 and v=1.
In code this will look like this:
var triangleTextureMap1 : Array = [ new NumberUV( 0, 0 ), new NumberUV( 1, 0 ), new NumberUV( 1, 1 ) ];
Ok, now we need to pass our triangle the texturemap.
Before:
var triangleFace1 : Triangle3D = new Triangle3D( this, triangleVertices1, material );
After:
var triangleFace1 : Triangle3D = new Triangle3D( this, triangleVertices1, material, triangleTextureMap1 );
Ok, so we have to do the same for our second triangle. I hope it is clear now how to handle the second texturemap. Our class will look like this now:
public function CustomTriangle (triangleMaterial : MaterialObject3D)
{
super( triangleMaterial, new Array( ), new Array( ) );
var v1 : Vertex3D = new Vertex3D( -200, -200, 0 );
var v2 : Vertex3D = new Vertex3D( 200, -200, 0 );
var v3 : Vertex3D = new Vertex3D( 200, 200, 0 );
var v4 : Vertex3D = new Vertex3D( -200, 200, 0 );
geometry.vertices.push( v1, v2, v3, v4 );
var triangleVertices1 : Array = [ v1, v2, v3 ];
var triangleTextureMap1 : Array = [ new NumberUV( 0, 0 ), new NumberUV( 1, 0 ), new NumberUV( 1, 1 ) ];
var triangleFace1 : Triangle3D = new Triangle3D( this, triangleVertices1, material, triangleTextureMap1 );
geometry.faces.push( triangleFace1 );
var triangleVertices2 : Array = [ v1, v3, v4 ];
var triangleTextureMap2 : Array = [ new NumberUV( 0, 0 ), new NumberUV( 1, 1 ), new NumberUV( 0, 1 ) ];
var triangleFace2 : Triangle3D = new Triangle3D( this, triangleVertices2, material, triangleTextureMap2 );
geometry.faces.push( triangleFace2 );
geometry.ready = true;
}
And if you apply a BitmapMaterial from the outside to your object it will look like that:
It looks a bit distorted. This is because we should actually build up a rectangle with more than 2 triangles. The more you use the better the texture is rendered and the more your CPU needs to work.
We could also tell our texture map that we don’t want to display the whole texture. With your set of NumberUV instances you can practically tell every triangle to display a different part of your texture. Just use .5 instead of 1 to display only the lower left part of the texure for example. Let’s play around with the values and you will see what I mean.
Im changing the values of our first texture map like this:
var triangleTextureMap1 : Array = [ new NumberUV( 1, 1 ), new NumberUV( 1, 0 ), new NumberUV( 0, 0 ) ];
I replaced the first with the last coordinate and the texture from our first triangle is rotated now:
It is just important for you to understand, that you can tell every triangle which part of the texture it should display.
Ok, thats it for now. In the next part we are going to animate our object.
1 comment