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

📄 zfxd3d_vcache.cpp

📁 This is a book introduce some tech about Game Engine 3D
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*******************************************************************
 * ZFXEngine!                                                      *
 * (c)2003 by Stefan Zerbst | www.zfx.info                         *
 *-----------------------------------------------------------------*
 * File: ZFXD3D_vcache.cpp                                         *
 * part of render dll implementing direct3d rendering              *
 *******************************************************************/


// I N C L U D E S /////////////////////////////////////////////////

#include "ZFXD3D_vcache.h"    // class definition
#include "ZFXD3D.h"           // FVF definitions
#include "ZFX.h"              // return values and stuff


extern bool g_bLF;


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

/**
 * Constructor: Initializes vertex cache arrays
 */
ZFXD3DVCManager::ZFXD3DVCManager(ZFXD3DSkinManager *pSkinMan,
                                 LPDIRECT3DDEVICE9 pDevice,
                                 ZFXD3D *pZFXD3D, UINT nMaxVerts, 
                                 UINT nMaxIndis, FILE *pLog) {
   DWORD dwID=1;
   int   i=0;

   m_pSB    = NULL;
   m_pIB    = NULL;
   m_nNumSB = 0;
   m_nNumIB = 0;

   m_pLog          = pLog;
   m_pDevice       = pDevice;
   m_pZFXD3D       = pZFXD3D;
   m_pSkinMan      = pSkinMan;
   m_dwActiveCache = MAX_ID;
   m_dwActiveSB    = MAX_ID;
   m_dwActiveIB    = MAX_ID;

   for (i=0; i<NUM_CACHES; i++) {
      m_CachePS[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(PVERTEX),
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_PVERTEX, pLog);

      m_CacheUU[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(VERTEX),
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_VERTEX, pLog);
      
      m_CacheUL[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(LVERTEX), 
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_LVERTEX, pLog);

      m_CacheCA[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(CVERTEX), 
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_CVERTEX, pLog);

      m_Cache3T[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(VERTEX3T), 
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_T3VERTEX, pLog);

      m_CacheTV[i] = new ZFXD3DVCache(nMaxVerts, nMaxIndis, 
                                      sizeof(TVERTEX), 
                                      pSkinMan, pDevice, this,
                                      dwID++, FVF_TVERTEX, pLog);
      } // for
   Log("online");
   } // constructor
/*----------------------------------------------------------------*/


/**
 * Destructor: Release vertex cache arrays
 */
ZFXD3DVCManager::~ZFXD3DVCManager(void) {
   UINT n=0;
   int  i=0;

   // release static buffers
   if ( m_pSB ) {
      for (n=0; n<m_nNumSB; n++) {
         if (m_pSB[n].pVB) {
            m_pSB[n].pVB->Release();
            m_pSB[n].pVB = NULL;
            }
         if (m_pSB[n].pIB) {
            m_pSB[n].pIB->Release();
            m_pSB[n].pIB = NULL;
            }
         }
      free( m_pSB );
      m_pSB = NULL;
      }

   // release index buffers
   for (n=0; n<m_nNumIB; n++) {
      if (m_pIB[n].pIB) {
         m_pIB[n].pIB->Release();
         m_pIB[n].pIB = NULL;
         }
      }

   // free memory for buffer lists
   if (m_pIB) { free(m_pIB); m_pIB=NULL; }

   // free dynamic vertex caches
   for (i=0; i<NUM_CACHES; i++) {
      if (m_CachePS[i]) {
         delete m_CachePS[i];
         m_CachePS[i] = NULL;
         }
      if (m_CacheUU[i]) {
         delete m_CacheUU[i];
         m_CacheUU[i] = NULL;
         }
      if (m_CacheCA[i]) {
         delete m_CacheCA[i];
         m_CacheCA[i] = NULL;
         }
      if (m_Cache3T[i]) {
         delete m_Cache3T[i];
         m_Cache3T[i] = NULL;
         }
      if (m_CacheTV[i]) {
         delete m_CacheTV[i];
         m_CacheTV[i] = NULL;
         }
      if (m_CacheUL[i]) {
         delete m_CacheUL[i];
         m_CacheUL[i] = NULL;
         }
      } // for
   Log("offline (ok)");
   } // destructor
/*----------------------------------------------------------------*/


ZFXRENDERSTATE ZFXD3DVCManager::GetShadeMode(void) 
   { return m_pZFXD3D->GetShadeMode(); }


/**
 * Create a static vertex/index buffer for the given data and returns
 * a handle to that buffer for later rendering processes.
 * -> IN:  ZFXVERTEXID - identify the vertex format used
 *         UINT        - skin that should be used
 *         UINT        - number of vertices to come
 *         UINT        - number of indices to come
 *         void        - pointer to vertex stream
 *         void        - pointer to index stream
 * -> OUT: UINT        - ID to the created buffer
 */
HRESULT ZFXD3DVCManager::CreateStaticBuffer(ZFXVERTEXID VertexID,
                                 UINT nSkinID, UINT nVerts, 
                                 UINT nIndis, const void *pVerts,
                                 const WORD *pIndis, UINT *pnID) {
   HRESULT  hr;
   DWORD    dwActualFVF;
   void    *pData;

   if (m_nNumSB >= (MAX_ID-1)) return ZFX_OUTOFMEMORY;

   // allocate memory for static buffers if needed
   if ( (m_nNumSB % 50) == 0) {
      int n = (m_nNumSB+50)*sizeof(ZFXSTATICBUFFER);
      m_pSB = (ZFXSTATICBUFFER*)realloc(m_pSB, n);
      if (!m_pSB) return ZFX_OUTOFMEMORY;
      }

   m_pSB[m_nNumSB].nNumVerts = nVerts;
   m_pSB[m_nNumSB].nNumIndis = nIndis;
   m_pSB[m_nNumSB].nSkinID   = nSkinID;
   m_pSB[m_nNumSB].pIB       = NULL;
   m_pSB[m_nNumSB].pVB       = NULL;

   // get size and format of vertex
   switch (VertexID) {
      case VID_PS: { 
         m_pSB[m_nNumSB].nStride = sizeof(PVERTEX); 
         m_pSB[m_nNumSB].dwFVF = FVF_PVERTEX;
         } break;
      case VID_UU: { 
         m_pSB[m_nNumSB].nStride = sizeof(VERTEX); 
         m_pSB[m_nNumSB].dwFVF = FVF_VERTEX;
         } break;
      case VID_UL: {
         m_pSB[m_nNumSB].nStride = sizeof(LVERTEX); 
         m_pSB[m_nNumSB].dwFVF = FVF_LVERTEX;
         } break;
      case VID_CA: {
         m_pSB[m_nNumSB].nStride = sizeof(CVERTEX); 
         m_pSB[m_nNumSB].dwFVF = FVF_CVERTEX;
         } break;
      case VID_3T: {
         m_pSB[m_nNumSB].nStride = sizeof(VERTEX3T); 
         m_pSB[m_nNumSB].dwFVF = FVF_T3VERTEX;
         } break;
      case VID_TV: {
         m_pSB[m_nNumSB].nStride = sizeof(TVERTEX); 
         m_pSB[m_nNumSB].dwFVF = FVF_TVERTEX;
         } break;

      default: return ZFX_INVALIDID;
      } // switch

   // create indexbuffer if needed
   if (nIndis > 0) {
      m_pSB[m_nNumSB].bIndis = true;
      m_pSB[m_nNumSB].nNumTris = int(nIndis / 3.0f);

      hr = m_pDevice->CreateIndexBuffer(
                           nIndis * sizeof(WORD),
                           D3DUSAGE_WRITEONLY,
                           D3DFMT_INDEX16,
                           D3DPOOL_DEFAULT,
                           &m_pSB[m_nNumSB].pIB, 
                           NULL);
      if (FAILED(hr)) return ZFX_CREATEBUFFER;

      // fill the index buffer
      if (SUCCEEDED(m_pSB[m_nNumSB].pIB->Lock(
                                     0, 0, (void**)
                                     (&pData), 0))) {
         memcpy(pData, pIndis, nIndis*sizeof(WORD));
         m_pSB[m_nNumSB].pIB->Unlock();
         }
      else return ZFX_BUFFERLOCK;
      }
   else {
      m_pSB[m_nNumSB].bIndis = false;
      m_pSB[m_nNumSB].nNumTris = int(nVerts / 3.0f);
      m_pSB[m_nNumSB].pIB = NULL;
      }

   // no need for FVF if shaders are used
   if (m_pZFXD3D->UsesShaders()) dwActualFVF = 0;
   else dwActualFVF = m_pSB[m_nNumSB].dwFVF;

   // create vertex buffer
   hr = m_pDevice->CreateVertexBuffer(
                           nVerts*m_pSB[m_nNumSB].nStride,
                           D3DUSAGE_WRITEONLY,
                           dwActualFVF,
                           D3DPOOL_DEFAULT,
                           &m_pSB[m_nNumSB].pVB, 
                           NULL);
   if (FAILED(hr)) return ZFX_CREATEBUFFER;

   // fill the vertex buffer
   if (SUCCEEDED(m_pSB[m_nNumSB].pVB->Lock(
                                  0, 0, (void**)
                                  (&pData), 0))) {
      memcpy(pData, pVerts, nVerts*m_pSB[m_nNumSB].nStride);
      m_pSB[m_nNumSB].pVB->Unlock();
      }
   else return ZFX_BUFFERLOCK;

   (*pnID) = m_nNumSB;
   m_nNumSB++;
   return ZFX_OK;
   } // CreateStaticBuffer
/*----------------------------------------------------------------*/


/**
 * Create a static index buffer for the given data and returns a 
 * handle to that buffer for later rendering processes.
 * -> IN:  UINT        - number of indices to come
 *         WORD        - pointer to index stream
 * -> OUT: UINT        - ID to the created buffer
 */
HRESULT ZFXD3DVCManager::CreateIndexBuffer(UINT nIndis,
                                           const WORD *pIndis, 
                                           UINT *pnID) {
   HRESULT  hr;
   void    *pData;

   if (m_nNumIB >= (MAX_ID-1)) return ZFX_OUTOFMEMORY;

   // allocate memory for static buffers if needed
   if ( (m_nNumIB % 50) == 0) {
      int n = (m_nNumIB+50)*sizeof(ZFXINDEXBUFFER);
      m_pIB = (ZFXINDEXBUFFER*)realloc(m_pIB, n);
      if (!m_pIB) return ZFX_OUTOFMEMORY;
      }

   m_pIB[m_nNumIB].nNumIndis = nIndis;
   m_pIB[m_nNumIB].nNumTris = int(nIndis / 3.0f);
   m_pIB[m_nNumIB].pIB = NULL;

   hr = m_pDevice->CreateIndexBuffer(
                        nIndis * sizeof(WORD),
                        D3DUSAGE_WRITEONLY,
                        D3DFMT_INDEX16,
                        D3DPOOL_DEFAULT,
                        &m_pIB[m_nNumIB].pIB, 
                        NULL);
   if (FAILED(hr)) return ZFX_CREATEBUFFER;

   // fill the index buffer
   if (SUCCEEDED(m_pIB[m_nNumIB].pIB->Lock(
                                  0, 0, (void**)
                                  (&pData), 0))) {
      memcpy(pData, pIndis, nIndis*sizeof(WORD));
      m_pIB[m_nNumIB].pIB->Unlock();
      }
   else return ZFX_BUFFERLOCK;

   (*pnID) = m_nNumIB;
   m_nNumIB++;
   return ZFX_OK;
   } // CreateIndexBuffer
/*----------------------------------------------------------------*/


/**
 * Flush all vertex caches no matter which vertex format.
 */
HRESULT ZFXD3DVCManager::ForcedFlushAll(void) {
   HRESULT hr = ZFX_OK;
   bool    bShaders = m_pZFXD3D->UsesShaders();
   int     i;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_CachePS[i]->IsEmpty() )
         if (FAILED( m_CachePS[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_CacheUU[i]->IsEmpty() )
         if (FAILED( m_CacheUU[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_CacheUL[i]->IsEmpty() )
         if (FAILED( m_CacheUL[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_CacheCA[i]->IsEmpty() )
         if (FAILED( m_CacheCA[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_Cache3T[i]->IsEmpty() )
         if (FAILED( m_Cache3T[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;

   for (i=0; i<NUM_CACHES; i++)
      if (!m_CacheTV[i]->IsEmpty() )
         if (FAILED( m_CacheTV[i]->Flush(bShaders) )) 
            hr = ZFX_FAIL;
   return hr;
   } // ForcedFlushAll
/*----------------------------------------------------------------*/


/**
 * Flush all buffers. Call this function if you want to force all
 * contents send to render device to be drawn in backbuffer. This
 * will automaticly be done when calling EndScene() for RenderDevice.
 * -> IN: ZFXVERTEXID - ID for vertex type
 */
HRESULT ZFXD3DVCManager::ForcedFlush(ZFXVERTEXID VertexID) {
   ZFXD3DVCache **pCache=NULL;
   HRESULT hr = ZFX_OK;
   int i=0;

   switch (VertexID) {
      case VID_PS: { pCache = m_CachePS; } break;
      case VID_UU: { pCache = m_CacheUU; } break;
      case VID_UL: { pCache = m_CacheUL; } break;
      case VID_CA: { pCache = m_CacheCA; } break;
      case VID_3T: { pCache = m_Cache3T; } break;
      case VID_TV: { pCache = m_CacheTV; } break;

      // unknown vertex type
      default: return ZFX_INVALIDID;
      } // switch

   for (i=0; i<NUM_CACHES; i++)
      if (FAILED( pCache[i]->Flush(m_pZFXD3D->UsesShaders()) ))
         hr = ZFX_FAIL;

   return hr;
   } // ForcedFlush
/*----------------------------------------------------------------*/


/**
 * Render static buffers with the given skin. Indexbuffer is optional.
 * -> IN: UINT    - index of static vertexbuffer to use
 */
HRESULT ZFXD3DVCManager::Render(UINT nID) {
   HRESULT hr=ZFX_OK;
   int iT=0;

   ZFXRENDERSTATE sm = m_pZFXD3D->GetShadeMode();

   // active cache gets invalid
   m_dwActiveCache = MAX_ID;

   if (nID >= m_nNumSB) {
      Log("error: invalid static buffer ID");
      return ZFX_INVALIDPARAM;
      }

   // activate buffers if not already active
   if (m_dwActiveSB != nID) {

⌨️ 快捷键说明

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