3D, ribbons, vertices, uv coordinates
Posted by Dennis on Aug 20, 2009 in 3D, ActionScript, Flash • 1 commentYesterday I helped my friend Tudor with a problem. When we solved it he got excited and told me to blog about it. Whatever Tudor says has to be done so here we go :-).
He was using the Ribbon3D class which is based on Papervision3D. Instead of using a color material he wanted to use a bitmap texture. When he applied this texture it was distorted. This indicated a problem with incorrect UV coordinates. Fixing this problem might seem like a daunting task for someone who is unfamiliar with UV coordinates and vertices. However, it is not as complicated as it seems.
So how does this work? The 3D ribbon object is a bunch of planes tied together to form a ribbon. A single plane consists of two triangles. A triangle is formed by connecting three vertices. A plane in turn consists of 4 vertices:

How do UV coordinates work? This post should help you understand them. If we take a rectangular image then these would be the UV coordinates for our plane:

Next we need to find out the position of the vertices. If you trace out all vertices of a single plane you can find out exactly what the order is. In the case of the 3D ribbon the order is:

Next we’ll take a look at how the plane is created. In the newPlane() function the geometry is created by pushing the four vertices and creating two triangles:
plane.geometry.vertices.push( v1, v2, v3, v4 );
plane.geometry.faces.push( newTriangle( plane, 0 ) );
plane.geometry.faces.push( newTriangle( plane, 1 ) );
The second parameter of the newTriangle function indicates which triangle to draw:
private function newTriangle( plane:TriangleMesh3D, type:int ):Triangle3D
{
var b:Boolean = Boolean( type );
var vA:Vertex3D = plane.geometry.vertices[ b ? 3 : 0 ];
var vB:Vertex3D = plane.geometry.vertices[ b ? 1 : 2 ];
var vC:Vertex3D = plane.geometry.vertices[ b ? 2 : 1 ];
var nA:NumberUV = new NumberUV( int(b), 1 );
var nB:NumberUV = new NumberUV( int(b), int(!b) );
var nC:NumberUV = new NumberUV( int(!b), int(b) );
return( new Triangle3D( plane, [ vA, vB, vC ], null, [ nA, nB, nC ] ) );
}
Note that “b ? 3 : 0″ is a shorthand if … else statement (condition ? true : false). So if 0 is passed as an argument it is converted to a boolean false (1 will converted to a boolean true). Then the shorthand if … else statement is used to specify the correct index of the vertex array. For 0/false the vertex indices will be 0 (vertex 1) , 2 (vertex 3), 1 (vertex 2). For 1/true these will be 3 (vertex 4), 1 (vertex 2), 2 (vertex 3). You can see that these vertices are in Clockwise order. This order is important because it is used in an optimisation technique called backface culling.
Now that we now the vertex order we can connect the UV coordinates to the vertices:
- coordinate (0,0) and vertex 2
- coordinate (1,0) and vertex 1
- coordinate (0,1) and vertex 4
- coordinate (1,1) and vertex 3
This changes the above code to the following (presented in a readable way):
var nA:NumberUV = b ? new NumberUV( 0, 1 ) : new NumberUV( 1, 0 );
var nB:NumberUV = b ? new NumberUV( 0, 0 ) : new NumberUV( 1, 1 );
var nC:NumberUV = b ? new NumberUV( 1, 1 ) : new NumberUV( 0, 0 );
So that’s it. It is not as hard as it seems. Or is it?




Hi,
Can you see a direction I would go to try and have a textfield instead of a colour material or bitmap, so it woul dhave the appearance of a 3d ticker tape?
Thanks mate