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

📄 zfxd3d_vcache.cpp

📁 This is a book introduce some tech about Game Engine 3D
💻 CPP
📖 第 1 页 / 共 4 页
字号:
   pVerts[0].y = fStart[1];
   pVerts[0].z = fStart[2];
   pVerts[1].x = fEnd[0];
   pVerts[1].y = fEnd[1];
   pVerts[1].z = fEnd[2];

   // set prelit
   pVerts[0].Color = pVerts[1].Color = D3DCOLOR_COLORVALUE(
      pClr->fR, pClr->fG,
      pClr->fB, pClr->fA);

   memset(&mtrl, 0, sizeof(D3DMATERIAL9));
	mtrl.Diffuse.r = mtrl.Ambient.r = pClr->fR;
   mtrl.Diffuse.g = mtrl.Ambient.g = pClr->fG;
   mtrl.Diffuse.b = mtrl.Ambient.b = pClr->fB;
   mtrl.Diffuse.a = mtrl.Ambient.a = pClr->fA;

   m_pDevice->SetMaterial(&mtrl);
   m_pDevice->SetTexture(0,NULL);

   m_pDevice->SetFVF(FVF_LVERTEX);
   m_pDevice->SetVertexShader(NULL);
   m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

   // render list of lines
   if (FAILED(m_pDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, 
                                         pVerts, sizeof(LVERTEX)))) {
      m_pDevice->SetFVF(NULL);
      m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
      return ZFX_FAIL;
      }
   m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
   m_pDevice->SetFVF(NULL);
   return ZFX_OK;
   } // RenderLine
/*----------------------------------------------------------------*/


/**
 * write outputstring to attribut outputstream if exists
 * -> IN: bool - flush immediately
 *        ...  - output values
 */
void ZFXD3DVCManager::Log(char *chString, ...) {

   char ch[256];
   char *pArgs;
   
   pArgs = (char*) &chString + sizeof(chString);
   vsprintf(ch, chString, pArgs);
   fprintf(m_pLog, "[ZFXD3DVCMngr]: ");
   fprintf(m_pLog, ch);
   fprintf(m_pLog, "\n");
   
   if (g_bLF)
      fflush(m_pLog);
   } // Log
/*----------------------------------------------------------------*/



// F U N C T I O N S ///////////////////////////////////////////////

/**
 * Constructor: Initialize members, especially vertex- and index-buffer.
 * -> IN: UINT       - max number of vertices in cache
 *        UINT       - max number of indices in cache
 *        UINT       - size of one vertex element
 *        SKINMAN    - pointer to initialized skin manager
 *        D3DDEVICE  - pointer to initialized d3d device
 */
ZFXD3DVCache::ZFXD3DVCache(UINT nVertsMax, UINT nIndisMax, 
                           UINT nStride,  ZFXD3DSkinManager *pSkinMan,
                           LPDIRECT3DDEVICE9 pDevice, ZFXD3DVCManager *pDad,
                           DWORD dwID, DWORD dwFVF, FILE *pLog) {
   HRESULT hr;

   m_pDevice      = pDevice;
   m_pSkinMan     = pSkinMan;
   m_pDad         = pDad;
   m_nNumVertsMax = nVertsMax;
   m_nNumIndisMax = nIndisMax;
   m_nNumVerts    = 0;
   m_nNumIndis    = 0;
   m_dwID         = dwID;
   m_dwFVF        = dwFVF;
   m_nStride      = nStride;
   m_pLog         = pLog;

   memset(&m_Skin, MAX_ID, sizeof(ZFXSKIN));
   m_SkinID = MAX_ID;

   // create the buffers
   m_pVB = NULL;
   m_pIB = NULL;

   hr = pDevice->CreateVertexBuffer(nVertsMax * nStride,
		                              D3DUSAGE_DYNAMIC | 
                                    D3DUSAGE_WRITEONLY,
                                    0, D3DPOOL_DEFAULT, 
                                    &m_pVB, NULL);
   if (FAILED(hr)) m_pVB = NULL;

   hr = pDevice->CreateIndexBuffer(nIndisMax * sizeof(WORD),
		                             D3DUSAGE_DYNAMIC | 
                                   D3DUSAGE_WRITEONLY,
                                   D3DFMT_INDEX16, 
                                   D3DPOOL_DEFAULT, &m_pIB, NULL);
   if (FAILED(hr)) m_pIB = NULL;
   } // constructor
/*----------------------------------------------------------------*/


/**
 * Destructor: Just release all of the stuff.
 */
ZFXD3DVCache::~ZFXD3DVCache(void) {
   if (m_pVB) {
      m_pVB->Release();
      m_pVB = NULL;
      }
   if (m_pIB) {
      m_pIB->Release();
      m_pIB = NULL;
      }
   } // destructor 
/*----------------------------------------------------------------*/


/**
 * Set the given texture for the given stage.
 * -> IN: ZFXSKIN - textures and material used by this polys
 */
void ZFXD3DVCache::SetSkin(UINT SkinID, bool bUseShaders) {
   // if a new texture is coming, flush all content of
   // the cache because that is using other textures
   if (!UsesSkin(SkinID)) {
      ZFXSKIN *pSkin = &m_pSkinMan->GetSkin(SkinID);

      if (!IsEmpty()) Flush(bUseShaders);
      
      memcpy(&m_Skin, pSkin, sizeof(ZFXSKIN));
      m_SkinID = SkinID;
      
      // skin changing so active cache is invalid any case
      m_pDad->InvalidateStates();
      }
   } // SetSkin
/*----------------------------------------------------------------*/


/**
 * Send the content of the cache to the renderer and resets the
 * cache to accept new content.
 */
HRESULT ZFXD3DVCache::Flush(bool bUseShaders) {
   HRESULT hr=ZFX_FAIL;
   int iT=0;

   // anything to do at all?
   if (m_nNumVerts <= 0) return ZFX_OK;

   // are the caches buffers still active?
   if ( m_pDad->GetActiveCache() != m_dwID) {


      // if using shaders they should be activated by the
      // ActivateVShader methods. Else set FVF
      if (!bUseShaders) m_pDevice->SetFVF(m_dwFVF);

      m_pDevice->SetIndices(m_pIB);
      m_pDevice->SetStreamSource(0, m_pVB, 0, m_nStride);
      m_pDad->SetActiveCache(m_dwID);
      } // [device->cache]


   // is the device already using this skin?   
   if (m_pDad->GetZFXD3D()->GetActiveSkinID() != m_SkinID) {
      // set material for device
      LPDIRECT3DTEXTURE9 pTex=NULL;
      ZFXMATERIAL *pMat = &m_pSkinMan->m_pMaterials[m_Skin.nMaterial];

      // WIREFRAME MODE NEEDS A SPECIAL CASE
      if (m_pDad->GetZFXD3D()->GetShadeMode() == RS_SHADE_SOLID) {
         if (!m_pDad->GetZFXD3D()->UsesShaders()) {
            D3DMATERIAL9 mat = { 
               pMat->cDiffuse.fR,  pMat->cDiffuse.fG,  pMat->cDiffuse.fB,  pMat->cDiffuse.fA,
               pMat->cAmbient.fR,  pMat->cAmbient.fG,  pMat->cAmbient.fB,  pMat->cAmbient.fA,
               pMat->cSpecular.fR, pMat->cSpecular.fG, pMat->cSpecular.fB, pMat->cSpecular.fA,
               pMat->cEmissive.fR, pMat->cEmissive.fG, pMat->cEmissive.fB, pMat->cEmissive.fA,
               pMat->fPower };

            m_pDevice->SetMaterial(&mat);
            }
         else {
            m_pDad->GetZFXD3D()->SetShaderConstant(SHT_PIXEL, DAT_FLOAT, 1, 1, &pMat->cAmbient);
            m_pDad->GetZFXD3D()->SetShaderConstant(SHT_PIXEL, DAT_FLOAT, 2, 1, &pMat->cDiffuse);
            m_pDad->GetZFXD3D()->SetShaderConstant(SHT_PIXEL, DAT_FLOAT, 3, 1, &pMat->cEmissive);
            m_pDad->GetZFXD3D()->SetShaderConstant(SHT_PIXEL, DAT_FLOAT, 4, 1, &pMat->cSpecular);
            }

         if ( m_pDad->GetZFXD3D()->UsesTextures() ) {
            // set texture for device
            for (iT=0; iT<8; iT++) {
               if (m_Skin.nTexture[iT] != MAX_ID) {
                  pTex = (LPDIRECT3DTEXTURE9)m_pSkinMan->m_pTextures[
                                             m_Skin.nTexture[iT]].pData;
                  if (FAILED(m_pDevice->SetTexture(iT, pTex)))
                     Log("error: SetTexture() in VC::Flush() failed");
               
                  // set texture operations
                  m_pDevice->SetTextureStageState(iT, D3DTSS_TEXCOORDINDEX, 0);
                  m_pDevice->SetTextureStageState(iT, D3DTSS_COLORARG1, D3DTA_TEXTURE);
                  m_pDevice->SetTextureStageState(iT, D3DTSS_COLORARG2, D3DTA_CURRENT);
                  m_pDevice->SetTextureStageState(iT, D3DTSS_COLOROP, 
                                                  m_pDad->GetZFXD3D()->GetTOP(iT));
                  }
               else break;
               } // for
            // deactivate unused stages at all costs
            m_pDevice->SetTextureStageState(iT, D3DTSS_COLOROP, D3DTOP_DISABLE);
            }
         else {
            m_pDevice->SetTexture(0, NULL);
            m_pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
            }
         }
      else {
         ZFXCOLOR clrWire = m_pDad->GetZFXD3D()->GetWireColor();
         // set material
         D3DMATERIAL9 matW = { 
            clrWire.fR, clrWire.fG, clrWire.fB, clrWire.fA,
            clrWire.fR, clrWire.fG, clrWire.fB, clrWire.fA,
            0.0f,             0.0f,       0.0f,       1.0f,
            0.0f,             0.0f,       0.0f,       1.0f,
            1.0f };
         m_pDevice->SetMaterial(&matW);

         // set no texture for device
         m_pDevice->SetTexture(0, NULL);
         m_pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
         }

      // set alpha states for device
      if (m_Skin.bAlpha) {
         m_pDevice->SetRenderState(D3DRS_ALPHAREF, 50);
         m_pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
         m_pDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
         m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
         m_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
         m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
         }
      else {
         m_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
         m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
         }
      // now its active
      m_pDad->GetZFXD3D()->SetActiveSkinID(m_SkinID);
      } // [device->skin]

   //  should we use additive rendering?
   if (m_pDad->GetZFXD3D()->UsesAdditiveBlending()) {
      m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
      m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
      m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
      }

   //  should we use rendering to color buffer at all?
   if (!m_pDad->GetZFXD3D()->UsesColorBuffer()) {
      m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
      m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
      m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
      }

   ZFXRENDERSTATE sm = m_pDad->GetZFXD3D()->GetShadeMode();

   // render content
   if ( sm == RS_SHADE_POINTS ) {
      hr = m_pDevice->DrawPrimitive(
                        D3DPT_POINTLIST,
                        0, m_nNumVerts);
      }
   else if ( sm == RS_SHADE_LINES ) {
      hr = m_pDevice->DrawIndexedPrimitive(
                        D3DPT_LINELIST,
                        0, 0, m_nNumVerts,
                        0, m_nNumIndis/2);
      }
   else if ( sm == RS_SHADE_HULLWIRE ) {
      hr = m_pDevice->DrawIndexedPrimitive(
                        D3DPT_LINESTRIP,
                        0, 0, m_nNumVerts,
                        0, m_nNumVerts);
      }
   else { // RS_SHADE_SOLID || RS_SHADE_TRIWIRE
      hr = m_pDevice->DrawIndexedPrimitive(
                        D3DPT_TRIANGLELIST,
                        0, 0, m_nNumVerts,
                        0, m_nNumIndis/3);
      }

   if (FAILED(hr)) {
      Log("error: IDirect3DDevice::DrawIndexedPrimitive failed");
      return ZFX_FAIL;
      }

   // reset counters
   m_nNumVerts = 0;
   m_nNumIndis = 0;
   return ZFX_OK;
   } // Flush
/*----------------------------------------------------------------*/


/**
 * Fill data into the cache. If the cache is full it will be flushed
 * prior to accept new data. If no Indexlist is used set indexlist
 * parameter to NULL.
 * -> IN: UINT  - number of vertices in list
 *        UINT  - number of indices in list
 *        void* - pointer to vertex list
 *        WORD* - pointer to index list
 */
HRESULT ZFXD3DVCache::Add(UINT  nVerts, UINT nIndis, 
                          const void *pVerts,
                          const WORD *pIndices,
                          bool  bUseShaders) {
   BYTE *tmp_pVerts=NULL;         // pointer to VB memory
   WORD *tmp_pIndis=NULL;         // pointer to IB memory
   
   int   nSizeV = m_nStride*nVerts;
   int   nSizeI = sizeof(WORD)*nIndis;

   int   nPosV;
   int   nPosI;
   DWORD dwFlags;

   // lists will never fit into this cache
   if (nVerts>m_nNumVertsMax || nIndis>m_nNumIndisMax)
      return ZFX_BUFFERSIZE;

   // cache is already full, so flush it
   if ( (nVerts+m_nNumVerts > m_nNumVertsMax) ||
        (nIndis+m_nNumIndis > m_nNumIndisMax) ) {
      if ( Flush(bUseShaders) != ZFX_OK) {
         Log("error: Flush()");
         return ZFX_FAIL;
         }
      }

   // if nothing is in buffer discard content
   if (m_nNumVerts == 0) {
      nPosV = nPosI = 0;
      dwFlags = D3DLOCK_DISCARD;
      }
   // else just append data without overwrites
   else {
      nPosV = m_nStride*m_nNumVerts;
      nPosI = sizeof(WORD)*m_nNumIndis;
      dwFlags = D3DLOCK_NOOVERWRITE;
      }
          
   // now lock buffers
   if (FAILED(m_pVB->Lock(nPosV, nSizeV, (void**)&tmp_pVerts, dwFlags)))
      return ZFX_BUFFERLOCK;
   if (FAILED(m_pIB->Lock(nPosI, nSizeI, (void**)&tmp_pIndis, dwFlags))) {
      m_pVB->Unlock();
      return ZFX_BUFFERLOCK;
      }

   // copy vertex data into the buffer
   memcpy(tmp_pVerts, pVerts, nSizeV);

   // copy indices into the buffer
   int nBase = m_nNumVerts;
   if (!pIndices) nIndis = nVerts;

   for (UINT i=0; i<nIndis; i++) {
      if (pIndices != NULL)
         tmp_pIndis[i] = pIndices[i] + nBase;
      else
         tmp_pIndis[i] = i + nBase;
      m_nNumIndis++;
      }

   // add to count
   m_nNumVerts += nVerts;

   // unlock buffers
   m_pVB->Unlock();
   m_pIB->Unlock();
   return ZFX_OK;
   } // Add
/*----------------------------------------------------------------*/


/**
 * write outputstring to attribut outputstream if exists
 * -> IN: bool - flush immediately
 *        char - format string to output
 *        ...  - output values
 */
void ZFXD3DVCache::Log(char *chString, ...) {

   char ch[256];
   char *pArgs;
   
   pArgs = (char*) &chString + sizeof(chString);
   vsprintf(ch, chString, pArgs);
   fprintf(m_pLog, "[ZFXD3DVCache]: ");
   fprintf(m_pLog, ch);
   fprintf(m_pLog, "\n");
   
   if (g_bLF)
      fflush(m_pLog);
   } // Log
/*----------------------------------------------------------------*/

⌨️ 快捷键说明

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