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; }
//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); }
// 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; }