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

📄 lights.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 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 + -