Sign in to follow this  

Error Rendering Materials and Texture

This topic is 2316 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

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

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:

[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[i] = d3dxMaterials[i].MatD3D;

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

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

}

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[i]);
d3dDevice->SetTexture(0,meshTextures[i]);

// 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;
}
[/code]

Any ideas?

Share this post


Link to post
Share on other sites
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][color=#000000]
DWORD numMaterials [/color][color=#666600]=[/color][color=#000000] [/color][color=#006666]0L[/color][color=#666600];[/color][color=#000000]
LPD3DXMESH mesh [/color][color=#666600]=[/color][color=#000000] NULL[/color][color=#666600];[/color][color=#000000]
D3DMATERIAL9[/color][color=#666600]*[/color][color=#000000] meshMaterials [/color][color=#666600]=[/color][color=#000000] NULL[/color][color=#666600];[/color][color=#000000]
LPDIRECT3DTEXTURE9[/color][color=#666600]*[/color][color=#000000] meshTextures [/color][color=#666600]=[/color][color=#000000] NULL[/color][color=#666600];[/color][/size][/color]

local:

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

Share this post


Link to post
Share on other sites
A quick solution would be to keep the global declarations, and in InitMesh() just have:

[color=#1C2837][size=2][color=#000000]meshMaterials [/color][color=#666600]=[/color][color=#000000] [/color][color=#000088]new[/color][color=#000000] D3DMATERIAL9[/color][color=#666600][[/color][color=#000000]numMaterials[/color][color=#666600]];[/color][color=#000000]
[/color][color=#000000]meshTextures [/color][color=#666600]=[/color][color=#000000] [/color][color=#000088]new[/color][color=#000000] LPDIRECT3DTEXTURE9[/color][color=#666600][[/color][color=#000000]numMaterials[/color][color=#666600]];[/color][/size][/color]
[color=#1C2837][size=2][color=#666600]
[/color][/size][/color]
[size="2"][color="#666600"][color=#000000][size=3]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.[/size][/color][/color][/size]

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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 [/size][/font][color=#1C2837][font=CourierNew, monospace][size=2][color=#000000]meshTextures[/color][color=#666600][[/color][color=#000000]0[/color][color=#666600]] ?[/color][/size][/font][/color]

Share this post


Link to post
Share on other sites
Hidden
[quote name='gsamour' timestamp='1312951134' post='4847028']
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 [/size][/font][color="#1C2837"][font="CourierNew, monospace"][size="2"][color="#000000"]meshTextures[/color][color="#666600"][[/color][color="#000000"]0[/color][color="#666600"]] ?[/color][/size][/font][/color]
[/quote]

I believe so. When it gets redfined by

Share this post


Link to post
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[i] = 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

Share this post


Link to post
Share on other sites
Try setting a breakpoint and inspect the values of variables... specifically the value of meshTextures[i] (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][color=#666600][[/color][color=#000000]i[/color][color=#666600]].[/color][color=#000000]pTextureFilename [/color][/size][/font][/color]to see what the file's path is.

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1312986607' post='4847171']
Try setting a breakpoint and inspect the values of variables... specifically the value of meshTextures[i] (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][color="#666600"][[/color][color="#000000"]i[/color][color="#666600"]].[/color][color="#000000"]pTextureFilename [/color][/size][/font][/color]to see what the file's path is.
[/quote]

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

Share this post


Link to post
Share on other sites
[quote name='Tiege' timestamp='1312993506' post='4847206']
The [color="#1C2837"][font="CourierNew, monospace"][size="2"][color="#000000"]d3dxMaterials[/color][color="#666600"][[/color][color="#000000"]i[/color][color="#666600"]].[/color][color="#000000"]pTextureFilename value for the tiger.x model sample is indeed tiger.bmp[/color][/size][/font][/color]
[/quote]

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));
}

Share this post


Link to post
Share on other sites
[quote name='Tiege' timestamp='1312993506' post='4847206']
[font="CourierNew, monospace"][size="2"]it stores the value of the texture in the &meshTextures[i] but for some reason when it gets to the DrawSubet(i) that value in meshTextures[i] becomes 0x00000. I can't figure out why[/size][/font]
[/quote]

Did you change these declarations:

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


to just assignments:

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

?

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1312995081' post='4847219']
[quote name='Tiege' timestamp='1312993506' post='4847206']
The [color="#1C2837"][font="CourierNew, monospace"][size="2"][color="#000000"]d3dxMaterials[/color][color="#666600"][[/color][color="#000000"]i[/color][color="#666600"]].[/color][color="#000000"]pTextureFilename value for the tiger.x model sample is indeed tiger.bmp[/color][/size][/font][/color]
[/quote]

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));
}
[/quote]


what library do i need to link for the DXGetErrorString

and with a breakpoint it says + &meshTextures[i] 0x00902c68 IDirect3DTexture9 * *
I'm assuming that's meshtextures[0] since its the first runthrough

Share this post


Link to post
Share on other sites
[quote name='Tiege' timestamp='1312995293' post='4847223']
what library do i need to link for the DXGetErrorString
[/quote]

You need to include <dxerr.h> and link dxerr.lib.

Share this post


Link to post
Share on other sites
Well i fixed it. I had to have the texture file in the project fold (silly me). But I already knew that. I assumed when I added the texture file to my Visual C++ 2010 project solution that would do the same? No???? I'm certain Visual doesn't want everyone to have to manage files on their OS for this to work. How can I do that through Visual.

Share this post


Link to post
Share on other sites
[quote name='Tiege' timestamp='1312996465' post='4847233']
Well i fixed it. I had to have the texture file in the project fold (silly me). But I already knew that. I assumed when I added the texture file to my Visual C++ 2010 project solution that would do the same? No???? I'm certain Visual doesn't want everyone to have to manage files on their OS for this to work. How can I do that through Visual.
[/quote]

Nope, adding the texture file to the project solution doesn't mean it'll "just work" (this is the way it's done in XNA, but not in DirectX/C++). You have to specify the folder where you want it to load the texture from. If you don't specify an absolute path (i.e. "myTexture.jpg") then it'll use the project's path as default (but you can change this). If you run the .exe without Visual Studio, then it'll use the .exe's folder. You might want to set up your own file loading scheme, then just use something like D3DXLoadTextureFromMemory().

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1312997191' post='4847242']
[quote name='Tiege' timestamp='1312996465' post='4847233']
Well i fixed it. I had to have the texture file in the project fold (silly me). But I already knew that. I assumed when I added the texture file to my Visual C++ 2010 project solution that would do the same? No???? I'm certain Visual doesn't want everyone to have to manage files on their OS for this to work. How can I do that through Visual.
[/quote]

Nope, adding the texture file to the project solution doesn't mean it'll "just work" (this is the way it's done in XNA, but not in DirectX/C++). You have to specify the folder where you want it to load the texture from. If you don't specify an absolute path (i.e. "myTexture.jpg") then it'll use the project's path as default (but you can change this). If you run the .exe without Visual Studio, then it'll use the .exe's folder. You might want to set up your own file loading scheme, then just use something like D3DXLoadTextureFromMemory().
[/quote]

I was specifying the file path for the texture before and it didn't work until i just put it in the same folder and changed it in the .x file to just "tiger.bmp" and it magically worked. Oh well, but thanks so much for your help! I really appreciate it

Share this post


Link to post
Share on other sites

This topic is 2316 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this