Graphics Reference
In-Depth Information
returned object represents a shape; its coordinates are assumed to be in the stan-
dard coordinate frame. This shape is then added to our world (represented by the
object
m_surfaceArray
) by specifying a coordinate frame using
CFrame::fromXYZYPRDegrees(center.x, center.y, center.z);
This method specifies a coordinate frame by saying how much to translate the
standard frame in
x
,
y
, and
z
(the “XYZ” part of the name), and then how much
yaw, pitch, and roll (the “YPR”) to apply, with the amounts specified in degrees.
The default values for yaw, pitch, and roll are 0, so we didn't specify them.
In the
insert
method, the model is “posed” in this new frame, that is, its coor-
dinates are now taken to be relative to that new frame. Since that new frame is
based at the specified
center
, we end up with a sphere translated to the specified
location. This transformed surface is added to the world-description member vari-
able
m_surfaceArray
, while its representation as a collection of triangles is added
to another member variable,
m_triArray
, which is used in visibility testing.
The square-insertion code is slightly more complex. The standard unit square
is read from a file, scaled up by the edge length. Since the standard square is cen-
tered at the origin, with edge length 1, and is aligned with the axes of the
xy
-plane,
the
x
and
y
unit vectors are tangent to the square and the
z
unit vector is normal
to it. We'll need to build a new coordinate frame whose first axis is the specified
axisTangent
and whose third axis is the specified
normal
.Todoso,webuilda
matrix transformation that sends the
x
-,
y
-, and
z
-axes to the
axisTangent
, a sec-
ond tangent, and the
normal
, respectively, although we assist the user slightly by
not requiring that either specified vector be unit length. To build the new coordi-
nate frame, we build a matrix that transforms the standard frame to the desired
new one, and then construct the new frame using
cFrame(rotmat, center);
, one
of the
CoordinateFrame
class's standard constructors.
Which kind of linear algebra support you choose will depend on both personal
taste and the kinds of programming you're doing. If peak efficiency in matrix oper-
ations is essential, you may choose to work directly with arrays of floats. If expres-
sive convenience matters to you, you may choose the style we first described, with
methods like
PointsToPoints
. If you'll frequently be inverting transformations,
perhaps the G3D approach will work best for you.
In general, however, your programs will be easier to write and debug if you
rely on a few carefully written and tested programs for building and applying
transformations, and use your language's type system to help you keep track of
the difference between points and vectors. The more your linear algebra module
can support the expression of
what
rather than
how
(e.g., “I want the camera to
look in
this
direction” rather than “I want to rotate the camera 37
◦
in
x
, then 12. 3
◦
in
y
”) the easier it will be to both understand and maintain your programs.
Exercise 12.1:
Create a
Ray
class to represent a ray in the plane, and build the asso-
ciated ray transformation in the
AffineTransformation2
class. Do the same for a