Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
147
51-04.md
Normal file
147
51-04.md
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](51-03.html) [Table of Contents](index.html) [Next](51-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
**LISTING 51.2 L51-2.C**
|
||||
|
||||
/* Transforms all vertices in the specified object into view spa ce, then
|
||||
perspective projects them to screen space and maps them to screen coordinates,
|
||||
storing the results in the object. */
|
||||
#include <math.h>
|
||||
#include “polygon.h”/
|
||||
|
||||
void XformAndProjectPoints(double Xform[4][4],
|
||||
struct Object * ObjectToXform)
|
||||
{
|
||||
int i, NumPoints = ObjectToXform->NumVerts;
|
||||
struct Point3 * Points = ObjectToXform->VertexList;
|
||||
struct Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
||||
struct Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
|
||||
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
||||
ProjectedPoints++, ScreenPoints++) {
|
||||
/* Transform to view space */
|
||||
XformVec(Xform, (double *)Points, (double *)XformedPoints);
|
||||
/* Perspective-project to screen space */
|
||||
ProjectedPoints->X = XformedPoints->X / XformedPoints->Z *
|
||||
PROJECTION_RATIO * (SCREEN_WIDTH / 2.0);
|
||||
ProjectedPoints->Y = XformedPoints->Y / XformedPoints->Z *
|
||||
PROJECTION_RATIO * (SCREEN_WIDTH / 2.0);
|
||||
ProjectedPoints->Z = XformedPoints->Z;
|
||||
/* Convert to screen coordinates. The Y coord is negated to
|
||||
flip from increasing Y being up to increasing Y being down,
|
||||
as expected by the polygon filler. Add in half the screen
|
||||
width and height to center on the screen. */
|
||||
ScreenPoints->X = ((int) floor(ProjectedPoints->X + 0.5)) + SCREEN_WIDTH/2;
|
||||
ScreenPoints->Y = (-((int) floor(ProjectedPoints->Y + 0.5))) +
|
||||
SCREEN_HEIGHT/2;
|
||||
}
|
||||
}
|
||||
|
||||
**LISTING 51.3 L51-3.C**
|
||||
|
||||
/* Draws all visible faces (faces pointing toward the viewer) in the specified
|
||||
object. The object must have previously been transformed and projected, so
|
||||
that the ScreenVertexList array is filled in. */
|
||||
#include “polygon.h”
|
||||
|
||||
void DrawVisibleFaces(struct Object * ObjectToXform)
|
||||
{
|
||||
int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
|
||||
int * VertNumsPtr;
|
||||
struct Face * FacePtr = ObjectToXform->FaceList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
long v1,v2,w1,w2;
|
||||
struct Point Vertices[MAX_POLY_LENGTH];
|
||||
struct PointListHeader Polygon;
|
||||
|
||||
/* Draw each visible face (polygon) of the object in turn */
|
||||
for (i=0; i<NumFaces; i++, FacePtr++) {
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
/* Copy over the face’s vertices from the vertex list */
|
||||
for (j=0, VertNumsPtr=FacePtr->VertNums; j<NumVertices; j++)
|
||||
Vertices[j] = ScreenPoints[*VertNumsPtr++];
|
||||
/* Draw only if outside face showing (if the normal to the
|
||||
polygon points toward the viewer; that is, has a positive
|
||||
Z component) */
|
||||
v1 = Vertices[1].X - Vertices[0].X;
|
||||
w1 = Vertices[NumVertices-1].X - Vertices[0].X;
|
||||
v2 = Vertices[1].Y - Vertices[0].Y;
|
||||
w2 = Vertices[NumVertices-1].Y - Vertices[0].Y;
|
||||
if ((v1*w2 - v2*w1) > 0) {
|
||||
/* It is facing the screen, so draw */
|
||||
/* Appropriately adjust the extent of the rectangle used to
|
||||
erase this page later */
|
||||
for (j=0; j<NumVertices; j++) {
|
||||
if (Vertices[j].X > EraseRect[NonDisplayedPage].Right)
|
||||
if (Vertices[j].X < SCREEN_WIDTH)
|
||||
EraseRect[NonDisplayedPage].Right = Vertices[j].X;
|
||||
else EraseRect[NonDisplayedPage].Right = SCREEN_WIDTH;
|
||||
if (Vertices[j].Y > EraseRect[NonDisplayedPage].Bottom)
|
||||
if (Vertices[j].Y < SCREEN_HEIGHT)
|
||||
EraseRect[NonDisplayedPage].Bottom = Vertices[j].Y;
|
||||
else EraseRect[NonDisplayedPage].Bottom=SCREEN_HEIGHT;
|
||||
if (Vertices[j].X < EraseRect[NonDisplayedPage].Left)
|
||||
if (Vertices[j].X > 0)
|
||||
EraseRect[NonDisplayedPage].Left = Vertices[j].X;
|
||||
else EraseRect[NonDisplayedPage].Left = 0;
|
||||
if (Vertices[j].Y < EraseRect[NonDisplayedPage].Top)
|
||||
if (Vertices[j].Y > 0)
|
||||
EraseRect[NonDisplayedPage].Top = Vertices[j].Y;
|
||||
else EraseRect[NonDisplayedPage].Top = 0;
|
||||
}
|
||||
/* Draw the polygon */
|
||||
DRAW_POLYGON(Vertices, NumVertices, FacePtr->Color, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The sample program, as shown in Figure 51.3, places a cube, floating in
|
||||
three-space, under the complete control of the user. The arrow keys may
|
||||
be used to move the cube left, right, up, and down, and the A and T keys
|
||||
may be used to move the cube away from or toward the viewer. The F1 and
|
||||
F2 keys perform rotation around the Z axis, the axis running from the
|
||||
viewer straight into the screen. The 4 and 6 keys perform rotation
|
||||
around the Y (vertical) axis, and the 2 and 8 keys perform rotation
|
||||
around the X axis, which runs horizontally across the screen; the latter
|
||||
four keys are most conveniently used by flipping the keypad to the
|
||||
numeric state.
|
||||
|
||||
\
|
||||
**Figure 51.3** *Sample screens from the 3-D cube program.*
|
||||
|
||||
The demo involves six polygons, one for each side of the cube. Each of
|
||||
the polygons must be transformed and projected, so it would seem that 24
|
||||
vertices (four for each polygon) must be handled, but some steps have
|
||||
been taken to improve performance. All vertices for the object have been
|
||||
stored in a single list; the definition of each face contains not the
|
||||
vertices for that face themselves, but rather indexes into the object’s
|
||||
vertex list, as shown in Figure 51.4. This reduces the number of
|
||||
vertices to be manipulated from 24 to 8, for there are, after all, only
|
||||
eight vertices in a cube, with three faces sharing each vertex. In this
|
||||
way, the transformation burden is lightened by two-thirds. Also, as
|
||||
mentioned earlier, backface removal is performed with integers, in
|
||||
screen coordinates, rather than with floating-point values in screen
|
||||
space. Finally, the **RecalcXForm** flag is set whenever the user
|
||||
changes the object-to-world transformation. Only when this flag is set
|
||||
is the full object-to-view transformation recalculated and the object’s
|
||||
vertices transformed and projected again; otherwise, the values already
|
||||
stored within the object are reused. In the sample application, this
|
||||
brings no visual improvement, because there’s only the one object, but
|
||||
the underlying mechanism is sound: In a full-blown 3-D animation
|
||||
application, with multiple objects moving about the screen, it would
|
||||
help a great deal to flag which of the objects had moved with respect to
|
||||
the viewer, performing a new transformation and projection only for
|
||||
those that had.
|
||||
|
||||
\
|
||||
**Figure 51.4** *The object data structure*
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](51-03.html) [Table of Contents](index.html) [Next](51-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue