My mesh appears translucent when I use lighting. I can see the polygons nearest to the camera, but I can also see through them to the ones further back. I started with a mesh with do normals or adjacancy information so I added a compute adjacancy and compure normals thing that was suggested. Computing normals gave some sense of light and shade but didn't lelp with the unwanted translucency. I've tried changing the z-buffer settings but the changes I tried seem to prevent it from being displayed properly or at all. Perhaps I'm missing something.:
I tried using diffuse like this and it at least made MeshView able to view the file that gets saved properly:
Leaving the culling on seemed to help but only at some angles. Is there anything else I could try?
The whole file:
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dxof.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
#include "AMF_Window.h"
#include <mmsystem.h>
#include <d3dx9.h>
/******************************************************************************************/
/* DIRECTX STUFF */
/******************************************************************************************/
struct SR_POLYGON {
WORD v1, v2, v3, unknown;
VOID* textureData; // TEXTUREDATA*
};
struct SR_EX_POLYGON {
WORD v1, v2, v3;
};
struct SR_SEGMENT {
DWORD unknown1;
WORD unknown2, unknown3;
WORD vFirst, vLast;
signed short x, y, z;
WORD parentID;
VOID* unknown5;
};
struct SR_EX_SEGMENT {
WORD vFirst, vLast;
float x, y, z;
SR_EX_SEGMENT* parent;
};
struct SR_VERTEX {
signed short x, y, z;
WORD normalID;
};
struct SR_EX_VERTEX {
D3DXVECTOR3 pos;
D3DXVECTOR3 norm;
DWORD colour;
};
#define D3DFVF_SR_EX_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL)
LPDIRECT3D9 g_pD3D = NULL; // D3D Object
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // D3D Device
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // D3D Vertex Buffer
LPD3DXMESH g_pD3DXMesh = NULL; // D3D X-Mesh
D3DXVECTOR3 centrePos = D3DXVECTOR3(0,0,0);
D3DXVECTOR3 cameraPos = D3DXVECTOR3(0,0,0);
int modelRotX = 0;
int modelRotY = 0;
float radius = 0;
bool fullscreen = false;
bool InitD3D (HWND hWnd);
void Cleanup ();
void Render ();
void SetupMatrices();
void SetupLights();
bool InitD3D (HWND hWnd) {
// Create the D3D Object.
if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) return false;
// Set the presentation paramaters.
D3DPRESENT_PARAMETERS D3Dpp = {0};
// Get the display mode
D3DDISPLAYMODE D3Ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &D3Ddm))) return false;
if(!fullscreen) {
D3Dpp.Windowed = TRUE;
D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
D3Dpp.BackBufferWidth = 0;
D3Dpp.BackBufferHeight = 0;
D3Dpp.BackBufferFormat = D3DFMT_UNKNOWN; //D3Ddm.Format;
// D3Dpp.EnableAutoDepthStencil = TRUE;
// D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else {
// I'm not using fullscreen mode this time.
D3Dpp.Windowed = FALSE;
D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
RECT deskTopRect;
GetClientRect(GetDesktopWindow(), &deskTopRect);
D3Dpp.BackBufferWidth = deskTopRect.right-deskTopRect.left;
D3Dpp.BackBufferHeight = deskTopRect.bottom-deskTopRect.top;
D3Dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
}
// Create the Direct3D device.
if (FAILED(
g_pD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, // Can use D3DCREATE_HARDWARE_VERTEXPROCESSING instead
&D3Dpp,
&g_pD3DDevice
)
)) return false;
// Turn off culling, so we see the front and back of the triangle
// OK, the culling makes a difference.
// g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// Setup lighting
SetupLights();
// Turn on the zbuffer
g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
return true;
}
void Cleanup() {
if (g_pD3DXMesh != NULL)
g_pD3DXMesh->Release(); // Release the mesh.
if (g_pVB != NULL)
g_pVB->Release(); // Release the vertex buffer.
if (g_pD3DDevice != NULL)
g_pD3DDevice->Release(); // Release the D3D device.
if (g_pD3D != NULL)
g_pD3D->Release(); // Release the D3D object.
}
void SetupMatrices() {
D3DXMATRIXA16 matWorld, matWorldRotX, matWorldRotY;
// Rotate once per second.
//DWORD dwTime = timeGetTime() % 10000;
//float fAngle = dwTime * (2.0f * D3DX_PI) / 10000.0f;
//D3DXMatrixRotationY(&matWorldRot, fAngle);
// Rotation set by user
modelRotX = modelRotX % 100;
float angle = modelRotX * (2.0f * D3DX_PI) / 100.0f;
D3DXMatrixRotationZ(&matWorldRotX, angle);
modelRotY = modelRotY % 100;
angle = modelRotY * (2.0f * D3DX_PI) / 100.0f;
D3DXMatrixRotationY(&matWorldRotY, angle);
D3DXMatrixIdentity(&matWorld);
matWorld._11 /= (2*radius);
matWorld._22 /= (2*radius);
matWorld._33 /= (2*radius);
matWorld._41 -= (centrePos.x / (2*radius));
matWorld._42 -= (centrePos.y / (2*radius));
matWorld._43 -= (centrePos.z / (2*radius));
D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldRotX);
D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldRotY);
g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
// Create the view matrix.
D3DXMATRIXA16 matView;
// The direction the camera is facing.
D3DXVECTOR3 vLookatPt ( 0.0f, 0.0f, 0.0f);
// The y axis represents up.
D3DXVECTOR3 vUpVec ( 0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&matView, &cameraPos, &vLookatPt, &vUpVec);
// Transform the view matrix.
g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 0.0f, 100.0f);
g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
void SetupLights() {
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
g_pD3DDevice->SetRenderState(D3DRS_AMBIENT, 0xFF808080);
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl, sizeof(D3DMATERIAL9));
mtrl.Diffuse.r = mtrl.Ambient.r = 0.5f;
mtrl.Diffuse.g = mtrl.Ambient.g = 0.5f;
mtrl.Diffuse.b = mtrl.Ambient.b = 0.5f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
g_pD3DDevice->SetMaterial(&mtrl);
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(D3DLIGHT9));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Range = 1000.0f;
light.Diffuse.r = 0.5f;
light.Diffuse.g = 0.5f;
light.Diffuse.b = 0.5f;
light.Diffuse.a = 1.0f;
D3DXVECTOR3 vecDir = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &vecDir);
g_pD3DDevice->SetLight(0, &light);
g_pD3DDevice->LightEnable(0, TRUE);
}
void Render() {
if (g_pD3DDevice == NULL) return;
// Clear the backbuffer to black
g_pD3DDevice->Clear(
0,
NULL,
D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0),
1.0f,
0
);
// Begin the scene
if(SUCCEEDED(g_pD3DDevice->BeginScene())) {
SetupMatrices();
if (g_pD3DXMesh != NULL) g_pD3DXMesh->DrawSubset(0);
g_pD3DDevice->EndScene();
}
g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}
/******************************************************************************************/
/* WINDOWS STUFF */
/******************************************************************************************/
enum {
ID_DX_VIEW=1, ID_SUBWIN,
ID_LOAD, ID_MLOAD,
ID_SAVE, ID_MSAVE,
ID_MWIRE, ID_MSOLID, ID_MRESETVIEW,
ID_MEXIT
};
HWND subWin, dxView, loadButton, saveButton;
HMENU hMenu, hFileSubMenu, hViewSubMenu;
void CreateSubWindows();
bool LoadSR1Object();
bool SaveSR1Object();
int WINAPI WinMain (HINSTANCE hInst,HINSTANCE hPrev,LPSTR line,int CmdShow) {
SetUpWindow("SR1-ModelEx", hInst);
ShowWindow(g_hWnd, SW_SHOW);
CreateSubWindows();
MSG msg ={0};
if(InitD3D(dxView)) {
while(msg.message != WM_QUIT) {
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Render();
}
}
Cleanup();
return (int) msg.wParam;
}
LRESULT WINAPI MsgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) {
switch(msg) {
case WM_DESTROY: {
PostQuitMessage(NULL);
break;
}
case WM_COMMAND: {
if (wParam==ID_MLOAD)
LoadSR1Object();
if (wParam==ID_MSAVE)
SaveSR1Object();
if (wParam==ID_MWIRE)
g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
if (wParam==ID_MSOLID)
g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
if (wParam==ID_MRESETVIEW) {
cameraPos.x = -1.5f;
modelRotX = 0;
modelRotY = 0;
g_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}
if (wParam==ID_MEXIT) PostQuitMessage(NULL);
switch(HIWORD(wParam)) {
case BN_CLICKED:
if ((LOWORD(wParam))==ID_LOAD) LoadSR1Object();
if ((LOWORD(wParam))==ID_SAVE) SaveSR1Object();
break;
}
break;
}
case WM_KEYDOWN:
switch (wParam) {
case VK_ADD:
case VK_OEM_PLUS:
cameraPos.x+=0.10f;
break;
case VK_SUBTRACT:
case VK_OEM_MINUS:
cameraPos.x-=0.10f;
break;
case VK_LEFT:
case VK_NUMPAD4:
modelRotY--;
break;
case VK_RIGHT:
case VK_NUMPAD6:
modelRotY++;
break;
case VK_UP:
case VK_NUMPAD8:
modelRotX++;
break;
case VK_DOWN:
case VK_NUMPAD2:
modelRotX--;
break;
}
break;
case WM_SIZE: {
RECT rcClient;
GetClientRect(g_hWnd, &rcClient);
LPRECT rcParent = (LPRECT)(LPARAM)&rcClient;
MoveWindow(
subWin,
0,
0,
rcParent->right,
rcParent->bottom,
TRUE
);
UpdateWindow(subWin);
break;
}
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
void CreateSubWindows() {
// Main Menu
hMenu = CreateMenu();
hFileSubMenu = CreatePopupMenu();
AppendMenu(hFileSubMenu, MF_STRING, ID_MLOAD, "Load");
AppendMenu(hFileSubMenu, MF_STRING, ID_MSAVE, "Save");
AppendMenu(hFileSubMenu, MF_STRING, ID_MEXIT, "Exit");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hFileSubMenu, "File");
hViewSubMenu = CreatePopupMenu();
AppendMenu(hViewSubMenu, MF_STRING, ID_MSOLID, "Solid");
AppendMenu(hViewSubMenu, MF_STRING, ID_MWIRE, "Wireframe");
AppendMenu(hViewSubMenu, MF_STRING, ID_MRESETVIEW, "Reset View");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hViewSubMenu, "View");
SetMenu(g_hWnd, hMenu);
// Model view window
subWin = CreateWindowEx(
WS_EX_CLIENTEDGE, "Static", "", WS_VISIBLE | WS_CHILD | WS_MAXIMIZE,
50,25,300,300, g_hWnd, (HMENU) ID_SUBWIN, g_hInst, 0
);
ShowWindow(subWin, SW_SHOW);
dxView = CreateWindowEx(
WS_EX_CLIENTEDGE, "Static", "", WS_VISIBLE | WS_CHILD,
50,25,300,300, subWin, (HMENU) ID_DX_VIEW, g_hInst, 0
);
ShowWindow(dxView, SW_SHOW);
// Load button
/*loadButton = CreateWindowEx(
0, "Button", "Load", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,
10,10,50,20, g_hWnd, (HMENU) ID_LOAD, g_hInst, 0
);
SendDlgItemMessage(g_hWnd, ID_LOAD ,WM_SETFONT, (WPARAM) g_hFont, FALSE);
ShowWindow(loadButton, SW_SHOW);*/
// Save button
/*saveButton = CreateWindowEx(
0, "Button", "Save", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,
10,30,50,20, g_hWnd, (HMENU) ID_SAVE, g_hInst, 0
);
SendDlgItemMessage(g_hWnd, ID_SAVE ,WM_SETFONT, (WPARAM) g_hFont, FALSE);
ShowWindow(saveButton, SW_SHOW);*/
return;
}
bool LoadSR1Object() {
OPENFILENAME ofn = {0};
char fileName[MAX_PATH] = "";
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = g_hWnd;
ofn.lpstrFilter = "Soul Reaver Object Files (*.SRObj)\0*.SRObj\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "SRObj";
if(!GetOpenFileName(&ofn)) {
return false;
}
// Open the file
HANDLE SRObj = CreateFile(
fileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, NULL, NULL
);
if (!SRObj) {
MessageBox(g_hWnd, "Couldn't open the file", "Error", MB_ICONERROR | MB_OK);
return false;
}
// Load File into Memory
DWORD fileSize = 0, bytesRead;
fileSize = GetFileSize(SRObj, NULL);
VOID* SRObjData = malloc(fileSize);
if (!SRObjData) {
MessageBox(g_hWnd, "Couldn't allocate memory", "Error", MB_ICONERROR | MB_OK);
return false;
}
if (!ReadFile(SRObj, SRObjData, fileSize, &bytesRead, NULL)) {
MessageBox(g_hWnd, "Couldn't read the file", "Error", MB_ICONERROR | MB_OK);
delete SRObjData;
CloseHandle(SRObj);
return false;
}
CloseHandle(SRObj);
// Build map of file
DWORD loadPoint = (((*(DWORD*) SRObjData)>>9)<<11)+0x00000800;
VOID* dataStart = (BYTE*) SRObjData+loadPoint;
VOID* modelData = (BYTE*) dataStart+*(DWORD*)((BYTE*)dataStart+*((BYTE*)dataStart+0x0000000C));
DWORD vertexCount = *(DWORD*) modelData;
SR_VERTEX* vertices = (SR_VERTEX*)((BYTE*)dataStart+*(DWORD*)((BYTE*)modelData+0x00000004));
DWORD polygonCount = *(DWORD*) ((BYTE*)modelData+0x00000010);
SR_POLYGON* polygons = (SR_POLYGON*)((BYTE*)dataStart+*(DWORD*)((BYTE*)modelData+0x00000014));
DWORD segmentCount = *(DWORD*) ((BYTE*)modelData+0x00000018);
SR_SEGMENT* segments = (SR_SEGMENT*)((BYTE*)dataStart+*(DWORD*)((BYTE*)modelData+0x0000001C));
// Extract the vertices
SR_EX_VERTEX* exVertices = new SR_EX_VERTEX[vertexCount];
for (DWORD v=0; v<vertexCount; v++) {
exVertices[v].pos.x = (float) vertices[v].y;
exVertices[v].pos.y = (float) vertices[v].z;
exVertices[v].pos.z = (float) vertices[v].x;
exVertices[v].colour = 0xFF0000FF;
exVertices[v].norm = D3DXVECTOR3(0,0,0);
}
// Extract the segment data
SR_EX_SEGMENT* exSegments = new SR_EX_SEGMENT[segmentCount];
SR_EX_SEGMENT* currentSegment = NULL;
D3DXVECTOR3 currentTrans = D3DXVECTOR3(0,0,0);
for (DWORD s=0; s<segmentCount; s++) {
exSegments.x = (<span class="cpp-keyword">float</span>) segments.y;
exSegments.y = (<span class="cpp-keyword">float</span>) segments.z;
exSegments.z = (<span class="cpp-keyword">float</span>) segments.x;
exSegments.vFirst = segments.vFirst;
exSegments.vLast = segments.vLast;
<span class="cpp-keyword">if</span> (segments.parentID==0xFFFF) exSegments.parent = NULL;
<span class="cpp-keyword">else</span> exSegments.parent = &exSegments[segments.parentID];
}
<span class="cpp-keyword">for</span> (DWORD s=<span class="cpp-number">0</span>; s<segmentCount; s++) {
ZeroMemory(&currentTrans, <span class="cpp-keyword">sizeof</span>(currentTrans));
currentSegment = &exSegments;
<span class="cpp-keyword">while</span> (currentSegment) {
currentTrans.x += currentSegment->x;
currentTrans.y += currentSegment->y;
currentTrans.z += currentSegment->z;
currentSegment = currentSegment->parent;
}
<span class="cpp-keyword">if</span> ((exSegments.vFirst!=0xFFFF) && (exSegments.vLast!=0xFFFF)) {
<span class="cpp-keyword">for</span> (WORD v=exSegments.vFirst; v<=exSegments.vLast; v++) {
exVertices[v].pos.x += currentTrans.x;
exVertices[v].pos.y += currentTrans.y;
exVertices[v].pos.z += currentTrans.z;
}
}
}
<span class="cpp-comment">// Extract the polygons</span>
SR_EX_POLYGON* exPolygons = <span class="cpp-keyword">new</span> SR_EX_POLYGON[polygonCount];
<span class="cpp-keyword">for</span> (DWORD p=<span class="cpp-number">0</span>; p<polygonCount; p++) {
exPolygons<p>.v1 = polygons<p>.v1;
exPolygons<p>.v2 = polygons<p>.v2;
exPolygons<p>.v3 = polygons<p>.v3;
}
<span class="cpp-comment">// Do the scaling</span>
<span class="cpp-keyword">for</span> (DWORD v=<span class="cpp-number">0</span>; v<vertexCount; v++) {
exVertices[v].pos.x /= <span class="cpp-number">100</span>.0f;
exVertices[v].pos.y /= <span class="cpp-number">100</span>.0f;
exVertices[v].pos.z /= <span class="cpp-number">100</span>.0f;
}
D3DXComputeBoundingSphere(
&(*exVertices).pos,
vertexCount,
<span class="cpp-keyword">sizeof</span>(SR_EX_VERTEX),
&centrePos,
&radius
);
<span class="cpp-comment">// Get rid of any existing mesh</span>
<span class="cpp-keyword">if</span> (g_pD3DXMesh != NULL)
g_pD3DXMesh->Release();
<span class="cpp-comment">// Create Mesh</span>
<span class="cpp-keyword">if</span>(FAILED(
D3DXCreateMeshFVF(
polygonCount,
vertexCount,
<span class="cpp-number">0</span>,
D3DFVF_SR_EX_VERTEX,
g_pD3DDevice,
&g_pD3DXMesh
)
)) {
MessageBox(g_hWnd,
<span class="cpp-literal">"Doesn't work!"</span>,
<span class="cpp-literal">"Error"</span>, MB_ICONERROR | MB_OK | MB_SETFOREGROUND
);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
<span class="cpp-comment">// Do Vertex Buffer</span>
<span class="cpp-keyword">void</span>* outVertices = NULL;
<span class="cpp-keyword">if</span>(FAILED(g_pD3DXMesh->LockVertexBuffer(<span class="cpp-number">0</span>,(<span class="cpp-keyword">void</span>**)&outVertices))) {
MessageBox(g_hWnd,
<span class="cpp-literal">"Doesn't work!"</span>,
<span class="cpp-literal">"Error"</span>, MB_ICONERROR | MB_OK | MB_SETFOREGROUND
);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
memcpy(outVertices, exVertices, vertexCount*<span class="cpp-keyword">sizeof</span>(SR_EX_VERTEX));
g_pD3DXMesh->UnlockVertexBuffer();
<span class="cpp-comment">// Do Index Buffer</span>
<span class="cpp-keyword">void</span>* outPolygons = NULL;
<span class="cpp-keyword">if</span>(FAILED(g_pD3DXMesh->LockIndexBuffer(<span class="cpp-number">0</span>,(<span class="cpp-keyword">void</span>**)&outPolygons))) {
MessageBox(g_hWnd,
<span class="cpp-literal">"Doesn't work!"</span>,
<span class="cpp-literal">"Error"</span>, MB_ICONERROR | MB_OK | MB_SETFOREGROUND
);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
memcpy(outPolygons, exPolygons, polygonCount*<span class="cpp-keyword">sizeof</span>(SR_EX_POLYGON));
g_pD3DXMesh->UnlockIndexBuffer();
<span class="cpp-comment">// Compute normals</span>
DWORD *adjacency = <span class="cpp-keyword">new</span> DWORD[g_pD3DXMesh->GetNumFaces()*<span class="cpp-number">3</span>];
<span class="cpp-keyword">if</span>(FAILED(g_pD3DXMesh->GenerateAdjacency(<span class="cpp-number">0</span>.01f, adjacency))) {
<span class="cpp-keyword">delete</span> adjacency;
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
<span class="cpp-keyword">if</span>(FAILED(D3DXComputeNormals(g_pD3DXMesh, adjacency))) {
<span class="cpp-keyword">delete</span> adjacency;
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
<span class="cpp-keyword">delete</span> adjacency;
<span class="cpp-keyword">delete</span> exVertices;
<span class="cpp-keyword">delete</span> exSegments;
<span class="cpp-keyword">delete</span> exPolygons;
free(SRObjData);
cameraPos.x = -<span class="cpp-number">1</span>.5f;
modelRotX = <span class="cpp-number">0</span>;
modelRotY = <span class="cpp-number">0</span>;
<span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;
}
<span class="cpp-keyword">bool</span> SaveSR1Object() {
OPENFILENAME ofn = {<span class="cpp-number">0</span>};
<span class="cpp-keyword">char</span> fileName[MAX_PATH] = <span class="cpp-literal">""</span>;
ofn.lStructSize = <span class="cpp-keyword">sizeof</span>(ofn);
ofn.hwndOwner = g_hWnd;
ofn.lpstrFilter = <span class="cpp-literal">"DirectX Mesh Files (*.x)\0*.x\0All Files (*.*)\0*.*\0"</span>;
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
ofn.lpstrDefExt = <span class="cpp-literal">"SRObj"</span>;
<span class="cpp-keyword">if</span>(GetSaveFileName(&ofn)) {
<span class="cpp-comment">// D3DXF_FILEFORMAT_BINARY, D3DXF_FILEFORMAT_COMPRESSED</span>
D3DXSaveMeshToX(fileName, g_pD3DXMesh, NULL, NULL, NULL, <span class="cpp-number">0</span>, D3DXF_FILEFORMAT_TEXT);
<span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;
}
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
</pre></div><!–ENDSCRIPT–>