Combining multiple .x files into a single .x file

Started by
28 comments, last by Steve_Segreto 10 years, 9 months ago

I have created multiple .x files, each one got different animation, example: "walk.x", "run.x", "die.x".

How do I combine them together to create "character.x"?

I tried using DirectX SDK tool called MeshView, but it's not working, I don't get to see the animations in the program.

I'm using Alin's DirectX Exporter for exporting .x file from 3Ds Max.

Advertisement

If you can get it the easy way with MeshView, you (might) need to use: ID3DXAnimationController::CloneAnimationController then RegisterAnimationSet then D3DXSaveHierarchyToFile.

I done it once this way but deleted the project long time ago since i don't use dx animation system anymore, so i will guess few steps here:

Load meshes with animations.

Clone and create new animation controller :


DWORD numAllAnimations = 0;
for i = numMeshes
    numAllAnimatios += mesh[i]->getAnimController()->GetNumAnimationSets();
 
// animCtrl is animation controller from first mesh, it doesn't matter much i just need starting point
LPD3DXANIMATIONCONTROLLER newController;
animCtrl->CloneAnimationController(
        animCtrl->GetMaxNumAnimationOutputs(),
        numAllAnimations,
        animCtrl->GetMaxNumTracks(),
        animCtrl->GetMaxNumEvents(), &newController);

Register each of their animation sets to new controller:


for i = numMeshes
    for j = mesh[i].numAnimationSet
        LPD3DXANIMATIONSET set;
        mesh[i]->getAnimController()->GetAnimationSet(j, &set);
        newController->RegisterAnimationSet(set);

then save your hierarchy to file:


D3DXSaveMeshHierarchyToFile("character_with_all_animations.x", D3DXF_FILEFORMAT_TEXT, &rootFrame, newController, 0);

That should be it.

Note that you should check all functions for failure!

EDIT:

You might want to skip registering first mesh animation sets as it is probably already included into new animation controller since we cloned it from.

You don't need to do this programmatically. You can do it from the command line or using a batch script.

Assuming all your X files are in text format, just trim all but one of the X Files on disk so that they only have "AnimationSets" in them. Leave one of the X files so it has the other skinned mesh pieces (like Frames and Meshes), now just use 'copy' from the command line to concatenate all the files into one.

e.g.

copy /A bugbear.x + bugbear_walk.x + bugbear_idle.x bugbear_all.x

This leaves a file bugbear_all.x that has the primary skinned mesh as well as the walk and idle animation sets. Unfortunately the copy command leaves a redundant EOF character at the end of the file, which you will have to remove somehow.

If it's BIP animations, then simply combine them in the 'Mixer' in Max (select root skeletal node and click on the Motion tab). I don't know if Alin's exporter supports multiple animations in one file, but Pandasoft's exporter most certainly does. Doing it this way means you don't have to post-combine them if you use the animations on another character.

******************************************************************************************
Youtube Channel

as i suspected, and as Steve's post confirms, you can put multiple animations in a single .x file. another way to do it is to use text format, and simply cut and paste them together using a text editor. double check your .xof file format description in the directx docs to make sure you get the syntax right. .x files tend to nest stuff using lots of "{ }'s " as i recall.


since i don't use dx animation system anymore

out of curiosity, what do you use now?

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


out of curiosity, what do you use now?

I am using my own mesh format and animation system, since i always wanted full control over things and i really hated dx a.s. guts.

It is working but not perfect yet (having some problems with transitions between animations... long story) but i am working really hard and i will resolve my issues.

Also i have created 3ds max utility plugin using their IGame interface, with which i was surprised how easy it was to use, to export animation (and other) data that i need.

Okay, trying to open and save .x file and the following code fail, getting D3DERR_INVALIDCALL when I call D3DXSaveMeshHierarchyToFile():

LPD3DXANIMATIONCONTROLLER animController;
hr = D3DXLoadMeshHierarchyFromX(filePath, D3DXMESH_MANAGED, device, 
memoryAllocator, NULL, &frameRoot, &animController);
assert(SUCCEEDED(hr)); // OK

hr = D3DXSaveMeshHierarchyToFile("character_with_all_animations.x", D3DXF_FILEFORMAT_TEXT, frameRoot, animController, NULL);
assert(SUCCEEDED(hr)); // <---- ERROR: Getting D3DERR_INVALIDCALL here

I have just tried the same thing, saving immediately after load function and it succeeded for me.

Enable dx debug runtime to examine any error logs you might have in output window. Do you know how?

@belfegor: Notice that "memoryAllocator" is associated with MeshHierarchy class.

I'm running debug mode and don't see any error message in the output window.

Here is main.cpp source code:


// main.cpp
#include "windows.h"
#include "d3d9.h"
#include "d3dx9.h"
#include "MeshHierarchy.h"
#include "assert.h"

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

LPDIRECT3DDEVICE9 device;
LPDIRECT3D9 d3d;

int main()
{
d3d = Direct3DCreate9(D3D9b_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.hDeviceWindow = GetConsoleWindow();
d3dpp.BackBufferCount = 1;

HRESULT hr;
hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetConsoleWindow(),
                       D3DCREATE_HARDWARE_VERTEXPROCESSING,
                       &d3dpp,
                       &device);
assert(SUCCEEDED(hr));

CMeshHierarchy *memoryAllocator = new CMeshHierarchy;

LPD3DXFRAME frameRoot;
LPD3DXANIMATIONCONTROLLER animController;
hr = D3DXLoadMeshHierarchyFromX("character.x", D3DXMESH_MANAGED, device, 
memoryAllocator, NULL, &frameRoot, &animController);
assert(SUCCEEDED(hr));

hr = D3DXSaveMeshHierarchyToFile("character_with_all_animations.x", D3DXF_FILEFORMAT_TEXT, frameRoot, animController, NULL);
if (hr == D3DERR_INVALIDCALL)
   MessageBox(NULL, "Invalid D3D Call", "Error", MB_ICONERROR | MB_OK);
assert(SUCCEEDED(hr));
}

You have not enabled DX debug runtime!

1. You need to link with debug dx lib: d3dx9d.lib (notice the d)

2. Set this at top of your cpp (before including any dx headers):

#define D3D_DEBUG_INFO          1

3. Set this options in dx control panel (dxcpl.exe), you can find it in DX SDK utilities folder:

dxcpl.jpg

4. Run your app with debugging and close it

5. Examine output window for DX error/warning logs

This topic is closed to new replies.

Advertisement