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

📄 vertex.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
<module>
* Name         : vertex.c
* Title        : D3DM software vertex manipulation functions
* Author(s)    : Imagination Technologies
* Created      : 2 March 2004
*
* Copyright    : 2004 by Imagination Technologies Limited.
*                All rights reserved.  No part of this software, either
*                material or conceptual may be copied or distributed,
*                transmitted, transcribed, stored in a retrieval system
*                or translated into any human or computer language in any
*                form by any means, electronic, mechanical, manual or
*                other-wise, or disclosed to third parties without the
*                express written permission of Imagination Technologies
*                Limited, Unit 8, HomePark Industrial Estate,
*                King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description  : D3DM software vertex manipulation functions
*
* Platform     : Windows CE
*
$Log: vertex.c $
********************************************************************************/
#include "context.h"

#if (!defined(SUPPORT_VGP) && !defined(SUPPORT_VGP_LITE))
/***********************************************************************************
 Function Name      : IsCounterClockWise
 Inputs             : psVertex
 Outputs            : -
 Returns            : Is the triangle winding counter clockwise
 Description        : Checks the winding order of an array of 3 vertices.		  
************************************************************************************/
IMG_BOOL IsCounterClockWise(PVR_NATIVE_VERTEX **ppsVertex)
{
	NTV_TYPE DxAC, DxBC, DyAC, DyBC, Area;

	/* Compute signed area of the triangle */
	DxAC = Sub(ppsVertex[0]->sWindow.x, ppsVertex[2]->sWindow.x);
	DyAC = Sub(ppsVertex[0]->sWindow.y, ppsVertex[2]->sWindow.y);
	DxBC = Sub(ppsVertex[1]->sWindow.x, ppsVertex[2]->sWindow.x);
	DyBC = Sub(ppsVertex[1]->sWindow.y, ppsVertex[2]->sWindow.y);

	Area = CLAMP(Sub(Mul(DxAC, DyBC), Mul(DxBC, DyAC)));
	
	/* extract sign */
	return (*(IMG_INT32 *)&Area >> 31);
}

/***********************************************************************************
 Function Name      : SetupNativeVertex
 Inputs             : psContext, psVertex, ui32FVFcode, psNativeVertex
 Outputs            : converted native verticex 
 Returns            : 
 Description        : Converts and sets up a vertex in native format		  
************************************************************************************/
IMG_VOID SetupNativeVertex (LPD3DM_CONTEXT		psContext,
							IMG_UINT32			*pui32Data, 
							IMG_UINT32			ui32FVFcode, 
							PVR_NATIVE_VERTEX	*psNativeVertex)
{
	IMG_UINT32 i;

	PROFILE_START_FUNC(SET_UP_NATIVE_VERTEX);

	/* 
		need to do a single pass of the FVF and setup
		function pointers to do the work on subsequent vertices 
	*/

	psNativeVertex->ui32Flags = 0;

	/*********************
		Position:
	*********************/
	switch (ui32FVFcode & D3DMFVF_POSITION_MASK)
	{
		case D3DMFVF_XYZ_FLOAT:
			psNativeVertex->sObj.x = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.y = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.z = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.w = D3DM_One;
			break;
		case D3DMFVF_XYZRHW_FLOAT:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_RHW;
			psNativeVertex->sObj.x = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.y = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.z = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.w = FLPTR2NTV(pui32Data); pui32Data++;
			break;
		case D3DMFVF_XYZ_FIXED:
			psNativeVertex->sObj.x = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.y = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.z = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.w = D3DM_One;
			break;
		case D3DMFVF_XYZRHW_FIXED:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_RHW;
			psNativeVertex->sObj.x = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.y = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.z = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sObj.w = FXPTR2NTV(pui32Data); pui32Data++;
			break;
		default:
			//error!!!!!!!!!!!
			break;
	}
	
	/*********************
		Normal:
	*********************/
	switch (ui32FVFcode & D3DMFVF_NORMAL_MASK)
	{
		case D3DMFVF_NORMAL_NONE:
			break;
		case D3DMFVF_NORMAL_FLOAT:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_NORMAL;
			psNativeVertex->sNormal.x = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.y = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.z = FLPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.w = D3DM_Zero;
			break;
		case D3DMFVF_NORMAL_FIXED:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_NORMAL;
			psNativeVertex->sNormal.x = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.y = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.z = FXPTR2NTV(pui32Data); pui32Data++;
			psNativeVertex->sNormal.w = D3DM_Zero;
			break;
	}

	/*********************
		Colours:
	*********************/
	if (ui32FVFcode & D3DMFVF_DIFFUSE)
	{
		psNativeVertex->sDiffuseIn.ui32Colour = *pui32Data++;

		psNativeVertex->ui32Flags |= D3DM_HASFLAG_DIFFUSE_COLOR;

		if(!(psNativeVertex->ui32Flags & D3DM_HASFLAG_RHW))
		{
			psNativeVertex->sDiffuseIn.a = Div(LONG_AS_NTV((psNativeVertex->sDiffuseIn.ui32Colour & 0xff000000) >> 24),	LONG_AS_NTV(255));
			psNativeVertex->sDiffuseIn.r = Div(LONG_AS_NTV((psNativeVertex->sDiffuseIn.ui32Colour & 0x00ff0000) >> 16),	LONG_AS_NTV(255));
			psNativeVertex->sDiffuseIn.g = Div(LONG_AS_NTV((psNativeVertex->sDiffuseIn.ui32Colour & 0x0000ff00) >>  8),	LONG_AS_NTV(255));
			psNativeVertex->sDiffuseIn.b = Div(LONG_AS_NTV(psNativeVertex->sDiffuseIn.ui32Colour & 0x000000ff),			LONG_AS_NTV(255));
		}
	}
	
	if (ui32FVFcode & D3DMFVF_SPECULAR)
	{
		psNativeVertex->sSpecularIn.ui32Colour = *pui32Data++;

		psNativeVertex->ui32Flags |= D3DM_HASFLAG_SPECULAR_COLOR;

		//FIXME: possible negative shifts - compiler support?
		psNativeVertex->sSpecularIn.a = Div(LONG_AS_NTV((psNativeVertex->sSpecularIn.ui32Colour & 0xff000000) >> 24),	LONG_AS_NTV(255));
		psNativeVertex->sSpecularIn.r = Div(LONG_AS_NTV((psNativeVertex->sSpecularIn.ui32Colour & 0x00ff0000) >> 16),	LONG_AS_NTV(255));
		psNativeVertex->sSpecularIn.g = Div(LONG_AS_NTV((psNativeVertex->sSpecularIn.ui32Colour & 0x0000ff00) >> 8),	LONG_AS_NTV(255));
		psNativeVertex->sSpecularIn.b = Div(LONG_AS_NTV(psNativeVertex->sSpecularIn.ui32Colour & 0x000000ff) ,			LONG_AS_NTV(255));
	}

	/*********************
		Textures:
	*********************/
	switch (ui32FVFcode & D3DMFVF_TEXCOUNT_MASK)
	{
		case D3DMFVF_TEX0:
			psNativeVertex->ui32TexCount = 0;
			psNativeVertex->sTextures[0].ui32NumOut = 0;
			psNativeVertex->sTextures[1].ui32NumOut = 0;
			break;
		case D3DMFVF_TEX1:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_TEXTURE0;
			psNativeVertex->ui32TexCount = 1;
			psNativeVertex->sTextures[1].ui32NumOut = 0;
			break;
		case D3DMFVF_TEX2:
			psNativeVertex->ui32Flags |= D3DM_HASFLAG_TEXTURE0 | D3DM_HASFLAG_TEXTURE1;
			psNativeVertex->ui32TexCount = 2;
			break;
		case D3DMFVF_TEX3:
		case D3DMFVF_TEX4:
		default:
			//error - don't support more than 2 layers
			break;
	}

	// FIXME: preprocess this state checking 
	// - replace with single switch statement for each possible outcome (4)
	for (i=0; i<psNativeVertex->ui32TexCount; i++)
	{
		PLAYER_TSTATE 	psLState = &psContext->sTState.sLState[i];
		
		if(((ui32FVFcode>>(24+(i*2))) & 0x3) == D3DMFVF_TEXCOORDFORMAT_FLOAT)
		{
			switch ((ui32FVFcode>>(16+(i*2))) & 0x3)
			{
				case D3DMFVF_TEXCOORDCOUNT1:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 1;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FLPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = D3DM_One;
				 		psNativeVertex->sTextures[i].z = D3DM_One;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data++;
					}
					break;
				}
				case D3DMFVF_TEXCOORDCOUNT2:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 2;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FLPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = FLPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].z = D3DM_One;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data += 2;
					}
					break;
				}
				case D3DMFVF_TEXCOORDCOUNT3:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 3;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FLPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = FLPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].z = FLPTR2NTV(pui32Data); pui32Data++;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data += 3;
					}
					break;
				}
				default:
					//error unsupported
					break;
			}
		}
		else if(((ui32FVFcode>>(24+(i*2))) & 0x3) == D3DMFVF_TEXCOORDFORMAT_FIXED)
		{
			switch ((ui32FVFcode>>(16+(i*2))) & 0x3)
			{
				case D3DMFVF_TEXCOORDCOUNT1:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 1;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FXPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = D3DM_One;
				 		psNativeVertex->sTextures[i].z = D3DM_One;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data++;
					}
					break;
				}
				case D3DMFVF_TEXCOORDCOUNT2:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 2;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FXPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = FXPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].z = D3DM_One;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data += 2;
					}
					break;
				}
				case D3DMFVF_TEXCOORDCOUNT3:
				{
					psNativeVertex->sTextures[i].ui32NumOut = 3;
					if(psLState->dwCoordAutoGenMode == D3DMTSS_TCI_PASSTHRU)
					{
				 		psNativeVertex->sTextures[i].x = FXPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].y = FXPTR2NTV(pui32Data); pui32Data++;
				 		psNativeVertex->sTextures[i].z = FXPTR2NTV(pui32Data); pui32Data++;
					}
					else
					{
						/* Just ignore the input data */
						pui32Data += 3;
					}
					break;
				}
				default:
					//error unsupported
					break;
			}				
		}
	}
	PROFILE_STOP_FUNC(SET_UP_NATIVE_VERTEX);
}
/***********************************************************************************
 Function Name      : ClipToPlane
 Inputs             : psContext, psDst, psVertA, psVertB
 Outputs            : -
 Returns            : Number of vertices post-clipping
 Description        : Define new vertex position based on the line between two vertices
					  intersecting a given plane
************************************************************************************/
IMG_VOID ClipToPlane (LPD3DM_CONTEXT psContext,
					  PVR_NATIVE_VERTEX *psDst, 
					  const PVR_NATIVE_VERTEX *psVertA, 
					  const PVR_NATIVE_VERTEX *psVertB, 
					  NTV_TYPE T)
{
	IMG_UINT32 i;

	PROFILE_START_FUNC(CLIP_TO_PLANE);

	/* Position */
    psDst->sClip.w = Add(MulPR_Y(T, Sub(psVertA->sClip.w, psVertB->sClip.w)), psVertB->sClip.w);
    psDst->sClip.x = Add(MulPR_Y(T, Sub(psVertA->sClip.x, psVertB->sClip.x)), psVertB->sClip.x);
    psDst->sClip.y = Add(MulPR_Y(T, Sub(psVertA->sClip.y, psVertB->sClip.y)), psVertB->sClip.y);
    psDst->sClip.z = Add(MulPR_Y(T, Sub(psVertA->sClip.z, psVertB->sClip.z)), psVertB->sClip.z);
    psDst->ui32Flags = D3DM_CLIPFLAG_MASK;

	if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_LIGHTING)
	{
		/* 
			We should have already calculated diffuse values for 
			each vertex so find diffuse value for the new vertex.
		*/

		/* If we're flat shading we will just copy the flat shading colours at output */
		if(!(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_FLAT_SHADING))
		{
			psDst->sDiffuseOut.r =	Add(Mul(T, Sub(psVertA->sDiffuseOut.r, psVertB->sDiffuseOut.r)), psVertB->sDiffuseOut.r);
			psDst->sDiffuseOut.g =	Add(Mul(T, Sub(psVertA->sDiffuseOut.g, psVertB->sDiffuseOut.g)), psVertB->sDiffuseOut.g);
			psDst->sDiffuseOut.b =	Add(Mul(T, Sub(psVertA->sDiffuseOut.b, psVertB->sDiffuseOut.b)), psVertB->sDiffuseOut.b);
			psDst->sDiffuseOut.a =	Add(Mul(T, Sub(psVertA->sDiffuseOut.a, psVertB->sDiffuseOut.a)), psVertB->sDiffuseOut.a);
		}
		else if(psContext->eCurrentPrimType == D3DMPT_LINESTRIP		|| 
			    psContext->eCurrentPrimType == D3DMPT_TRIANGLESTRIP ||
				psContext->eCurrentPrimType == D3DMPT_TRIANGLEFAN)
		{
			/* Take the flat shade colour */
			psDst->sDiffuseOut = *psContext->sTState.sSWTNLState.psCurrentFlatShadeDiffuse;
		}
		
		if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_SPECULAR)
		{
			/* 
				We should have already calculated specular values for 
				each vertex so find specular value for the new vertex.
			*/

			/* 
				If we're flat shading we will just copy the flat shading colours when we output,
				unless we're drawing triangle or line strips, in which case we use flat shade clour
			*/
			if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_FLAT_SHADING)
			{
				if(psContext->eCurrentPrimType == D3DMPT_LINESTRIP		|| 
				   psContext->eCurrentPrimType == D3DMPT_TRIANGLESTRIP  ||
				   psContext->eCurrentPrimType == D3DMPT_TRIANGLEFAN)
				{
					/* Take the flat shade colour */
					psDst->sSpecularOut = *psContext->sTState.sSWTNLState.psCurrentFlatShadeSpecular;
				}

				/* We need to interpolate the fog value if there is one */
				if(psVertA->ui32Flags & D3DM_HASFLAG_FOG)
				{
					psDst->sSpecularOut.a =	Add(Mul(T, Sub(psVertA->sSpecularOut.a, psVertB->sSpecularOut.a)), psVertB->sSpecularOut.a);
				}
			}
			else /* Gourad shading requires interpolated colour */
			{
				psDst->sSpecularOut.r =	Add(Mul(T, Sub(psVertA->sSpecularOut.r, psVertB->sSpecularOut.r)), psVertB->sSpecularOut.r);
				psDst->sSpecularOut.g =	Add(Mul(T, Sub(psVertA->sSpecularOut.g, psVertB->sSpecularOut.g)), psVertB->sSpecularOut.g);
				psDst->sSpecularOut.b =	Add(Mul(T, Sub(psVertA->sSpecularOut.b, psVertB->sSpecularOut.b)), psVertB->sSpecularOut.b);
				psDst->sSpecularOut.a =	Add(Mul(T, Sub(psVertA->sSpecularOut.a, psVertB->sSpecularOut.a)), psVertB->sSpecularOut.a);
			}
		}
		else
		{
			/* No specular value, and specular disabled, so default to 0 (From d3dm spec) */
			psDst->sSpecularOut.r = D3DM_Zero;
			psDst->sSpecularOut.g = D3DM_Zero;
			psDst->sSpecularOut.b = D3DM_Zero;
			if(psVertA->ui32Flags & D3DM_HASFLAG_FOG)
			{
				psDst->sSpecularOut.a = Add(Mul(T, Sub(psVertA->sSpecularOut.a, psVertB->sSpecularOut.a)), psVertB->sSpecularOut.a);
			}
			else
			{
				psDst->sSpecularOut.a = D3DM_Zero;
			}
		}
	}
	else /* Lighting disabled */
	{
		if(psVertA->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR)
		{
			/* 
				No lighting, but we've got a diffuse value so pass it through.
				Note: Inputs will have been copied to outputs during vertex validation
			*/

			/* If we're flat shading we will just copy the flat shading colours when we output */
			if(!(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_FLAT_SHADING))
			{
				psDst->sDiffuseOut.r =	Add(Mul(T, Sub(psVertA->sDiffuseOut.r, psVertB->sDiffuseOut.r)), psVertB->sDiffuseOut.r);
				psDst->sDiffuseOut.g =	Add(Mul(T, Sub(psVertA->sDiffuseOut.g, psVertB->sDiffuseOut.g)), psVertB->sDiffuseOut.g);
				psDst->sDiffuseOut.b =	Add(Mul(T, Sub(psVertA->sDiffuseOut.b, psVertB->sDiffuseOut.b)), psVertB->sDiffuseOut.b);
				psDst->sDiffuseOut.a =	Add(Mul(T, Sub(psVertA->sDiffuseOut.a, psVertB->sDiffuseOut.a)), psVertB->sDiffuseOut.a);
			}

⌨️ 快捷键说明

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