示例#1
0
void VertexFuncSmoothSphereMapAOS(
    const VERTEXINPUT &in,
    VERTEXOUTPUT &out)
{
    const FLOAT *pWorldMat = (FLOAT *)in.pConstants;
    const FLOAT *pLightPos = (FLOAT *)in.pConstants + CONST_OFFSET_LIGHT_POSITION;

    Mat4Vec3Multiply(out.pVertices, pWorldMat, (FLOAT *)in.pAttribs);

    // Transform normals in attrib buffer by world matrix.
    OSALIGNLINE(FLOAT) normals[4];
    Mat4Vec3Multiply(&normals[0], pWorldMat, &in.pAttribs[SHADER_INPUT_SLOT_NORMAL]);

    // Normalize normals
    __m128 normal = Vec3Normalize(&normals[0]);

    __m128 lightPos = _mm_load_ps(pLightPos);
    __m128 lightDir = _mm_load_ps(in.pAttribs);

    // Compute a light direction vector for each vertex.
    //     lightDir = Normalize(lightPos - vertexPos)
    lightDir = _mm_sub_ps(lightPos, lightDir);
    lightDir = Vec3Normalize(lightDir);

    __m128 ndotl0 = Vec3Diffuse(normal, lightDir);

    _mm_store_ps(&out.pAttribs[0], _mm_load_ps(&in.pAttribs[0]));

    _mm_store_ss(&out.pAttribs[0x2], ndotl0);
}
	//
	// 影响粒子
	// 注意: 只影响从KeepLocal=TRUE 到 KeepLocal=FALSE
	//
	VOID CAffectorKeepLocal::Affect(CParticle *pParticle, FLOAT deltaTime)
	{
		if (IsCanAffect(pParticle)) {
			if (pParticle->bKeepLocal && m_bKeepLocal == FALSE) {
				const VEC3 *parentWorldScale = pParticle->pEmitter->GetWorldScale();
				const VEC3 *parentWorldPosition = pParticle->pEmitter->GetWorldPosition();
				const QUAT *parentWorldOrientation = pParticle->pEmitter->GetWorldOrientation();

				QuatMul(&pParticle->localOrientation, &pParticle->localOrientation, parentWorldOrientation);

				VEC3 scalePosition;
				VEC3 scaleOrientationPosition;
				Vec3Mul(&scalePosition, &pParticle->localPosition, parentWorldScale);
				Vec3MulQuat(&scaleOrientationPosition, &scalePosition, parentWorldOrientation);
				Vec3Add(&pParticle->localPosition, &scaleOrientationPosition, parentWorldPosition);

				FLOAT velocity = Vec3Normalize(&pParticle->localVelocity);
				VEC3 localDirection;
				Vec3Set(&localDirection, 0.0f, 0.0f, 1.0f);
				Vec3MulQuat(&pParticle->localVelocity, &localDirection, &pParticle->localOrientation);
				Vec3Normalize(&pParticle->localVelocity);
				Vec3Scale(&pParticle->localVelocity, &pParticle->localVelocity, velocity);
				Vec3Mul(&pParticle->localVelocity, &pParticle->localVelocity, parentWorldScale);

				pParticle->bKeepLocal = FALSE;
			}
		}
	}
示例#3
0
// performs simple maneuvers
void CBE_Floater::AttackManeuver(CCopyEntity* pCopyEnt, SBE_EnemyExtraData *pExtraData)
{
	float& rfSensoringInterval	= pCopyEnt->f1;
	Vector3& rvDesiredDirection  = pCopyEnt->v1;
	float& rfCurrentManeuverTime = pExtraData->fCurrentManeuverTime;
	float& rfTotalManeuverTime = pExtraData->fTotalManeuverTime;
	Vector3& rvManeuverDir = pExtraData->vManeuverDirection;
	float fSqDistToPlayer = pExtraData->fLastCheckedSqDistToPlayer;

	ApplyFriction( pCopyEnt, 1.8f );

	// evasive maneuver
	if( 0.20f < rfCurrentManeuverTime - rfTotalManeuverTime ||
		rvManeuverDir == Vector3(0,0,0) )
	{
		rfCurrentManeuverTime = 0;
		rfTotalManeuverTime = 0.7f + 0.5f * (float)rand() / (float)RAND_MAX;

		// set up  a new direction
		rvManeuverDir
			+= pCopyEnt->GetRightDirection()	* ( 3.0f * (float)rand()/(float)RAND_MAX - 1.5f )
			+  pCopyEnt->GetUpDirection()		* ( 3.0f * (float)rand()/(float)RAND_MAX - 1.5f )
			+  pCopyEnt->GetDirection()			* ( 1.6f * (float)rand()/(float)RAND_MAX - 0.8f );

		if( 36.0f < fSqDistToPlayer )	// if over 6m away from player
			rvManeuverDir += rvDesiredDirection * fSqDistToPlayer / 50.0f;	// move toward the player
			
		Vec3Normalize( rvManeuverDir, rvManeuverDir );
	}
	else
		rfCurrentManeuverTime += m_pStage->GetFrameTime();

	if( 0.5f < rfTotalManeuverTime - rfCurrentManeuverTime )
	{
//		float fWishSpeed = 12.0f;
		float fWishSpeed = 10.0f * m_fMobility;
		Accelerate( pCopyEnt, rvManeuverDir, fWishSpeed, 4.0f );
	}


	if( rfSensoringInterval == 0 )
	{	// check if there is an obstacle in the direction to which the entity is heading
		STrace tr;
		tr.bvType = BVTYPE_AABB;
		tr.aabb   = this->m_aabb;
		tr.pSourceEntity = pCopyEnt;
		tr.vStart       = pCopyEnt->GetWorldPosition();
		tr.vGoal        = pCopyEnt->GetWorldPosition() + pCopyEnt->vVelocity * 1.2f;
		tr.SetAABB();
		m_pStage->ClipTrace(tr);
		// since the entity is heading for some obstacle, correct the velocity to avoid it
		if( tr.fFraction < 1.0f )
		{
			pCopyEnt->vVelocity += tr.plane.normal * (1.0f - tr.fFraction ) * 3.0f; // m_pStage->GetFrameTime();
		}
	}

	SlideMove( pCopyEnt );
}
示例#4
0
int CPolyMesh3::CalcNormal( D3DXVECTOR3* newn, D3DXVECTOR3* curp, D3DXVECTOR3* aftp1, D3DXVECTOR3* aftp2 )
{
	D3DXVECTOR3 vec1, vec2, crossvec;

	vec1 = *aftp1 - *curp;
	vec2 = *aftp2 - *curp;

	if( vec1 != vec2 ){
		Vec3Cross( &crossvec, &vec1, &vec2 );
	}else{
		crossvec = *curp;
	}

	Vec3Normalize( newn, &crossvec );

	return 0;
}
示例#5
0
void CES_Search::Act( CCopyEntity& rEntity, CBE_Enemy& rBaseEntity, float dt )
{
	// first, get the extra data of 'pCopyEnt'
	SBE_EnemyExtraData* pExtraData = rBaseEntity.GetExtraData( rEntity.iExtraDataIndex );

	short& rsCurrentState = rEntity.s1;
	float& rfSensoringInterval	= rEntity.f1;
	Vector3& rvDesiredDirection  = rEntity.v1;
	float fSqDistToPlayer;

	rfSensoringInterval += dt;

	if( 0.32f <= rfSensoringInterval )
	{
		rfSensoringInterval = 0;

		// check if the player is in a visible position and update 'rvDesiredDirection' and 'rsMode'
		short sSearchResult = 0;
		rBaseEntity.SearchPlayer( &rEntity, sSearchResult, rvDesiredDirection, &fSqDistToPlayer );

		if( sSearchResult == STATE_ATTACK )
		{	// the player is in sight - engage
			rsCurrentState = STATE_ATTACK;
			rBaseEntity.UpdateDesiredYawAndPitch( &rEntity, rvDesiredDirection );
			pExtraData->vLastCheckedDirectionToPlayer = rvDesiredDirection;
			pExtraData->fLastCheckedSqDistToPlayer    = fSqDistToPlayer;
			pExtraData->vLastCheckedPlayerPosition = rvDesiredDirection * (float)sqrt(fSqDistToPlayer);
			return;
		}
		else
		{	// lost sight of the player
			if( pExtraData->vLastCheckedPlayerPosition != Vector3(0,0,0) )
			{
				Vector3 vDir = pExtraData->vLastCheckedPlayerPosition - rEntity.GetWorldPosition();
				Vec3Normalize( rvDesiredDirection, vDir );
			}
		}
	}

	rBaseEntity.SearchManeuver(&rEntity,pExtraData);
}
//-----------------------------------------------------------------------------
// Set Light
//-----------------------------------------------------------------------------
void RSPLightManager::setLight( unsigned int lightIndex, unsigned int rdramAddress  )
{
    //Error control 
    if ((rdramAddress + sizeof(RDRAMLight)) > m_memory->getRDRAMSize() ) {
        return;
    }

    //Get Light from memory
    RDRAMLight* light = (RDRAMLight*)m_memory->getRDRAM(rdramAddress);

    if ( lightIndex < 8 ) //Only supports 8 lights
    {
        m_lights[lightIndex].r = light->r * 0.0039215689f;  //Convert from 0-255 to 0-1
        m_lights[lightIndex].g = light->g * 0.0039215689f;
        m_lights[lightIndex].b = light->b * 0.0039215689f;

        m_lights[lightIndex].x = light->x;
        m_lights[lightIndex].y = light->y;
        m_lights[lightIndex].z = light->z;    

        Vec3Normalize( &m_lights[lightIndex].x );
    }
}
示例#7
0
void C3d::Render()
{
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,255), 1.0f, 0);
	//IDirect3DSurface9* backbuffer = 0;
	//mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
	//g_pd3dDevice->SetRenderTarget(0, backbuffer);
	//g_pd3dDevice->SetDepthStencilSurface(mDepthStencil);
	//SAFE_RELEASE(backbuffer);

	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
	{
		SetupMatrices();
		Vec3Normalize(&light.Direction, &(D3DXVECTOR3(cosf(alight), -1.0f, sinf(alight))));
		g_pd3dDevice->SetLight( 0, &light );
		g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
		g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		for(dword i = 0; i < g_pIB.size(); i++)
		{
			LPDIRECT3DTEXTURE9 tmp = g_pTexture[i];
			g_pd3dDevice->SetTexture( 0, tmp );
			g_pd3dDevice->SetIndices( g_pIB[i]);
			if(loaded)
			{
				// Draw 10 surfaces based on selection in GUI
				if( (9 >= i) && (1 == drawSurface[i]) )
					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,vcount,0,fcount[i]);
				// If we have more surfaces always draw them
				else if ( 9 < i )
					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,vcount,0,fcount[i]);
			}
		}
		g_pd3dDevice->EndScene();
	}
	g_pd3dDevice->Present(0, 0, 0, 0);
	//mSwapChain->Present(0, 0, m_hWnd, 0, 0);
	//mSwapChain->Present(0, 0, 0, 0, 0);
}
示例#8
0
/**
Update the enemy's position.
@param timeElapsed The time that has elapsed since the last clock tick.
@see PrecisionTimer
*/
void Enemy::update(float time_elapsed)
{
	Vector3 steering_force;
	Vector3 acceleration;
	
	if (mAlive && mHP > 0)
	{
		setHeight(mPosition);
		render();
		
		steering_force = mSteering->calculate();	//calculate the combined force from each steering behavior in the vehicle's list
		acceleration = steering_force / mMass;	//Acceleration = Force/Mass
		mVelocity += acceleration * time_elapsed;		//update velocity
		mVelocity.truncate(mMaxSpeed);					//make sure vehicle does not exceed maximum velocity
		mPosition += mVelocity * time_elapsed;			//update the position
		
		//update the heading if the vehicle has a non zero velocity
		if (mVelocity.lengthSq() > 0.00000001)
		{
			mHeading = Vec3Normalize(mVelocity);
			mSide = Cross(mHeading, getRotation());
		}
		
		float player_to_enemy = Vec3Distance(mGameWorld.mPlayer->mPosition, this->getPosition());
		
		// If player is within n units of enemy.
		if (player_to_enemy <= 40)
		{
			this->mSteering->setTarget(mGameWorld.mPlayer->getPosition());
			this->mSteering->followPathOff();
			this->mSteering->seekOn();
			
			float dx = mGameWorld.mPlayer->getPosition().x - this->getPosition().x;
			float dz = mGameWorld.mPlayer->getPosition().z - this->getPosition().z;
			setRotation(Vector3(0, RAD2DEG(atan2(dx,dz)), 0));
		}
		else
		{
			float dx = mSteering->GetPath()->CurrentWaypoint().x - this->getPosition().x;
			float dz = mSteering->GetPath()->CurrentWaypoint().z - this->getPosition().z;
			setRotation(Vector3(0, RAD2DEG(atan2(dx,dz)), 0));
			
			this->mSteering->followPathOn();
			this->mSteering->seekOff();
		}
		
		if (player_to_enemy <= 10)
		{
			playerCloseCounter++;
			
			if (playerCloseCounter > 30)
			{
				mGameWorld.mPlayer->hurt(5); // damage the player
				playerCloseCounter = 0;
			}
			mMesh.initAnim(2);
		}
		else
		{
			mMesh.initAnim(1);
			if (playerCloseCounter > 0)
			{
				playerCloseCounter--;
			}
		}
		
		if (player_to_enemy <= 15)
		{
			int mx, my, mb;
			CML_GetMouse(&mx,&my,&mb);
			
			if (hurtCounter == 0 && (mb & CML_INPUT_MOUSEBUTTON_LEFT))
			{
				mMesh.initAnim(3);
				this->hurt(10);
				hurtCounter++;
			}
			else if (hurtCounter > 0 && hurtCounter <= 30)
				hurtCounter++;
			else if (hurtCounter > 30)
				hurtCounter = 0;
		}
		else
		{
			if (hurtCounter > 0)
			{
				hurtCounter--;
			}
		}
	}
	else if (mAlive && mHP <= 0)
	{
		mAlive = false;	
		mGameWorld.mEnemyCounter--;
	}
}
示例#9
0
void CBE_Floater::SearchManeuver(CCopyEntity* pCopyEnt, SBE_EnemyExtraData *pExtraData)
{
	Vector3& rvDesiredDirection  = pCopyEnt->v1;
	Vector3& rvTargetPosition    = pExtraData->vTargetPosition;
	float& rfSensoringInterval2      = pExtraData->fSensoringInterval2;
	float& rfCurrentManeuverTime     = pExtraData->fCurrentManeuverTime;
	float& rfTotalManeuverTime       = pExtraData->fTotalManeuverTime;
	Vector3& rvManeuverDir       = pExtraData->vManeuverDirection;
	float fWishSpeed = 6.0f;

	const float frametime = m_pStage->GetFrameTime();

//	if( pCopyEnt->vVelocity == Vector3(0,0,0) )
//		return;

	ApplyFriction( pCopyEnt, 1.5f );

	if( m_iRandomSearchManeuver != 0 )
	{
		Vector3 vFromCurrentPosToDest = rvTargetPosition - pCopyEnt->GetWorldPosition();
		float fDist = Vec3LengthSq( vFromCurrentPosToDest );

		if( 0.20f < rfCurrentManeuverTime - rfTotalManeuverTime ||
			rvManeuverDir == Vector3(0,0,0) || fDist < 0.2f )
		{
			rfCurrentManeuverTime = 0;
			rfTotalManeuverTime = 1.0f + 0.6f * (float)rand() / (float)RAND_MAX;

			// set up a target locaion
			rvTargetPosition
				= pExtraData->vOriginalPosition
				+ Vector3(1,0,0) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f )
				+ Vector3(0,1,0) * (  6.0f * (float)rand()/(float)RAND_MAX - 3.0f )
				+ Vector3(0,0,1) * ( 12.0f * (float)rand()/(float)RAND_MAX - 6.0f )
				+ pCopyEnt->GetDirection() * 2.5f;

			Vec3Normalize( rvManeuverDir, rvManeuverDir );
		}
		else
			rfCurrentManeuverTime += frametime;

		if( 0.16f < rfSensoringInterval2 )
		{
			rfSensoringInterval2 = 0.0f;
			Vec3Normalize( rvManeuverDir, vFromCurrentPosToDest );
		}
		else
			rfSensoringInterval2 += frametime;

		if( 0.1f < rfTotalManeuverTime - rfCurrentManeuverTime )
		{
			float fWishSpeed = 4.5f;
			Accelerate( pCopyEnt, rvManeuverDir, fWishSpeed, 2.0f );
		}

		UpdateDesiredYawAndPitch(pCopyEnt, rvManeuverDir);
		AimAlong(pCopyEnt, rvManeuverDir);
	}

	SlideMove( pCopyEnt );
}
	//
	// 更新
	//
	VOID CGfxBillboard::Update(const CEntityCamera *pCamera, CParticle *pParticleList, INT numParticles)
	{
		//
		// 1. 参数安全检查
		//
		if (pCamera == NULL || pParticleList == NULL || numParticles <= 0) {
			return;
		}

		//
		// 2. 更新相机矩阵
		//
		if (m_directionType == DIRECTION_CAMERA) {
			VEC3 direction;
			VEC3 position, up, target;

			Vec3Scale(&direction, pCamera->GetForwardDirection(), -1.0f);
			Vec3Set(&up, 0.0f, 1.0f, 0.0f);
			Vec3Set(&position, 0.0f, 0.0f, 0.0f);
			Vec3Ma(&target, &position, &direction, 1.0f);

			MtxDefLookAt(&m_mtxFaceToCamera, &position, &up, &target);
		}

		//
		// 3. 更新粒子数据
		//
		VERTEX *vertices = (VERTEX *)SAFE_MALLOC(4 * numParticles * sizeof(*vertices), MEMTYPE_STACK);
		{
			//    Billboard
			//    0 ___ 3
			//     |   |
			//     |___|
			//    1     2

			INT indexVertex = 0;
			CParticle *pParticle = pParticleList;

			while (pParticle) {
				const VEC3 *parentWorldScale = pParticle->pEmitter->GetWorldScale();
				const VEC3 *parentWorldPosition = pParticle->pEmitter->GetWorldPosition();
				const QUAT *parentWorldOrientation = pParticle->pEmitter->GetWorldOrientation();

				//
				// 1. 计算粒子位置与朝向
				//
				VEC3 scale;
				VEC3 position;
				QUAT orientation;

				if (pParticle->bKeepLocal && pParticle->pEmitter) {
					Vec3Mul(&scale, &pParticle->localScale, parentWorldScale);

					if (m_directionType == DIRECTION_FIXED) {
						QuatMul(&orientation, &pParticle->localOrientation, parentWorldOrientation);
					}

					VEC3 scalePosition;
					VEC3 scaleOrientationPosition;
					Vec3Mul(&scalePosition, &pParticle->localPosition, parentWorldScale);
					Vec3MulQuat(&scaleOrientationPosition, &scalePosition, parentWorldOrientation);
					Vec3Add(&position, &scaleOrientationPosition, parentWorldPosition);
				}
				else {
					Vec3Copy(&scale, &pParticle->localScale);

					if (m_directionType == DIRECTION_FIXED) {
						QuatCopy(&orientation, &pParticle->localOrientation);
					}

					Vec3Copy(&position, &pParticle->localPosition);
				}

				//
				// 2. 粒子位置偏移量
				//
				MATRIX4 mtxOrientation;

				if (m_directionType == DIRECTION_CAMERA) {
					MtxCopy(&mtxOrientation, &m_mtxFaceToCamera);

					if (m_offset < -EPSILON_E3 || m_offset > EPSILON_E3) {
						VEC3 offsetDirection;
						Vec3Sub(&offsetDirection, pCamera->GetPosition(), &position);
						Vec3Normalize(&offsetDirection);
						Vec3Ma(&position, &position, &offsetDirection, m_offset);
					}
				}
				else {
					QuatToMtxRotation(&mtxOrientation, &orientation);

					if (m_offset < -EPSILON_E3 || m_offset > EPSILON_E3) {
						VEC3 localDirection;
						VEC3 offsetDirection;
						Vec3Set(&localDirection, 0.0f, 0.0f, 1.0f);
						Vec3MulQuat(&offsetDirection, &localDirection, &orientation);
						Vec3Normalize(&offsetDirection);
						Vec3Ma(&position, &position, &offsetDirection, m_offset);
					}
				}

				//
				// 3. 计算粒子变换矩阵
				//
				MATRIX4 mtxScale;
				MATRIX4 mtxRotate;
				MATRIX4 mtxRotateSelf;
				MATRIX4 mtxTranslate;
				MtxDefScale(&mtxScale, scale[0], scale[1], scale[2]);
				MtxDefTranslate(&mtxTranslate, position[0], position[1], position[2]);
				MtxDefRotateAxisAngle(&mtxRotateSelf, &axisz, pParticle->radian);
				MtxMul(&mtxRotate, &mtxRotateSelf, &mtxOrientation);

				MATRIX4 mtxSR;
				MATRIX4 mtxTransform;
				MtxMul(&mtxSR, &mtxScale, &mtxRotate);
				MtxMul(&mtxTransform, &mtxSR, &mtxTranslate);

				//
				// 4. 计算粒子纹理矩阵
				//
				MATRIX4 mtxTexScale;
				MATRIX4 mtxTexTranslate;
				MATRIX4 mtxTexTransform;
				MtxDefScale(&mtxTexScale, pParticle->texSequenceScale[0], pParticle->texSequenceScale[1], 1.0f);
				MtxDefTranslate(&mtxTexTranslate, pParticle->texSequenceOffset[0] + pParticle->texScrollOffset[0], pParticle->texSequenceOffset[1] + pParticle->texScrollOffset[1], 0.0f);
				MtxMul(&mtxTexTransform, &mtxTexScale, &mtxTexTranslate);

				//
				// 5. 计算粒子顶点
				//
				VEC3 desVertices[4];
				VEC3 srcVertices[4] = {
					VEC3(-1.0f,  1.0f, 0.0f),
					VEC3(-1.0f, -1.0f, 0.0f),
					VEC3( 1.0f, -1.0f, 0.0f),
					VEC3( 1.0f,  1.0f, 0.0f),
				};

				VEC2 texCoords[4] = {
					VEC2(pParticle->uvOffset[0] + 0.0f, pParticle->uvOffset[1] + 0.0f),
					VEC2(pParticle->uvOffset[0] + 0.0f, pParticle->uvOffset[1] + 1.0f),
					VEC2(pParticle->uvOffset[0] + 1.0f, pParticle->uvOffset[1] + 1.0f),
					VEC2(pParticle->uvOffset[0] + 1.0f, pParticle->uvOffset[1] + 0.0f),
				};

				VEC3 localNormal, localBinormal;
				VEC3 worldNormal, worldBinormal;

				Vec3Set(&localNormal, 0.0f, 0.0f, 1.0f);
				Vec3Set(&localBinormal, 1.0f, 0.0f, 0.0f);
				Vec3MulMtx3x3(&worldNormal, &localNormal, &mtxTransform);
				Vec3MulMtx3x3(&worldBinormal, &localBinormal, &mtxTransform);

				Vec3MulMtx4x4(&desVertices[0], &srcVertices[0], &mtxTransform);
				Vec3MulMtx4x4(&desVertices[1], &srcVertices[1], &mtxTransform);
				Vec3MulMtx4x4(&desVertices[2], &srcVertices[2], &mtxTransform);
				Vec3MulMtx4x4(&desVertices[3], &srcVertices[3], &mtxTransform);

				Vec3Copy(&vertices[indexVertex].position, &desVertices[0]);
				Vec3Copy(&vertices[indexVertex].normal, &worldNormal);
				Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal);
				Vec4Copy(&vertices[indexVertex].color, &pParticle->color);
				Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[0], &mtxTexTransform);
				indexVertex++;

				Vec3Copy(&vertices[indexVertex].position, &desVertices[1]);
				Vec3Copy(&vertices[indexVertex].normal, &worldNormal);
				Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal);
				Vec4Copy(&vertices[indexVertex].color, &pParticle->color);
				Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[1], &mtxTexTransform);
				indexVertex++;

				Vec3Copy(&vertices[indexVertex].position, &desVertices[2]);
				Vec3Copy(&vertices[indexVertex].normal, &worldNormal);
				Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal);
				Vec4Copy(&vertices[indexVertex].color, &pParticle->color);
				Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[2], &mtxTexTransform);
				indexVertex++;

				Vec3Copy(&vertices[indexVertex].position, &desVertices[3]);
				Vec3Copy(&vertices[indexVertex].normal, &worldNormal);
				Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal);
				Vec4Copy(&vertices[indexVertex].color, &pParticle->color);
				Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[3], &mtxTexTransform);
				indexVertex++;

				pParticle = pParticle->pNext;
			}

			Renderer()->BindVBO(GL_ARRAY_BUFFER, m_vbo);
			Renderer()->UpdateVBO(GL_ARRAY_BUFFER, 0, 4 * numParticles * sizeof(*vertices), vertices);
		}
		SAFE_FREE(vertices);
	}
示例#11
0
	//--------------------------------------------------------------------------------------------------------------
	//获取该矢量的单位化矢量
	Vector3 Vector3::GetNormalizedVec() const
	{
		static Vector3 tmp;
		Vec3Normalize( &tmp, this );
		return tmp;
	}
示例#12
0
	//--------------------------------------------------------------------------------------------------------------
	//单位化该矢量
	void Vector3::Normalize()
	{
		Vec3Normalize( this, this );
	}
示例#13
0
bool ModelImport::ImportObj(const std::string& srcFilename, std::string& dstFilename)
{
	const AssetLib::AssetDef& rAssetDef = AssetLib::Model::GetAssetDef();

	std::ifstream srcFile(srcFilename);
	assert(srcFile.is_open());

	std::ofstream dstFile(dstFilename, std::ios::binary);
	assert(dstFile.is_open());

	// Write header
	AssetLib::BinFileHeader header;
	header.binUID = AssetLib::BinFileHeader::kUID;
	header.assetUID = rAssetDef.GetAssetUID();
	header.version = rAssetDef.GetBinVersion();
	header.srcHash = Hashing::SHA1();
	dstFile.write((char*)&header, sizeof(header));

	// Build and write the main geo data
	GeoData geo;
	ObjData obj;

	char line[1024];
	int lineNum = 0; // for debugging

	while (srcFile.getline(line, 1024))
	{
		++lineNum;

		char* context = nullptr;
		char* tok = strtok_s(line, " ", &context);

		if (strcmp(tok, "v") == 0)
		{
			// Position
			Vec3 pos;
			pos.x = (float)atof(strtok_s(nullptr, " ", &context));
			pos.y = (float)atof(strtok_s(nullptr, " ", &context));
			pos.z = (float)atof(strtok_s(nullptr, " ", &context));
			obj.positions.push_back(pos);
		}
		else if (strcmp(tok, "vn") == 0)
		{
			// Normal
			Vec3 norm;
			norm.x = (float)atof(strtok_s(nullptr, " ", &context));
			norm.y = (float)atof(strtok_s(nullptr, " ", &context));
			norm.z = (float)atof(strtok_s(nullptr, " ", &context));
			obj.normals.push_back(norm);
		}
		else if (strcmp(tok, "vt") == 0)
		{
			// Tex coord
			Vec2 uv;
			uv.x = (float)atof(strtok_s(nullptr, " ", &context));
			uv.y = (float)atof(strtok_s(nullptr, " ", &context));
			obj.texcoords.push_back(uv);
		}
		else if (strcmp(tok, "f") == 0)
		{
			// Face
			for (int i = 0; i < 3; ++i)
			{
				ObjVertex objVert;
				objVert.iPos = atoi(strtok_s(nullptr, "/ ", &context)) - 1;
				objVert.iUv = atoi(strtok_s(nullptr, "/ ", &context)) - 1;
				objVert.iNorm = atoi(strtok_s(nullptr, "/ ", &context)) - 1;

				// Find matching vert to re-use.
				int reuseIndex = -1;
				for (int v = (int)obj.verts.size() - 1; v >= 0; --v)
				{
					const ObjVertex& otherVert = obj.verts[v];
					if (otherVert.iPos == objVert.iPos && otherVert.iUv == objVert.iUv && otherVert.iNorm == objVert.iNorm)
					{
						reuseIndex = v;
						break;
					}
				}

				if (reuseIndex >= 0)
				{
					geo.indices.push_back((uint16)reuseIndex);
				}
				else
				{
					geo.indices.push_back((uint16)geo.positions.size());

					Color color = { 1.f, 1.f, 1.f, 1.f };
					geo.positions.push_back(obj.positions[objVert.iPos]);
					geo.texcoords.push_back(obj.texcoords[objVert.iUv]);
					geo.normals.push_back(obj.normals[objVert.iNorm]);
					geo.colors.push_back(color);

					obj.verts.push_back(objVert);
				}
			}
		}
		else if (strcmp(tok, "usemtl") == 0)
		{
			std::string material = strtok_s(nullptr, " ", &context);
			obj.materials.push_back(material);

			obj.subobjectStartIndices.push_back((uint)geo.indices.size());
		}
	}

	obj.subobjectStartIndices.push_back((uint)geo.indices.size());
	geo.tangents.resize(geo.positions.size());
	geo.bitangents.resize(geo.positions.size());

	// TODO: Tangents/bitangents for shared verts
	for (uint i = 0; i < geo.indices.size(); i += 3)
	{
		uint v0 = geo.indices[i + 0];
		uint v1 = geo.indices[i + 1];
		uint v2 = geo.indices[i + 2];
		const Vec3& pos0 = geo.positions[v0];
		const Vec3& pos1 = geo.positions[v1];
		const Vec3& pos2 = geo.positions[v2];
		const Vec2& uv0 = geo.texcoords[v0];
		const Vec2& uv1 = geo.texcoords[v1];
		const Vec2& uv2 = geo.texcoords[v2];

		Vec3 edge1 = pos1 - pos0;
		Vec3 edge2 = pos2 - pos0;

		Vec2 uvEdge1 = uv1 - uv0;
		Vec2 uvEdge2 = uv2 - uv0;

		float r = 1.f / (uvEdge1.y * uvEdge2.x - uvEdge1.x * uvEdge2.y);

		Vec3 tangent = (edge1 * -uvEdge2.y + edge2 * uvEdge1.y) * r;
		Vec3 bitangent = (edge1 * -uvEdge2.x + edge2 * uvEdge1.x) * r;

		tangent = Vec3Normalize(tangent);
		bitangent = Vec3Normalize(bitangent);

		geo.tangents[v0] = geo.tangents[v1] = geo.tangents[v2] = tangent;
		geo.bitangents[v0] = geo.bitangents[v1] = geo.bitangents[v2] = bitangent;
	}

	// Calc radius
	Vec3 vMin(FLT_MAX, FLT_MAX, FLT_MAX);
	Vec3 vMax(-FLT_MIN, -FLT_MIN, -FLT_MIN);
	for (int i = (int)geo.positions.size() - 1; i >= 0; --i)
	{
		vMin.x = std::min(geo.positions[i].x, vMin.x);
		vMax.x = std::max(geo.positions[i].x, vMax.x);
		vMin.y = std::min(geo.positions[i].y, vMin.y);
		vMax.y = std::max(geo.positions[i].y, vMax.y);
		vMin.z = std::min(geo.positions[i].z, vMin.z);
		vMax.z = std::max(geo.positions[i].z, vMax.z);
	}

	Vec3 modelBoundsMin(FLT_MAX, FLT_MAX, FLT_MAX);
	Vec3 modelBoundsMax(-FLT_MIN, -FLT_MIN, -FLT_MIN);
	uint totalVertCount = 0;
	for (int i = 0; i < obj.subobjectStartIndices.size() - 1; ++i)
	{
		AssetLib::Model::SubObject subobj;

		strcpy_s(subobj.materialName, obj.materials[i].c_str());
		subobj.indexCount = obj.subobjectStartIndices[i + 1] - obj.subobjectStartIndices[i];

		uint16 vertMin = -1;
		uint16 vertMax = 0;
		subobj.boundsMin = Vec3(FLT_MAX, FLT_MAX, FLT_MAX);
		subobj.boundsMax = Vec3(-FLT_MIN, -FLT_MIN, -FLT_MIN);
		for (uint tri = obj.subobjectStartIndices[i]; tri < obj.subobjectStartIndices[i + 1]; ++tri)
		{
			uint16 iVert = geo.indices[tri];
			vertMin = std::min(iVert, vertMin);
			vertMax = std::max(iVert, vertMax);

			subobj.boundsMin.x = std::min(geo.positions[iVert].x, subobj.boundsMin.x);
			subobj.boundsMax.x = std::max(geo.positions[iVert].x, subobj.boundsMax.x);
			subobj.boundsMin.y = std::min(geo.positions[iVert].y, subobj.boundsMin.y);
			subobj.boundsMax.y = std::max(geo.positions[iVert].y, subobj.boundsMax.y);
			subobj.boundsMin.z = std::min(geo.positions[iVert].z, subobj.boundsMin.z);
			subobj.boundsMax.z = std::max(geo.positions[iVert].z, subobj.boundsMax.z);
		}

		subobj.vertCount = (vertMax - vertMin) + 1;
		totalVertCount += subobj.vertCount;

		modelBoundsMin = Vec3Min(modelBoundsMin, subobj.boundsMin);
		modelBoundsMax = Vec3Max(modelBoundsMax, subobj.boundsMax);

		geo.subobjects.push_back(subobj);
	}

	assert(totalVertCount == (uint)geo.positions.size());

	AssetLib::Model modelBin;
	modelBin.totalVertCount = totalVertCount;
	modelBin.totalIndexCount = (uint)geo.indices.size();
	modelBin.boundsMin = modelBoundsMin;
	modelBin.boundsMax = modelBoundsMax;
	modelBin.subObjectCount = (uint)geo.subobjects.size();
	modelBin.subobjects.offset = 0;
	modelBin.positions.offset = modelBin.subobjects.offset + modelBin.subobjects.CalcSize(modelBin.subObjectCount);
	modelBin.texcoords.offset = modelBin.positions.offset + modelBin.positions.CalcSize(totalVertCount);
	modelBin.normals.offset = modelBin.texcoords.offset + modelBin.texcoords.CalcSize(totalVertCount);
	modelBin.colors.offset = modelBin.normals.offset + modelBin.normals.CalcSize(totalVertCount);
	modelBin.tangents.offset = modelBin.colors.offset + modelBin.colors.CalcSize(totalVertCount);
	modelBin.bitangents.offset = modelBin.tangents.offset + modelBin.tangents.CalcSize(totalVertCount);
	modelBin.indices.offset = modelBin.bitangents.offset + modelBin.bitangents.CalcSize(totalVertCount);

	dstFile.write((char*)&modelBin, sizeof(AssetLib::Model));
	dstFile.write((char*)geo.subobjects.data(), sizeof(geo.subobjects[0]) * geo.subobjects.size());
	dstFile.write((char*)geo.positions.data(), sizeof(geo.positions[0]) * geo.positions.size());
	dstFile.write((char*)geo.texcoords.data(), sizeof(geo.texcoords[0]) * geo.texcoords.size());
	dstFile.write((char*)geo.normals.data(), sizeof(geo.normals[0]) * geo.normals.size());
	dstFile.write((char*)geo.colors.data(), sizeof(geo.colors[0]) * geo.colors.size());
	dstFile.write((char*)geo.tangents.data(), sizeof(geo.tangents[0]) * geo.tangents.size());
	dstFile.write((char*)geo.bitangents.data(), sizeof(geo.bitangents[0]) * geo.bitangents.size());
	dstFile.write((char*)geo.indices.data(), sizeof(geo.indices[0]) * geo.indices.size());

	return true;
}
void RSPVertexManager::_processVertex( unsigned int v )
{
//    float intensity;
//    float r, g, b;

    transformVertex( m_matrixMgr->getViewProjectionMatrix(), &m_vertices[v].x, &m_vertices[v].x);
    //TransformVertex( &m_vertices[v].x, m_worldProject );


    if ( m_billboard )
    {
        m_vertices[v].x += m_vertices[0].x;
        m_vertices[v].y += m_vertices[0].y;
        m_vertices[v].z += m_vertices[0].z;
        m_vertices[v].w += m_vertices[0].w;
    }


    if ( !OpenGLManager::getSingleton().getZBufferEnabled() )
    {
        m_vertices[v].z = -m_vertices[v].w;
    }

    //Temporary variables
    float intensity;
    float r, g, b;

    if ( m_lightMgr->getLightEnabled() )
    {
        //Transform normal
        transformVector( m_matrixMgr->getModelViewMatrix(), &m_vertices[v].nx, &m_vertices[v].nx );
        Vec3Normalize( &m_vertices[v].nx );

        //Get Ambient Color
        const float* ambientColor = m_lightMgr->getAmbientLight();
        r = ambientColor[0];
        g = ambientColor[1];
        b = ambientColor[2];

        for (int i=0; i<m_lightMgr->getNumLights(); ++i)
        {
            intensity = DotProduct( (float*)&m_vertices[v].nx, (float*)m_lightMgr->getLightDirection(i) );

            if (intensity < 0.0f) intensity = 0.0f;

            const float* lightColor = m_lightMgr->getLightColor(i);
            r += lightColor[0] * intensity;
            g += lightColor[1] * intensity;
            b += lightColor[2] * intensity;
        }

        //Set Color
        m_vertices[v].r = r;
        m_vertices[v].g = g;
        m_vertices[v].b = b;    
    }

    //Texture Generation
    if ( m_texCoordGenType != TCGT_NONE )
    {
        transformVector( m_matrixMgr->getProjectionMatrix(), &m_vertices[v].nx, &m_vertices[v].nx );

        Vec3Normalize( &m_vertices[v].nx );

        if ( m_texCoordGenType == TCGT_LINEAR )
        {   
            m_vertices[v].s = acosf(m_vertices[v].nx) * 325.94931f;
            m_vertices[v].t = acosf(m_vertices[v].ny) * 325.94931f;
        }
        else // TGT_GEN
        {
            m_vertices[v].s = (m_vertices[v].nx + 1.0f) * 512.0f;
            m_vertices[v].t = (m_vertices[v].ny + 1.0f) * 512.0f;
        }
    }

    //Clipping
    if (m_vertices[v].x < -m_vertices[v].w)  
        m_vertices[v].xClip = -1.0f;
    else if (m_vertices[v].x > m_vertices[v].w)
        m_vertices[v].xClip = 1.0f;
    else
        m_vertices[v].xClip = 0.0f;

    if (m_vertices[v].y < -m_vertices[v].w)
        m_vertices[v].yClip = -1.0f;
    else if (m_vertices[v].y > m_vertices[v].w)
        m_vertices[v].yClip = 1.0f;
    else
        m_vertices[v].yClip = 0.0f;

    if (m_vertices[v].w <= 0.0f)
        m_vertices[v].zClip = -1.0f;
    else if (m_vertices[v].z < -m_vertices[v].w)
        m_vertices[v].zClip = -0.1f;
    else if (m_vertices[v].z > m_vertices[v].w)
        m_vertices[v].zClip = 1.0f;
    else
        m_vertices[v].zClip = 0.0f;

}
示例#15
0
//-------------------------------------
// Action()
//-------------------------------------
void FbxGrandfather::Action(
	Object *target,
	const float range,
	D3DXVECTOR3 my_position)
{
	//-------------------------------------
	// Xモデルと当たったら
	if (target->parameter().layer_ == LAYER_MODEL_FORT ||
		target->parameter().layer_ == LAYER_MODEL_CHILD){
		Vector3 vec = target->parameter().position_ - parameter_.position_;
		Vector3 v = vec;
		Vec3Normalize(vec, vec);
		float distance = sqrtf(
			(v.x_ * v.x_) + (v.y_ * v.y_) + (v.z_ * v.z_));
		float sub = range - distance;
		vec *= sub;
		parameter_.position_ -= vec;
	}

	//-------------------------------------
	// 湖と当たったら
	if (target->parameter().layer_ == LAYER_SPRITE_LAKE){
		if (GamePad::isPress(GAMEPAD_GRANDFATHER, PAD_BUTTON_5) 
			&& !GamePad::isPress(GAMEPAD_GRANDFATHER, PAD_BUTTON_8)
			&& water_gauge_ < 1.0f){
			if (water_supply_enable_){
				//-------------------------------------
				// シーン取得
				Scene *scene = SceneManager::GetCurrentScene();
				std::string str = SceneManager::GetCurrentSceneName();
				if (str == "Game"){
					Game *game = dynamic_cast<Game*>(scene);

					// 水補給
					water_gauge_ += GRANDFATHER_SUB_BULLET_WATERGAUGE;
					water_gauge_ = std::min<float>(water_gauge_, 1.0f);
					Object *obj = game->object_manager()->Get("water_gage");
					WaterGage *water_gage_obj = static_cast<WaterGage*>(obj);
					water_gage_obj->SetChangeValue(water_gauge_);
					// 重複防止
					water_supply_enable_ = false;

					if (water_supply_effect_timer_ % 45 == 0)
					{
						// 補給エフェクト
						OBJECT_PARAMETER_DESC grandfather_parameter = this->parameter();
						EFFECT_PARAMETER_DESC effect_param;
						MyEffect *effect = game->effect_manager()->Get("watersupply");
						effect_param = effect->parameter();
						effect_param.position_ = grandfather_parameter.position_;
						effect_param.position_.x_ += sinf(grandfather_parameter.rotation_.y_)*0.2f;
						effect_param.position_.z_ += cosf(grandfather_parameter.rotation_.y_)*0.2f;
						effect_param.position_.y_ += 0.5f;
						effect->SetParameter(effect_param);
						game->effect_manager()->Play("watersupply");
                        //-------------------------------------
                        // 弾補給SE再生
                        Sound::LoadAndPlaySE("resource/sound/se/game/chargeWater.wav");
					}
					// 補給泡エフェクト
					OBJECT_PARAMETER_DESC grandfather_parameter = this->parameter();
					EFFECT_PARAMETER_DESC effect_param;
					MyEffect *effect = game->effect_manager()->Get("watersupplybubble");
					effect_param = effect->parameter();
					effect_param.position_ = grandfather_parameter.position_;
					effect_param.position_.y_ += 0.2f;
					effect->SetParameter(effect_param);
					game->effect_manager()->Play("watersupplybobble");


					water_supply_effect_timer_++;
				}
			}
		}
		else{
			water_supply_effect_timer_ = 0;
		}
	}
}
示例#16
0
void GLVSLightShader(
    const VERTEXINPUT &in,
    VERTEXOUTPUT &out)
{
    // output description
    const UINT FRONT_COLOR = 0;
    const UINT BACK_COLOR = 4;

    // compute position
    const FLOAT *pConstants = (FLOAT *)in.pConstants;
    const FLOAT *pMVP = &pConstants[GLVSLightConstants::MVP_MATRIX];
    Mat4Vec3Multiply(out.pVertices, pMVP, (FLOAT *)&in.pAttribs[SHADER_INPUT_SLOT_POSITION]);

    // Transform normals in attrib buffer by normal matrix.
    OSALIGNLINE(FLOAT) normals[4];
    Mat4Vec3Multiply(&normals[0], &pConstants[GLVSLightConstants::MV_MATRIX], &in.pAttribs[SHADER_INPUT_SLOT_NORMAL]);

    // Normalize normals
    //__m128 vNormal		= Vec3Normalize(&normals[0]);
    __m128 vNormal = _mm_load_ps(&normals[0]);

    // normalize light
    __m128 vLightDir = _mm_load_ps(&pConstants[GLVSLightConstants::LIGHT0_POS]);
    vLightDir = Vec3Normalize(vLightDir);

    // nDotL and clamp
    __m128 vNdotL0 = Vec3Diffuse(vNormal, vLightDir);

    // light diffuse * nDotL
    __m128 vLightDiffuse = _mm_load_ps(&pConstants[GLVSLightConstants::LIGHT0_DIFFUSE]);
    vLightDiffuse = _mm_mul_ps(vLightDiffuse, vNdotL0);

    // front color = front scene color + light_ambient * front_mat_ambient + light_diffuse * front_mat_diffuse;
    __m128 vFrontColor = _mm_load_ps(&pConstants[GLVSLightConstants::FRONT_SCENE_COLOR]);
    vFrontColor = _mm_add_ps(vFrontColor, _mm_mul_ps(vLightDiffuse, _mm_load_ps(&pConstants[GLVSLightConstants::FRONT_MAT_DIFFUSE])));
    __m128 vAmbient = _mm_mul_ps(_mm_load_ps(&pConstants[GLVSLightConstants::LIGHT0_AMBIENT]), _mm_load_ps(&pConstants[GLVSLightConstants::FRONT_MAT_AMBIENT]));
    vFrontColor = _mm_add_ps(vFrontColor, vAmbient);

    // clamp to 0..1
    vFrontColor = _mm_max_ps(vFrontColor, _mm_setzero_ps());
    vFrontColor = _mm_min_ps(vFrontColor, _mm_set1_ps(1.0));

    // store front color
    _mm_store_ps(&out.pAttribs[FRONT_COLOR], vFrontColor);

#if 1
    // back color
    // invert normal
    vNormal = _mm_mul_ps(vNormal, _mm_set1_ps(-1.0));

    // nDotL and clamp
    vNdotL0 = Vec3Diffuse(vNormal, vLightDir);

    // light diffuse * nDotL
    vLightDiffuse = _mm_load_ps(&pConstants[GLVSLightConstants::LIGHT0_DIFFUSE]);
    vLightDiffuse = _mm_mul_ps(vLightDiffuse, vNdotL0);

    // back color = back scene color + light_ambient * back_mat_ambient + light_diffuse * back_mat_diffuse;
    __m128 vBackColor = _mm_load_ps(&pConstants[GLVSLightConstants::BACK_SCENE_COLOR]);
    vBackColor = _mm_add_ps(vBackColor, _mm_mul_ps(vLightDiffuse, _mm_load_ps(&pConstants[GLVSLightConstants::BACK_MAT_DIFFUSE])));
    vAmbient = _mm_mul_ps(_mm_load_ps(&pConstants[GLVSLightConstants::LIGHT0_AMBIENT]), _mm_load_ps(&pConstants[GLVSLightConstants::BACK_MAT_AMBIENT]));
    vBackColor = _mm_add_ps(vBackColor, vAmbient);

    // clamp 0..1
    vBackColor = _mm_max_ps(vBackColor, _mm_setzero_ps());
    vBackColor = _mm_min_ps(vBackColor, _mm_set1_ps(1.0));

    // store back color
    _mm_store_ps(&out.pAttribs[BACK_COLOR], vBackColor);
#endif
}
	//
	// 获得光照参数
	//
	BOOL CLightGrid::GetLightParams(DWORD dwChannel, const VEC3 *position, VEC4 *direction, VEC3 *ambient, VEC3 *diffuse, VEC3 *specular, VEC3 *rim, VEC3 *skyLower, VEC3 *skyUpper, VEC3 *indirectUp, VEC3 *indirectDown, VEC3 *indirectLeft, VEC3 *indirectRight, VEC3 *indirectFront, VEC3 *indirectBack) const
	{
		ASSERT(position);

		//
		// 1. 通道检查
		//
		if ((LIGHT_CHANNEL & dwChannel) == 0) {
			return FALSE;
		}

		//
		// 2. 获得光照参数
		//
		for (LightVolumeSet::const_iterator itVolume = m_volumes.begin(); itVolume != m_volumes.end(); ++itVolume) {
			const LIGHT_VOLUME *pVolume = *itVolume;
			ASSERT(pVolume);

			if (IsPointInAABB(&pVolume->aabb, (*position)[0], (*position)[1], (*position)[2])) {
				FLOAT posx = ((*position)[0] - pVolume->aabb.minVertex[0]) / pVolume->stepx;
				FLOAT posy = ((*position)[1] - pVolume->aabb.minVertex[1]) / pVolume->stepy;
				FLOAT posz = ((*position)[2] - pVolume->aabb.minVertex[2]) / pVolume->stepz;

				INT x = FastFloor(posx);
				INT y = FastFloor(posy);
				INT z = FastFloor(posz);

				FLOAT factor;
				FLOAT factorx = posx - x;
				FLOAT factory = posy - y;
				FLOAT factorz = posz - z;

				VEC3 _direction;
				VEC3 _ambient;
				VEC3 _diffuse;
				VEC3 _indirectUp;
				VEC3 _indirectDown;
				VEC3 _indirectLeft;
				VEC3 _indirectRight;
				VEC3 _indirectFront;
				VEC3 _indirectBack;
				Vec3Zero(&_direction);
				Vec3Zero(&_ambient);
				Vec3Zero(&_diffuse);
				Vec3Zero(&_indirectUp);
				Vec3Zero(&_indirectDown);
				Vec3Zero(&_indirectLeft);
				Vec3Zero(&_indirectRight);
				Vec3Zero(&_indirectFront);
				Vec3Zero(&_indirectBack);

				for (INT xx = 0; xx <= 1; xx++) {
					factorx = 1.0f - factorx;

					for (INT yy = 0; yy <= 1; yy++) {
						factory = 1.0f - factory;

						for (INT zz = 0; zz <= 1; zz++) {
							factorz = 1.0f - factorz;
							factor  = factorx * factory * factorz;

							if (LIGHT_POINT *pLightPoint = &pVolume->pppLightPoints[x + xx][y + yy][z + zz]) {
								VEC3 __direction;
								VEC3 __ambient;
								VEC3 __diffuse;
								VEC3 __indirectUp;
								VEC3 __indirectDown;
								VEC3 __indirectLeft;
								VEC3 __indirectRight;
								VEC3 __indirectFront;
								VEC3 __indirectBack;

								Vec3LatLongToDirection(&__direction, pLightPoint->direction);
								Vec3BytesToColor(&__ambient, pLightPoint->ambient);
								Vec3BytesToColor(&__diffuse, pLightPoint->diffuse);
								Vec3BytesToColor(&__indirectUp, pLightPoint->indirectup);
								Vec3BytesToColor(&__indirectDown, pLightPoint->indirectdown);
								Vec3BytesToColor(&__indirectLeft, pLightPoint->indirectleft);
								Vec3BytesToColor(&__indirectRight, pLightPoint->indirectright);
								Vec3BytesToColor(&__indirectFront, pLightPoint->indirectfront);
								Vec3BytesToColor(&__indirectBack, pLightPoint->indirectback);

								Vec3Ma(&_direction, &_direction, &__direction, factor);
								Vec3Ma(&_ambient, &_ambient, &__ambient, factor);
								Vec3Ma(&_diffuse, &_diffuse, &__diffuse, factor);
								Vec3Ma(&_indirectUp, &_diffuse, &__indirectUp, factor);
								Vec3Ma(&_indirectDown, &_diffuse, &__indirectDown, factor);
								Vec3Ma(&_indirectLeft, &_diffuse, &__indirectLeft, factor);
								Vec3Ma(&_indirectRight, &_diffuse, &__indirectRight, factor);
								Vec3Ma(&_indirectFront, &_diffuse, &__indirectFront, factor);
								Vec3Ma(&_indirectBack, &_diffuse, &__indirectBack, factor);
							}
						}
					}
				}

				Vec3Normalize(&_direction);
				Vec3Clamp(&_ambient);
				Vec3Clamp(&_diffuse);
				Vec3Clamp(&_indirectUp);
				Vec3Clamp(&_indirectDown);
				Vec3Clamp(&_indirectLeft);
				Vec3Clamp(&_indirectRight);
				Vec3Clamp(&_indirectFront);
				Vec3Clamp(&_indirectBack);

				static const FLOAT specularFactor = 0.8f;
				static const FLOAT rimFactor = 0.2f;
				static const FLOAT skyLowerFactor = 0.2f;
				static const FLOAT skyUpperFactor = 0.4f;

				if (direction) Vec4Set(direction, _direction[0], _direction[1], _direction[2], 0.0f);
				if (ambient) Vec3Set(ambient, _ambient[0], _ambient[1], _ambient[2]);
				if (diffuse) Vec3Set(diffuse, _diffuse[0], _diffuse[1], _diffuse[2]);
				if (specular) Vec3Set(specular, specularFactor * _diffuse[0], specularFactor * _diffuse[1], specularFactor * _diffuse[2]);
				if (rim) Vec3Set(rim, rimFactor * _diffuse[0], rimFactor * _diffuse[1], rimFactor * _diffuse[2]);
				if (skyLower) Vec3Set(skyLower, skyLowerFactor * _diffuse[0], skyLowerFactor * _diffuse[1], skyLowerFactor * _diffuse[2]);
				if (skyUpper) Vec3Set(skyUpper, skyUpperFactor * _diffuse[0], skyUpperFactor * _diffuse[1], skyUpperFactor * _diffuse[2]);
				if (indirectUp) Vec3Set(indirectUp, _indirectUp[0], _indirectUp[1], _indirectUp[2]);
				if (indirectDown) Vec3Set(indirectDown, _indirectDown[0], _indirectDown[1], _indirectDown[2]);
				if (indirectLeft) Vec3Set(indirectLeft, _indirectLeft[0], _indirectLeft[1], _indirectLeft[2]);
				if (indirectRight) Vec3Set(indirectRight, _indirectRight[0], _indirectRight[1], _indirectRight[2]);
				if (indirectFront) Vec3Set(indirectFront, _indirectFront[0], _indirectFront[1], _indirectFront[2]);
				if (indirectBack) Vec3Set(indirectBack, _indirectBack[0], _indirectBack[1], _indirectBack[2]);

				return TRUE;
			}
		}

		return FALSE;
	}