📄 lights.c
字号:
/******************************************************************************
<module>
* Name : Lights.c
* Title : Light-list maintenance
* 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 : Tools for maintaining a list of D3D lights. Intended to
* hold all the lights associated with a given 3D context.
*
* Platform : Windows CE
*
</module>
$Log: lights.c $
********************************************************************************/
#include "context.h"
/*----------------------------------------------------------------------------
<function>
FUNCTION : GetLight
PURPOSE : Gets a light from the list
PARAMETERS : psContext - 3D rendering context
RETURNS : PLIGHTDATA - pointer to the requested light
</function>
------------------------------------------------------------------------------*/
PLIGHTDATA GetLight(LPD3DM_CONTEXT psContext, DWORD dwIndex)
{
PLIGHTDATA psLight;
psLight = psContext->psLightList;
while((psLight != NULL) && (psLight->dwIndex != dwIndex))
{
psLight = psLight->psNext;
}
if(psLight == NULL)
{
psContext->hrLastError = D3DM_GENERICFAILURE;
return NULL;
}
return psLight;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : CreateLight
PURPOSE : Allocate and initialise a new LIGHTDATA structure and add it
to the light list
PARAMETERS : psContext - 3D rendering context
RETURNS : DWORD - The index of the new light-data
</function>
------------------------------------------------------------------------------*/
VOID CreateLight(LPD3DM_CONTEXT psContext, DWORD dwIndex)
{
PLIGHTDATA psNewLightData = NULL;
PLIGHTDATA psLightList;
/* Allocate memory for the data */
psNewLightData = (PLIGHTDATA)D3DMAllocate(sizeof(LIGHTDATA));
if(psNewLightData == NULL)
{
D3DM_DPF((DPF_LIGHT, "CreateLight: Failed to allocate space for new light-data"));
psContext->hrLastError = D3DM_GENERICFAILURE;
return;
}
/* Initialise it (mostly 0.0f) */
memset(psNewLightData, 0, sizeof(LIGHTDATA));
psNewLightData->sLightInfo.Type = D3DMLIGHT_POINT;
psNewLightData->sLightInfo.Diffuse.r = D3DM_One;
psNewLightData->sLightInfo.Diffuse.g = D3DM_One;
psNewLightData->sLightInfo.Diffuse.b = D3DM_One;
psNewLightData->sLightInfo.Direction.z = D3DM_One;
psNewLightData->sLightInfo.Position.w = D3DM_One;
psNewLightData->dwIndex = dwIndex;
psContext->dwLightCount++;
/* Add the light */
if(psContext->psLightList == NULL)
{
/* First entry */
psContext->psLightList = psNewLightData;
return;
}
else
{
/* Find the end of the current light list */
psLightList = psContext->psLightList;
while(psLightList->psNext != NULL)
{
psLightList = psLightList->psNext;
}
/* Add the light to the end */
psLightList->psNext = psNewLightData;
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : EnableLight
PURPOSE : Adds a light to the enabled light List
PARAMETERS : psContext - 3d rendering context
psLight - light to enable
RETURNS :
</function>
------------------------------------------------------------------------------*/
VOID EnableLight(LPD3DM_CONTEXT psContext, PLIGHTDATA psLight)
{
PLIGHTDATA *ppsEnabledLight;
PLIGHTDATA *ppsEnabledLightsEnd;
PSWTNLSTATE psSWTNLState;
D3DM_DPF((DPF_LIGHT, "EnableLight:Enabling light 0x%8.8X", psLight));
psSWTNLState = &psContext->sTState.sSWTNLState;
/* Do nothing if this light is already enabled */
if(psLight->dwFlags & LIGHTDATA_FLAGS_ENABLED)
return;
/* Find the first unused entry in the enabled-light list */
ppsEnabledLight = psSWTNLState->ppsEnabledLights;
ppsEnabledLightsEnd = ppsEnabledLight + MAX_LIGHTS;
*ppsEnabledLightsEnd = 0;
while(*ppsEnabledLight)
{
ppsEnabledLight++;
}
/* Add the light to the list if we found space */
if(ppsEnabledLight < ppsEnabledLightsEnd)
{
*ppsEnabledLight = psLight;
psSWTNLState->dwLightCount++;
/* Mark light as needing transform incase matrices have changed */
(*ppsEnabledLight)->dwFlags |= LIGHTDATA_FLAGS_NEED_XFORM;
}
else
{
D3DM_DPF((DPF_WARN, "EnableLight: Cannot enable light, all lights in-use"));
psContext->hrLastError = D3DM_GENERICFAILURE;
return;
}
/* Flag that the light is enabled */
psLight->dwFlags |= LIGHTDATA_FLAGS_ENABLED;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : DisableLight
PURPOSE : removes a light from the enabled light List
PARAMETERS : psContext - 3d rendering context
psLight - light to disable
RETURNS :
</function>
------------------------------------------------------------------------------*/
VOID DisableLight(LPD3DM_CONTEXT psContext, PLIGHTDATA psLight)
{
PLIGHTDATA *ppsEnabledLight;
PLIGHTDATA *ppsEnabledLightsEnd;
PSWTNLSTATE psSWTNLState;
D3DM_DPF((DPF_LIGHT, "DisableLight: Disabling light 0x%8.8X", psLight));
psSWTNLState = &psContext->sTState.sSWTNLState;
/* Do nothing if this light is not enabled */
if(!(psLight->dwFlags & LIGHTDATA_FLAGS_ENABLED))
return;
/* Find the entry for this light in the list of enabled lights */
ppsEnabledLight = psSWTNLState->ppsEnabledLights;
ppsEnabledLightsEnd = ppsEnabledLight + TNL_MAXIMUM_LIGHTS;
*ppsEnabledLightsEnd = psLight;
while (*ppsEnabledLight != psLight)
{
ppsEnabledLight++;
}
/* Remove the light from the enabled-light array */
if(ppsEnabledLight < ppsEnabledLightsEnd)
{
*ppsEnabledLightsEnd = NULL;
while (ppsEnabledLight < ppsEnabledLightsEnd)
{
*ppsEnabledLight = *(ppsEnabledLight + 1);
ppsEnabledLight++;
}
psSWTNLState->dwLightCount--;
}
else
{
D3DM_DPF((DPF_WARN, "DisableLight: Error disabling light, enabled but not in list"));
return;
}
/* Flag that the light is not enabled */
psLight->dwFlags &= ~LIGHTDATA_FLAGS_ENABLED;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : SetLightData
PURPOSE : Converts and sets the data for a D3D light
PARAMETERS : psLight - light whose data is to be set
psLightData - Data to convert\set
eDataFormat - format of data
RETURNS :
</function>
------------------------------------------------------------------------------*/
VOID SetLightData(PLIGHTDATA psLight,
D3DMLIGHT *psLightData,
D3DMFORMAT eDataFormat)
{
/* Copy/Convert the light data appropriately */
PVRCopyConvertD3DLight(psLightData,
&psLight->sLightInfo,
(eDataFormat == D3DMFMT_D3DMVALUE_FIXED));
/* record that data has changed */
psLight->dwFlags |= (LIGHTDATA_FLAGS_DATA_CHANGED | LIGHTDATA_FLAGS_NEED_XFORM);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : UpdateLights
PURPOSE : traverses enabled lights and transforms light vectors
with the current matrices
PARAMETERS : psContext - 3d rendering context
RETURNS :
</function>
------------------------------------------------------------------------------*/
VOID UpdateLights(LPD3DM_CONTEXT psContext)
{
PLIGHTDATA *ppsEnabledLight;
PVR_LIGHT *psLightInfo;
PSWTNLSTATE psSWTNLState;
psSWTNLState = &psContext->sTState.sSWTNLState;
ppsEnabledLight = psSWTNLState->ppsEnabledLights;
while(*ppsEnabledLight)
{
psLightInfo = &(*ppsEnabledLight)->sLightInfo;
if((*ppsEnabledLight)->dwFlags & LIGHTDATA_FLAGS_NEED_XFORM)
{
/* Transform the light position to view space */
TransformVector4(&psSWTNLState->sViewMatrix, &psLightInfo->Position, &psLightInfo->EyePosition);
if(psLightInfo->Type == D3DMLIGHT_DIRECTIONAL)
{
/*
if (directional lights)
Light Direction is provided in world space
therefore transform by view matrix and
normalise and reverse direction
*/
TransformVector4(&psSWTNLState->sViewInvT, &psLightInfo->Direction, &psLightInfo->EyeDirection);
Normalize((PVR_VECTOR3*)&psLightInfo->EyeDirection);
VectorNegate((PVR_VECTOR3*)&psLightInfo->EyeDirection, (PVR_VECTOR3*)&psLightInfo->EyeDirection);
}
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
(*ppsEnabledLight)->RangeSquared = Mul(psLightInfo->Range, psLightInfo->Range);
psSWTNLState->dwConstantFlags |= VGPTNL_CONST_LIGHTS_CHANGED;
#endif
/* record that we've transformed light vectors */
(*ppsEnabledLight)->dwFlags &= ~LIGHTDATA_FLAGS_NEED_XFORM;
}
/* advance to next light */
ppsEnabledLight++;
}
#if defined (SUPPORT_VGP)
/* Update light-data if required */
if(psSWTNLState->dwTNLFlags & PVRD3DTNL_FLAGS_LIGHTS_CHANGED)
{
PLIGHTDATA* ppsEnabledLights;
PLIGHTDATA* ppsSortedLightData;
PLIGHTDATA ppsPointLights[VGPTNL_MAXIMUM_LIGHTS];
DWORD dwNumEnabledLights;
DWORD dwNumDirectionalLights;
DWORD dwNumPointLights;
DWORD i;
/* Setup the TNL light-data for each of the enabled lights */
ppsEnabledLights = psSWTNLState->ppsEnabledLights;
ppsSortedLightData = psSWTNLState->ppsSortedLightData;
dwNumEnabledLights = psSWTNLState->dwLightCount;
/*
Count and sort the lights by type, placing the diffuse lights
first, followed by point.
*/
dwNumDirectionalLights = 0;
dwNumPointLights = 0;
for(i = 0; i < dwNumEnabledLights; i++)
{
PLIGHTDATA psEnabledLight;
psEnabledLight = ppsEnabledLights[i];
switch(psEnabledLight->sLightInfo.Type)
{
case D3DMLIGHT_DIRECTIONAL:
{
ppsSortedLightData[dwNumDirectionalLights] = psEnabledLight;
dwNumDirectionalLights++;
break;
}
case D3DMLIGHT_POINT:
{
ppsPointLights[dwNumPointLights] = psEnabledLight;
dwNumPointLights++;
break;
}
}
}
/* Copy point Lights and zero the rest */
memcpy(&ppsSortedLightData[dwNumDirectionalLights], ppsPointLights, dwNumPointLights * sizeof(PLIGHTDATA));
memset(&ppsSortedLightData[dwNumEnabledLights], 0, sizeof(psSWTNLState->ppsSortedLightData[0]) *
(VGPTNL_MAXIMUM_LIGHTS - dwNumEnabledLights));
/* Record the number of lights of each type */
psSWTNLState->dwDirectionalLightCount = dwNumDirectionalLights;
psSWTNLState->dwPointLightCount = dwNumPointLights;
}
#endif
}
/*****************************************************************************
End of file (Lights.c)
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -