CAllocateHierarchy problem!

Started by
3 comments, last by Tiege 12 years, 8 months ago
So I got a program to load a .x file as a model and render it. All my code is just taken from tutorials and all the bare minimums because I'm learning as I go. I'm moving onto the animation .x files instead of static ones and I followed the animation tutorial on this site but when I run the program i get an error:


C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\dinput.h: DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
1>Source1.cpp(113): error C2259: 'CAllocateHierarchy' : cannot instantiate abstract class
1> due to following members:
1> 'HRESULT ID3DXAllocateHierarchy::CreateMeshContainer(LPCSTR,const D3DXMESHDATA *,const D3DXMATERIAL *,const D3DXEFFECTINSTANCE *,DWORD,const DWORD *,LPD3DXSKININFO,LPD3DXMESHCONTAINER *)' : is abstract
1> C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\d3dx9anim.h(168) : see declaration of 'ID3DXAllocateHierarchy::CreateMeshContainer'

For some reason when I delcare:

CAllocateHierarchy Alloc;

it does that even thought I used the struct derives from the tutorial. I basically am just trying to get the bare minimum of an animated x file to load and animate. So my code is crap but I assume it should work. What am I missing from the tutorial?


#include "animation.h"

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


typedef struct _D3DXFRAME_DERIVED: public D3DXFRAME
{ D3DXMATRIX matCombined; //Combined Transformation Matrix
}FRAME, *LPFRAME;
typedef struct _D3DXMESHCONTAINER_DERIVED: public D3DXMESHCONTAINER
{
//Mesh variables
LPDIRECT3DTEXTURE9* ppTextures; // Textures of the mesh
D3DMATERIAL9* pMaterials9; // Use the DirectX 9 Material type

//Skinned mesh variables
LPD3DXMESH pOrigMesh; // The original mesh
D3DXMATRIX* pBoneMatrices; // The bones for the mesh
D3DXMATRIX* pBoneOffsets; // The bone matrix Offsets
D3DXMATRIX* pFrameMatrices; // The Frame Matrix

}MESHCONTAINER, *LPMESHCONTAINER;

class CAllocateHierarchy: public ID3DXAllocateHierarchy
{
public:
// Create a frame
//1. The name of the frame
//2. The output new frame
STDMETHOD(CreateFrame)(THIS_ LPCTSTR Name,
LPD3DXFRAME *ppNewFrame);

// Create a Mesh Container
//1. Name of the Mesh
//2. The mesh Data
//3. that materials of the mesh
//4. the effects on the mesh
//5. the number of materials in the mesh
//6. the adjacency array for the mesh
//7. the skin information for the mesh
//8. the output mesh container
STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name,
LPD3DXMESHDATA pMeshData,
LPD3DXMATERIAL pMaterials,
LPD3DXEFFECTINSTANCE pEffectInstances,
DWORD NumMaterials,
DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer);

// Destroy a frame
//1. The frame to delete
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);

// Destroy a mesh container
//1. The container to destroy
STDMETHOD(DestroyMeshContainer)(THIS_
LPD3DXMESHCONTAINER pMeshContainerBase);
};

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

//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;
LPD3DXFRAME frameRoot;
LPD3DXANIMATIONCONTROLLER animController;
CAllocateHierarchy Alloc;


D3DXLoadMeshHierarchyFromX(
"barb2.x",
D3DXMESH_MANAGED,
d3dDevice,
&Alloc,
NULL,
&frameRoot,
NULL);






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

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

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


note: that animation.h is just an empty file with all the other directx headers in it zzz....
Advertisement
It looks like your function signature for CreateMeshContainer() doesn't match ID3DXAllocateHierarchy::CreateMeshContainer()'s function signature. In particular pAdjacency seems to be a pointer to a constant DWORD in the base class.
Ok so I basically just copied the same function for the CreateMeshContainer found in CAllocateHierarchy and ID3DXAllocateHierarchy but now I get a new error saysing unresolved external symbol for the 4 main methods in the class.


1> C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\dinput.h: DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
1>Source1.obj : error LNK2001: unresolved external symbol "public: virtual long __stdcall CAllocateHierarchy::DestroyMeshContainer(struct _D3DXMESHCONTAINER *)" (?DestroyMeshContainer@CAllocateHierarchy@@UAGJPAU_D3DXMESHCONTAINER@@@Z)
1>Source1.obj : error LNK2001: unresolved external symbol "public: virtual long __stdcall CAllocateHierarchy::DestroyFrame(struct _D3DXFRAME *)" (?DestroyFrame@CAllocateHierarchy@@UAGJPAU_D3DXFRAME@@@Z)
1>Source1.obj : error LNK2001: unresolved external symbol "public: virtual long __stdcall CAllocateHierarchy::CreateMeshContainer(char const *,struct _D3DXMESHDATA const *,struct _D3DXMATERIAL const *,struct _D3DXEFFECTINSTANCE const *,unsigned long,unsigned long const *,struct ID3DXSkinInfo *,struct _D3DXMESHCONTAINER * *)" (?CreateMeshContainer@CAllocateHierarchy@@UAGJPBDPBU_D3DXMESHDATA@@PBU_D3DXMATERIAL@@PBU_D3DXEFFECTINSTANCE@@KPBKPAUID3DXSkinInfo@@PAPAU_D3DXMESHCONTAINER@@@Z)
1>Source1.obj : error LNK2001: unresolved external symbol "public: virtual long __stdcall CAllocateHierarchy::CreateFrame(char const *,struct _D3DXFRAME * *)" (?CreateFrame@CAllocateHierarchy@@UAGJPBDPAPAU_D3DXFRAME@@@Z)
1>C:\Documents and Settings\Trevor\my documents\visual studio 2010\Projects\poop\Release\poop.exe : fatal error LNK1120: 4 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Any ideas?

It looks like your function signature for CreateMeshContainer() doesn't match ID3DXAllocateHierarchy::CreateMeshContainer()'s function signature. In particular pAdjacency seems to be a pointer to a constant DWORD in the base class.
A simpler solution would be to go with ASSIMP, which would load .x files as well as any other file format you would ever need loaded. It is not a bloated library, but takes only a single header and cpp to transfer the file from the ASSIMP loader to your own custom format . . its very simple.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
Stupid question... do I need to fill out each of the four methods with my own code or are the functions built in and can animate it for me with the directx sdk?

And I'm trying to get this working without more librarys other than the directx ones

Answered my own question... I guess I do basically have to just copy all of the example code if I want to see any results...

It was just so much easier getting up to the point of loading a simple .x file model. I think the tutorial on here for the animation makes it way more complicated than it has to be, adding a bunch of unnecessary things for people who just want to load a spinning cube.

Is there any simple way to load and render an animated .x file?

This topic is closed to new replies.

Advertisement