JurassicParkTrespasser/jp2_pc/Source/Lib/Renderer/Primitives/IndexPerspectiveT.hpp
2018-01-01 23:07:24 +01:00

1135 lines
28 KiB
C++

/***********************************************************************************************
*
* Copyright © DreamWorks Interactive. 1996
*
* Contents:
*
* Notes:
*
* To Do:
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/IndexPerspectiveT.hpp $
*
* 56 98.09.19 12:39a Mmouni
* Added "forceinline" to many small inline functions.
* Inlined some functions for speed.
*
* 55 98.08.02 7:25p Mmouni
* Changed default adaptive min to 16.
*
* 54 98.07.21 8:21p Mmouni
* Adaptive perspective correction is now on by default.
* Change adaptive default values.
*
* 53 98.07.17 6:30p Mmouni
* Added new adaptive perspective stuff.
*
* 52 98.04.24 6:59p Mmouni
* Changed alternate perspective correction setting.
*
* 51 98.03.24 8:17p Mmouni
* Made changes to support alternate perspective correction settings.
*
* 50 98.01.14 9:08p Mmouni
* Made changes for K6 3D polygon setup optimizations.
*
* 49 97.11.14 11:54p Mmouni
* Added CIndexPerspectiveFilter index type.
*
* 48 97.11.04 10:21p Mmouni
* Spelling corrections.
*
* 47 97.10.30 11:18a Mmouni
* iGetSubdivisionLen was using the wrong variable for insuring the subdivision length chosen is
* even.
*
* 46 97.10.27 1:27p Mmouni
* Made changes to support the K6-3D.
*
* 45 97/10/23 10:56a Pkeet
* Added a K6 3D switch.
*
* 44 97.10.15 7:41p Mmouni
* Removed support for right to left scanlines.
*
* 43 10/10/97 1:44p Mmouni
* Now gets fTexWith, fTexHeight directly from texture.
*
* 42 9/29/97 11:12a Mmouni
* Now calculates values to support aligment in first texture correction span.
* Calculated correction spans are now always a power of 2.
*
* 41 9/15/97 2:02p Mmouni
* Added dFastFixed16Conversion constant.
* Now takes into account clamp flag when calculating fTexWidth, fTexheight.
*
* 40 9/01/97 8:00p Rwyatt
* GetIndex member is and-ed with the texture tile mask to enable tiling
*
* 39 97/08/17 4:14p Pkeet
* Added the 'BuildTileMask' member function.
*
* 38 8/17/97 12:18a Agrant
* Put texture coord clamping on a VER switch.
*
* 37 8/15/97 12:50a Rwyatt
* Added externs for new global perspective constants.
*
* 36 97/08/07 11:35a Pkeet
* Added interface support for mipmapping.
*
* 35 97/08/06 3:20p Pkeet
* Added mipmapping interface.
*
* 34 97/08/05 14:19 Speter
* Slightly optimised polygon vertex setup by adding InitializeVertexData() functions.
*
* 33 97/07/17 5:09p Pkeet
* Turned adaptive subdivision off.
*
* 32 97/07/16 15:54 Speter
* InitializeTriangleData now takes two params to use as coefficients in derivative calculation
* rather than f_invdx; also takes b_update parameter to use for multiple-triangle gradient
* calculations. Added AssertXRange function to test the validity of a single scanline.
*
* 31 7/07/97 11:53p Rwyatt
* No includes headers that contain assembly code from the processor specific directories
*
* 30 97/07/07 14:05 Speter
* Now copy vertices for current polygon locally to arvRasterVertices, and set tcTex to scaled
* coordinates.
*
* 29 97/06/27 15:34 Speter
* Moved code to new InitializePolygonData(), added bIsPlanar(). Added fD[U||V]InvEdge
* variables, needed for multiple base edges per polygon.
*
* 28 97/06/27 2:03p Pkeet
* Changed default values for a better-looking fit.
*
* 27 97/06/24 1:59p Pkeet
* Added adaptive subdivision.
*
* 26 6/19/97 2:53p Mlange
* Moved Profile.hpp to Lib/Sys.
*
* 25 97/06/16 11:06p Pkeet
* Changed default subdivision setting.
*
* 24 97/06/03 18:48 Speter
* Added bIsPerspective() member.
*
* 23 97-03-31 22:21 Speter
* Removed pvGetTexture() function, placed code into InitializeTriangleData().
*
*
* 22 1/27/97 9:04p Pkeet
* Changed default subdivision value to 20.
*
* 21 1/16/97 1:35p Pkeet
* Changed the default subdivision length to 16.
*
* 20 1/15/97 1:09p Pkeet
* Added the 'i4StartSubdivision' member function. Simplified the UpdatePerspective function.
*
* 19 1/09/97 5:12p Pkeet
* Moved assembly code to a separate file in the 'P5' subdirectory. Fixed bugs associated with
* compilation under Visual C++ 5.0.
*
* 18 97/01/07 12:05 Speter
* Updated for ptr_const.
*
* 17 1/03/97 4:41p Pkeet
* Added the 'iSubdivideLen' and 'fInvSubdivideLen' globals.
*
* 16 96/12/31 17:04 Speter
* Changed some pointers to ptr<>.
*
* 15 12/16/96 12:36p Pkeet
* More optimizations.
*
* 14 12/15/96 4:36p Pkeet
* More optimizations.
*
* 13 12/15/96 4:04p Pkeet
* Converted the entire initialization function to assembly.
*
* 12 12/15/96 3:19p Pkeet
* More optimizations.
*
* 11 12/12/96 7:40p Pkeet
* More conversions to assembly.
*
* 10 12/12/96 2:53p Pkeet
* Changed subdivision length from 8 to 12.
*
* 9 12/12/96 11:55a Pkeet
* Added more assembly code.
*
* 8 12/11/96 10:29p Pkeet
* Converted more member functions to assembly.
*
* 7 12/11/96 5:15p Pkeet
* Initial code for the subdivision set up to optionally use the fast inverse approximation or
* the fdiv instruction.
*
* 6 12/11/96 3:55p Pkeet
* Overlapping fdiv done.
*
* 5 12/11/96 2:51p Pkeet
* Removed unnecessary code.
*
* 4 12/11/96 2:22p Pkeet
* Enabled subdivision using the fast inverse function.
*
* 3 12/10/96 10:40a Pkeet
* Made perspective correction occur every eight pixels.
*
* 2 12/09/96 4:10p Pkeet
* Implemented perspective correction using floats.
*
* 1 12/09/96 3:50p Pkeet
* Initial implementation. Converted all values to use floats instead of big fixed point
* numbers.
*
**********************************************************************************************/
#ifndef HEADER_LIB_RENDERER_PRIMITIVES_INDEXPERSPECTIVET_HPP
#define HEADER_LIB_RENDERER_PRIMITIVES_INDEXPERSPECTIVET_HPP
//
// Defines.
//
// Define the maximum scanline length to subdivide over.
#define iDEFAULT_SUBDIVIDELEN (32)
// Define the minimum scanline subdivision length.
#define iDEFAULT_MIN_SUBDIVIDELEN (32)
#define iDEFAULT_ALT_MIN_SUBDIVIDELEN (64)
// Maximum scanline subdivision length.
#define iMAX_SUBDIVIDELEN (iNUM_ENTRIES_INVERSEINT - 2)
// Switch to use the fast inverse subdivision.
#define bUSE_FAST_INVERSE (false)
// Constants for fast conversions.
#define iBITS_ACCURACY 11
//const float fFixed16Scale = 65536.0;
const float fFastFixed16Conversion = float(1 << (23 - iBITS_ACCURACY));
// Constant to add for low dword of a double to be signed 16.16 fixed.
const double dFastFixed16Conversion = 103079215104.0;
//
// Includes.
//
#include "Config.hpp"
#include "Lib/Sys/Profile.hpp"
#include "Lib/Math/FloatDef.hpp"
#include "Lib/Math/FastInverse.hpp"
//
// A vector of three float values used for perspective correction.
// These must be allocated together for 3dx/mmx.
//
struct TexVals
{
float UInvZ;
float VInvZ;
float InvZ;
};
//
// Externally defined globals.
//
extern int iTexWidth;
extern float fDUInvZScanline;
extern float fDVInvZScanline;
extern float fDInvZScanline;
extern const float fFixed16Scale;
extern const float fOne;
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
extern TexVals tvDeltas;
#define fDUInvZ tvDeltas.UInvZ
#define fDVInvZ tvDeltas.VInvZ
#define fDInvZ tvDeltas.InvZ
extern TexVals tvDEdge;
#define fDUInvZEdge tvDEdge.UInvZ
#define fDVInvZEdge tvDEdge.VInvZ
#define fDInvZEdge tvDEdge.InvZ
#else
extern float fDUInvZ;
extern float fDVInvZ;
extern float fDInvZ;
extern float fDUInvZEdge;
extern float fDVInvZEdge;
extern float fDInvZEdge;
#endif
extern float fDUInvZEdgeMinusOne;
extern float fDVInvZEdgeMinusOne;
extern float fDInvZEdgeMinusOne;
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
extern TexVals tvNegAdj;
#define fNegUInvZ tvNegAdj.UInvZ
#define fNegVInvZ tvNegAdj.VInvZ
#define fNegInvZ tvNegAdj.InvZ
#else
extern float fNegUInvZ;
extern float fNegVInvZ;
extern float fNegInvZ;
#endif
extern float fGUInvZ;
extern float fGVInvZ;
extern float fGInvZ;
#if (TARGET_PROCESSOR == PROCESSOR_K6_3D)
extern ClampVals cvMaxCoords;
#define fTexWidth cvMaxCoords.U
#define fTexHeight cvMaxCoords.V
#else
extern float fTexWidth;
extern float fTexHeight;
#endif
extern float fU, fNextU;
extern float fV, fNextV;
extern int iNextSubdivide;
extern int iCacheNextSubdivide;
extern int32 i4ScanlineDirection;
extern CWalk2D w2dTex;
extern CWalk2D w2dDeltaTex;
// Inverse subdivision length.
extern float fInvSubdivideLen;
// Subdivision length.
extern int iSubdivideLen;
//*********************************************************************************************
//
class CPerspectiveSettings
//
// Object encapsulates settings and functions for perspective correction subdivision.
//
// Prefix: perset
//
//**************************************
{
public:
bool bAdaptive; // Use adaptive subdivision.
// Adaptive settings.
int iAdaptiveMinSubdivision; // Adaptive mininum subdivision size.
int iAdaptiveMaxSubdivision; // Adaptive maximimum subdivision size.
float fInvZForMaxSubdivision; // 1/Z delta where maximum is used.
float fInvZScale; // Scale for 1/z delta.
// Non-adaptive settings.
int iMinSubdivision; // Mininum subdivision size.
int iAltMinSubdivision; // Alternative mininum subdivision size.
//*****************************************************************************************
//
// Constructor.
//
CPerspectiveSettings()
{
// Default settings.
bAdaptive = true;
iAdaptiveMinSubdivision = 16;
iAdaptiveMaxSubdivision = 64;
fInvZForMaxSubdivision = 1e-6f;
fInvZScale = 1e7f;
iMinSubdivision = iDEFAULT_MIN_SUBDIVIDELEN;
iAltMinSubdivision = iDEFAULT_ALT_MIN_SUBDIVIDELEN;
}
//*****************************************************************************************
//
// Member functions.
//
//*****************************************************************************************
//
forceinline int iGetSubdivisionLen
(
float f_dinvz,
int b_usealt
)
//
// Returns the number of pixels to subdivide over given an inverse Z delta.
//
//**************************************
{
int i_subdivisionlen;
// Use adaptive value?
if (bAdaptive)
{
// Use positive values only.
f_dinvz = fabs(f_dinvz);
// If the value is too small, use max.
if (f_dinvz < fInvZForMaxSubdivision)
{
return iAdaptiveMaxSubdivision;
}
// Decrease the subdivision length based on the 1/z delta.
i_subdivisionlen = iAdaptiveMaxSubdivision -
Fist((f_dinvz - fInvZForMaxSubdivision) * fInvZScale);
// Make subdivision length a multiple of 2.
i_subdivisionlen &= 0xfffffffe;
// Keep the value from being too small.
if (i_subdivisionlen < iAdaptiveMinSubdivision)
return iAdaptiveMinSubdivision;
}
else
{
if (b_usealt)
i_subdivisionlen = iAltMinSubdivision;
else
i_subdivisionlen = iMinSubdivision;
}
// Return the value.
return i_subdivisionlen;
}
};
// Extern the settings so that everybody can access them.
extern CPerspectiveSettings persetSettings;
//
// Class definitions.
//
//*********************************************************************************************
//
class CIndexPerspective : public CIndex
//
// Prefix: ipls
//
//**************************************
{
public:
float fUInvZ;
float fVInvZ;
float fInvZ;
public:
//*****************************************************************************************
//
// CIndexPerspective constructors.
//
forceinline CIndexPerspective()
{
}
forceinline CIndexPerspective(const CIndexPerspective& index, int i_pixel)
{
// Copy the essential values.
fGUInvZ = index.fUInvZ;
fGVInvZ = index.fVInvZ;
fGInvZ = index.fInvZ;
fDUInvZScanline = fDUInvZEdge;
fDVInvZScanline = fDVInvZEdge;
fDInvZScanline = fDInvZEdge;
// Start the divide for the first scanline subdivision.
InitializeSubdivision(i_pixel);
}
//*****************************************************************************************
//
// CIndexPerspective member functions.
//
forceinline void Mask()
{
w2dTex.iUVInt[1] &= u4TextureTileMask;
}
//*****************************************************************************************
//
static forceinline bool bIsIndexed
(
)
//
//**************************************
{
return true;
}
//*****************************************************************************************
//
static forceinline bool bIsPerspective
(
)
//
//**************************************
{
return true;
}
//*****************************************************************************************
//
forceinline int i4StartSubdivision
(
int32& ri4_pixel // Pixel
)
//
// Returns zero.
//
//**************************************
{
int32 i4_retval;
if (ri4_pixel < 0)
{
if (-ri4_pixel > iSubdivideLen)
{
i4_retval = -iSubdivideLen;
ri4_pixel += iSubdivideLen;
}
else
{
i4_retval = ri4_pixel;
ri4_pixel = 0;
}
}
else
{
if (ri4_pixel > iSubdivideLen)
{
i4_retval = iSubdivideLen;
ri4_pixel -= iSubdivideLen;
}
else
{
i4_retval = ri4_pixel;
ri4_pixel = 0;
}
}
return i4_retval;
}
//*****************************************************************************************
//
void InitializeSubdivision
(
int i_pixel // Pixel position in the scanline.
);
//
// Returns the index value into the bitmap representing the position reference by the u and
// v values.
//
//**************************************
//*****************************************************************************************
//
forceinline int iSetNextDividePixel
(
int i_pixel // Pixel position in the scanline.
)
//
//
//
//**************************************
{
int i_next_subdivide;
i_next_subdivide = i_pixel + iSubdivideLen;
if (i_next_subdivide > 0)
{
i_next_subdivide = 0;
float f_ratio = fInvSubdivideLen * float(-i_pixel);
fDUInvZScanline *= f_ratio;
fDVInvZScanline *= f_ratio;
fDInvZScanline *= f_ratio;
}
return i_next_subdivide;
}
//*****************************************************************************************
//
void BeginNextSubdivision
(
);
//
// Returns the index value into the bitmap representing the position reference by the u and
// v values.
//
//**************************************
//*****************************************************************************************
//
void EndNextSubdivision
(
);
//
// Returns the index value into the bitmap representing the position reference by the u and
// v values.
//
//**************************************
//*****************************************************************************************
//
forceinline int iGetIndex
(
)
//
// Returns the index value into the bitmap representing the position reference by the u and
// v values.
//
//**************************************
{
w2dTex.iUVInt[1] &= u4TextureTileMask;
int i_index = w2dTex.iUVInt[1];
#if VER_CLAMP_UV_TILE
Assert(i_index >= 0);
Assert(i_index < iTexSize);
#endif
return i_index;
}
//*****************************************************************************************
//
forceinline void UpdatePerspective
(
int i_pixel
)
//
// Increments the u and v values for the next position on the horizontal scanline.
//
//**************************************
{
EndNextSubdivision();
}
//*****************************************************************************************
//
forceinline void operator++
(
)
//
// Increments the u and v values for the next position on the horizontal scanline.
//
//**************************************
{
w2dTex += w2dDeltaTex;
}
//*****************************************************************************************
//
forceinline void operator +=
(
const CIndexPerspective& rind_linear
)
//
// Adds two CLineLinearTexZ objects together and accumulates it in the calling object.
//
//**************************************
{
fUInvZ += rind_linear.fUInvZ;
fVInvZ += rind_linear.fVInvZ;
fInvZ += rind_linear.fInvZ;
}
//*****************************************************************************************
//
forceinline void operator -
(
)
//
// Negates the sign of the modulus subtraction factor.
//
//**************************************
{
fNegUInvZ = -fNegUInvZ;
fNegVInvZ = -fNegVInvZ;
fNegInvZ = -fNegInvZ;
}
//*****************************************************************************************
//
forceinline void ModulusSubtract
(
)
//
// Perform the modulus subtraction. Note that no '-=' operator is available, but that
// 'bfNegDU' and 'w1fNegDV' contain values that are already made negative.
//
//**************************************
{
fUInvZ += fNegUInvZ;
fVInvZ += fNegVInvZ;
fInvZ += fNegInvZ;
}
//*********************************************************************************************
//
static forceinline bool bIsPlanar()
//
// Returns:
// Whether this feature has planar gradients across any polygon.
//
//**********************************
{
return true;
}
//*********************************************************************************************
//
forceinline void InitializePolygonData
(
ptr_const<CTexture> ptex, // Texture for polygon.
int i_mip_level
)
//
//**************************************
{
rptr<CRaster> pras_texture = ptex->prasGetTexture(i_mip_level);
Assert(pras_texture);
// Build the texture mask.
BuildTileMask(pras_texture);
// Set a pointer to the texture.
pvTextureBitmap = pras_texture->pSurface;
Assert(pvTextureBitmap);
// Set the global texture width variable.
iTexWidth = pras_texture->iLinePixels;
// Initialize values used in debugging.
#if VER_DEBUG
iTexSize = pras_texture->iLinePixels * pras_texture->iHeight;
#endif
//
// Scale the texture coordinates according to the width and height of the texture.
//
fTexWidth = pras_texture->fWidth;
fTexHeight = pras_texture->fHeight;
}
//*********************************************************************************************
//
forceinline void InitializeVertexData
(
SRenderVertex* prv_src,
SRenderVertex* prv_dst
)
//
//**************************************
{
// Copy scaled, unprojected texture coords to our private vertices.
if (bClampUV)
{
prv_dst->tcTex.tX = (prv_src->tcTex.tX * fTexWidth + fTexEdgeTolerance) * prv_src->v3Screen.tZ;
prv_dst->tcTex.tY = (prv_src->tcTex.tY * fTexHeight + fTexEdgeTolerance) * prv_src->v3Screen.tZ;
}
else
{
prv_dst->tcTex.tX = (prv_src->tcTex.tX * fTexWidth) * prv_src->v3Screen.tZ;
prv_dst->tcTex.tY = (prv_src->tcTex.tY * fTexHeight) * prv_src->v3Screen.tZ;
}
}
//*****************************************************************************************
//
forceinline void InitializeTriangleData
(
SRenderVertex* prv_1, // First of three non-collinear coordinates describing the
// plane of the triangle in screen coordinates.
SRenderVertex* prv_2, // Second coordinate describing the plane.
SRenderVertex* prv_3, // Third coordinate describing the plane.
ptr_const<CTexture> ptex,
float f_yab_invdx, // Multipliers for gradients.
float f_yac_invdx,
bool b_update = false, // Modify the gradients rather than setting them.
bool b_altpersp = false // Use alternate perspecive settings.
)
//
// Initialize data used for the entire triangle, including converting texture coordinates
// from unit values in the range [0..1] to pixel values in the range [0..WifTh - 1] and
// [0..Height - 1], initializing the fDUInvZScanline and fDVInvZScanline values and finding the base address for the
// clut associated with the texture.
//
//**************************************
{
Assert(prv_1);
Assert(prv_2);
Assert(prv_3);
//
// Get the step values for u and v with respect to x.
//
float f_duinvz = (prv_2->tcTex.tX - prv_1->tcTex.tX) * f_yac_invdx -
(prv_3->tcTex.tX - prv_1->tcTex.tX) * f_yab_invdx;
float f_dvinvz = (prv_2->tcTex.tY - prv_1->tcTex.tY) * f_yac_invdx -
(prv_3->tcTex.tY - prv_1->tcTex.tY) * f_yab_invdx;
float f_dinvz = (prv_2->v3Screen.tZ - prv_1->v3Screen.tZ) * f_yac_invdx -
(prv_3->v3Screen.tZ - prv_1->v3Screen.tZ) * f_yab_invdx;
if (b_update)
{
//SetMinAbs(fDUInvZ, f_duinvz);
if (fabs(f_duinvz) < fabs(fDUInvZ))
fDUInvZ = f_duinvz;
//SetMinAbs(fDVInvZ, f_dvinvz);
if (fabs(f_dvinvz) < fabs(fDVInvZ))
fDVInvZ = f_dvinvz;
SetMax(fDInvZ, f_dinvz);
}
else
{
fDUInvZ = f_duinvz;
fDVInvZ = f_dvinvz;
fDInvZ = f_dinvz;
}
// Calculate the subdivision length with respect to X.
iSubdivideLen = persetSettings.iGetSubdivisionLen(fDInvZ, b_altpersp);
fInvSubdivideLen = fUnsignedInverseInt(iSubdivideLen);
}
//*****************************************************************************************
//
forceinline void InitializeAsBase
(
ptr_const<CTexture> ptex,
SRenderVertex* prv_from, // First of three non-collinear coordinates describing the
SRenderVertex* prv_to, // Second coordinate describing the plane.
CIndexPerspective& rind_linear_increment,
float f_inv_dy,
float f_x_diff_increment,
float f_x_diff_edge,
float f_y_diff_edge,
int i_mip_level
)
//
// Initializes the Z components of the edge, including starting position and edge w2ding
// increment.
//
// Notes:
// The subpixel calculation made in CEdge is applied here.
//
//**************************************
{
Assert(prv_from);
Assert(prv_to);
//
// 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);
//
// Calculate the increment for the U and V values for modulus subtraction.
//
fNegUInvZ = fDUInvZ;
fNegVInvZ = fDVInvZ;
fNegInvZ = fDInvZ;
fDUInvZEdge = fDUInvZ;
fDVInvZEdge = fDVInvZ;
fDInvZEdge = fDInvZ;
//
// Set up the increments for edge walking. Note that the increment of the x difference
// must be incorporated into this value.
//
rind_linear_increment.fUInvZ = f_increment_u + f_x_diff_increment * fDUInvZEdge;
rind_linear_increment.fVInvZ = f_increment_v + f_x_diff_increment * fDVInvZEdge;
rind_linear_increment.fInvZ = f_increment_z + f_x_diff_increment * fDInvZEdge;
//
// 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.
//
fUInvZ = prv_from->tcTex.tX + f_increment_u * f_y_diff_edge + f_x_diff_edge * fDUInvZEdge;
fVInvZ = prv_from->tcTex.tY + f_increment_v * f_y_diff_edge + f_x_diff_edge * fDVInvZEdge;
fInvZ = prv_from->v3Screen.tZ + f_increment_z * f_y_diff_edge + f_x_diff_edge * fDInvZEdge;
float f_subdivide_len = float(iSubdivideLen);
// Slopes times subdivision length minus one.
fDUInvZEdgeMinusOne = fDUInvZEdge * (f_subdivide_len - 1.0f);
fDVInvZEdgeMinusOne = fDVInvZEdge * (f_subdivide_len - 1.0f);
fDInvZEdgeMinusOne = fDInvZEdge * (f_subdivide_len - 1.0f);
// Slopes times subdivision length.
fDUInvZEdge *= f_subdivide_len;
fDVInvZEdge *= f_subdivide_len;
fDInvZEdge *= f_subdivide_len;
}
//*****************************************************************************************
//
void AssertRange
(
ptr_const<CTexture> ptex,
int i_mip_level
)
//
// Tests for valid UV entries. Use in debug mode only.
//
//**************************************
{
#if VER_DEBUG
#endif
}
//*****************************************************************************************
//
void AssertXRange
(
int i_xrange
)
//
// Uses asserts to check if the range of texture coords for this scanline is valid.
//
//**************************************
{
#if VER_DEBUG
#if VER_CLAMP_UV_TILE
// Check starting values.
float f_u = fUInvZ / fInvZ;
float f_v = fVInvZ / fInvZ;
// fTexWidth is a float slightly less than the width of the texture.
// So int(fTexWidth) is the maximum integer value allowed.
Assert(bWithin(int(f_u), 0, int(fTexWidth)));
Assert(bWithin(int(f_v), 0, int(fTexHeight)));
// Check ending values.
float f_uinvz = fUInvZ + fDUInvZ * i_xrange;
float f_vinvz = fVInvZ + fDVInvZ * i_xrange;
float f_invz = fInvZ + fDInvZ * i_xrange;
f_u = f_uinvz / f_invz;
f_v = f_vinvz / f_invz;
Assert(bWithin(int(f_u), 0, int(fTexWidth)));
Assert(bWithin(int(f_v), 0, int(fTexHeight)));
#endif
#endif
}
};
//*********************************************************************************************
//
class CIndexPerspectiveFilter : public CIndexPerspective
//
// Perspective index that will give us the fractional part of the index.
//
//**************************************
{
public:
//*****************************************************************************************
//
// CIndexLinearFilter constructors.
//
forceinline CIndexPerspectiveFilter() : CIndexPerspective()
{
}
forceinline CIndexPerspectiveFilter(const CIndexPerspective& index, int i_pixel) : CIndexPerspective(index, i_pixel)
{
}
};
//
// Class implementations.
//
#if VER_ASM
//******************************************************************************************
#if TARGET_PROCESSOR == PROCESSOR_PENTIUM
#include "Lib/Renderer/Primitives/P5/IndexPerspectiveTEx.hpp"
#elif TARGET_PROCESSOR == PROCESSOR_PENTIUMPRO
#include "Lib/Renderer/Primitives/P6/IndexPerspectiveTEx.hpp"
#elif TARGET_PROCESSOR == PROCESSOR_K6_3D
#include "Lib/Renderer/Primitives/AMDK6/IndexPerspectiveTEx.hpp"
#else
#error Invalid [No] target processor specified
#endif
//******************************************************************************************
#else
//*************************************************************************************
forceinline void CIndexPerspective::InitializeSubdivision(int i_pixel)
{
float f_u;
float f_v;
float f_z;
float f_next_z;
// Get the next pixel index value to subdivide to.
iNextSubdivide = iSetNextDividePixel(i_pixel);
// Get current u, v and z values.
f_z = 1.0f / fGInvZ;
// Set current texture coordinates.
f_u = fGUInvZ * f_z;
f_v = fGVInvZ * f_z;
if (bClampUV)
{
SetMinMax(f_u, fTexEdgeTolerance, fTexWidth);
SetMinMax(f_v, fTexEdgeTolerance, fTexHeight);
}
w2dTex.Initialize(f_u, f_v, iTexWidth);
// Increment u, v and z values.
fGUInvZ += fDUInvZScanline;
fGVInvZ += fDVInvZScanline;
fGInvZ += fDInvZScanline;
// Get next u, v and z values.
f_next_z = 1.0f / fGInvZ;
// Set new texture coordinate increments.
fU = fGUInvZ * f_next_z;
fV = fGVInvZ * f_next_z;
if (bClampUV)
{
SetMinMax(fU, fTexEdgeTolerance, fTexWidth);
SetMinMax(fV, fTexEdgeTolerance, fTexHeight);
}
float f_inv_pixel = fUnsignedInverseInt(i_pixel - iNextSubdivide);
w2dDeltaTex.Initialize
(
(fU - f_u) * f_inv_pixel,
(fV - f_v) * f_inv_pixel,
iTexWidth
);
// Get ready for the next subdivision.
BeginNextSubdivision();
}
//*************************************************************************************
forceinline void CIndexPerspective::BeginNextSubdivision()
{
iCacheNextSubdivide = iSetNextDividePixel(iNextSubdivide);
// Increment global U, V and inverse Z values.
fGUInvZ += fDUInvZScanline;
fGVInvZ += fDVInvZScanline;
fGInvZ += fDInvZScanline;
}
//*************************************************************************************
forceinline void CIndexPerspective::EndNextSubdivision()
{
float f_u, f_v, f_z;
if (iNextSubdivide == iCacheNextSubdivide)
return;
float f_inv_pixel = fUnsignedInverseInt(iNextSubdivide - iCacheNextSubdivide);
f_z = 1.0f / fGInvZ;
f_u = fGUInvZ * f_z;
f_v = fGVInvZ * f_z;
if (bClampUV)
{
SetMinMax(f_u, fTexEdgeTolerance, fTexWidth);
SetMinMax(f_v, fTexEdgeTolerance, fTexHeight);
}
w2dDeltaTex.Initialize
(
(f_u - fU) * f_inv_pixel,
(f_v - fV) * f_inv_pixel,
iTexWidth
);
fU = f_u;
fV = f_v;
iNextSubdivide = iCacheNextSubdivide;
BeginNextSubdivision();
}
#endif
#endif