⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scanconverter.cpp

📁 手机 GAME c++ 版
💻 CPP
字号:
////////////////////////////////////////////////////////////////////////
//
// ScanConverter.cpp
//
// Copyright (c) 2003 Nokia Mobile Phones Ltd.  All rights reserved.
//
////////////////////////////////////////////////////////////////////////

#include "Face.h"
#include "MathLookup.h"
#include "ScanConverter.h"

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

TIntersectionBuffer::TIntersectionBuffer()
	{
	Reset();
	}

////////////////////////////////////////////////////////////////////////

void TIntersectionBuffer::Reset()
	{
	iMinY = numEntries - 1;
	iMaxY = 0;
	}

////////////////////////////////////////////////////////////////////////

void TIntersectionBuffer::ScanEdge
	(
	const TScreenVertex &aVertexA, 
	const TScreenVertex &aVertexB, TMathLookup &aMath
	)
	{
	TInt screenYA = aVertexA.iScreenY;
	TInt screenYB = aVertexB.iScreenY;

	TInt pixelYA = screenYA >> Geometry3D::screenCoordUnityLog;
	TInt pixelYB = screenYB >> Geometry3D::screenCoordUnityLog;

	if ( ( pixelYB - pixelYA ) < 1 )
		{
		// Edge doesn't cross any scanlines!
		return;
		}

	//
	// Update extrema as necessary:
	//
	if ( pixelYB > iMaxY )
		{
		iMaxY = pixelYB;
		}

	if ( pixelYA < iMinY )
		{
		iMinY = pixelYA;
		}

	TInt screenXA = aVertexA.iScreenX;
	TInt screenXB = aVertexB.iScreenX;

	TInt deltaX = screenXB - screenXA;
	TInt deltaY = screenYB - screenYA;

	TInt recipDeltaY;
	TInt downshift;

	aMath.GetReciprocal(deltaY, recipDeltaY, downshift);

	// Adjust downshift to leave results in correct fixed-point units:
	downshift -= interpolationUnityLog;
	TInt downshiftBias = 1 << ( downshift - 1 );

	// Calculate start x value (= intersection of edge with first scanline):
	TInt startErrorY = ( -screenYA ) & Geometry3D::screenCoordFractionMask;
	TInt startErrorYDeltaX = ( ( startErrorY * deltaX ) + Geometry3D::screenCoordBias ) 
														>> Geometry3D::screenCoordUnityLog;

	TInt startErrorX = ( startErrorYDeltaX * recipDeltaY ) >> downshift;
	TInt interpX = startErrorX + ( screenXA << resultDownshift );

	// Calculate scanline x increment (= gradient of edge):
	TInt stepX = ( ( deltaX * recipDeltaY ) + downshiftBias ) >> downshift;

	for ( TInt y = pixelYA ; y < pixelYB ; y++ )
		{
		iEntry[y] = interpX >> resultDownshift;

		interpX += stepX;
		}
	}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

TScanConverter::TScanConverter(const TSize& aSize)
	{
	iSize = aSize;
	iScreenPtr = NULL;

	iLeftX		= 0;
	iRightX		= iSize.iWidth;
	iTopY		= 0;
	iBottomY	= iSize.iHeight;

	// Set camera field-of-view to be 60 degrees from top to bottom of
	// the screen. (Angle is arbitrary - the larger the angle, the
	// stronger the "fish-eye" effect of projection.)
	TReal halfHeight = iSize.iHeight * 0.5;
	iCamera.SetFieldOfView(60.0, halfHeight);
	iCamera.SetBounds(iLeftX, iTopY, iRightX, iBottomY, iSize.iWidth >> 1, iSize.iHeight >> 1);
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::ClearScreen(TUint16 aFillColor)
	{
	TInt count = iSize.iWidth * iSize.iHeight;
	TUint16 * screenPtrRov = iScreenPtr;

	for ( TInt i = 0 ; i < count ; i++ )
		{
		*screenPtrRov = aFillColor;
		screenPtrRov++;
		}
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::TransformVerts
	( 
	TInt aNumVerts, 
	const TVector3 * aSrcVertPtr, 
	TAffineTransform &aAffine, 
	TScreenVertex * aDestVertPtr, 
	TVector3 &aCameraInModelSpace 
	)
	{
	iCamera.TransformVerts(aNumVerts, aSrcVertPtr, aAffine, aDestVertPtr, aCameraInModelSpace);
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::ClipAndRender(TClipFace &aFaceA, TClipFace &aFaceB, TMathLookup &aMath)
	{
	iCamera.ClipAndRender(aFaceA, aFaceB, aMath, *this);
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::ResetScan()
	{
	iLeftBuffer.Reset();
	iRightBuffer.Reset();
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::ScanEdge
	(
	const TScreenVertex &aVertexA, 
	const TScreenVertex &aVertexB, 
	TMathLookup &aMath
	)
	{
	if ( aVertexA.iScreenY > aVertexB.iScreenY )
		{
		iRightBuffer.ScanEdge(aVertexB,aVertexA,aMath);
		}
	else
		{
		iLeftBuffer.ScanEdge(aVertexA,aVertexB,aMath);
		}
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::Fill(TUint16 aFlatColor)
	{
	TInt minY = iLeftBuffer.iMinY;
	TInt maxY = iLeftBuffer.iMaxY;

	//
	// Clamping in y: these tests (and the corresponding tests in x)
	// are for added security only, and are intended to allow the
	// system to continue running despite overfow errors elsewhere.
	//
	if ( minY < iTopY )
		{
		minY = iTopY;
		}

	if ( maxY > iBottomY )
		{
		maxY = iBottomY;
		}

	TUint16 * scanLinePtr = &iScreenPtr[ iSize.iWidth * minY ];

	for ( TInt y = minY ; y < maxY ; y++ )
		{
		TInt xL = iLeftBuffer.iEntry[ y ] >> Geometry3D::screenCoordUnityLog;
		TInt xR = iRightBuffer.iEntry[ y ] >> Geometry3D::screenCoordUnityLog;

		//
		// Clamping in x: see comments for clamping in y
		//
		if ( xL < iLeftX )
			{
			xL = iLeftX;
			}

		if ( xR > iRightX )
			{
			xR = iRightX;
			}

		TUint16 * scanPtr = &scanLinePtr[ xL ];
		scanLinePtr += iSize.iWidth;

		for ( TInt x = xL ; x < xR ; x++ )
			{
			*scanPtr = aFlatColor;
			scanPtr++;
			}
		}
	}

////////////////////////////////////////////////////////////////////////

void TScanConverter::PlotPixel(TInt aX, TInt aY, TUint16 aFillColor)
	{
	if ( ( aX >= 0 ) && ( aX < iSize.iWidth ) && ( aY >= 0 ) && ( aY < iSize.iHeight ) )
		{
		TInt pixelIndex = ( iSize.iWidth * aY ) + aX;

		iScreenPtr[ pixelIndex ] = aFillColor;
		}
	}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -