Exemple #1
0
void gr_GetEulerVectors(
	const LTVector vAngles,
	LTVector &vRight,
	LTVector &vUp,
	LTVector &vForward)
{
	LTMatrix mTemp;

	gr_SetupMatrixEuler(vAngles, mTemp.m);
	mTemp.GetBasisVectors(&vRight, &vUp, &vForward);
}
Exemple #2
0
bool CTrackedNodeMgr::GetOrientationSpace( HTRACKEDNODE ID,	LTVector& vRight, 
											LTVector& vUp, 
											LTVector& vForward)
{
	if(!CheckValidity(ID))
		return false;

	//read in the vectors
	LTMatrix mTargetTransform = ID->m_mInvTargetTransform;
	mTargetTransform.Transpose();

	mTargetTransform.GetBasisVectors(&vRight, &vUp, &vForward);
	return true;
}
Exemple #3
0
LTBOOL gr_IntersectPlanes(
	LTPlane &plane0,
	LTPlane &plane1,
	LTPlane &plane2,
	LTVector &vOut)
{
	LTMatrix mPlanes;

	/*
		Math behind this:

		Plane equation is Ax + By + Cz - D = 0
		Standard matrix equation Ax = b.

		So stick the plane equations into the A matrix:

		A B C -D	(from plane 0)
		A B C -D	(from plane 1)
		A B C -D	(from plane 2)
		0 0 0  1

		then the b vector is:
		[0 0 0 1]

		and we're solving for the x vector so:
		~AAx = ~Ab
		x = ~Ab
	*/

	mPlanes.Init(
		plane0.m_Normal[0], plane0.m_Normal[1], plane0.m_Normal[2], -plane0.m_Dist,
		plane1.m_Normal[0], plane1.m_Normal[1], plane1.m_Normal[2], -plane1.m_Dist,
		plane2.m_Normal[0], plane2.m_Normal[1], plane2.m_Normal[2], -plane2.m_Dist,
		0.0f, 0.0f, 0.0f, 1.0f);

	// If we can't invert the matrix, then two or more planes are equal.
	if(!mPlanes.Inverse())
		return LTFALSE;

	// Since our b vector is all zeros, we don't need to do a full matrix multiply.
	// vOut = mPlaneNormal * vPlaneDist;
	vOut.Init(
		mPlanes.m[0][3],
		mPlanes.m[1][3],
		mPlanes.m[2][3]);

	vOut *= (1.0f / mPlanes.m[3][3]);
	return LTTRUE;
}
Exemple #4
0
bool d3d_InitFrustum(ViewParams *pParams, 
	float xFov, float yFov, float nearZ, float farZ, 
	float screenMinX, float screenMinY, float screenMaxX, float screenMaxY,
	const LTVector *pPos, const LTRotation *pRotation, ViewParams::ERenderMode eMode)
{
	LTMatrix mat;

	quat_ConvertToMatrix((float*)pRotation, mat.m);
	mat.SetTranslation(*pPos);

	ViewBoxDef viewBox;
	d3d_InitViewBox(&viewBox, nearZ, farZ, xFov, yFov);

	// Setup initial states and stuff.
	return d3d_InitFrustum2(pParams, &viewBox, 
		screenMinX, screenMinY, screenMaxX, screenMaxY, &mat, LTVector(1.0f, 1.0f, 1.0f), eMode);
}
Exemple #5
0
//Given a stage to install it on, it will grab the global world envmap transform
//and apply it into the texture transform on that stage
void d3d_SetEnvMapTransform(RTexture* pEnvMap, uint32 nStage)
{
	//determine how many times the texture will be tiling.

	float fScale = g_CV_EnvScale;

	//now see if it is okay to divide by it, since that will provide proper scaling
	if(fabs(fScale) > 0.001f)
		fScale = -0.5f / fScale;

	//now apply our custom scale
	LTMatrix mScale;

	if(pEnvMap->IsCubeMap())
	{
		PD3DDEVICE->SetTextureStageState(nStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
		mScale = g_ViewParams.m_mWorldEnvMap;
	}
	else
	{
		PD3DDEVICE->SetTextureStageState(nStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
		mScale.Init(fScale,	0.0f,	0.0f, 0.5f,
					0.0f,   fScale, 0.0f, 0.5f,
					0.0f,	0.0f,   1.0f, 0.0f,
					0.0f,   0.0f,   0.0f, 1.0f);

		//now multiply the two together to get our result
		mScale = mScale * g_ViewParams.m_mWorldEnvMap;
	}

	LTMatrix& m = mScale;

	//now setup the D3D version of our matrix
	D3DMATRIX mat;
	mat._11 = m.m[0][0]; mat._12 = m.m[1][0]; mat._13 = m.m[2][0]; mat._14 = m.m[3][0];
	mat._21 = m.m[0][1]; mat._22 = m.m[1][1]; mat._23 = m.m[2][1]; mat._24 = m.m[3][1];
	mat._31 = m.m[0][2]; mat._32 = m.m[1][2]; mat._33 = m.m[2][2]; mat._34 = m.m[3][2];
	mat._41 = m.m[0][3]; mat._42 = m.m[1][3]; mat._43 = m.m[2][3]; mat._44 = m.m[3][3];

	//and install the transform
	PD3DDEVICE->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + nStage), &mat);
	PD3DDEVICE->SetTextureStageState(nStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR | nStage);

}
Exemple #6
0
static void GeneratePolyGridFresnelAlphaAndCamera(const LTVector& vViewPos, CPolyGridBumpVertex* pVerts, LTPolyGrid* pGrid, uint32 nNumVerts)
{
	//we need to transform the camera position into our view space
	LTMatrix mInvWorldTrans;

	mInvWorldTrans.Identity();
	mInvWorldTrans.SetTranslation(-pGrid->GetPos());

	LTMatrix mOrientation;
	pGrid->m_Rotation.ConvertToMatrix(mOrientation);

	mInvWorldTrans = mOrientation * mInvWorldTrans;

	LTVector vCameraPos = mInvWorldTrans * vViewPos;

	//now generate the internals of the polygrid
	CPolyGridBumpVertex* pCurrVert	= pVerts;
	CPolyGridBumpVertex* pEnd		= pCurrVert + nNumVerts;

	//determine the fresnel table that we are going to be using
	const CFresnelTable* pTable = g_FresnelCache.GetTable(LTMAX(1.0003f, pGrid->m_fFresnelVolumeIOR), pGrid->m_fBaseReflection);

	//use a vector from the camera to the center of the grid to base our approximations off of. The further
	//we get to the edges the more likely this error will be, but it is better than another sqrt per vert
	LTVector vToPGPt;

	while(pCurrVert < pEnd)
	{
		//the correct but slow way, so only do it every once in a while
		//if((pCurrVert - g_TriVertList) % 4 == 0)
		{
			vToPGPt = vCameraPos - pCurrVert->m_Vec;
			vToPGPt.Normalize();
		}

		pCurrVert->m_fEyeX = vToPGPt.x;
		pCurrVert->m_fEyeY = vToPGPt.y;
		pCurrVert->m_fEyeZ = vToPGPt.z;

		pCurrVert->m_nColor |= pTable->GetValue(vToPGPt.Dot(pCurrVert->m_vBasisUp));
		++pCurrVert;
	}
}
Exemple #7
0
// ------------------------------------------------------------------------
// Draw
// use gl to draw the model
// ------------------------------------------------------------------------
void CRenderWnd::Draw()
{
	static LTMatrix IdMat;
	IdMat.Identity();

	DrawStruct *pStruct;

	pStruct = &m_DrawStruct;

	// Setup with 2 lights.
	pStruct->m_ViewerPos = m_Camera.m_Position;
	pStruct->m_LookAt = m_Camera.m_LookAt;
	pStruct->m_LightPositions[0] = m_LightLocators[0].m_Location;
	pStruct->m_LightPositions[1] = m_LightLocators[1].m_Location;
	pStruct->m_LightColors[0].Init(255.0f, 255.0f, 255.0f);
	pStruct->m_LightColors[1].Init(128.0f, 128.0f, 128.0f);
	pStruct->m_nLights = 2;

	SetupViewingParameters((GLMContext*)m_hContext, pStruct );

 	DrawWorldCoordSys();
	
	// if the model exists 
	if (GetModel()  )
	{
		pStruct->m_SelectedPieces = m_SelectedPieces.GetArray();
		pStruct->m_SelectedNodes = m_SelectedNodes.GetArray();

		pStruct->m_bCalcRadius = m_bCalcRadius;
		pStruct->m_fModelRadius = 0.0f;
		pStruct->m_bCalcAndDraw = m_bCalcAndDraw;

		DrawModel (m_hContext, pStruct);

		m_fCurRadius = pStruct->m_fModelRadius;
	}
		
	SwapBuffers( (( GLMContext*)m_hContext)->m_hDC);

}
Exemple #8
0
void CLoadedPrefab::CalcDims()
{
	LTVector vMin, vMax;
	vMin.Init(FLT_MAX, FLT_MAX, FLT_MAX);
	vMax.Init(FLT_MIN, FLT_MIN, FLT_MIN);

	LTMatrix mIdent;
	mIdent.Identity();
	RecurseAndGrowDims(m_cRegion.GetRootNode(), vMin, vMax, mIdent);

	// If one of the members didn't get modified, none of them did...
	if (vMin.x == FLT_MAX)
	{
		ASSERT(vMin.y == FLT_MAX && vMin.z == FLT_MAX && 
			vMax.x == FLT_MIN && vMax.y == FLT_MIN && vMax.y == FLT_MIN);
		// Treat it as an empty set (Which it probably is...  All null nodes or something..)
		vMin.Init();
		vMax.Init();
	}

	m_vMin = vMin;
	m_vMax = vMax;
}
void CTransitionAggregate::Save( ILTMessage_Write *pMsg, uint32 dwSaveFlags )
{
	if( !pMsg ) return;

	SAVE_HOBJECT( m_hObject );

	// The rest is dependent on the save type...
	
	if( dwSaveFlags != LOAD_TRANSITION ) return;

	HOBJECT hTransArea = g_pTransMgr->GetTransitionArea();
	if( !hTransArea ) return;

	TransitionArea *pTransArea = (TransitionArea*)g_pLTServer->HandleToObject( hTransArea );
	if( !pTransArea ) return;

	LTransform tfLocal;
	LTransform tfObjectWorld;
	LTransform const& tfTransAreaWorld = pTransArea->GetWorldTransform( );
	LTMatrix mInverseRot;
	tfTransAreaWorld.m_Rot.ConvertToMatrix( mInverseRot );
	mInverseRot.Inverse( );

	g_pLTServer->GetObjectPos( m_hObject, &tfObjectWorld.m_Pos );
	g_pLTServer->GetObjectRotation( m_hObject, &tfObjectWorld.m_Rot );
	LTVector vVel;
	g_pPhysicsLT->GetVelocity( m_hObject, &vVel );

	tfLocal.m_Pos = mInverseRot * ( tfObjectWorld.m_Pos - tfTransAreaWorld.m_Pos );
	tfLocal.m_Rot = tfObjectWorld.m_Rot * ~tfTransAreaWorld.m_Rot;
	LTVector vRelVel = mInverseRot * vVel;

	SAVE_VECTOR( tfLocal.m_Pos );
	SAVE_ROTATION( tfLocal.m_Rot );
	SAVE_VECTOR( vRelVel );
}
Exemple #10
0
/* Construct matrix from Euler angles (in radians). */
void Eul_ToMatrix(EulerAngles ea, LTMatrix &M)
{
    float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
    int i,j,k,h,n,s,f;
    EulGetOrd((int)ea.w,i,j,k,h,n,s,f);
    if (f==EulFrmR) {
        float t = ea.x;
        ea.x = ea.z;
        ea.z = t;
    }
    if (n==EulParOdd) {
        ea.x = -ea.x;
        ea.y = -ea.y;
        ea.z = -ea.z;
    }
    ti = ea.x;
    tj = ea.y;
    th = ea.z;
    ci = (float)cos(ti);
    cj = (float)cos(tj);
    ch = (float)cos(th);
    si = (float)sin(ti);
    sj = (float)sin(tj);
    sh = (float)sin(th);
    cc = ci*ch;
    cs = ci*sh;
    sc = si*ch;
    ss = si*sh;
    if (s==EulRepYes) {
        M.El(i,i) = cj;
        M.El(i,j) =  sj*si;
        M.El(i,k) =  sj*ci;
        M.El(j,i) = sj*sh;
        M.El(j,j) = -cj*ss+cc;
        M.El(j,k) = -cj*cs-sc;
        M.El(k,i) = -sj*ch;
        M.El(k,j) =  cj*sc+cs;
        M.El(k,k) =  cj*cc-ss;
    } else {
        M.El(i,i) = cj*ch;
        M.El(i,j) = sj*sc-cs;
        M.El(i,k) = sj*cc+ss;
        M.El(j,i) = cj*sh;
        M.El(j,j) = sj*ss+cc;
        M.El(j,k) = sj*cs-sc;
        M.El(k,i) = -sj;
        M.El(k,j) = cj*si;
        M.El(k,k) = cj*ci;
    }
    M.El(EulW,EulX)=M.El(EulW,EulY)=M.El(EulW,EulZ)=M.El(EulX,EulW)=M.El(EulY,EulW)=M.El(EulZ,EulW)=0.0;
    M.El(EulW,EulW)=1.0;
}
Exemple #11
0
/* Convert quaternion to Euler angles (in radians). */
EulerAngles Eul_FromQuat(LTRotation const& q, int order)
{
    LTMatrix M;
    float Nq = q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3];
    float s = (Nq > 0.0f) ? (2.0f / Nq) : 0.0f;
    float xs = q[0]*s,	  ys = q[1]*s,	 zs = q[2]*s;
    float wx = q[3]*xs,	  wy = q[3]*ys,	 wz = q[3]*zs;
    float xx = q[0]*xs,	  xy = q[0]*ys,	 xz = q[0]*zs;
    float yy = q[1]*ys,	  yz = q[1]*zs,	 zz = q[2]*zs;
    M.El(EulX,EulX) = 1.0f - (yy + zz);
    M.El(EulX,EulY) = xy - wz;
    M.El(EulX,EulZ) = xz + wy;
    M.El(EulY,EulX) = xy + wz;
    M.El(EulY,EulY) = 1.0f - (xx + zz);
    M.El(EulY,EulZ) = yz - wx;
    M.El(EulZ,EulX) = xz - wy;
    M.El(EulZ,EulY) = yz + wx;
    M.El(EulZ,EulZ) = 1.0f - (xx + yy);
    M.El(EulW,EulX)=M.El(EulW,EulY)=M.El(EulW,EulZ)=M.El(EulX,EulW)=M.El(EulY,EulW)=M.El(EulZ,EulW)=0.0;
    M.El(EulW,EulW)=1.0f;
    return (Eul_FromMatrix(M, order));
}
Exemple #12
0
/* Convert matrix to Euler angles (in radians). */
EulerAngles Eul_FromMatrix(LTMatrix& M, int order)
{
    EulerAngles ea;
    int i,j,k,h,n,s,f;
    EulGetOrd(order,i,j,k,h,n,s,f);
    if (s==EulRepYes) {
        float sy = (float)sqrt(M.El(i,j)*M.El(i,j) + M.El(i,k)*M.El(i,k));
        if (sy > 16*FLT_EPSILON) {
            ea.x = (float)atan2(M.El(i,j), M.El(i,k));
            ea.y = (float)atan2(sy, M.El(i,i));
            ea.z = (float)atan2(M.El(j,i), -M.El(k,i));
        } else {
            ea.x = (float)atan2(-M.El(j,k), M.El(j,j));
            ea.y = (float)atan2(sy, M.El(i,i));
            ea.z = 0;
        }
    } else {
        float cy = (float)sqrt(M.El(i,i)*M.El(i,i) + M.El(j,i)*M.El(j,i));
        if (cy > 16*FLT_EPSILON) {
            ea.x = (float)atan2(M.El(k,j), M.El(k,k));
            ea.y = (float)atan2(-M.El(k,i), cy);
            ea.z = (float)atan2(M.El(j,i), M.El(i,i));
        } else {
            ea.x = (float)atan2(-M.El(j,k), M.El(j,j));
            ea.y = (float)atan2(-M.El(k,i), cy);
            ea.z = 0;
        }
    }
    if (n==EulParOdd) {
        ea.x = -ea.x;
        ea.y = - ea.y;
        ea.z = -ea.z;
    }
    if (f==EulFrmR) {
        float t = ea.x;
        ea.x = ea.z;
        ea.z = t;
    }
    ea.w = (float)order;
    return (ea);
}
Exemple #13
0
static void d3d_DrawRotatableSprite(const ViewParams& Params, SpriteInstance *pInstance, SharedTexture *pShared)
{
	
	if(!d3d_SetTexture(pShared, 0, eFS_SpriteTexMemory))
		return;

	float fWidth = (float)((RTexture*)pShared->m_pRenderData)->GetBaseWidth();
	float fHeight = (float)((RTexture*)pShared->m_pRenderData)->GetBaseHeight();

	//cache the object position
	LTVector vPos = pInstance->GetPos();
	
	LTMatrix mRotation;
	d3d_SetupTransformation(&vPos, (float*)&pInstance->m_Rotation, &pInstance->m_Scale, &mRotation);

	//get our basis vectors
	LTVector vRight, vUp, vForward;
	mRotation.GetBasisVectors(&vRight, &vUp, &vForward);

	//scale the vectors to be the appropriate size
	vRight  *= fWidth;
	vUp		*= fHeight;

	// Setup the points.
	RGBColor Color;
	d3d_GetSpriteColor(pInstance, &Color);
	uint32 nColor = Color.color;

	CSpriteVertex SpriteVerts[4];
	SpriteVerts[0].SetupVert(vPos + vUp - vRight, nColor, 0.0f, 0.0f);
	SpriteVerts[1].SetupVert(vPos + vUp + vRight, nColor, 1.0f, 0.0f);
	SpriteVerts[2].SetupVert(vPos + vRight - vUp, nColor, 1.0f, 1.0f);
	SpriteVerts[3].SetupVert(vPos - vRight - vUp, nColor, 0.0f, 1.0f);


	//figure out our final vertices to use
	CSpriteVertex	*pPoints;
	uint32			nPoints;
	CSpriteVertex	ClippedSpriteVerts[40 + 5];

	if(pInstance->m_ClipperPoly != INVALID_HPOLY)
	{
		if(!d3d_ClipSprite(pInstance, pInstance->m_ClipperPoly, &pPoints, &nPoints, ClippedSpriteVerts))
		{
			return;
		}
	}
	else
	{
		pPoints = SpriteVerts;
		nPoints = 4;
	}

	if((pInstance->m_Flags & FLAG_SPRITEBIAS) && !(pInstance->m_Flags & FLAG_REALLYCLOSE))
	{
		//adjust the points
		for(uint32 nCurrPt = 0; nCurrPt < nPoints; nCurrPt++)
		{
			//get the sprite vertex that we are modifying
			LTVector& vPt = SpriteVerts[nCurrPt].m_Vec;

			//find a point relative to the viewer position
			LTVector vPtRelCamera = vPt - Params.m_Pos;

			//determine the distance from the camera
			float fZ = vPtRelCamera.Dot(Params.m_Forward);

			if(fZ <= NEARZ)
				continue;

			//find the bias, up to, but not including the near plane
			float fBiasDist = SPRITE_POSITION_ZBIAS;
			if((fZ + fBiasDist) < NEARZ)
				fBiasDist = NEARZ - fZ;
			
			//now adjust our vectors accordingly so that we can move it forward
			//but have it be the same size
			float fScale = 1 + fBiasDist / fZ;

			vPt = Params.m_Right * vPtRelCamera.Dot(Params.m_Right) * fScale +
				  Params.m_Up * vPtRelCamera.Dot(Params.m_Up) * fScale +
				  (fZ + fBiasDist) * Params.m_Forward + Params.m_Pos;
		}
	}
	
	LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pInstance->m_nEffectShaderID);
	if(pEffect)
	{
		pEffect->UploadVertexDeclaration();

		ID3DXEffect* pD3DEffect = pEffect->GetEffect();
		if(pD3DEffect)
		{
			RTexture* pTexture = (RTexture*)pShared->m_pRenderData;
			pD3DEffect->SetTexture("texture0", pTexture->m_pD3DTexture);

			i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton());

			UINT nPasses = 0;
			pD3DEffect->Begin(&nPasses, 0);

			for(UINT i = 0; i < nPasses; ++i)
			{
				pD3DEffect->BeginPass(i);
				D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex)));
				pD3DEffect->EndPass();
			}

			pD3DEffect->End();
		}

	}
	else
	{	
		D3D_CALL(PD3DDEVICE->SetVertexShader(NULL));
		D3D_CALL(PD3DDEVICE->SetFVF(SPRITEVERTEX_FORMAT));
		D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex)));
	}

	d3d_DisableTexture(0);
}
Exemple #14
0
bool CPolyTubeFX::Update(float tmFrameTime)
{
	// Base class update first
	if (!CBaseFX::Update(tmFrameTime)) 
		return false;

	if ((!m_hTexture) && (!m_bLoadFailed))
	{
		m_pLTClient->GetTexInterface()->CreateTextureFromName(m_hTexture, GetProps()->m_sPath);

		if (m_hTexture)
		{
			// Retrieve texture dims
			uint32 nHeight;
			m_pLTClient->GetTexInterface()->GetTextureDims(m_hTexture, m_dwWidth, nHeight);
		}
		else
		{
			m_bLoadFailed = true;
		}
	}

	if ((m_collPathPts.GetSize() < 2) && IsShuttingDown())
	{
		m_collPathPts.RemoveAll();
		return true;
	}
	
	float tmAddPtInterval = GetProps()->m_tmAddPtInterval * 2.0f;

	LTRotation rRot;
	m_pLTClient->GetObjectRotation( m_hObject, &rRot );

	//increase the emission time elapse
	m_tmElapsedEmission += tmFrameTime;

	if (!IsShuttingDown() && 
	    (m_collPathPts.GetSize() < GetProps()->m_nMaxTrailLength) && 
		((m_tmElapsedEmission > GetProps()->m_tmAddPtInterval) || (m_collPathPts.GetSize() == 1)))
	{
		LTVector vNew = m_vPos;
		
		// Only add the new point if it's not the same as the last one....

		// Add a new trail section

		PT_TRAIL_SECTION ts;
		ts.m_vPos		= vNew;
		ts.m_tmElapsed	= 0.0f;

		switch( GetProps()->m_eAllignment )
		{
			case ePTA_Up:
				ts.m_vBisector = rRot.Up();
			break;

			case ePTA_Right:
				ts.m_vBisector = rRot.Right();
			break;

			case ePTA_Forward:
				ts.m_vBisector = rRot.Forward();
			break;

			case ePTA_Camera:
			default:
				ts.m_vBisector.Init();
			break;
		}
		
		
		// Compute u coordinate

		if (m_collPathPts.GetSize())
		{
			LTVector vPrev = m_collPathPts.GetTail()->m_Data.m_vPos;
			float fUPrev = m_collPathPts.GetTail()->m_Data.m_uVal;
			
			float fWidth = (float)m_dwWidth;
			float fScalar = fWidth / GetProps()->m_fTrailWidth;

			ts.m_uVal = fUPrev + ((((vNew - vPrev).Mag()) / fWidth) * fScalar);

		}
		else
		{
			ts.m_uVal = 0.0f;
		}

		m_collPathPts.AddTail(ts);
		
		m_tmElapsedEmission = 0.0f;
	}

	// Render the tube....

	if (m_collPathPts.GetSize() < 2) return true;

	CLinkListNode<PT_TRAIL_SECTION> *pNode = m_collPathPts.GetHead();

	// Fudge the last point to be the current one...

	if( !IsShuttingDown() )
		m_collPathPts.GetTail()->m_Data.m_vPos = m_vPos;

	// Transform the path

	LTMatrix mCam;
	if( m_bReallyClose || (GetProps()->m_eAllignment != ePTA_Camera))
	{
		mCam.Identity();
	}
	else
	{
		mCam = GetCamTransform(m_pLTClient, m_hCamera);
	}
	 
	while (pNode)
	{
		MatVMul(&pNode->m_Data.m_vTran, &mCam, &pNode->m_Data.m_vPos);
		pNode = pNode->m_pNext;
	}

	// Do some precalculations

	pNode = m_collPathPts.GetHead();

	float fCurU = 0.0f;

	while (pNode)
	{
		pNode->m_Data.m_tmElapsed += tmFrameTime;

		if( GetProps()->m_eAllignment == ePTA_Camera )
		{
			LTVector vBisector;
			vBisector.z = 0.0f;

			// Compute the midpoint vectors

			if (pNode == m_collPathPts.GetHead())
			{
				LTVector vStart = pNode->m_Data.m_vTran;
				LTVector vEnd   = pNode->m_pNext->m_Data.m_vTran;
				
				vBisector.x = vEnd.y - vStart.y;
				vBisector.y = -(vEnd.x - vStart.x);
			}
			else if (pNode == m_collPathPts.GetTail())
			{
				LTVector vEnd   = pNode->m_Data.m_vTran;
				LTVector vStart = pNode->m_pPrev->m_Data.m_vTran;
				
				vBisector.x = vEnd.y - vStart.y;
				vBisector.y = -(vEnd.x - vStart.x);
			}
			else
			{
				LTVector vPrev  = pNode->m_pPrev->m_Data.m_vTran;
				LTVector vStart = pNode->m_Data.m_vTran;
				LTVector vEnd   = pNode->m_pNext->m_Data.m_vTran;

				float x1 = vEnd.y - vStart.y;
				float y1 = -(vEnd.x - vStart.x);
				float z1 = vStart.z - vEnd.z;

				float x2 = vStart.y - vPrev.y;
				float y2 = -(vStart.x - vPrev.x);
				float z2 = vPrev.z - vEnd.z;
				
				vBisector.x = (x1 + x2) / 2.0f;
				vBisector.y = (y1 + y2) / 2.0f;
			}

			pNode->m_Data.m_vBisector = vBisector;
		}
		
		LTFLOAT fWidth = CalcCurWidth();
		pNode->m_Data.m_vBisector.Norm( fWidth );

		// Setup the colour
		
		float r, g, b, a;			
		CalcColour(pNode->m_Data.m_tmElapsed, GetProps()->m_tmSectionLifespan, &r, &g, &b, &a);			

		int ir = (int)(r * 255.0f);
		int ig = (int)(g * 255.0f);
		int ib = (int)(b * 255.0f);
		int ia = (int)(a * 255.0f);

		pNode->m_Data.m_red = Clamp( ir, 0, 255 );
		pNode->m_Data.m_green = Clamp( ig, 0, 255 );
		pNode->m_Data.m_blue = Clamp( ib, 0, 255 );
		pNode->m_Data.m_alpha = Clamp( ia, 0, 255 );
	
		pNode = pNode->m_pNext;
	}

	pNode = m_collPathPts.GetHead();

	pNode = m_collPathPts.GetHead();

	// Delete any dead nodes

	while (pNode->m_pNext)
	{
		CLinkListNode<PT_TRAIL_SECTION> *pDelNode= NULL;

		if (pNode->m_Data.m_tmElapsed >= GetProps()->m_tmSectionLifespan)
		{
			pDelNode = pNode;
		}
		
		pNode = pNode->m_pNext;

		if (pDelNode) m_collPathPts.Remove(pDelNode);
	}

	// Increment the offset
	m_uOffset += tmFrameTime * GetProps()->m_uAdd;

	// Success !!

	return true;
}
Exemple #15
0
static void RecurseAndGrowDims(CWorldNode *pNode, LTVector &vMin, LTVector &vMax, LTMatrix& mTransMat)
{
	//sanity check
	if(pNode == NULL)
	{
		return;
	}

	// Grow the dims for this node
	switch (pNode->GetType())
	{
		case Node_Object :
		{
			CBaseEditObj *pObject = pNode->AsObject();
			LTVector vCenter;
			mTransMat.Apply(pObject->GetPos(), vCenter);

			//always include at least the object center
			VEC_MIN(vMin, vMin, vCenter);
			VEC_MAX(vMax, vMax, vCenter);

#ifdef DIRECTEDITOR_BUILD			
			
			//see if there are other dims we need
			for (uint32 nCurDim = pObject->GetNumDims(); nCurDim > 0; --nCurDim)
			{
				LTVector vDims = *pObject->GetDim(nCurDim - 1);
				LTVector vObjMin = vCenter - vDims;
				LTVector vObjMax = vCenter + vDims;
				VEC_MIN(vMin, vMin, vObjMin);
				VEC_MAX(vMax, vMax, vObjMax);
			}
#endif
		}
		break;
		case Node_Brush:
		{
			CEditBrush *pBrush = pNode->AsBrush();
			
			CBoundingBox BBox = pBrush->CalcBoundingBox();

			//transform the bounding box
			LTVector vBoxMin, vBoxMax;
			mTransMat.Apply(BBox.m_Min, vBoxMin);
			mTransMat.Apply(BBox.m_Max, vBoxMax);

			VEC_MIN(vMin, vMin, vBoxMin);
			VEC_MAX(vMax, vMax, vBoxMax);
		}
		break;
		case Node_PrefabRef:
		{
			//create the new transformation matrix
			LTMatrix mRot;
			::gr_SetupMatrixEuler(pNode->GetOr(), mRot.m);

			LTMatrix mTranslate;
			mTranslate.Identity();
			mTranslate.SetTranslation(pNode->GetPos());

			LTMatrix mNewTransMat = mTransMat * mTranslate * mRot;
			RecurseAndGrowDims((CWorldNode*)((CPrefabRef*)pNode)->GetPrefabTree(), vMin, vMax, mNewTransMat);
		}
		break;
	}

	// Go through the children
	GPOS iFinger = pNode->m_Children.GetHeadPosition();
	while (iFinger)
	{
		CWorldNode *pChild = pNode->m_Children.GetNext(iFinger);
		RecurseAndGrowDims(pChild, vMin, vMax, mTransMat);
	}
}
Exemple #16
0
// Sets up pParams.
// pPos and pRotation are the view position and orientation.
// pRect is the rectangle on the screen that the viewing window maps into.
// pScale is an extra scale that scales all the coordinates up.
bool d3d_InitFrustum2(ViewParams *pParams, 
	ViewBoxDef *pViewBox, 
	float screenMinX, float screenMinY, float screenMaxX, float screenMaxY,
	const LTMatrix *pMat, const LTVector& vScale, ViewParams::ERenderMode eMode)
{
	LTMatrix mTempWorld, mRotation, mScale;
	LTMatrix mFOVScale, mBackTransform;
	LTMatrix mDevice, mBackTranslate;
	float leftX, rightX, topY, bottomY, normalZ;
	uint32 i;
	LTVector forwardVec, zPlanePos, vTrans;
	LTMatrix mProjectionTransform; //mUnit, mPerspective;
	
	pParams->m_mIdentity.Identity();
	pParams->m_mInvView = *pMat;


	// Here's how the viewing works:
	// The world to camera transformation rotates and translates
	// the world into camera space.
	// The camera to clip transformation just scales the sides so the
	// field of view is 90 degrees (faster to clip in).
	// Clipping takes place on NEARZ and g_ViewParams.m_FarZ.
	// In terms of Z buffer calculations, the maximum Z is MAX_FARZ (that way,
	// when the farZ clipping plane is changed, sz and rhw stay the same).



	/////// Copy stuff in and setup view limits.

	memcpy(&pParams->m_ViewBox, pViewBox, sizeof(pParams->m_ViewBox));
	pMat->GetTranslation(pParams->m_Pos);

	pParams->m_FarZ = pViewBox->m_FarZ;
	if(pParams->m_FarZ < 3.0f) pParams->m_FarZ = 3.0f;
	if(pParams->m_FarZ > MAX_FARZ) pParams->m_FarZ = MAX_FARZ;
	pParams->m_NearZ = pViewBox->m_NearZ;
	
	pParams->m_Rect.left = (int)RoundFloatToInt(screenMinX);
	pParams->m_Rect.top = (int)RoundFloatToInt(screenMinY);
	pParams->m_Rect.right = (int)RoundFloatToInt(screenMaxX);
	pParams->m_Rect.bottom = (int)RoundFloatToInt(screenMaxY);

	/////// Setup all the matrices.

	// Setup the rotation and translation transforms.
	mRotation = *pMat;
	mRotation.SetTranslation(0.0f, 0.0f, 0.0f);
	Mat_GetBasisVectors(&mRotation, &pParams->m_Right, &pParams->m_Up, &pParams->m_Forward);

	// We want to transpose (ie: when we're looking left, rotate the world to the right..)
	MatTranspose3x3(&mRotation);
	mBackTranslate.Init(
		1, 0, 0, -pParams->m_Pos.x,
		0, 1, 0, -pParams->m_Pos.y,
		0, 0, 1, -pParams->m_Pos.z,
		0, 0, 0, 1);
	MatMul(&mTempWorld, &mRotation, &mBackTranslate);
	
	// Scale it to get the full world transform.
	mScale.Init(
		vScale.x, 0, 0, 0,
		0, vScale.y, 0, 0,
		0, 0, vScale.z, 0,
		0, 0, 0, 1);
	MatMul(&pParams->m_mView, &mScale, &mTempWorld);

	// Shear so the center of projection is (0,0,COP.z)
	LTMatrix mShear;
	mShear.Init(
		1.0f, 0.0f, -pViewBox->m_COP.x/pViewBox->m_COP.z, 0.0f,
		0.0f, 1.0f, -pViewBox->m_COP.y/pViewBox->m_COP.z, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f);

	// Figure out X and Y scale to get frustum into unit slopes.
	float fFovXScale = pViewBox->m_COP.z / pViewBox->m_WindowSize[0];
	float fFovYScale = pViewBox->m_COP.z / pViewBox->m_WindowSize[1];

	// Squash the sides to 45 degree angles.
	mFOVScale.Init(
		fFovXScale, 0.0f, 0.0f, 0.0f,
		0.0f, fFovYScale, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f);

	// Setup the projection transform.
	d3d_SetupPerspectiveMatrix(&mProjectionTransform, pViewBox->m_NearZ, pParams->m_FarZ);

	// Setup the projection space (-1<x<1) to device space transformation.
	pParams->m_fScreenWidth = (screenMaxX - screenMinX);
	pParams->m_fScreenHeight = (screenMaxY - screenMinY);
	
	// Setup the device transform.  It subtracts 0.4 to account for the FP's tendency
	// to slip above and below 0.5.
	Mat_Identity(&mDevice);
	mDevice.m[0][0] = pParams->m_fScreenWidth * 0.5f - 0.0001f;
	mDevice.m[0][3] = screenMinX + pParams->m_fScreenWidth * 0.5f;
	mDevice.m[1][1] = -(pParams->m_fScreenHeight * 0.5f - 0.0001f);
	mDevice.m[1][3] = screenMinY + pParams->m_fScreenHeight * 0.5f;


	// Precalculate useful matrices.
	pParams->m_DeviceTimesProjection = mDevice * mProjectionTransform;
	pParams->m_FullTransform = pParams->m_DeviceTimesProjection * mFOVScale * mShear * pParams->m_mView;

	pParams->m_mProjection = mProjectionTransform * mFOVScale * mShear;
	
	/////// Setup the view frustum points in camera space.
	
	float xNearZ, yNearZ, xFarZ, yFarZ;
	xNearZ = (pParams->m_NearZ * pViewBox->m_WindowSize[0]) / pViewBox->m_COP.z;
	yNearZ = (pParams->m_NearZ * pViewBox->m_WindowSize[1]) / pViewBox->m_COP.z;
	xFarZ = (pParams->m_FarZ * pViewBox->m_WindowSize[0]) / pViewBox->m_COP.z;
	yFarZ = (pParams->m_FarZ * pViewBox->m_WindowSize[1]) / pViewBox->m_COP.z;

	pParams->m_ViewPoints[0].Init(-xNearZ, yNearZ,  pParams->m_NearZ);	// Near Top Left
	pParams->m_ViewPoints[1].Init(xNearZ,  yNearZ,  pParams->m_NearZ);	// Near Top Right
	pParams->m_ViewPoints[2].Init(-xNearZ, -yNearZ, pParams->m_NearZ);	// Near Bottom Left
	pParams->m_ViewPoints[3].Init(xNearZ,  -yNearZ, pParams->m_NearZ);	// Near Bottom Right

	pParams->m_ViewPoints[4].Init(-xFarZ, yFarZ,  pParams->m_FarZ);	// Far Top Left
	pParams->m_ViewPoints[5].Init(xFarZ,  yFarZ,  pParams->m_FarZ);	// Far Top Right
	pParams->m_ViewPoints[6].Init(-xFarZ, -yFarZ, pParams->m_FarZ);	// Far Bottom Left
	pParams->m_ViewPoints[7].Init(xFarZ,  -yFarZ, pParams->m_FarZ);	// Far Bottom Right

	// Transform them into world space.
	for(i=0; i < 8; i++)
	{
		MatVMul_InPlace_Transposed3x3(&pParams->m_mView, &pParams->m_ViewPoints[i]);
		pParams->m_ViewPoints[i] += pParams->m_Pos;
	}

	// Get the AABB of the view frustum
	pParams->m_ViewAABBMin = pParams->m_ViewPoints[0];
	pParams->m_ViewAABBMax = pParams->m_ViewPoints[0];
	for(i=1; i < 8; i++)
	{
		VEC_MIN(pParams->m_ViewAABBMin, pParams->m_ViewAABBMin, pParams->m_ViewPoints[i]);
		VEC_MAX(pParams->m_ViewAABBMax, pParams->m_ViewAABBMax, pParams->m_ViewPoints[i]);
	}

	/////// Setup the camera-space clipping planes.

	leftX = pViewBox->m_COP.x - pViewBox->m_WindowSize[0];
	rightX = pViewBox->m_COP.x + pViewBox->m_WindowSize[0];
	topY = pViewBox->m_COP.y + pViewBox->m_WindowSize[1];
	bottomY = pViewBox->m_COP.y - pViewBox->m_WindowSize[1];
	normalZ = pViewBox->m_COP.z;
	
	LTPlane CSClipPlanes[NUM_CLIPPLANES];
	CSClipPlanes[CPLANE_NEAR_INDEX].m_Normal.Init(0.0f, 0.0f, 1.0f);		// Near Z
	CSClipPlanes[CPLANE_NEAR_INDEX].m_Dist = 1.0f;

	CSClipPlanes[CPLANE_FAR_INDEX].m_Normal.Init(0.0f, 0.0f, -1.0f);			// Far Z
	CSClipPlanes[CPLANE_FAR_INDEX].m_Dist = -pParams->m_FarZ;
	
	CSClipPlanes[CPLANE_LEFT_INDEX].m_Normal.Init(normalZ,  0.0f, -leftX);		// Left
	CSClipPlanes[CPLANE_RIGHT_INDEX].m_Normal.Init(-normalZ, 0.0f, rightX);		// Right
	CSClipPlanes[CPLANE_TOP_INDEX].m_Normal.Init(0.0f,  -normalZ, topY);		// Top
	CSClipPlanes[CPLANE_BOTTOM_INDEX].m_Normal.Init(0.0f,  normalZ, -bottomY);	// Bottom

	CSClipPlanes[CPLANE_LEFT_INDEX].m_Normal.Norm();
	CSClipPlanes[CPLANE_TOP_INDEX].m_Normal.Norm();
	CSClipPlanes[CPLANE_RIGHT_INDEX].m_Normal.Norm();
	CSClipPlanes[CPLANE_BOTTOM_INDEX].m_Normal.Norm();

	CSClipPlanes[CPLANE_LEFT_INDEX].m_Dist = CSClipPlanes[CPLANE_RIGHT_INDEX].m_Dist = 0.0f;
	CSClipPlanes[CPLANE_TOP_INDEX].m_Dist = CSClipPlanes[CPLANE_BOTTOM_INDEX].m_Dist = 0.0f;

	// Now setup the world space clipping planes.
	mBackTransform = pParams->m_mView;
	MatTranspose3x3(&mBackTransform);
	for(i=0; i < NUM_CLIPPLANES; i++)
	{
		if(i != CPLANE_NEAR_INDEX && i != CPLANE_FAR_INDEX)
		{
			MatVMul_3x3(&pParams->m_ClipPlanes[i].m_Normal, &mBackTransform, &CSClipPlanes[i].m_Normal);
			pParams->m_ClipPlanes[i].m_Dist = pParams->m_ClipPlanes[i].m_Normal.Dot(pParams->m_Pos);
		}
	}

	// The Z planes need to be handled a little differently.
	forwardVec.Init(mRotation.m[2][0], mRotation.m[2][1], mRotation.m[2][2]);

	zPlanePos = forwardVec * pViewBox->m_NearZ;
	zPlanePos += pParams->m_Pos;

	MatVMul_3x3(&pParams->m_ClipPlanes[CPLANE_NEAR_INDEX].m_Normal, 
		&mBackTransform, &CSClipPlanes[CPLANE_NEAR_INDEX].m_Normal);

	pParams->m_ClipPlanes[CPLANE_NEAR_INDEX].m_Dist = 
		pParams->m_ClipPlanes[CPLANE_NEAR_INDEX].m_Normal.Dot(zPlanePos);

	zPlanePos = forwardVec * pParams->m_FarZ;
	zPlanePos += pParams->m_Pos;
	
	MatVMul_3x3(&pParams->m_ClipPlanes[CPLANE_FAR_INDEX].m_Normal,
		&mBackTransform, &CSClipPlanes[CPLANE_FAR_INDEX].m_Normal);

	pParams->m_ClipPlanes[CPLANE_FAR_INDEX].m_Dist = 
		pParams->m_ClipPlanes[CPLANE_FAR_INDEX].m_Normal.Dot(zPlanePos);

	// Remember AABB Corners the planes are pointing at
	for (uint32 nPlaneLoop = 0; nPlaneLoop < NUM_CLIPPLANES; ++nPlaneLoop)
	{
		pParams->m_AABBPlaneCorner[nPlaneLoop] = 
			GetAABBPlaneCorner(pParams->m_ClipPlanes[nPlaneLoop].m_Normal);
	}

	// Default the world transform to identity
	pParams->m_mInvWorld.Identity();

	//setup the environment mapping info
	pParams->m_mWorldEnvMap.SetBasisVectors(&pParams->m_Right, &pParams->m_Up, &pParams->m_Forward);

	//turn off glowing by default
	pParams->m_eRenderMode = eMode;

	d3d_SetupSkyStuff(g_pSceneDesc->m_SkyDef, pParams);
	return true;
}
BOOL CRVTrackerDrawPoly::OnRotate()
{
	// Get the brush
	CEditBrush *pBrush = &m_pView->DrawingBrush();

	// Make sure we've got at least three points specified
	if (pBrush->m_Points.GetSize() < 3)
		return FALSE;

	// The origin's point #1
	CVector vOrigin = pBrush->m_Points[0];
	// The original rotation direction's point #2
	CVector vBase = pBrush->m_Points[1];
	// The new rotation's point #3
	CVector vNew = pBrush->m_Points[2];

	// Get the base direction
	CVector vBaseDir = vBase - vOrigin;
	float fBaseMag = vBaseDir.Mag();
	// Don't allow duplicate points
	if (fBaseMag < 0.01f)
		return TRUE;
	vBaseDir *= 1.0f / fBaseMag;

	// Get the rotation direction
	CVector vNewDir = vNew - vOrigin;
	float fNewMag = vNewDir.Mag();
	// Don't allow duplicate points
	if (fNewMag < 0.01f)
		return TRUE;
	vNewDir *= 1.0f / fNewMag;

	// Get the rotation axis
	CVector vRotAxis = vNewDir.Cross(vBaseDir);

	// Get the sin of the angle from the cross product
	float fRotAngle = vRotAxis.Mag();

	// Don't bother if the angle's 0...
	if (fRotAngle == 0.0f)
		return TRUE;

	// Normalize the axis
	vRotAxis *= 1.0f / fRotAngle;

	// Get the actual angle
	fRotAngle = (float)asin(fRotAngle);

	// Handle obtuse angles..
	if (vBaseDir.Dot(vNewDir) < 0.0f)
		fRotAngle = MATH_PI - fRotAngle;

	LTMatrix mRotation;
	// Get the rotation matrix
	mRotation.SetupRot(vRotAxis, fRotAngle);

	// Set up an undo..
	CEditRegion *pRegion = m_pView->GetRegion();
	PreActionList actionList;
	for (uint32 nUndoLoop = 0; nUndoLoop < pRegion->m_Selections; ++nUndoLoop)
		actionList.AddTail(new CPreAction(ACTION_MODIFYNODE, pRegion->m_Selections[nUndoLoop]));
	m_pView->GetRegionDoc()->Modify(&actionList, TRUE);

	// If we're in geometry mode..
	if (m_pView->GetEditMode() == GEOMETRY_EDITMODE)
	{
		// Get the selected vertices
		CVertRefArray vertList;
		m_pView->GetSelectedVerts(vertList);
		// Rotate 'em
		for (uint32 nVertLoop = 0; nVertLoop < vertList.GetSize(); ++nVertLoop)
		{
			CVertRef vert = vertList[nVertLoop];
			if (!vert.IsValid())
				continue;
			vert() -= vOrigin;
			mRotation.Apply(vert());
			vert() += vOrigin;
		}
	}
	else
	{
		// Otherwise, rotate all the selected nodes
		for (uint32 nNodeLoop = 0; nNodeLoop < pRegion->m_Selections.GetSize( ); ++nNodeLoop)
		{
			pRegion->m_Selections[nNodeLoop]->Rotate(mRotation, vOrigin);
		}

		// Update the selection box since stuff rotated...
		m_pView->GetRegionDoc()->UpdateSelectionBox();
	}

	return TRUE;
}
Exemple #18
0
//given an animation and a keyframe, this will find the dims that encompass the
//model
bool CDimensionsDlg::FindAnimDims(Model* pModel, uint32 nAnim, uint32 nKeyFrame, LTVector& vDims)
{
    //clear out the dims to start out with in case we fail
    vDims.Init();

    AnimTracker tracker, *pTracker;
    tracker.m_TimeRef.Init(pModel, nAnim, nKeyFrame, nAnim, nKeyFrame, 0.0f);

    AnimInfo *pAnim = &pModel->m_Anims[nAnim];

    pTracker = &tracker;//pAnim->m_pAnim;

    static CMoArray<TVert> tVerts;

    // Use the model code to setup the vertices.

    int nTrackers = 1;
    nTrackers = DMIN(nTrackers, MAX_GVP_ANIMS);

    GVPStruct gvp;

    gvp.m_nAnims = 0;
    for(int i = 0; i < nTrackers; i++)
    {
        gvp.m_Anims[i] = pTracker[i].m_TimeRef;
        gvp.m_nAnims++;
    }

    LTMatrix m;
    m.Identity();

    int nWantedVerts = pModel->GetTotalNumVerts() * 2;
    if(tVerts.GetSize() < nWantedVerts)
    {
        if(!tVerts.SetSize(nWantedVerts))
            return false;
    }

    gvp.m_VertexStride = sizeof(TVert);
    gvp.m_Vertices = tVerts.GetArray();
    gvp.m_BaseTransform = m;
    gvp.m_CurrentLODDist = 0;

    if (AlternateGetVertexPositions(pModel, &gvp, true, false, false, false))
    {
        LTVector vMax(0, 0, 0);

        for (i = 0; i < pModel->GetTotalNumVerts(); i ++)
        {
            TVert v = tVerts[i];

            if (fabs(v.m_vPos.x) > vMax.x) vMax.x = (float)fabs(v.m_vPos.x);
            if (fabs(v.m_vPos.y) > vMax.y) vMax.y = (float)fabs(v.m_vPos.y);
            if (fabs(v.m_vPos.z) > vMax.z) vMax.z = (float)fabs(v.m_vPos.z);
        }

        // Setup the new dims....

        //round max up to the .1 decimal place
        vMax.x = (float)(ceil(vMax.x * 10.0) / 10.0);
        vMax.y = (float)(ceil(vMax.y * 10.0) / 10.0);
        vMax.z = (float)(ceil(vMax.z * 10.0) / 10.0);

        vDims = vMax;

        return true;
    }

    //failure
    return false;
}
Exemple #19
0
void CLightningFX::PreRender( float tmFrameTime )
{
	
	LTVector vPulse;
	LTVector vF(0.0f, 0.0f, 1.0f);
	LTVector vU(0.0f, 1.0f, 0.0f);
	LTVector vR(1.0f, 0.0f, 0.0f);

	
	// Transform the bolt 

	LTMatrix mCam;
	if( m_bReallyClose )
	{
		mCam.Identity();
	}
	else
	{
		mCam = GetCamTransform(m_pLTClient, m_hCamera);
	}
	 
	
	CLightningBolt *pBolt = LTNULL;
	LightningBolts::iterator iter;
	for( iter = m_lstBolts.begin(); iter != m_lstBolts.end(); ++iter )
	{
		pBolt = *iter;

		// Skip this bolt if there are not enough segments...

		if( pBolt->m_collPathPts.GetSize() < 2 || !pBolt->m_bActive )
			continue;

		CLinkListNode<PT_TRAIL_SECTION> *pNode = pBolt->m_collPathPts.GetHead();

		//as long as some amount of time has passed, apply a pulse onto the bolt to make
		//it jitter
		if(tmFrameTime > 0.001f)
		{
			while (pNode)
			{
				vPulse = pNode->m_Data.m_vPos;
				vPulse += (vF * GetRandom( -GetProps()->m_fPulse, GetProps()->m_fPulse ));
				vPulse += (vU * GetRandom( -GetProps()->m_fPulse, GetProps()->m_fPulse ));
				vPulse += (vR * GetRandom( -GetProps()->m_fPulse, GetProps()->m_fPulse ));

				if( pNode == pBolt->m_collPathPts.GetHead() || !pNode->m_pNext )
				{
					MatVMul(&pNode->m_Data.m_vTran, &mCam, &pNode->m_Data.m_vPos);
				}
				else
				{
					MatVMul(&pNode->m_Data.m_vTran, &mCam, &vPulse);
				}

				pNode = pNode->m_pNext;
			}
		}

		// Do some precalculations

		float fScale;
		CalcScale( pBolt->m_tmElapsed, pBolt->m_fLifetime, &fScale );
		float fWidth = pBolt->m_fWidth * fScale;

		// Setup the colour
		
		float r, g, b, a;			
		CalcColour( pBolt->m_tmElapsed, pBolt->m_fLifetime, &r, &g, &b, &a );			

		int ir = Clamp( (int)(r * 255.0f), 0, 255 );
		int ig = Clamp( (int)(g * 255.0f), 0, 255 );
		int ib = Clamp( (int)(b * 255.0f), 0, 255 );
		int ia = Clamp( (int)(a * 255.0f), 0, 255 );

		LTVector vStart, vEnd, vPrev, vBisector;
		vBisector.z = 0.0f;

		pNode = pBolt->m_collPathPts.GetHead();

		while( pNode )
		{
			if( GetProps()->m_eAllignment == ePTA_Camera )
			{
				// Compute the midpoint vectors

				if( pNode == pBolt->m_collPathPts.GetHead() )
				{
					vStart = pNode->m_Data.m_vTran;
					vEnd   = pNode->m_pNext->m_Data.m_vTran;
					
					vBisector.x = vEnd.y - vStart.y;
					vBisector.y = -(vEnd.x - vStart.x);
				}
				else if( pNode == pBolt->m_collPathPts.GetTail() )
				{
					vEnd   = pNode->m_Data.m_vTran;
					vStart = pNode->m_pPrev->m_Data.m_vTran;
					
					vBisector.x = vEnd.y - vStart.y;
					vBisector.y = -(vEnd.x - vStart.x);
				}
				else
				{
					vPrev  = pNode->m_pPrev->m_Data.m_vTran;
					vStart = pNode->m_Data.m_vTran;
					vEnd   = pNode->m_pNext->m_Data.m_vTran;

					float x1 = vEnd.y - vStart.y;
					float y1 = -(vEnd.x - vStart.x);
					float z1 = vStart.z - vEnd.z;

					float x2 = vStart.y - vPrev.y;
					float y2 = -(vStart.x - vPrev.x);
					float z2 = vPrev.z - vEnd.z;
					
					vBisector.x = (x1 + x2) / 2.0f;
					vBisector.y = (y1 + y2) / 2.0f;
				}

				pNode->m_Data.m_vBisector = vBisector;
			}
			
			// Set the width for this section...

			pNode->m_Data.m_vBisector.Norm( fWidth );
			
			// Set the color for this section...

			pNode->m_Data.m_red = ir;
			pNode->m_Data.m_green = ig;
			pNode->m_Data.m_blue = ib;
			pNode->m_Data.m_alpha = ia;
		
			pNode = pNode->m_pNext;
		}
	}
}
// Wrap the textures, starting at a poly index
void CRVTrackerTextureWrap::WrapTexture(CTWPolyInfo *pPoly, const CVector &vWrapDir, CTextExtents &cExtents) const
{
	// Mark this poly as wrapped
	pPoly->m_bTouched = TRUE;

	CTexturedPlane& Texture = pPoly->m_pPoly->GetTexture(GetCurrTexture());

	// Get the texture space
	LTVector vWrapO = Texture.GetO();
	LTVector vWrapP = Texture.GetP();
	LTVector vWrapQ = Texture.GetQ();

	// Get the texture offset projections
	float fWrapOdotP = vWrapO.Dot(vWrapP);
	float fWrapOdotQ = vWrapO.Dot(vWrapQ);

	// Update the texturing extents
	for (uint32 nExtentLoop = 0; nExtentLoop < pPoly->m_aEdges.GetSize(); ++nExtentLoop)
	{
		LTVector vEdgePt = pPoly->m_aEdges[nExtentLoop]->m_aPt[0];

		float fCurU = vWrapP.Dot(vEdgePt) - fWrapOdotP;
		float fCurV = vWrapQ.Dot(vEdgePt) - fWrapOdotQ;

		cExtents.m_fMinU = LTMIN(fCurU, cExtents.m_fMinU);
		cExtents.m_fMaxU = LTMAX(fCurU, cExtents.m_fMaxU);
		cExtents.m_fMinV = LTMIN(fCurV, cExtents.m_fMinV);
		cExtents.m_fMaxV = LTMAX(fCurV, cExtents.m_fMaxV);
	}

	CMoArray<uint32> aNeighbors;
	CMoArray<float> aDots;

	// Insert the neighbors into a list in dot-product order
	for (uint32 nNeighborLoop = 0; nNeighborLoop < pPoly->m_aNeighbors.GetSize(); ++nNeighborLoop)
	{
		CTWPolyInfo *pNeighbor = pPoly->m_aNeighbors[nNeighborLoop];

		// Skip edges that don't have a neighbor
		if (!pNeighbor)
			continue;

		// Skip neighbors that are already wrapped
		if (pNeighbor->m_bTouched)
			continue;

		// Get our dot product
		float fCurDot = vWrapDir.Dot(pPoly->m_aEdges[nNeighborLoop]->m_Plane.m_Normal);

		if ((m_bRestrictWalkDir) && (fCurDot < 0.707f))
			continue;

		// Mark this neighbor as touched (to avoid later polygons pushing it onto the stack)
		pNeighbor->m_bTouched = TRUE;

		// Insert it into the list
		for (uint32 nInsertLoop = 0; nInsertLoop < aNeighbors.GetSize(); ++nInsertLoop)
		{
			if (fCurDot > aDots[nInsertLoop])
				break;
		}
		aDots.Insert(nInsertLoop, fCurDot);
		aNeighbors.Insert(nInsertLoop, nNeighborLoop);
	}

	// Recurse through its neighbors
	for (uint32 nWrapLoop = 0; nWrapLoop < aNeighbors.GetSize(); ++nWrapLoop)
	{
		CTWPolyInfo *pNeighbor = pPoly->m_aNeighbors[aNeighbors[nWrapLoop]];
		CTWEdgeInfo *pEdge = pPoly->m_aEdges[aNeighbors[nWrapLoop]];

		//////////////////////////////////////////////////////////////////////////////
		// Wrap this neighbor

		// Create a matrix representing the basis of the polygon in relation to this edge
		LTMatrix mPolyBasis;
		mPolyBasis.SetTranslation(0.0f, 0.0f, 0.0f);
		mPolyBasis.SetBasisVectors(&pEdge->m_vDir, &pPoly->m_pPoly->m_Plane.m_Normal, &pEdge->m_Plane.m_Normal);

		// Create a new basis for the neighbor polygon
		LTMatrix mNeighborBasis;
		LTVector vNeighborForward;
		vNeighborForward = pNeighbor->m_pPoly->m_Plane.m_Normal.Cross(pEdge->m_vDir);
		// Just to be sure..
		vNeighborForward.Norm();
		mNeighborBasis.SetTranslation(0.0f, 0.0f, 0.0f);
		mNeighborBasis.SetBasisVectors(&pEdge->m_vDir, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vNeighborForward);

		// Create a rotation matrix from here to there
		LTMatrix mRotation;
		mRotation = mNeighborBasis * ~mPolyBasis;

		// Rotate the various vectors
		LTVector vNewP;
		LTVector vNewQ;
		LTVector vNewDir;

		mRotation.Apply3x3(vWrapP, vNewP);
		mRotation.Apply3x3(vWrapQ, vNewQ);
		mRotation.Apply3x3(vWrapDir, vNewDir);

		// Rotate the texture basis if we're following a path
		if (m_nWrapStyle == k_WrapPath)
		{
			LTVector vNeighborEdgeDir;
			if (GetSimilarEdgeDir(pNeighbor, vNewDir, vNeighborEdgeDir, 0.707f))
			{
				LTMatrix mRotatedNeighbor;
				LTVector vNeighborRight;
				vNeighborRight = vNeighborEdgeDir.Cross(pNeighbor->m_pPoly->m_Plane.m_Normal);
				vNeighborRight.Norm();
				// Make sure we're pointing the right way...
				if (vNeighborRight.Dot(pEdge->m_vDir) < 0.0f)
					vNeighborRight = -vNeighborRight;
				mRotatedNeighbor.SetTranslation(0.0f, 0.0f, 0.0f);
				mRotatedNeighbor.SetBasisVectors(&vNeighborRight, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vNeighborEdgeDir);
				// Build a basis based on an edge from the current polygon 
				LTVector vBestPolyEdge;
				GetSimilarEdgeDir(pPoly, vWrapDir, vBestPolyEdge);
				LTVector vPolyRight = vBestPolyEdge.Cross(pNeighbor->m_pPoly->m_Plane.m_Normal);
				vPolyRight.Norm();
				// Make sure we're pointing the right way...
				if (vPolyRight.Dot(pEdge->m_vDir) < 0.0f)
					vPolyRight = -vPolyRight;
				// Build the poly edge matrix
				LTMatrix mPolyEdgeBasis;
				mPolyEdgeBasis.SetTranslation(0.0f, 0.0f, 0.0f);
				mPolyEdgeBasis.SetBasisVectors(&vPolyRight, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vBestPolyEdge);

				// Get a matrix from here to there
				LTMatrix mRotator;
				mRotator = mRotatedNeighbor * ~mPolyEdgeBasis;
				// Rotate the texture basis
				mRotator.Apply3x3(vNewP);
				mRotator.Apply3x3(vNewQ);
				// And use the new edge as the new direction
				vNewDir = vNeighborEdgeDir;
			}

			// Remove skew from vNewP/vNewQ
			if ((float)fabs(vNewP.Dot(vNewQ)) > 0.001f)
			{
				float fMagP = vNewP.Mag();
				float fMagQ = vNewQ.Mag();
				vNewQ *= 1.0f / fMagQ;
				vNewP -= vNewQ * vNewQ.Dot(vNewP);
				vNewP.Norm(fMagP);
				vNewQ *= fMagQ;
			}
		}

		// Get the first edge point..
		CVector vEdgePt = pEdge->m_aPt[0];

		// Calculate the texture coordinate at this point
		float fWrapU = vWrapP.Dot(vEdgePt) - fWrapOdotP;
		float fWrapV = vWrapQ.Dot(vEdgePt) - fWrapOdotQ;

		// Build the new offset
		float fNewOdotP = vNewP.Dot(vEdgePt) - fWrapU;
		float fNewOdotQ = vNewQ.Dot(vEdgePt) - fWrapV;
		LTVector vNewO;
		vNewO.Init();
		float fNewPMag = vNewP.MagSqr();
		if (fNewPMag > 0.0f)
			vNewO += vNewP * (fNewOdotP / fNewPMag);
		float fNewQMag = vNewQ.MagSqr();
		if (fNewQMag > 0.0f)
			vNewO += vNewQ * (fNewOdotQ / fNewQMag);

		pNeighbor->m_pPoly->SetTextureSpace(GetCurrTexture(), vNewO, vNewP, vNewQ);

		// Recurse into this neighbor
		WrapTexture(pNeighbor, vNewDir, cExtents);
	}
}
// returns true if intersection happened, plus fills hit dist param with 
// the parametric position of the intersection on the ray dir. 
// the obb must be within ray-origin + ray-dir. So ray-dir isn't normalized.
// source : Real-time rendering moller&haines
inline bool i_OrientedBoundingBoxTest(const ModelOBB &mobb, 
									  const LTransform &tf, 
									  const LTVector &origin, 
									  const LTVector &dir, 
									  float &t)
{
	float tmin = -999999999999.0f;
	float tmax = 999999999999.0f;

	LTVector vObbPos = mobb.m_Pos;

	// Setup our OBB's translated position
	LTMatrix obb_mat;
	obb_mat.Identity();
	obb_mat.SetBasisVectors( &tf.m_Rot.Right(), &tf.m_Rot.Up(), &tf.m_Rot.Forward() );
	obb_mat.SetTranslation( tf.m_Pos );
	obb_mat.Apply(vObbPos);  

	LTVector p = vObbPos - origin;
	float e ;
	float f;
	float hi;
	float t1,t2;
	
	// Setup OBB rotation tranforms
	LTMatrix mObbMat;
	mObbMat.SetBasisVectors(&mobb.m_Basis[0], &mobb.m_Basis[1], &mobb.m_Basis[2]);
	
	// Get matrix of our Node's rotation
	LTMatrix mTrMat;
	tf.m_Rot.ConvertToMatrix(mTrMat);
	
	// Apply our node rotation to our obb rotation
	mTrMat.Apply(mObbMat);
	
	// Get our translated basis vectors
	LTVector axis[3];
	mObbMat.GetBasisVectors(&axis[0], &axis[1], &axis[2]);

	LTVector vSize =  mobb.m_Size * 0.5f ; // we want the 1/2 size of the box.

	for( int i = 0 ; i < 3 ; i++ )
	{
		e = axis[i].Dot(p);  
		f = axis[i].Dot(dir);		
		hi= vSize[i]  ; // 

		if( fabs(f) > 0.00015 )
		{
			t1 = ( e + hi ) / f ;
			t2 = ( e - hi ) / f ;
			if( t1 > t2 ) {float v = t2 ; t2 = t1 ; t1 = v ; }
			if(t1 > tmin ) {tmin = t1 ;}
			if(t2 < tmax ) {tmax = t2 ;}
			if(tmin > tmax ) { 
				 return false ; }
			if(tmax < 0  ) { 
				 return false ; }
		}
		else if( ((-e - hi) > 0 ) || ( (-e + hi) < 0 )) { t = 0 ; return false ; }
	}

	if( tmin > 0 ) { t = tmin ;  return true ; }
	else { t = tmax ;  return true ;}
}
Exemple #22
0
float ModelDraw::GetDirLightAmount(ModelInstance* pInstance, const LTVector& vInstancePosition)
{
	const WorldTreeNode* pWTRoot = world_bsp_client->ClientTree()->GetRootNode();

	//the maximum distance we would ever need to cast a node
	float fLongestDist = (pWTRoot->GetBBoxMax() - pWTRoot->GetBBoxMin()).Mag();

	//figure out the segment that we will now intersect (opposite direction that the sun is going
	//since we are shooting towards it)
	LTVector vDir = g_pStruct->m_GlobalLightDir * -fLongestDist;

	// Just do a single intersection in the middle out if the variance calculation's turned off
	if (!g_CV_ModelSunVariance.m_Val)
		return CastRayAtSky(vInstancePosition, vDir) ? 1.0f : 0.0f;

	// Get the orienation of the model instance
	LTMatrix mInstanceTransform;
	pInstance->SetupTransform(mInstanceTransform);

	// Figure out the shadow in/out direction
	LTVector vUp, vForward, vRight;
	mInstanceTransform.GetBasisVectors(&vRight, &vUp, &vForward);
	LTVector vLightUp = g_pStruct->m_GlobalLightDir.Cross(vRight);

	// Apply the size of the model to the shadow direction
	vLightUp *= pInstance->GetRadius();

	// Get top/bottom light states
	bool bTopInLight = CastRayAtSky(vInstancePosition + vLightUp, vDir);
	bool bBottomInLight = CastRayAtSky(vInstancePosition - vLightUp, vDir);

	// Jump out if they're the same
	if (bTopInLight == bBottomInLight)
		return (bTopInLight) ? 1.0f : 0.0f;

	// Do a binary subdivision to try and find the point of cross-over
	bool bMiddleInLight;
	float fVariance = 1.0f, fTop = 1.0f, fBottom = -1.0f, fMiddle;
	float fLight = 1.0f;

	while ((fVariance > g_CV_ModelSunVariance.m_Val) && (bBottomInLight != bTopInLight))
	{
		// Find the middle state
		fMiddle = (fTop + fBottom) * 0.5f;
		bMiddleInLight = CastRayAtSky(vInstancePosition + (vLightUp * fMiddle), vDir);
		// Drop the variance
		fVariance *= 0.5f;
		// Keep track of the total
		if (!bMiddleInLight)
			fLight -= fVariance;
		// Decide which half to keep
		if (bMiddleInLight == bTopInLight)
		{
			fTop = fMiddle;
			bTopInLight = bMiddleInLight;
		}
		else
		{
			fBottom = fMiddle;
			bBottomInLight = bMiddleInLight;
		}
	}

	return fLight;
}