mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-24 17:41:56 +00:00
406 lines
10 KiB
C++
406 lines
10 KiB
C++
/***********************************************************************************************
|
|
*
|
|
* Copyright © DreamWorks Interactive, 1997.
|
|
*
|
|
* Contents:
|
|
* Specialized (non-template) versions of the DrawSubtriangle function.
|
|
* Optimized for the Pentium Processor
|
|
*
|
|
***********************************************************************************************
|
|
*
|
|
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/P5/DrawSubTriangleGourEx.cpp $
|
|
*
|
|
* 9 97.12.22 9:08p Mmouni
|
|
* Fixed error with destination of terrain gouraud shading primitive.
|
|
*
|
|
* 8 97.12.22 6:07p Mmouni
|
|
* Changed terrain gouraud shading routines so that they don't always draw to the screen.
|
|
*
|
|
* 7 97.12.22 2:53p Mmouni
|
|
* Added new terrain gouraud shading primitive.
|
|
*
|
|
* 6 10/10/97 1:47p Mmouni
|
|
* All inner loops are now left to right only, and optimized some.
|
|
*
|
|
* 5 9/15/97 2:10p Mmouni
|
|
* Optimized inner loops (not final yet).
|
|
*
|
|
* 4 9/01/97 8:02p Rwyatt
|
|
*
|
|
* 3 97/07/18 3:29p Pkeet
|
|
* Removed use of the 'b_right' parameter from DrawSubTriangle.
|
|
*
|
|
* 2 7/14/97 12:36p Rwyatt
|
|
* Checkled in so Scott can move them....
|
|
*
|
|
* 1 7/07/97 11:15p Rwyatt
|
|
* Initial Implementation of Pentium Specifics
|
|
*
|
|
***********************************************************************************************
|
|
***********************************************************************************************
|
|
*
|
|
* 5 97/06/12 5:56p Pkeet
|
|
* Added capability to render only every other scanline and to double the number of scanlines.
|
|
*
|
|
* 4 97/06/11 11:41p Pkeet
|
|
* Added more optimal inner loop code.
|
|
*
|
|
* 3 97/06/11 11:27p Pkeet
|
|
* Initial assembly version.
|
|
*
|
|
* 2 97/06/11 11:20p Pkeet
|
|
* Simplified the C++ version.
|
|
*
|
|
* 1 97/06/11 10:15p Pkeet
|
|
* Initial C++ versions of primitives.
|
|
*
|
|
**********************************************************************************************/
|
|
|
|
#include "Common.hpp"
|
|
|
|
#include "Lib/View/Raster.hpp"
|
|
#include "Lib/Renderer/Primitives/DrawTriangle.hpp"
|
|
|
|
//
|
|
// Temporary Globals.
|
|
//
|
|
// Notes:
|
|
// These variables should be arraigned along with the external globals for maximum
|
|
// cache efficiency.
|
|
//
|
|
static fixed fx_gour_inc;
|
|
static int i_line_pixels;
|
|
static uint16* ppix_clut;
|
|
|
|
|
|
//*****************************************************************************************
|
|
// Gouraud shaded triangle function.
|
|
//
|
|
void DrawSubtriangle(TGour* pscan, CDrawPolygon<TGour>* pdtri)
|
|
{
|
|
static TGour* pscanGlbl;
|
|
static CDrawPolygon<TGour>* pdtriGlbl;
|
|
|
|
fx_inc = pdtri->pedgeBase->lineIncrement.fxX;
|
|
fx_diff = pdtri->pedgeBase->lineIncrement.fxXDifference;
|
|
fx_gour_inc = pdtri->pedgeBase->lineIncrement.gourIntensity.fxIntensity;
|
|
i_line_pixels = pdtri->prasScreen->iLinePixels;
|
|
ppix_clut = ((uint16*)pvClutConversion) + u4ConstColour;
|
|
pscanGlbl = pscan;
|
|
pdtriGlbl = pdtri;
|
|
|
|
_asm
|
|
{
|
|
mov edx,[pdtri]
|
|
mov ecx,[pscan]
|
|
|
|
push ebp
|
|
|
|
mov eax,[edx]CDrawPolygonBase.iY
|
|
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
|
|
// ecx, edi, eax and edx are also set from the loop end.
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// scan line start
|
|
NEXT_SCAN:
|
|
and eax,[bEvenScanlinesOnly]
|
|
jnz short SKIP_LOOP
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Calculate start, length of edge.
|
|
mov esi,[ecx]TGour.fxX.i4Fx
|
|
mov eax,[edx]CDrawPolygonBase.fxLineLength.i4Fx
|
|
|
|
add eax,esi
|
|
|
|
sar eax,16
|
|
mov ebx,gsGlobals.pvScreen
|
|
|
|
sar esi,16
|
|
add edi,eax
|
|
|
|
sub esi,eax
|
|
jge short SKIP_LOOP
|
|
|
|
// Get the starting gouraud shading value.
|
|
mov edx,[ecx]TGour.gourIntensity.fxIntensity.i4Fx
|
|
lea edi,[edi*2+ebx]
|
|
|
|
mov ecx,[ppix_clut]
|
|
mov ebx,0xFFFF0000
|
|
|
|
mov [pvBaseOfLine],edi
|
|
mov ebp,[fxDeltaXIntensity]
|
|
|
|
lea eax,[edi + esi*2]
|
|
|
|
test eax,3
|
|
jz short ALIGNED
|
|
|
|
// Check for one pixel before starting.
|
|
inc esi
|
|
jz short FINISH_REMAINDER
|
|
|
|
//
|
|
// Do one pixel for alignment.
|
|
//
|
|
and ebx,edx // Copy and mask intensity value
|
|
add edx,ebp // Step intensity value
|
|
shr ebx,8 // Shift masked intensity value
|
|
// AGI on ebx
|
|
mov bx,[ecx + ebx*2] // Lookup pixel
|
|
mov [edi + esi*2 - 2],bx // Store pixel
|
|
mov ebx,0xFFFF0000 // Load mask value into ebx
|
|
|
|
ALIGNED:
|
|
// Make sure we have two pixels left.
|
|
add esi,2
|
|
jg short FINISH_REMAINDER
|
|
|
|
mov edi,0xFFFF0000 // Load mask value into edi.
|
|
|
|
//
|
|
// Do two pixels at a time.
|
|
//
|
|
INNER_LOOP_2P:
|
|
and ebx,edx // Copy and mask intensity (1).
|
|
add edx,ebp // Step intensity.
|
|
|
|
shr ebx,8 // Shift masked intensity value (1).
|
|
and edi,edx // Copy and mask intensity (2).
|
|
|
|
shr edi,8 // Shift masked intensity value (2).
|
|
xor eax,eax // Clear eax
|
|
|
|
add edx,ebp // Step intensity.
|
|
mov al,[ecx + ebx*2] // Lookup low byte of pixel (1)
|
|
|
|
mov ah,[ecx + ebx*2 + 1] // Lookup high byte of pixel (1)
|
|
mov bl,[ecx + edi*2] // Lookup low byte of pixel (2)
|
|
|
|
mov bh,[ecx + edi*2 + 1] // Lookup high byte of pixel (2)
|
|
mov edi,[pvBaseOfLine] // Load pointer to base of scanline.
|
|
|
|
shl ebx,16 // Shift second pixel up
|
|
|
|
or eax,ebx // Merge pixels
|
|
mov ebx,0xFFFF0000 // Load mask value into ebx.
|
|
|
|
mov [edi + esi*2 - 4],eax // Store pixel.
|
|
mov edi,0xFFFF0000 // Load mask value into edi.
|
|
|
|
add esi,2
|
|
jle short INNER_LOOP_2P
|
|
|
|
// esi is 1 if there is a pixel left.
|
|
cmp esi,1
|
|
jne short SKIP_LOOP
|
|
|
|
//
|
|
// Finish left over pixel.
|
|
//
|
|
FINISH_REMAINDER:
|
|
and ebx,edx // Copy and mask intensity value
|
|
mov edi,[pvBaseOfLine] // Load pointer to base of scanline.
|
|
shr ebx,8 // Shift masked intensity value
|
|
// AGI on ebx
|
|
mov bx,[ecx + ebx*2] // Lookup pixel
|
|
mov [edi - 2],bx // Store pixel
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Loop control an sub pixel correction for edges
|
|
SKIP_LOOP:
|
|
mov edx,[pdtriGlbl]
|
|
mov ecx,[pscanGlbl]
|
|
|
|
mov esi,[ecx]TGour.gourIntensity.fxIntensity.i4Fx
|
|
mov ebx,[ecx]TGour.fxXDifference
|
|
|
|
add esi,[fx_gour_inc]
|
|
add ebx,[fx_diff]
|
|
|
|
mov eax,[fxIModDiv]
|
|
jge short NO_UNDERFLOW
|
|
|
|
// Undeflow of fxXDifference.
|
|
add ebx,0x00010000
|
|
add esi,eax
|
|
|
|
jmp short DONE_Y
|
|
|
|
NO_UNDERFLOW:
|
|
cmp ebx,0x00010000
|
|
jl short DONE_Y
|
|
|
|
// Overflow of fxXDifference.
|
|
sub ebx,0x00010000
|
|
add esi,eax
|
|
|
|
DONE_Y:
|
|
// Store modified variables.
|
|
mov [ecx]TGour.gourIntensity.fxIntensity.i4Fx,esi
|
|
mov [ecx]TGour.fxXDifference,ebx
|
|
|
|
// Step length, line starting address.
|
|
mov ebx,[edx]CDrawPolygonBase.fxLineLength.i4Fx
|
|
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
|
|
|
|
add ebx,[edx]CDrawPolygonBase.fxDeltaLineLength.i4Fx
|
|
add edi,[i_line_pixels]
|
|
|
|
mov [edx]CDrawPolygonBase.fxLineLength.i4Fx,ebx
|
|
mov [edx]CDrawPolygonBase.iLineStartIndex,edi
|
|
|
|
mov ebx,[ecx]TGour.fxX
|
|
mov esi,[fx_inc]
|
|
|
|
add ebx,esi
|
|
mov eax,[edx]CDrawPolygonBase.iY
|
|
|
|
mov [ecx]TGour.fxX,ebx
|
|
inc eax
|
|
|
|
mov ebx,[edx]CDrawPolygonBase.iYTo
|
|
mov [edx]CDrawPolygonBase.iY,eax
|
|
|
|
// ecx, edi, eax and edx are set for the next interation of the loop.
|
|
cmp eax,ebx
|
|
jl NEXT_SCAN
|
|
|
|
pop ebp
|
|
}
|
|
}
|
|
|
|
|
|
//*****************************************************************************************
|
|
// Gouraud shaded triangle function that draws to a composite texture map.
|
|
//
|
|
void DrawSubtriangle(TShadeTerrain* pscan, CDrawPolygon<TShadeTerrain>* pdtri)
|
|
{
|
|
typedef CDrawPolygon<TShadeTerrain> TAccess;
|
|
static TShadeTerrain* pscanGlbl;
|
|
static CDrawPolygon<TShadeTerrain>* pdtriGlbl;
|
|
|
|
fx_inc = pdtri->pedgeBase->lineIncrement.fxX;
|
|
fx_diff = pdtri->pedgeBase->lineIncrement.fxXDifference;
|
|
fx_gour_inc = pdtri->pedgeBase->lineIncrement.gourIntensity.fxIntensity;
|
|
i_line_pixels = pdtri->prasScreen->iLinePixels;
|
|
pscanGlbl = pscan;
|
|
pdtriGlbl = pdtri;
|
|
|
|
_asm
|
|
{
|
|
mov edx,[pdtri]
|
|
mov ecx,[pscan]
|
|
|
|
mov eax,[edx]CDrawPolygonBase.iY
|
|
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
|
|
// ecx, edi, eax and edx are also set from the loop end.
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// scan line start
|
|
NEXT_SCAN:
|
|
and eax,[bEvenScanlinesOnly]
|
|
jnz short SKIP_LOOP
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Calculate start, length of edge.
|
|
mov esi,[ecx]TGour.fxX.i4Fx
|
|
mov eax,[edx]CDrawPolygonBase.fxLineLength.i4Fx
|
|
|
|
add eax,esi
|
|
|
|
sar eax,16
|
|
mov ebx,[edx]TAccess.prasScreen
|
|
|
|
sar esi,16
|
|
add edi,eax
|
|
|
|
mov ebx,[ebx]CRasterBase.pSurface
|
|
|
|
sub esi,eax
|
|
jge short SKIP_LOOP
|
|
|
|
// Get the starting gouraud shading value.
|
|
mov edx,[ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx
|
|
lea edi,[edi*2+ebx]
|
|
|
|
mov [pvBaseOfLine],edi
|
|
mov eax,[fxDeltaXIntensity]
|
|
|
|
//
|
|
// Write intensity value to every other pixel.
|
|
//
|
|
INNER_LOOP:
|
|
mov ebx,edx // Copy intensity value
|
|
add edx,eax // Step intensity value
|
|
|
|
shr ebx,16 // Shift intensity value
|
|
|
|
mov [edi + esi*2 + 1],bl // Store integer intensity byte
|
|
inc esi // Step count
|
|
|
|
jnz short INNER_LOOP
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Loop control an sub pixel correction for edges
|
|
SKIP_LOOP:
|
|
mov edx,[pdtriGlbl]
|
|
mov ecx,[pscanGlbl]
|
|
|
|
mov esi,[ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx
|
|
mov ebx,[ecx]TShadeTerrain.fxXDifference
|
|
|
|
add esi,[fx_gour_inc]
|
|
add ebx,[fx_diff]
|
|
|
|
mov eax,[fxIModDiv]
|
|
jge short NO_UNDERFLOW
|
|
|
|
// Undeflow of fxXDifference.
|
|
add ebx,0x00010000
|
|
add esi,eax
|
|
|
|
jmp short DONE_Y
|
|
|
|
NO_UNDERFLOW:
|
|
cmp ebx,0x00010000
|
|
jl short DONE_Y
|
|
|
|
// Overflow of fxXDifference.
|
|
sub ebx,0x00010000
|
|
add esi,eax
|
|
|
|
DONE_Y:
|
|
// Store modified variables.
|
|
mov [ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx,esi
|
|
mov [ecx]TShadeTerrain.fxXDifference,ebx
|
|
|
|
// Step length, line starting address.
|
|
mov ebx,[edx]CDrawPolygonBase.fxLineLength.i4Fx
|
|
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
|
|
|
|
add ebx,[edx]CDrawPolygonBase.fxDeltaLineLength.i4Fx
|
|
add edi,[i_line_pixels]
|
|
|
|
mov [edx]CDrawPolygonBase.fxLineLength.i4Fx,ebx
|
|
mov [edx]CDrawPolygonBase.iLineStartIndex,edi
|
|
|
|
mov ebx,[ecx]TShadeTerrain.fxX
|
|
mov esi,[fx_inc]
|
|
|
|
add ebx,esi
|
|
mov eax,[edx]CDrawPolygonBase.iY
|
|
|
|
mov [ecx]TShadeTerrain.fxX,ebx
|
|
inc eax
|
|
|
|
mov ebx,[edx]CDrawPolygonBase.iYTo
|
|
mov [edx]CDrawPolygonBase.iY,eax
|
|
|
|
// ecx, edi, eax and edx are set for the next interation of the loop.
|
|
cmp eax,ebx
|
|
jl NEXT_SCAN
|
|
}
|
|
}
|