Modelmanagement

Hi!

I am working on modelmanagement stuff. In my mind this can be a very complex topic, especialy when using different modelformats and different animationsystems.

Now the first question:
Is it better to convert other formats to a own one?

I have here sources from books and from the internet, which explain to load some fileformats like md2/3, ase, obj, milkshape and 3ds. But it is very very hard to put it all together in some basic classes and structs. Until now i have here a CMesh, CStaticMesh and some structs that can be found on www.gametutorials.com .
The other problem is that it is not easy to create a own and good meshformat.

The next “problem” is that it should be easy to use. If possible loading of different models and their animations in a same way, like:

CStaticMesh* Window = gMeshMng->Load(“Filename”, some flags);

Also i think that use all formats with a programm (no use of a conferter) will blow up the exe.

So i hope you can understand me and give me some possible solutions.

Thanks to all, Christian

It’s not in general possible to do the same things to all kinds of models, because some models lose too much data (say, md2 or md3, which are just vertex blended).

If there’s common functionality (say, “render” and maybe “render at animation frame X”) then that can be abstracted into an interface that the different concrete meshes all implement, and which you would be going through when talking to them.

Yes, adding more code to a program makes it bigger.

“render at animation frame X”

I’m not even sure you would want that, in the general case, at least. If you’re doing skinned character models with complicated physics, you don’t want your render function doing the animation. Instead, you want to run your animation loop, then your physics (depending on how complex this is, it may loop between them until no objects are interpenetrating), and lastly, feed that data into the rendering functions.

If you want your load time to be fairly low (or, if you’re doing dynamic loading of data), then you’re going to want to have all of the data in a game-usable format. That means that you should have, as a preprocessing step, converted all of your mesh and texture data into a format that can be quickly thrown up into the game and used without any complex conversion.

Korval,

If you read the context, you realize that I was suggesting a COMMON operation for all kinds of meshes that he’d like to load, such as the md2 meshes he suggested. If you want to deal with a lot of mesh formats in a uniform fashion, then there’s not a whole lot of specialization you can do. Not even “extract verts at time X” is necessarily a good idea, because that may only be known after the vertex program has been run (on the card) for some formats.

If you instead design your own mesh format, and support skinning, envelope deformation, and all that nice stuff, of course you’d rather want to separate all kinds of controllers from the “mesh” itself. But that was not the question.

@jwatte:

So do you think a onw fileformat would be the best solution? Or shall i make something like that:

// ase loading
CStaticAseMesh* Door = gMeshMng->Load(“door.ase”, ASE,…);

// 3ds loading
CAnimated3dsMesh* Women = gMeshMng->Load(“women.3ds”, 3DS,…);

Or do you know a good solution at this topic? Would be great.

Korval:
game-usable format - sounds logical, but to programm it is not so easy.

Six of one, half a dozen of the other. The important part is to isolate geometry management, mesh loading, and rendering into separate interfaces.

Exactly how your factory decides to call your ASE parsing code versus your .3ds parsing code versus your .md2 parsing code just don’t matter too much. I’d probably just do it by inspecting the data after it’s loaded, and dispatching to a suitable handler, or by dispatching to a suitable handler using the extension of the file.

Think:

class CMeshLoader :
public IMeshLoader {
vector< IMeshParser * > parsers;
public:
virtual void registerParser( IMeshParser * p ) {
parsers.push_back( p );
}
virtual IMesh * load( char const * path ) {
size_t size; void * data = fileData( path, &size );
if( !data ) {
return 0;
}
IMeshParser * p = findParserMatching( path, data, size );
if( !p ) {
error( “file %s is not a valid mesh”, path );
return 0;
}
return p->makeMesh( data, size );
}
};

You’d create concrete CMd2Parser, CMdlParser, CAseParser etc classes, all deriving from the IMeshParser interface (and thus implementing the “makeMesh()” and “recognizesData()” functions), and register them on the CMeshLoader at program start-up.

Bonus for making each of those concrete classes live in a DLL that gets loaded from a directory on start-up. Except, at that point, you might want to look into COM, and then you’ll go mad just trying to get the Best Possible Interface and never finish your code :slight_smile:

[This message has been edited by jwatte (edited 11-26-2002).]