void gr_GetEulerVectors( const LTVector vAngles, LTVector &vRight, LTVector &vUp, LTVector &vForward) { LTMatrix mTemp; gr_SetupMatrixEuler(vAngles, mTemp.m); mTemp.GetBasisVectors(&vRight, &vUp, &vForward); }
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; }
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; }
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); }
//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); }
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; } }
// ------------------------------------------------------------------------ // 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); }
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 ); }
/* 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; }
/* 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)); }
/* 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); }
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); }
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; }
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); } }
// 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; }
//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; }
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 ;} }
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; }