📄 vertex.c
字号:
/******************************************************************************
<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 + -