Error Rendering Materials and Texture

Started by
13 comments, last by Tiege 12 years, 8 months ago
So I basically have a program to view a model which i basically just copied to learn from samples. An Unhandled exception error occurs when the program gets to the lines

// Set the material and texture for this subset
d3dDevice->SetMaterial(&meshMaterials);
d3dDevice->SetTexture(0,meshTextures);


If I comment them both out the program works perfect and renders the model without textures. On the debugging mode it says numMaterials = 1. Here's my code:



#include <windows.h>
#include <d3dx9.h>
#include <MMSystem.h>


//globals
LPDIRECT3D9 d3dObject=NULL;
LPDIRECT3DDEVICE9 d3dDevice=NULL;

//mesh loading variables
DWORD numMaterials = 0L;
LPD3DXMESH mesh = NULL;
D3DMATERIAL9* meshMaterials = NULL;
LPDIRECT3DTEXTURE9* meshTextures = NULL;

HRESULT InitD3D( HWND hWnd )
{
//create D3D Object
if( NULL == ( d3dObject=Direct3DCreate9(D3D_SDK_VERSION) ) )
return E_FAIL;

//setup structure for parameters for D3D Device
D3DPRESENT_PARAMETERS presParams;
ZeroMemory(&presParams,sizeof(presParams));
presParams.Windowed=TRUE;
presParams.SwapEffect=D3DSWAPEFFECT_DISCARD;
presParams.BackBufferFormat=D3DFMT_UNKNOWN;
presParams.PresentationInterval=D3DPRESENT_INTERVAL_ONE;


//create D3D Device
if( FAILED (d3dObject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &presParams, &d3dDevice) ) )
{
return E_FAIL;
}
// Turn on ambient lighting
d3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );


return S_OK;
}

HRESULT InitMesh()
{
LPD3DXBUFFER materialBuffer;

// Load the mesh from the specified file
if( FAILED( D3DXLoadMeshFromX( "C:\\Program Files\\Microsoft DirectX SDK\\Samples\\Media\\Tiger\\tiger.x", D3DXMESH_SYSTEMMEM,
d3dDevice, NULL,
&materialBuffer, NULL, &numMaterials,
&mesh ) ) )
{
// If model is not in current folder, try parent folder
if( FAILED( D3DXLoadMeshFromX( "..\\tiger.x", D3DXMESH_SYSTEMMEM,
d3dDevice, NULL,
&materialBuffer, NULL, &numMaterials,
&mesh ) ) )
{
MessageBox( NULL, "Could not find tiger.x", "Meshes.exe", MB_OK );
return E_FAIL;
}
}

D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer();

D3DMATERIAL9 *meshMaterials = new D3DMATERIAL9[numMaterials];
LPDIRECT3DTEXTURE9 *meshTextures = new LPDIRECT3DTEXTURE9[numMaterials];

for (DWORD i=0; i<numMaterials; i++)
{

// Copy the material
meshMaterials = d3dxMaterials.MatD3D;

// Set the ambient color for the material (D3DX does not do this)
meshMaterials.Ambient = meshMaterials.Diffuse;

// Create the texture if it exists - it may not
meshTextures = NULL;
if (d3dxMaterials.pTextureFilename)
D3DXCreateTextureFromFile(d3dDevice, d3dxMaterials.pTextureFilename, &meshTextures);

}

materialBuffer->Release();

return S_OK;
}

VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIXA16 matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime() / 1000.0f );
d3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
d3dDevice->SetTransform( D3DTS_VIEW, &matView );

// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
d3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

void Render()
{
//clear buffer
d3dDevice->Clear(0,NULL,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,40,100),1.0f,0);

//begin scene
d3dDevice->BeginScene();

SetupMatrices();

//draw mesh
for (DWORD i=0; i<numMaterials; i++)
{
// Set the material and texture for this subset
d3dDevice->SetMaterial(&meshMaterials);
d3dDevice->SetTexture(0,meshTextures);

// Draw the mesh subset
mesh->DrawSubset( i );
}
//end scene
d3dDevice->EndScene();

//present screen
d3dDevice->Present( NULL, NULL, NULL, NULL );
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
//case WM_COMMAND:
// handle menu selections etc.
//break;
//case WM_PAINT:
// draw our window - note: you must paint something here or not trap it!
//break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
// We do not want to handle this message so pass back to Windows
// to handle it in a default way
return DefWindowProc(hWnd, message, wParam, lParam);
}

return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc= (WNDPROC)WndProc;
wcex.cbClsExtra= 0;
wcex.cbWndExtra= 0;
wcex.hInstance= hInstance;
wcex.hIcon= 0;
wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName= 0;
wcex.lpszClassName= "MyWindowClass";
wcex.hIconSm= 0;

// Now we can go ahead and register our new window class
RegisterClassEx(&wcex);

HWND hWnd = CreateWindow("MyWindowClass", "Poop", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

//call initD3D
InitD3D(hWnd);

InitMesh();

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

//enter main loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

Render();
}

return (int)msg.wParam;
}


Any ideas?
Advertisement
First off, you seem to have both a global and a local declaration for meshMaterials and meshTextures:

global:

[color=#1C2837][size=2][color=#880000]//mesh loading variables[color=#000000]
DWORD numMaterials [color=#666600]=[color=#000000] [color=#006666]0L[color=#666600];[color=#000000]
LPD3DXMESH mesh [color=#666600]=[color=#000000] NULL[color=#666600];[color=#000000]
D3DMATERIAL9[color=#666600]*[color=#000000] meshMaterials [color=#666600]=[color=#000000] NULL[color=#666600];[color=#000000]
LPDIRECT3DTEXTURE9[color=#666600]*[color=#000000] meshTextures [color=#666600]=[color=#000000] NULL[color=#666600];

local:

[color=#1C2837][size=2][color=#000000] D3DMATERIAL9 [color=#666600]*[color=#000000]meshMaterials [color=#666600]=[color=#000000] [color=#000088]new[color=#000000] D3DMATERIAL9[color=#666600][[color=#000000]numMaterials[color=#666600]];[color=#000000]
LPDIRECT3DTEXTURE9 [color=#666600]*[color=#000000]meshTextures [color=#666600]=[color=#000000] [color=#000088]new[color=#000000] LPDIRECT3DTEXTURE9[color=#666600][[color=#000000]numMaterials[color=#666600]];
A quick solution would be to keep the global declarations, and in InitMesh() just have:

[color=#1C2837][size=2][color=#000000]meshMaterials [color=#666600]=[color=#000000] [color=#000088]new[color=#000000] D3DMATERIAL9[color=#666600][[color=#000000]numMaterials[color=#666600]];[color=#000000]
[color=#000000]meshTextures [color=#666600]=[color=#000000] [color=#000088]new[color=#000000] LPDIRECT3DTEXTURE9[color=#666600][[color=#000000]numMaterials[color=#666600]];
[color=#1C2837][size=2][color=#666600]

[color="#666600"][color=#000000]

Since this is meant for you to learn from samples, it should be okay. But generally, you want to avoid globals. One way to do that is to have a mesh class where meshMaterials and meshTextures are member variables and InitMesh() is a member function.

Double Edit!!! Ok so I actually was dumb and didnt make the appropriate fixes. So now i think it loads the material but not the texture. My model went from black nothingness tiger to a grey (material im assuming) tiger. Still missing the tiger color texture. Does this mean setmaterial works but not settexture?

Edit: I actually reread what you suggested. Didn't get any errors but it still didn't load the texture. I'm using the tiger model from the DirectX SDK for testing this. Do I need to link or include a texture file to make this work or should the data already be in the tiger.x?
The globals are just to declare them and initialize them as NULL. When I load a mesh they should be filled in with whatever the file has. When I comment out the globals and just keep the the local it says unidentified variables and if I get rid of the local and keep the global how will the program know what texture and material to render?
Another suggestion... check the return value of DirectX function calls.. for example [font=CourierNew, monospace][size=2]D3DXCreateTextureFromFile(). If it's not D3D_OK, check the error. are you getting a valid pointer in [/font][color=#1C2837][font=CourierNew, monospace][size=2][color=#000000]meshTextures[color=#666600][[color=#000000]0[color=#666600]] ?[/font]

Another suggestion... check the return value of DirectX function calls.. for example [font="CourierNew, monospace"]D3DXCreateTextureFromFile(). If it's not D3D_OK, check the error. are you getting a valid pointer in [/font][color="#1C2837"][font="CourierNew, monospace"][color="#000000"]meshTextures[color="#666600"][[color="#000000"]0[color="#666600"]] ?[/font]


I believe so. When it gets redfined by
Well I just had a friend send me simple models he made in blender. He sent an untextured cube which loaded and then he textured it and it worked! So here's a kicker, Cube 1 untextured worked. Cube 2 textured as red worked. Cube 3 with a "Wood" textured failed to load. Is there something special I have to do for custom textures like that? The xfile cant take care of it?




I believe so. For some reason in the tutorial it has meshTexture = NULL; before it creatures texture from file. No idea why. But when meshtexture[numMaterials] is set numMatierlas does have a value of 1.

I'm not so good at checking return values of built in function calls. Other than using an IF statement I still don't really know what to make the program do if it returns bad
Try setting a breakpoint and inspect the values of variables... specifically the value of meshTextures (for all i's). If one of them is NULL (0x00000000), then it wasn't able to load it. Usually this is because the file was not found. Sometimes meshes will reference texture files in an absolute path like "C:\my_game\my_textures\texture1.jpg". Check the value of [color=#1C2837][font=CourierNew, monospace][size=2][color=#000000]d3dxMaterials[color=#666600][[color=#000000]i[color=#666600]].[color=#000000]pTextureFilename [/font]to see what the file's path is.

Try setting a breakpoint and inspect the values of variables... specifically the value of meshTextures (for all i's). If one of them is NULL (0x00000000), then it wasn't able to load it. Usually this is because the file was not found. Sometimes meshes will reference texture files in an absolute path like "C:\my_game\my_textures\texture1.jpg". Check the value of [color="#1C2837"][font="CourierNew, monospace"][color="#000000"]d3dxMaterials[color="#666600"][[color="#000000"]i[color="#666600"]].[color="#000000"]pTextureFilename [/font]to see what the file's path is.


The [color="#1C2837"][font="CourierNew, monospace"][color="#000000"]d3dxMaterials[color="#666600"][[color="#000000"]i[color="#666600"]].[color="#000000"]pTextureFilename value for the tiger.x model sample is indeed tiger.bmp[/font]
[color="#1C2837"][font="CourierNew, monospace"] [/font]
[font="CourierNew, monospace"]it stores the value of the texture in the &meshTextures but for some reason when it gets to the DrawSubet(i) that value in meshTextures becomes 0x00000. I can't figure out why[/font]

The [color="#1C2837"][font="CourierNew, monospace"][color="#000000"]d3dxMaterials[color="#666600"][[color="#000000"]i[color="#666600"]].[color="#000000"]pTextureFilename value for the tiger.x model sample is indeed tiger.bmp[/font]


So then, does it load the texture correctly? What is the value of meshTextures[0]? Is it a valid pointer, or is it NULL? What is the return value of D3DXCreateTextureFromFile()? You can check it like this:



HRESULT hr = D3DXCreateTextureFromFile(......);

if (hr != D3D_OK)
{
OutputDebugString(DXGetErrorString(hr));
OutputDebugString(DXGetErrorDescription(hr));
}

This topic is closed to new replies.

Advertisement