797 lines
21 KiB
C++
797 lines
21 KiB
C++
//**************************************************************************
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999 All Rights Reserved.
|
|
//
|
|
// File: frmsave.cpp
|
|
//
|
|
// Description: Save LPDIRECT3DRMFRAME to an x file.
|
|
//
|
|
// History:
|
|
// 011/06/98 CongpaY Created
|
|
//
|
|
//**************************************************************************
|
|
|
|
|
|
#include <d3drm.h>
|
|
#include <dxfile.h>
|
|
#include <rmxftmpl.h>
|
|
#include <rmxfguid.h>
|
|
#include "frmsave.h"
|
|
|
|
extern HINSTANCE g_hInstD3DXOFDLL;
|
|
|
|
#define MyD3DRMColorGetAlpha(color) ((float)((color & 0xFF000000)>>24)/(float)255)
|
|
#define MyD3DRMColorGetRed(color) ((float)((color & 0x00FF0000)>>16)/(float)255)
|
|
#define MyD3DRMColorGetGreen(color) ((float)((color & 0x0000FF00)>>8)/(float)255)
|
|
#define MyD3DRMColorGetBlue(color) ((float)((color & 0x000000FF))/(float)255)
|
|
|
|
|
|
HRESULT FrameToXFile(LPDIRECT3DRMFRAME3 pFrame,
|
|
LPCSTR filename,
|
|
D3DRMXOFFORMAT d3dFormat,
|
|
D3DRMSAVEOPTIONS d3dSaveFlags)
|
|
{
|
|
Saver saver;
|
|
saver.Init(filename, d3dFormat, d3dSaveFlags);
|
|
saver.SaveHeaderObject();
|
|
saver.SaveFrame(pFrame);
|
|
return S_OK;
|
|
}
|
|
|
|
Saver::Saver()
|
|
{
|
|
pXFile=NULL;
|
|
pSave=NULL;
|
|
}
|
|
|
|
Saver::~Saver()
|
|
{
|
|
if (pSave) pSave->Release();
|
|
if (pXFile) pXFile->Release();
|
|
}
|
|
|
|
HRESULT Saver::Init(LPCSTR filename,
|
|
D3DRMXOFFORMAT d3dFormatArg,
|
|
D3DRMSAVEOPTIONS d3dSaveFlagsArg)
|
|
{
|
|
HRESULT hr;
|
|
d3dFormat = d3dFormatArg;
|
|
d3dSaveFlags = d3dSaveFlagsArg;
|
|
|
|
|
|
CREATEXFILE pCreateXFile=(CREATEXFILE)GetProcAddress( g_hInstD3DXOFDLL, "DirectXFileCreate" );
|
|
if (!pCreateXFile) return E_NOTIMPL;
|
|
|
|
|
|
DXFILEFORMAT xFormat;
|
|
|
|
if (d3dFormat == D3DRMXOF_BINARY)
|
|
xFormat = DXFILEFORMAT_BINARY;
|
|
else if (d3dFormat == D3DRMXOF_TEXT)
|
|
xFormat = DXFILEFORMAT_TEXT;
|
|
else
|
|
xFormat = DXFILEFORMAT_COMPRESSED;
|
|
|
|
//DirectXFileCreate(&pXFile);
|
|
pCreateXFile(&pXFile);
|
|
if (!pXFile) return E_FAIL;
|
|
|
|
hr=pXFile->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
|
|
if FAILED(hr)
|
|
{
|
|
pXFile->Release();
|
|
pXFile=NULL;
|
|
return hr;
|
|
}
|
|
|
|
hr=pXFile->CreateSaveObject(filename, xFormat, &pSave);
|
|
if FAILED(hr)
|
|
{
|
|
pXFile->Release();
|
|
pXFile=NULL;
|
|
pSave=NULL;
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::SaveHeaderObject()
|
|
{
|
|
LPDIRECTXFILEDATA pHeader=NULL;
|
|
Header data;
|
|
HRESULT hr;
|
|
|
|
data.major = 1;
|
|
data.minor = 0;
|
|
data.flags = (d3dFormat == D3DRMXOF_TEXT)? 1 : 0;
|
|
|
|
if (!pSave) return E_FAIL;
|
|
|
|
hr=pSave->CreateDataObject(TID_DXFILEHeader,
|
|
NULL,
|
|
NULL,
|
|
sizeof(Header),
|
|
&data,
|
|
&pHeader);
|
|
if FAILED(hr) return hr;
|
|
if (!pHeader) return hr;
|
|
|
|
hr=pSave->SaveData(pHeader);
|
|
pHeader->Release();
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Saver::SaveFrame(LPDIRECT3DRMFRAME3 pFrame,
|
|
LPDIRECT3DRMFRAME3 pRefFrame,
|
|
LPDIRECTXFILEDATA pRefFrameObj)
|
|
{
|
|
DWORD i;
|
|
HRESULT hr;
|
|
LPDIRECTXFILEDATA pFrameObj=NULL;
|
|
|
|
if (!pSave) return E_FAIL;
|
|
if (!pFrame) return E_FAIL;
|
|
|
|
hr=pSave->CreateDataObject(TID_D3DRMFrame,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&pFrameObj);
|
|
if FAILED(hr) return hr;
|
|
if (!pFrameObj) return E_FAIL;
|
|
|
|
hr=SaveFrameTransform(pFrameObj, pFrame, pRefFrame);
|
|
if FAILED(hr) {
|
|
pFrameObj->Release();
|
|
return hr;
|
|
}
|
|
|
|
// Enumerate visuals.
|
|
|
|
DWORD cVisuals=0;
|
|
|
|
hr=pFrame->GetVisuals(&cVisuals, NULL);
|
|
if FAILED(hr) {
|
|
pFrameObj->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
if (cVisuals)
|
|
{
|
|
LPUNKNOWN *ppUnk = new LPUNKNOWN[cVisuals];
|
|
|
|
hr=pFrame->GetVisuals(&cVisuals, ppUnk);
|
|
if SUCCEEDED(hr)
|
|
{
|
|
for (i = 0; i < cVisuals; i++)
|
|
{
|
|
LPDIRECT3DRMFRAME3 pChildFrame;
|
|
if (ppUnk[i])
|
|
{
|
|
hr = ppUnk[i]->QueryInterface(IID_IDirect3DRMFrame3, (LPVOID *)&pChildFrame);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SaveFrame(pChildFrame, pFrame, pFrameObj);
|
|
pChildFrame->Release();
|
|
}
|
|
else
|
|
{
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder;
|
|
hr = ppUnk[i]->QueryInterface(IID_IDirect3DRMMeshBuilder3, (LPVOID *)&pMeshBuilder);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SaveMeshBuilder(pFrameObj, pMeshBuilder);
|
|
pMeshBuilder->Release();
|
|
}
|
|
}
|
|
ppUnk[i]->Release();
|
|
}
|
|
}
|
|
|
|
delete[] ppUnk;
|
|
}
|
|
} //cVisuals
|
|
|
|
// Enumerate child frames.
|
|
|
|
LPDIRECT3DRMFRAMEARRAY pFrameArray=NULL;
|
|
|
|
hr=pFrame->GetChildren(&pFrameArray);
|
|
if SUCCEEDED(hr)
|
|
{
|
|
for (i = 0; i < pFrameArray->GetSize(); i++)
|
|
{
|
|
LPDIRECT3DRMFRAME pTmpFrame;
|
|
LPDIRECT3DRMFRAME3 pChildFrame;
|
|
pFrameArray->GetElement(i, &pTmpFrame);
|
|
pTmpFrame->QueryInterface(IID_IDirect3DRMFrame3, (LPVOID *)&pChildFrame);
|
|
pTmpFrame->Release();
|
|
SaveFrame(pChildFrame, pFrame, pFrameObj);
|
|
pChildFrame->Release();
|
|
}
|
|
|
|
pFrameArray->Release();
|
|
|
|
// Add frame object to the saved list.
|
|
|
|
if (pRefFrameObj)
|
|
pRefFrameObj->AddDataObject(pFrameObj);
|
|
else
|
|
pSave->SaveData(pFrameObj);
|
|
|
|
pFrameObj->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Saver::SaveFrameTransform(LPDIRECTXFILEDATA pFrameObj,
|
|
LPDIRECT3DRMFRAME3 pFrame,
|
|
LPDIRECT3DRMFRAME3 pRefFrame)
|
|
{
|
|
LPDIRECTXFILEDATA pFrameTransformObj=NULL;
|
|
D3DRMMATRIX4D rmMatrix;
|
|
HRESULT hr;
|
|
|
|
if (!pFrame) return E_INVALIDARG;
|
|
|
|
pFrame->GetTransform(pRefFrame, rmMatrix);
|
|
|
|
hr=pSave->CreateDataObject(TID_D3DRMFrameTransformMatrix,
|
|
NULL,
|
|
NULL,
|
|
sizeof(D3DRMMATRIX4D),
|
|
&rmMatrix,
|
|
&pFrameTransformObj);
|
|
if FAILED(hr) return hr;
|
|
|
|
hr=pFrameObj->AddDataObject(pFrameTransformObj);
|
|
pFrameTransformObj->Release();
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Saver::SaveMeshBuilder(LPDIRECTXFILEDATA pFrameObj,
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder)
|
|
{
|
|
LPDIRECTXFILEDATA pMeshObj;
|
|
DWORD cVertices, cNormals, cFaces, dwFaceData, *pdwFaceData;
|
|
LPDIRECT3DRMFACEARRAY pFaceArray = NULL;
|
|
HRESULT hr;
|
|
|
|
if (!pMeshBuilder) return E_INVALIDARG;
|
|
//pFrameObj can be null
|
|
|
|
hr=pMeshBuilder->GetGeometry(&cVertices, NULL,
|
|
&cNormals, NULL,
|
|
&dwFaceData, NULL);
|
|
if FAILED(hr) return hr;
|
|
|
|
cFaces = pMeshBuilder->GetFaceCount();
|
|
|
|
if (!cVertices || !cNormals || !dwFaceData || !cFaces)
|
|
return S_OK;
|
|
|
|
pdwFaceData = new DWORD[dwFaceData];
|
|
if FAILED(pdwFaceData) return E_OUTOFMEMORY;
|
|
|
|
hr=pMeshBuilder->GetGeometry(NULL, NULL,
|
|
NULL, NULL,
|
|
&dwFaceData, pdwFaceData);
|
|
if FAILED(hr) return hr;
|
|
|
|
hr=CreateMeshObject(cVertices, cFaces, dwFaceData, pdwFaceData,
|
|
pMeshBuilder, &pMeshObj);
|
|
if FAILED(hr) return hr;
|
|
|
|
D3DRMCOLORSOURCE clrSrc = pMeshBuilder->GetColorSource();
|
|
|
|
if (clrSrc == D3DRMCOLOR_FROMVERTEX)
|
|
{
|
|
CreateVertexColorsObject(pMeshObj, cVertices, pMeshBuilder);
|
|
}
|
|
|
|
if (d3dSaveFlags & D3DRMXOFSAVE_MATERIALS)
|
|
{
|
|
if (!pFaceArray)
|
|
pMeshBuilder->GetFaces(&pFaceArray);
|
|
CreateMaterialListObject(pMeshObj, pFaceArray);
|
|
}
|
|
|
|
if (d3dSaveFlags & D3DRMXOFSAVE_NORMALS)
|
|
{
|
|
CreateNormalsObject(pMeshObj,
|
|
cNormals, cFaces, dwFaceData, pdwFaceData,
|
|
pMeshBuilder);
|
|
}
|
|
|
|
|
|
if (d3dSaveFlags & D3DRMXOFSAVE_TEXTURETOPOLOGY)
|
|
{
|
|
if (!pFaceArray)
|
|
pMeshBuilder->GetFaces(&pFaceArray);
|
|
CreateTextureWrapsObject(pMeshObj, pFaceArray);
|
|
}
|
|
|
|
if (d3dSaveFlags & D3DRMXOFSAVE_TEXTURECOORDINATES)
|
|
{
|
|
CreateTextureCoordsObject(pMeshObj, cVertices, pMeshBuilder);
|
|
}
|
|
|
|
if (pFrameObj)
|
|
pFrameObj->AddDataObject(pMeshObj);
|
|
else
|
|
pSave->SaveData(pMeshObj);
|
|
|
|
pMeshObj->Release();
|
|
delete[] pdwFaceData;
|
|
if (pFaceArray)
|
|
pFaceArray->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateMeshObject(DWORD cVertices,
|
|
DWORD cFaces,
|
|
DWORD dwFaceData,
|
|
LPDWORD pdwFaceData,
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder,
|
|
LPDIRECTXFILEDATA *ppMeshObj)
|
|
{
|
|
// mesh data is vertex_count + vertices + face_count + face_vertex_data;
|
|
HRESULT hr;
|
|
|
|
if (!pMeshBuilder) return E_INVALIDARG;
|
|
if (!pSave) return E_INVALIDARG;
|
|
|
|
DWORD cbSize, *data;
|
|
cbSize = cVertices * sizeof(D3DVECTOR) +
|
|
(1 + (dwFaceData + cFaces + 1)/2) * sizeof(DWORD);
|
|
|
|
data = (LPDWORD) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
data[0] = cVertices;
|
|
LPD3DVECTOR pVertices = (LPD3DVECTOR)&data[1];
|
|
pMeshBuilder->GetGeometry(&cVertices, pVertices,
|
|
NULL, NULL,
|
|
NULL, NULL);
|
|
|
|
LPDWORD pdwTmp = (LPDWORD)&pVertices[cVertices];
|
|
*pdwTmp++ = cFaces;
|
|
|
|
while (*pdwFaceData)
|
|
{
|
|
DWORD cFaceVertices = *pdwFaceData++;
|
|
*pdwTmp++ = cFaceVertices;
|
|
|
|
for (DWORD i = 0; i < cFaceVertices; i++)
|
|
{
|
|
*pdwTmp++ = *pdwFaceData++;
|
|
pdwFaceData++; // skip normal index.
|
|
}
|
|
}
|
|
|
|
DWORD dwSize;
|
|
pMeshBuilder->GetName(&dwSize, NULL);
|
|
|
|
LPSTR szName = NULL;
|
|
if (dwSize)
|
|
{
|
|
szName = new char[dwSize];
|
|
pMeshBuilder->GetName(&dwSize, szName);
|
|
}
|
|
|
|
hr=pSave->CreateDataObject(TID_D3DRMMesh,
|
|
szName,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
ppMeshObj);
|
|
|
|
if (szName) lNames.Add(szName);
|
|
delete[] data;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateNormalsObject(LPDIRECTXFILEDATA pMeshObj,
|
|
DWORD cNormals,
|
|
DWORD cFaces,
|
|
DWORD dwFaceData,
|
|
LPDWORD pdwFaceData,
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder)
|
|
{
|
|
// normals data is normal_count + normals + face_count + face_normal_data;
|
|
HRESULT hr;
|
|
|
|
if (!pMeshObj) return E_INVALIDARG;
|
|
|
|
DWORD cbSize, *data;
|
|
cbSize = cNormals * sizeof(D3DVECTOR) +
|
|
(1 + (dwFaceData + cFaces + 1)/2) * sizeof(DWORD);
|
|
|
|
data = (LPDWORD) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
|
|
data[0] = cNormals;
|
|
|
|
LPD3DVECTOR pNormals = (LPD3DVECTOR)&data[1];
|
|
|
|
hr=pMeshBuilder->GetGeometry(NULL, NULL,
|
|
&cNormals, pNormals,
|
|
NULL, NULL);
|
|
if FAILED(hr) return hr;
|
|
|
|
LPDWORD pdwTmp = (LPDWORD)&pNormals[cNormals];
|
|
*pdwTmp++ = cFaces;
|
|
|
|
while (*pdwFaceData)
|
|
{
|
|
DWORD cFaceVertices = *pdwFaceData++;
|
|
*pdwTmp++ = cFaceVertices;
|
|
|
|
for (DWORD i = 0; i < cFaceVertices; i++)
|
|
{
|
|
pdwFaceData++; // skip vertex index.
|
|
*pdwTmp++ = *pdwFaceData++;
|
|
}
|
|
}
|
|
|
|
LPDIRECTXFILEDATA pNormalsObj=NULL;
|
|
|
|
hr=pSave->CreateDataObject(TID_D3DRMMeshNormals,
|
|
NULL,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
&pNormalsObj);
|
|
if FAILED(hr) return hr;
|
|
|
|
pMeshObj->AddDataObject(pNormalsObj);
|
|
pNormalsObj->Release();
|
|
delete[] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateVertexColorsObject(LPDIRECTXFILEDATA pMeshObj,
|
|
DWORD cVertices,
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder)
|
|
{
|
|
DWORD cbSize;
|
|
VertexColors *data;
|
|
HRESULT hr;
|
|
|
|
if (!pSave) return E_INVALIDARG;
|
|
if (!pMeshBuilder) return E_INVALIDARG;
|
|
|
|
cbSize = sizeof(DWORD) + cVertices * sizeof(IndexedColor);
|
|
|
|
data = (VertexColors *) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
|
|
data->cVertices = cVertices;
|
|
|
|
for (DWORD i = 0; i < cVertices; i++)
|
|
{
|
|
D3DCOLOR color = pMeshBuilder->GetVertexColor(i);
|
|
data->vertexColors[i].index = i;
|
|
data->vertexColors[i].color.r = MyD3DRMColorGetRed(color);
|
|
data->vertexColors[i].color.g = MyD3DRMColorGetGreen(color);
|
|
data->vertexColors[i].color.b = MyD3DRMColorGetBlue(color);
|
|
data->vertexColors[i].color.a = MyD3DRMColorGetAlpha(color);
|
|
}
|
|
|
|
LPDIRECTXFILEDATA pVertexColorsObj=NULL;
|
|
|
|
hr=pSave->CreateDataObject(TID_D3DRMMeshVertexColors,
|
|
NULL,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
&pVertexColorsObj);
|
|
if FAILED(hr) {
|
|
delete[] data;
|
|
return hr;
|
|
}
|
|
|
|
pMeshObj->AddDataObject(pVertexColorsObj);
|
|
pVertexColorsObj->Release();
|
|
delete[] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateMaterialListObject(LPDIRECTXFILEDATA pMeshObj,
|
|
LPDIRECT3DRMFACEARRAY pFaceArray)
|
|
{
|
|
DWORD cbSize, cFaces;
|
|
FaceMaterials *data;
|
|
FaceMaterialList lMat;
|
|
|
|
|
|
cFaces = pFaceArray->GetSize();
|
|
cbSize = (2 + cFaces) * sizeof(DWORD);
|
|
|
|
data = (FaceMaterials *) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
|
|
data->cFaceIndexes = cFaces;
|
|
LPDWORD pdwIndex = data->faceIndexes;
|
|
|
|
for (DWORD i = 0; i < cFaces; i++, pdwIndex++)
|
|
{
|
|
LPDIRECT3DRMFACE pFace;
|
|
pFaceArray->GetElement(i, &pFace);
|
|
|
|
D3DCOLOR faceColor;
|
|
LPDIRECT3DRMMATERIAL pMaterial;
|
|
LPDIRECT3DRMTEXTURE pTexture;
|
|
|
|
faceColor = pFace->GetColor();
|
|
pFace->GetMaterial(&pMaterial);
|
|
pFace->GetTexture(&pTexture);
|
|
|
|
*pdwIndex = lMat.Find(faceColor, pMaterial, pTexture);
|
|
|
|
pMaterial->Release();
|
|
if (pTexture) pTexture->Release();
|
|
pFace->Release();
|
|
}
|
|
|
|
data->cMaterials = lMat.Count();
|
|
|
|
if (data->cMaterials == 1)
|
|
{
|
|
data->cFaceIndexes = 1;
|
|
data->faceIndexes[0] = 0;
|
|
cbSize = 3 * sizeof(DWORD);
|
|
}
|
|
|
|
LPDIRECTXFILEDATA pMatListObj;
|
|
|
|
pSave->CreateDataObject(TID_D3DRMMeshMaterialList,
|
|
NULL,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
&pMatListObj);
|
|
|
|
FaceMaterial *pMat;
|
|
for (pMat = lMat.First(); pMat; pMat = pMat->pNext)
|
|
{
|
|
CreateMaterialObject(pMatListObj,
|
|
pMat);
|
|
}
|
|
|
|
pMeshObj->AddDataObject(pMatListObj);
|
|
pMatListObj->Release();
|
|
delete[] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateMaterialObject(LPDIRECTXFILEDATA pMatListObj,
|
|
FaceMaterial *pMat)
|
|
{
|
|
BaseMaterial data;
|
|
|
|
data.faceColor.r = MyD3DRMColorGetRed(pMat->faceColor);
|
|
data.faceColor.g = MyD3DRMColorGetGreen(pMat->faceColor);
|
|
data.faceColor.b = MyD3DRMColorGetBlue(pMat->faceColor);
|
|
data.faceColor.a = MyD3DRMColorGetAlpha(pMat->faceColor);
|
|
|
|
data.power = pMat->pMaterial->GetPower();
|
|
|
|
pMat->pMaterial->GetSpecular(&data.specularColor.r,
|
|
&data.specularColor.g,
|
|
&data.specularColor.b);
|
|
|
|
pMat->pMaterial->GetEmissive(&data.emissiveColor.r,
|
|
&data.emissiveColor.g,
|
|
&data.emissiveColor.b);
|
|
|
|
LPDIRECTXFILEDATA pMaterialObj;
|
|
|
|
pSave->CreateDataObject(TID_D3DRMMaterial,
|
|
NULL,
|
|
NULL,
|
|
sizeof(BaseMaterial),
|
|
&data,
|
|
&pMaterialObj);
|
|
|
|
if (pMat->pTexture)
|
|
{
|
|
IDirectXFileData *pTextureObj;
|
|
|
|
DWORD dwSize;
|
|
pMat->pTexture->GetName(&dwSize, NULL);
|
|
|
|
if (dwSize)
|
|
{
|
|
LPSTR szName = new char[dwSize];
|
|
pMat->pTexture->GetName(&dwSize, szName);
|
|
|
|
pSave->CreateDataObject(TID_D3DRMTextureFilename,
|
|
NULL,
|
|
NULL,
|
|
sizeof(LPSTR),
|
|
&szName,
|
|
&pTextureObj);
|
|
|
|
pMaterialObj->AddDataObject(pTextureObj);
|
|
pTextureObj->Release();
|
|
lNames.Add(szName);
|
|
}
|
|
}
|
|
|
|
pMatListObj->AddDataObject(pMaterialObj);
|
|
pMaterialObj->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateTextureWrapsObject(LPDIRECTXFILEDATA pMeshObj,
|
|
LPDIRECT3DRMFACEARRAY pFaceArray)
|
|
{
|
|
DWORD cbSize, cFaces;
|
|
FaceWraps *data;
|
|
|
|
cFaces = pFaceArray->GetSize();
|
|
cbSize = sizeof(DWORD) + cFaces * sizeof(Boolean2d);
|
|
|
|
data = (FaceWraps *) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
|
|
data->cFaces = cFaces;
|
|
Boolean2d *pWrap = data->faceWraps;
|
|
|
|
for (DWORD i = 0; i < cFaces; i++, pWrap++)
|
|
{
|
|
LPDIRECT3DRMFACE pFace;
|
|
pFaceArray->GetElement(i, &pFace);
|
|
pFace->GetTextureTopology(&pWrap->u, &pWrap->v);
|
|
pFace->Release();
|
|
}
|
|
|
|
LPDIRECTXFILEDATA pTextureWrapsObj;
|
|
|
|
pSave->CreateDataObject(TID_D3DRMMeshFaceWraps,
|
|
NULL,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
&pTextureWrapsObj);
|
|
|
|
pMeshObj->AddDataObject(pTextureWrapsObj);
|
|
pTextureWrapsObj->Release();
|
|
delete[] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Saver::CreateTextureCoordsObject(LPDIRECTXFILEDATA pMeshObj,
|
|
DWORD cVertices,
|
|
LPDIRECT3DRMMESHBUILDER3 pMeshBuilder)
|
|
{
|
|
DWORD cbSize;
|
|
TextureCoords *data;
|
|
|
|
cbSize = sizeof(DWORD) + cVertices * sizeof(Coords2d);
|
|
|
|
data = (TextureCoords *) new BYTE[cbSize];
|
|
if (!data) return E_OUTOFMEMORY;
|
|
|
|
data->cVertices = cVertices;
|
|
Coords2d *pCoords = data->textureCoords;
|
|
|
|
for (DWORD i = 0; i < cVertices; i++, pCoords++)
|
|
{
|
|
pMeshBuilder->GetTextureCoordinates(i, &pCoords->u, &pCoords->v);
|
|
}
|
|
|
|
LPDIRECTXFILEDATA pTexCoordsObj;
|
|
|
|
pSave->CreateDataObject(TID_D3DRMMeshTextureCoords,
|
|
NULL,
|
|
NULL,
|
|
cbSize,
|
|
data,
|
|
&pTexCoordsObj);
|
|
|
|
pMeshObj->AddDataObject(pTexCoordsObj);
|
|
pTexCoordsObj->Release();
|
|
delete[] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
FaceMaterialList::FaceMaterialList()
|
|
: cElements(0), pFirst(NULL)
|
|
{
|
|
}
|
|
|
|
FaceMaterialList::~FaceMaterialList()
|
|
{
|
|
FaceMaterial *pMat = pFirst;
|
|
while (pMat)
|
|
{
|
|
FaceMaterial *pNext = pMat->pNext;
|
|
pMat->pMaterial->Release();
|
|
if (pMat->pTexture) pMat->pTexture->Release();
|
|
delete pMat;
|
|
pMat = pNext;
|
|
}
|
|
}
|
|
|
|
DWORD FaceMaterialList::Find(D3DCOLOR faceColor,
|
|
LPDIRECT3DRMMATERIAL pMaterial,
|
|
LPDIRECT3DRMTEXTURE pTexture)
|
|
{
|
|
FaceMaterial *pTmp = pFirst;
|
|
FaceMaterial **ppNew = &pFirst;
|
|
|
|
for (DWORD i = 0; pTmp; i++, pTmp = pTmp->pNext)
|
|
{
|
|
if (pTmp->faceColor == faceColor &&
|
|
pTmp->pMaterial == pMaterial &&
|
|
pTmp->pTexture == pTexture)
|
|
return i;
|
|
|
|
if (!pTmp->pNext)
|
|
ppNew = &pTmp->pNext;
|
|
}
|
|
|
|
FaceMaterial *pNew = new FaceMaterial;
|
|
if (!pNew) return 0;
|
|
|
|
pNew->faceColor = faceColor;
|
|
pNew->pMaterial = pMaterial;
|
|
pNew->pTexture = pTexture;
|
|
pNew->pNext = NULL;
|
|
pMaterial->AddRef();
|
|
if (pTexture) pTexture->AddRef();
|
|
|
|
*ppNew = pNew;
|
|
cElements++;
|
|
return i;
|
|
}
|
|
|
|
NameList::NameList()
|
|
: pFirst(NULL),
|
|
ppLast(NULL)
|
|
{
|
|
}
|
|
|
|
NameList::~NameList()
|
|
{
|
|
NameEntry *pEntry = pFirst;
|
|
|
|
while (pEntry)
|
|
{
|
|
NameEntry *pNext = pEntry->pNext;
|
|
delete[] pEntry->pName;
|
|
delete pEntry;
|
|
pEntry = pNext;
|
|
}
|
|
}
|
|
|
|
void NameList::Add(LPSTR pName)
|
|
{
|
|
NameEntry *pNew = new NameEntry;
|
|
if (!pNew) return;
|
|
|
|
pNew->pName = pName;
|
|
pNew->pNext = NULL;
|
|
|
|
if (ppLast)
|
|
*ppLast = pNew;
|
|
else
|
|
pFirst = pNew;
|
|
|
|
ppLast = &pNew->pNext;
|
|
}
|