97 lines
5.3 KiB
Markdown
97 lines
5.3 KiB
Markdown
With the above optimizations, the sample program is certainly adequately
|
|
responsive on a 20 MHz 386 (sans 387; I'm sure it's wonderfully
|
|
responsive with a math coprocessor). Still, it couldn't quite keep up
|
|
with the keyboard when I modified it to read only one key each time
|
|
through the loop—and we're talking about only eight vertices here. This
|
|
indicates that we're already near the limit of animation complexity
|
|
possible with our current approach. It's time to start rethinking that
|
|
approach; over two-thirds of the overall time is spent in floating-point
|
|
calculations, and it's there that we'll begin to attack the performance
|
|
bottleneck we find ourselves up against.
|
|
|
|
### Incremental Transformation {#Heading5}
|
|
|
|
Listing 51.4 contains three functions; each concatenates an additional
|
|
rotation around one of the three axes to an existing rotation. To
|
|
improve performance, only the matrix entries that are affected in a
|
|
rotation around each particular axis are recalculated (all but four of
|
|
the entries in a single-axis rotation matrix are either 0 or 1, as shown
|
|
in Chapter 50). This cuts the number of floating-point multiplies from
|
|
the 64 required for the multiplication of two 4x4 matrices to just 12,
|
|
and floating point adds from 48 to 6.
|
|
|
|
Be aware that Listing 51.4 performs an incremental rotation on top of
|
|
whatever rotation is already in the matrix. The cube may already have
|
|
been turned left, right, up, down, and sideways; regardless, Listing
|
|
51.4 just tacks the specified rotation onto whatever already exists. In
|
|
this way, the object-to-world transformation matrix contains a history
|
|
of all the rotations ever specified by the user, concatenated one after
|
|
another onto the original matrix. Potential loss of precision is a
|
|
problem associated with using such an approach to represent a very long
|
|
concatenation of transformations, especially with fixed-point
|
|
arithmetic; that's not a problem for us yet, but we'll run into it
|
|
eventually.
|
|
|
|
**LISTING 51.4 L51-4.C**
|
|
|
|
/* Routines to perform incremental rotations around the three axes */
|
|
#include <math.h>
|
|
#include "polygon.h"
|
|
|
|
/* Concatenate a rotation by Angle around the X axis to the transformation in
|
|
XformToChange, placing result back in XformToChange. */
|
|
void AppendRotationX(double XformToChange[4][4], double Angle)
|
|
{
|
|
double Temp10, Temp11, Temp12, Temp20, Temp21, Temp22;
|
|
double CosTemp = cos(Angle), SinTemp = sin(Angle);
|
|
/* Calculate the new values of the four affected matrix entries */
|
|
Temp10 = CosTemp*XformToChange[1][0]+ -SinTemp*XformToChange[2][0];
|
|
Temp11 = CosTemp*XformToChange[1][1]+ -SinTemp*XformToChange[2][1];
|
|
Temp12 = CosTemp*XformToChange[1][2]+ -SinTemp*XformToChange[2][2];
|
|
Temp20 = SinTemp*XformToChange[1][0]+ CosTemp*XformToChange[2][0];
|
|
Temp21 = SinTemp*XformToChange[1][1]+ CosTemp*XformToChange[2][1];
|
|
Temp22 = SinTemp*XformToChange[1][2]+ CosTemp*XformToChange[2][2];
|
|
/* Put the results back into XformToChange */
|
|
XformToChange[1][0] = Temp10; XformToChange[1][1] = Temp11;
|
|
XformToChange[1][2] = Temp12; XformToChange[2][0] = Temp20;
|
|
XformToChange[2][1] = Temp21; XformToChange[2][2] = Temp22;
|
|
}
|
|
|
|
/* Concatenate a rotation by Angle around the Y axis to the transformation in
|
|
XformToChange, placing result back in XformToChange. */
|
|
void AppendRotationY(double XformToChange[4][4], double Angle)
|
|
{
|
|
double Temp00, Temp01, Temp02, Temp20, Temp21, Temp22;
|
|
double CosTemp = cos(Angle), SinTemp = sin(Angle);
|
|
|
|
/* Calculate the new values of the four affected matrix entries */
|
|
Temp00 = CosTemp*XformToChange[0][0]+ SinTemp*XformToChange[2][0];
|
|
Temp01 = CosTemp*XformToChange[0][1]+ SinTemp*XformToChange[2][1];
|
|
Temp02 = CosTemp*XformToChange[0][2]+ SinTemp*XformToChange[2][2];
|
|
Temp20 = -SinTemp*XformToChange[0][0]+ CosTemp*XformToChange[2][0];
|
|
Temp21 = -SinTemp*XformToChange[0][1]+ CosTemp*XformToChange[2][1];
|
|
Temp22 = -SinTemp*XformToChange[0][2]+ CosTemp*XformToChange[2][2];
|
|
/* Put the results back into XformToChange */
|
|
XformToChange[0][0] = Temp00; XformToChange[0][1] = Temp01;
|
|
XformToChange[0][2] = Temp02; XformToChange[2][0] = Temp20;
|
|
XformToChange[2][1] = Temp21; XformToChange[2][2] = Temp22;
|
|
}
|
|
|
|
/* Concatenate a rotation by Angle around the Z axis to the transformation in
|
|
XformToChange, placing result back in XformToChange. */
|
|
void AppendRotationZ(double XformToChange[4][4], double Angle)
|
|
{
|
|
double Temp00, Temp01, Temp02, Temp10, Temp11, Temp12;
|
|
double CosTemp = cos(Angle), SinTemp = sin(Angle);
|
|
/* Calculate the new values of the four affected matrix entries */
|
|
Temp00 = CosTemp*XformToChange[0][0]+ -SinTemp*XformToChange[1][0];
|
|
Temp01 = CosTemp*XformToChange[0][1]+ -SinTemp*XformToChange[1][1];
|
|
Temp02 = CosTemp*XformToChange[0][2]+ -SinTemp*XformToChange[1][2];
|
|
Temp10 = SinTemp*XformToChange[0][0]+ CosTemp*XformToChange[1][0];
|
|
Temp11 = SinTemp*XformToChange[0][1]+ CosTemp*XformToChange[1][1];
|
|
Temp12 = SinTemp*XformToChange[0][2]+ CosTemp*XformToChange[1][2];
|
|
/* Put the results back into XformToChange */
|
|
XformToChange[0][0] = Temp00; XformToChange[0][1] = Temp01;
|
|
XformToChange[0][2] = Temp02; XformToChange[1][0] = Temp10;
|
|
XformToChange[1][1] = Temp11; XformToChange[1][2] = Temp12;
|
|
}
|