Problem Loading MeshContainer

Started by
1 comment, last by Tiege 12 years, 7 months ago
I'm trying to load tiny.x as an animated x file. So far my program just renders the head itself, so at least I know im getting close! I actually have no idea why because when I run through the program in debug mode it doesnt even get to the DrawMeshContainer function but somehow it gets there once to draw just the head. It appears that my problem is that my pFrameRoot doesn't carry a meshContainer value. Since my draw functions check the value of the meshContainer to do they don't run because there isn't any. I can't find a problem in my CMeshHierarchy::CreateMeshContainer or in my loading that would cause this.

Can you see why my pFrameRoot->pmeshContainer remains NULL?

Source.cpp


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

char* filename = "tiny.x";

//globals
LPDIRECT3D9 d3dObject=NULL;
LPDIRECT3DDEVICE9 d3dDevice;
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

LPD3DXFRAME pFrameRoot;
LPD3DXANIMATIONCONTROLLER pAnimController;

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


void Load()
{
CMeshHierarchy Alloc;

D3DXLoadMeshHierarchyFromX(
"tiny.x",
D3DXMESH_MANAGED,
d3dDevice,
&Alloc,
NULL,
&pFrameRoot,
&pAnimController );

//Set Breakpoint to check value of pFrameRoot
if (pFrameRoot)
;
}

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


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( 0.0f, 150.0f, 130.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();

DrawFrame(pFrameRoot);

SetupMatrices();

//end scene
d3dDevice->EndScene();

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




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

void DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase)
{
// Cast to our extended frame type
D3DXFRAME_EXTENDED *frame = (D3DXFRAME_EXTENDED*)frameBase;

// Cast to our extended mesh container
D3DXMESHCONTAINER_EXTENDED *meshContainer = (D3DXMESHCONTAINER_EXTENDED*)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 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
}


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

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

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

Load();
Render();
}

return (int)msg.wParam;
}


AllocateHierarchy.h


#include "Utilities.h"
//Derived Structs
struct D3DXFRAME_EXTENDED: public D3DXFRAME
{
D3DXMATRIX exCombinedTransformationMatrix;
};
struct D3DXMESHCONTAINER_EXTENDED: public D3DXMESHCONTAINER
{
// The base D3DXMESHCONTAINER has a pMaterials member which is a D3DXMATERIAL structure
// that contains a texture filename and material data. It is easier to ignore this and
// instead store the data in arrays of textures and materials in this extended structure:
IDirect3DTexture9** exTextures; // Array of texture pointers
D3DMATERIAL9* exMaterials; // Array of materials

// Skinned mesh variables
ID3DXMesh* exSkinMesh; // The skin mesh
D3DXMATRIX* exBoneOffsets; // The bone matrix Offsets, one per bone
D3DXMATRIX** exFrameCombinedMatrixPointer; // Array of frame matrix pointers
};

class CMeshHierarchy : public ID3DXAllocateHierarchy
{
public:
// callback to create a D3DXFRAME extended object and initialize it
STDMETHOD( CreateFrame )(LPCSTR Name, LPD3DXFRAME *retNewFrame );

// callback to create a D3DXMESHCONTAINER extended object and initialize it
STDMETHOD( CreateMeshContainer )(LPCSTR Name, CONST D3DXMESHDATA * meshData,
CONST D3DXMATERIAL * materials, CONST D3DXEFFECTINSTANCE * effectInstances,
DWORD numMaterials, CONST DWORD * adjacency, LPD3DXSKININFO skinInfo,
LPD3DXMESHCONTAINER * retNewMeshContainer );

// callback to release a D3DXFRAME extended object
STDMETHOD( DestroyFrame )(LPD3DXFRAME frameToFree );

// callback to release a D3DXMESHCONTAINER extended object
STDMETHOD( DestroyMeshContainer )(LPD3DXMESHCONTAINER meshContainerToFree );
};

HRESULT CMeshHierarchy::CreateFrame(LPCSTR Name, LPD3DXFRAME *retNewFrame)
{
// Always a good idea to initialise a return pointer before proceeding
*retNewFrame = 0;

// Create a new frame using the derived version of the structure
D3DXFRAME_EXTENDED *newFrame = new D3DXFRAME_EXTENDED;
ZeroMemory(newFrame,sizeof(D3DXFRAME_EXTENDED));

// Now fill in the data members in the frame structure

// Now initialize other data members of the frame to defaults
D3DXMatrixIdentity(&newFrame->TransformationMatrix);
D3DXMatrixIdentity(&newFrame->exCombinedTransformationMatrix);

newFrame->pMeshContainer = 0;
newFrame->pFrameSibling = 0;
newFrame->pFrameFirstChild = 0;

// Assign the return pointer to our newly created frame
*retNewFrame = newFrame;

// The frame name (note: may be 0 or zero length)
if (Name != NULL)
{
newFrame->Name = new char[strlen(Name) + 1];
strcpy(newFrame->Name, Name);
}
return S_OK;
}

/**
* \brief callback called when a mesh data is encountered during the .x file load
* \param Name - name of the Mesh (const char*)
* \param meshData - the mesh data
* \param materials - material array
* \param effectInstances - effect files / settings for the mesh
* \param numMaterials - number of materials in the mesh
* \param adjacency - adjacency array
* \param pSkinInfo - skin info.
* \param retNewMeshContainer - output pointer to assign our newly created mesh container
* \return success code
* \author Keith Ditchburn \date 17 July 2005
*/
HRESULT CMeshHierarchy::CreateMeshContainer(
LPCSTR Name,
CONST D3DXMESHDATA *meshData,
CONST D3DXMATERIAL *materials,
CONST D3DXEFFECTINSTANCE *effectInstances,
DWORD numMaterials,
CONST DWORD *adjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER* retNewMeshContainer)
{
// Create a mesh container structure to fill and initilaise to zero values
// Note: I use my extended version of the structure (D3DXMESHCONTAINER_EXTENDED) defined in MeshStructures.h
D3DXMESHCONTAINER_EXTENDED *newMeshContainer=new D3DXMESHCONTAINER_EXTENDED;
ZeroMemory(newMeshContainer, sizeof(D3DXMESHCONTAINER_EXTENDED));

// Always a good idea to initialise return pointer before proceeding
*retNewMeshContainer = 0;

// The mesh name (may be 0) needs copying over
if (Name != NULL)
{
newMeshContainer->Name = new char[strlen(Name) + 1];
strcpy(newMeshContainer->Name, Name);
}

// The mesh type (D3DXMESHTYPE_MESH, D3DXMESHTYPE_PMESH or D3DXMESHTYPE_PATCHMESH)
if (meshData->Type!=D3DXMESHTYPE_MESH)
{
// This demo does not handle mesh types other than the standard
// Other types are D3DXMESHTYPE_PMESH (progressive mesh) and D3DXMESHTYPE_PATCHMESH (patch mesh)
DestroyMeshContainer(newMeshContainer);
return E_FAIL;
}

newMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

// Adjacency data - holds information about triangle adjacency, required by the ID3DMESH object
DWORD dwFaces = meshData->pMesh->GetNumFaces();
newMeshContainer->pAdjacency = new DWORD[dwFaces*3];
if (adjacency)
{
memcpy(newMeshContainer->pAdjacency, adjacency, sizeof(DWORD) * dwFaces*3);
}
else
{
// Added 24/08/10: previously did not detect null adjacency
if(FAILED( newMeshContainer->MeshData.pMesh->GenerateAdjacency( 1e-6f, (DWORD*)(void*)newMeshContainer->pAdjacency ) ) )
FillMemory((void*)newMeshContainer->pAdjacency, dwFaces*3, 0xFF );
}

// Get the Direct3D device, luckily this is held in the mesh itself (Note: must release it when done with it)
LPDIRECT3DDEVICE9 pd3dDevice = 0;
meshData->pMesh->GetDevice(&pd3dDevice);

// Changed 24/09/07 - can just assign pointer and add a ref rather than need to clone
newMeshContainer->MeshData.pMesh=meshData->pMesh;
newMeshContainer->MeshData.pMesh->AddRef();

// Create material and texture arrays. Note that I always want to have at least one
newMeshContainer->NumMaterials = max(numMaterials,1);
newMeshContainer->exMaterials = new D3DMATERIAL9[newMeshContainer->NumMaterials];
newMeshContainer->exTextures = new LPDIRECT3DTEXTURE9[newMeshContainer->NumMaterials];

ZeroMemory(newMeshContainer->exTextures, sizeof(LPDIRECT3DTEXTURE9) * newMeshContainer->NumMaterials);

if (numMaterials>0)
{
// Load all the textures and copy the materials over
for(DWORD i = 0; i < numMaterials; ++i)
{
newMeshContainer->exTextures = 0;
newMeshContainer->exMaterials=materials.MatD3D;

if(materials.pTextureFilename)
{

D3DXCreateTextureFromFile(pd3dDevice, materials.pTextureFilename,
&newMeshContainer->exTextures);

}
}
}
else
// make a default material in the case where the mesh did not provide one
{
ZeroMemory(&newMeshContainer->exMaterials[0], sizeof( D3DMATERIAL9 ) );
newMeshContainer->exMaterials[0].Diffuse.r = 0.5f;
newMeshContainer->exMaterials[0].Diffuse.g = 0.5f;
newMeshContainer->exMaterials[0].Diffuse.b = 0.5f;
newMeshContainer->exMaterials[0].Specular = newMeshContainer->exMaterials[0].Diffuse;
newMeshContainer->exTextures[0]=0;
}

// If there is skin data associated with the mesh copy it over
if (pSkinInfo)
{
// save off the SkinInfo
newMeshContainer->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef();

// Need an array of offset matrices to move the vertices from the figure space to the bone's space
UINT numBones = pSkinInfo->GetNumBones();
newMeshContainer->exBoneOffsets = new D3DXMATRIX[numBones];

// Create the arrays for the bones and the frame matrices
newMeshContainer->exFrameCombinedMatrixPointer = new D3DXMATRIX*[numBones];

// get each of the bone offset matrices so that we don't need to get them later
for (UINT i = 0; i < numBones; i++)
newMeshContainer->exBoneOffsets = *(newMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i));


// Note: in the Microsoft samples a GenerateSkinnedMesh function is called here in order to prepare
// the skinned mesh data for optimial hardware acceleration. As mentioned in the notes this sample
// does not do hardware skinning but instead uses software skinning.
}
else
{
// No skin info so 0 all the pointers
newMeshContainer->pSkinInfo = 0;
newMeshContainer->exBoneOffsets = 0;
newMeshContainer->exSkinMesh = 0;
newMeshContainer->exFrameCombinedMatrixPointer = 0;
}

// When we got the device we caused an internal reference count to be incremented
// So we now need to release it
pd3dDevice->Release();

// The mesh may contain a reference to an effect file
if (effectInstances)
{
if (effectInstances->pEffectFilename)
MessageBox(NULL, "Effect Instance", "Model Load Error", MB_OK);
}

// Set the output mesh container pointer to our newly created one
*retNewMeshContainer = newMeshContainer;

return S_OK;
}

/**
* \brief callback called to deallocate the frame data
* \param the frame to free
* \return success result
* \author Keith Ditchburn \date 17 July 2005
*/
HRESULT CMeshHierarchy::DestroyFrame(LPD3DXFRAME frameToFree)
{
// Convert to our extended type. OK to do this as we know for sure it is:
D3DXFRAME_EXTENDED *frame = (D3DXFRAME_EXTENDED*)frameToFree;

delete []frame->Name;
delete frame;

return S_OK;
}

/**
* \brief callback called to deallocate the mesh container data
* \param the mesh data to free
* \return success result
* \author Keith Ditchburn \date 17 July 2005
*/
HRESULT CMeshHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER meshContainerBase)
{
// Convert to our extended type. OK as we know for sure it is:
D3DXMESHCONTAINER_EXTENDED* meshContainer = (D3DXMESHCONTAINER_EXTENDED*)meshContainerBase;
if (!meshContainer)
return S_OK;

// name
delete []meshContainer->Name;
meshContainer->Name=0;

// material array
delete []meshContainer->exMaterials;
meshContainer->exMaterials=0;

// release the textures before deleting the array
if(meshContainer->exTextures)
{
for(UINT i = 0; i < meshContainer->NumMaterials; ++i)
{
if (meshContainer->exTextures)
meshContainer->exTextures->Release();
}
}

// texture array
delete []meshContainer->exTextures;

// adjacency data
delete []meshContainer->pAdjacency;

// bone parts
delete []meshContainer->exBoneOffsets;

// frame matrices
delete []meshContainer->exFrameCombinedMatrixPointer;

// release skin mesh
if (meshContainer->exSkinMesh)
meshContainer->exSkinMesh->Release();

// release the main mesh
if (meshContainer->MeshData.pMesh)
meshContainer->MeshData.pMesh->Release();

// release skin information
if (meshContainer->pSkinInfo)
meshContainer->pSkinInfo->Release();

// finally delete the mesh container itself
delete meshContainer;
meshContainer=0;

return S_OK;
}
Advertisement
UPDATE: It occured to me as I was trying to move around the head that i could render that it might not be the head. It might be all the meshes loaded and jumbled into unset places. I cant really tell because it looks similar to the spikey hair head from tiny.x but doesn't look exact. I also added the SetUpBoneMatrices function from the tutorial on here so I can't see what the problem would be if they are loading and rendering but not being set up to produce the figure of tiny.

Updated Source.cpp:


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

char* filename = "tiny.x";

int p = 0;


//globals
LPDIRECT3D9 d3dObject=NULL;
LPDIRECT3DDEVICE9 d3dDevice;
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

LPD3DXFRAME pFrameRoot;
LPD3DXANIMATIONCONTROLLER pAnimController;

// Bone data
D3DXMATRIX *boneMatrices;
UINT maxBones;

//declare functions
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void Render();
void DrawFrame(LPD3DXFRAME frame);
void DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase);
void detect_input(void); // gets the current input state
void cleanDInput(void); // closes DirectInput and releases memory
void SetupBoneMatrices(D3DXFRAME_EXTENDED *pFrame);
void UpdateSkinnedMesh(const D3DXFRAME *frameBase);
void UpdateFrameMatrices(const D3DXFRAME *frameBase, const D3DXMATRIX *parentMatrix);

void Load()
{
CMeshHierarchy Alloc;

D3DXLoadMeshHierarchyFromX(
"tiny.x",
D3DXMESH_MANAGED,
d3dDevice,
&Alloc,
NULL,
&pFrameRoot,
&pAnimController );

//Set Breakpoint to check value of pFrameRoot
if (pFrameRoot)
{
SetupBoneMatrices((D3DXFRAME_EXTENDED*)pFrameRoot);

// Create the bone matrices array for use during FrameMove to hold the final transform
boneMatrices = new D3DXMATRIX[maxBones];
ZeroMemory(boneMatrices, sizeof(D3DXMATRIX)*maxBones);
}
}

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


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

static float index3 = 0.0f;
static float index = 0.0f;
static float index2 = 0.0f;
if(keystate[DIK_LEFT] & 0x80)
index += 5.0f;
if(keystate[DIK_RIGHT] & 0x80)
index -= 5.0f;
if(keystate[DIK_UP] & 0x80)
index2 += 5.0f;
if(keystate[DIK_DOWN] & 0x80)
index2 -= 5.0f;

if(keystate[DIK_R] & 0x80)
index3 -= 2.0f;


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

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

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( 30.0f, 150.0f, 150.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();

DrawFrame(pFrameRoot);


SetupMatrices();

//end scene
d3dDevice->EndScene();

//present screen
d3dDevice->Present( NULL, NULL, NULL, NULL );
}
/*
void UpdateSkinnedMesh(const D3DXFRAME *frameBase)
{
D3DXFRAME_EXTENDED *currentFrame = (D3DXFRAME_EXTENDED*)frameBase;

D3DXMESHCONTAINER_EXTENDED* pMesh = (D3DXMESHCONTAINER_EXTENDED*)currentFrame->pMeshContainer;
while(pMesh && pMesh->pSkinInfo) // handle chained skinned mesh added 24/08/10
{
unsigned int Bones = pMesh->pSkinInfo->GetNumBones();

// Create the bone matrices that transform each bone from bone space into character space
// (via exFrameCombinedMatrixPointer) and also wraps the mesh around the bones using the bone offsets
// in exBoneOffsetsArray
for (unsigned int i = 0; i < Bones; ++i)
{

// Note: during set up exFrameCombinedMatrixPointer is made to point to the correct frame matrix (exCombinedTransformationMatrix)
// So it does not directly get updated but uses the existing frame calculated value from the correct 'controller' frame
D3DXMatrixMultiply(&boneMatrices,&pMesh->exBoneOffsets, pMesh->exFrameCombinedMatrixPointer);
}

// We need to modify the vertex positions based on the new bone matrices. This is achieved
// by locking the vertex buffers and then calling UpdateSkinnedMesh. UpdateSkinnedMesh takes the
// original vertex data (in pMesh->MeshData.pMesh), applies the matrices and writes the new vertices
// out to skin mesh (pMesh->exSkinMesh).

// UpdateSkinnedMesh uses software skinning which is the slowest way of carrying out skinning
// but is easiest to describe and works on the majority of graphic devices.
// Other methods exist that use hardware to do this skinning - see the notes and the
// DirectX SDK skinned mesh sample for more details
void *srcPtr=0;
pMesh->MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&srcPtr);


void *destPtr=0;
pMesh->exSkinMesh->LockVertexBuffer(0, (void**)&destPtr);


// Update the skinned mesh
pMesh->pSkinInfo->UpdateSkinnedMesh(boneMatrices, NULL, srcPtr, destPtr);

// Note: bounds may have changed due to skinning! Need to recalc
D3DXVECTOR3 min,max;
D3DXComputeBoundingBox((D3DXVECTOR3*)destPtr,pMesh->exSkinMesh->GetNumVertices(),
D3DXGetFVFVertexSize(pMesh->exSkinMesh->GetFVF()),&min,&max);


// Unlock the meshes vertex buffers
pMesh->exSkinMesh->UnlockVertexBuffer();
pMesh->MeshData.pMesh->UnlockVertexBuffer();

// If we have more than one mesh
pMesh=(D3DXMESHCONTAINER_EXTENDED*)pMesh->pNextMeshContainer;
}

// If we have a sibling recurse
if (currentFrame->pFrameSibling != NULL)
UpdateSkinnedMesh(currentFrame->pFrameSibling);

// If we have a child recurse
if (currentFrame->pFrameFirstChild != NULL)
UpdateSkinnedMesh(currentFrame->pFrameFirstChild);
}

/**
* \brief Called to update the frame matrices in the hierarchy to reflect current animation stage
* \param frameBase - frame being looked at
* \param parentMatrix - the matrix of our parent (if we have one)
* \author Keith Ditchburn \date 18 July 2005

void UpdateFrameMatrices(const D3DXFRAME *frameBase, const D3DXMATRIX *parentMatrix)
{
D3DXFRAME_EXTENDED *currentFrame = (D3DXFRAME_EXTENDED*)frameBase;

// If parent matrix exists multiply our frame matrix by it
if (parentMatrix != NULL)
D3DXMatrixMultiply(&currentFrame->exCombinedTransformationMatrix, &currentFrame->TransformationMatrix, parentMatrix);
else
currentFrame->exCombinedTransformationMatrix = currentFrame->TransformationMatrix;

// If we have a sibling recurse
if (currentFrame->pFrameSibling != NULL)
UpdateFrameMatrices(currentFrame->pFrameSibling, parentMatrix);

// If we have a child recurse
if (currentFrame->pFrameFirstChild != NULL)
UpdateFrameMatrices(currentFrame->pFrameFirstChild, &currentFrame->exCombinedTransformationMatrix);
}
*/
void SetupBoneMatrices(D3DXFRAME_EXTENDED *pFrame)
{
// Cast to our extended structure first
D3DXMESHCONTAINER_EXTENDED* pMesh = (D3DXMESHCONTAINER_EXTENDED*)pFrame->pMeshContainer;

// If this frame has a mesh and there is skin info, then setup the bone matrices
// Note: handles multiple mesh (// Added 24/08/10
while(pMesh && pMesh->pSkinInfo)
{
// Create a copy of the mesh to skin into later
D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE];
if (FAILED(pMesh->MeshData.pMesh->GetDeclaration(Declaration)))
return;

pMesh->MeshData.pMesh->CloneMesh(D3DXMESH_MANAGED,
Declaration, d3dDevice,
&pMesh->exSkinMesh);

// Max bones is calculated for later use (to know how big to make the temp bone matrices array)
maxBones=max(maxBones,(UINT)pMesh->pSkinInfo->GetNumBones());

// For each bone work out its matrix
for (unsigned int i = 0; i < pMesh->pSkinInfo->GetNumBones(); i++)
{
// Find the frame containing the bone
// Must do this from root as skinned mesh and bone frame are not together
D3DXFRAME_EXTENDED* pTempFrame = (D3DXFRAME_EXTENDED*)D3DXFrameFind(pFrameRoot,
pMesh->pSkinInfo->GetBoneName(i));


// set the bone part - Note just point it at the transformation matrix of the relevant frame (aliase)
pMesh->exFrameCombinedMatrixPointer = &pTempFrame->exCombinedTransformationMatrix;
}

pMesh=(D3DXMESHCONTAINER_EXTENDED*)pMesh->pNextMeshContainer;
}

// Pass on to sibblings
if(pFrame->pFrameSibling)
SetupBoneMatrices((D3DXFRAME_EXTENDED*)pFrame->pFrameSibling);

// Pass on to children
if(pFrame->pFrameFirstChild)
SetupBoneMatrices((D3DXFRAME_EXTENDED*)pFrame->pFrameFirstChild);
}


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

void DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase)
{
// Cast to our extended frame type
D3DXFRAME_EXTENDED *frame = (D3DXFRAME_EXTENDED*)frameBase;

// Cast to our extended mesh container
D3DXMESHCONTAINER_EXTENDED *meshContainer = (D3DXMESHCONTAINER_EXTENDED*)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;
LPD3DXMESH pDrawMesh = (meshContainer->pSkinInfo) ? meshContainer->exSkinMesh: meshContainer->MeshData.pMesh;
// Finally Call the mesh draw function
pDrawMesh->DrawSubset(iMaterial);
}
}

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
}


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

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

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

detect_input();
Render();
}
cleanDInput();

return (int)msg.wParam;
}
Figured it out myself... It was actually fine :) The camera view distance wouldnt render the entire model. But why is Tiny so big??? (heh)

But also it's not loading her skin, its just a dark image of her body. Why is that?

This topic is closed to new replies.

Advertisement