home *** CD-ROM | disk | FTP | other *** search
- #include "..\Source\LastWolf.hpp"
-
-
- // What the fixed-point numbers are shifted by (as extra precision) for the VLine routines.
- #define TEXTURE_FIX 5
-
- #define CLIP_Z FIX(2)
- #define MAX_X_CLIPS 200
-
- // A lookup table for the parallaxing sky.
- MDWordArray parallaxLookup;
-
- // Top and bottom Y for all the Lines.
- Fixed topY = FIX(-84);
- Fixed bottomY = FIX(36);
-
- // Used when projecting coordinates.
- WORD centerX = 160;
- WORD centerY = 100;
-
- // The transformation stuff.
- Fixed playerAngleSine, playerAngleCosine;
- Fixed translateX, translateY;
- Angle transAngle;
-
-
- // What you scale the world by horizontally .. xViewSlope and xViewSlopeAngle depend on it!
- WORD xWorldScale=160;
-
- // World Y scale.
- WORD yWorldScale;
-
- // The slope of the viewing angle ... used to cut off excess lines.
- // Equation to get slope = (screenMaxX / xWorldScale)
- // NOTE: This is an x/y slope, because x has the possibility of being zero.
- // Also, screenMaxX = half the screen (160).
- Fixed xViewSlope = (Fixed)(1.0F * 16384.0F);
-
- // xViewSlopeAngle = atan( 1/xViewSlope ).
- Angle xViewAngle = 128;
-
-
- // Variables for the screen X clipping table.
- X_Clip clipSpace[MAX_X_CLIPS];
- WORD nClipsUsed;
-
- X_Clip headNode, tailNode;
-
-
- void dr_InitTables()
- {
- Angle i;
- float ArcTangent, ArcCosine;
-
- // Fill in SIN_TABLE[].
- for( i=0; i < ANGLE_RES; i++ )
- SIN_TABLE[i] = (Fixed)(sin(((float)i * 6.28) / ANGLE_RES) * FIXED_ONE);
-
- // Fill in ATAN_TABLE[].
- for( i=0; i < ANGLE_RES; i++ )
- {
- ArcTangent = atan((float)i / (float)ANGLE_RES);
- ATAN_TABLE[i] = (Angle)((ArcTangent * (float)ANGLE_RES) / 6.28F);
- }
-
- // Fill in ACOS_TABLE[].
- for( i=0; i < ANGLE_RES; i++ )
- {
- ArcCosine = acos( (float)i / (float)ANGLE_RES );
- ACOS_TABLE[i] = (ArcCosine * FIXED_ONE);
- }
-
- // Set up the X_Clip stuff.
- headNode.pNext = &tailNode;
- tailNode.pNext = &tailNode;
- }
-
- void dr_GenerateLookups()
- {
- Fixed parallaxX;
- DWORD x;
- Texture *pSky;
-
- // Generate the parallaxing sky lookup table.
- pSky = tx_GetTexture( curLevel.idCurSky );
-
- parallaxLookup.SetSize( s_DrawWidth );
- for( x=s_MinX; x < s_MaxX; x++ )
- {
- parallaxX = FIXED_ONE - (FIX( (x-s_MinX)-(s_DrawWidth/2) ) / ((s_DrawWidth*2) / 3));
- parallaxX = SIN_TABLE[ (parallaxX >> (FIXED_SHIFT-8)) + 255 ];
- parallaxX = parallaxX >> pSky->xTextureShift;
-
- parallaxLookup.Set( x-s_MinX, parallaxX );
- }
- }
-
- void dr_DrawScreen()
- {
- // Setup misc. variables.
- nClipsUsed = 0;
-
- headNode.x = s_MinX;
- headNode.pNext = &tailNode;
-
- tailNode.x = s_MaxX;
- tailNode.pNext = &tailNode;
-
- // Re-computer all the viewing parameters.
- centerX = s_MinX + ((s_MaxX - s_MinX)/2);
- centerY = s_MinY + ((s_MaxY - s_MinY)/2);
-
- yWorldScale = s_DrawHeight / 2;
- xWorldScale = s_DrawWidth / 2;
- xViewSlope = FIX(centerX) / (s_DrawWidth/2);
-
-
- dr_SetupTransformation(&player);
- bsp_TraverseAndDrawTree(curLevel.pRootLine);
-
- return;
- }
-
-
- void dr_SetupTransformation( Player *pPlayer )
- {
- playerAngleSine = SAFE_SIN(pPlayer->facingAngle);
- playerAngleCosine = SAFE_COS(pPlayer->facingAngle);
-
- transAngle = (pPlayer->facingAngle - PI) & ANGLE_MASK;
-
- translateX = -pPlayer->xPos;
- translateY = -pPlayer->yPos;
- }
-
-
- DrawReturn dr_DrawWall( CLine *pWall, SideDir viewSide )
- {
- ProcessWall Wall;
-
- Wall.pLine = pWall;
- Wall.pPlayer = &player;
- Wall.viewSide = viewSide;
- Wall.bTextureInitted = FALSE;
-
- // Get the wall into the player's viewspace to project it.
- if( !dr_TransformWall( &Wall ) )
- return WallOffScreen;
-
- // Clip it against the y=CLIP_Z Line.
- if( !dr_ClipWall( &Wall ) )
- return WallOffScreen;
-
- // Project it to get all the screen coordinates.
- if( !dr_ProjectWall( &Wall ) )
- return WallOffScreen;
-
- // Clip the wall's x coordinates against the current clip stuff.
- return dr_TableClipAndDrawWall( &Wall );
- }
-
-
- SideDir dr_PruneTree( CLine *pLine )
- {
- // Check if the wall is off AND it doesn't touch the viewing angles, in which case it has
- // a whole invisible subtree.
-
- // TEMPORARY: Return intercept until this routine is implemented.
- pLine=pLine;
- return Intersect;
-
- }
-
-
- BOOL dr_TransformWall( ProcessWall *pWall )
- {
- WORD localX1, localY1, localX2, localY2;
- WORD texOriginX, texOriginY, texHorzX, texHorzY;
-
-
- // Rotate the Line's coordinates.
- localX1 = pWall->pLine->pPoint1->localX + translateX;
- localY1 = pWall->pLine->pPoint1->localY + translateY;
- localX2 = pWall->pLine->pPoint2->localX + translateX;
- localY2 = pWall->pLine->pPoint2->localY + translateY;
-
- pWall->x1 = ((localX1 * playerAngleCosine) - (localY1 * playerAngleSine));
- pWall->y1 = ((localX1 * playerAngleSine) + (localY1 * playerAngleCosine));
- pWall->x2 = ((localX2 * playerAngleCosine) - (localY2 * playerAngleSine));
- pWall->y2 = ((localX2 * playerAngleSine) + (localY2 * playerAngleCosine));
-
- pWall->normalX = FMul(pWall->pLine->A, playerAngleCosine) - FMul(pWall->pLine->B, playerAngleSine) + translateX;
- pWall->normalY = FMul(pWall->pLine->A, playerAngleSine) + FMul(pWall->pLine->B, playerAngleCosine) + translateY;
-
-
- // Fill in texture mapping stuff.
- texOriginX = pWall->pLine->texOriginX + translateX;
- texOriginY = pWall->pLine->texOriginY + translateY;
- texHorzX = pWall->pLine->texHorzX + translateX;
- texHorzY = pWall->pLine->texHorzY + translateY;
-
- pWall->originX = ((texOriginX * playerAngleCosine) - (texOriginY * playerAngleSine));
- pWall->originZ = ((texOriginX * playerAngleSine) + (texOriginY * playerAngleCosine));
- pWall->horzX = ((texHorzX * playerAngleCosine) - (texHorzY * playerAngleSine));
- pWall->horzZ = ((texHorzX * playerAngleSine) + (texHorzY * playerAngleCosine));
-
-
- // Set which side the player is looking at and, if there's no texture there, don't draw the wall.
- if( pWall->viewSide == LeftSide )
- {
- if( pWall->pLine->idLeftTex == BAD_TEXTURE_ID )
- return FALSE;
- else
- pWall->viewSide = LeftSide;
- }
- else
- {
- if( pWall->pLine->idRightTex == BAD_TEXTURE_ID )
- return FALSE;
- else
- pWall->viewSide = RightSide;
- }
-
-
- return TRUE;
- }
-
-
- BOOL dr_ClipWall( ProcessWall *pWall )
- {
- // Used for clipping against the view boundaries.
- Fixed x1, y1, x2, y2;
- Angle rotateAngle;
- WORD pointClipped;
-
-
-
- // First check if it even needs to be clipped.
- if( pWall->y1 > CLIP_Z && pWall->y2 > CLIP_Z )
- {
- pWall->t1 = 0;
- pWall->t2 = FIXED_ONE;
- }
- else if( pWall->y1 <= CLIP_Z && pWall->y2 <= CLIP_Z )
- return FALSE;
- else
- {
- // Clip against z=CLIP_Z.
- dr_ClipAgainstLine( CLIP_Z, &pWall->x1, &pWall->y1, &pWall->x2, &pWall->y2, &pWall->t1, &pWall->t2, TRUE );
- }
-
-
- // Now clip the Line against the viewing angles.
-
- // Clip against the right side.
- rotateAngle = (ANGLE_RES-xViewAngle) & ANGLE_MASK;
- RotatePointFixed( 0, 0, rotateAngle, pWall->x1, pWall->y1, &x1, &y1 );
- RotatePointFixed( 0, 0, rotateAngle, pWall->x2, pWall->y2, &x2, &y2 );
-
- // Check if it needs to be clipped at all.
- if( y1 < 0 && y2 < 0 )
- return FALSE;
- else if( y1 > 0 && y2 > 0 )
- ;
- else
- {
- // Clip it.
- pointClipped = dr_ClipAgainstLine( 0, &x1, &y1, &x2, &y2, &pWall->t1, &pWall->t2, TRUE );
-
- // Rotate the point that got clipped back.
- rotateAngle = xViewAngle;
- if( pointClipped == 1 )
- RotatePointFixed( 0, 0, rotateAngle, x1, y1, &pWall->x1, &pWall->y1 );
- else
- RotatePointFixed( 0, 0, rotateAngle, x2, y2, &pWall->x2, &pWall->y2 );
- }
-
-
-
- // Clip against the left side (xViewAngle+HALF_PI).
- rotateAngle = (ANGLE_RES - (PI-xViewAngle)) & ANGLE_MASK;
- RotatePointFixed( 0, 0, rotateAngle, pWall->x1, pWall->y1, &x1, &y1 );
- RotatePointFixed( 0, 0, rotateAngle, pWall->x2, pWall->y2, &x2, &y2 );
-
- // Check if it needs to be clipped at all.
- if( y1 > 0 && y2 > 0 )
- return FALSE;
- else if( y1 < 0 && y2 < 0 )
- ;
- else
- {
- // Clip it.
- pointClipped = dr_ClipAgainstLine( 0, &x1, &y1, &x2, &y2, &pWall->t1, &pWall->t2, FALSE );
-
- // Rotate the point that got clipped back.
- rotateAngle = PI-xViewAngle;
-
- if( pointClipped == 1 )
- RotatePointFixed( 0, 0, rotateAngle, x1, y1, &pWall->x1, &pWall->y1 );
- else
- RotatePointFixed( 0, 0, rotateAngle, x2, y2, &pWall->x2, &pWall->y2 );
- }
-
-
- return TRUE;
- }
-
-
- BOOL dr_ProjectWall( ProcessWall *pWall )
- {
- WORD tempX;
-
- WORD y1Top, y2Top;
- WORD y1Bottom, y2Bottom;
-
- Fixed x1Div, x2Div, y1Div, y2Div;
-
- BYTE drawColor;
-
-
- // Keep in mind, pWall->y1 & 2 is really z1 & 2...
- x1Div = pWall->y1 / xWorldScale;
- x2Div = pWall->y2 / xWorldScale;
-
- y1Div = pWall->y1 / yWorldScale;
- y2Div = pWall->y2 / yWorldScale;
-
- pWall->screenX1 = W_UNFIX( FDiv( pWall->x1, x1Div ) ) + centerX;
- pWall->screenX2 = W_UNFIX( FDiv( pWall->x2, x2Div ) ) + centerX;
-
- if( pWall->screenX1 == pWall->screenX2 )
- return FALSE;
-
- y1Top = W_UNFIX( FDiv( topY, y1Div ) ) + centerY;
- y1Bottom = W_UNFIX( FDiv( bottomY, y1Div ) ) + centerY;
-
- y2Top = W_UNFIX( FDiv( topY, y2Div ) ) + centerY;
- y2Bottom = W_UNFIX( FDiv( bottomY, y2Div ) ) + centerY;
-
-
- // Fill in the information for the top and bottom lines.
- pWall->topSlope = FIX(y2Top - y1Top) / (pWall->screenX2 - pWall->screenX1);
- pWall->bottomSlope = FIX(y2Bottom - y1Bottom) / (pWall->screenX2 - pWall->screenX1);
-
- pWall->yTopIntercept = y1Top - W_UNFIX(pWall->screenX1 * pWall->topSlope);
- pWall->yBottomIntercept = y1Bottom - W_UNFIX(pWall->screenX1 * pWall->bottomSlope);
-
-
- // Make sure screenX 1 and 2 go from left to right.
- if( pWall->screenX1 > pWall->screenX2 )
- {
- tempX = pWall->screenX1;
- pWall->screenX1 = pWall->screenX2;
- pWall->screenX2 = tempX;
-
- pWall->bFlippedX = TRUE;
- }
- else
- pWall->bFlippedX = FALSE;
-
-
- // Show the projected points.
- if( bDisplayProjectionPoints )
- {
- drawColor = 35;
-
- if( tempX == pWall->screenX2 )
- {
- s_SetPixel( pWall->screenX2, y1Top, drawColor );
- s_SetPixel( pWall->screenX2, y1Bottom, drawColor );
- s_SetPixel( pWall->screenX1, y2Top, drawColor );
- s_SetPixel( pWall->screenX1, y2Bottom, drawColor );
- }
- else
- {
- s_SetPixel( pWall->screenX1, y1Top, drawColor );
- s_SetPixel( pWall->screenX1, y1Bottom, drawColor );
- s_SetPixel( pWall->screenX2, y2Top, drawColor );
- s_SetPixel( pWall->screenX2, y2Bottom, drawColor );
- }
- }
-
-
- // Set the unclipped ones here.
- pWall->unclippedScreenX1 = pWall->screenX1;
- pWall->unclippedScreenX2 = pWall->screenX2;
-
-
- return TRUE;
- }
-
-
-
- DrawReturn dr_TableClipAndDrawWall( ProcessWall *pWall )
- {
- X_Clip *pCurNode, *pPrevNode, *pNewNode;
- BOOL bIn;
-
-
-
- // Screen boundary clipping.
- //////////////////////
-
- // Test if it's all the way off the screen.
- if( pWall->screenX2 < s_MinX )
- return WallOffScreen;
-
- if( pWall->screenX1 >= s_MaxX )
- return WallOffScreen;
-
- if( pWall->screenX1 < s_MinX )
- pWall->screenX1 = s_MinX;
-
- if( pWall->screenX2 >= s_MaxX )
- pWall->screenX2 = s_MaxX;
-
- if( pWall->screenX1 == pWall->screenX2 )
- return DrewWall;
-
-
- // Find where the Line enters into the table. Insert a new X_Clip in the table
- // if necessary.
-
- pCurNode = &headNode;
- pPrevNode = &headNode;
-
- bIn = FALSE;
-
- while( pCurNode->pNext != pCurNode )
- {
- if( pWall->screenX1 >= pCurNode->x && pWall->screenX1 < pCurNode->pNext->x )
- {
- if( bIn )
- {
- // Doesn't matter what these are because you're not going to be drawing anything
- // at screenX1.
- pPrevNode = pCurNode;
- break;
- }
- else if( (pWall->screenX1 - pCurNode->x) < 1 && pCurNode != &headNode )
- {
- break;
- }
- else
- {
- pNewNode = GetXClip();
- pNewNode->x = pWall->screenX1;
-
- pNewNode->pNext = pCurNode->pNext;
- pCurNode->pNext = pNewNode;
-
- pCurNode = pNewNode;
- pPrevNode = pCurNode;
- break;
- }
- }
-
- // Advance in the list and update the in/out flag.
- pPrevNode = pCurNode;
- pCurNode = pCurNode->pNext;
- bIn = !bIn;
- }
-
-
-
- // At this point, pPrevNode = pCurNode, and bIn is valid. Draw and remove edges until
- // you hit pWall->screenX2.
-
- while( pCurNode->pNext != pCurNode )
- {
- // If you're at the end of the Line...
- if( pWall->screenX2 <= pCurNode->pNext->x || pCurNode->pNext == &tailNode )
- {
- if( !bIn )
- {
- if( pCurNode->pNext->x - pWall->screenX2 < 1 )
- {
- pPrevNode->pNext = pCurNode->pNext->pNext;
- dr_DrawHorizontalStrip( pWall, pCurNode->x, pWall->screenX2 );
- }
- else
- {
- // If you're in open space, add a new edge for screenX2 and get rid of the
- // current edge.
- pNewNode = GetXClip();
- pNewNode->x = pWall->screenX2;
-
- pNewNode->pNext = pCurNode->pNext;
- pPrevNode->pNext = pNewNode;
- dr_DrawHorizontalStrip( pWall, pCurNode->x, pWall->screenX2 );
- }
- }
- else
- {
- pPrevNode->pNext = pCurNode->pNext;
- }
-
- break;
- }
-
- if( !bIn )
- dr_DrawHorizontalStrip( pWall, pCurNode->x, pCurNode->pNext->x );
-
-
- pPrevNode->pNext = pCurNode->pNext;
- pCurNode = pCurNode->pNext;
- bIn = !bIn;
- }
-
-
- // Check if the whole screen is drawn.
- if( (headNode.pNext->x == s_MinX && headNode.pNext->pNext->x == s_MaxX) || headNode.pNext->x == s_MaxX )
- return ScreenCompletelyDrawn;
- else
- return DrewWall;
- }
-
-
-
- X_Clip *GetXClip()
- {
- X_Clip *pRetVal;
-
- pRetVal = &clipSpace[nClipsUsed++];
- assert(nClipsUsed < MAX_X_CLIPS);
- return pRetVal;
- }
-
-
- void dr_DrawHorizontalStrip( ProcessWall *pWall, WORD xLeft, WORD xRight )
- {
- Fixed tLeft, tRight;
-
- Fixed curTopY, curBottomY;
- WORD x;
-
- BYTE *pPaletteMap;
- DWORD paletteMap;
-
- Fixed worldXStart, worldZStart;
- Fixed worldXEnd, worldZEnd;
- Fixed worldXStep, worldZStep;
- Fixed fixedWorldX, fixedWorldZ;
- DWORD worldX, worldZ;
-
- WORD xTexturePos=0;
- Texture *pTexture, *pSky;
-
- // Stuff for showing projection lines.
- DWORD y1, y2;
- BYTE color1=30, color2=130;
-
- // Texture mapping variables.
- Fixed a, c, u;
-
- WORD unfixedTopY, unfixedBottomY;
- Fixed textureStep, textureClipAdd, tempStep, texturePos;
- BYTE *pParallax;
-
-
- #pragma aux dr_WallLine = \
- "mov eax,texturePos" \
- "sub eax,textureStep" \
- "LOOP_AGAIN:" \
- "add eax,textureStep" \
- "mov texturePos,eax" \
- "shr eax,20" \
- "xor edx,edx" \
- "mov dl,[esi+eax]" \
- "mov al, [ebx+edx]" \
- "mov [edi],al" \
- "mov eax,texturePos" \
- "add edi,s_PagedWidth" \
- "loopnz LOOP_AGAIN" \
- modify [edx] \
- parm [edi] [esi] [ebx] [eax] [ecx];
-
-
- #pragma aux dr_ParallaxLine = \
- "push ebp" \
- "mov ebp,s_PagedWidth" \
- "LOOP_AGAIN:" \
- "xor eax,eax" \
- "lodsb" \
- "mov dl,[ebx+eax]" \
- "mov [edi],dl" \
- "add edi,ebp" \
- "loopnz LOOP_AGAIN" \
- "pop ebp" \
- modify [eax] \
- parm [edi] [esi] [ebx] [ecx];
-
-
- #pragma aux dr_BlankVLine = \
- "LOOP_AGAIN:" \
- "mov [edi],al" \
- "add edi,esi" \
- "loopnz LOOP_AGAIN" \
- parm [edi] [ecx] [esi] [al];
-
-
- // Increment the Y coordinates.
- curTopY = (pWall->topSlope * (Fixed)xLeft) + FIX(pWall->yTopIntercept);
- curBottomY = (pWall->bottomSlope * (Fixed)xLeft) + FIX(pWall->yBottomIntercept);
-
- if( pWall->viewSide == RightSide )
- {
- pTexture = tx_GetTexture( pWall->pLine->idRightTex );
-
- tLeft = FIX(xLeft - pWall->unclippedScreenX1) / (pWall->unclippedScreenX2 - pWall->unclippedScreenX1);
- tRight = FIX(xRight - pWall->unclippedScreenX1) / (pWall->unclippedScreenX2 - pWall->unclippedScreenX1);
- }
- else
- {
- pTexture = tx_GetTexture( pWall->pLine->idLeftTex );
-
- tLeft = FIX(xRight - pWall->unclippedScreenX1) / (pWall->unclippedScreenX2 - pWall->unclippedScreenX1);
- tRight = FIX(xLeft - pWall->unclippedScreenX1) / (pWall->unclippedScreenX2 - pWall->unclippedScreenX1);
- }
-
- worldXStart = pWall->x1 + FMul(tLeft, pWall->x2 - pWall->x1);
- worldZStart = pWall->y1 + FMul(tLeft, pWall->y2 - pWall->y1);
- worldXEnd = pWall->x1 + FMul(tRight, pWall->x2 - pWall->x1);
- worldZEnd = pWall->y1 + FMul(tRight, pWall->y2 - pWall->y1);
- worldXStep = (worldXEnd - worldXStart) / (xRight-xLeft);
- worldZStep = (worldZEnd - worldZStart) / (xRight-xLeft);
-
- fixedWorldX = worldXStart;
- fixedWorldZ = worldZStart;
-
-
- // Set up texture mapping stuff for this Wall (if it's not already.)
- if( !pWall->bTextureInitted )
- {
- pWall->Px = pWall->originX;
- pWall->Py = bottomY;
- pWall->Pz = pWall->originZ / xWorldScale;
-
- pWall->Mx = (pWall->horzX - pWall->originX);
- pWall->My = 0;
- pWall->Mz = (pWall->horzZ - pWall->originZ) / xWorldScale;
-
- pWall->Nx = 0;
- pWall->Ny = topY - bottomY;
- pWall->Nz = 0;
-
- // Magic numbers..
- pWall->Oa = -FMul(pWall->Ny,pWall->Px);
- pWall->Ha = FMul(pWall->Ny,pWall->Pz);
-
- pWall->Oc = -FMul(pWall->Mx,pWall->Ny);
- pWall->Hc = FMul(pWall->Mz,pWall->Ny);
-
- pWall->bTextureInitted = TRUE;
- }
-
-
- // Set up the texture mapping.
- a = pWall->Oa + ((xLeft-centerX) * pWall->Ha);
- c = pWall->Oc + ((xLeft-centerX) * pWall->Hc);
-
-
- // Get a pointer to the sky texture.
- pSky = tx_GetTexture( curLevel.idCurSky );
-
- // Draw from xLeft to xRight.
- for( x=xLeft; x < xRight; x++ )
- {
- worldX = UNFIX(fixedWorldX);
- worldZ = UNFIX(fixedWorldZ);
- fixedWorldX += worldXStep;
- fixedWorldZ += worldZStep;
-
-
- // Get the texture position.
- a += pWall->Ha;
- c += pWall->Hc;
- u = FDiv(a,c);
- xTexturePos = (u >> pTexture->xTextureShift) & pTexture->xTextureMask;
-
-
- // Get the right palette map.
- if( bBlackAndWhite )
- {
- pPaletteMap = blackWhitePal;
- }
- else
- {
- paletteMap = (worldZ * worldZ) >> (FIXED_SHIFT-5);
-
- #ifndef PALETTE_MAPS
- paletteMap = (FIX(paletteMap) / zFadeOut) >> (FIXED_SHIFT-5);
- #else
- paletteMap = (FIX(paletteMap) / zFadeOut) >> (FIXED_SHIFT-6);
- #endif
- if( paletteMap >= nPaletteMaps )
- paletteMap = nPaletteMaps-1;
-
- pPaletteMap = pPaletteMaps[paletteMap];
- }
-
-
- // Do the actual drawing of the vertical lines.
- unfixedTopY = UNFIX(curTopY);
- unfixedBottomY = UNFIX(curBottomY);
- textureStep = FDiv(FIX(pTexture->height-1)<<TEXTURE_FIX, (curBottomY - curTopY));
-
- if( unfixedTopY > s_MinY )
- {
- // Draw the parallaxing sky.
- pParallax = pSky->pVertLines[ (parallaxLookup.Get(x-s_MinX) + player.facingAngle) & pSky->xTextureMask ];
-
- tempStep = textureStep;
- textureStep = (FIX(128)<<TEXTURE_FIX) / (centerY - s_MinY);
-
- texturePos = 0;
-
- dr_WallLine( &pScreenMem[(s_MinY*s_PagedWidth) + s_PageLookup[x]], pParallax, pPaletteMaps[parallaxMap], s_MinX, unfixedTopY );
- textureStep = tempStep;
-
-
- // Do the texture map.
- textureClipAdd = textureStep * unfixedTopY;
- textureClipAdd -= FMul(textureStep, curTopY - FIXED_ONE);
-
- texturePos = textureClipAdd;
-
- if( unfixedBottomY >= s_MaxY )
- dr_WallLine( &pScreenMem[(unfixedTopY*s_PagedWidth) + s_PageLookup[x]], pTexture->pVertLines[xTexturePos], pPaletteMap, textureClipAdd, s_MaxY-unfixedTopY );
- else
- dr_WallLine( &pScreenMem[(unfixedTopY*s_PagedWidth) + s_PageLookup[x]], pTexture->pVertLines[xTexturePos], pPaletteMap, textureClipAdd, unfixedBottomY-unfixedTopY );
- }
- else
- {
- textureClipAdd = FMul(textureStep, FIX(s_MinY)-curTopY + FIXED_ONE);
-
- texturePos = textureClipAdd;
-
- if( unfixedBottomY >= s_MaxY )
- dr_WallLine( &pScreenMem[(s_MinY*s_PagedWidth) + s_PageLookup[x]], pTexture->pVertLines[xTexturePos], pPaletteMap, textureClipAdd, s_DrawHeight );
- else
- dr_WallLine( &pScreenMem[(s_MinY*s_PagedWidth) + s_PageLookup[x]], pTexture->pVertLines[xTexturePos], pPaletteMap, textureClipAdd, unfixedBottomY );
- }
-
- if( unfixedBottomY < s_MaxY )
- dr_BlankVLine( &pScreenMem[((DWORD)unfixedBottomY*s_PagedWidth)+s_PageLookup[x]], s_Height-unfixedBottomY, s_PagedWidth, 0 );
-
- // Increment top and bottom lines.
- curTopY += pWall->topSlope;
- curBottomY += pWall->bottomSlope;
- }
-
- if( bDisplayProjectionPoints )
- {
- if( pWall->viewSide == LeftSide )
- {
- // Left side has lines going up and down.
-
- y1 = W_UNFIX(pWall->screenX1 * pWall->topSlope) + pWall->yTopIntercept;
- y2 = W_UNFIX(pWall->screenX1 * pWall->bottomSlope) + pWall->yBottomIntercept;
- dr_DrawLine( pWall->screenX1, y1, pWall->screenX1, y2, s_MaxX, s_MaxY, color1 );
-
- y1 = W_UNFIX(pWall->screenX2 * pWall->topSlope) + pWall->yTopIntercept;
- y2 = W_UNFIX(pWall->screenX2 * pWall->bottomSlope) + pWall->yBottomIntercept;
- dr_DrawLine( pWall->screenX2, y1, pWall->screenX2, y2, s_MaxX, s_MaxY, color1 );
- }
- else
- {
- // Right side has lines going left to right.
-
- y1 = W_UNFIX(pWall->screenX1 * pWall->topSlope) + pWall->yTopIntercept;
- y2 = W_UNFIX(pWall->screenX2 * pWall->topSlope) + pWall->yTopIntercept;
- dr_DrawLine( pWall->screenX1, y1, pWall->screenX2, y2, s_MaxX, s_MaxY, color2 );
-
- y1 = W_UNFIX(pWall->screenX1 * pWall->bottomSlope) + pWall->yBottomIntercept;
- y2 = W_UNFIX(pWall->screenX2 * pWall->bottomSlope) + pWall->yBottomIntercept;
- dr_DrawLine( pWall->screenX1, y1, pWall->screenX2, y2, s_MaxX, s_MaxY, color2 );
- }
- }
- }
-
- /*
- void dr_WallLine( BYTE *pDrawTo, BYTE *pBuffer, BYTE *pPaletteMap, Fixed bufferStartPos, Fixed bufferAdd, WORD vLineInc, WORD numPixels )
- {
- WORD i;
- Fixed bufferPos;
- BYTE color;
-
- bufferPos=bufferStartPos;
- for( i=0; i < numPixels; i++ )
- {
- color = pBuffer[bufferPos >> (FIXED_SHIFT+TEXTURE_FIX)];
- *pDrawTo = pPaletteMap[color];
-
- bufferPos += bufferAdd;
- pDrawTo += vLineInc;
- }
- }
- */
-
- /*
- void dr_ParallaxLine( BYTE *pDrawTo, BYTE *pBuffer, BYTE *pPaletteMap, DWORD vLineInc, DWORD numPixels )
- {
- WORD i;
-
- for( i=0; i < numPixels; i++ )
- {
- *pDrawTo = pPaletteMap[*pBuffer];
-
- ++pBuffer;
- pDrawTo += vLineInc;
- }
- }
- */
-
- void Draw2DEnvironment( CLineArray *pLines, CPointArray *pPoints, WORD xOffset, WORD yOffset, Fixed scale, WORD maxX, WORD maxY )
- {
- Fixed x1, y1, x2, y2;
- Fixed x, y;
- WORD drawX, drawY;
- WORD i;
- CLine *pCurLine;
- CPoint *pCurPt;
-
- // Draw all the Lines.
- for( i=0; i < pLines->NumElements(); i++ )
- {
- pCurLine = pLines->GetLine(i);
-
- x1 = xOffset + pCurLine->pPoint1->localX;
- y1 = yOffset + pCurLine->pPoint1->localY;
- x2 = xOffset + pCurLine->pPoint2->localX;
- y2 = yOffset + pCurLine->pPoint2->localY;
-
- x1 = x1 * scale;
- y1 = y1 * scale;
- x2 = x2 * scale;
- y2 = y2 * scale;
-
- dr_DrawLine( W_UNFIX(x1), -W_UNFIX(y1), W_UNFIX(x2), -W_UNFIX(y2), maxX, maxY, 30 );
- }
-
-
- // Draw all the Points.
- for( i=0; i < pPoints->NumElements(); i++ )
- {
- pCurPt = pPoints->GetPoint(i);
-
- x = xOffset + pCurPt->localX;
- y = yOffset + pCurPt->localY;
-
- x = x * scale;
- y = y * scale;
-
- drawX = W_UNFIX(x);
- drawY = -W_UNFIX(y);
-
- if( drawX >= 0 && drawX < maxX && drawY >= 0 && drawY < maxY )
- pScreenMem[ (drawY*s_PagedWidth) + s_PageLookup[drawX] ] = 60;
- }
-
- s_SetPixel( W_UNFIX(player.xPos*scale), W_UNFIX(player.yPos*scale), 120 );
- }
-
-
- void dr_DrawLine( DWORD x1, DWORD y1, DWORD x2, DWORD y2, WORD maxX, WORD maxY, BYTE color )
- {
- WORD numPixels;
- WORD i;
- Fixed curX, curY, xInc, yInc;
- WORD x, y;
-
- // Test if it's off the screen so we might not have to draw it.
- if( (x1 < 0 || x1 >= maxX) && (y1 < 0 || y1 >= maxY) &&
- (x2 < 0 || x2 >= maxX) && (y2 < 0 || y2 >= maxY) )
- return;
-
- if( ABS(x2-x1) > ABS(y2-y1) )
- numPixels = (WORD)ABS(x2-x1);
- else
- numPixels = (WORD)ABS(y2-y1);
-
- if( numPixels < 2 )
- return;
-
- curX = FIX(x1);
- curY = FIX(y1);
-
- xInc = FIX(x2-x1) / numPixels;
- yInc = FIX(y2-y1) / numPixels;
-
- for( i=0; i < numPixels; i++ )
- {
- x = W_UNFIX(curX);
- y = W_UNFIX(curY);
-
- if( x >= 0 && x < maxX && y >= 0 && y < maxY )
- pScreenMem[ s_PageLookup[x] + (y*s_PagedWidth) ] = color;
-
- curX += xInc;
- curY += yInc;
- }
- }
-
-
- WORD dr_ClipAgainstLine( Fixed clipLine, Fixed *pX1, Fixed *pY1, Fixed *pX2, Fixed *pY2, Fixed *pT1, Fixed *pT2, BOOL bPositiveHalf )
- {
- assert( *pY1 != *pY2 );
-
- // Replace (x1,y1) or (x2,y2), depending on which one was off the screen.
- if( bPositiveHalf )
- {
- if( *pY1 < clipLine )
- {
- *pT1 = FDiv( clipLine - *pY1, *pY2 - *pY1 );
- *pT2 = FIXED_ONE;
-
- *pX1 = *pX1 + FMul(*pT1, *pX2 - *pX1);
- *pY1 = *pY1 + FMul(*pT1, *pY2 - *pY1);
-
- return 1;
- }
- else
- {
- *pT1 = 0;
- *pT2 = FDiv( clipLine - *pY1, *pY2 - *pY1 );
-
- *pX2 = *pX1 + FMul(*pT2, *pX2 - *pX1);
- *pY2 = *pY1 + FMul(*pT2, *pY2 - *pY1);
-
- return 2;
- }
- }
- else
- {
- if( *pY1 < clipLine )
- {
- *pT1 = 0;
- *pT2 = FDiv( clipLine - *pY1, *pY2 - *pY1 );
-
- *pX2 = *pX1 + FMul(*pT2, *pX2 - *pX1);
- *pY2 = *pY1 + FMul(*pT2, *pY2 - *pY1);
-
- return 2;
- }
- else
- {
- *pT1 = FDiv( *pY1 - clipLine, *pY2 - *pY1 );
- *pT2 = FIXED_ONE;
-
- *pX1 = *pX1 - FMul(*pT1, *pX2 - *pX1);
- *pY1 = *pY1 - FMul(*pT1, *pY2 - *pY1);
-
- return 1;
- }
- }
-
- return 0;
- }
-
-
-
-