/*KJL********************************************************************* * krender.c - Kevin's scandrawing code. (New render, new danger.) * * * * The new scandraws are called by patching the functions below into the * * jumptables used in item.c. If the KRENDER_ON flag in krender.h is zero * * then the old scandraws will be used. * *********************************************************************KJL*/ /* this file is a bit messy at the moment, but I'll be back later... */ #include "3dc.h" #include "inline.h" #include "module.h" #include "gamedef.h" #include "krender.h" #include "vision.h" #define UseLocalAssert Yes #include "ourasert.h" #define PENTIUM_PROFILING_ON 0 #if PENTIUM_PROFILING_ON #include "pentime.h" #else #define ProfileStart(); #define ProfileStop(x); #endif int ReciprocalTable[321]; #if 1 #define DIVIDE(a,b) ((a)/(b)) #else #define DIVIDE(a,b) (MUL_FIXED((a),ReciprocalTable[(b)])) #endif int Transparent; /* assembler fns */ extern void ScanDraw2D_Gouraud(void); extern void ScanDraw2D_GouraudTransparent(void); extern void ScanDraw2D_VAlignedTransparent(void); extern void ScanDraw2D_VAlignedOpaque(void); extern void ScanDraw2D_Transparent(void); extern void ScanDraw2D_TransparentLit(void); extern void ScanDraw2D_Opaque(void); extern void ScanDraw_GouraudScan(void); extern void ScanDrawF3D_Gouraud(void); /* globals accessed by the assembler routines */ unsigned char *SCASM_Lighting; unsigned char *SCASM_Destination; unsigned char *SCASM_Bitmap; int SCASM_StartU; int SCASM_StartV; int SCASM_StartI; int SCASM_DeltaU; int SCASM_DeltaV; int SCASM_DeltaI; int SCASM_ScanLength; int SCASM_ShadingTableSize; int SCASM_TextureDeltaScan; /* things from item.c */ extern int NumScans; extern int ItemColour; extern IMAGEHEADER *ImageHeaderPtrs[MaxImages]; extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock; extern unsigned char *TextureLightingTable; extern int MIP_Index; extern int ScanData[maxpolys*maxscansize]; extern unsigned char *ScreenBuffer; extern long BackBufferPitch; void Draw_Gouraud3dTexture_Spans(int *itemptr); int KRenderDrawMode = 0; /***********/ void KR_ScanDraw_Item_Gouraud2dTexturePolygon_VideoModeType_8(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *) itemptr; I_GOURAUD2DTEXTUREPOLYGON_SCAN *sptr; if(NumScans) { int y = NumScans; /* Get the Image Data required for the Draw */ { IMAGEHEADER *ImageHdr; { int TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { TEXTURE **TxImagePtr = &ImageHdr->ImagePtr; SCASM_Bitmap = TxImagePtr[MIP_Index]; GLOBALASSERT(SCASM_Bitmap); SCASM_TextureDeltaScan = ImageHdr->ImageWidth >> MIP_Index; #if MIP_ROUNDUP if (ImageHdr->ImageWidth & (1<ImageWidth; SCASM_Bitmap = ImageHdr->ImagePtr; GLOBALASSERT(SCASM_Bitmap); } } SCASM_Lighting = TextureLightingTable; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_Raw256) SCASM_ShadingTableSize = 256; else SCASM_ShadingTableSize = 64; sptr = (I_GOURAUD2DTEXTUREPOLYGON_SCAN *) ScanData; do { int dx = sptr->ig2s_x2 - sptr->ig2s_x1; if (dx>0 && !(sptr->ig2s_y & KRenderDrawMode) ) { /* Fixed Point U for Interpolation */ { int StartU = sptr->ig2s_u1; SCASM_DeltaU = DIVIDE((sptr->ig2s_u2 - StartU),dx); SCASM_StartU = StartU; } /* Fixed Point V for Interpolation */ { int StartV = sptr->ig2s_v1; SCASM_DeltaV = DIVIDE((sptr->ig2s_v2 - StartV),dx); SCASM_StartV = StartV; } /* Fixed Point I for Interpolation */ { int StartI = sptr->ig2s_c1; SCASM_DeltaI = DIVIDE((sptr->ig2s_c2 - StartI),dx); SCASM_StartI = StartI; } /* Draw the Gouraud 2d Texture Scan */ SCASM_Destination = ScreenBuffer + (sptr->ig2s_y * BackBufferPitch) + sptr->ig2s_x1; SCASM_ScanLength = dx; if(pheader->PolyFlags & iflag_ignore0) { ScanDraw2D_GouraudTransparent(); } else { ScanDraw2D_Gouraud(); } } sptr++; y--; } while(y); } } void Draw3DScan(I_GOURAUD3DTEXTUREPOLYGON_SCAN *scanPtr, POLYHEADER *pheader) { int dx = scanPtr->ig3s_x2 - scanPtr->ig3s_x1; if(dx > 0) { float uf; float vf; float uf2; float vf2; /* Get start and end UVs */ { float ooz1; ooz1 = 65536.0 / scanPtr->ig3s_z1; uf = scanPtr->ig3s_u1 * ooz1; vf = scanPtr->ig3s_v1 * ooz1; } { float ooz2; ooz2 = 65536.0 / scanPtr->ig3s_z2; uf2 = scanPtr->ig3s_u2 * ooz2; vf2 = scanPtr->ig3s_v2 * ooz2; } if ( (uf>16700000.0) ||(uf<0.0) ||(vf>16700000.0) ||(vf<0.0) ) { textprint("WARNING: UV coords invalid\n"); // LOCALASSERT(0); return; } if ( (uf2>16700000.0) ||(uf2<0.0) ||(vf2>16700000.0) ||(vf2<0.0) ) { textprint("WARNING: UV coords invalid\n"); // LOCALASSERT(0); return; } /* For UV interpolation */ f2i(SCASM_StartU,uf); f2i(SCASM_StartV,vf); { int EndU,EndV; f2i(EndU,uf2); f2i(EndV,vf2); SCASM_DeltaU =(EndU-SCASM_StartU)/dx; SCASM_DeltaV =(EndV-SCASM_StartV)/dx; } /* Fixed Point I for Interpolation */ { int StartI = scanPtr->ig3s_c1; SCASM_DeltaI = (scanPtr->ig3s_c2 - StartI)/dx; SCASM_StartI = StartI; } /* Draw the 3d Texture Scan */ SCASM_Destination = ScreenBuffer + (scanPtr->ig3s_y * BackBufferPitch) + scanPtr->ig3s_x1; SCASM_ScanLength = dx; if(pheader->PolyFlags & iflag_ignore0) { ScanDraw2D_GouraudTransparent(); } else { ScanDraw2D_Gouraud(); } } } void KR_ScanDraw_Item_Gouraud3dTexturePolygon_Linear_S_VideoModeType_8(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *) itemptr; int num_scans_s; I_GOURAUD3DTEXTUREPOLYGON_SCAN *sptr_array_ptr; I_GOURAUD3DTEXTUREPOLYGON_SCAN *next_free_sptr; I_GOURAUD3DTEXTUREPOLYGON_SCAN sptr_array[lin_s_max + 1]; int StillSubdividing; int i; if(NumScans) { I_GOURAUD3DTEXTUREPOLYGON_SCAN *sptr; int y; /* Get the Image Data required for the Draw */ { IMAGEHEADER *ImageHdr; { int TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { TEXTURE **TxImagePtr = &ImageHdr->ImagePtr; SCASM_Bitmap = TxImagePtr[MIP_Index]; GLOBALASSERT(SCASM_Bitmap); SCASM_TextureDeltaScan = ImageHdr->ImageWidth >> MIP_Index; #if MIP_ROUNDUP if (ImageHdr->ImageWidth & (1<ImageWidth; SCASM_Bitmap = ImageHdr->ImagePtr; GLOBALASSERT(SCASM_Bitmap); } } SCASM_Lighting = TextureLightingTable; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_Raw256) SCASM_ShadingTableSize = 256; else SCASM_ShadingTableSize = 64; sptr = (I_GOURAUD3DTEXTUREPOLYGON_SCAN *) ScanData; for(y = NumScans; y!=0; y--) { int dx = sptr->ig3s_x2 - sptr->ig3s_x1; if (dx>0 && !(sptr->ig3s_y & KRenderDrawMode) ) { float zmax, zmin, z_ratio; /* Have a look at the z-ratio */ if(sptr->ig3s_z1 > sptr->ig3s_z2) { zmax = sptr->ig3s_z1; zmin = sptr->ig3s_z2; } else { zmax = sptr->ig3s_z2; zmin = sptr->ig3s_z1; } z_ratio = (zmax * 256); /* Draw if the z ratio is inside the threshold */ if(z_ratio < lin_s_zthr*zmin) { Draw3DScan(sptr,pheader); } /* Else subdivide until scan segments are inside threshold */ else { /* Copy the current scan to the subdivision array */ sptr_array_ptr = sptr_array; num_scans_s = 1; sptr_array_ptr->ig3s_u1 = sptr->ig3s_u1; sptr_array_ptr->ig3s_v1 = sptr->ig3s_v1; sptr_array_ptr->ig3s_z1 = sptr->ig3s_z1; sptr_array_ptr->ig3s_c1 = sptr->ig3s_c1; sptr_array_ptr->ig3s_u2 = sptr->ig3s_u2; sptr_array_ptr->ig3s_v2 = sptr->ig3s_v2; sptr_array_ptr->ig3s_z2 = sptr->ig3s_z2; sptr_array_ptr->ig3s_c2 = sptr->ig3s_c2; sptr_array_ptr->ig3s_x1 = sptr->ig3s_x1; sptr_array_ptr->ig3s_x2 = sptr->ig3s_x2; sptr_array_ptr->ig3s_y = sptr->ig3s_y; /* Subdivide until no further divisions are needed */ next_free_sptr = sptr_array_ptr + 1; do { sptr_array_ptr = sptr_array; StillSubdividing = No; /* Assume not */ for(i = num_scans_s; i!=0; i--) { #if 0 /* z ratio of this scan */ if(sptr_array_ptr->ig3s_z1 > sptr_array_ptr->ig3s_z2) { z_ratio = (sptr_array_ptr->ig3s_z1 * 256) / sptr_array_ptr->ig3s_z2; } else { z_ratio = (sptr_array_ptr->ig3s_z2 * 256) / sptr_array_ptr->ig3s_z1; } /* Is it within the threshold? */ if(z_ratio > lin_s_zthr && num_scans_s < lin_s_max) #endif int overThreshold=0; /* z ratio of this scan */ if(sptr_array_ptr->ig3s_z1 > sptr_array_ptr->ig3s_z2) { if ( (sptr_array_ptr->ig3s_z1 * 256) > (lin_s_zthr*sptr_array_ptr->ig3s_z2)) overThreshold=1; } else { if ( (sptr_array_ptr->ig3s_z2 * 256) > (lin_s_zthr*sptr_array_ptr->ig3s_z1)) overThreshold=1; } /* Is it within the threshold? */ if(overThreshold && num_scans_s < lin_s_max) { int mid_x, mid_c; float mid_u, mid_v, mid_z; /* No - subdivide */ StillSubdividing = Yes; mid_u = (sptr_array_ptr->ig3s_u1 + sptr_array_ptr->ig3s_u2) / 2; mid_v = (sptr_array_ptr->ig3s_v1 + sptr_array_ptr->ig3s_v2) / 2; mid_z = (sptr_array_ptr->ig3s_z1 + sptr_array_ptr->ig3s_z2) / 2; mid_c = (sptr_array_ptr->ig3s_c1 + sptr_array_ptr->ig3s_c2) / 2; mid_x = (sptr_array_ptr->ig3s_x1 + sptr_array_ptr->ig3s_x2) / 2; /* Create new scan */ next_free_sptr->ig3s_u1 = mid_u; next_free_sptr->ig3s_v1 = mid_v; next_free_sptr->ig3s_z1 = mid_z; next_free_sptr->ig3s_c1 = mid_c; next_free_sptr->ig3s_x1 = mid_x; next_free_sptr->ig3s_u2 = sptr_array_ptr->ig3s_u2; next_free_sptr->ig3s_v2 = sptr_array_ptr->ig3s_v2; next_free_sptr->ig3s_z2 = sptr_array_ptr->ig3s_z2; next_free_sptr->ig3s_c2 = sptr_array_ptr->ig3s_c2; next_free_sptr->ig3s_x2 = sptr_array_ptr->ig3s_x2; next_free_sptr->ig3s_y = sptr_array_ptr->ig3s_y; /* Redefine old scan */ sptr_array_ptr->ig3s_u2 = mid_u; sptr_array_ptr->ig3s_v2 = mid_v; sptr_array_ptr->ig3s_z2 = mid_z; sptr_array_ptr->ig3s_c2 = mid_c; sptr_array_ptr->ig3s_x2 = mid_x; /* Update pointer and counter */ next_free_sptr++; num_scans_s++; } sptr_array_ptr++; } } while(StillSubdividing); /* Draw the scan array */ sptr_array_ptr = sptr_array; for(i = num_scans_s; i!=0; i--) { Draw3DScan(sptr_array_ptr,pheader); sptr_array_ptr++; } } } sptr++; } } } void KR_ScanDraw_Item_2dTexturePolygon_VideoModeType_8(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *) itemptr; if(NumScans) { if(pheader->PolyFlags & iflag_nolight) { int y; I_2DTEXTUREPOLYGON_SCAN *sptr = (I_2DTEXTUREPOLYGON_SCAN *) ScanData; /* Offset in Screen Buffer */ { IMAGEHEADER *ImageHdr; { int TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { TEXTURE **TxImagePtr = &ImageHdr->ImagePtr; SCASM_Bitmap = TxImagePtr[MIP_Index]; GLOBALASSERT(SCASM_Bitmap); SCASM_TextureDeltaScan = ImageHdr->ImageWidth >> MIP_Index; #if MIP_ROUNDUP if (ImageHdr->ImageWidth & (1<ImageWidth; SCASM_Bitmap = ImageHdr->ImagePtr; GLOBALASSERT(SCASM_Bitmap); } } /* Get the Image Data required for the Draw */ for(y=NumScans; y!=0; y--) { int dx = sptr->i2s_x2 - sptr->i2s_x1; if (dx>0 && !(sptr->i2s_y & KRenderDrawMode) ) { /* Fixed Point U for Interpolation */ { int StartU = sptr->i2s_u1; SCASM_DeltaU = (sptr->i2s_u2 - StartU)/dx; SCASM_StartU = StartU; } /* Fixed Point V for Interpolation */ { int StartV = sptr->i2s_v1; SCASM_DeltaV = (sptr->i2s_v2 - StartV)/dx; SCASM_StartV = StartV; } SCASM_Destination = ScreenBuffer + (sptr->i2s_y * BackBufferPitch) + sptr->i2s_x1; SCASM_ScanLength = dx; /* Is VDelta = 0? */ if(SCASM_DeltaV == 0) { if(pheader->PolyFlags & iflag_ignore0) { ScanDraw2D_VAlignedTransparent(); } else { ScanDraw2D_VAlignedOpaque(); } } else { if(pheader->PolyFlags & iflag_ignore0) { ScanDraw2D_Transparent(); } else { ScanDraw2D_Opaque(); } } } sptr++; } } #if 1 else { int y; I_2DTEXTUREPOLYGON_SCAN *sptr = (I_2DTEXTUREPOLYGON_SCAN *) ScanData; /* Offset in Screen Buffer */ { IMAGEHEADER *ImageHdr; { int TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { TEXTURE **TxImagePtr = &ImageHdr->ImagePtr; SCASM_Bitmap = TxImagePtr[MIP_Index]; GLOBALASSERT(SCASM_Bitmap); SCASM_TextureDeltaScan = ImageHdr->ImageWidth >> MIP_Index; #if MIP_ROUNDUP if (ImageHdr->ImageWidth & (1<ImageWidth; SCASM_Bitmap = ImageHdr->ImagePtr; GLOBALASSERT(SCASM_Bitmap); } } SCASM_StartI = ItemColour >> TxDefn; SCASM_Lighting = TextureLightingTable; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_Raw256) SCASM_ShadingTableSize = 256; else SCASM_ShadingTableSize = 64; /* Get the Image Data required for the Draw */ for(y=NumScans; y!=0; y--) { int dx = sptr->i2s_x2 - sptr->i2s_x1; if (dx>0 && !(sptr->i2s_y & KRenderDrawMode) ) { /* Fixed Point U for Interpolation */ { int StartU = sptr->i2s_u1; SCASM_DeltaU = (sptr->i2s_u2 - StartU)/dx; SCASM_StartU = StartU; } /* Fixed Point V for Interpolation */ { int StartV = sptr->i2s_v1; SCASM_DeltaV = (sptr->i2s_v2 - StartV)/dx; SCASM_StartV = StartV; } SCASM_Destination = ScreenBuffer + (sptr->i2s_y * BackBufferPitch) + sptr->i2s_x1; SCASM_ScanLength = dx; ScanDraw2D_TransparentLit(); // PredatorScanDraw(); } sptr++; } } #endif } } unsigned char LighterTable[255]; int predatorTimer = 0; void ScanDraw_CloakedScan(void) { unsigned char *screen = SCASM_Destination; int x = SCASM_ScanLength; unsigned char buffer[1000]; do { buffer[x] = *screen++; } while(--x); screen = SCASM_Destination; x = SCASM_ScanLength; if (FastRandom()&3==3 && x>2) { x--; screen++; } if (FastRandom()&3==3 && x>2) { x--; } do { { extern sine[]; extern cosine[]; unsigned char colour; int offset = (GetCos( ((x*2047)/SCASM_ScanLength + predatorTimer)&4095 )+65536)/2; offset = MUL_FIXED(offset,offset); colour = (buffer[SCASM_ScanLength-x+1]); // colour = (buffer[x]); #if 0 int i; for (i=0; i<=255;i++) { if (colour==*(TextureLightingTable + 256*200 + i)) break; } #endif colour=*(TextureLightingTable + 256*(60+MUL_FIXED(4,GetCos(predatorTimer&4095)) ) + colour); *screen++ = colour; } } while(--x); } #if 0 void PredatorScanDraw(void) { unsigned char *screen = SCASM_Destination; unsigned char *source; do { source = SCASM_Bitmap+ (SCASM_StartU>>16) + (SCASM_StartV>>16)*SCASM_TextureDeltaScan; *screen++ = *source++; SCASM_StartU += SCASM_DeltaU; SCASM_StartV += SCASM_DeltaV; } while(--SCASM_ScanLength); } #else void PredatorScanDraw(void) { unsigned char *screen = SCASM_Destination; unsigned char *source; int x = SCASM_ScanLength; do { source = SCASM_Bitmap+ (SCASM_StartU>>16) + (SCASM_StartV>>16)*SCASM_TextureDeltaScan; if (*source) { extern sine[]; extern cosine[]; unsigned char colour = *(screen); *screen = LighterTable[colour]; } screen++; SCASM_StartU += SCASM_DeltaU; SCASM_StartV += SCASM_DeltaV; } while(--x); } #endif void Draw_Item_CloakedPolygon(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *)itemptr; int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; { I_GOURAUDPOLYGON_PT *vertexPtr = (I_GOURAUDPOLYGON_PT*)&pheader->Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_GOURAUDPOLYGON_PT *vertexPtr = (I_GOURAUDPOLYGON_PT*)&pheader->Poly1stPt; I_GOURAUDPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion=0; NumScans=0; /* scan out the right edge */ polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int i,x,y; int deltaX,deltaI; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_int - vertexPtr[curVertex].i_int; deltaX = (width<<16)/height; deltaI = contrast/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_int; for (y=vertexPtr[curVertex].i_y; yigs_x2 = x>>16; x+=deltaX; polyScan->igs_c2 = i; i+=deltaI; polyScan->igs_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int i,x,y; int deltaX,deltaI; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_int - vertexPtr[curVertex].i_int; deltaX = (width<<16)/height; deltaI = contrast/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_int; for (y=vertexPtr[curVertex].i_y; yigs_x1 = x>>16; x+=deltaX; polyScan->igs_c1 = i; i+=deltaI; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionPolyColour; I_GOURAUDPOLYGON_SCAN *polyScan; polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; SCASM_Lighting = TextureLightingTable+colour; SCASM_ShadingTableSize = 256; while(NumScans) { int dx = polyScan->igs_x2 - polyScan->igs_x1; if (dx>0) { SCASM_Destination = ScreenBuffer+(polyScan->igs_y * BackBufferPitch) + polyScan->igs_x1; SCASM_ScanLength = dx; SCASM_DeltaI = (polyScan->igs_c2-polyScan->igs_c1)/dx; SCASM_StartI = polyScan->igs_c1; ScanDraw_CloakedScan(); } NumScans--; polyScan++; } } } #if 1 void KDraw_Item_GouraudPolygon(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *)itemptr; int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; { I_GOURAUDPOLYGON_PT *vertexPtr = (I_GOURAUDPOLYGON_PT*)&pheader->Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_GOURAUDPOLYGON_PT *vertexPtr = (I_GOURAUDPOLYGON_PT*)&pheader->Poly1stPt; I_GOURAUDPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion=0; NumScans=0; /* scan out the right edge */ polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int i,x,y; int deltaX,deltaI; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_int - vertexPtr[curVertex].i_int; deltaX = (width<<16)/height; deltaI = contrast/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_int; for (y=vertexPtr[curVertex].i_y; yigs_x2 = x>>16; x+=deltaX; polyScan->igs_c2 = i; i+=deltaI; polyScan->igs_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int i,x,y; int deltaX,deltaI; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_int - vertexPtr[curVertex].i_int; deltaX = (width<<16)/height; deltaI = contrast/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_int; for (y=vertexPtr[curVertex].i_y; yigs_x1 = x>>16; x+=deltaX; polyScan->igs_c1 = i; i+=deltaI; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionPolyColour; I_GOURAUDPOLYGON_SCAN *polyScan; polyScan = (I_GOURAUDPOLYGON_SCAN*)ScanData; SCASM_Lighting = TextureLightingTable+colour; SCASM_ShadingTableSize = 256; while(NumScans) { int dx = polyScan->igs_x2 - polyScan->igs_x1; if (dx>0) { SCASM_Destination = ScreenBuffer+(polyScan->igs_y * BackBufferPitch) + polyScan->igs_x1; SCASM_ScanLength = dx; SCASM_DeltaI = (polyScan->igs_c2-polyScan->igs_c1)/dx; SCASM_StartI = polyScan->igs_c1; ScanDraw_GouraudScan(); } NumScans--; polyScan++; } } } void KDraw_Item_2dTexturePolygon(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *) itemptr; int TxIndex; IMAGEHEADER *ImageHdr; ItemColour = pheader->PolyColour; TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; /* Colour */ /* If MIP Mapping, calculate the scale */ if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { I_2DTEXTUREPOLYGON_PT *vector1; I_2DTEXTUREPOLYGON_PT *vector2; I_2DTEXTUREPOLYGON_PT *vector3; int mip1, mip2; int xyd, uvd; VECTOR2D s0, s1; VECTOR2D t0, t1; /* Screen and Texture Space Vectors */ /* Express the "uvd / xyd" ratio as a binary scale */ vector1 = (I_2DTEXTUREPOLYGON_PT *) &pheader->Poly1stPt; vector2 = &vector1[1]; vector3 = &vector1[2]; /* Vector 1 */ s0.vx = vector1->i_x; s0.vy = vector1->i_y; s1.vx = vector2->i_x; s1.vy = vector2->i_y; t0.vx = vector1->i_u >> 16; t0.vy = vector1->i_v >> 16; t1.vx = vector2->i_u >> 16; t1.vy = vector2->i_v >> 16; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip1 = FindShift32(uvd, xyd); /* Vector 2 */ s0.vx = vector2->i_x; s0.vy = vector2->i_y; s1.vx = vector3->i_x; s1.vy = vector3->i_y; t0.vx = t1.vx; t0.vy = t1.vy; t1.vx = vector3->i_u >> 16; t1.vy = vector3->i_v >> 16; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip2 = FindShift32(uvd, xyd); /* Choose the larger of the two */ if(pheader->PolyFlags & iflag_no_mip) { MIP_Index = 0; } else { #if UseMIPMax if(mip1 > mip2) MIP_Index = mip1; else MIP_Index = mip2; #endif #if UseMIPMin if(mip1 > mip2) MIP_Index = mip2; else MIP_Index = mip1; #endif #if UseMIPAvg MIP_Index = (mip1 + mip2) >> 1; #endif } /* Clamp "MIP_Index" */ #if MIP_INDEX_SUBTRACT MIP_Index -= MIP_INDEX_SUBTRACT; if(MIP_Index < 0) MIP_Index = 0; else if(MIP_Index > 6) MIP_Index = 6; #else if(MIP_Index > 6) MIP_Index = 6; #endif } { int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; { I_2DTEXTUREPOLYGON_PT *vertexPtr = (I_2DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_u >>= MIP_Index; vertexPtr->i_v >>= MIP_Index; } vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_u >>= MIP_Index; vertexPtr->i_v >>= MIP_Index; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_2DTEXTUREPOLYGON_PT *vertexPtr = (I_2DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; I_2DTEXTUREPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion = 0; NumScans=0; /* scan out the right edge */ polyScan = (I_2DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int x,y,u,v; int deltaX,deltaU,deltaV; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int widthU = vertexPtr[nextVertex].i_u - vertexPtr[curVertex].i_u; int widthV = vertexPtr[nextVertex].i_v - vertexPtr[curVertex].i_v; deltaX = (width<<16)/height; deltaU = widthU/height; deltaV = widthV/height; x = vertexPtr[curVertex].i_x<<16; u = vertexPtr[curVertex].i_u; v = vertexPtr[curVertex].i_v; for (y=vertexPtr[curVertex].i_y; yi2s_x2 = x>>16; x+=deltaX; polyScan->i2s_u2 = u; u+=deltaU; polyScan->i2s_v2 = v; v+=deltaV; polyScan->i2s_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_2DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int x,y,u,v; int deltaX,deltaU,deltaV; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int widthU = vertexPtr[nextVertex].i_u - vertexPtr[curVertex].i_u; int widthV = vertexPtr[nextVertex].i_v - vertexPtr[curVertex].i_v; deltaX = (width<<16)/height; deltaU = widthU/height; deltaV = widthV/height; x = vertexPtr[curVertex].i_x<<16; u = vertexPtr[curVertex].i_u; v = vertexPtr[curVertex].i_v; for (y=vertexPtr[curVertex].i_y; yi2s_x1 = x>>16; x+=deltaX; polyScan->i2s_u1 = u; u+=deltaU; polyScan->i2s_v1 = v; v+=deltaV; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionPolyColour; TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; /* Colour */ /* If MIP Mapping, calculate the scale */ if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { I_GOURAUD2DTEXTUREPOLYGON_PT *vector1; I_GOURAUD2DTEXTUREPOLYGON_PT *vector2; I_GOURAUD2DTEXTUREPOLYGON_PT *vector3; int mip1, mip2; int xyd, uvd; VECTOR2D s0, s1; VECTOR2D t0, t1; /* Screen and Texture Space Vectors */ /* Express the "uvd / xyd" ratio as a binary scale */ vector1 = (I_GOURAUD2DTEXTUREPOLYGON_PT *) &pheader->Poly1stPt; vector2 = &vector1[1]; vector3 = &vector1[2]; /* Vector 1 */ s0.vx = vector1->i_x; s0.vy = vector1->i_y; s1.vx = vector2->i_x; s1.vy = vector2->i_y; t0.vx = vector1->i_u >> 16; t0.vy = vector1->i_v >> 16; t1.vx = vector2->i_u >> 16; t1.vy = vector2->i_v >> 16; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip1 = FindShift32(uvd, xyd); /* Vector 2 */ s0.vx = vector2->i_x; s0.vy = vector2->i_y; s1.vx = vector3->i_x; s1.vy = vector3->i_y; t0.vx = t1.vx; t0.vy = t1.vy; t1.vx = vector3->i_u >> 16; t1.vy = vector3->i_v >> 16; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip2 = FindShift32(uvd, xyd); /* Choose the larger of the two */ if(pheader->PolyFlags & iflag_no_mip) { MIP_Index = 0; } else { #if UseMIPMax if(mip1 > mip2) MIP_Index = mip1; else MIP_Index = mip2; #endif #if UseMIPMin if(mip1 > mip2) MIP_Index = mip2; else MIP_Index = mip1; #endif #if UseMIPAvg MIP_Index = (mip1 + mip2) >> 1; #endif } /* Clamp "MIP_Index" */ #if MIP_INDEX_SUBTRACT MIP_Index -= MIP_INDEX_SUBTRACT; if(MIP_Index < 0) MIP_Index = 0; else if(MIP_Index > 6) MIP_Index = 6; #else if(MIP_Index > 6) MIP_Index = 6; #endif } { int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; { I_GOURAUD2DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD2DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_u >>= MIP_Index; vertexPtr->i_v >>= MIP_Index; } vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_u >>= MIP_Index; vertexPtr->i_v >>= MIP_Index; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_GOURAUD2DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD2DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; I_GOURAUD2DTEXTUREPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion=0; NumScans=0; /* scan out the right edge */ polyScan = (I_GOURAUD2DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y,u,v; int deltaX,deltaI,deltaU,deltaV; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_i - vertexPtr[curVertex].i_i; int widthU = vertexPtr[nextVertex].i_u - vertexPtr[curVertex].i_u; int widthV = vertexPtr[nextVertex].i_v - vertexPtr[curVertex].i_v; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_i; u = vertexPtr[curVertex].i_u; v = vertexPtr[curVertex].i_v; for (y=vertexPtr[curVertex].i_y; yig2s_x2 = x>>16; x+=deltaX; polyScan->ig2s_c2 = i; i+=deltaI; polyScan->ig2s_u2 = u; u+=deltaU; polyScan->ig2s_v2 = v; v+=deltaV; polyScan->ig2s_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_GOURAUD2DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y,u,v; int deltaX,deltaI,deltaU,deltaV; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_i - vertexPtr[curVertex].i_i; int widthU = vertexPtr[nextVertex].i_u - vertexPtr[curVertex].i_u; int widthV = vertexPtr[nextVertex].i_v - vertexPtr[curVertex].i_v; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_i; u = vertexPtr[curVertex].i_u; v = vertexPtr[curVertex].i_v; for (y=vertexPtr[curVertex].i_y; yig2s_x1 = x>>16; x+=deltaX; polyScan->ig2s_c1 = i; i+=deltaI; polyScan->ig2s_u1 = u; u+=deltaU; polyScan->ig2s_v1 = v; v+=deltaV; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionPolyColour; I_GOURAUD2DTEXTUREPOLYGON_SCAN *polyScan; polyScan = (I_GOURAUD2DTEXTUREPOLYGON_SCAN*)ScanData; SCASM_Lighting = TextureLightingTable+colour; SCASM_ShadingTableSize = 256; while(NumScans) { int dx = polyScan->ig2s_x2 - polyScan->ig2s_x1; if (dx>0) { SCASM_Destination = ScreenBuffer+(polyScan->ig2s_y * BackBufferPitch) + polyScan->ig2s_x1; SCASM_ScanLength = dx; SCASM_DeltaI = (polyScan->ig2s_c2-polyScan->ig2s_c1)/dx; SCASM_StartI = polyScan->ig2s_c1; ScanDraw_GouraudScan(); } NumScans--; polyScan++; } } #endif } } #endif #if 0 void KDraw_Item_Gouraud3dTexturePolygon(int *itemptr) { POLYHEADER *pheader = (POLYHEADER *) itemptr; int TxIndex; IMAGEHEADER *ImageHdr; ItemColour = pheader->PolyColour; TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; /* Colour */ /* If MIP Mapping, calculate the scale */ if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { I_GOURAUD3DTEXTUREPOLYGON_PT *vector1; I_GOURAUD3DTEXTUREPOLYGON_PT *vector2; I_GOURAUD3DTEXTUREPOLYGON_PT *vector3; int mip1, mip2; int xyd, uvd; VECTOR2D s0, s1; VECTOR2D t0, t1; /* Screen and Texture Space Vectors */ /* Express the "uvd / xyd" ratio as a binary scale */ vector1 = (I_GOURAUD3DTEXTUREPOLYGON_PT *) &pheader->Poly1stPt; vector2 = &vector1[1]; vector3 = &vector1[2]; /* Vector 1 */ s0.vx = vector1->i_x; s0.vy = vector1->i_y; s1.vx = vector2->i_x; s1.vy = vector2->i_y; t0.vx = vector1->i_gtx3d_u / vector1->i_gtx3d_z; t0.vy = vector1->i_gtx3d_v / vector1->i_gtx3d_z; t1.vx = vector2->i_gtx3d_u / vector2->i_gtx3d_z; t1.vy = vector2->i_gtx3d_v / vector2->i_gtx3d_z; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip1 = FindShift32(uvd, xyd); /* Vector 2 */ s0.vx = vector2->i_x; s0.vy = vector2->i_y; s1.vx = vector3->i_x; s1.vy = vector3->i_y; t0.vx = t1.vx; t0.vy = t1.vy; t1.vx = vector3->i_gtx3d_u / vector3->i_gtx3d_z; t1.vy = vector3->i_gtx3d_v / vector3->i_gtx3d_z; xyd = FandVD_Distance_2d(&s0, &s1); uvd = FandVD_Distance_2d(&t0, &t1); mip2 = FindShift32(uvd, xyd); /* Choose the larger of the two */ if(pheader->PolyFlags & iflag_no_mip) { MIP_Index = 0; } else { #if UseMIPMax if(mip1 > mip2) MIP_Index = mip1; else MIP_Index = mip2; #endif #if UseMIPMin if(mip1 > mip2) MIP_Index = mip2; else MIP_Index = mip1; #endif #if UseMIPAvg MIP_Index = (mip1 + mip2) >> 1; #endif } /* Clamp "MIP_Index" */ #if MIP_INDEX_SUBTRACT MIP_Index -= MIP_INDEX_SUBTRACT; if(MIP_Index < 0) MIP_Index = 0; else if(MIP_Index > 6) MIP_Index = 6; #else if(MIP_Index > 6) MIP_Index = 6; #endif } { int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; float MIP_Divide = 1<Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_gtx3d_u /= MIP_Divide; vertexPtr->i_gtx3d_v /= MIP_Divide; } vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } if(ScreenDescriptorBlock.SDB_Flags & SDB_Flag_MIP && ImageHdr->ImageFlags & ih_flag_mip) { vertexPtr->i_gtx3d_u /= MIP_Divide; vertexPtr->i_gtx3d_v /= MIP_Divide; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_GOURAUD3DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD3DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; I_GOURAUD3DTEXTUREPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion=0; NumScans=0; /* scan out the right edge */ polyScan = (I_GOURAUD3DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y; float u,v,z; int deltaX,deltaI; float deltaU,deltaV,deltaZ; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_gtx3d_i - vertexPtr[curVertex].i_gtx3d_i; float widthU = vertexPtr[nextVertex].i_gtx3d_u - vertexPtr[curVertex].i_gtx3d_u; float widthV = vertexPtr[nextVertex].i_gtx3d_v - vertexPtr[curVertex].i_gtx3d_v; float widthZ = vertexPtr[nextVertex].i_gtx3d_z - vertexPtr[curVertex].i_gtx3d_z; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; deltaZ = widthZ/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_gtx3d_i; u = vertexPtr[curVertex].i_gtx3d_u; v = vertexPtr[curVertex].i_gtx3d_v; z = vertexPtr[curVertex].i_gtx3d_z; for (y=vertexPtr[curVertex].i_y; yig3s_x2 = x>>16; x+=deltaX; polyScan->ig3s_c2 = i; i+=deltaI; polyScan->ig3s_u2 = u; u+=deltaU; polyScan->ig3s_v2 = v; v+=deltaV; polyScan->ig3s_z2 = z; z+=deltaZ; polyScan->ig3s_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_GOURAUD3DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y; float u,v,z; int deltaX,deltaI; float deltaU,deltaV,deltaZ; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_gtx3d_i - vertexPtr[curVertex].i_gtx3d_i; float widthU = vertexPtr[nextVertex].i_gtx3d_u - vertexPtr[curVertex].i_gtx3d_u; float widthV = vertexPtr[nextVertex].i_gtx3d_v - vertexPtr[curVertex].i_gtx3d_v; float widthZ = vertexPtr[nextVertex].i_gtx3d_z - vertexPtr[curVertex].i_gtx3d_z; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; deltaZ = widthZ/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_gtx3d_i; u = vertexPtr[curVertex].i_gtx3d_u; v = vertexPtr[curVertex].i_gtx3d_v; z = vertexPtr[curVertex].i_gtx3d_z; for (y=vertexPtr[curVertex].i_y; yig3s_x1 = x>>16; x+=deltaX; polyScan->ig3s_c1 = i; i+=deltaI; polyScan->ig3s_u1 = u; u+=deltaU; polyScan->ig3s_v1 = v; v+=deltaV; polyScan->ig3s_z1 = z; z+=deltaZ; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionPolyColour; TxIndex = ItemColour & ClrTxDefn; ImageHdr = ImageHeaderPtrs[TxIndex]; { int minYVertex = 0; int maxYVertex = 0; int maxVertexNum = 0; { I_GOURAUD3DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD3DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; int minY = vertexPtr->i_y; int maxY = vertexPtr->i_y; vertexPtr++; do { maxVertexNum++; if (minY > vertexPtr->i_y) { minY = vertexPtr->i_y; minYVertex = maxVertexNum; } else if (maxY < vertexPtr->i_y) { maxY = vertexPtr->i_y; maxYVertex = maxVertexNum; } vertexPtr++; } while(vertexPtr->i_x != Term); } /* Initialise the Scan Data Buffer */ { I_GOURAUD3DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD3DTEXTUREPOLYGON_PT*)&pheader->Poly1stPt; I_GOURAUD3DTEXTUREPOLYGON_SCAN *polyScan; int curVertex; int SecondOpinion=0; NumScans=0; /* scan out the right edge */ polyScan = (I_GOURAUD3DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex-1; if (nextVertex<0) nextVertex = maxVertexNum; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y; float u,v,z; int deltaX,deltaI; float deltaU,deltaV,deltaZ; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_gtx3d_i - vertexPtr[curVertex].i_gtx3d_i; float widthU = vertexPtr[nextVertex].i_gtx3d_u - vertexPtr[curVertex].i_gtx3d_u; float widthV = vertexPtr[nextVertex].i_gtx3d_v - vertexPtr[curVertex].i_gtx3d_v; float widthZ = vertexPtr[nextVertex].i_gtx3d_z - vertexPtr[curVertex].i_gtx3d_z; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; deltaZ = widthZ/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_gtx3d_i; u = vertexPtr[curVertex].i_gtx3d_u; v = vertexPtr[curVertex].i_gtx3d_v; z = vertexPtr[curVertex].i_gtx3d_z; for (y=vertexPtr[curVertex].i_y; yig3s_x2 = x>>16; x+=deltaX; polyScan->ig3s_c2 = i; i+=deltaI; polyScan->ig3s_u2 = u; u+=deltaU; polyScan->ig3s_v2 = v; v+=deltaV; polyScan->ig3s_z2 = z; z+=deltaZ; polyScan->ig3s_y = y; NumScans++; polyScan++; } } curVertex--; if (curVertex<0) curVertex = maxVertexNum; } while(curVertex!=maxYVertex); /* scan out the left edge */ polyScan = (I_GOURAUD3DTEXTUREPOLYGON_SCAN*)ScanData; curVertex = minYVertex; do { int height; int nextVertex = curVertex+1; if (nextVertex>maxVertexNum) nextVertex = 0; height = vertexPtr[nextVertex].i_y - vertexPtr[curVertex].i_y; if (height!=0) { int i,x,y; float u,v,z; int deltaX,deltaI; float deltaU,deltaV,deltaZ; int width = vertexPtr[nextVertex].i_x - vertexPtr[curVertex].i_x; int contrast = vertexPtr[nextVertex].i_gtx3d_i - vertexPtr[curVertex].i_gtx3d_i; float widthU = vertexPtr[nextVertex].i_gtx3d_u - vertexPtr[curVertex].i_gtx3d_u; float widthV = vertexPtr[nextVertex].i_gtx3d_v - vertexPtr[curVertex].i_gtx3d_v; float widthZ = vertexPtr[nextVertex].i_gtx3d_z - vertexPtr[curVertex].i_gtx3d_z; deltaX = (width<<16)/height; deltaI = contrast/height; deltaU = widthU/height; deltaV = widthV/height; deltaZ = widthZ/height; x = vertexPtr[curVertex].i_x<<16; i = vertexPtr[curVertex].i_gtx3d_i; u = vertexPtr[curVertex].i_gtx3d_u; v = vertexPtr[curVertex].i_gtx3d_v; z = vertexPtr[curVertex].i_gtx3d_z; for (y=vertexPtr[curVertex].i_y; yig3s_x1 = x>>16; x+=deltaX; polyScan->ig3s_c1 = i; i+=deltaI; polyScan->ig3s_u1 = u; u+=deltaU; polyScan->ig3s_v1 = v; v+=deltaV; polyScan->ig3s_z1 = z; z+=deltaZ; SecondOpinion++; polyScan++; } } curVertex++; if (curVertex>maxVertexNum) curVertex = 0; } while(curVertex!=maxYVertex); if (SecondOpinionImageWidth; SCASM_Bitmap = ImageHdr->ImagePtr; GLOBALASSERT(SCASM_Bitmap); } } SCASM_Lighting = TextureLightingTable; sptr = (I_GOURAUD3DTEXTUREPOLYGON_SCAN *) ScanData; do { int length = sptr->ig3s_x2 - sptr->ig3s_x1; int dx=length; if (dx>0 && !(sptr->ig3s_y & KRenderDrawMode) ) { float deltaZ; float endZ; float endU,endV; float deltaU,deltaV; { int StartI = sptr->ig3s_c1; SCASM_DeltaI = (sptr->ig3s_c2 - StartI)/dx; SCASM_StartI = StartI; } SCASM_Destination = ScreenBuffer + (sptr->ig3s_y * BackBufferPitch) + sptr->ig3s_x1; SCASM_ScanLength = PERS_STEP; { float oneOverdx = 1.0/dx; endZ = sptr->ig3s_z1; deltaZ = (sptr->ig3s_z2 - endZ)*oneOverdx; endU = sptr->ig3s_u1; deltaU = (sptr->ig3s_u2 - endU)*oneOverdx; endV = sptr->ig3s_v1; deltaV = (sptr->ig3s_v2 - endV)*oneOverdx; } { float z = 65536.0/endZ; SCASM_StartU = endU*z; SCASM_StartV = endV*z; } while(dx>PERS_STEP) { /* subdivide! */ int u,v; dx -= PERS_STEP; endZ += PERS_STEP*deltaZ; endU += PERS_STEP*deltaU; endV += PERS_STEP*deltaV; { float z = 65536.0/endZ; u = endU*z; v = endV*z; } SCASM_DeltaU = (u-SCASM_StartU)/PERS_STEP; SCASM_DeltaV = (v-SCASM_StartV)/PERS_STEP; /* draw PERS_STEP pixels */ ScanDraw2D_Gouraud(); SCASM_StartU = u; SCASM_StartV = v; SCASM_Destination +=PERS_STEP; SCASM_StartI += PERS_STEP*SCASM_DeltaI; } if (dx>0) { int u,v; SCASM_ScanLength = dx; { float z = 65536.0/sptr->ig3s_z2; u = sptr->ig3s_u2*z; v = sptr->ig3s_v2*z; } SCASM_DeltaU = (u-SCASM_StartU)/dx; SCASM_DeltaV = (v-SCASM_StartV)/dx; /* draw 8 pixels */ ScanDraw2D_Gouraud(); } } sptr++; y--; } while(y); } } #endif #if 0 void MakeInverseLightingTable(void) { int lookingForColour; for(lookingForColour=1; lookingForColour<=255; lookingForColour++) { int exit =0; int table; for (table=128; (table>0 && (!exit)); table--) { int entry; for(entry=1; (entry<=255 && (!exit)); entry++) { if(lookingForColour == *(TextureLightingTable + 256*(table) + entry)) { LighterTable[lookingForColour] = entry; exit=1; } } } if (exit==0) LighterTable[lookingForColour] = 255; } } #endif struct ColourVector { VECTORCH Direction; int Magnitude; }; struct ColourVector ColourTable[256]; void MakeInverseLightingTable(void) { extern unsigned char TestPalette[]; unsigned char *palPtr = TestPalette; int i; for(i = 0; i < 256; i++) { VECTORCH colour; int mag; colour.vx = *palPtr++; colour.vy = *palPtr++; colour.vz = *palPtr++; mag = Magnitude(&colour); if (mag!=0) { colour.vx = (colour.vx*32)/mag; colour.vy = (colour.vy*32)/mag; colour.vz = (colour.vz*32)/mag; } ColourTable[i].Magnitude = mag; ColourTable[i].Direction = colour; } for(i = 0; i < 256; i++) { int entry; int brightest=0; for(entry = 0; entry < 256; entry++) { VECTORCH v1 = ColourTable[i].Direction; VECTORCH v2 = ColourTable[entry].Direction; if ((v1.vx == v2.vx) &&(v1.vy == v2.vy) &&(v1.vz == v2.vz) &&(ColourTable[i].Magnitude < ColourTable[entry].Magnitude) &&(ColourTable[brightest].Magnitude > ColourTable[entry].Magnitude ||(!brightest))) brightest = entry; } if (brightest==0) { for(entry = 0; entry < 256; entry++) { VECTORCH v1 = ColourTable[i].Direction; VECTORCH v2 = ColourTable[entry].Direction; if ((v1.vx>>2 == v2.vx>>1) &&(v1.vy>>2 == v2.vy>>1) &&(v1.vz>>2 == v2.vz>>1) &&(ColourTable[i].Magnitude < ColourTable[entry].Magnitude) &&(ColourTable[brightest].Magnitude > ColourTable[entry].Magnitude ||(!brightest))) brightest = entry; } } if (brightest==0) { for(entry = 0; entry < 256; entry++) { VECTORCH v1 = ColourTable[i].Direction; VECTORCH v2 = ColourTable[entry].Direction; if ((v1.vx>>2 == v2.vx>>2) &&(v1.vy>>2 == v2.vy>>2) &&(v1.vz>>2 == v2.vz>>2) &&(ColourTable[i].Magnitude < ColourTable[entry].Magnitude) &&(ColourTable[brightest].Magnitude > ColourTable[entry].Magnitude ||(!brightest))) brightest = entry; } } #if 0 if (brightest==0) { for(entry = 0; entry < 256; entry++) { VECTORCH v1 = ColourTable[i].Direction; VECTORCH v2 = ColourTable[entry].Direction; if ((v1.vx>>3 == v2.vx>>3) &&(v1.vy>>3 == v2.vy>>3) &&(v1.vz>>3 == v2.vz>>3) &&(ColourTable[i].Magnitude < ColourTable[entry].Magnitude) &&(ColourTable[brightest].Magnitude > ColourTable[entry].Magnitude ||(!brightest))) brightest = entry; } } #endif if (brightest==0) brightest = i; LighterTable[i] = brightest; } } void DrawPaletteScreen(void) { int sortedColours[256]; { extern unsigned char TestPalette[]; unsigned char *palPtr = TestPalette; int i; for(i = 0; i < 256; i++) { VECTORCH colour; int mag; colour.vx = *palPtr++; colour.vy = *palPtr++; colour.vz = *palPtr++; mag = Magnitude(&colour); if (mag!=0) { colour.vx = (colour.vx*7)/mag; colour.vy = (colour.vy*7)/mag; colour.vz = (colour.vz*7)/mag; } ColourTable[i].Magnitude = mag; ColourTable[i].Direction = colour; } for(i = 0; i<256; i++) { int e; int maxKey=-1; int selectedEntry=0; for (e=0; e<256; e++) { int key = ColourTable[e].Direction.vx + ColourTable[e].Direction.vy*64+ColourTable[e].Direction.vz*64*64; if (key>maxKey) { maxKey = key; selectedEntry = e; } else if (key==maxKey) { if (ColourTable[e].MagnitudemaxKey) { maxKey = key; selectedEntry = e; } else if (key==maxKey) { int key2 = ColourTable[e].Direction.vx + ColourTable[e].Direction.vy*64+ColourTable[e].Direction.vz*64*64; int key3 = ColourTable[selectedEntry].Direction.vx + ColourTable[selectedEntry].Direction.vy*64 + ColourTable[selectedEntry].Direction.vz*64*64; if (key2>16; } } ChangePalette(TestPalette2); } else { d3d_light_ctrl.ctrl = LCCM_CONSTCOLOUR; d3d_light_ctrl.r = fadeLevel; d3d_light_ctrl.g = fadeLevel; d3d_light_ctrl.b = fadeLevel; } } void FadeBetweenPalettes(unsigned char *palPtr, int fadeLevel) { extern unsigned char TestPalette[]; unsigned char TestPalette3[768]; { int x; for (x=0; x<768; x++) { TestPalette3[x] = ( (unsigned int)TestPalette[x]*fadeLevel + (unsigned int)(palPtr[x])*(65536-fadeLevel) )>>16; } } ChangePalette(TestPalette3); } void FadePaletteToWhite(unsigned char *palPtr,int fadeLevel) { unsigned char TestPalette3[768]; { int x; for (x=0; x<768; x++) { TestPalette3[x] = ( (unsigned int)(palPtr[x])*fadeLevel + 63*(65536-fadeLevel) )>>16; } } ChangePalette(TestPalette3); } void BlankScreen(void) { extern int ScanDrawMode; if (ScanDrawDirectDraw==ScanDrawMode) { extern unsigned char *ScreenBuffer; extern unsigned char TestPalette[]; unsigned int *screenPtr; int i; screenPtr = (unsigned int *)ScreenBuffer; i = ScreenDescriptorBlock.SDB_Width * ScreenDescriptorBlock.SDB_Height /4; do { *screenPtr++=0; } while(--i); } else { ColourFillBackBuffer(0); } // FlipBuffers(); } void GenerateReciprocalTable(void) { int i=320; do { ReciprocalTable[i] = 65536/i; } while(--i); } #if 0 #define NO_OF_STARS 500 typedef struct { VECTORCH Position; int Colour; } STARDESC; static STARDESC StarArray[NO_OF_STARS]; #endif void CreateStarArray(void) { #if 0 int i; extern int sine[],cosine[]; for(i=0; iVDB_Mat)); /* is star within alien (wide) view frustrum ? */ if((-rotatedPosition.vx <= rotatedPosition.vz*2) &&(rotatedPosition.vx <= rotatedPosition.vz*2) &&(-rotatedPosition.vy*2 <= rotatedPosition.vz*3) &&(rotatedPosition.vy*2 <= rotatedPosition.vz*3)) { /* project into screen space */ int y = (rotatedPosition.vy*(Global_VDB_Ptr->VDB_ProjY))/rotatedPosition.vz+Global_VDB_Ptr->VDB_CentreY; int x = (rotatedPosition.vx*(Global_VDB_Ptr->VDB_ProjX))/rotatedPosition.vz+Global_VDB_Ptr->VDB_CentreX; /* draw pixel of required bit depth */ if (ScanDrawMode == ScanDrawDirectDraw) { /* 8 bit mode */ *(ScreenBuffer + x + y*BackBufferPitch) = StarArray[i].Colour&255; } else { /* 16 bit mode */ *(unsigned short*)(ScreenBuffer + (x*2 + y*BackBufferPitch)) = StarArray[i].Colour; } } } } else /* normal frustrum */ { for(i=0; iVDB_Mat)); /* is star within normal view frustrum ? */ if((-rotatedPosition.vx <= rotatedPosition.vz) &&(rotatedPosition.vx <= rotatedPosition.vz) &&(-rotatedPosition.vy*4 <= rotatedPosition.vz*3) &&(rotatedPosition.vy*4 <= rotatedPosition.vz*3)) { /* project into screen space */ int y = (rotatedPosition.vy*(Global_VDB_Ptr->VDB_ProjY))/rotatedPosition.vz+Global_VDB_Ptr->VDB_CentreY; int x = (rotatedPosition.vx*(Global_VDB_Ptr->VDB_ProjX))/rotatedPosition.vz+Global_VDB_Ptr->VDB_CentreX; /* draw pixel of required bit depth */ if (ScanDrawMode == ScanDrawDirectDraw) { /* 8 bit mode */ *(ScreenBuffer + x + y*BackBufferPitch) = StarArray[i].Colour&255; } else { /* 16 bit mode */ *(unsigned short*)(ScreenBuffer + (x*2 + y*BackBufferPitch)) = StarArray[i].Colour; } } } } UnlockSurface(); #endif }