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

📄 loadsavedds.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* Copyright (C) Greg James, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Greg James, 2001"
 */
#include "cdds.h"

/////////////////////////////////////////////////////////////////////////////
// CDDS construction/destruction


CDDS::CDDS()
{
    m_ptexOrig = NULL;
    m_ptexNew = NULL;

    m_dwWidth = 0;
    m_dwHeight = 0;
    m_dwDepth = 0;
    m_numMips = 0;

    m_dwCubeMapFlags = 0;
    m_bAllocatedInternally = false;


    //m_bTitleModsChanged = FALSE;
}


CDDS::~CDDS()
{
   if (m_bAllocatedInternally)
        ReleasePpo(&m_ptexOrig);
    //ReleasePpo(&m_ptexNew);
}


BOOL CDDS::MakeTexture(TextureType iTexType, DWORD dwWidth, DWORD dwHeight, int numMips,
                      D3DFORMAT fmt, int dwDepth)
{
    HRESULT hr;



    m_dwWidth = dwWidth;
    m_dwHeight  = dwHeight;
    m_numMips = numMips;

    switch(iTexType)
    {
    case TEXTURE2D:
        LPDIRECT3DTEXTURE8 pmiptex;
        hr = m_pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 
            0, fmt, D3DPOOL_MANAGED, &pmiptex);
        if (FAILED(hr))
        {
            AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
            return FALSE;
        }
        m_bAllocatedInternally = true;
        m_ptexOrig = pmiptex;
        break;
    
    case CUBE_TEXTURE:
        // Cube Map
        LPDIRECT3DCUBETEXTURE8 pcubetex;
        m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
        hr = m_pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 
            0, fmt, D3DPOOL_MANAGED, &pcubetex);
        if (FAILED(hr))
        {
            AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
            return FALSE;
        }
        m_bAllocatedInternally = true;
        m_ptexOrig = pcubetex;
        break;

    case VOLUME_TEXTURE:
        LPDIRECT3DVOLUMETEXTURE8 pvoltex;
        m_dwDepth = dwDepth;
        hr = m_pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips, 
            0, fmt, D3DPOOL_SYSTEMMEM, &pvoltex);
        if (FAILED(hr))
        {
            AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
            return FALSE;
        }
        m_bAllocatedInternally = true;
        m_ptexOrig = pvoltex;
        break;
    }

    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CDDS serialization

/*void CDDS::Serialize(CArchive& ar)
{
    HRESULT hr;
    
    if (ar.IsStoring())
    {
        LPDIRECT3DBASETEXTURE8 ptex;
        ptex = (m_ptexNew == NULL ? m_ptexOrig : m_ptexNew);
        SaveDDS(ptex, ar);
    }
    else
    {
        CFile* pFile = ar.GetFile();
        CSTR str = pFile->GetFilePath();
        TCHAR* pszExt = strrchr(str, '.');
        if (lstrcmpi(pszExt, ".bmp") == 0 || lstrcmpi(pszExt, ".tga") == 0)
        {
            if (FAILED(hr = LoadBmp(str)))
                AfxThrowArchiveException(CArchiveException::generic);
        }
        else if (lstrcmpi(pszExt, ".dds") == 0)
        {
            ReleasePpo(&m_ptexOrig);
            ReleasePpo(&m_ptexNew);
            if (FAILED(hr = LoadDDS(&m_ptexOrig, ar)))
                AfxThrowArchiveException(CArchiveException::badIndex); // invalid file format
        }
        else
        {
            AfxThrowArchiveException(CArchiveException::badIndex); // invalid file format
        }
    }
} */


HRESULT CDDS::SaveTexture(LPDIRECT3DTEXTURE8 ptex, const char * filename)
{
    //HRESULT hr;
    D3DSURFACE_DESC sd;
    ptex->GetLevelDesc(0, &sd);
    
    m_dwWidth = sd.Width;
    m_dwHeight  = sd.Height;

    m_numMips = ptex->GetLevelCount();

    m_ptexOrig = ptex;

    return SaveDDS(ptex, filename);

}
HRESULT CDDS::SaveCubeMap(LPDIRECT3DCUBETEXTURE8 pcubetex, const char * filename)
{
    //HRESULT hr;
    D3DSURFACE_DESC sd;
    pcubetex->GetLevelDesc(0, &sd);
    
    m_dwWidth = sd.Width;
    m_dwHeight  = sd.Height;

    m_numMips = pcubetex->GetLevelCount();


    m_ptexOrig = pcubetex;
    
    return SaveDDS(pcubetex, filename);
}

HRESULT CDDS::SaveVolumeTexture(LPDIRECT3DVOLUMETEXTURE8 pvoltex, const char * filename)
{
    //HRESULT hr;
    D3DVOLUME_DESC vd;
    pvoltex->GetLevelDesc(0, &vd);

    m_dwWidth = vd.Width;
    m_dwHeight  = vd.Height;
    m_dwDepth = vd.Depth;

    m_numMips = pvoltex->GetLevelCount();

    m_ptexOrig = pvoltex;


    return SaveDDS(pvoltex, filename);
    
}

HRESULT CDDS::SaveDDS(LPDIRECT3DBASETEXTURE8 ptex, const char * filename)
{
    CArchive  ar;

    HRESULT hr;
    DDS_HEADER ddsh;
    DWORD dwMagic;
    D3DFORMAT fmt;
    DWORD dwSize;
    DWORD dwPitch = 0;
    D3DLOCKED_RECT lr;
    D3DLOCKED_BOX lb;
    LPDIRECT3DTEXTURE8 pmiptex = NULL;
    LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
    LPDIRECT3DVOLUMETEXTURE8 pvoltex = NULL;

    ar.Open(filename, "wb");

    if (IsVolumeMap())
        pvoltex = (LPDIRECT3DVOLUMETEXTURE8)ptex;
    else if (!IsCubeMap())
        pmiptex = (LPDIRECT3DTEXTURE8)ptex;
    else
        pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;

    dwMagic = MAKEFOURCC('D','D','S',' ');
    ar.Write(&dwMagic, sizeof(dwMagic));

    // Fill in the DDS header structure
    ZeroMemory(&ddsh, sizeof(ddsh));
    ddsh.dwSize = sizeof(ddsh);
    ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE;
    ddsh.dwWidth = m_dwWidth;
    ddsh.dwHeight = m_dwHeight;
    ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE;
    if (m_numMips > 1)
    {
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_MIPMAP;
        ddsh.dwSurfaceFlags |= DDS_SURFACE_FLAGS_MIPMAP;
        ddsh.dwMipMapCount = m_numMips;
    }
    if (pvoltex != NULL)
    {
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_VOLUME;
        // Note: "dwCubemapFlags" is mostly for cubemap flags,
        // but in this case is also used to indicate a volume texture
        ddsh.dwCubemapFlags |= DDS_FLAGS_VOLUME;
        ddsh.dwDepth = m_dwDepth;
    }
    
    // In DX7, you could (optionally) use and save a subset of 
    // cubemap faces.  In DX8, you must use and save all faces of a cubemap.
    if (IsCubeMap())
    {
        ddsh.dwSurfaceFlags |= DDS_SURFACE_FLAGS_CUBEMAP;
        ddsh.dwCubemapFlags = DDS_CUBEMAP_ALLFACES;
    }

    // Determine dwPitch and dwSize for the texture
    if (pvoltex != NULL)
    {
        D3DVOLUME_DESC vd;
        pvoltex->GetLevelDesc(0, &vd);
        fmt = vd.Format;
        dwSize = vd.Size;
        if (SUCCEEDED(pvoltex->LockBox(0, &lb, NULL, D3DLOCK_READONLY)))
        {
            dwPitch = lb.RowPitch;
            pvoltex->UnlockBox(0);
        }
    }
    else if (pmiptex != NULL)
    {
        D3DSURFACE_DESC sd;
        pmiptex->GetLevelDesc(0, &sd);
        fmt = sd.Format;
        dwSize = sd.Size;
        if (SUCCEEDED(pmiptex->LockRect(0, &lr, NULL, D3DLOCK_READONLY)))
        {
            dwPitch = lr.Pitch;
            pmiptex->UnlockRect(0);
        }
    }
    else
    {
        D3DSURFACE_DESC sd;
        pcubetex->GetLevelDesc(0, &sd);
        fmt = sd.Format;
        dwSize = sd.Size;
        if (SUCCEEDED(pcubetex->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, 
            &lr, NULL, D3DLOCK_READONLY)))
        {
            dwPitch = lr.Pitch;
            pcubetex->UnlockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0);
        }
    }

    // Note that although this code stores the pitch or linear size
    // of the surface in the DDS file (for consistency with DX7), it
    // is better to use the pitch or linear size of the surface
    // created when loading the DDS file into a texture than to use
    // the file values.  The pitch of a created surface, especially, 
    // can be different from the pitch stored in the DDS file.
    switch (fmt)
    {
    case D3DFMT_DXT1:
        ddsh.ddspf = DDSPF_DXT1;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = dwSize;
        break;
    case D3DFMT_DXT2:
        ddsh.ddspf = DDSPF_DXT2;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = dwSize;
        break;
    case D3DFMT_DXT3:
        ddsh.ddspf = DDSPF_DXT3;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = dwSize;
        break;
    case D3DFMT_DXT4:
        ddsh.ddspf = DDSPF_DXT4;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = dwSize;
        break;
    case D3DFMT_DXT5:
        ddsh.ddspf = DDSPF_DXT5;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
        ddsh.dwPitchOrLinearSize = dwSize;
        break;
    case D3DFMT_A8R8G8B8:
        ddsh.ddspf = DDSPF_A8R8G8B8;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
        ddsh.dwPitchOrLinearSize = dwPitch;
        break;
    case D3DFMT_A1R5G5B5:
        ddsh.ddspf = DDSPF_A1R5G5B5;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
        ddsh.dwPitchOrLinearSize = dwPitch;
        break;
    case D3DFMT_A4R4G4B4:
        ddsh.ddspf = DDSPF_A4R4G4B4;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
        ddsh.dwPitchOrLinearSize = dwPitch;
        break;
    case D3DFMT_R8G8B8:
        ddsh.ddspf = DDSPF_R8G8B8;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
        ddsh.dwPitchOrLinearSize = dwPitch;
        break;
    case D3DFMT_R5G6B5:
        ddsh.ddspf = DDSPF_R5G6B5;
        ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
        ddsh.dwPitchOrLinearSize = dwPitch;
        break;
    default:
        return E_FAIL;
    }

    ar.Write(&ddsh, sizeof(ddsh));

    if (pvoltex != NULL)
    {
        if (FAILED(hr = SaveAllVolumeSurfaces(pvoltex, ar)))
            return hr;
    }
    else if (pmiptex != NULL)
    {
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_FORCE_DWORD, ar)))
            return hr;
    }
    else
    {
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_X, ar)))
            return hr;
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_X, ar)))
            return hr;
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_Y, ar)))
            return hr;
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_Y, ar)))
            return hr;
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_Z, ar)))
            return hr;
        if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_Z, ar)))
            return hr;
    }

    ar.Close();
    return S_OK;
}


HRESULT CDDS::SaveAllMipSurfaces(LPDIRECT3DBASETEXTURE8 ptex, D3DCUBEMAP_FACES FaceType, CArchive& ar)
{
    HRESULT hr;
    LPDIRECT3DSURFACE8 psurf;
    D3DSURFACE_DESC sd;
    UINT iLevel;
    D3DLOCKED_RECT lr;
    LPDIRECT3DTEXTURE8 pmiptex = NULL;
    LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;

    if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
        pmiptex = (LPDIRECT3DTEXTURE8)ptex;
    else
        pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;

    for (iLevel = 0; iLevel < m_numMips; iLevel++)
    {
        if (pmiptex != NULL)
            hr = pmiptex->GetSurfaceLevel(iLevel, &psurf);
        else
            hr = pcubetex->GetCubeMapSurface(FaceType, iLevel, &psurf);
        if (FAILED(hr))
            return hr;
        psurf->GetDesc(&sd);
        if (pmiptex != NULL)
            hr = pmiptex->LockRect(iLevel, &lr, NULL, 0);
        else
            hr = pcubetex->LockRect(FaceType, iLevel, &lr, NULL, 0);
        if (FAILED(hr))
            return hr;
        if (sd.Format == D3DFMT_DXT1 ||
            sd.Format == D3DFMT_DXT2 ||
            sd.Format == D3DFMT_DXT3 ||
            sd.Format == D3DFMT_DXT4 ||
            sd.Format == D3DFMT_DXT5)
        {
            ar.Write(lr.pBits, sd.Size);
        }
        else
        {
            DWORD yp;
            BYTE* pbDest = (BYTE*)lr.pBits;
            LONG dataBytesPerRow = 0;
            if (sd.Format == D3DFMT_A8R8G8B8)
                dataBytesPerRow = 4 * sd.Width;
            else if (sd.Format == D3DFMT_R8G8B8)
                dataBytesPerRow = 3 * sd.Width;
            else
                dataBytesPerRow = 2 * sd.Width;
            for (yp = 0; yp < sd.Height; yp++)
            {
                ar.Write(pbDest, dataBytesPerRow);
                pbDest += lr.Pitch;
            }
        }
        if (pmiptex != NULL)
            hr = pmiptex->UnlockRect(iLevel);
        else
            hr = pcubetex->UnlockRect(FaceType, iLevel);
    }

    return S_OK;
}


HRESULT CDDS::SaveAllVolumeSurfaces(LPDIRECT3DVOLUMETEXTURE8 pvoltex, CArchive& ar)
{
    HRESULT hr;
    D3DVOLUME_DESC vd;
    D3DBOX box;
    D3DLOCKED_BOX lb;
    UINT iLevel;
    UINT numBytesPerRow;
    BYTE* pbSlice;
    BYTE* pbRow;
    UINT zp;
    UINT yp;

    for (iLevel = 0; iLevel < m_numMips; iLevel++)
    {
        pvoltex->GetLevelDesc(iLevel, &vd);
        box.Left = 0;
        box.Right = vd.Width;
        box.Top = 0;
        box.Bottom = vd.Height;
        box.Front = 0;
        box.Back = vd.Depth;
        hr = pvoltex->LockBox(iLevel, &lb, &box, 0);
        if (FAILED(hr))
            return hr;
        switch(vd.Format)
        {
        case D3DFMT_A8R8G8B8:
            numBytesPerRow = 4 * vd.Width;
            break;
        case D3DFMT_R8G8B8:
            numBytesPerRow = 3 * vd.Width;

⌨️ 快捷键说明

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