Problem Loading X Hierarchy

Started by
12 comments, last by Tiege 12 years, 8 months ago
I'm attempting to load and render an animated X file. I managed to get a static model loaded and rendered but I'm having issues with the animated one.

Right now my issue is that my pFrameRoot becomes Null right after the D3DXLoadMeshHierarchyFromX function. I ran it in debug to check the values and during the function call it had values for pFrameRoot but the very next line (i put in an empty if statement to check it) the same variable becomes NULL. The Load mesh function doesn't fail, I used another if statement to check that. But I can't tell why my pFrameroot is going to NULL;

My code is completely horrible and sloppy since I'm just trying to get things to run not to make it clean or developed. I don't even know if it's capable of loading the file properly since I left out a lot from the X file animation tutorial on this website.

But I really just want to get tiny.x rendered and walking. I'm leaving out the textures and skins and other unnecessary (i hope) things which I can fix and implement later.



#include <windows.h>
#include <d3dx9.h>
#include <MMSystem.h>
#include <dinput.h>
#include <d3dx9anim.h>
#include <d3d9.h>


// #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
// #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

//globals
LPDIRECT3D9 d3dObject=NULL;
LPDIRECT3DDEVICE9 d3dDevice=NULL;
LPDIRECTINPUT8 din; // the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8 dinkeyboard; // the pointer to the keyboard device
BYTE keystate[256]; // the storage for the key-information

//declare functions
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void detect_input(void); // gets the current input state
void cleanDInput(void); // closes DirectInput and releases memory
void Render();
void DrawFrame(LPD3DXFRAME frame);

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


/********************************ANIMATION***************************************/
LPD3DXFRAME pFrameRoot = NULL;
LPD3DXANIMATIONCONTROLLER pAnimController = NULL;

class CAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:
STDMETHOD( CreateFrame )( THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame );
STDMETHOD( CreateMeshContainer )( THIS_
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer );
STDMETHOD( DestroyFrame )( THIS_ LPD3DXFRAME pFrameToFree );
STDMETHOD( DestroyMeshContainer )( THIS_ LPD3DXMESHCONTAINER pMeshContainerBase );

CAllocateHierarchy()
{
}
};

HRESULT CAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME* ppNewFrame )
{
D3DXFRAME* pFrame;

*ppNewFrame = NULL;

pFrame = new D3DXFRAME;

D3DXMatrixIdentity( &pFrame->TransformationMatrix );

pFrame->pMeshContainer = NULL;
pFrame->pFrameSibling = NULL;
pFrame->pFrameFirstChild = NULL;

*ppNewFrame = pFrame;
pFrame = NULL;

delete pFrame;

return S_OK;
}

HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer )
{

D3DXMESHCONTAINER *pMeshContainer = NULL;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;

*ppNewMeshContainer = NULL;

pMesh = pMeshData->pMesh;

pMeshContainer = new D3DXMESHCONTAINER;

pMesh->GetDevice( &pd3dDevice );

pMesh = pMeshContainer->MeshData.pMesh;

pMeshContainer->NumMaterials = max( 1, NumMaterials );
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
//pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
//pMeshContainer->pAdjacency = new DWORD[NumFaces*3];

pMeshContainer->pMaterials[0].pTextureFilename = NULL;
memset( &pMeshContainer->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;

pd3dDevice->Release();

if( pMeshContainer != NULL )
DestroyMeshContainer( pMeshContainer );

return S_OK;
}

HRESULT CAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree )
{
//delete[] pFrameToFree->Name;
//delete pFrameToFree;
return S_OK;
}

HRESULT CAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerBase )
{
D3DXMESHCONTAINER* pMeshContainer = ( D3DXMESHCONTAINER* )pMeshContainerBase;

//delete[] pMeshContainer->Name;
// delete[] pMeshContainer->pAdjacency;
// delete[] pMeshContainer->pMaterials;

// (pMeshContainer->MeshData.pMesh)->Release();
// (pMeshContainer->pSkinInfo)->Release();
// delete pMeshContainer;

return S_OK;
}
/******************************END ANIMATION*************************************/

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;
CAllocateHierarchy Alloc;

if (D3DXLoadMeshHierarchyFromX( "tiny.x", // File load
D3DXMESH_MANAGED, // Load Options
d3dDevice, // D3D Device
&Alloc, // Hierarchy allocation class
NULL, // NO Effects
&pFrameRoot, // Frame hierarchy
&pAnimController))
// Animation Controller
MessageBox( NULL, "Could not poop", "Meshes.exe", MB_OK );

//check value of pFrameRoot via Debug
if (pFrameRoot)
;

// Load the mesh from the specified file
if( FAILED( D3DXLoadMeshFromX( "cube6.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();

meshMaterials = new D3DMATERIAL9[numMaterials];
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)
HRESULT hr = (D3DXCreateTextureFromFile(d3dDevice, d3dxMaterials.pTextureFilename, &meshTextures));

}

materialBuffer->Release();

return S_OK;
}

VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIXA16 matWorld;
D3DXMATRIX mtranslate;

// index+=0.03f;
static float index = 0.0f;
if(keystate[DIK_LEFT] & 0x80)
index += 0.06f;
if(keystate[DIK_RIGHT] & 0x80)
index -= 0.06f;

//rotate model
D3DXMatrixRotationY( &matWorld, index );

//translate model
D3DXMatrixTranslation(&mtranslate, index, 0.0f, 0.0f);

d3dDevice->SetTransform( D3DTS_WORLD, &(matWorld * mtranslate) );

// 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( -4.0f, 8.0f,0.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 0.0f, 1.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,50,100),1.0f,0);

//begin scene
d3dDevice->BeginScene();

SetupMatrices();

if (pFrameRoot)
DrawFrame(pFrameRoot);
else
MessageBox( NULL, "Could not find tiger.x", "Meshes.exe", MB_OK );

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


void DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase)
{
D3DXFRAME *frame = frameBase;

D3DXMESHCONTAINER *meshContainer = meshContainerBase;

// Loop through all the materials in the mesh rendering each subset
for (unsigned int iMaterial = 0; iMaterial < meshContainer->NumMaterials; iMaterial++)
{
// use the material in our extended data rather than the one in meshContainer->pMaterials[iMaterial].MatD3D
//d3dDevice->SetMaterial( &meshContainer->exMaterials[iMaterial] );
//d3dDevice->SetTexture( 0, meshContainer->exTextures[iMaterial] );

// Select the mesh to draw, if there is skin then use the skinned mesh else the normal one
LPD3DXMESH pDrawMesh = meshContainer->MeshData.pMesh;

// Finally Call the mesh draw function
pDrawMesh->DrawSubset(iMaterial);
}
}

void DrawFrame(LPD3DXFRAME frame)
{
// Draw all mesh containers in this frame
LPD3DXMESHCONTAINER meshContainer = frame->pMeshContainer;
while (meshContainer)
{
DrawMeshContainer(meshContainer, frame);
meshContainer = meshContainer->pNextMeshContainer;
}

// Recurse for sibblings
if (frame->pFrameSibling != NULL)
DrawFrame(frame->pFrameSibling);

// Recurse for children
if (frame->pFrameFirstChild != NULL)
DrawFrame(frame->pFrameFirstChild);
}

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

// this is the function that initializes DirectInput
void initDInput(HINSTANCE hInstance, HWND hWnd)
{
// create the DirectInput interface
DirectInput8Create(hInstance, // the handle to the application
DIRECTINPUT_VERSION, // the compatible version
IID_IDirectInput8, // the DirectInput interface version
(void**)&din, // the pointer to the interface
NULL); // COM stuff, so we'll set it to NULL

// create the keyboard device
din->CreateDevice(GUID_SysKeyboard, // the default keyboard ID being used
&dinkeyboard, // the pointer to the device interface
NULL); // COM stuff, so we'll set it to NULL

// set the data format to keyboard format
dinkeyboard->SetDataFormat(&c_dfDIKeyboard);

// set the control we will have over the keyboard
dinkeyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
}


// this is the function that gets the latest input data
void detect_input(void)
{
// get access if we don't have it already
dinkeyboard->Acquire();

// get the input data
dinkeyboard->GetDeviceState(256, (LPVOID)keystate);
}


// this is the function that closes DirectInput
void cleanDInput(void)
{
dinkeyboard->Unacquire(); // make sure the keyboard is unacquired
din->Release(); // close DirectInput before exiting
}

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);
initDInput(hInstance, hWnd); // initialize DirectInput

InitMesh();

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

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

detect_input(); // update the input data before rendering
Render();
}
cleanDInput(); // release DirectInput

return (int)msg.wParam;
}
Advertisement
I'm pretty sure your problem is that you free pFrame inside the CreateFrame function.

delete pFrame; <- remove this line from CreateFrame() function. To free memory, just implement the DestroyFrame() function correctly. Here's my simple version of each function:



HRESULT CHierarchyLoader::CreateFrame(LPCSTR Name, LPD3DXFRAME* ppNewFrame)
{
SBone* pBone = new SBone;
memset(pBone, 0, sizeof(SBone));

// copy name
if (Name != NULL)
{
pBone->Name = new char[strlen(Name) + 1];
strcpy(pBone->Name, Name);
}

// set the TM's
D3DXMatrixIdentity(&pBone->TransformationMatrix);
D3DXMatrixIdentity(&pBone->CombinedTransformationMatrix);

// return the new bone
*ppNewFrame = (D3DXFRAME*)pBone;

return S_OK;
}

HRESULT CHierarchyLoader::CreateMeshContainer(THIS_ LPCSTR Name,
CONST D3DXMESHDATA* pMeshData,
CONST D3DXMATERIAL* pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD* pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER* ppNewMeshContainer)
{
//Just return a temporary mesh for now...
*ppNewMeshContainer = new SBoneMeshContainer;
memset(*ppNewMeshContainer, 0, sizeof(SBoneMeshContainer));

return S_OK;
}

HRESULT CHierarchyLoader::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
// free siblings and children first
if (pFrameToFree->pFrameSibling)
DestroyFrame(pFrameToFree->pFrameSibling);

if (pFrameToFree->pFrameFirstChild)
DestroyFrame(pFrameToFree->pFrameFirstChild);


// now free the current frame
if (pFrameToFree)
{
// free Name string
if (pFrameToFree->Name != NULL)
delete [] pFrameToFree->Name;

// free mesh container
DestroyMeshContainer(pFrameToFree->pMeshContainer);

// free frame
delete pFrameToFree;
}

pFrameToFree = NULL;

return S_OK;
}

HRESULT CHierarchyLoader::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
if(pMeshContainerBase != NULL)
delete pMeshContainerBase;

return S_OK;
}



You'll notice the SBone and SBoneMeshContainer functions. Those are custom but don't add a whole lot. I'm using the "Character Animation with Direct3D" book as my guide.
I did what you said and replaced my worthless DestroyFrame and DestroyMeshContainer with yours but my pFrameRoot still turns to NULL when its time to draw. Althought it didnt go NULL as soon as DXDLoadFromXFileHierarchy finished.

I cleaned up my code a little and got rid of all the other static xfile stuff:



#include "Utilities.h"
#include "allocatehierarchy.h"

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

//declare functions
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void Render();
void DrawFrame(LPD3DXFRAME frame);



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()
{
CAllocateHierarchy Alloc;

D3DXLoadMeshHierarchyFromX( "tiny.x", // File load
D3DXMESH_MANAGED, // Load Options
d3dDevice, // D3D Device
&Alloc, // Hierarchy allocation class
NULL, // NO Effects
&pFrameRoot, // Frame hierarchy
&pAnimController);
// Animation Controller

//check value of pFrameRoot via Debug
if (pFrameRoot)
;

return S_OK;
}

VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIXA16 matWorld;
D3DXMATRIX mtranslate;

//rotate model
D3DXMatrixRotationY( &matWorld, 0 );

//translate model
D3DXMatrixTranslation(&mtranslate, 0.0f, 0.0f, 0.0f);

d3dDevice->SetTransform( D3DTS_WORLD, &(matWorld * mtranslate) );

// 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( -4.0f, 8.0f,0.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 0.0f, 1.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,50,100),1.0f,0);

//begin scene
d3dDevice->BeginScene();

SetupMatrices();

if (pFrameRoot)
DrawFrame(pFrameRoot);
else
MessageBox( NULL, "Could not find tiger.x", "Meshes.exe", MB_OK );

//end scene
d3dDevice->EndScene();

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


void DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase)
{
D3DXFRAME *frame = frameBase;

D3DXMESHCONTAINER *meshContainer = meshContainerBase;

// Loop through all the materials in the mesh rendering each subset
for (unsigned int iMaterial = 0; iMaterial < meshContainer->NumMaterials; iMaterial++)
{
// use the material in our extended data rather than the one in meshContainer->pMaterials[iMaterial].MatD3D
//d3dDevice->SetMaterial( &meshContainer->exMaterials[iMaterial] );
//d3dDevice->SetTexture( 0, meshContainer->exTextures[iMaterial] );

// Select the mesh to draw, if there is skin then use the skinned mesh else the normal one
LPD3DXMESH pDrawMesh = meshContainer->MeshData.pMesh;

// Finally Call the mesh draw function
pDrawMesh->DrawSubset(iMaterial);
}
}

void DrawFrame(LPD3DXFRAME frame)
{
// Draw all mesh containers in this frame
LPD3DXMESHCONTAINER meshContainer = frame->pMeshContainer;
while (meshContainer)
{
DrawMeshContainer(meshContainer, frame);
meshContainer = meshContainer->pNextMeshContainer;
}

// Recurse for sibblings
if (frame->pFrameSibling != NULL)
DrawFrame(frame->pFrameSibling);

// Recurse for children
if (frame->pFrameFirstChild != NULL)
DrawFrame(frame->pFrameFirstChild);
}

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


CAllocateHierarchy:


#include "Utilities.h"

/********************************ANIMATION***************************************/
LPD3DXFRAME pFrameRoot = NULL;
LPD3DXANIMATIONCONTROLLER pAnimController = NULL;

class CAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:
STDMETHOD( CreateFrame )( THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame );
STDMETHOD( CreateMeshContainer )( THIS_
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer );
STDMETHOD( DestroyFrame )( THIS_ LPD3DXFRAME pFrameToFree );
STDMETHOD( DestroyMeshContainer )( THIS_ LPD3DXMESHCONTAINER pMeshContainerBase );

CAllocateHierarchy()
{
}
};

HRESULT CAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME* ppNewFrame )
{
D3DXFRAME* pFrame;

*ppNewFrame = NULL;

pFrame = new D3DXFRAME;

// copy name
if (Name != NULL)
{
pFrame->Name = new char[strlen(Name) + 1];
strcpy(pFrame->Name, Name);
}

D3DXMatrixIdentity( &pFrame->TransformationMatrix );

pFrame->pMeshContainer = NULL;
pFrame->pFrameSibling = NULL;
pFrame->pFrameFirstChild = NULL;

*ppNewFrame = (D3DXFRAME*)pFrame;
pFrame = NULL;

return S_OK;
}

HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer )
{

D3DXMESHCONTAINER *pMeshContainer = NULL;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;

*ppNewMeshContainer = NULL;

pMesh = pMeshData->pMesh;

pMeshContainer = new D3DXMESHCONTAINER;

pMesh->GetDevice( &pd3dDevice );

pMesh = pMeshContainer->MeshData.pMesh;

pMeshContainer->NumMaterials = max( 1, NumMaterials );
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
//pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
//pMeshContainer->pAdjacency = new DWORD[NumFaces*3];

pMeshContainer->pMaterials[0].pTextureFilename = NULL;
memset( &pMeshContainer->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;

pd3dDevice->Release();

if( pMeshContainer != NULL )
DestroyMeshContainer( pMeshContainer );

return S_OK;
}
/*
HRESULT CAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree )
{
//delete[] pFrameToFree->Name;
//delete pFrameToFree;
return S_OK;
}

HRESULT CAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerBase )
{
D3DXMESHCONTAINER* pMeshContainer = ( D3DXMESHCONTAINER* )pMeshContainerBase;

//delete[] pMeshContainer->Name;
// delete[] pMeshContainer->pAdjacency;
// delete[] pMeshContainer->pMaterials;

// (pMeshContainer->MeshData.pMesh)->Release();
// (pMeshContainer->pSkinInfo)->Release();
// delete pMeshContainer;

return S_OK;
}
*/
/******************************END ANIMATION*************************************/



HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
// free siblings and children first
if (pFrameToFree->pFrameSibling)
DestroyFrame(pFrameToFree->pFrameSibling);

if (pFrameToFree->pFrameFirstChild)
DestroyFrame(pFrameToFree->pFrameFirstChild);


// now free the current frame
if (pFrameToFree)
{
// free Name string
if (pFrameToFree->Name != NULL)
delete [] pFrameToFree->Name;

// free mesh container
DestroyMeshContainer(pFrameToFree->pMeshContainer);

// free frame
delete pFrameToFree;
}

pFrameToFree = NULL;

return S_OK;
}

HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
if(pMeshContainerBase != NULL)
delete pMeshContainerBase;

return S_OK;
}
if you are using delete [] pFrameToFree->Name, then you must allocate it in CreateFrame() (see my CreateFrame.. you can either add the name allocation code, or remove the delete[] name code). Bottom line, you can't delete something that isn't there. As for SBone, it's essentially equivalent to D3DXFRAME. It inherits from it, but adds a D3DXMATRIX that acts as a combined transformation matrix. For now, you can just use D3DXFRAME.
Sorry I don't think I edited in time heh. I figured the name thing was the problem so I did add the name allocation and thats fine now. But my frameRoot still turns NULL when I try to draw it.

if you are using delete [] pFrameToFree->Name, then you must allocate it in CreateFrame() (see my CreateFrame.. you can either add the name allocation code, or remove the delete[] name code). Bottom line, you can't delete something that isn't there. As for SBone, it's essentially equivalent to D3DXFRAME. It inherits from it, but adds a D3DXMATRIX that acts as a combined transformation matrix. For now, you can just use D3DXFRAME.
This may be a dumb question, but... are you sure the mesh you're testing with has a skeleton? Are you testing with Tiny.x or with Tiger.x.... you said tiny.x, but mention tiger.x in code comments.
Ya it's Tiny.x
I was using tiger.x to learn how to load static meshes then I moved onto tiny but I just keep the same error message "Could Not Load tiger.x" cause it doesnt matter what it displays.

But anywho so now it appears that when I get the frameroot the meshcontainer is NULL. Your CreateMeshContainer function just makes an empty meshcontainer doesn't it? When does it actually import the mesh data into the meshcontainer because mine just returns NULL.


I'm assuming at this point after seeing other samples that your CreateMeshContainer function wasn't really like that but just so I didn't have to worry about it... Well now I'm pretty sure any problems I have are from that function so I need to figure out what is wrong with mine or a simple one I can use. I skipped a lot of things like texture and skinning and materials and error checking because I just want to get it to work for now.



HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer )
{

D3DXMESHCONTAINER *pMeshContainer = NULL;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;

*ppNewMeshContainer = NULL;

pMesh = pMeshData->pMesh;

pMeshContainer = new D3DXMESHCONTAINER;

pMesh->GetDevice( &pd3dDevice );

pMesh = pMeshContainer->MeshData.pMesh;

pMeshContainer->NumMaterials = max( 1, NumMaterials );
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
//pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
//pMeshContainer->pAdjacency = new DWORD[NumFaces*3];

pMeshContainer->pMaterials[0].pTextureFilename = NULL;
memset( &pMeshContainer->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;

pd3dDevice->Release();

if( pMeshContainer != NULL )
DestroyMeshContainer( pMeshContainer );

return S_OK;
}

This may be a dumb question, but... are you sure the mesh you're testing with has a skeleton? Are you testing with Tiny.x or with Tiger.x.... you said tiny.x, but mention tiger.x in code comments.
UPDATE: Well I hope you come back. So now I'm at the point where I get a memory error when it gets to the DrawSubset function. After comparing back and forth between the SkinnedMesh values and mine I fixed the mesh data problems. Right now I have a few variables in my mesh container which i purposely left NULL because I didn't think I needed them to render the model. these are: NAME, pEffects, pSkinInfo, and pNextMesh.

Althought some are 0x000000 and others (like pSkinInfo) is 0xdcdcdcdc. I assume those both mean NULL?

Would having any of these cause my program to error like it is?
I didn't see this until too late tonight to do much looking around. Taking a quick look at a couple tutorials it looks like you leave some parameters NULL in your D3DXLoadMeshFromX calls that they don't have NULL in the tutorials, but I don't know if that's kosher or not. Certainly something isn't set that ought to be, but I'm not sure what. But It's 2a.m. here, so I'm going to bed ;) I'll take a closer look at it when I have more time.

I didn't see this until too late tonight to do much looking around. Taking a quick look at a couple tutorials it looks like you leave some parameters NULL in your D3DXLoadMeshFromX calls that they don't have NULL in the tutorials, but I don't know if that's kosher or not. Certainly something isn't set that ought to be, but I'm not sure what. But It's 2a.m. here, so I'm going to bed ;) I'll take a closer look at it when I have more time.


Hmm I tried only using NULL if i saw it in a tutorial =P I just didn't see much use for pEffects n such

This topic is closed to new replies.

Advertisement