summaryrefslogtreecommitdiff
path: root/3dc/win95/Krender.c
diff options
context:
space:
mode:
authorRebellion Developments <rebellion@nomail>2000-03-16 11:25:00 +0100
committerPatryk Obara <dreamer.tan@gmail.com>2019-08-19 05:45:17 +0200
commit218ca90543758a20ac326e444ca0643174ca7384 (patch)
tree16bfe3e5307f9f515489000f28728224291a0e3b /3dc/win95/Krender.c
Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
Diffstat (limited to '3dc/win95/Krender.c')
-rw-r--r--3dc/win95/Krender.c2830
1 files changed, 2830 insertions, 0 deletions
diff --git a/3dc/win95/Krender.c b/3dc/win95/Krender.c
new file mode 100644
index 0000000..a52c1d5
--- /dev/null
+++ b/3dc/win95/Krender.c
@@ -0,0 +1,2830 @@
+/*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<<MIP_Index)-1) ++SCASM_TextureDeltaScan;
+ #endif
+
+
+ }
+ else
+ {
+ SCASM_TextureDeltaScan = ImageHdr->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<<MIP_Index)-1) ++SCASM_TextureDeltaScan;
+ #endif
+
+ }
+ else
+ {
+ SCASM_TextureDeltaScan = ImageHdr->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<<MIP_Index)-1) ++SCASM_TextureDeltaScan;
+ #endif
+ }
+ else
+ {
+ SCASM_TextureDeltaScan = ImageHdr->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<<MIP_Index)-1) ++SCASM_TextureDeltaScan;
+ #endif
+ }
+ else
+ {
+ SCASM_TextureDeltaScan = ImageHdr->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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->igs_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->igs_x1 = x>>16;
+ x+=deltaX;
+ polyScan->igs_c1 = i;
+ i+=deltaI;
+
+ SecondOpinion++;
+ polyScan++;
+ }
+ }
+ curVertex++;
+ if (curVertex>maxVertexNum) curVertex = 0;
+
+ }
+ while(curVertex!=maxYVertex);
+
+ if (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+
+ }
+
+ //draw 'em
+
+ {
+ unsigned char colour= pheader->PolyColour;
+ 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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->igs_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->igs_x1 = x>>16;
+ x+=deltaX;
+ polyScan->igs_c1 = i;
+ i+=deltaI;
+
+ SecondOpinion++;
+ polyScan++;
+ }
+ }
+ curVertex++;
+ if (curVertex>maxVertexNum) curVertex = 0;
+
+ }
+ while(curVertex!=maxYVertex);
+
+ if (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+
+ }
+
+ //draw 'em
+
+ {
+ unsigned char colour= pheader->PolyColour;
+ 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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->i2s_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->i2s_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 (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+ }
+
+ //draw 'em
+ KR_ScanDraw_Item_2dTexturePolygon_VideoModeType_8(itemptr);
+
+ }
+}
+void KDraw_Item_Gouraud2dTexturePolygon(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_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig2s_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig2s_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 (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+ }
+ //draw 'em
+ KR_ScanDraw_Item_Gouraud2dTexturePolygon_VideoModeType_8(itemptr);
+
+ #if 0
+ {
+ unsigned char colour= pheader->PolyColour;
+ 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<<MIP_Index;
+
+ {
+ I_GOURAUD3DTEXTUREPOLYGON_PT *vertexPtr = (I_GOURAUD3DTEXTUREPOLYGON_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_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig3s_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig3s_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 (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+ }
+
+ //draw 'em
+ KR_ScanDraw_Item_Gouraud3dTexturePolygon_Linear_S_VideoModeType_8(itemptr);
+ }
+}
+#else
+void KDraw_Item_Gouraud3dTexturePolygon(int *itemptr)
+{
+ POLYHEADER *pheader = (POLYHEADER *) itemptr;
+ int TxIndex;
+ IMAGEHEADER *ImageHdr;
+ ItemColour = pheader->PolyColour;
+
+ 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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig3s_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; y<vertexPtr[nextVertex].i_y; y++)
+ {
+ polyScan->ig3s_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 (SecondOpinion<NumScans)
+ {
+ textprint("WARNING: Rasterization error\n");
+ NumScans = SecondOpinion;
+// LOCALASSERT(0);
+ return;
+ }
+ }
+
+ //draw 'em
+ Draw_Gouraud3dTexture_Spans(itemptr);
+ }
+}
+
+#define PERS_STEP 16
+void Draw_Gouraud3dTexture_Spans(int *itemptr)
+{
+ I_GOURAUD3DTEXTUREPOLYGON_SCAN *sptr;
+
+ if(NumScans)
+ {
+ int y = NumScans;
+ /* Get the Image Data required for the Draw */
+ {
+ IMAGEHEADER *ImageHdr;
+ {
+ int TxIndex = ItemColour & ClrTxDefn;
+ ImageHdr = ImageHeaderPtrs[TxIndex];
+ }
+ {
+ SCASM_TextureDeltaScan = ImageHdr->ImageWidth;
+ 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].Magnitude<ColourTable[selectedEntry].Magnitude)
+ selectedEntry = e;
+ }
+ }
+
+ sortedColours[i] = selectedEntry;
+ ColourTable[selectedEntry].Direction.vx=-1;
+ ColourTable[selectedEntry].Direction.vy=-1;
+ ColourTable[selectedEntry].Direction.vz=-1;
+ }
+
+ }
+ {
+ char colour = 0;
+ int *bufferPtr = (int*)ScreenBuffer;
+ int i,x,y;
+
+ for (i=0; i<=12; i++)
+ {
+ for (y=0; y<=6; y++)
+ {
+ for (x=0; x<=19; x++)
+ {
+ unsigned int c=colour+x;
+
+ if (c<256)
+ {
+ c = sortedColours[c];
+ c = c + (c<<8) + (c<<16) +(c<<24);
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ }
+ else
+ {
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ }
+ }
+ }
+ colour+=20;
+ }
+ }
+
+ #if 0
+ {
+ 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*63)/mag;
+ colour.vy = (colour.vy*63)/mag;
+ colour.vz = (colour.vz*63)/mag;
+ }
+
+ ColourTable[i].Direction = colour;
+ ColourTable[i].Magnitude = mag;
+ }
+
+ for(i = 0; i<256; i++)
+ {
+ int e;
+ int maxKey=-1;
+ int selectedEntry=0;
+
+ for (e=0; e<256; e++)
+ {
+ int key = ColourTable[e].Magnitude;
+
+ if (key>maxKey)
+ {
+ 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<key3)
+ selectedEntry=e;
+ }
+
+ }
+
+ sortedColours[i] = selectedEntry;
+ ColourTable[selectedEntry].Magnitude=-1;
+ }
+
+ }
+ {
+ char colour = 0;
+ int *bufferPtr = (int*)(ScreenBuffer+32000);
+ int i,x,y;
+
+ for (i=0; i<=12; i++)
+ {
+ for (y=0; y<=6; y++)
+ {
+ for (x=0; x<=19; x++)
+ {
+ unsigned int c=colour+x;
+
+ if (c<256)
+ {
+ c = sortedColours[c];
+ c = c + (c<<8) + (c<<16) +(c<<24);
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ }
+ else
+ {
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ }
+ }
+ }
+ colour+=20;
+ }
+ }
+ #else
+ {
+ extern unsigned char TestPalette[];
+ char colour = 0;
+ int *bufferPtr = (int*)(ScreenBuffer+32000);
+ int i,x,y;
+
+ for (i=0; i<=12; i++)
+ {
+ for (y=0; y<=6; y++)
+ {
+ for (x=0; x<=19; x++)
+ {
+ unsigned int c=colour+x;
+
+ if (c<256)
+ {
+ c = c + (c<<8) + (c<<16) +(c<<24);
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ *bufferPtr++=c;
+ }
+ else
+ {
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ bufferPtr++;
+ }
+ }
+ }
+ colour+=20;
+ }
+ }
+ #endif
+}
+
+void OddLineScreenCopy(unsigned int *source,unsigned int *dest)
+{
+ int lines = 240;
+
+ do
+ {
+ int i = 640/4;
+
+ dest += 640/4;
+ source += 640/4;
+
+ do
+ {
+ *dest++=*source++;
+ }
+ while(--i);
+ }
+ while(--lines);
+
+}
+
+
+
+/*KJL*****************************************************
+* Palette fading; a value of 65536 corresponds to normal *
+* palette, 0 is completely black. *
+*****************************************************KJL*/
+void SetPaletteFadeLevel(int fadeLevel)
+{
+ extern int ScanDrawMode;
+ if(ScanDrawDirectDraw == ScanDrawMode)
+ {
+ extern unsigned char TestPalette[];
+ extern unsigned char TestPalette2[];
+ {
+ int x;
+ for (x=0; x<768; x++)
+ {
+ TestPalette2[x] = ((unsigned int)TestPalette[x]*fadeLevel)>>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; i<NO_OF_STARS; i++)
+ {
+ int phi = FastRandom()&4095;
+ int theta = FastRandom()&4095;
+
+ StarArray[i].Position.vx = MUL_FIXED(GetCos(phi),GetSin(theta));
+ StarArray[i].Position.vy = MUL_FIXED(GetSin(phi),GetSin(theta));
+ StarArray[i].Position.vz = GetCos(theta);
+ StarArray[i].Colour = FastRandom()&32767;
+ }
+ #endif
+}
+
+/* KJL 12:10:36 9/30/97 - starfield, currently implemented for 8 & 16 bit displays */
+void DrawStarfilledSky(void)
+{
+ #if 0
+ int i;
+ extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
+ extern int ScanDrawMode;
+
+ /* blank the screen */
+ ColourFillBackBuffer(0);
+
+ LockSurfaceAndGetBufferPointer();
+
+ if(AvP.PlayerType==I_Alien) /* wide frustrum */
+ {
+ for(i=0; i<NO_OF_STARS; i++)
+ {
+ VECTORCH rotatedPosition = StarArray[i].Position;
+
+ /* rotate star into view space */
+ RotateVector(&rotatedPosition,&(Global_VDB_Ptr->VDB_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; i<NO_OF_STARS; i++)
+ {
+ VECTORCH rotatedPosition = StarArray[i].Position;
+
+ /* rotate star into view space */
+ RotateVector(&rotatedPosition,&(Global_VDB_Ptr->VDB_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
+} \ No newline at end of file