JurassicParkTrespasser/jp2_pc/Source/Lib/Renderer/Primitives/DrawTriangleEx.cpp

9063 lines
269 KiB
C++
Raw Permalink Normal View History

2018-01-01 22:07:24 +00:00
/***********************************************************************************************
*
* Copyright <EFBFBD> DreamWorks Interactive. 1996
*
* Contents:
* Functions that impelment parts of DrawTriangle in assembly.
*
* Bugs:
*
* Notes:
* Some of these may be faster inlined, but in general it's not worthwhile.
*
* To do:
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/DrawTriangleEx.cpp $
*
* 30 10/01/98 12:37a Asouth
* Added config to ensure proper configuration
*
* 29 9/03/98 1:52p Asouth
* removed 'short' from a couple of long jumps
*
* 28 98.08.26 6:55p Mmouni
* Removed gouraud gradient clamping code for degenerate edges becuase polygons with degenerate
* edges are now drawn by triangulation.
*
* 27 98.08.18 11:37p Mmouni
* Added special case code to prevent gouraud primitive from walking outside texture.
*
* 26 98.08.13 4:26p Mmouni
* Changes for VC++ 5.0sp3 compatibility.
*
* 25 98.07.21 8:22p Mmouni
* Added 3DX routine to get the perspective subdivision without using an x86 code.
*
* 24 98.07.17 6:36p Mmouni
* Added new alpha texture primitive.
*
* 23 98.06.17 6:45p Mmouni
* Removed pixel counting (it was broken for planar N-sided polygons)
*
* 22 98.06.12 3:36p Mmouni
* Added optimized versions of planar polygon gradient routines.
*
* 21 3/25/98 11:55a Kmckis
* Added missing comma.
*
* 20 98.03.24 8:17p Mmouni
* Made changes to support alternate perspective correction settings.
*
* 19 3/05/98 3:37p Pkeet
* Added the 'bCAT_PIXEL_STAT' macro switch.
*
* 18 2/26/98 2:54p Mmouni
* DrawTriangle routines now only do femms at the start and end.
*
* 17 2/17/98 11:10p Mmouni
* Fixed problem with K6-3D GenericInitTriangleDataGour() routine.
*
* 16 98.02.17 10:20p Mmouni
* Gouraud shaded gradient is now zeroed if gradients from any two subtriangles have different
* signs.
*
* 15 98.01.22 3:14p Mmouni
* Removed bump-map depth conditional compilation.
*
* 14 1/19/98 7:34p Pkeet
* Added support for 16 bit bumpmaps.
*
* 13 98.01.14 9:08p Mmouni
* Made changes for K6 3D polygon setup optimizations.
*
* 12 97.12.17 7:05p Mmouni
* Replaced fdivs with reciprocal lookups.
*
* 11 97.12.11 7:10p Mmouni
* Fixed error in edge setup.
*
* 10 97/12/08 17:44 Speter
* Updated offsets for new non-virtual CRenderPoly.
*
* 9 97.11.25 9:23p Mmouni
* Fixed error in bInitTriangleData for terrain fog primitives.
*
* 8 97.11.25 7:02p Mmouni
* Finished Pentium/Pentium Pro triangle setup optimization.
*
* 7 97.11.14 11:59p Mmouni
* Added specialized versions of InitializePolygonData for terrain texture that normalize the
* texture co-ordinates for tiled textures.
*
* 6 10/30/97 3:41p Mlange
* Fixed broken build.
*
* 5 97.10.30 1:41p Mmouni
* Added Asserts for assumptions made by assembly routines.
*
*
* 4 97.10.27 1:27p Mmouni
* Made changes to support the K6-3D.
*
* 3 97.10.16 2:15p Mmouni
* Added in some missing debug version only setup.
*
* 2 97.10.15 7:39p Mmouni
* Added more optimized stuff.
*
* 1 10/13/97 7:11p Mmouni
*
**********************************************************************************************/
// Includes.
#include "Common.hpp"
#include "Config.hpp"
#include "DrawTriangle.hpp"
#include "AsmSupport.hpp"
// Make sure we have the best optimization.
#pragma optimize("tag", on)
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
// Disable useless warning about no EMMS instruction in a function.
#pragma warning(disable: 4799)
// Stupid assembler complains about the size of an element of a struct,
// but assembles the instruction with the correct size anyway.
#pragma warning(disable: 4410)
#endif // (TARGET_PROCESSOR == PROCESSOR_K6_3D)
// Floating point constatnts.
const float fONE = 1.0f;
const float fTWO = 2.0f;
const float fPOINT_ZERO_ONE = 0.01f;
const float fRECIP_POINT_ZERO_ONE = 1.0f / 0.01f;
const float fSIXTEEN = 16.0f;
const float fNegativeFifty = -50.0f;
// Magic numbers for floating point conversions.
const double dFloatToInt = 6.755399441055744E15;
const double dFloatToFixed16 = 103079215104.0;
const double dFloatToFixed32 = 1572864.0;
// Temps.
static double d_temp_a;
static double d_temp_b;
//
// Class members we can't get to using normal means.
//
#define CRenderPolygon_paprvPolyVertices_uLen 0
#define CRenderPolygon_paprvPolyVertices_atArray 4
//*****************************************************************************************
//
// Generic functions and macros that implement the funcionality of the routines.
//
//*****************************************************************************************
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
// Packed constants.
const float pfFixed16Scale[2] = { 65536.0f, 65536.0f };
const int pf_abs_mask[2] = { 0x7fffffff, 0x7fffffff };
const int64 qFpSignBits = 0x8000000080000000;
const float fInverseTwoToTheSixteenth = 1.0f / 65536.0f;
//*****************************************************************************************
//
inline void GenericInitializePolygonData(CRenderPolygon *rpoly)
//
// Scanline data initialization for un-shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
pfmul (m0,m1) // Scaled texture co-ordinates.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
pf2id (m4,m4) // Truncate to integer.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfmul (m0,m3) // Multiply by screen z.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
pfmul (m0,m3) // Multiply by screen z.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataFlat(CRenderPolygon *rpoly)
//
// Scanline data initialization for flat shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = iPosFloatCast(rpoly->cvFace);
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = 0;
if (rpoly->ptexTexture && rpoly->ptexTexture->ppcePalClut && rpoly->ptexTexture->ppcePalClut->pclutClut)
{
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
Assert(iBaseIntensity < rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues);
}
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
pfmul (m0,m1) // Scaled texture co-ordinates.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
pf2id (m4,m4) // Truncate to integer.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfmul (m0,m3) // Multiply by screen z.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
pfmul (m0,m3) // Multiply by screen z.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataGour(CRenderPolygon *rpoly)
//
// Scanline data initialization for gouraud shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
pfmul (m0,m1) // Scaled texture co-ordinates.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
pf2id (m4,m4) // Truncate to integer.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfmul (m0,m3) // Multiply by screen z.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
pfmul (m0,m3) // Multiply by screen z.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataBump(CRenderPolygon *rpoly)
//
// Scanline data initialization for bump shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapBump::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
pfmul (m0,m1) // Scaled texture co-ordinates.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
pf2id (m4,m4) // Truncate to integer.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfmul (m0,m3) // Multiply by screen z.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm3,[eax]SRenderCoord.v3Screen.tZ // Screen Z.
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
punpckldq mm3,mm3 // Duplicate Z across quadword.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
pfmul (m0,m3) // Multiply by screen z.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinear(CRenderPolygon *rpoly)
//
// Scanline data initialization for un-shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pfmul (m0,m1) // Scaled texture co-ordinates.
pf2id (m4,m4) // Truncate to integer.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearFlat(CRenderPolygon *rpoly)
//
// Scanline data initialization for flat shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = iPosFloatCast(rpoly->cvFace);
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = 0;
if (rpoly->ptexTexture && rpoly->ptexTexture->ppcePalClut && rpoly->ptexTexture->ppcePalClut->pclutClut)
{
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
Assert(iBaseIntensity < rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues);
}
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pfmul (m0,m1) // Scaled texture co-ordinates.
pf2id (m4,m4) // Truncate to integer.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearGour(CRenderPolygon *rpoly)
//
// Scanline data initialization for gouraud shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pfmul (m0,m1) // Scaled texture co-ordinates.
pf2id (m4,m4) // Truncate to integer.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearBump(CRenderPolygon *rpoly)
//
// Scanline data initialization for bump shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
qUVMasks = ((uint64)pras_texture->u4HeightTileMask << 48) |
((uint64)pras_texture->u4WidthTileMask << 32) |
((uint64)pras_texture->u4HeightTileMask << 16) |
((uint64)pras_texture->u4WidthTileMask);
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapBump::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
femms
mov eax,[pras_texture] // Pointer to texture.
mov ecx,[rpoly] // Pointer to polygon.
lea edi,[arvRasterVertices] // Destination vertices.
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
movq mm1,[eax]CRasterBase.fWidth // fWidth,fHeight
movq [cvMaxCoords],mm1 // fTexWidth,Height = pras_texture->fWidth,Height
mov ebx,[bClampUV] // Clamp flag.
test ebx,ebx
jz VTXLOOP2
movq mm2,[pfTexEdgeTolerance] // fTexEdgeTolerance,fTexEdgeTolerance
//
// Copy vertices & scale texture values with clamping.
//
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pfmul (m0,m1) // Scaled texture co-ordinates.
pf2id (m4,m4) // Truncate to integer.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
pfadd (m0,m2) // Add edge tolerance to tX,tY.
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
//
// Copy vertices & scale texture values, no clamping.
//
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
movd mm4,[eax]SRenderCoord.v3Screen.tY // Screen Y.
movq mm0,[eax]SRenderVertex.tcTex.tX // tX,tY
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
pf2id (m4,m4) // Truncate to integer.
pfmul (m0,m1) // Scaled texture co-ordinates.
movd [edi]SRenderCoord.iYScr,mm4 // Store truncated value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
movq [edi]SRenderVertex.tcTex,mm0 // Store texture co-ordinates.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
//femms
}
}
//*****************************************************************************************
//
template <class aCEdge> void GenericInitializeEdge
(
aCEdge &edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Sets up a polygon edge.
//
//**************************************
{
typedef aCEdge::TScanline aScanline;
int i4temp[2];
float f_dy;
__asm
{
//femms
mov esi,[prv_from] // From vertex.
mov ebx,1
mov edi,[prv_to] // To vertex.
mov [i4temp+4],ebx // Put one in temp+4
mov eax,[esi]SRenderCoord.iYScr // Integer y.
inc eax // iy + 1
mov [i4temp],eax // Save in temp+0.
movd mm1,[edi]SRenderCoord.v3Screen.tY // prv_to->v3Screen.tY
movd mm2,[esi]SRenderCoord.v3Screen.tY // prv_from->v3Screen.tY
movq mm0,[i4temp] // 1 | prv_from->iYScr+1
mov edx,[edge] // Load edge poniter.
pfsub (m1,m2) // mm1 = prv_to->v3Screen.tY - prv_from->v3Screen.tY
pi2fd (m0,m0) // (float)(prv_from->iYScr + 1)
pfsub (m0,m2) // mm0 = (float)(prv_from->iYScr + 1) - prv_from->v3Screen.tY
mov [edx]aCEdge.prvFrom,esi // prvFrom = prv_from
mov [edx]aCEdge.prvTo,edi // prvTo = prv_to
movd [f_dy],mm1 // Save f_dy (mm1)
mov ebx,[fPOINT_ZERO_ONE] // Load minimum constant
movd [edx]aCEdge.fStartYDiff,mm0 // Save fStartYDiff (mm0)
mov eax,[f_dy] // Load f_dy
cmp eax,ebx // f_dy >= 0.01
jge short DO_DIVIDE
movd mm2,[fRECIP_POINT_ZERO_ONE] // Clamp fInvDY to 1 / 0.01
movd mm4,[esi]SRenderCoord.v3Screen.tX // prv_from->v3Screen.tX
movd mm3,[edi]SRenderCoord.v3Screen.tX // prv_to->v3Screen.tX
jmp short DONE_WITH_DIVIDE
DO_DIVIDE:
pfrcp (m3,m1) // mm2 = 1.0 / f_dy
movq mm2,mm1 // copy f_dy
pfrcpit1 (m2,m3) // Newton-Raphson interation 1.
movd mm4,[esi]SRenderCoord.v3Screen.tX // prv_from->v3Screen.tX
pfrcpit2 (m2,m3) // Newton-Raphson interation 2.
movd mm3,[edi]SRenderCoord.v3Screen.tX // prv_to->v3Screen.tX
DONE_WITH_DIVIDE:
mov eax,[esi]SRenderCoord.iYScr // prv_from->iYScr
movd [edx]aCEdge.fInvDY,mm2 // Save fInvDY (mm2)
pfsub (m3,m4) // prv_to->v3Screen.tX - prv_from->v3Screen.tX
mov ebx,[edi]SRenderCoord.iYScr // prv_to->iYScr
cmp eax,ebx // if (prv_from->iYScr == prv_to->iYScr)
je RETURN_FROM_FUNC // return;
pfmul (m3,m2) // f_increment_x = fInvDY * (prv_to->v3Screen.tX - prv_from->v3Screen.tX)
movq mm5,[pfFixed16Scale] // 2^16 scaling factor
punpckldq mm3,mm3 // Duplicate f_i_x into both dwords.
pfmul (m3,m0) // f_i_x | f_i_x*fStartYDiff
pfadd (m3,m4) // f_i_x | f_i_x*fStartYDiff+tX
pfmul (m3,m5) // Scale by 2^16.
pf2id (m3,m3) // Convert to integer.
movd [edx]aCEdge.lineStart.fxX,mm3 // Store converted (f_i_x*fStartYDiff+tX)
psrlq mm3,32 // Shift f_i_x down
movd [edx]aCEdge.lineIncrement.fxX,mm3 // Store converted f_i_x
RETURN_FROM_FUNC:
//femms
}
}
//*****************************************************************************************
//
inline int iGetSubdivisionLen_3DX
(
float f_dinvz,
int b_usealt
)
//
// Returns the number of pixels to subdivide over given an inverse Z delta.
// Avoid using FPU code since this is called from a 3dx only routine.
//
//**************************************
{
int i_subdivisionlen;
// typedef CPerspectiveSettings tdPerspectiveSettings;
// Use adaptive value?
if (persetSettings.bAdaptive) __asm
{
mov eax,[f_dinvz]
mov ebx,persetSettings.iAdaptiveMaxSubdivision
and eax,0x7fffffff
// If the value is too small, use max.
cmp eax,persetSettings.fInvZForMaxSubdivision
jl RETURN_EBX
/* Decrease the subdivision length based on the 1/z delta.
i_subdivisionlen = iAdaptiveMaxSubdivision -
Fist((f_dinvz - fInvZForMaxSubdivision) * fInvZScale);
*/
movd mm0,eax
movd mm1,persetSettings.fInvZForMaxSubdivision
movd mm2,persetSettings.fInvZScale
pfsub (m0,m1)
pfmul (m0,m2)
pf2id (m0,m0)
movd eax,mm0
sub ebx,eax
// Make subdivision length a multiple of 2.
and ebx,0xfffffffe
mov eax,persetSettings.iAdaptiveMinSubdivision
cmp ebx,eax
jge RETURN_EBX
mov ebx,eax
RETURN_EBX:
mov [i_subdivisionlen],ebx
}
else
{
if (b_usealt)
i_subdivisionlen = persetSettings.iAltMinSubdivision;
else
i_subdivisionlen = persetSettings.iMinSubdivision;
}
// Return the value.
return i_subdivisionlen;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleData
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update,
bool b_altpersp
)
//
// Sets up triangle-wide rasterising info for
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
__asm
{
//femms
mov edx,[prv_a] // prv_a = edx
mov esi,[prv_b] // prv_b = esi
mov edi,[prv_c] // prv_c = edi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
pfsub (m1,m0) // b-a
pfsub (m2,m0) // c-a
movq mm5,mm1 // save mm1
// stall
punpckhdq mm1,mm2 // f_yac = cY-aY | f_yab = bY-aY
punpckldq mm2,mm5 // bX-aX | cX-aX
pfmul (m2,m1) // bX-aX * cY-aY | cX-aX * bY-aY
// stall
punpckldq mm5,mm2 // cX-aX * bY-aY | junk
pfsub (m2,m5) // (bX-aX * cY-aY) - (cX-aX * bY-aY) | junk
movd mm5,[fMAX_NEG_AREA] // Load value for comparison
punpckhdq mm2,mm2 // f_dx | f_dx
movq mm0,mm2 // copy f_dx
pfcmpge (m0,m5) // Set to mm0 ones if (mm0 >= mm5)
// stall
movd eax,mm0
test eax,eax // if (f_dx >= fMAX_NEG_AREA)
jnz RETURN_FALSE
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
pfrcp (m0,m2) // f_invdx = 1.0 / f_dx
movq mm6,[edx]SRenderVertex.tcTex.tX // prv_a->tY | tX
movd [f_dx],mm2 // save f_dx
movq mm3,[esi]SRenderVertex.tcTex.tX // prv_b->tY | tX
pfrcpit1 (m2,m0) // Newton-Raphson interation 1.
movq mm4,[edi]SRenderVertex.tcTex.tX // prv_c->tY | tX
pfsub (m3,m6) // f_vab | f_uab
movd mm5,[esi]SRenderCoord.v3Screen.tZ // prv_b->tZ
pfrcpit2 (m2,m0) // Newton-Raphson interation 2.
pfsub (m4,m6) // f_vac | f_uac
movd mm6,[edi]SRenderCoord.v3Screen.tZ // prv_c->tZ
pfmul (m1,m2) // f_yac_invdx | f_yab_invdx
movd mm2,[edx]SRenderCoord.v3Screen.tZ // prv_a->tZ
//
// Get the step values for u and v with respect to x.
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
punpckldq mm6,mm5 // prv_b->tZ | prv_c->tZ
movq mm0,mm1 // copy f_yac_invdx | f_yab_invdx
punpckhdq mm1,mm1 // f_yac_invdx | f_yac_invdx
pfmul (m3,m1) // f_vab*f_yab_invdx | f_uab*f_yab_invdx
movq mm1,mm0 // copy f_yac_invdx | f_yab_invdx
punpckldq mm0,mm0 // f_yab_invdx | f_yab_invdx
punpckldq mm2,mm2 // prv_a->tZ | prv_a->tZ
pfmul (m4,m0) // f_vac*f_yab_invdx | f_uac*f_yab_invdx
pfsub (m6,m2) // f_zab | f_zac
pfmul (m6,m1) // f_zab * f_yac_invdx | f_zac * f_yab_invdx
pfsub (m3,m4) // f_dvinvz | f_duinvz
punpckldq mm0,mm6 // f_zac * f_yab_invdx | junk
pfsub (m6,m0) // f_dinvz | junk
mov eax,[b_update]
test eax,eax
psrlq mm6,32 // 0 | f_dinvz
jz short COPY_UVZ
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
// SetMax(fDInvZ, f_dinvz);
//
movq mm0,[fDUInvZ] // fDVInvZ | fDUInvz
movq mm1,mm3 // Copy (f_dvinvz | f_duinvz)
movq mm4,[pf_abs_mask]
movq mm2,mm0 // Copy (fDVInvZ | fDUInvz)
pand mm0,mm4 // Mask off sign bits
pand mm1,mm4 // Mask off sign bits
movd mm5,[fDInvZ] // 0 | fDInvZ
pfcmpge (m0,m1) // Set ones where we should copy mm3
pand mm3,mm0 // Zero parts of new values we don't want.
pandn mm0,mm2 // Copy parts of old values we want.
por mm3,mm0 // Or them together.
pfmax (m6,m5) // Take maximum of fDInvZ, f_dinvz
COPY_UVZ:
//
// fDUInvZ = f_duinvz;
// fDVInvZ = f_dvinvz;
// fDInvZ = f_dinvz;
//
movq [fDUInvZ],mm3 // Store updated values.
movd [fDInvZ],mm6
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = iGetSubdivisionLen_3DX(fDInvZ, b_altpersp);
fInvSubdivideLen = fInverseIntTable[iSubdivideLen];
//__asm femms
return true;
RETURN_FALSE:
//__asm femms
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataGour
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update,
bool b_altpersp
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
__asm
{
//femms
mov edx,[prv_a] // prv_a = edx
mov esi,[prv_b] // prv_b = esi
mov edi,[prv_c] // prv_c = edi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
pfsub (m1,m0) // b-a
pfsub (m2,m0) // c-a
movq mm5,mm1 // save mm1
// stall
punpckhdq mm1,mm2 // f_yac = cY-aY | f_yab = bY-aY
punpckldq mm2,mm5 // bX-aX | cX-aX
pfmul (m2,m1) // bX-aX * cY-aY | cX-aX * bY-aY
// stall
punpckldq mm5,mm2 // cX-aX * bY-aY | junk
pfsub (m2,m5) // (bX-aX * cY-aY) - (cX-aX * bY-aY) | junk
movd mm5,[fMAX_NEG_AREA] // Load value for comparison
punpckhdq mm2,mm2 // f_dx | f_dx
movq mm0,mm2 // copy f_dx
pfcmpge (m0,m5) // Set to mm0 ones if (mm0 >= mm3)
// stall
movd eax,mm0
test eax,eax // if (f_dx >= fMAX_NEG_AREA)
jnz RETURN_FALSE
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
pfrcp (m0,m2) // f_invdx = 1.0 / f_dx
movq mm6,[edx]SRenderVertex.tcTex.tX // prv_a->tY | tX
movd [f_dx],mm2 // save f_dx
movq mm3,[esi]SRenderVertex.tcTex.tX // prv_b->tY | tX
pfrcpit1 (m2,m0) // Newton-Raphson interation 1.
movq mm4,[edi]SRenderVertex.tcTex.tX // prv_c->tY | tX
pfsub (m3,m6) // f_vab | f_uab
movd mm5,[esi]SRenderCoord.v3Screen.tZ // prv_b->tZ
pfrcpit2 (m2,m0) // Newton-Raphson interation 2.
pfsub (m4,m6) // f_vac | f_uac
movd mm6,[edx]SRenderCoord.v3Screen.tZ // prv_a->tZ
punpckldq mm5,[esi]SRenderVertex.cvIntensity // prv_b->cvIntensity | prv_b->tZ
pfmul (m1,m2) // f_yac_invdx | f_yab_invdx
movd mm2,[edi]SRenderCoord.v3Screen.tZ // prv_c->tZ
//
// Get the step values for u and v with respect to x.
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
// Find the step value for intensity with respect to the horizontal axis.
//
// float f_di_invdx = (prv_b->cvIntensity - prv_a->cvIntensity) * f_yac_invdx -
// (prv_c->cvIntensity - prv_a->cvIntensity) * f_yab_invdx;
//
punpckldq mm6,[edx]SRenderVertex.cvIntensity // prv_a->cvIntensity | prv_a->tZ
movq mm0,mm1 // copy (f_yac_invdx | f_yab_invdx)
punpckldq mm1,mm1 // f_yab_invdx | f_yab_invdx
punpckldq mm2,[edi]SRenderVertex.cvIntensity // prv_c->cvIntensity | prv_c->tZ
punpckhdq mm0,mm0 // f_yac_invdx | f_yac_invdx
pfmul (m4,m1) // f_vac*f_yab_invdx | f_uac*f_yab_invdx
pfsub (m5,m6) // f_iab | f_zab
pfmul (m3,m0) // f_vab*f_yac_invdx | f_uab*f_yac_invdx
pfsubr (m6,m2) // f_iac | f_zac
pfmul (m5,m0) // f_iab*f_yac_invdx | f_zab*f_yac_invdx
pfsub (m3,m4) // f_dvinvz | f_duinvz
pfmul (m6,m1) // f_iac*f_yab_invdx | f_zac*f_yab_invdx
mov eax,[b_update]
test eax,eax
pfsubr (m6,m5) // f_di_invdx | f_dinvz
jz short COPY_UVZ
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
// SetMax(fDInvZ, f_dinvz);
//
movq mm0,[fDUInvZ] // fDVInvZ | fDUInvz
movq mm1,mm3 // Copy (f_dvinvz | f_duinvz)
movq mm4,[pf_abs_mask]
movq mm2,mm0 // Copy (fDVInvZ | fDUInvz)
pand mm0,mm4 // Mask off sign bits
pand mm1,mm4 // Mask off sign bits
movd mm5,[fDInvZ] // 0 | fDInvZ
pfcmpge (m0,m1) // Set ones where we should copy mm3
pand mm3,mm0 // Zero parts of new values we don't want.
pandn mm0,mm2 // Copy parts of old values we want.
por mm3,mm0 // Or them together.
movq mm2,mm6 // Need a copy of f_di_invdx
pfmax (m6,m5) // Take maximum of fDInvZ, f_dinvz
//
// if (CIntFloat(f_di_invdx).bSign() != CIntFloat(fDeltaXIntensity).bSign())
// {
// fDeltaXIntensity = 0.0f;
// fxDeltaXIntensity = 0;
// goto SKIP_INTENSITY_UPDATE;
// }
//
// if (fabs(f_di_invdx) >= fabs(fDeltaXIntensity))
// goto SKIP_INTENSITY_UPDATE;
//
psrlq mm2,32 // 0 | f_di_invdx
mov ebx,[fDeltaXIntensity] // Get fDeltaXIntensity
movd eax,mm2
punpckldq mm6,mm2 // Repack as (f_di_invdx | f_invz)
mov ecx,eax // copy f_di_invdx
xor eax,ebx // xor sign bits
and eax,0x80000000 // test for sign bit.
jz COMPARE_INTENSITY // same sign, compare abs. values
mov eax,0
mov [fDeltaXIntensity],eax
mov [fxDeltaXIntensity],eax
jmp SKIP_INTENSITY_UPDATE
COMPARE_INTENSITY:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge SKIP_INTENSITY_UPDATE
COPY_UVZ:
//
// fDeltaXIntensity = f_di_invdx;
//
// Clamp(fDeltaXIntensity, 16.0f);
//
// Convert to fixed point representation.
//
// fxDeltaXIntensity.fxFromFloat(fDeltaXIntensity);
//
movd mm1,[fSIXTEEN] // 0 | 16.0
movq mm2,mm6 // f_di_invdx | f_invz
psrlq mm2,32 // 0 | f_di_invdx
movq mm0,[pfFixed16Scale] // 2^16 | 2^16
pfmin (m2,m1) // Clamp to 16.0
movd [fDeltaXIntensity],mm2 // Save updated, possibly clamped value.
pfmul (m2,m0) // Scale by 2^16
pf2id (m2,m2)
movd [fxDeltaXIntensity],mm2 // Save fixed point value.
SKIP_INTENSITY_UPDATE:
//
// fDUInvZ = f_duinvz;
// fDVInvZ = f_dvinvz;
// fDInvZ = f_dinvz;
//
movq [fDUInvZ],mm3 // Store updated values.
movd [fDInvZ],mm6
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = iGetSubdivisionLen_3DX(fDInvZ, b_altpersp);
fInvSubdivideLen = fInverseIntTable[iSubdivideLen];
//__asm femms
return true;
RETURN_FALSE:
//__asm femms
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataLinear
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update
)
//
// Sets up triangle-wide rasterising info for
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
__asm
{
//femms
mov edx,[prv_a] // prv_a = edx
mov esi,[prv_b] // prv_b = esi
mov edi,[prv_c] // prv_c = edi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
pfsub (m1,m0) // b-a
pfsub (m2,m0) // c-a
movq mm5,mm1 // save mm1
// stall
punpckhdq mm1,mm2 // f_yac = cY-aY | f_yab = bY-aY
punpckldq mm2,mm5 // bX-aX | cX-aX
pfmul (m2,m1) // bX-aX * cY-aY | cX-aX * bY-aY
// stall
punpckldq mm5,mm2 // cX-aX * bY-aY | junk
pfsub (m2,m5) // (bX-aX * cY-aY) - (cX-aX * bY-aY) | junk
movd mm5,[fMAX_NEG_AREA] // Load value for comparison
punpckhdq mm2,mm2 // f_dx | f_dx
movq mm0,mm2 // copy f_dx
pfcmpge (m0,m5) // Set to mm0 ones if (mm0 >= mm3)
// stall
movd eax,mm0
test eax,eax // if (f_dx >= fMAX_NEG_AREA)
jnz RETURN_FALSE
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
pfrcp (m0,m2) // f_invdx = 1.0 / f_dx
movq mm6,[edx]SRenderVertex.tcTex.tX // prv_a->tY | tX
movd [f_dx],mm2 // save f_dx
movq mm3,[esi]SRenderVertex.tcTex.tX // prv_b->tY | tX
pfrcpit1 (m2,m0) // Newton-Raphson interation 1.
movq mm4,[edi]SRenderVertex.tcTex.tX // prv_c->tY | tX
pfsub (m3,m6) // f_vab | f_uab
pfrcpit2 (m2,m0) // Newton-Raphson interation 2.
pfsub (m4,m6) // f_vac | f_uac
// stall
//
// Get the step values for u and v with respect to x.
//
// float f_du = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dv = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
pfmul (m1,m2) // f_yac_invdx | f_yab_invdx
// stall
movq mm0,mm1 // copy f_yac_invdx | f_yab_invdx
punpckhdq mm1,mm1 // f_yac_invdx | f_yac_invdx
pfmul (m3,m1) // f_vab*f_yab_invdx | f_uab*f_yab_invdx
punpckldq mm0,mm0 // f_yab_invdx | f_yab_invdx
pfmul (m4,m0) // f_vac*f_yab_invdx | f_uac*f_yab_invdx
mov eax,[b_update]
pfsub (m3,m4) // f_dv | f_du
movq mm0,[fDU] // fDV | fDU
test eax,eax
jz short COPY_UV
//
// SetMinAbs(fDU, f_du);
// SetMinAbs(fDV, f_dv);
//
movq mm4,[pf_abs_mask] // Mask to get rid of sign bit
movq mm1,mm3 // Copy (f_dv | f_du)
movq mm2,mm0 // Copy (fDV | fDU)
pand mm0,mm4 // Mask off sign bits
pand mm1,mm4 // Mask off sign bits
pfcmpge (m0,m1) // Set ones where we should copy mm3
movq mm5,mm4 // Copy abs mask
pandn mm4,mm2 // Sign bits of (fDV | fDU)
pandn mm5,mm3 // Sign bits of (f_dv | f_du)
pand mm3,mm0 // Zero parts of new values we don't want.
pxor mm4,mm5 // Xor of sign bits (one when sign differs)
pandn mm0,mm2 // Copy parts of old values we want.
por mm3,mm0 // Or them together
psrad mm4,32 // Extend sign bits into mask
pandn mm4,mm3 // Zero anything with a different sign.
movq mm3,mm4 // Put it back in mm3.
COPY_UV:
//
// fDU = f_du;
// fDV = f_dv;
//
movq [fDU],mm3 // Store updated values.
}
//__asm femms
return true;
RETURN_FALSE:
//__asm femms
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataLinearGour
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
__asm
{
//femms
mov edx,[prv_a] // prv_a = edx
mov esi,[prv_b] // prv_b = esi
mov edi,[prv_c] // prv_c = edi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
pfsub (m1,m0) // b-a
pfsub (m2,m0) // c-a
movq mm5,mm1 // save mm1
// stall
punpckhdq mm1,mm2 // f_yac = cY-aY | f_yab = bY-aY
punpckldq mm2,mm5 // bX-aX | cX-aX
pfmul (m2,m1) // bX-aX * cY-aY | cX-aX * bY-aY
// stall
punpckldq mm5,mm2 // cX-aX * bY-aY | junk
pfsub (m2,m5) // (bX-aX * cY-aY) - (cX-aX * bY-aY) | junk
movd mm5,[fMAX_NEG_AREA] // Load value for comparison
punpckhdq mm2,mm2 // f_dx | f_dx
movq mm0,mm2 // copy f_dx
pfcmpge (m0,m5) // Set to mm0 ones if (mm0 >= mm3)
// stall
movd eax,mm0
test eax,eax // if (f_dx >= fMAX_NEG_AREA)
jnz RETURN_FALSE
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
pfrcp (m0,m2) // f_invdx = 1.0 / f_dx
movq mm6,[edx]SRenderVertex.tcTex.tX // prv_a->tY | tX
movd [f_dx],mm2 // save f_dx
movq mm3,[esi]SRenderVertex.tcTex.tX // prv_b->tY | tX
pfrcpit1 (m2,m0) // Newton-Raphson interation 1.
movq mm4,[edi]SRenderVertex.tcTex.tX // prv_c->tY | tX
pfsub (m3,m6) // f_vab | f_uab
movd mm5,[esi]SRenderVertex.cvIntensity // prv_b->cvIntensity
pfrcpit2 (m2,m0) // Newton-Raphson interation 2.
pfsub (m4,m6) // f_vac | f_uac
movd mm6,[edi]SRenderVertex.cvIntensity // prv_c->cvIntensity
pfmul (m1,m2) // f_yac_invdx | f_yab_invdx
movd mm2,[edx]SRenderVertex.cvIntensity // prv_a->cvIntensity
//
// Get the step values for u and v with respect to x.
//
// float f_du = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dv = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
//
// Find the step value for intensity with respect to the horizontal axis.
//
// float f_di_invdx = (prv_b->cvIntensity - prv_a->cvIntensity) * f_yac_invdx -
// (prv_c->cvIntensity - prv_a->cvIntensity) * f_yab_invdx;
//
punpckldq mm6,mm5 // prv_b->cvIntensity | prv_c->cvIntensity
movq mm0,mm1 // copy f_yac_invdx | f_yab_invdx
punpckhdq mm1,mm1 // f_yac_invdx | f_yac_invdx
pfmul (m3,m1) // f_vab*f_yab_invdx | f_uab*f_yab_invdx
movq mm1,mm0 // copy f_yac_invdx | f_yab_invdx
punpckldq mm0,mm0 // f_yab_invdx | f_yab_invdx
punpckldq mm2,mm2 // prv_a->cvIntensity | prv_a->cvIntensity
pfmul (m4,m0) // f_vac*f_yab_invdx | f_uac*f_yab_invdx
pfsub (m6,m2) // f_iab | f_iac
pfmul (m6,m1) // f_iab * f_yac_invdx | f_iac * f_yab_invdx
pfsub (m3,m4) // f_dv | f_du
punpckldq mm0,mm6 // f_iac * f_yab_invdx | junk
pfsub (m6,m0) // f_di_invdx | junk
mov eax,[b_update]
test eax,eax
movq mm0,[fDU] // fDV | fDU
psrlq mm6,32 // 0 | f_di_invdx
jz short COPY_UV
//
// SetMinAbs(fDU, f_du);
// SetMinAbs(fDV, f_dv);
//
movq mm4,[pf_abs_mask] // Mask to get rid of sign bits
movq mm1,mm3 // Copy (f_dv | f_du)
movq mm2,mm0 // Copy (fDV | fDU)
pand mm0,mm4 // Mask off sign bits
pand mm1,mm4 // Mask off sign bits
pfcmpge (m0,m1) // Set ones where we should copy mm3
movq mm5,mm4 // Copy abs mask
pandn mm4,mm2 // Sign bits of (fDV | fDU)
pandn mm5,mm3 // Sign bits of (f_dv | f_du)
pand mm3,mm0 // Zero parts of new values we don't want.
pxor mm4,mm5 // Xor of sign bits (one when sign differs)
pandn mm0,mm2 // Copy parts of old values we want.
por mm3,mm0 // Or them together
psrad mm4,32 // Extend sign bits into mask
movq mm7,[pf_abs_mask] // Mask to get rid of sign bits
pandn mm4,mm3 // Zero anything with a different sign.
movd eax,mm6 // Need a copy of f_di_invdx
movq mm3,mm4 // Put it back in mm3.
mov ebx,[fDeltaXIntensity] // Load fDeltaXIntensity
//
// if (CIntFloat(f_di_invdx).bSign() != CIntFloat(fDeltaXIntensity).bSign())
// {
// fDeltaXIntensity = 0.0f;
// fxDeltaXIntensity = 0;
// goto SKIP_INTENSITY_UPDATE;
// }
//
// if (fabs(f_di_invdx) >= fabs(fDeltaXIntensity))
// goto SKIP_INTENSITY_UPDATE;
//
mov ecx,eax // copy f_di_invdx
xor eax,ebx // xor sign bits
and eax,0x80000000 // test for sign bit.
jz COMPARE_INTENSITY // same sign, compare abs. values
mov eax,0
mov [fDeltaXIntensity],eax
mov [fxDeltaXIntensity],eax
jmp SKIP_INTENSITY_UPDATE
COMPARE_INTENSITY:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge SKIP_INTENSITY_UPDATE
COPY_UV:
//
// fDeltaXIntensity = f_di_invdx;
//
// Clamp(fDeltaXIntensity, 16.0f);
//
// Convert to fixed point representation.
//
// fxDeltaXIntensity.fxFromFloat(fDeltaXIntensity);
//
movd mm1,[fSIXTEEN] // 0 | 16.0
movq mm0,[pfFixed16Scale] // 2^16 | 2^16
pfmin (m6,m1) // Clamp to 16.0
movd [fDeltaXIntensity],mm6 // Save updated, possibly clamped value.
pfmul (m6,m0) // Scale by 2^16
pf2id (m6,m6)
movd [fxDeltaXIntensity],mm6 // Save fixed point value.
SKIP_INTENSITY_UPDATE:
//
// fDU = f_du;
// fDV = f_dv;
//
movq [fDU],mm3 // Store updated values.
}
//__asm femms
return true;
RETURN_FALSE:
//__asm femms
return false;
}
//*****************************************************************************************
//
template <class TScanlineType> void GenericInitializeForWalk
(
CDrawPolygon<TScanlineType>* pdtri,
CEdge<TScanlineType>* pedge
)
//
// Specialized version of Intialization of an edge for walking.
//
//**************************************
{
typedef CDrawPolygon<TScanlineType> aCDrawPolygon;
typedef CEdge<TScanlineType> aCEdge;
typedef aCEdge::TScanline aScanline;
Assert(pedge);
Assert(pedge->prvFrom);
Assert(pedge->prvTo);
Assert(pdtri);
#if bPRIM_STATS
psBaseEdges.Add(0, 1);
psLines.Add(0, pedge->prvTo->iYScr - pedge->prvFrom->iYScr);
#endif
// Set base edge.
pdtri->pedgeBase = pedge;
__asm
{
//femms
mov edi,[pdtri]
mov esi,[pedge]
// Initialize edge chosen to be the base edge.
// pedge->lineStart.InitializeAsBase(pedge, poly);
//
// Get the fractional portions of the starting x difference and the increment x
// difference. See the 'Notes' section of this module for an explanation of this
// implementation.
//
// pedge->lineStart.fxXDifference = fixed(1) - pedge->lineStart.fxX.fxFractional();
// pedge->lineIncrement.fxXDifference = -pedge->lineIncrement.fxX.fxFractional();
//
mov ecx,[esi]aCEdge.lineStart.fxX.i4Fx
mov edx,[esi]aCEdge.lineIncrement.fxX.i4Fx
mov eax,ecx // Copy fixed value.
sar eax,16 // Extend sign to 16 bits.
mov ebx,edx // Copy fixed value.
and eax,0xffff0000 // Mask integral part (sign).
sar ebx,16 // Extend sign to 16 bits.
and ecx,0xffff // Mask fractional part.
and ebx,0xffff0000 // Mask integral part (sign).
or ecx,eax // Combine sign bits with fraction.
and edx,0xffff // Mask fractional part.
mov eax,0x10000 // Fixed point one.
sub eax,ecx // fixed(1) - fraction part of fxX
mov [esi]aCEdge.lineStart.fxXDifference,eax
or edx,ebx // Combine sign bits with fraction.
neg edx // Negate edx.
mov [esi]aCEdge.lineIncrement.fxXDifference,edx
//
// Convert x difference and increment to floating point.
// pedge->lineStart.fXDifference = (float)pedge->lineStart.fxXDifference;
// pedge->lineIncrement.fXDifference = (float)pedge->lineIncrement.fxXDifference;
//
movd mm0,[esi]aCEdge.lineStart.fxXDifference
movd mm1,[esi]aCEdge.lineIncrement.fxXDifference
movd mm2,[fInverseTwoToTheSixteenth] // 1.0 / 65536.0
pi2fd (m0,m0) // Convert to float
mov eax,[esi]aCEdge.prvFrom
pi2fd (m1,m1) // Convert to float
mov ebx,[esi]aCEdge.prvTo
pfmul (m0,m2) // Scale by 1 / 2^16
movd mm4,[esi]aCEdge.fInvDY // f_inv_dy
pfmul (m1,m2) // Scale by 1 / 2^16
movq mm5,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | tX
movd [esi]aCEdge.lineStart.fXDifference,mm0 // Save f_x_diff_edge
movq mm2,[ebx]SRenderVertex.tcTex.tX // prv_to->tcTex.tY | tX
movd [esi]aCEdge.lineIncrement.fXDifference,mm1 // Save f_x_diff_increment
punpckldq mm4,mm4 // f_inv_dy | f_inv_dy
//
// Use the setup routine for indexed coordinates.
//
// SRenderVertex* prv_from = pedge->prvFrom;
// SRenderVertex* prv_to = pedge->prvTo;
// float f_inv_dy = pedge->fInvDY;
// float f_x_diff_increment = pedge->lineIncrement.fXDifference;
// float f_x_diff_edge = pedge->lineStart.fXDifference;
// float f_y_diff_edge = pedge->fStartYDiff;
//
//
// Find the u and v increment values across x. The value is calculated from:
//
// du (u1 - u0)
// u increment = ---- = ---------
// dy (y1 - y0)
//
// with a similar formula for v.
//
// float f_increment_u = f_inv_dy * (prv_to->tcTex.tX - prv_from->tcTex.tX);
// float f_increment_v = f_inv_dy * (prv_to->tcTex.tY - prv_from->tcTex.tY);
// float f_increment_z = f_inv_dy * (prv_to->v3Screen.tZ - prv_from->v3Screen.tZ);
//
pfsub (m2,m5) // prv_to - prv_from
movd mm6,[eax]SRenderCoord.v3Screen.tZ // 0 | prv_to->v3Screen.tZ
punpckldq mm0,mm0 // f_x_diff_edge | f_x_diff_edge
punpckldq mm1,mm1 // f_x_diff_increment | f_x_diff_increment
pfmul (m2,m4) // f_increment_y | f_increment_x
movd mm3,[ebx]SRenderCoord.v3Screen.tZ // 0 | prv_to->v3Screen.tZ
movd mm5,[fDInvZ] // fDInvZ
pfsub (m3,m6) // prv_to - prv_from
// stall
pfmul (m3,m4) // 0 | f_increment_z
movq mm4,[fDUInvZ] // fDVInvZ | fDUInvZ
//
// Set up the increments for edge walking. Note that the increment of the x difference
// must be incorporated into this value.
//
// pedge->lineIncrement.indCoord.fUInvZ = f_increment_u + f_x_diff_increment * fDUInvZ;
// pedge->lineIncrement.indCoord.fVInvZ = f_increment_v + f_x_diff_increment * fDVInvZ;
// pedge->lineIncrement.indCoord.fInvZ = f_increment_z + f_x_diff_increment * fDInvZ;
//
movq mm7,mm5 // fDInvZ
movq mm6,mm4 // fDVInvZ | fDUInvZ
pfmul (m7,m1) // f_x_diff_increment * fDZInvZ;
pfmul (m6,m1) // f_x_diff_increment * fD[U,V]InvZ;
pfadd (m7,m3) // pedge->lineIncrement.indCoord.fInvZ
pfadd (m6,m2) // pedge->lineIncrement.indCoord.f[U,V]InvZ
movd [esi]aCEdge.lineIncrement.indCoord.fInvZ,mm7
movq [esi]aCEdge.lineIncrement.indCoord.fUInvZ,mm6
//
// Adjust u and v to the value they would be when the edge first intersects the first
// horizontal line, and add the starting adjust values with respect to x.
//
// pedge->lineStart.indCoord.fUInvZ = prv_from->tcTex.tX + f_increment_u * f_y_diff_edge + f_x_diff_edge * fDUInvZEdge;
// pedge->lineStart.indCoord.fVInvZ = prv_from->tcTex.tY + f_increment_v * f_y_diff_edge + f_x_diff_edge * fDVInvZEdge;
// pedge->lineStart.indCoord.fInvZ = prv_from->v3Screen.tZ + f_increment_z * f_y_diff_edge + f_x_diff_edge * fDInvZEdge;
//
movd mm6,[esi]aCEdge.fStartYDiff // f_y_diff_edge
// stall
punpckldq mm6,mm6 // f_y_diff_edge | f_y_diff_edge
pfmul (m2,m6) // f_increment_[u,v] * f_y_diff_edge
movq mm7,mm5 // fDInvZ
pfmul (m3,m6) // f_increment_z * f_y_diff_edge
movq mm6,mm4 // fDVInvZ | fDUInvZ
pfmul (m7,m0) // f_x_diff_edge * fDZInvZEdge
pfmul (m6,m0) // f_x_diff_edge * fD[U,V]InvZEdge
pfadd (m3,m7) // + f_increment_z * f_y_diff_edge
movd mm7,[eax]SRenderCoord.v3Screen.tZ // prv_from->v3Screen.tZ
pfadd (m2,m6) // + f_increment_[u,v] * f_y_diff_edge
movq mm6,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | prv_from->tcTex.tX
pfadd (m3,m7) // pedge->lineStart.indCoord.fInvZ
pfadd (m2,m6) // pedge->lineStart.indCoord.f[U,V]InvZ
movd [esi]aCEdge.lineStart.indCoord.fInvZ,mm3 // Save
movq [esi]aCEdge.lineStart.indCoord.fUInvZ,mm2 // Save
//
// If the negate modulus subraction sign is set, negate the modulus subraction sign
// for all related variables.
//
// if (f_x_diff_increment >= 0.0f)
// {
// -pedge->lineStart.indCoord;
// fNegUInvZ = -fDUInvZ;
// fNegVInvZ = -fDVInvZ;
// fNegInvZ = -fDInvZ;
// }
// else
// {
// fNegUInvZ = fDUInvZ;
// fNegVInvZ = fDVInvZ;
// fNegInvZ = fDInvZ;
// }
//
// float f_subdivide_len = float(iSubdivideLen);
//
// Slopes times subdivision length.
// fDUInvZEdge = fDUInvZ * f_subdivide_len;
// fDVInvZEdge = fDVInvZ * f_subdivide_len;
// fDInvZEdge = fDInvZ * f_subdivide_len;
//
movq mm0,[qFpSignBits] // 0x80000000 | 0x80000000
movq mm6,mm4 // fDVInvZEdge | fDUInvZEdge
movd mm3,iSubdivideLen // iSubdivideLen
movq mm7,mm5 // fDInvZEdge
punpckldq mm3,mm3 // iSubdivideLen | iSubdivideLen
pand mm1,mm0 // Only leave sign bit of f_x_diff_incrment
pi2fd (m3,m3) // f_subdivide_len | f_subdivide_len
pxor mm1,mm0 // Negate sign bit of f_x_diff_incrment
pxor mm6,mm1 // May negate sign bit of fDVInvZ,fDUInvZ
movq [fNegUInvZ],mm6 // Save
pxor mm7,mm1 // May negate sign bit of fDInvZ
movd [fNegInvZ],mm7 // Save
pfmul (m4,m3) // fDVInvZ * f_subdivide_len | fDUInvZ * f_subdivide_len
pfmul (m5,m3) // fDInvZ * f_subdivide_len
movq [fDUInvZEdge],mm4 // Save
movd [fDInvZEdge],mm5 // Save
//femms
}
}
//*****************************************************************************************
//
template <class TScanlineType> void GenericInitializeForWalkGour
(
CDrawPolygon<TScanlineType>* pdtri,
CEdge<TScanlineType>* pedge
)
//
// Specialized version of Intialization of an edge for walking.
//
//**************************************
{
typedef CDrawPolygon<TScanlineType> aCDrawPolygon;
typedef CEdge<TScanlineType> aCEdge;
typedef aCEdge::TScanline aScanline;
Assert(pedge);
Assert(pedge->prvFrom);
Assert(pedge->prvTo);
Assert(pdtri);
Assert((int)&((TTexturePerspGour *)0)->gourIntensity.fxIntensity - (int)&((TTexturePerspGour *)0)->gourIntensity == 0);
#if bPRIM_STATS
psBaseEdges.Add(0, 1);
psLines.Add(0, pedge->prvTo->iYScr - pedge->prvFrom->iYScr);
#endif
// Set base edge.
pdtri->pedgeBase = pedge;
__asm
{
//femms
mov edi,[pdtri]
mov esi,[pedge]
// Initialize edge chosen to be the base edge.
// pedge->lineStart.InitializeAsBase(pedge, poly);
//
// Get the fractional portions of the starting x difference and the increment x
// difference. See the 'Notes' section of this module for an explanation of this
// implementation.
//
// pedge->lineStart.fxXDifference = fixed(1) - pedge->lineStart.fxX.fxFractional();
// pedge->lineIncrement.fxXDifference = -pedge->lineIncrement.fxX.fxFractional();
//
mov ecx,[esi]aCEdge.lineStart.fxX.i4Fx
mov edx,[esi]aCEdge.lineIncrement.fxX.i4Fx
mov eax,ecx // Copy fixed value.
sar eax,16 // Extend sign to 16 bits.
mov ebx,edx // Copy fixed value.
and eax,0xffff0000 // Mask integral part (sign).
sar ebx,16 // Extend sign to 16 bits.
and ecx,0xffff // Mask fractional part.
and ebx,0xffff0000 // Mask integral part (sign).
or ecx,eax // Combine sign bits with fraction.
and edx,0xffff // Mask fractional part.
mov eax,0x10000 // Fixed point one.
sub eax,ecx // fixed(1) - fraction part of fxX
mov [esi]aCEdge.lineStart.fxXDifference,eax
or edx,ebx // Combine sign bits with fraction.
neg edx // Negate edx.
mov [esi]aCEdge.lineIncrement.fxXDifference,edx
//
// Convert x difference and increment to floating point.
// pedge->lineStart.fXDifference = (float)pedge->lineStart.fxXDifference;
// pedge->lineIncrement.fXDifference = (float)pedge->lineIncrement.fxXDifference;
//
movd mm0,[esi]aCEdge.lineStart.fxXDifference
movd mm1,[esi]aCEdge.lineIncrement.fxXDifference
movd mm2,[fInverseTwoToTheSixteenth] // 1.0 / 65536.0
pi2fd (m0,m0) // Convert to float
mov eax,[esi]aCEdge.prvFrom
pi2fd (m1,m1) // Convert to float
mov ebx,[esi]aCEdge.prvTo
pfmul (m0,m2) // Scale by 1 / 2^16
movd mm4,[esi]aCEdge.fInvDY // f_inv_dy
pfmul (m1,m2) // Scale by 1 / 2^16
movq mm5,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | tX
movd [esi]aCEdge.lineStart.fXDifference,mm0 // Save f_x_diff_edge
movq mm2,[ebx]SRenderVertex.tcTex.tX // prv_to->tcTex.tY | tX
movd [esi]aCEdge.lineIncrement.fXDifference,mm1 // Save f_x_diff_increment
movd mm6,[eax]SRenderCoord.v3Screen.tZ // 0 | prv_from->v3Screen.tZ
//
// Use the setup routine for indexed coordinates.
// Use the setup routine for Gouraud-shaded base edges.
//
// SRenderVertex* prv_from = pedge->prvFrom;
// SRenderVertex* prv_to = pedge->prvTo;
// float f_inv_dy = pedge->fInvDY;
// float f_x_diff_increment = pedge->lineIncrement.fXDifference;
// float f_x_diff_edge = pedge->lineStart.fXDifference;
// float f_y_diff_edge = pedge->fStartYDiff;
//
//
// Find the u and v increment values across x. The value is calculated from:
//
// du (u1 - u0)
// u increment = ---- = ---------
// dy (y1 - y0)
//
// with a similar formula for v.
//
// float f_increment_u = f_inv_dy * (prv_to->tcTex.tX - prv_from->tcTex.tX);
// float f_increment_v = f_inv_dy * (prv_to->tcTex.tY - prv_from->tcTex.tY);
// float f_increment_z = f_inv_dy * (prv_to->v3Screen.tZ - prv_from->v3Screen.tZ);
// float f_increment_i = f_inv_dy * (prv_to->cvIntensity - prv_from->cvIntensity);
//
pfsub (m2,m5) // prv_to - prv_from
punpckldq mm4,mm4 // f_inv_dy | f_inv_dy
punpckldq mm6,[eax]SRenderVertex.cvIntensity // prv_from->cvIntensity | prv_from->v3Screen.tZ
punpckldq mm0,mm0 // f_x_diff_edge | f_x_diff_edge
movd mm3,[ebx]SRenderCoord.v3Screen.tZ // 0 | prv_to->v3Screen.tZ
punpckldq mm1,mm1 // f_x_diff_increment | f_x_diff_increment
punpckldq mm3,[ebx]SRenderVertex.cvIntensity // prv_to->cvIntensity | prv_to->v3Screen.tZ
pfmul (m2,m4) // f_increment_y | f_increment_x
movd mm5,[fDInvZ] // fDInvZ
// stall
pfsub (m3,m6) // prv_to - prv_from
punpckldq mm5,[fDeltaXIntensity] // fDeltaXIntensity | fDInvZ
pfmul (m3,m4) // f_increment_i | f_increment_z
movq mm4,[fDUInvZ] // fDVInvZ | fDUInvZ
//
// Set up the increments for edge walking. Note that the increment of the x difference
// must be incorporated into this value.
//
// pedge->lineIncrement.indCoord.fUInvZ = f_increment_u + f_x_diff_increment * fDUInvZ;
// pedge->lineIncrement.indCoord.fVInvZ = f_increment_v + f_x_diff_increment * fDVInvZ;
// pedge->lineIncrement.indCoord.fInvZ = f_increment_z + f_x_diff_increment * fDInvZ;
// pedge->lineIncrement.gourIntensity.fxIntensity = fixed(f_increment_i + f_x_diff_increment * fDeltaXIntensity);
//
movq mm7,mm5 // fDeltaXIntensity | fDInvZ
movq mm6,mm4 // fDVInvZ | fDUInvZ
pfmul (m7,m1) // f_x_diff_increment * [fDZInvZ,fDeltaXIntensity];
pfmul (m6,m1) // f_x_diff_increment * fD[U,V]InvZ;
pfadd (m7,m3) // fIntensity | pedge->lineIncrement.indCoord.fInvZ
pfadd (m6,m2) // pedge->lineIncrement.indCoord.f[U,V]InvZ
movd [esi]aCEdge.lineIncrement.indCoord.fInvZ,mm7
psrlq mm7,32
movq [esi]aCEdge.lineIncrement.indCoord.fUInvZ,mm6
movq mm6,[pfFixed16Scale]
// stall
pfmul (m7,m6) // Scale by 2^16
movd mm6,[esi]aCEdge.fStartYDiff // f_y_diff_edge
// stall
pf2id (m7,m7) // Convert to integer
punpckldq mm6,mm6 // f_y_diff_edge | f_y_diff_edge
movd [esi]aCEdge.lineIncrement.gourIntensity,mm7
//
// Adjust u and v to the value they would be when the edge first intersects the first
// horizontal line, and add the starting adjust values with respect to x.
//
// pedge->lineStart.indCoord.fUInvZ = prv_from->tcTex.tX + f_increment_u * f_y_diff_edge + f_x_diff_edge * fDUInvZEdge;
// pedge->lineStart.indCoord.fVInvZ = prv_from->tcTex.tY + f_increment_v * f_y_diff_edge + f_x_diff_edge * fDVInvZEdge;
// pedge->lineStart.indCoord.fInvZ = prv_from->v3Screen.tZ + f_increment_z * f_y_diff_edge + f_x_diff_edge * fDInvZEdge;
// pedge->lineStart.gourIntensity.fxIntensity = fixed(prv_from->cvIntensity + f_increment_i * f_y_diff_edge + f_x_diff_edge * fDeltaXIntensity);
//
pfmul (m2,m6) // f_increment_[u,v] * f_y_diff_edge
movq mm7,mm5 // fDeltaXIntensity | fDInvZ
pfmul (m3,m6) // f_increment_[z,i] * f_y_diff_edge
movq mm6,mm4 // fDVInvZ | fDUInvZ
pfmul (m7,m0) // f_x_diff_edge * [fDZInvZ,fDeltaXIntensity]
pfmul (m6,m0) // f_x_diff_edge * fD[U,V]InvZ
pfadd (m3,m7) // + f_increment_[z,i] * f_y_diff_edge
movd mm7,[eax]SRenderCoord.v3Screen.tZ // prv_from->v3Screen.tZ
pfadd (m2,m6) // + f_increment_[u,v] * f_y_diff_edge
punpckldq mm7,[eax]SRenderVertex.cvIntensity // prv_from->cvIntensity | prv_from->v3Screen.tZ
movq mm6,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | prv_from->tcTex.tX
movq mm0,[pfFixed16Scale] // Load fixed point scaling factor
pfadd (m3,m7) // pedge->lineStart.indCoord.fInvZ
pfadd (m2,m6) // pedge->lineStart.indCoord.f[U,V]InvZ
movd [esi]aCEdge.lineStart.indCoord.fInvZ,mm3 // Save
pfmul (m3,m0) // Scale by 2^16
movq [esi]aCEdge.lineStart.indCoord.fUInvZ,mm2 // Save
//
// If the negate modulus subraction sign is set, negate the modulus subraction sign
// for all related variables.
//
// if (f_x_diff_increment >= 0.0f)
// {
// -pedge->lineStart.indCoord;
// fNegUInvZ = -fDUInvZ;
// fNegVInvZ = -fDVInvZ;
// fNegInvZ = -fDInvZ;
//
// -gourIntensity;
// fxIModDiv = -fxDeltaXIntensity;
// }
// else
// {
// fNegUInvZ = fDUInvZ;
// fNegVInvZ = fDVInvZ;
// fNegInvZ = fDInvZ;
// fxIModDiv = fxDeltaXIntensity;
// }
//
// float f_subdivide_len = float(iSubdivideLen);
//
// Slopes times subdivision length.
// fDUInvZEdge = fDUInvZ * f_subdivide_len;
// fDVInvZEdge = fDVInvZ * f_subdivide_len;
// fDInvZEdge = fDInvZ * f_subdivide_len;
//
movq mm0,[qFpSignBits] // 0x80000000 | 0x80000000
movq mm6,mm4 // fDVInvZEdge | fDUInvZEdge
pf2id (m3,m3) // Convert to integer
movd mm2,iSubdivideLen // iSubdivideLen
movq mm7,mm5 // fDInvZEdge
psrlq mm3,32
movd [esi]aCEdge.lineStart.gourIntensity,mm3
punpckldq mm2,mm2 // iSubdivideLen | iSubdivideLen
pand mm1,mm0 // Only leave sign bit of f_x_diff_incrment
pi2fd (m2,m2) // f_subdivide_len | f_subdivide_len
pxor mm1,mm0 // Negate sign bit of f_x_diff_incrment
pxor mm6,mm1 // May negate sign bit of fDVInvZ,fDUInvZ
movq [fNegUInvZ],mm6 // Save
pxor mm7,mm1 // May negate sign bit of fDInvZ
movd [fNegInvZ],mm7 // Save
pfmul (m4,m2) // fDVInvZ * f_subdivide_len | fDUInvZ * f_subdivide_len
mov ecx,[esi]aCEdge.lineIncrement.fXDifference
pfmul (m5,m2) // fDInvZ * f_subdivide_len
movq [fDUInvZEdge],mm4 // Save
movd [fDInvZEdge],mm5 // Save
mov edx,[fxDeltaXIntensity]
test ecx,0x80000000 // Test sign bit.
jnz STORE_IMODDIV
neg edx // Negate fxIModDiv
STORE_IMODDIV:
mov [fxIModDiv],edx
//femms
}
}
//*****************************************************************************************
//
template <class TScanlineType> void GenericInitializeForWalkLinear
(
CDrawPolygon<TScanlineType>* pdtri,
CEdge<TScanlineType>* pedge
)
//
// Specialized version of Intialization of an edge for walking.
//
//**************************************
{
typedef CDrawPolygon<TScanlineType> aCDrawPolygon;
typedef CEdge<TScanlineType> aCEdge;
typedef aCEdge::TScanline aScanline;
Assert(pedge);
Assert(pedge->prvFrom);
Assert(pedge->prvTo);
Assert(pdtri);
#if bPRIM_STATS
psBaseEdges.Add(0, 1);
psLines.Add(0, pedge->prvTo->iYScr - pedge->prvFrom->iYScr);
#endif
// Set base edge.
pdtri->pedgeBase = pedge;
__asm
{
//femms
mov edi,[pdtri]
mov esi,[pedge]
// Initialize edge chosen to be the base edge.
// pedge->lineStart.InitializeAsBase(pedge, poly);
//
// Get the fractional portions of the starting x difference and the increment x
// difference. See the 'Notes' section of this module for an explanation of this
// implementation.
//
// pedge->lineStart.fxXDifference = fixed(1) - pedge->lineStart.fxX.fxFractional();
// pedge->lineIncrement.fxXDifference = -pedge->lineIncrement.fxX.fxFractional();
//
mov ecx,[esi]aCEdge.lineStart.fxX.i4Fx
mov edx,[esi]aCEdge.lineIncrement.fxX.i4Fx
mov eax,ecx // Copy fixed value.
sar eax,16 // Extend sign to 16 bits.
mov ebx,edx // Copy fixed value.
and eax,0xffff0000 // Mask integral part (sign).
sar ebx,16 // Extend sign to 16 bits.
and ecx,0xffff // Mask fractional part.
and ebx,0xffff0000 // Mask integral part (sign).
or ecx,eax // Combine sign bits with fraction.
and edx,0xffff // Mask fractional part.
mov eax,0x10000 // Fixed point one.
sub eax,ecx // fixed(1) - fraction part of fxX
mov [esi]aCEdge.lineStart.fxXDifference,eax
or edx,ebx // Combine sign bits with fraction.
neg edx // Negate edx.
mov [esi]aCEdge.lineIncrement.fxXDifference,edx
//
// Convert x difference and increment to floating point.
// pedge->lineStart.fXDifference = (float)pedge->lineStart.fxXDifference;
// pedge->lineIncrement.fXDifference = (float)pedge->lineIncrement.fxXDifference;
//
movd mm0,[esi]aCEdge.lineStart.fxXDifference
movd mm1,[esi]aCEdge.lineIncrement.fxXDifference
movd mm2,[fInverseTwoToTheSixteenth] // 1.0 / 65536.0
pi2fd (m0,m0) // Convert to float
mov eax,[esi]aCEdge.prvFrom
pi2fd (m1,m1) // Convert to float
mov ebx,[esi]aCEdge.prvTo
pfmul (m0,m2) // Scale by 1 / 2^16
movd mm4,[esi]aCEdge.fInvDY // f_inv_dy
pfmul (m1,m2) // Scale by 1 / 2^16
movq mm5,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | tX
movd [esi]aCEdge.lineStart.fXDifference,mm0 // Save f_x_diff_edge
movq mm2,[ebx]SRenderVertex.tcTex.tX // prv_to->tcTex.tY | tX
movd [esi]aCEdge.lineIncrement.fXDifference,mm1 // Save f_x_diff_increment
punpckldq mm4,mm4 // f_inv_dy | f_inv_dy
//
// Use the setup routine for indexed coordinates.
// Use the setup routine for Gouraud-shaded base edges.
//
// SRenderVertex* prv_from = pedge->prvFrom;
// SRenderVertex* prv_to = pedge->prvTo;
// float f_inv_dy = pedge->fInvDY;
// float f_x_diff_increment = pedge->lineIncrement.fXDifference;
// float f_x_diff_edge = pedge->lineStart.fXDifference;
// float f_y_diff_edge = pedge->fStartYDiff;
//
//
// Find the u and v increment values across x. The value is calculated from:
//
// du (u1 - u0)
// u increment = ---- = ---------
// dy (y1 - y0)
//
// with a similar formula for v.
//
// float f_increment_u = f_inv_dy * (prv_to->tcTex.tX - prv_from->tcTex.tX);
// float f_increment_v = f_inv_dy * (prv_to->tcTex.tY - prv_from->tcTex.tY);
//
pfsub (m2,m5) // prv_to - prv_from
movq mm3,[pfFixed16Scale] // Fixed point scaling factor
punpckldq mm0,mm0 // f_x_diff_edge | f_x_diff_edge
movq mm6,[fDU] // fDV | fDU
pfmul (m2,m4) // f_increment_v | f_increment_u
punpckldq mm1,mm1 // f_x_diff_increment | f_x_diff_increment
//
// Set up the increments for edge walking. Note that the increment of the x difference
// must be incorporated into this value.
//
// pedge->lineIncrement.indCoord.pfIndex.U = (f_increment_u + f_x_diff_increment * fDU) * 65536.0f;
// pedge->lineIncrement.indCoord.pfIndex.V = (f_increment_v + f_x_diff_increment * fDV) * 65536.0f;
//
//
// Adjust u and v to the value they would be when the edge first intersects the first
// horizontal line, and add the starting adjust values with respect to x.
//
// pedge->lineStart.indCoord.pfIndex.U = (prv_from->tcTex.tX + f_increment_u * f_y_diff_edge + f_x_diff_edge * fDU) * 65536.0f;
// pedge->lineStart.indCoord.pfIndex.V = (prv_from->tcTex.tY + f_increment_v * f_y_diff_edge + f_x_diff_edge * fDV) * 65536.0f;
//
movd mm5,[esi]aCEdge.fStartYDiff // f_y_diff_edge
movq mm4,mm6 // fDV | fDU
pfmul (m6,m1) // f_x_diff_increment * fD[U,V];
punpckldq mm5,mm5 // f_y_diff_edge | f_y_diff_edge
pfadd (m6,m2) // pedge->lineIncrement.indCoord.pfIndex.[U,V]
pfmul (m2,m5) // f_increment_[u,v] * f_y_diff_edge
movq mm5,mm4 // fDV | fDU
pfmul (m4,m0) // f_x_diff_edge * fD[U,V]
pfmul (m6,m3) // multiply by 2^16
movq mm0,[eax]SRenderVertex.tcTex.tX
pfadd (m2,m4) // + f_increment_[u,v] * f_y_diff_edge
movq [esi]aCEdge.lineIncrement.indCoord.pfIndex,mm6
pfadd (m2,m0) // pedge->lineStart.indCoord.pfIndex.[U,V]
movq mm0,[qFpSignBits]
pfmul (m2,m3) // multiply by 2^16
//
// If the negate modulus subraction sign is set, negate the modulus subraction sign
// for all related variables.
//
// if (pedge->lineIncrement.fXDifference >= 0.0f)
// {
// -pedge->lineStart.indCoord;
// pfNegD.U = -fDU * 65536.0f;
// pfNegD.V = -fDV * 65536.0f;
// }
// else
// {
// pfNegD.U = fDU * 65536.0f;
// pfNegD.V = fDV * 65536.0f;
// }
//
pfmul (m3,m5) // fDV * 65536.0f | fDU * 65536.0f
pand mm1,mm0 // Only leave sign bit of f_x_diff_incrment
movq [esi]aCEdge.lineStart.indCoord.pfIndex,mm2
pxor mm1,mm0 // Negate sign bit of f_x_diff_incrment
pf2id (m4,m3)
pxor mm3,mm1 // May negate sign bit of fDV,fDU
movq [pfNegD],mm3 // Save sub-pixel correction offset
movq [pfxDeltaTex],mm4 // Set pfxDeltaTex.[U,V]
//femms
}
}
//*****************************************************************************************
//
template <class TScanlineType> void GenericInitializeForWalkLinearGour
(
CDrawPolygon<TScanlineType>* pdtri,
CEdge<TScanlineType>* pedge
)
//
// Specialized version of Intialization of an edge for walking.
//
//**************************************
{
typedef CDrawPolygon<TScanlineType> aCDrawPolygon;
typedef CEdge<TScanlineType> aCEdge;
typedef aCEdge::TScanline aScanline;
Assert(pedge);
Assert(pedge->prvFrom);
Assert(pedge->prvTo);
Assert(pdtri);
#if bPRIM_STATS
psBaseEdges.Add(0, 1);
psLines.Add(0, pedge->prvTo->iYScr - pedge->prvFrom->iYScr);
#endif
// Set base edge.
pdtri->pedgeBase = pedge;
__asm
{
//femms
mov edi,[pdtri]
mov esi,[pedge]
// Initialize edge chosen to be the base edge.
// pedge->lineStart.InitializeAsBase(pedge, poly);
//
// Get the fractional portions of the starting x difference and the increment x
// difference. See the 'Notes' section of this module for an explanation of this
// implementation.
//
// pedge->lineStart.fxXDifference = fixed(1) - pedge->lineStart.fxX.fxFractional();
// pedge->lineIncrement.fxXDifference = -pedge->lineIncrement.fxX.fxFractional();
//
mov ecx,[esi]aCEdge.lineStart.fxX.i4Fx
mov edx,[esi]aCEdge.lineIncrement.fxX.i4Fx
mov eax,ecx // Copy fixed value.
sar eax,16 // Extend sign to 16 bits.
mov ebx,edx // Copy fixed value.
and eax,0xffff0000 // Mask integral part (sign).
sar ebx,16 // Extend sign to 16 bits.
and ecx,0xffff // Mask fractional part.
and ebx,0xffff0000 // Mask integral part (sign).
or ecx,eax // Combine sign bits with fraction.
and edx,0xffff // Mask fractional part.
mov eax,0x10000 // Fixed point one.
sub eax,ecx // fixed(1) - fraction part of fxX
mov [esi]aCEdge.lineStart.fxXDifference,eax
or edx,ebx // Combine sign bits with fraction.
movd mm2,[fInverseTwoToTheSixteenth] // 1.0 / 65536.0
neg edx // Negate edx.
mov [esi]aCEdge.lineIncrement.fxXDifference,edx
//
// Convert x difference and increment to floating point.
// pedge->lineStart.fXDifference = (float)pedge->lineStart.fxXDifference;
// pedge->lineIncrement.fXDifference = (float)pedge->lineIncrement.fxXDifference;
//
movd mm0,[esi]aCEdge.lineStart.fxXDifference
movd mm1,[esi]aCEdge.lineIncrement.fxXDifference
pi2fd (m0,m0) // Convert to float
mov eax,[esi]aCEdge.prvFrom
pi2fd (m1,m1) // Convert to float
mov ebx,[esi]aCEdge.prvTo
pfmul (m0,m2) // Scale by 1 / 2^16
movd mm4,[esi]aCEdge.fInvDY // f_inv_dy
pfmul (m1,m2) // Scale by 1 / 2^16
movq mm5,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | tX
movd [esi]aCEdge.lineStart.fXDifference,mm0 // Save f_x_diff_edge
movq mm2,[ebx]SRenderVertex.tcTex.tX // prv_to->tcTex.tY | tX
movd [esi]aCEdge.lineIncrement.fXDifference,mm1 // Save f_x_diff_increment
punpckldq mm4,mm4 // f_inv_dy | f_inv_dy
//
// Use the setup routine for indexed coordinates.
//
// SRenderVertex* prv_from = pedge->prvFrom;
// SRenderVertex* prv_to = pedge->prvTo;
// float f_inv_dy = pedge->fInvDY;
// float f_x_diff_increment = pedge->lineIncrement.fXDifference;
// float f_x_diff_edge = pedge->lineStart.fXDifference;
// float f_y_diff_edge = pedge->fStartYDiff;
//
//
// Find the u and v increment values across x. The value is calculated from:
//
// du (u1 - u0)
// u increment = ---- = ---------
// dy (y1 - y0)
//
// with a similar formula for v.
//
// float f_increment_u = f_inv_dy * (prv_to->tcTex.tX - prv_from->tcTex.tX);
// float f_increment_v = f_inv_dy * (prv_to->tcTex.tY - prv_from->tcTex.tY);
// float f_increment_i = f_inv_dy * (prv_to->cvIntensity - prv_from->cvIntensity);
//
pfsub (m2,m5) // prv_to - prv_from
movd mm6,[eax]SRenderVertex.cvIntensity // 0 | prv_from->cvIntenstiy
punpckldq mm0,mm0 // f_x_diff_edge | f_x_diff_edge
movd mm3,[ebx]SRenderVertex.cvIntensity // 0 | prv_to->cvIntensity
pfmul (m2,m4) // f_increment_y | f_increment_x
punpckldq mm1,mm1 // f_x_diff_increment | f_x_diff_increment
movd mm5,[fDeltaXIntensity] // fDeltaXIntensity
pfsub (m3,m6) // prv_to - prv_from
movq mm6,[fDU] // fDV | fDU
pfmul (m3,m4) // 0 | f_increment_i
movq mm7,[pfFixed16Scale] // Fixed point scaling factor
//
// Set up the increments for edge walking. Note that the increment of the x difference
// must be incorporated into this value.
//
// pedge->lineIncrement.indCoord.pfIndex.U = (f_increment_u + f_x_diff_increment * fDU) * 65536.0f;
// pedge->lineIncrement.indCoord.pfIndex.V = (f_increment_v + f_x_diff_increment * fDV) * 65536.0f;
// pedge->lineIncrement.gourIntensity.fxIntensity = fixed(f_increment_i + f_x_diff_increment * fDeltaXIntensity);
//
movq mm4,mm6 // fDV | fDU
pfmul (m5,m1) // f_x_diff_increment * fDeltaXIntensity
pfmul (m6,m1) // f_x_diff_increment * fD[U,V]
pfadd (m5,m3) // pedge->lineIncrement.gourIntensity.fxIntensity
pfadd (m6,m2) // pedge->lineIncrement.indCoord.f[U,V]
pfmul (m5,m7) // scale by 2^16
pfmul (m6,m7) // scale by 2^16
pf2id (m5,m5) // convert to integer.
movq [esi]aCEdge.lineIncrement.indCoord.pfIndex,mm6
movd [esi]aCEdge.lineIncrement.gourIntensity,mm5
//
// Adjust u and v to the value they would be when the edge first intersects the first
// horizontal line, and add the starting adjust values with respect to x.
//
// pedge->lineStart.indCoord.pfIndex.U = (prv_from->tcTex.tX + f_increment_u * f_y_diff_edge + f_x_diff_edge * fDU) * 65536.0f;
// pedge->lineStart.indCoord.pfIndex.V = (prv_from->tcTex.tY + f_increment_v * f_y_diff_edge + f_x_diff_edge * fDV) * 65536.0f;
// pedge->lineStart.gourIntensity.fxIntensity = fixed(prv_from->cvIntensity + f_increment_i * f_y_diff_edge + f_x_diff_edge * fDeltaXIntensity);
//
movd mm6,[esi]aCEdge.fStartYDiff // f_y_diff_edge
// stall
punpckldq mm6,mm6 // f_y_diff_edge | f_y_diff_edge
pfmul (m2,m6) // f_increment_[u,v] * f_y_diff_edge
movd mm5,[fDeltaXIntensity] // fDeltaXIntensity
pfmul (m3,m6) // f_increment_i * f_y_diff_edge
movq mm6,mm4 // fDV | fDU
pfmul (m5,m0) // f_x_diff_edge * fDeltaXIntensity
pfmul (m6,m0) // f_x_diff_edge * fD[U,V]
pfadd (m3,m5) // + f_increment_i * f_y_diff_edge
movd mm5,[eax]SRenderVertex.cvIntensity // prv_from->cvIntensity
pfadd (m2,m6) // + f_increment_[u,v] * f_y_diff_edge
movq mm6,[eax]SRenderVertex.tcTex.tX // prv_from->tcTex.tY | prv_from->tcTex.tX
pfadd (m3,m5) // pedge->lineStart.gourIntensity.fxIntensity
movq mm0,[qFpSignBits]
pfadd (m2,m6) // pedge->lineStart.indCoord.f[U,V]
pfmul (m4,m7) // fDV * 65536.0f | fDU * 65536.0f
pfmul (m3,m7) // scale by 2^16
pand mm1,mm0 // Only leave sign bit of f_x_diff_incrment
pfmul (m2,m7) // scale by 2^16
pxor mm1,mm0 // Negate sign bit of f_x_diff_incrment
pf2id (m3,m3) // Convert to integer.
movq [esi]aCEdge.lineStart.indCoord.pfIndex,mm2 // Save
movd [esi]aCEdge.lineStart.gourIntensity,mm3 // Save
pf2id (m3,m4) // Convert fDV,fDU to integer.
//
// If the negate modulus subraction sign is set, negate the modulus subraction sign
// for all related variables.
//
// if (pedge->lineIncrement.fXDifference >= 0.0f)
// {
// -pedge->lineStart.indCoord;
// pfNegD.U = -fDU * 65536.0f;
// pfNegD.V = -fDV * 65536.0f;
//
// -gourIntensity;
// fxIModDiv = -fxDeltaXIntensity;
// }
// else
// {
// pfNegD.U = fDU * 65536.0f;
// pfNegD.V = fDV * 65536.0f;
//
// fxIModDiv = fxDeltaXIntensity;
// }
//
pxor mm4,mm1 // May negate sign bit of fDV,fDU
movq [pfNegD],mm4 // Save sub-pixel correction offset
mov ecx,[esi]aCEdge.lineIncrement.fXDifference
movq [pfxDeltaTex],mm3 // Set pfxDeltaTex.[U,V]
mov edx,[fxDeltaXIntensity]
test ecx,0x80000000 // Test sign bit.
jnz STORE_IMODDIV
neg edx // Negate fxIModDiv
STORE_IMODDIV:
mov [fxIModDiv],edx
//femms
}
}
//*****************************************************************************************
//
inline bool GenericInitGradientDataPlanar(CDrawPolygonBase* poly, bool b_altpersp)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
// These are saved for the best edge pair.
float f_dx;
SRenderVertex *prv_a;
SRenderVertex *prv_b;
SRenderVertex *prv_c;
__asm
{
// femms
//
// Find the first edge pair with an area greater than 25 pixels, or if no
// edge pair has an area greater than 25 pixels find the maximum.
//
// Set starting vertices [N-2, N-1, 0].
lea edi,[arvRasterVertices] // prv_c = edi = a[n]
mov ecx,[iNumRasterVertices]
mov eax,SIZE SRenderVertex
dec ecx
imul eax,ecx
lea edx,[edi + eax] // prv_b = esi = a[n-1]
mov esi,edx
sub edx,SIZE SRenderVertex // prv_a = edx = a[n-2]
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
mov [prv_c],edi
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
mov [prv_b],esi
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
mov [prv_a],edx
pfsub (m2,m0) // yac | xac
pfsub (m1,m0) // yab | xab
movq mm3,mm2 // yac | xac
punpckldq mm2,mm1 // xab | xac
punpckhdq mm1,mm3 // yac | yab
pfmul (m2,m1) // xab*yac | xac*yab
movq mm7,mm1 // Save yac | yab
movq mm4,mm2 // xab*yac | xac*yab
punpckhdq mm4,mm4 // xab*yac | xab*yac
pfsub (m4,m2) // f_dx = xab*yac - xac*yab
mov ebx,[fNegativeFifty]
movd eax,mm4 // f_dx
cmp eax,ebx // If our best < -50, then stop
ja EXIT_LOOP
EDGE_LOOP:
mov edx,esi // prv_a = prv_b
mov esi,edi // prv_b = prv_c
add edi,SIZE SRenderVertex // prv_c = next vertex
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
movq mm2,[edi]SRenderCoord.v3Screen.tX // prv_c->tY | tX
movq mm0,[edx]SRenderCoord.v3Screen.tX // prv_a->tY | tX
movq mm1,[esi]SRenderCoord.v3Screen.tX // prv_b->tY | tX
pfsub (m2,m0) // yac | xac
pfsub (m1,m0) // yab | xab
movq mm3,mm2 // yac | xac
punpckldq mm2,mm1 // xab | xac
punpckhdq mm1,mm3 // yac | yab
pfmul (m2,m1) // xab*yac | xac*yab
movq mm0,mm2 // xab*yac | xac*yab
punpckhdq mm0,mm0 // xab*yac | xab*yac
pfsub (m0,m2) // f_dx = xab*yac - xac*yab
movq mm2,mm0 // Make a copy of f_dx
pfcmpge (m0,m4) // Set mm0 to ones if (mm0 >= mm4)
// stall
movd eax,mm0
test eax,eax // if mm1 < f_dx then new minimum
jz NEW_MINIMUM
dec ecx
jnz EDGE_LOOP
jmp short EXIT_LOOP
NEW_MINIMUM:
// Yes, save f_dx in mm4, yac|yab in mm7 and vertex pointers.
movd eax,mm2 // f_dx
movq mm4,mm2 // New f_dx
movq mm7,mm1 // Save yac | yab
mov [prv_a],edx
mov [prv_b],esi
cmp eax,ebx // If our best < -50, then stop
mov [prv_c],edi
ja EXIT_LOOP
dec ecx
jnz EDGE_LOOP
EXIT_LOOP:
//
// Is the polygon too small to draw?
// if (f_dx >= fMAX_NEG_AREA) goto RETURN_FALSE;
//
// mm4 = f_dx
// mm7 = yac | yab
//
mov ebx,[fMAX_NEG_AREA]
movd eax,mm4
movd [f_dx],mm4
punpckldq mm4,mm4
cmp eax,ebx
jbe RETURN_FALSE
//
// Initialize the texture gradients based on the best edge.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
mov edx,[prv_a]
pfrcp (m0,m4) // f_invdx = 1.0 / f_dx
mov esi,[prv_b]
mov edi,[prv_c]
pfrcpit1 (m4,m0) // Newton-Raphson interation 1.
movq mm6,[edx]SRenderVertex.tcTex.tX // prv_a->tY | tX
movq mm3,[esi]SRenderVertex.tcTex.tX // prv_b->tY | tX
pfrcpit2 (m4,m0) // Newton-Raphson interation 2.
movq mm2,[edi]SRenderVertex.tcTex.tX // prv_c->tY | tX
pfsub (m3,m6) // f_vab | f_uab
movd mm5,[esi]SRenderCoord.v3Screen.tZ // prv_b->tZ
pfsub (m2,m6) // f_vac | f_uac
movd mm6,[edi]SRenderCoord.v3Screen.tZ // prv_c->tZ
pfmul (m7,m4) // f_yac_invdx | f_yab_invdx
movd mm4,[edx]SRenderCoord.v3Screen.tZ // prv_a->tZ
//
// Get the step values for u and v with respect to x.
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
punpckldq mm6,mm5 // prv_b->tZ | prv_c->tZ
movq mm0,mm7 // copy f_yac_invdx | f_yab_invdx
punpckhdq mm7,mm7 // f_yac_invdx | f_yac_invdx
pfmul (m3,m7) // f_vab*f_yab_invdx | f_uab*f_yab_invdx
movq mm7,mm0 // copy f_yac_invdx | f_yab_invdx
punpckldq mm0,mm0 // f_yab_invdx | f_yab_invdx
punpckldq mm4,mm4 // prv_a->tZ | prv_a->tZ
pfmul (m2,m0) // f_vac*f_yab_invdx | f_uac*f_yab_invdx
pfsub (m6,m4) // f_zab | f_zac
pfmul (m6,m7) // f_zab * f_yac_invdx | f_zac * f_yab_invdx
pfsub (m3,m2) // f_dvinvz | f_duinvz
punpckldq mm0,mm6 // f_zac * f_yab_invdx | junk
pfsub (m6,m0) // f_dinvz | junk
psrlq mm6,32 // 0 | f_dinvz
movq [fDUInvZ],mm3 // Store updated values.
movd [fDInvZ],mm6
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = iGetSubdivisionLen_3DX(fDInvZ, b_altpersp);
fInvSubdivideLen = fInverseIntTable[iSubdivideLen];
//__asm femms
return true;
RETURN_FALSE:
//__asm femms
return false;
}
#else // #if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
//*****************************************************************************************
//
inline void GenericInitializePolygonData(CRenderPolygon *rpoly)
//
// Scanline data initialization for un-shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tX,iY,tY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,iY,tY)
fxch st(2) // (tY,iY,tX*Z)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
fxch st(2) // (tX*Z,iY,tY*Z)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fxch st(2) // (tX,tY,iY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,tY,iY)
fxch st(2) // (iY,tY,tX*Z)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tY,iY,tX*Z)
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataFlat(CRenderPolygon *rpoly)
//
// Scanline data initialization for flat shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = iPosFloatCast(rpoly->cvFace);
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = 0;
if (rpoly->ptexTexture && rpoly->ptexTexture->ppcePalClut && rpoly->ptexTexture->ppcePalClut->pclutClut)
{
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
Assert(iBaseIntensity < rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues);
}
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tX,iY,tY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,iY,tY)
fxch st(2) // (tY,iY,tX*Z)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
fxch st(2) // (tX*Z,iY,tY*Z)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fxch st(2) // (tX,tY,iY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,tY,iY)
fxch st(2) // (iY,tY,tX*Z)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tY,iY,tX*Z)
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataGour(CRenderPolygon *rpoly)
//
// Scanline data initialization for gouraud shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tX,iY,tY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,iY,tY)
fxch st(2) // (tY,iY,tX*Z)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
fxch st(2) // (tX*Z,iY,tY*Z)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
and ecx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
mov [edi]SRenderCoord.iYScr,ecx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fxch st(2) // (tX,tY,iY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,tY,iY)
fxch st(2) // (iY,tY,tX*Z)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tY,iY,tX*Z)
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
and ecx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
mov [edi]SRenderCoord.iYScr,ecx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataBump(CRenderPolygon *rpoly)
//
// Scanline data initialization for bump shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapBump::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tX,iY,tY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,iY,tY)
fxch st(2) // (tY,iY,tX*Z)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
fxch st(2) // (tX*Z,iY,tY*Z)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight) *
// rpoly.paprvPolyVertices[i]->v3Screen.tZ;
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fxch st(2) // (tX,tY,iY)
fmul [eax]SRenderCoord.v3Screen.tZ // (tX*Z,tY,iY)
fxch st(2) // (iY,tY,tX*Z)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(1) // (tY,iY,tX*Z)
fmul [eax]SRenderCoord.v3Screen.tZ // (tY*Z,iY,tX*Z)
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinear(CRenderPolygon *rpoly)
//
// Scanline data initialization for un-shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tY,tX,iY)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
fxch st(1) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearFlat(CRenderPolygon *rpoly)
//
// Scanline data initialization for flat shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = iPosFloatCast(rpoly->cvFace);
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = 0;
if (rpoly->ptexTexture && rpoly->ptexTexture->ppcePalClut && rpoly->ptexTexture->ppcePalClut->pclutClut)
{
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
Assert(iBaseIntensity < rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues);
}
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tY,tX,iY)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
fxch st(1) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearGour(CRenderPolygon *rpoly)
//
// Scanline data initialization for gouraud shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
#if VER_DEBUG
iNumIntensities = rpoly->ptexTexture->ppcePalClut->pclutClut->iNumRampValues;
#endif
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapTexture<uint8>::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance)
//
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance)
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tY,tX,iY)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
fxch st(1) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
and ecx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
mov [edi]SRenderCoord.iYScr,ecx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = (rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth)
// arvRasterVertices[i].tcTex.tY = (rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight)
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov ebx,[eax]SRenderVertex.cvIntensity // Load intenstity.
and ecx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderVertex.cvIntensity,ebx // Store intensity.
mov [edi]SRenderCoord.iYScr,ecx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
inline void GenericInitializePolygonDataLinearBump(CRenderPolygon *rpoly)
//
// Scanline data initialization for bump shaded primitives.
//
//**************************************
{
// Make sure these assumptions are correct.
Assert(CRenderPolygon_paprvPolyVertices_uLen == (int)&((CRenderPolygon *)0)->paprvPolyVertices.uLen);
Assert(CRenderPolygon_paprvPolyVertices_atArray == (int)&((CRenderPolygon *)0)->paprvPolyVertices.atArray);
//
// Set up polygon-wide variables for rasterising; i.e. those not associated with
// triangle gradients. Also, set needed per-vertex data.
// Initialize polygon-wide variables for index coordinates.
//
rptr<CRaster> pras_texture = rpoly->ptexTexture->prasGetTexture(rpoly->iMipLevel);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Set the tiling & mask globals.
//lineData.indCoord.BuildTileMask(pras_texture);
bClampUV = pras_texture->bNotTileable;
u4TextureTileMask = (pras_texture->u4HeightTileMask << 9) | pras_texture->u4WidthTileMask;
u4TextureTileMaskStepU = pras_texture->u4WidthTileMask;
// Set the base address for the clut.
//lineData.SetClutAddress(ptexTexture);
iBaseIntensity = 0;
u4ConstColour = 0;
// Call the get address function for the clut.
pvClutConversion = rpoly->ptexTexture->ppcePalClut->pclutClut->pvGetConversionAddress
(
CMapBump::u4GetClutBaseColour(rpoly->ptexTexture),
iBaseIntensity,
iDefaultFog
);
__asm
{
mov ebx,bClampUV
mov eax,pras_texture // Pointer to texture.
test ebx,ebx
jz NO_CLAMP
//
// Copy vertices & scale texture values with clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP1:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX *
// fTexWidth + fTexEdgeTolerance
//
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY *
// fTexHeight + fTexEdgeTolerance
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fxch st(1) // (tX,tY)
fadd fTexEdgeTolerance // Add edge tolerance to tX.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tX,tY)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tY,tX,iY)
fadd fTexEdgeTolerance // Add edge tolerance to tY.
fxch st(1) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov ebx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
and ebx,0x0007ffff // Mask off FP junk.
mov [edi]SRenderCoord.iYScr,ebx // Store integer Y.
add edi,SIZE SRenderVertex // Step destination.
dec edx
jnz VTXLOOP1
jmp VTXDONE
NO_CLAMP:
//
// Copy vertices & scale texture values, no clamping.
//
mov ecx,rpoly // Pointer to polygon.
lea edi,arvRasterVertices // Destination vertices.
mov ebx,[eax]CRasterBase.fWidth
mov eax,[eax]CRasterBase.fHeight
mov esi,[ecx + CRenderPolygon_paprvPolyVertices_atArray]
mov edx,[ecx + CRenderPolygon_paprvPolyVertices_uLen]
mov fTexWidth,ebx // fTexWidth = pras_texture->fWidth;
mov fTexHeight,eax // fTexHeight = pras_texture->fHeight;
VTXLOOP2:
// Pointer to source vertex in eax.
mov eax,[esi] // Pointer to vertex.
add esi,4 // Step vertex pointer array index.
//
// arvRasterVertices[i].iYScr = TruncateToInt(arvRasterVertices[i].v3Screen.tY);
//
// arvRasterVertices[i].tcTex.tX = rpoly.paprvPolyVertices[i]->tcTex.tX * fTexWidth
// arvRasterVertices[i].tcTex.tY = rpoly.paprvPolyVertices[i]->tcTex.tY * fTexHeight
//
// arvRasterVertices[i].v3Screen = rpoly.paprvPolyVertices[i]->v3Screen;
// arvRasterVertices[i].cvIntensity = rpoly.paprvPolyVertices[i]->cvIntensity;
//
fld [fTexWidth] // Texture X value. (tX)
fmul [eax]SRenderVertex.tcTex.tX // Scaled by width.
fld [eax]SRenderVertex.tcTex.tY // Texture Y value. (tY,tX)
fmul [fTexHeight] // Scaled by height.
fld [eax]SRenderCoord.v3Screen.tY // Screen Y. (iY,tY,tX)
fadd dFloatToFixed32 // Add integer conversion constant.
fxch st(2) // (tX,tY,iY)
fstp [edi]SRenderVertex.tcTex.tX // Store texture X.
fstp [edi]SRenderVertex.tcTex.tY // Store texture Y.
fstp d_temp_a // Store 19.32 integer y value.
mov ecx,[eax]SRenderCoord.v3Screen.tX // Load X
mov ebx,[eax]SRenderCoord.v3Screen.tY // Load Y
mov [edi]SRenderCoord.v3Screen.tX,ecx // Store X
mov ecx,[eax]SRenderCoord.v3Screen.tZ // Load Z
mov [edi]SRenderCoord.v3Screen.tY,ebx // Store Y
mov [edi]SRenderCoord.v3Screen.tZ,ecx // Store Z
mov ecx,dword ptr[d_temp_a + 4] // Get integer part of 19.32 y value.
add edi,SIZE SRenderVertex // Step destination.
and ecx,0x0007ffff // Mask off FP junk.
dec edx
mov [edi - SIZE SRenderVertex]SRenderCoord.iYScr,ecx // Store integer Y.
jnz VTXLOOP2
VTXDONE:
}
}
//*****************************************************************************************
//
template <class aCEdge> void GenericInitializeEdge
(
aCEdge &edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Sets up a polygon edge.
//
//**************************************
{
typedef aCEdge::TScanline aScanline;
int i4temp;
float f_dy;
__asm
{
mov esi,prv_from // From vertex.
mov edi,prv_to // To vertex.
mov edx,edge // Load edge poniter.
mov eax,[esi]SRenderCoord.iYScr
inc eax
mov i4temp,eax
fild i4temp // (float)(prv_from->iYScr + 1)
fld [edi]SRenderCoord.v3Screen.tY // prv_to->v3Screen.tY
fsub [esi]SRenderCoord.v3Screen.tY // prv_to->v3Screen.tY - prv_from->v3Screen.tY
fxch st(1) // i4temp,f_dy
fsub [esi]SRenderCoord.v3Screen.tY // (float)(prv_from->iYScr + 1) - prv_from->v3Screen.tY
fxch st(1) // f_dy,fStartYDiff
mov [edx]aCEdge.prvFrom,esi // prvFrom = prv_from
mov [edx]aCEdge.prvTo,edi // prvTo = prv_to
fstp f_dy // Save f_dy
fstp [edx]aCEdge.fStartYDiff // Save fStartYDiff
mov eax,f_dy // Load f_dy
mov ebx,fPOINT_ZERO_ONE // Load minimum constant
cmp eax,ebx // fdy >= 0.01
jge short DO_DIVIDE
mov eax,fRECIP_POINT_ZERO_ONE
mov [edx]aCEdge.fInvDY,eax
jmp short DONE_WITH_DIVIDE
DO_DIVIDE:
// fld fONE
// fdiv f_dy // 1.0 / f_dy
mov ebx,[f_dy]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dy]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov [edx]aCEdge.fInvDY,eax
fmul [edx]aCEdge.fInvDY // (v*r)
fsubr [fTWO] // (2.0 - v*r)
fmul [edx]aCEdge.fInvDY // (2.0 - v*r)*r
fstp [edx]aCEdge.fInvDY // fInvDY = ^
DONE_WITH_DIVIDE:
mov eax,[esi]SRenderCoord.iYScr
mov ebx,[edi]SRenderCoord.iYScr
cmp eax,ebx // if (prv_from->iYScr == prv_to->iYScr)
je RETURN_FROM_FUNC // return;
fld [edi]SRenderCoord.v3Screen.tX // prv_to->v3Screen.tX
fsub [esi]SRenderCoord.v3Screen.tX // prv_to->v3Screen.tX - prv_from->v3Screen.tX
fmul [edx]aCEdge.fInvDY // f_increment_x = fInvDY * (prv_to->v3Screen.tX - prv_from->v3Screen.tX)
fld st(0) // Dup f_increment_x
fmul [edx]aCEdge.fStartYDiff // fix*fStartYDiff, fix
fxch st(1) // fix, fix*fStartYDiff
fadd dFloatToFixed16 // Convert to 16.16
fxch st(1) // fix*fStartYDiff, fix
fadd [esi]SRenderCoord.v3Screen.tX // fix*fStartYDiff+tX, fix
fxch st(1) // fix,fix*fStartYDiff+tX
fstp d_temp_a // Store converted value
fadd dFloatToFixed16 // Convert to 16.16
fstp d_temp_b // Store converted value
mov ebx,dword ptr[d_temp_a]
mov ecx,dword ptr[d_temp_b]
mov [edx]aCEdge.lineIncrement.fxX,ebx
mov [edx]aCEdge.lineStart.fxX,ecx
RETURN_FROM_FUNC:
}
}
//*****************************************************************************************
//
inline bool GenericInitTriangleData
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update,
bool b_altpersp
)
//
// Sets up triangle-wide rasterising info for
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
float f_invdx;
float f_yab_invdx;
float f_yac_invdx;
float f_duinvz;
float f_dvinvz;
float f_dinvz;
float f_temp;
__asm
{
mov edi,prv_c // prv_c = edi
mov edx,prv_a // prv_a = edx
mov esi,prv_b // prv_b = esi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab,f_yac
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_xab,f_yac
fxch st(1) // f_xab,f_yab,f_yac
fmul st(0),st(2) // f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_xab*f_yac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uab,f_xac,f_xab*f_yac,f_yab,f_yac
fxch st(1) // f_xac,f_uab,f_xab*f_yac,f_yab,f_yac
fmul st(0),st(3) // f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uac,f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fxch st(3) // f_xab*f_yac,f_xac*f_yab,f_uab,f_uac,f_yab,f_yac
fsubrp st(1),st(0) // f_dx,f_uab,f_uac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fld st(1) // f_dx,f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fsub fMAX_NEG_AREA // f_dx',f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fxch st(2) // f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fsub [edx]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fxch st(3) // f_dx',f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// stall(1)
fstp f_temp // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
mov eax,f_temp
test eax,0x80000000 // if (f_dx >= fMAX_NEG_AREA)
jnz short GOOD_TO_GO
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcomp st(0) // Dump stuff off the stack
jmp RETURN_FALSE
GOOD_TO_GO:
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
fstp f_dx // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// fdivr fONE // invdx,vab,vac,uab,uac,yab,yac
mov ebx,dword ptr[f_dx]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dx]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov dword ptr[f_invdx],eax
fmul [f_invdx] // (v*r)
fsubr [fTWO] // (2.0 - v*r)
fmul [f_invdx] // (2.0 - v*r)*r
fmul st(5),st(0) // invdx,vab,vac,uab,uac,yab_invdx,yac
fst f_invdx
fmulp st(6),st(0) // vab,_vac,uab,uac,yab_invdx,yac_invdx
fxch st(4) // yab_invdx,vac,uab,uac,vab,yac_invdx
fst f_yab_invdx
fmul st(3),st(0) // yab_invdx,vac,uab,uac*yab,vab,yac_invdx
fxch st(5) // yac_invdx,vac,uab,uac*yab,vab,yab_invdx
fst f_yac_invdx
fmul st(2),st(0) // yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
//
// Get the step values for u and v with respect to x.
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
fld [esi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zab,yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
fxch st(6) // yab_invdx,yac_invdx,vac,uab*yac,uac*yab,vab,zab
fmul st(2),st(0) // yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab,zab
fld [edi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zac,yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab,zab
fxch st(2) // yac_invdx,yab_invdx,zac,vac*yab,uab*yac,uac*yab,vab,zab
fmul st(6),st(0) // yac_invdx,yab_invdx,zac,vac*yab,uab*yac,uac*yab,vab*yac,zab
fxch st(4) // uab*yac,yab_invdx,zac,vac*yab,yac_invdx,uac*yab,vab*yac,zab
fsubrp st(5),st(0) // yab_invdx,zac,vac*yab,yac_invdx,duinvz,vab*yac,zab
fxch st(6) // zab,zac,vac*yab,yac_invdx,duinvz,vab*yac,yab_invdx
fmulp st(3),st(0) // zac,vac*yab,zab*yac,duinvz,vab*yac,yab_invdx
fxch st(1) // vac*yab,zac,zab*yac,duinvz,vab*yac,yab_invdx
fsubp st(4),st(0) // zac,zab*yac,duinvz,dvinvz,yab_invdx
fmulp st(4),st(0) // zab*yac,duinvz,dvinvz,zac*yab
fxch st(1) // duinvz,zab*yac,dvinvz,zac*yab
fstp f_duinvz // zab*yac,dvinvz,zac*yab
fsubrp st(2),st(0) // dvinvz,dinvz
fstp f_dvinvz // dinvz
mov eax,b_update
// stall(1)
fstp f_dinvz
test eax,eax
jz short COPY_UVZ
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
// SetMax(fDInvZ, f_dinvz);
//
mov eax,f_duinvz
mov ebx,fDUInvZ
and eax,0x7fffffff
and ebx,0x7fffffff
cmp eax,ebx
jge short SKIP_U_COPY
mov eax,f_duinvz
mov fDUInvZ,eax
SKIP_U_COPY:
mov eax,f_dvinvz
mov ebx,fDVInvZ
and eax,0x7fffffff
and ebx,0x7fffffff
cmp eax,ebx
jge short SKIP_V_COPY
mov eax,f_dvinvz
mov fDVInvZ,eax
SKIP_V_COPY:
mov eax,f_dinvz
mov ecx,0x80000000
mov ebx,fDInvZ
mov edx,0x80000000
and ecx,eax
and eax,0x7fffffff
sar ecx,31
and edx,ebx
sar edx,31
and ebx,0x7fffffff
xor eax,ecx
xor ebx,edx
cmp eax,ebx
jle short SKIP_Z_COPY
mov eax,f_dinvz
mov fDInvZ,eax
SKIP_Z_COPY:
jmp short DONE_WITH_COPY
COPY_UVZ:
//
// fDUInvZ = f_duinvz;
// fDVInvZ = f_dvinvz;
// fDInvZ = f_dinvz;
//
mov eax,f_duinvz
mov ebx,f_dvinvz
mov ecx,f_dinvz
mov fDUInvZ,eax
mov fDVInvZ,ebx
mov fDInvZ,ecx
DONE_WITH_COPY:
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = persetSettings.iGetSubdivisionLen(fDInvZ, b_altpersp);
fInvSubdivideLen = fUnsignedInverseInt(iSubdivideLen);
return true;
RETURN_FALSE:
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataGour
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update,
bool b_altpersp
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
float f_invdx;
float f_yab_invdx;
float f_yac_invdx;
float f_duinvz;
float f_dvinvz;
float f_dinvz;
float f_di_invdx;
float f_temp;
__asm
{
mov edi,prv_c // prv_c = edi
mov edx,prv_a // prv_a = edx
mov esi,prv_b // prv_b = esi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab,f_yac
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_xab,f_yac
fxch st(1) // f_xab,f_yab,f_yac
fmul st(0),st(2) // f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_xab*f_yac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uab,f_xac,f_xab*f_yac,f_yab,f_yac
fxch st(1) // f_xac,f_uab,f_xab*f_yac,f_yab,f_yac
fmul st(0),st(3) // f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uac,f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fxch st(3) // f_xab*f_yac,f_xac*f_yab,f_uab,f_uac,f_yab,f_yac
fsubrp st(1),st(0) // f_dx,f_uab,f_uac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fld st(1) // f_dx,f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fsub fMAX_NEG_AREA // f_dx',f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fxch st(2) // f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fsub [edx]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fxch st(3) // f_dx',f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// stall(1)
fstp f_temp // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
mov eax,f_temp
test eax,0x80000000 // if (f_dx >= fMAX_NEG_AREA)
jnz short GOOD_TO_GO
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcomp st(0) // Dump stuff off the stack
jmp RETURN_FALSE
GOOD_TO_GO:
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
fstp f_dx // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// fdivr fONE // invdx,vab,vac,uab,uac,yab,yac
mov ebx,dword ptr[f_dx]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dx]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov dword ptr[f_invdx],eax
fmul [f_invdx] // (v*r)
fsubr [fTWO] // (2.0 - v*r)
fmul [f_invdx] // (2.0 - v*r)*r
fmul st(5),st(0) // invdx,vab,vac,uab,uac,yab_invdx,yac
fst f_invdx
fmulp st(6),st(0) // vab,_vac,uab,uac,yab_invdx,yac_invdx
fxch st(4) // yab_invdx,vac,uab,uac,vab,yac_invdx
fst f_yab_invdx
fmul st(3),st(0) // yab_invdx,vac,uab,uac*yab,vab,yac_invdx
fxch st(5) // yac_invdx,vac,uab,uac*yab,vab,yab_invdx
fst f_yac_invdx
fmul st(2),st(0) // yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
//
// Get the step values for u and v with respect to x.
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
//
// Find the step value for intensity with respect to the horizontal axis.
//
// float f_di_invdx = (prv_b->cvIntensity - prv_a->cvIntensity) * f_yac_invdx -
// (prv_c->cvIntensity - prv_a->cvIntensity) * f_yab_invdx;
//
fld [esi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zab,yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
fxch st(6) // yab_invdx,yac_invdx,vac,uab*yac,uac*yab,vab,zab
fmul st(2),st(0) // yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab,zab
fld [edi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zac,yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab,zab
fxch st(2) // yac_invdx,yab_invdx,zac,vac*yab,uab*yac,uac*yab,vab,zab
fmul st(6),st(0) // yac_invdx,yab_invdx,zac,vac*yab,uab*yac,uac*yab,vab*yac,zab
fxch st(4) // uab*yac,yab_invdx,zac,vac*yab,yac_invdx,uac*yab,vab*yac,zab
fsubrp st(5),st(0) // yab,zac,vac*yab,yac,duinvz,vab*yac,zab
fmul st(1),st(0) // yab,zac*yab,vac*yab,yac,duinvz,vab*yac,zab
fld [esi]SRenderVertex.cvIntensity
fsub [edx]SRenderVertex.cvIntensity // iab,yab,zac*yab,vac*yab,yac,duinvz,vab*yac,zab
fxch st(6) // vab*yac,yab,zac*yab,vac*yab,yac,duinvz,iab,zab
fsubrp st(3),st(0) // yab,zac*yab,dvinvz,yac,duinvz,iab,zab
fxch st(3) // yac,zac*yab,dvinvz,yab,duinvz,iab,zab
fmul st(6),st(0) // yac,zac*yab,dvinvz,yab,duinvz,iab,zab*yac
fld [edi]SRenderVertex.cvIntensity
fsub [edx]SRenderVertex.cvIntensity // iac,yac,zac*yab,dvinvz,yab,duinvz,iab,zab*yac
fxch st(2) // zac*yab,yac,iac,dvinvz,yab,duinvz,iab,zab*yac
fsubp st(7),st(0) // yac,iac,dvinvz,yab,duinvz,iab,dinvz
fmulp st(5),st(0) // iac,dvinvz,yab,duinvz,iab*yac,dinvz
fxch st(1) // dvinvz,iac,yab,duinvz,iab*yac,dinvz
fstp f_dvinvz // iac,yab,duinvz,iab*yac,dinvz
fmulp st(1),st(0) // iac*yab,duinvz,iab*yac,dinvz
fxch st(1) // duinvz,iac*yab,iab*yac,dinvz
fstp f_duinvz // iac*yab,iab*yac,dinvz
fsubp st(1),st(0) // di_invdx,dinvz
fxch st(1) // dinvz,di_invdx
fstp f_dinvz // di_invdx
mov eax,b_update // Load b_update flag.
fstp f_di_invdx // fp stack empty
test eax,eax
jz COPY_UVZ
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
// SetMax(fDInvZ, f_dinvz);
//
mov eax,f_duinvz
mov ebx,fDUInvZ
and eax,0x7fffffff
and ebx,0x7fffffff
cmp eax,ebx
jge short SKIP_U_COPY
mov eax,f_duinvz
mov fDUInvZ,eax
SKIP_U_COPY:
mov eax,f_dvinvz
mov ebx,fDVInvZ
and eax,0x7fffffff
and ebx,0x7fffffff
cmp eax,ebx
jge short SKIP_V_COPY
mov eax,f_dvinvz
mov fDVInvZ,eax
SKIP_V_COPY:
mov eax,f_dinvz
mov ecx,0x80000000
mov ebx,fDInvZ
mov edx,0x80000000
and ecx,eax
and eax,0x7fffffff
sar ecx,31
and edx,ebx
sar edx,31
and ebx,0x7fffffff
xor eax,ecx
xor ebx,edx
cmp eax,ebx
jle short SKIP_Z_COPY
mov eax,f_dinvz
mov fDInvZ,eax
SKIP_Z_COPY:
//
// if (CIntFloat(f_di_invdx).bSign() != CIntFloat(fDeltaXIntensity).bSign())
// {
// fDeltaXIntensity = 0.0f;
// fxDeltaXIntensity = 0;
// goto SKIP_INTENSITY_UPDATE;
// }
//
// if (fabs(f_di_invdx) >= fabs(fDeltaXIntensity))
// goto SKIP_INTENSITY_UPDATE;
//
mov eax,f_di_invdx
mov ebx,fDeltaXIntensity
mov ecx,eax // copy f_di_invdx
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_INTENSITY // same sign, compare abs. values
xor eax,eax
mov fDeltaXIntensity,eax
mov fxDeltaXIntensity,eax
jmp SKIP_INTENSITY_UPDATE
COMPARE_INTENSITY:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge SKIP_INTENSITY_UPDATE
jmp DONE_WITH_COPY
COPY_UVZ:
//
// fDUInvZ = f_duinvz;
// fDVInvZ = f_dvinvz;
// fDInvZ = f_dinvz;
//
mov eax,f_duinvz
mov ebx,f_dvinvz
mov ecx,f_dinvz
mov fDUInvZ,eax
mov fDVInvZ,ebx
mov fDInvZ,ecx
DONE_WITH_COPY:
//
// fDeltaXIntensity = f_di_invdx;
//
// Clamp(fDeltaXIntensity, 16.0f);
//
// Convert to fixed point representation.
//
// fxDeltaXIntensity.fxFromFloat(fDeltaXIntensity);
//
fld f_di_invdx // Load intensity (assuming no clamp).
fadd dFloatToFixed16 // Add integer conversion constant.
mov eax,f_di_invdx // Load value.
mov ecx,fSIXTEEN // Load clamp value.
mov ebx,eax // Copy value for sign.
mov edx,eax // Keep orignal value.
and eax,0x7fffffff // Mask off sign bit.
and ebx,0x80000000 // Keep just the sign bit.
cmp eax,ecx // Compare against 16.0
jle short NO_INTENSITY_CLAMP
//
// Clamp value. This is a relatively rare case.
//
fcomp st(0) // Dump unclamped value.
mov edx,ecx // Clamp value.
or edx,ebx // Keep sign bit.
mov f_di_invdx,edx // Save clamped value.
fld f_di_invdx // Load clamped intensity.
fadd dFloatToFixed16 // Add integer conversion constant.
// stall(3)
NO_INTENSITY_CLAMP:
fstp d_temp_a // Store fixed point value.
mov fDeltaXIntensity,edx // Save updated, possibly clamped value.
mov eax,dword ptr[d_temp_a] // Load fixed point value.
mov fxDeltaXIntensity,eax // Save fixed point value.
SKIP_INTENSITY_UPDATE:
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = persetSettings.iGetSubdivisionLen(fDInvZ, b_altpersp);
fInvSubdivideLen = fUnsignedInverseInt(iSubdivideLen);
return true;
RETURN_FALSE:
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataLinear
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update
)
//
// Sets up triangle-wide rasterising info for
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
float f_invdx;
float f_yab_invdx;
float f_yac_invdx;
float f_du;
float f_dv;
float f_temp;
__asm
{
mov edi,prv_c // prv_c = edi
mov edx,prv_a // prv_a = edx
mov esi,prv_b // prv_b = esi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab,f_yac
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_xab,f_yac
fxch st(1) // f_xab,f_yab,f_yac
fmul st(0),st(2) // f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_xab*f_yac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uab,f_xac,f_xab*f_yac,f_yab,f_yac
fxch st(1) // f_xac,f_uab,f_xab*f_yac,f_yab,f_yac
fmul st(0),st(3) // f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uac,f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fxch st(3) // f_xab*f_yac,f_xac*f_yab,f_uab,f_uac,f_yab,f_yac
fsubrp st(1),st(0) // f_dx,f_uab,f_uac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fld st(1) // f_dx,f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fsub fMAX_NEG_AREA // f_dx',f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fxch st(2) // f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fsub [edx]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fxch st(3) // f_dx',f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// stall(1)
fstp f_temp // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
mov eax,f_temp
test eax,0x80000000 // if (f_dx >= fMAX_NEG_AREA)
jnz short GOOD_TO_GO
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcomp st(0) // Dump stuff off the stack
jmp RETURN_FALSE
GOOD_TO_GO:
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
fstp f_dx // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// fdivr fONE // invdx,vab,vac,uab,uac,yab,yac
mov ebx,dword ptr[f_dx]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dx]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov dword ptr[f_invdx],eax
fmul [f_invdx] // (v*r)
fsubr [fTWO] // (2.0 - v*r)
fmul [f_invdx] // (2.0 - v*r)*r
fmul st(5),st(0) // invdx,vab,vac,uab,uac,yab_invdx,yac
fst f_invdx
fmulp st(6),st(0) // vab,_vac,uab,uac,yab_invdx,yac_invdx
fxch st(4) // yab_invdx,vac,uab,uac,vab,yac_invdx
fst f_yab_invdx
fmul st(3),st(0) // yab_invdx,vac,uab,uac*yab,vab,yac_invdx
fxch st(5) // yac_invdx,vac,uab,uac*yab,vab,yab_invdx
fst f_yac_invdx
fmul st(2),st(0) // yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
//
// Get the step values for u and v with respect to x.
//
// float f_du = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dv = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
mov eax,b_update
fmulp st(4),st(0) // vac,uab*yac,uac*yab,vab*yac,yab_invdx
fxch st(2) // uac*yab,uab*yac,vac,vab*yac,yab_invdx
fsubp st(1),st(0) // f_du,vac,vab*yac,yab_invdx
fxch st(1) // vac,f_du,vab*yac,yab_invdx
fmulp st(3),st(0) // f_du,vab*yac,vac*yab
// stall(2)
fstp f_du // vab*yac,vac*yab
fsubrp st(1),st(0) // f_dv
// stall(3)
fstp f_dv
test eax,eax
jz short COPY_UV
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
//
mov eax,[f_du]
mov ebx,[fDU]
mov ecx,eax // copy f_du
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_U // same sign, compare abs. values
xor ecx,ecx // clear ecx
jmp SAVE_NEW_U // go store it
COMPARE_U:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge short SKIP_U_COPY
mov ecx,[f_du]
SAVE_NEW_U:
mov [fDU],ecx
SKIP_U_COPY:
mov eax,[f_dv]
mov ebx,[fDV]
mov ecx,eax // copy f_dv
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_V // same sign, compare abs. values
xor ecx,ecx // clear ecx
jmp SAVE_NEW_V // go store it
COMPARE_V:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge short DONE_WITH_COPY
mov ecx,[f_dv]
SAVE_NEW_V:
mov [fDV],ecx
jmp short DONE_WITH_COPY
COPY_UV:
//
// fDU = f_du
// fDV = f_dv
//
mov eax,[f_du]
mov ebx,[f_dv]
mov [fDU],eax
mov [fDV],ebx
DONE_WITH_COPY:
}
return true;
RETURN_FALSE:
return false;
}
//*****************************************************************************************
//
inline bool GenericInitTriangleDataLinearGour
(
CDrawPolygonBase* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
int b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
Assert(prv_a);
Assert(prv_b);
Assert(prv_c);
//
// Calculate fInvDx, the partial derivative of x over the triangle, using the following
// formula:
//
// 1 1
// fInvDx = ---- = ---------------------------------------
// dx (x2 - x1)(y3 - y1) - (x3 - x1)(y2 - y1)
//
// dx also happens to be -2 times the area of the triangle, so we can check for correct
// orientation here as well.
//
float f_dx;
float f_invdx;
float f_yab_invdx;
float f_yac_invdx;
float f_du;
float f_dv;
float f_di_invdx;
float f_temp;
__asm
{
mov edi,prv_c // prv_c = edi
mov edx,prv_a // prv_a = edx
mov esi,prv_b // prv_b = esi
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab,f_yac
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_xab,f_yac
fxch st(1) // f_xab,f_yab,f_yac
fmul st(0),st(2) // f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_xab*f_yac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uab,f_xac,f_xab*f_yac,f_yab,f_yac
fxch st(1) // f_xac,f_uab,f_xab*f_yac,f_yab,f_yac
fmul st(0),st(3) // f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // f_uac,f_xac*f_yab,f_uab,f_xab*f_yac,f_yab,f_yac
fxch st(3) // f_xab*f_yac,f_xac*f_yab,f_uab,f_uac,f_yab,f_yac
fsubrp st(1),st(0) // f_dx,f_uab,f_uac,f_yab,f_yac
fld [esi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fld st(1) // f_dx,f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fsub fMAX_NEG_AREA // f_dx',f_vab,f_dx,f_uab,f_uac,f_yab,f_yac
fxch st(2) // f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fld [edi]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fsub [edx]SRenderVertex.tcTex.tY // f_vac,f_dx,f_vab,f_dx',f_uab,f_uac,f_yab,f_yac
fxch st(3) // f_dx',f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// stall(1)
fstp f_temp // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
mov eax,f_temp
test eax,0x80000000 // if (f_dx >= fMAX_NEG_AREA)
jnz short GOOD_TO_GO
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcompp // Dump stuff off the stack
fcomp st(0) // Dump stuff off the stack
jmp RETURN_FALSE
GOOD_TO_GO:
//
// Calculate coefficients to pass to template InitializeTriangleData functions.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
fstp f_dx // f_dx,f_vab,f_vac,f_uab,f_uac,f_yab,f_yac
// fdivr fONE // invdx,vab,vac,uab,uac,yab,yac
mov ebx,dword ptr[f_dx]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dx]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov dword ptr[f_invdx],eax
fmul [f_invdx] // (v*r)
fsubr [fTWO] // (2.0 - v*r)
fmul [f_invdx] // (2.0 - v*r)*r
fmul st(5),st(0) // invdx,vab,vac,uab,uac,yab_invdx,yac
fst f_invdx
fmulp st(6),st(0) // vab,_vac,uab,uac,yab_invdx,yac_invdx
fxch st(4) // yab_invdx,vac,uab,uac,vab,yac_invdx
fst f_yab_invdx
fmul st(3),st(0) // yab_invdx,vac,uab,uac*yab,vab,yac_invdx
fxch st(5) // yac_invdx,vac,uab,uac*yab,vab,yab_invdx
fst f_yac_invdx
fmul st(2),st(0) // yac_invdx,vac,uab*yac,uac*yab,vab,yab_invdx
//
// Get the step values for u and v with respect to x.
//
// float f_du = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dv = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
//
// Find the step value for intensity with respect to the horizontal axis.
//
// float f_di_invdx = (prv_b->cvIntensity - prv_a->cvIntensity) * f_yac_invdx -
// (prv_c->cvIntensity - prv_a->cvIntensity) * f_yab_invdx;
//
mov eax,b_update
fmul st(4),st(0) // yac_invdx,vac,uab*yac,uac*yab,vab*yac,yab_invdx
fld [esi]SRenderVertex.cvIntensity // iab,yac_invdx,vac,uab*yac,uac*yab,vab*yac,yab_invdx
fsub [edx]SRenderVertex.cvIntensity // iab,yac_invdx,vac,uab*yac,uac*yab,vab*yac,yab_invdx
fxch st(6) // yab_invdx,yac_invdx,vac,uab*yac,uac*yab,vab*yac,iab
fmul st(2),st(0) // yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab*yac,iab
fld [edi]SRenderVertex.cvIntensity // iac,yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab*yac,iab
fsub [edx]SRenderVertex.cvIntensity // iac,yab_invdx,yac_invdx,vac*yab,uab*yac,uac*yab,vab*yac,iab
fxch st(2) // yac_invdx,yab_invdx,iac,vac*yab,uab*yac,uac*yab,vab*yac,iab
fmulp st(7),st(0) // yab_invdx,iac,vac*yab,uab*yac,uac*yab,vab*yac,iab*yac
fxch st(3) // uab*yac,iac,vac*yab,yab_invdx,uac*yab,vab*yac,iab*yac
fsubrp st(4),st(0) // iac,vac*yab,yab_invdx,f_du,vab*yac,iab*yac
fmulp st(2),st(0) // vac*yab,iac*yab,f_du,vab*yac,iab*yac
fsubp st(3),st(0) // iac*yab,f_du,f_dv,iab*yac
fxch st(1) // f_du,iac*yab,f_dv,iab*yac
// stall(1)
fstp f_du // iac*yab,f_dv,iab*yac
fsubp st(2),st(0) // f_dv,f_di_invdx
fstp f_dv // f_di_invdx
// stall(1)
fstp f_di_invdx // fp stack empty
test eax,eax
jz COPY_UV
//
// SetMinAbs(fDUInvZ, f_duinvz);
// SetMinAbs(fDVInvZ, f_dvinvz);
//
mov eax,[f_du]
mov ebx,[fDU]
mov ecx,eax // copy f_du
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_U // same sign, compare abs. values
xor ecx,ecx // clear ecx
jmp SAVE_NEW_U // go store it
COMPARE_U:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge short SKIP_U_COPY
mov ecx,[f_du]
SAVE_NEW_U:
mov [fDU],ecx
SKIP_U_COPY:
mov eax,[f_dv]
mov ebx,[fDV]
mov ecx,eax // copy f_dv
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_V // same sign, compare abs. values
xor ecx,ecx // clear ecx
jmp SAVE_NEW_V // go store it
COMPARE_V:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge short SKIP_V_COPY
mov ecx,[f_dv]
SAVE_NEW_V:
mov [fDV],ecx
SKIP_V_COPY:
//
// if (CIntFloat(f_di_invdx).bSign() != CIntFloat(fDeltaXIntensity).bSign())
// {
// fDeltaXIntensity = 0.0f;
// fxDeltaXIntensity = 0;
// goto SKIP_INTENSITY_UPDATE;
// }
//
// if (fabs(f_di_invdx) >= fabs(fDeltaXIntensity))
// goto SKIP_INTENSITY_UPDATE;
//
mov eax,f_di_invdx
mov ebx,fDeltaXIntensity
mov ecx,eax // copy f_di_invdx
xor eax,ebx // xor sign bits
test eax,0x80000000 // test for sign bit.
jz COMPARE_INTENSITY // same sign, compare abs. values
xor eax,eax
mov fDeltaXIntensity,eax
mov fxDeltaXIntensity,eax
jmp SKIP_INTENSITY_UPDATE
COMPARE_INTENSITY:
and ecx,0x7fffffff
and ebx,0x7fffffff
cmp ecx,ebx
jge short SKIP_INTENSITY_UPDATE
jmp short DONE_WITH_COPY
COPY_UV:
//
// fDU = f_du
// fDV = f_dv
//
mov eax,[f_du]
mov ebx,[f_dv]
mov [fDU],eax
mov [fDV],ebx
DONE_WITH_COPY:
//
// fDeltaXIntensity = f_di_invdx;
//
// Clamp(fDeltaXIntensity, 16.0f);
//
// Convert to fixed point representation.
//
// fxDeltaXIntensity.fxFromFloat(fDeltaXIntensity);
//
fld f_di_invdx // Load intensity (assuming no clamp).
fadd dFloatToFixed16 // Add integer conversion constant.
mov eax,f_di_invdx // Load value.
mov ecx,fSIXTEEN // Load clamp value.
mov ebx,eax // Copy value for sign.
mov edx,eax // Keep orignal value.
and eax,0x7fffffff // Mask off sign bit.
and ebx,0x80000000 // Keep just the sign bit.
cmp eax,ecx // Compare against 16.0
jle short NO_INTENSITY_CLAMP
//
// Clamp value. This is a relatively rare case.
//
fcomp st(0) // Dump unclamped value.
mov edx,ecx // Clamp value.
or edx,ebx // Keep sign bit.
mov f_di_invdx,edx // Save clamped value.
fld f_di_invdx // Load clamped intensity.
fadd dFloatToFixed16 // Add integer conversion constant.
// stall(3)
NO_INTENSITY_CLAMP:
fstp d_temp_a // Store fixed point value.
mov fDeltaXIntensity,edx // Save updated, possibly clamped value.
mov eax,dword ptr[d_temp_a] // Load fixed point value.
mov fxDeltaXIntensity,eax // Save fixed point value.
SKIP_INTENSITY_UPDATE:
}
return true;
RETURN_FALSE:
return false;
}
//*****************************************************************************************
//
inline bool GenericInitGradientDataPlanar(CDrawPolygonBase* poly, bool b_altpersp)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
// These are saved for the best edge pair.
SRenderVertex *prv_a;
SRenderVertex *prv_b;
SRenderVertex *prv_c;
float f_dx;
float f_invdx;
__asm
{
//
// Find the first edge pair with an area greater than 25 pixels, or if no
// edge pair has an area greater than 25 pixels find the maximum.
//
// Set starting vertices [N-2, N-1, 0].
lea edi,[arvRasterVertices] // prv_c = edi = a[n]
mov ecx,[iNumRasterVertices]
mov eax,SIZE SRenderVertex
dec ecx
imul eax,ecx
lea edx,[edi + eax] // prv_b = esi = a[n-1]
mov esi,edx
sub edx,SIZE SRenderVertex // prv_a = edx = a[n-2]
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab,f_yac
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_xab,f_yac
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_yab,f_xab,f_yac
fxch st(3) // f_yac,f_yab,f_xab,f_xac
fmulp st(2),st(0) // f_yab,f_xab*f_yac,f_xac
// 1 cycle stall
fmulp st(2),st(0) // f_xab*f_yac,f_xac*f_yab
// 2 cycle stall
fsubrp st(1),st(0) // f_xab*f_yac - f_xac*f_yab
// 3 cycle stall
mov [prv_c],edi
mov [prv_b],esi
mov [prv_a],edx
fstp [f_dx] // Assume this is best.
mov eax,[f_dx]
mov ebx,[fNegativeFifty]
cmp eax,ebx // If our best < -50, then stop
ja EXIT_LOOP
EDGE_LOOP:
mov edx,esi // prv_a = prv_b
mov esi,edi // prv_b = prv_c
add edi,SIZE SRenderVertex // prv_c = next vertex
//
// float f_yab = (prv_b->v3Screen.tY - prv_a->v3Screen.tY);
// float f_yac = (prv_c->v3Screen.tY - prv_a->v3Screen.tY);
//
// float f_dx = (prv_b->v3Screen.tX - prv_a->v3Screen.tX) * f_yac -
// (prv_c->v3Screen.tX - prv_a->v3Screen.tX) * f_yab;
//
fld [esi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xab
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yac,f_xab
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // f_yab,f_yac,f_xab
fld [edi]SRenderCoord.v3Screen.tX
fsub [edx]SRenderCoord.v3Screen.tX // f_xac,f_yab,f_yac,f_xab
fxch st(2) // f_yac,f_yab,f_xac,f_xab
fmulp st(3),st(0) // f_yab,f_xac,f_xab*f_yac
// 1 cycle stall
fmulp st(1),st(0) // f_xac*f_yab,f_xab*f_yac
// 2 cycle stall
fsubp st(1),st(0) // f_xab*f_yac - f_xac*f_yab
// 3 cycle stall
fcom [f_dx] // Is this smaller than f_dx
fnstsw ax
test eax,0x0100 // ST < Operand
jnz NEW_MINIMUM
// No, discard f_dx
fcomp st(0)
dec ecx
jnz EDGE_LOOP
jmp short EXIT_LOOP
NEW_MINIMUM:
// Yes, save f_dx and vertex pointers.
fstp [f_dx]
mov [prv_a],edx
mov [prv_b],esi
mov [prv_c],edi
mov eax,[f_dx]
cmp eax,ebx // If our best < -50, then stop
ja EXIT_LOOP
dec ecx
jnz EDGE_LOOP
EXIT_LOOP:
//
// Is the polygon too small to draw?
// if (f_dx >= fMAX_NEG_AREA) goto RETURN_FALSE;
//
mov eax,[f_dx]
mov ebx,[fMAX_NEG_AREA]
cmp eax,ebx
jbe RETURN_FALSE
//
// Initialize the texture gradients based on the best edge.
//
// float f_invdx = 1.0f / f_dx;
// float f_yab_invdx = f_yab * f_invdx;
// float f_yac_invdx = f_yac * f_invdx;
//
// float f_duinvz = (prv_b->tcTex.tX - prv_a->tcTex.tX) * f_yac_invdx -
// (prv_c->tcTex.tX - prv_a->tcTex.tX) * f_yab_invdx;
//
// float f_dvinvz = (prv_b->tcTex.tY - prv_a->tcTex.tY) * f_yac_invdx -
// (prv_c->tcTex.tY - prv_a->tcTex.tY) * f_yab_invdx;
//
// float f_dinvz = (prv_b->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yac_invdx -
// (prv_c->v3Screen.tZ - prv_a->v3Screen.tZ) * f_yab_invdx;
//
mov edx,[prv_a]
mov esi,[prv_b]
mov ebx,dword ptr[f_dx]
mov eax,iFI_SIGN_EXPONENT_SUB
sub eax,ebx
and ebx,iFI_MASK_MANTISSA
sar ebx,iSHIFT_MANTISSA
and eax,iFI_MASK_SIGN_EXPONENT
// One iteration of Newton-Raphson doubles the number of bits of accuary.
fld [f_dx]
add eax,dword ptr[i4InverseMantissa + ebx*4]
mov edi,[prv_c]
mov dword ptr[f_invdx],eax
fmul [f_invdx] // (v*r)
fld [esi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // yab (v*r)
fxch st(1) // (v*r) yab
fsubr [fTWO] // (2.0 - v*r) yab
fld [edi]SRenderCoord.v3Screen.tY
fsub [edx]SRenderCoord.v3Screen.tY // yac (2.0 - v*r) yab
fxch st(1) // (2.0 - v*r) yac yab
fmul [f_invdx] // (2.0 - v*r)*r yac yab
fld [esi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // uab invdx yac yab
fxch st(2) // yac invdx uab yab
fmul st(0),st(1) // yac*invdx invdx uab yab
fld [edi]SRenderVertex.tcTex.tX
fsub [edx]SRenderVertex.tcTex.tX // uac yac*invdx invdx uab yab
fxch st(2) // invdx yac*invdx uac uab yab
fmulp st(4),st(0) // yac*invdx uac uab yab*invdx
fld [esi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // vab yac_invdx uac uab yab_invdx
fxch st(1) // yac_invdx vab uac uab yab_invdx
fmul st(3),st(0) // yac_invdx vab uac uab*yac_invdx yab_invdx
fld [edi]SRenderVertex.tcTex.tY
fsub [edx]SRenderVertex.tcTex.tY // vac yac_invdx vab uac uab*yac_invdx yab_invdx
fxch st(3) // uac yac_invdx vab vac uab*yac_invdx yab_invdx
fmul st(0),st(5) // uac*yab_invdx yac_invdx vab vac uab*yac_invdx yab_invdx
fld [esi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zab uac*yab_invdx yac_invdx vab vac uab*yac_invdx yab_invdx
fxch st(3) // vab uac*yab_invdx yac_invdx zab vac uab*yac_invdx yab_invdx
fmul st(0),st(2) // vab*yac_invdx uac*yab_invdx yac_invdx zab vac uab*yac_invdx yab_invdx
fxch st(5) // uab*yac_invdx uac*yab_invdx yac_invdx zab vac vab*yac_invdx yab_invdx
fsubrp st(1),st(0) // duinvz yac_invdx zab vac vab*yac_invdx yab_invdx
fxch st(3) // vac yac_invdx zab duinvz vab*yac_invdx yab_invdx
fmul st(0),st(5) // vac*yab_invdx yac_invdx zab duinvz vab*yac_invdx yab_invdx
fld [edi]SRenderCoord.v3Screen.tZ
fsub [edx]SRenderCoord.v3Screen.tZ // zac vac*yab_invdx yac_invdx zab duinvz vab*yac_invdx yab_invdx
fxch st(3) // zab vac*yab_invdx yac_invdx zac duinvz vab*yac_invdx yab_invdx
fmulp st(2),st(0) // vac*yab_invdx zab*yac_invdx zac duinvz vab*yac_invdx yab_invdx
fsubp st(4),st(0) // zab*yac_invdx zac duinvz dvinvz yab_invdx
fxch st(1) // zac zab*yac_invdx duinvz dvinvz yab_invdx
fmulp st(4),st(0) // zab*yac_invdx duinvz dvinvz zac*yab_invdx
fxch st(1) // duinvz zab*yac_invdx dvinvz zac*yab_invdx
fstp [fDUInvZ] // zab*yac_invdx dvinvz zac*yab_invdx
fsubrp st(2),st(0) // dvinvz dzinvz
fstp [fDVInvZ]
fstp [fDInvZ]
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = persetSettings.iGetSubdivisionLen(fDInvZ, b_altpersp);
fInvSubdivideLen = fUnsignedInverseInt(iSubdivideLen);
return true;
RETURN_FALSE:
return false;
}
#endif // #else // #if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
//*****************************************************************************************
//
// InitlizePolygonData routines for each scanline type.
//
//*****************************************************************************************
//*****************************************************************************************
//
void InitializePolygonData(TCopyPersp& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyPersp.
//
//**************************************
{
GenericInitializePolygonData(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TCopyPerspTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyPerspTrans.
//
//**************************************
{
GenericInitializePolygonData(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TCopyTerrainPersp& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyTerrainPersp.
//
//**************************************
{
GenericInitializePolygonData(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTexturePersp& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexturePersp.
//
//**************************************
{
GenericInitializePolygonDataFlat(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTexturePerspTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexturePerspTrans.
//
//**************************************
{
GenericInitializePolygonDataFlat(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTexturePerspGour& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexturePerspGour.
//
//**************************************
{
GenericInitializePolygonDataGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTexturePerspTransGour& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexturePerspTransGour.
//
//**************************************
{
GenericInitializePolygonDataGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TBumpPersp& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TBumpPersp.
//
//**************************************
{
GenericInitializePolygonDataBump(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TBumpPerspTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TBumpPerspTrans.
//
//**************************************
{
GenericInitializePolygonDataBump(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TGFogPersp& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TGFogPersp.
//
//**************************************
{
GenericInitializePolygonDataGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TCopyLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyLinear.
//
//**************************************
{
GenericInitializePolygonDataLinear(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TCopyLinearTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyLinearTrans.
//
//**************************************
{
GenericInitializePolygonDataLinear(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TCopyTerrainLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TCopyTerrainLinear.
//
//**************************************
{
GenericInitializePolygonDataLinear(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTextureLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTextureLinear.
//
//**************************************
{
GenericInitializePolygonDataLinearFlat(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTextureLinearTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTextureLinearTrans.
//
//**************************************
{
GenericInitializePolygonDataLinearFlat(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTextureLinearGour& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTextureLinearGour.
//
//**************************************
{
GenericInitializePolygonDataLinearGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTextureLinearTransGour& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTextureLinearTransGour.
//
//**************************************
{
GenericInitializePolygonDataLinearGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TBumpLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TBumpLinear.
//
//**************************************
{
GenericInitializePolygonDataLinearBump(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TBumpLinearTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TBumpLinearTrans.
//
//**************************************
{
GenericInitializePolygonDataLinearBump(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TGFogLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TGFogLinear.
//
//**************************************
{
GenericInitializePolygonDataLinearGour(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TTexNoClutLinearTrans& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexNoClutLinearTrans.
//
//**************************************
{
#if (NORMALIZE_TERRAIN_OBJECT_TEXTURE_COORDS)
CPArray<SRenderVertex*> parv_all = rpoly->paprvPolyVertices;
ptr_const<CTexture> ptex = rpoly->ptexTexture;
TClutVal cv_face = rpoly->cvFace;
int i_mip_level = rpoly->iMipLevel;
// Copy screen coords to our local vertices.
Assert(parv_all.uLen <= iMAX_RASTER_VERTICES);
// Initialize polygon-wide variables for index coordinates.
lineData.indCoord.InitializePolygonData(ptex, i_mip_level);
// Set the base address for the clut.
lineData.SetClutAddress(ptex);
if (bClampUV)
{
for (int i = 0; i < parv_all.uLen; i++)
{
arvRasterVertices[i].v3Screen = parv_all[i]->v3Screen;
arvRasterVertices[i].iYScr = iPosFloatCast(arvRasterVertices[i].v3Screen.tY);
arvRasterVertices[i].tcTex.tX = parv_all[i]->tcTex.tX * fTexWidth + fTexEdgeTolerance;
arvRasterVertices[i].tcTex.tY = parv_all[i]->tcTex.tY * fTexHeight + fTexEdgeTolerance;
}
}
else
{
// Find offsets to normalize range of texture co-ordinates.
float fMinU = parv_all[0]->tcTex.tX;
float fMinV = parv_all[0]->tcTex.tY;
int i;
for (i = 1; i < parv_all.uLen; i++)
{
if (fMinU > parv_all[i]->tcTex.tX)
fMinU = parv_all[i]->tcTex.tX;
if (fMinV > parv_all[i]->tcTex.tY)
fMinV = parv_all[i]->tcTex.tY;
}
float fAdjU = floor(fMinU);
float fAdjV = floor(fMinV);
for (i = 0; i < parv_all.uLen; i++)
{
arvRasterVertices[i].v3Screen = parv_all[i]->v3Screen;
arvRasterVertices[i].iYScr = iPosFloatCast(arvRasterVertices[i].v3Screen.tY);
arvRasterVertices[i].tcTex.tX = (parv_all[i]->tcTex.tX - fAdjU) * fTexWidth;
arvRasterVertices[i].tcTex.tY = (parv_all[i]->tcTex.tY - fAdjV) * fTexHeight;
}
}
#else
GenericInitializePolygonDataLinear(rpoly);
#endif
}
//*****************************************************************************************
//
void InitializePolygonData(TTexNoClutLinear& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TTexNoClutLinear.
//
//**************************************
{
#if (NORMALIZE_TERRAIN_OBJECT_TEXTURE_COORDS)
CPArray<SRenderVertex*> parv_all = rpoly->paprvPolyVertices;
ptr_const<CTexture> ptex = rpoly->ptexTexture;
TClutVal cv_face = rpoly->cvFace;
int i_mip_level = rpoly->iMipLevel;
// Copy screen coords to our local vertices.
Assert(parv_all.uLen <= iMAX_RASTER_VERTICES);
// Initialize polygon-wide variables for index coordinates.
lineData.indCoord.InitializePolygonData(ptex, i_mip_level);
// Set the base address for the clut.
lineData.SetClutAddress(ptex);
if (bClampUV)
{
for (int i = 0; i < parv_all.uLen; i++)
{
arvRasterVertices[i].v3Screen = parv_all[i]->v3Screen;
arvRasterVertices[i].iYScr = iPosFloatCast(arvRasterVertices[i].v3Screen.tY);
arvRasterVertices[i].tcTex.tX = parv_all[i]->tcTex.tX * fTexWidth + fTexEdgeTolerance;
arvRasterVertices[i].tcTex.tY = parv_all[i]->tcTex.tY * fTexHeight + fTexEdgeTolerance;
}
}
else
{
// Find offsets to normalize range of texture co-ordinates.
float fMinU = parv_all[0]->tcTex.tX;
float fMinV = parv_all[0]->tcTex.tY;
int i;
for (i = 1; i < parv_all.uLen; i++)
{
if (fMinU > parv_all[i]->tcTex.tX)
fMinU = parv_all[i]->tcTex.tX;
if (fMinV > parv_all[i]->tcTex.tY)
fMinV = parv_all[i]->tcTex.tY;
}
float fAdjU = floor(fMinU);
float fAdjV = floor(fMinV);
for (i = 0; i < parv_all.uLen; i++)
{
arvRasterVertices[i].v3Screen = parv_all[i]->v3Screen;
arvRasterVertices[i].iYScr = iPosFloatCast(arvRasterVertices[i].v3Screen.tY);
arvRasterVertices[i].tcTex.tX = (parv_all[i]->tcTex.tX - fAdjU) * fTexWidth;
arvRasterVertices[i].tcTex.tY = (parv_all[i]->tcTex.tY - fAdjV) * fTexHeight;
}
}
#else
GenericInitializePolygonDataLinear(rpoly);
#endif
}
//*****************************************************************************************
//
void InitializePolygonData(TShadowTrans8& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TShadowTrans8.
//
//**************************************
{
GenericInitializePolygonDataLinear(rpoly);
}
//*****************************************************************************************
//
void InitializePolygonData(TShadowTrans32& lineData, CRenderPolygon* rpoly)
//
// Scanline data initialization specialized for TShadowTrans32.
//
//**************************************
{
GenericInitializePolygonDataLinear(rpoly);
}
#if (BILINEAR_FILTER)
void InitializePolygonData(TCopyPerspFilter& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonData(rpoly);
}
void InitializePolygonData(TCopyLinearFilter& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonDataLinear(rpoly);
}
#endif
void InitializePolygonData(TStippleTexPersp& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonData(rpoly);
}
void InitializePolygonData(TStippleTexLinear& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonDataLinear(rpoly);
}
void InitializePolygonData(TWaterPersp& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonData(rpoly);
}
void InitializePolygonData(TWaterLinear& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonDataLinear(rpoly);
}
void InitializePolygonData(TAlphaTexPersp& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonData(rpoly);
}
void InitializePolygonData(TAlphaTexLinear& lineData, CRenderPolygon* rpoly)
{
GenericInitializePolygonDataLinear(rpoly);
}
//*****************************************************************************************
//
// InitializeEdge routines for each scanline type.
//
//*****************************************************************************************
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyPersp>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyPersp>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyPerspTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyPerspTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyTerrainPersp>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyTerrainPersp>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexturePersp>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexturePersp>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexturePerspTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexturePerspTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexturePerspGour>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexturePerspGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexturePerspTransGour>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexturePerspTransGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TBumpPersp>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TBumpPersp>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TBumpPerspTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TBumpPerspTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TGFogPersp>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TGFogPersp>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyLinear>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyLinearTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyLinearTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TCopyTerrainLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TCopyTerrainLinear>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTextureLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinear>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTextureLinearTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinearTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTextureLinearGour>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinearGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTextureLinearTransGour>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinearTransGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TBumpLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinearTransGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TBumpLinearTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTextureLinearTransGour>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TGFogLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TGFogLinear>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexNoClutLinear>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexNoClutLinear>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TTexNoClutLinearTrans>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TTexNoClutLinearTrans>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TShadowTrans8>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TShadowTrans8>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
void InitializeEdge
(
CEdge<TShadowTrans32>& edge, // The edge to initialize.
SRenderVertex* prv_from, // Starting coordinate of edge.
SRenderVertex* prv_to // End coordinate of edge.
)
//
// Specialzed replacement for CEdge<TShadowTrans32>::IntializeEdge
//
//**************************************
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
#if (BILINEAR_FILTER)
void InitializeEdge(CEdge<TCopyPerspFilter>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TCopyLinearFilter>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
#endif
void InitializeEdge(CEdge<TStippleTexPersp>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TStippleTexLinear>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TWaterPersp>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TWaterLinear>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TAlphaTexPersp>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
void InitializeEdge(CEdge<TAlphaTexLinear>& edge, SRenderVertex* prv_from, SRenderVertex* prv_to)
{
GenericInitializeEdge(edge, prv_from, prv_to);
}
//*****************************************************************************************
//
// bInitTriangleDataEx routines for each scanline type.
//
//*****************************************************************************************
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyPersp>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, true);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyPerspTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyTerrainPersp>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, true);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexturePersp>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexturePerspTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexturePerspGour>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataGour(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexturePerspTransGour>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataGour(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TBumpPersp>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TBumpPerspTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TGFogPersp>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataGour(poly, prv_a, prv_b, prv_c, b_update, true);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyLinearTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyTerrainLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTextureLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTextureLinearTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTextureLinearGour>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinearGour(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTextureLinearTransGour>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinearGour(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TBumpLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TBumpLinearTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TGFogLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinearGour(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexNoClutLinear>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TTexNoClutLinearTrans>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TShadowTrans8>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
bool bInitTriangleDataEx
(
CDrawPolygon<TShadowTrans32>* poly,
SRenderVertex* prv_a, // 3 vertices making up this triangle.
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
//
// Sets up triangle-wide rasterising info.
//
// Returns:
// Whether the triangle is large enough to render.
//
//**************************************
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
#if (BILINEAR_FILTER)
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyPerspFilter>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TCopyLinearFilter>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
#endif
bool bInitTriangleDataEx
(
CDrawPolygon<TStippleTexPersp>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TStippleTexLinear>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TWaterPersp>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TWaterLinear>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TAlphaTexPersp>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleData(poly, prv_a, prv_b, prv_c, b_update, false);
}
bool bInitTriangleDataEx
(
CDrawPolygon<TAlphaTexLinear>* poly,
SRenderVertex* prv_a,
SRenderVertex* prv_b,
SRenderVertex* prv_c,
bool b_update
)
{
return GenericInitTriangleDataLinear(poly, prv_a, prv_b, prv_c, b_update);
}
//*****************************************************************************************
//
// bInitGradientDataPlanarEx routines for each scanline type.
//
//*****************************************************************************************
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TCopyPersp>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, true);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TCopyPerspTrans>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, false);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TCopyTerrainPersp>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, true);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TTexturePersp>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, false);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TTexturePerspTrans>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, false);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TBumpPersp>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, false);
}
//*****************************************************************************************
//
bool bInitGradientDataPlanarEx(CDrawPolygon<TBumpPerspTrans>* poly)
//
// Sets up polygon-wide rasterising info.
//
// Returns:
// Whether the polygon is large enough to render.
//
//**************************************
{
return GenericInitGradientDataPlanar(poly, false);
}
#if (BILINEAR_FILTER)
bool bInitGradientDataPlanarEx(CDrawPolygon<TCopyPerspFilter>* poly)
{
return GenericInitGradientDataPlanar(poly, false);
}
#endif
bool bInitGradientDataPlanarEx(CDrawPolygon<TStippleTexPersp>* poly)
{
return GenericInitGradientDataPlanar(poly, false);
}
bool bInitGradientDataPlanarEx(CDrawPolygon<TWaterPersp>* poly)
{
return GenericInitGradientDataPlanar(poly, false);
}
bool bInitGradientDataPlanarEx(CDrawPolygon<TAlphaTexPersp>* poly)
{
return GenericInitGradientDataPlanar(poly, false);
}
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
//*****************************************************************************************
//
// InitializeForWalkEx routines for each scanline type.
//
//*****************************************************************************************
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyPersp>* poly, CEdge<TCopyPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyPerspTrans>* poly, CEdge<TCopyPerspTrans>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyTerrainPersp>* poly, CEdge<TCopyTerrainPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexturePersp>* poly, CEdge<TTexturePersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexturePerspTrans>* poly, CEdge<TTexturePerspTrans>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexturePerspGour>* poly, CEdge<TTexturePerspGour>* pedge)
{
GenericInitializeForWalkGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexturePerspTransGour>* poly, CEdge<TTexturePerspTransGour>* pedge)
{
GenericInitializeForWalkGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TBumpPersp>* poly, CEdge<TBumpPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TBumpPerspTrans>* poly, CEdge<TBumpPerspTrans>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TGFogPersp>* poly, CEdge<TGFogPersp>* pedge)
{
GenericInitializeForWalkGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyLinear>* poly, CEdge<TCopyLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyLinearTrans>* poly, CEdge<TCopyLinearTrans>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TCopyTerrainLinear>* poly, CEdge<TCopyTerrainLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTextureLinear>* poly, CEdge<TTextureLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTextureLinearTrans>* poly, CEdge<TTextureLinearTrans>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTextureLinearGour>* poly, CEdge<TTextureLinearGour>* pedge)
{
GenericInitializeForWalkLinearGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTextureLinearTransGour>* poly, CEdge<TTextureLinearTransGour>* pedge)
{
GenericInitializeForWalkLinearGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TBumpLinear>* poly, CEdge<TBumpLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TBumpLinearTrans>* poly, CEdge<TBumpLinearTrans>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TGFogLinear>* poly, CEdge<TGFogLinear>* pedge)
{
GenericInitializeForWalkLinearGour(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexNoClutLinear>* poly, CEdge<TTexNoClutLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TTexNoClutLinearTrans>* poly, CEdge<TTexNoClutLinearTrans>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TShadowTrans8>* poly, CEdge<TShadowTrans8>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
void InitializeForWalkEx(CDrawPolygon<TShadowTrans32>* poly, CEdge<TShadowTrans32>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
#if (BILINEAR_FILTER)
void InitializeForWalkEx(CDrawPolygon<TCopyPerspFilter>* poly, CEdge<TCopyPerspFilter>* pedge)
{
// Use the same routine as TCopyPersp.
GenericInitializeForWalk(reinterpret_cast<CDrawPolygon<TCopyPersp>*>(poly), reinterpret_cast<CEdge<TCopyPersp>*>(pedge));
}
void InitializeForWalkEx(CDrawPolygon<TCopyLinearFilter>* poly, CEdge<TCopyLinearFilter>* pedge)
{
// Use the same routine as TCopyLinear.
GenericInitializeForWalkLinear(reinterpret_cast<CDrawPolygon<TCopyLinear>*>(poly), reinterpret_cast<CEdge<TCopyLinear>*>(pedge));
}
#endif
void InitializeForWalkEx(CDrawPolygon<TStippleTexPersp>* poly, CEdge<TStippleTexPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
void InitializeForWalkEx(CDrawPolygon<TStippleTexLinear>* poly, CEdge<TStippleTexLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
void InitializeForWalkEx(CDrawPolygon<TWaterPersp>* poly, CEdge<TWaterPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
void InitializeForWalkEx(CDrawPolygon<TWaterLinear>* poly, CEdge<TWaterLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
void InitializeForWalkEx(CDrawPolygon<TAlphaTexPersp>* poly, CEdge<TAlphaTexPersp>* pedge)
{
GenericInitializeForWalk(poly, pedge);
}
void InitializeForWalkEx(CDrawPolygon<TAlphaTexLinear>* poly, CEdge<TAlphaTexLinear>* pedge)
{
GenericInitializeForWalkLinear(poly, pedge);
}
//*****************************************************************************************
//
// DoneDrawingPolygon routines for each scanline type.
//
//*****************************************************************************************
void DoneDrawingPolygon(CDrawPolygon<TCopyPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyPerspTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyTerrainPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexturePersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexturePerspTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexturePerspGour>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexturePerspTransGour>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TBumpPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TBumpPerspTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TGFogPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyLinearTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyTerrainLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTextureLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTextureLinearTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTextureLinearGour>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTextureLinearTransGour>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TBumpLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TBumpLinearTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TGFogLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexNoClutLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TTexNoClutLinearTrans>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TShadowTrans8>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TShadowTrans32>* poly)
{
// Empty MMX state.
__asm femms
}
#if (BILINEAR_FILTER)
void DoneDrawingPolygon(CDrawPolygon<TCopyPerspFilter>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TCopyLinearFilter>* poly)
{
// Empty MMX state.
__asm femms
}
#endif
void DoneDrawingPolygon(CDrawPolygon<TStippleTexPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TStippleTexLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TWaterPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TWaterLinear>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TAlphaTexPersp>* poly)
{
// Empty MMX state.
__asm femms
}
void DoneDrawingPolygon(CDrawPolygon<TAlphaTexLinear>* poly)
{
// Empty MMX state.
__asm femms
}
#endif // #if (TARGET_PROCESSOR == PROCESSOR_K6_3D)