/* Transforms all vertices in the specified polygon-based object into view space, then perspective projects them to screen space and maps them to screen coordinates, storing the results in the object. Recalculates object->view transformation because only if the transform changes would we bother to retransform the vertices. Also recalculates CenterInView and moves the object through the object list accordingly. */ #include #include "polygon.h" static Point3 CenterPoint = {0, 0, 0}; void XformAndProjectPObject(PObject * ObjectToXform) { int i, NumPoints = ObjectToXform->NumVerts; int NumRealPoints = ObjectToXform->NumRealVerts; Point3 * Points = ObjectToXform->VertexList; Point3 * XformedPoints = ObjectToXform->XformedVertexList; Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList; Point * ScreenPoints = ObjectToXform->ScreenVertexList; /* Recalculate the object->view transform */ ConcatXforms(WorldViewXform, ObjectToXform->XformToWorld, ObjectToXform->XformToView); /* Recalculate CenterInView */ XformVec(ObjectToXform->XformToView, (Fixedpoint *) &CenterPoint, (Fixedpoint *) &ObjectToXform->CenterInView); /* Apply that new transformation and project all polygon vertices (not unit normal endpoints yet, though) */ for (i=0; iXformToView, (Fixedpoint *) Points, (Fixedpoint *) XformedPoints); /* Perspective-project to screen space */ ProjectedPoints->X = FixedMul(FixedDiv(XformedPoints->X, XformedPoints->Z), DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2))); ProjectedPoints->Y = FixedMul(FixedDiv(XformedPoints->Y, XformedPoints->Z), DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2))); 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) ((ProjectedPoints->X + DOUBLE_TO_FIXED(0.5)) >> 16)) + SCREEN_WIDTH/2; ScreenPoints->Y = (-((int) ((ProjectedPoints->Y + DOUBLE_TO_FIXED(0.5)) >> 16))) + SCREEN_HEIGHT/2; } /* Now transform the unit normal endpoints into view space, but there's no reason to waste time getting them into screen space or screen coordinates */ for (i=NumRealPoints; iXformToView, (Fixedpoint *) Points, (Fixedpoint *) XformedPoints); } }