Original Post
So my code is crap. I just want an animated x file to load and render. I tried avoided skinning, materials, textures, bones, because I'm hoping I can just get a dark figure to load on the screen and walk without them.
When my program reaches:
pDrawMesh->DrawSubset(iMaterial);
I get a memory error (Access violation)
The values of my MeshContainer at this point:

Maybe you can find whats obviously wrong with my code.
(Note: I really have little idea what good Rendering functions to draw the meshes should look like)
my CAllocateHierarchy:
Everything else:
When my program reaches:
pDrawMesh->DrawSubset(iMaterial);
I get a memory error (Access violation)
The values of my MeshContainer at this point:

Maybe you can find whats obviously wrong with my code.
(Note: I really have little idea what good Rendering functions to draw the meshes should look like)
my 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;
int NumFaces;
*ppNewMeshContainer = NULL;
pMesh = pMeshData->pMesh;
pMesh->GetDevice( &pd3dDevice );
NumFaces = pMesh->GetNumFaces();
pMeshContainer = new D3DXMESHCONTAINER;
pMeshContainer->MeshData.pMesh = pMesh;
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
pMeshContainer->NumMaterials = max( 1, NumMaterials );
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
//pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
memset( &pMeshContainer->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.0f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.3f;
pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
pd3dDevice->Release();
*ppNewMeshContainer = pMeshContainer;
pMeshContainer = NULL;
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;
}
Everything else:
#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;
}