Unwanted translucency when lighting a mesh:

Started by
7 comments, last by CodeReaver 18 years, 2 months ago
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.:
D3Dpp.BackBufferFormat	= D3DFMT_UNKNOWN;  //D3Ddm.Format;
// D3Dpp.EnableAutoDepthStencil = TRUE;
// D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
I tried using diffuse like this and it at least made MeshView able to view the file that gets saved properly:
g_pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
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 = &amp;exSegments[segments.parentID];
	}
	<span class="cpp-keyword">for</span> (DWORD s=<span class="cpp-number">0</span>; s&lt;segmentCount; s++) {
		ZeroMemory(&amp;currentTrans, <span class="cpp-keyword">sizeof</span>(currentTrans));
		currentSegment = &amp;exSegments;
		<span class="cpp-keyword">while</span> (currentSegment) {
			currentTrans.x += currentSegment-&gt;x;
			currentTrans.y += currentSegment-&gt;y;
			currentTrans.z += currentSegment-&gt;z;
			currentSegment = currentSegment-&gt;parent;
		}
		<span class="cpp-keyword">if</span> ((exSegments.vFirst!=0xFFFF) &amp;&amp; (exSegments.vLast!=0xFFFF)) {
			<span class="cpp-keyword">for</span> (WORD v=exSegments.vFirst; v&lt;=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&lt;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&lt;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(
		&amp;(*exVertices).pos,
		vertexCount,
		<span class="cpp-keyword">sizeof</span>(SR_EX_VERTEX),
		&amp;centrePos,
		&amp;radius
	);

	<span class="cpp-comment">// Get rid of any existing mesh</span>
	<span class="cpp-keyword">if</span> (g_pD3DXMesh != NULL)        
    g_pD3DXMesh-&gt;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,
			&amp;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-&gt;LockVertexBuffer(<span class="cpp-number">0</span>,(<span class="cpp-keyword">void</span>**)&amp;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-&gt;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-&gt;LockIndexBuffer(<span class="cpp-number">0</span>,(<span class="cpp-keyword">void</span>**)&amp;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-&gt;UnlockIndexBuffer();

	<span class="cpp-comment">// Compute normals</span>
	DWORD *adjacency = <span class="cpp-keyword">new</span> DWORD[g_pD3DXMesh-&gt;GetNumFaces()*<span class="cpp-number">3</span>];
	<span class="cpp-keyword">if</span>(FAILED(g_pD3DXMesh-&gt;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(&amp;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–> 
Advertisement
First of all, the term translucent is a bit misleading here, I think. Translucency is the effect of a transparent object which appears solid (i.e. an ice cube for example). In your case, I rather think you mean the back faces are shown in front of the front faces sometimes.

You do turn on the Z-buffer but have you created one? It might help to uncomment these lines:
// D3Dpp.EnableAutoDepthStencil = TRUE;// D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;


Culling should also be turned on (usually counter-clockwise).

Illco
I commented them out because they didn't work properly. My image was reduced to a few horizontal streaks. I already said that leaving the culling switched on only helped at some angles, but not all.

Quote:The back faces are shown in front of the front faces sometimes.

That was what I meant though.
Quote:Original post by CodeReaver
My image was reduced to a few horizontal streaks.

That happens if you forget to clear your depth buffer :P
But of course that may not be your problem.
I'm using this:

// Clear the backbuffer to black	g_pD3DDevice->Clear(		0,		NULL,		D3DCLEAR_TARGET,		D3DCOLOR_XRGB(0,0,0),		1.0f,		0	);


Also, does culling take the normals into account? Like if some vertices are clockwise instead of anti-clockwise or vice-versa, would it use the normals to figure out which side to cull? If that doesn't work, would it need to be the indices in my mesh I need to change?
You aren't clearing the depth buffer on your Clear() call. Try replacing "D3DCLEAR_TARGET" with "D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER". This will clear the depth buffer values as well.
I'll try fixing the call to clear, switching culling on and uncommenting the z-buffer stuff then.
That should do the trick, I believe. I missed the clearing point.

Quote:
Also, does culling take the normals into account? Like if some vertices are clockwise instead of anti-clockwise or vice-versa, would it use the normals to figure out which side to cull? If that doesn't work, would it need to be the indices in my mesh I need to change?

No, culling is based solely on the winding order of the face -- i.e. the order in which the vertices are listed. With CCW-culling, counter clockwise faces are culled while clockwise faces are shown (order of the vertices when seen from the current viewpoint).

The normals are not involved; they're only used to light non-culled faced.

Illco
I tried that and none of it worked. Infact, it made things worse depending on whether I used hardware or software vertex processing. I did manage to fix the problem, though. The problem was here:

D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 0.0f, 100.0f);


I used replaced the 0.0f with 0.01f because I wanted my model to be able to get really close to the camera before it stops being drawn. I did look up the function on msdn, but it didn't really explain why using zero causes back faces to show through front faces.

I had to turn off culling as well, because one on the models had wings and other components that I think only had one side to them and I needed no culling to only see one side.

I added a zoom function and it seems that if I move the camera past the object, the thing flips around and heads the other way. I guess I'd either need to move the object instead of the camera or adjust the point the camera is aimed at. It's an exportor/viewer that I'm trying to build.

This topic is closed to new replies.

Advertisement