Graphics Reference
In-Depth Information
•
ProjectiveTransformation2
: A transformation that operates on
Point
s
in their homogeneous representation and includes a division by the last
coordinate after the matrix multiplication.
(There are four corresponding classes for transformations in 3D.)
In each case, we've defined composition of transformations by overloading
the
*
operator, and the application of a transformation to a
Point
or
Vector
by
overloading the
*
operator again. To translate a point and then rotate it by
π/
6, we
could write
1
2
3
4
Point P = new Point(...);
AffineTransformation2 T = AffineTransformation2.Translate(Vector(3,1));
AffineTransformation2 S = AffineTransformation2.RotateXY(Math.PI/6);
Point Q = (S
*
T)
*
P;
If we were planning to operate on many points with this composed transfor-
mation, we'd precompute the composed transformation and instead write
1
2
3
...
AffineTransformation2 T2 = (S
*
T);
Point Q = T2
*
P;
Applying a transformation to a point or vector involves some memory allocation,
a method invocation, and a matrix multiplication. If you simply stored the matrix
yourself, you could avoid most of this cost. And since graphics programs end up
applying
lots
of transformations to
lots
of points and vectors, you might think
that doing it yourself is the best possible approach. If you're writing a program
that will be doing real-time graphics on a processor where computation is a real
bottleneck (e.g., a game that runs on a battery-powered device), it may well be.
But as a student of computer graphics, you're likely to write a lot of programs
that get run just a few times. The great “cost” in your programs is
your
time as
a developer. Using a high-level approach can help reduce bugs and even
increase
efficiency, as you notice ways to restructure your code that would be difficult to
see if you were looking at every detail all the time. A profiler can help you to
determine exactly
where
in your code it's worth the trouble of working with a
low-level construct rather than a high-level one.
Nonetheless, there are places where one can get a certain amount of efficiency
at no cost. For instance, the
LinearTransformation2
class uses a 3
×
3matrixto
represent a transformation, but that matrix always has the form
⎡
⎤
ab
0
cd
0
001
⎣
⎦
,
(12.1)
so it's much easier to invert than a general 3
×
3 matrix (we just invert the upper-
left 2
2 matrix); in the same way, multiplying two of these is much less work than
multiplying two 3
×
2 matrices).
By overriding the
MatrixTransform2
methods for inversion and multiplication,
we get a large efficiency improvement.
×
3 matrices (we just multiply the upper-left 2
×