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

📄 zfxd3d_misc.cpp

📁 This is a book introduce some tech about Game Engine 3D
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// File: ZFXD3D_misc.cpp

#include "math.h"          // sqrt function
#include "ZFX.h"           // return values and stuff
#include "ZFXD3D.h"        // class definition
#include "d3dx9.h"         // shader compiler




extern bool g_bLF;

/*-----------------------------------------------------------*/
/* ZFXD3D class implementation                               *
/*-----------------------------------------------------------*/

/**
 * Set mode for projection and view for given Stage.
 * -> IN: ZFXENGINEMODE - mode perspective, ortho or 2D
 *        int           - stage, not needed for 2D mode
 */
HRESULT ZFXD3D::SetMode(ZFXENGINEMODE Mode, int nStage) {
   D3DVIEWPORT9 d3dVP;

   if (!m_bRunning) return E_FAIL;
   if ((nStage > 3) || (nStage < 0)) nStage=0;
   
   if (m_Mode != Mode)
      m_Mode  = Mode;

   // we change fundamentals settings so fush all content
   m_pVertexMan->ForcedFlushAll();

   m_nStage = nStage;

   // set viewport
   d3dVP.X      = m_VP[nStage].X;
   d3dVP.Y      = m_VP[nStage].Y;
   d3dVP.Width  = m_VP[nStage].Width;
   d3dVP.Height = m_VP[nStage].Height;
   d3dVP.MinZ   = 0.0f;
   d3dVP.MaxZ   = 1.0f;

   // if 2D mode set orthogonal projection and view
   if (Mode==EMD_TWOD) {
      if (FAILED(m_pDevice->SetViewport(&d3dVP)))
         return ZFX_FAIL;

      if (!m_bUseShaders) {
         if (FAILED(m_pDevice->SetTransform(D3DTS_PROJECTION, &m_mProj2D)))
            return ZFX_FAIL;

         if (FAILED(m_pDevice->SetTransform(D3DTS_VIEW, &m_mView2D)))
            return ZFX_FAIL;
         }
      }

   // perspective or orthogonal projection
   else {
      if (FAILED(m_pDevice->SetViewport(&d3dVP)))
         return ZFX_FAIL;

      if (!m_bUseShaders) {
         if (FAILED(m_pDevice->SetTransform(D3DTS_VIEW, &m_mView3D)))
            return ZFX_FAIL;

         if (m_Mode == EMD_PERSPECTIVE) {
            if (FAILED(m_pDevice->SetTransform(D3DTS_PROJECTION, 
                                               &m_mProjP[nStage])))
               return ZFX_FAIL;
            }
         else { // EMD_ORTHOGONAL
            if (FAILED(m_pDevice->SetTransform(D3DTS_PROJECTION, 
                                               &m_mProjO[nStage])))
               return ZFX_FAIL;
            }
         }
      CalcViewProjMatrix();
      CalcWorldViewProjMatrix();
      }
   return ZFX_OK;
   } // SetMode
/*----------------------------------------------------------------*/

/**
 * Calculate perspective and orthogonal projection matrix for given
 * stage using given values. Thi will not activate any settings.
 * -> IN: float       - field of view (horizontal)
 *        ZFXVIEWPORT - viewport dimensions or NULL for screen dimensions
 *        int         - which stage to set (4 possible)
 */
HRESULT ZFXD3D::InitStage(float fFOV, ZFXVIEWPORT *pView, int nStage) {
   float fAspect;
   bool  bOwnRect=false;
   
   if (!pView) {
      ZFXVIEWPORT vpOwn = { 0, 0, m_dwWidth, m_dwHeight};
      memcpy(&m_VP[nStage], &vpOwn, sizeof(RECT));
      }
   else
      memcpy(&m_VP[nStage], pView, sizeof(RECT));

   if ( (nStage>3) || (nStage<0) ) nStage=0;

   fAspect = ((float)(m_VP[nStage].Height)) / (m_VP[nStage].Width);

   // PERSPECTIVE PROJEKTION MATRIX
   if (FAILED(this->CalcPerspProjMatrix(fFOV, fAspect, &m_mProjP[nStage])))
      return ZFX_FAIL;

   // ORTHOGONAL PROJECTION MATRIX
   memset(&m_mProjO[nStage], 0, sizeof(float)*16); 
   m_mProjO[nStage]._11 =  2.0f/m_VP[nStage].Width;
   m_mProjO[nStage]._22 =  2.0f/m_VP[nStage].Height;
   m_mProjO[nStage]._33 =  1.0f/(m_fFar-m_fNear);

   m_mProjO[nStage]._43 =  m_fNear/(m_fNear-m_fFar);
   m_mProjO[nStage]._44 =  1.0f;

   return ZFX_OK;
   } // InitStage
/*----------------------------------------------------------------*/


/**
 * Recalculate view-projection combo matrix each time one of them
 * is changing to maintain integrity.
 */
void ZFXD3D::CalcViewProjMatrix(void) {
   ZFXMatrix *pA;
   ZFXMatrix *pB;

   // 2D, perspective or orthogonal mode
   if (m_Mode == EMD_TWOD) {
      pA = (ZFXMatrix*)&m_mProj2D;
      pB = (ZFXMatrix*)&m_mView2D;
      }
   else {
      pB = (ZFXMatrix*)&m_mView3D;

      if (m_Mode == EMD_PERSPECTIVE)
         pA = (ZFXMatrix*)&(m_mProjP[m_nStage]);
      else
         pA = (ZFXMatrix*)&(m_mProjO[m_nStage]);
      }

   ZFXMatrix *pM = (ZFXMatrix*)&m_mViewProj;
   (*pM) = (*pB) * (*pA);
   } // CalcViewProjMatrix
/*----------------------------------------------------------------*/



void ZFXD3D::CalcOrthoProjMatrix(float l, float r, float b, float t,
                                 float fN, float fF, int nStage) {
   float x =  2.0f / (r-l);
   float y =  2.0f / (t-b);
   float z =  2.0f / (fF-fN);
   float tx = -(r+l) / (r-l);
   float ty = -(t+b) / (t-b);
   float tz = -(fF+fN) / (fF-fN);

   memset(&m_mProjO[nStage], 0, sizeof(D3DMATRIX));
   m_mProjO[nStage]._11 = x;
   m_mProjO[nStage]._22 = y;
   m_mProjO[nStage]._33 = z;
   m_mProjO[nStage]._44 = 1.0f;
   m_mProjO[nStage]._41 = tx;
   m_mProjO[nStage]._42 = ty;
   m_mProjO[nStage]._43 = tz;
   } // CalcOrthoProjMatrix
/*----------------------------------------------------------------*/


/**
 * Calculate a combo matrix for world, view and projection.
 */
void ZFXD3D::CalcWorldViewProjMatrix(void) {
   ZFXMatrix *pProj;
   ZFXMatrix *pView;
   ZFXMatrix *pWorld;

   pWorld = (ZFXMatrix*)&m_mWorld;

   // 2D, perspective or orthogonal mode
   if (m_Mode == EMD_TWOD) {
      pProj = (ZFXMatrix*)&m_mProj2D;
      pView = (ZFXMatrix*)&m_mView2D;
      }
   else {
      pView = (ZFXMatrix*)&m_mView3D;

      if (m_Mode == EMD_PERSPECTIVE)
         pProj = (ZFXMatrix*)&(m_mProjP[m_nStage]);
      else
         pProj = (ZFXMatrix*)&(m_mProjO[m_nStage]);
      }

   ZFXMatrix *pCombo = (ZFXMatrix*)&m_mWorldViewProj;
   (*pCombo) = ((*pWorld) * (*pView)) * (*pProj);
   } // CalcWorldViewProjMatrix
/*----------------------------------------------------------------*/


/**
 * Calculate perspective 3D projection matrix.
 * -> IN: float     - field of horizontal view
 *        float     - aspect ration (viewport height / width)
 *        D3DMATRIX - adress to store result
 */
HRESULT ZFXD3D::CalcPerspProjMatrix(float fFOV, float fAspect, D3DMATRIX *m) {
   if(fabs(m_fFar - m_fNear) < 0.01f)
      return ZFX_FAIL;

   float sinFOV2 = sinf(fFOV/2);

   if(fabs(sinFOV2) < 0.01f)
      return ZFX_FAIL;

   float cosFOV2 = cosf(fFOV/2);

   float w = fAspect * (cosFOV2 / sinFOV2);
   float h =   1.0f  * (cosFOV2 / sinFOV2);
   float Q = m_fFar / (m_fFar - m_fNear);

   memset(m, 0, sizeof(D3DMATRIX));
   (*m)._11 = w;
   (*m)._22 = h;
   (*m)._33 = Q;
   (*m)._34 = 1.0f;
   (*m)._43 = -Q*m_fNear;
   return ZFX_OK;
   } // CalcPerspProjMatrix
/*----------------------------------------------------------------*/


/**
 * Set camera as viewmatrix.
 * -> IN: float* - 4 float building camera's right vector
 *        float* - 4 float building camera's up vector
 *        float* - 4 float building camera's direction vector
 *        float* - 4 float building camera's pos vector
 */
HRESULT ZFXD3D::SetView3D(const ZFXVector &vcRight, 
                          const ZFXVector &vcUp, 
                          const ZFXVector &vcDir,
                          const ZFXVector &vcPos) {
   if (!m_bRunning) return E_FAIL;

   m_mView3D._14 = m_mView3D._21 = m_mView3D._34 = 0.0f;
   m_mView3D._44 = 1.0f;

   m_mView3D._11 = vcRight.x;
   m_mView3D._21 = vcRight.y;
   m_mView3D._31 = vcRight.z;
   m_mView3D._41 = - (vcRight*vcPos);

   m_mView3D._12 = vcUp.x;
   m_mView3D._22 = vcUp.y;
   m_mView3D._32 = vcUp.z;
   m_mView3D._42 = - (vcUp*vcPos);

   m_mView3D._13 = vcDir.x;
   m_mView3D._23 = vcDir.y;
   m_mView3D._33 = vcDir.z;
   m_mView3D._43 = - (vcDir*vcPos);

   if (!m_bUseShaders) {
      // activate viewmatrix for D3D
      if (FAILED(m_pDevice->SetTransform(D3DTS_VIEW, &m_mView3D)))
         return ZFX_FAIL;
      }

   // view changed so recalculate combomatrix
   CalcViewProjMatrix();
   CalcWorldViewProjMatrix();
   return ZFX_OK;
   }
/*----------------------------------------------------------------*/


/**
 * Calculates look at matrix for given point and calls SetView3D
 * to active the look at matrix.
 * -> IN: float* - 3 floats building camera's psoition vector
 *        float* - 3 floats building lookat point vector
 *        float* - 3 floats building world up vector at cam pos
 */
HRESULT ZFXD3D::SetViewLookAt(const ZFXVector &vcPos, 
                              const ZFXVector &vcPoint, 
                              const ZFXVector &vcWorldUp) {
   ZFXVector vcDir, vcTemp, vcUp;

   vcDir = vcPoint - vcPos;
   vcDir.Normalize();

   // calculate up vector
   float fDot = vcWorldUp * vcDir;
   
   vcTemp = vcDir * fDot;
   vcUp = vcWorldUp - vcTemp;
   float fL = vcUp.GetLength();

   // if length too small take normal y axis as up vector
   if (fL < 1e-6f) {
      ZFXVector vcY;
      vcY.Set(0.0f, 1.0f, 0.0f);

      vcTemp = vcDir * vcDir.y;
      vcUp = vcY - vcTemp;

      fL = vcUp.GetLength();

      // if still too small take z axis as up vector
      if (fL < 1e-6f) {
         vcY.Set(0.0f, 0.0f, 1.0f);

         vcTemp = vcDir * vcDir.z;
         vcUp = vcY - vcTemp;

         // if still too small we are lost         
         fL = vcUp.GetLength();
         if(fL < 1e-6f) return ZFX_FAIL;
         }
      }

   vcUp /= fL;

   // build right vector using cross product
   ZFXVector vcRight;
   vcRight.Cross(vcUp, vcDir);

   // build final matrix and set for device
   return SetView3D(vcRight, vcUp, vcDir, vcPos);
   } // SetViewLookAt
/*----------------------------------------------------------------*/


/**
 * Set Clipping Planes and take care of other values that need
 * to be changed then. 
 */
void ZFXD3D::SetClippingPlanes(float fNear, float fFar) {
   m_fNear = fNear;
   m_fFar  = fFar;

   if (m_fNear <= 0.0f)
      m_fNear = 0.01f;

   if (m_fFar <= 1.0f)
      m_fFar = 1.00f;
   
   if (m_fNear >= m_fFar) {
      m_fNear = m_fFar;
      m_fFar  = m_fNear + 1.0f;
      }

   // change 2D projection and view
   Prepare2D();

   // change orthogonal projection
   float Q = 1.0f / (m_fFar-m_fNear);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -