Chapter 18. 3D Sprites


Subclassing the Lathe Shape

Figure 17-2 shows that LatheShape3D can be subclassed. The aim is to override its xCoord( ) and zCoord( ) methods, which control the shape of the path made by the lathe curve when it's rotated. These methods appear in LatheShape3D as shown here:

     protected double xCoord(double radius, double angle)     {  return radius * Math.cos(angle);  }     protected double zCoord(double radius, double angle)     {  return radius * Math.sin(angle);  }

radius is the x-value of the point being rotated around the y-axis, and angle is the angle of rotation currently being applied. xCoord( ) and zCoord( ) return the new x-and z-values after the rotation has been applied.

An Elliptical Shape

An ellipse resembles a circle stretched in one direction. Another (more formal) way of characterizing the ellipse is that its points all have the same sum of distances from two fixed points (called the foci).

The line that passes through the foci is called the major axis, and is the longest line through the ellipse. The minor axis is the line that passes through the center of the ellipse, perpendicular to the major axis. The semi-major axis is half the length of the major axis: it runs from the center of the ellipse to its edge. There's also a semi-minor axis(half of the minor axis). See Figure 17-19 for illustrations of all of these concepts.

Figure 17-19. Elements of an ellipse


Figure 17-20 shows an ellipse with a semi-major axis of 4 and a semi-minor axis of length 2.

Figure 17-20. Another ellipse


The semi-major and semi-minor axes can be used to calculate the (x, y) coordinates of the ellipse:

     x = semiMajorAxis * cos(angle)     y = semiMinorAxis * sin(angle)

In the case of the ellipse in Figure 17-20, these calculations would result in the following:

     x = 4 * cos(angle)     y = 2 * sin(angle)

The y equation can be rephrased by writing the semi-minor axis value as a scale factor applied to the semi-major axis number:

     x = 4 * cos(angle)     y = 0.5 * 4 * sin(angle)

The scale factor is 0.5 since 0.5 x 4 is 2, the semi-minor axis value. This means that the semi-minor axis is half the length of the semi-major, as illustrated by Figure 17-20.

I've been talking about x and y equations, but now it's time to change the axes. A lathe shape is made by rotating a lathe curve over the floor (the XZ plane). This means that my ellipses are drawn on the x- and z-axes, not the x- and y-axes. As a consequence, the y equation becomes the z equation:

     z = 0.5 * 4 * sin(angle)

The x and z equations use the semi-major axis number (4). Is there a way of obtaining this from the radius value supplied as an argument to the xCoord( ) and zCoord( ) methods? Yes, when the angle is 0, the x-value is the semi-major axis, which is the radius:

     radius = semiMajorAxis * cos(0),    so radius = semiMajorAxis.

This means I can use the radius as a replacement for the semi major axis value in the x and z equations. The equations become:

     x = radius * cos(angle)     z = scaleFactor * radius * sin(angle)

The x equation is the same as the xCoord( ) method in LatheShape3D, so doesn't need to be overridden. The zCoord( ) method does need changing and becomes the following in the EllipseShape3D class:

     protected double zCoord(double radius, double angle)     {  return  0.5 * radius * Math.sin(angle);  }

The scale factor is set to 0.5, which makes the semi-minor axis half the semi-major axis, which can be confirmed by examining the oval R example in Figure 17-8.

A weakness of this approach is that the user cannot set the scale factor via a parameter of EllipseShape3D's constructor. The reason is that the xCoord( ) and zCoord( ) methods are called (indirectly) by the LatheShape3D constructor, so must be fully specified before any code in the EllipseShape3D constructor is executed. In other words, the scale factor (e.g., 0.5) must be hardwired into the EllipseShape3D class as a constant in zCoord( ).

The armor example uses EllipseShape3D:

     double xsIn9[] = {-0.01, 0.5, -1, -1.2, 1.4, -0.5, -0.5, 0};     double ysIn9[] = {0, 0, 1.5, 1.5, 2, 2.5, 2.7, 2.7};     EllipseShape3D ls13 = new EllipseShape3D( xsIn9, ysIn9, plateTex);     displayLathe(ls13, 3.0f, 5.0f, "armour");

Figure 17-21 shows the rendering of armor.

Figure 17-21. The armor ellipse


A Rhodonea Shape

A rhodonea curve resembles the petals of a rose. The simplest way to define one is with an equation using polar coordinates:

     r = a * cos(k*angle)

This lays down a curve with k or 2k petals, depending if k is an odd or even integer. a is the amplitude, affecting the length of the petals. Some examples of rhodonea curves with different k values are given in Figure 17-22.

Figure 17-22. Some rhodonea curves


Once r is obtained for a given angle, it can be translated to Cartesian coordinates with:

     x = r * cos(angle)     y = r * sin(angle)

I store the initial x value in radius, which is the length of the first petal when the angle is 0:

     radius = a * cos(0),    so radius = a

The rhodonea equation then becomes:

     r = radius * cos(k*angle)

In the RhodoneaShape3D class, k is set to be 4, and xCoord( ) and yCoord( ) must be overridden:

     protected double xCoord(double radius, double angle)     { double r = radius * Math.cos(4 * angle);   // 8 petals       return  r * Math.cos(angle);     }     protected double zCoord(double radius, double angle)     { double r = radius * Math.cos(4 * angle);       return  r * Math.sin(angle);     }

RhodoneaShape3D is used in the flower example, which is defined as:

     double xsIn3[] = {-1, -1};     double ysIn3[] = {0, 1};     RhodoneaShape3D ls7 = new RhodoneaShape3D(xsIn3, ysIn3, null);     displayLathe(ls7, 3.0f, 0, "flower");

A vertical straight line of unit length is rotated and then colored pink. The resulting curve is shown in Figure 17-23.

Figure 17-23. A rough RhodoneaShape3D shape


The curve is rather rough due to the ANGLE_INCR setting in LatheShape3D (15 degrees between each slice). If this is reduced to 5 degrees, the result will be more pleasing (see Figure 17-24).

Figure 17-24. A smoother RhodoneaShape3D shape


The drawback of reducing the ANGLE_INCR value is the increase in the number of vertices generated for each 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