The Lathe Curve


Creating the Scene

The novel parts of the scene creation carried out by WrapLathe3D are located in addLatheShapes( ), which generates the lathe shapes on the checkerboard:

     TextureLoader texLd3 =  new TextureLoader("textures/water.jpg", null);     Texture waterTex = texLd3.getTexture( );     double xsIn15[] = {0, 0.1, 0.7, 0};     double ysIn15[] = {0, 0.1, 1.5, 2};     LatheShape3D ls2 = new LatheShape3D( xsIn15, ysIn15, waterTex);     displayLathe(ls2, -3.5f, -5.0f, "drip");

This particular bit of code produces the water globule, shown in Figure 17-3.

Figure 17-3. Water globule


The coordinates for the lathe curve are supplied as two arrays: one for the x-values and one for the y-values. Figure 17-4 shows the four coordinates plotted against the x- and y-axes.

Figure 17-4. Coordinates for the water globule


These coordinates are ordered by increasing the y-value, indicated by the numbered circles in the figure.


The x- and y-values must be greater than or equal to 0, and the first y-value must be 0. These restrictions simplify the calculation of the shape's height, which is used when mapping a texture over the shape's surface. Since the shape always starts at 0 on the y-axis, and there are no negative values, the shape's height is the largest y-value. An x-value may use a negative sign, but this has a special meaning (explained below).

displayLathe( ) positions the shape at a given (x, z) location, 1.5 units above the XZ plane (the floor of the scene). The shape's label is displayed as a Text2D object, a little below the shape:

     private void displayLathe(LatheShape3D ls, float x, float z, String label)     {       // position the LatheShape3D object       Transform3D t3d = new Transform3D( );       t3d.set( new Vector3f(x, 1.5f, z));       TransformGroup tg1 = new TransformGroup(t3d);       tg1.addChild( ls );       sceneBG.addChild(tg1);       // position the label for the shape       Text2D message = new Text2D(label, white, "SansSerif", 72, Font.BOLD );       t3d.set( new Vector3f(x-0.4f, 0.75f, z) );       TransformGroup tg2 = new TransformGroup(t3d);       tg2.addChild(message);       sceneBG.addChild(tg2);     }

Due to the ordering of the coordinates, the base of a lathe shape is its origin (most Java 3D utilities have their origins at their centers).

displayLathe( ) shows that a LatheShape3D instance can be used in the same way as a Shape3D object due to LatheShape3D being a subclass of Shape3D.

Shapes with Curves and Lines

A LatheShape3D object can be built from a lathe curve made up of curve segments and straight lines as illustrated by the cup in Figure 17-5.

Figure 17-5. A cup with curves and straight edges


By the way, it's possible to create lathe shapes purely from straight lines if you want. Those are pretty boring, so I've boogied on down to more interesting shapes.


The code for this shape is:

     TextureLoader texLd10 = new TextureLoader("textures/swirled.jpg", null);     Texture swirledTex = texLd10.getTexture( );     double xsIn2[] = {-0.001, -0.7, -0.25, 0.25, 0.7, -0.6, -0.5};     double ysIn2[] = { 0,      0,    0.5,  1,    2.5,  3,    3};     LatheShape3D ls3 = new LatheShape3D( xsIn2, ysIn2, swirledTex);     displayLathe(ls3, -1.0f, -5.0f, "cup");

This code fragment (and the others in this section) come from addLatheShapes( ) in WrapLathe3D.


A confusing aspect of this fragment is the use of negative x-values, especially the starting value of -0.001. A plot of these points should ignore the negative signs, resulting in Figure 17-6. This hack will be explained momentarily.

Figure 17-6. Coordinates for a cup


Points with negative x-values are represented by squares in the figure. Dotted lines have been added to indicate the curve segments or straight lines between the points.

The LatheCurve class (which LatheShape3D utilizes) can link points together with curves or lines. If a coordinate has a negative x-value, then a straight line is drawn from it to the next point in the sequence; otherwise, a curve is created. Once this choice about the next segment has been made, any negative sign is discarded.

The negative sign labeling is admittedly a bit confusing but keeps the specification of the shape's coordinates simple without the need to introduce additional data structures or classes. The drawback is shown in Figure 17-6: how can you make a coordinate with an x-value equal to 0 be treated as negative and, therefore, result in a straight line being drawn? The solution is to use a small negative x-value (-0.001). This leaves a tiny hole in the base of the cup when the shape is rotated, but the hole is too little to be visible.

Shapes with Colors

Figure 17-5 shows the texture is rendered on both sides of the lathe shape. If no texture is supplied (or the texture loading stage fails, returning null), then the shape will be rendered in pink. This approach is seen in two of the examples from Figure 17-1: the egg and the flower.

I like pink because it is a good default color for limbs. The moveable figure in Chapter 20 is constructed from LatheShape3D shapes, so I'm preparing the groundwork in advance with this coloring.


The shape coloring can be changed by supplying two Color3f objects: one for ambient lighting and the other for diffuse illumination. Often, the ambient color is a darker version of the diffused one. The saucer example uses brown and then a darker brown as in Figure 17-7.

Figure 17-7. Brown saucer


The code that creates the saucer is:

     Color3f brown = new Color3f( 0.3f, 0.2f, 0.0f);     Color3f darkBrown = new Color3f(0.15f, 0.1f, 0.0f);     double xsIn10[] = {0, 0.75, 0.9, 0.75, 0};     double ysIn10[] = {0, 0.23, 0.38, 0.53, 0.75};     LatheShape3D ls14 = new LatheShape3D( xsIn10, ysIn10, darkBrown, brown);     displayLathe(ls14, 6.0f, 5.0f, "saucer");

Different Curve Rotations

LatheShape3D rotates each point in the lathe curve around the y-axis, marking out a circular path back to the point's starting position. However, it's possible to subclass LatheShape3D to modify the path. EllipseShape3D sends the points in an elliptical orbit, and RhodoneaShape3D makes the points trace the outlines of petals.

Figure 17-8 shows two shapes: the LatheShape3D object at the back of the picture is a rotation of a single straight line in a circular orbit covered with a texture of the letter "R." The object in the foreground is an EllipseShape3D object made with the same line but forming an ellipse. The same "R" texture dresses the shape.

Figure 17-8. Circular and elliptical Rs


Here's the code that creates these shapes:

     TextureLoader texLd1 = new TextureLoader("textures/r.gif", null);     Texture rTex = texLd1.getTexture( );     double xsIn3[] = {-1, -1};   // straight line     double ysIn3[] = {0, 1};     LatheShape3D ls5 = new LatheShape3D( xsIn3, ysIn3, rTex);     displayLathe(ls5, 6.0f, -5.0f, "round R");     EllipseShape3D ls6 = new EllipseShape3D( xsIn3, ysIn3, rTex);     displayLathe(ls6, 6.0f, 0, "oval R");

These examples show that the texture is stretched over a shape, rather than being tiled (i.e., repeatedly applied to the shape like a wallpaper stencil). The left side of the texture is attached to the middle of the back of the shape and wrapped around it in a counterclockwise direction. The texture is stretched in the vertical direction to cover the shape from its base (at y == 0) to its maximum height. The decision to stretch the texture over the shape means the texture image should contain all the detail for the shape.



Killer Game Programming in Java
Killer Game Programming in Java
ISBN: 0596007302
EAN: 2147483647
Year: 2006
Pages: 340

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net