The reason for this is that currently Irrlicht supports some scene formats but treats them as meshes, for example the collada and Quake 3 maps. There are community made scene loaders (ie 3D World Studio) with no way to cleanly add them. Also there are some cool scene formats which we could support in future (VRML/WRL, ASE, etc).
Another thing is that it would be an easy way to solve the SkinnedMesh issues. I'll explain a bit-
A skinned mesh (X, B3D, MS3D) can be several different things-
1) An animated character which uses joints for animation, the mesh buffers are deformed by the position of the joints.
2) A ragdoll or clothing mesh, which has joints but gets its animation from an external source. It contains no animation frames.
3) An animated character like 1 or 2, but with a static mesh attached to a joint. For example a weapon in hand. Deforming this static mesh by skinning is a waste of CPU cycles, the whole thing can be transformed instead*.
4) A static scene with no moving parts, but contains mesh sections for each sub-part. Because each sub-part loads onto a separate joint, it renders as lots of mesh buffers and has terrible performance*
5) A static scene (usually) with no animation frames. Sub-parts need to be loaded onto separate joints, so that you can animate doors, elevators etc.
* Because CSkinnedMeshBuffer has a transformation field which is not present in IMeshBuffer, it doesn't work with things which expect an IMeshBuffer (octtree, triangle selectors). This is interface breaking behaviour and means back-casting to SkinnedMeshBuffer.
1, 3 and 4 are the usual case, so these need to work without extra complexities. My idea for a solution here is to remove the transformation from CSkinnedMeshBuffer and skin the meshes by default, but if loaded using loadScene we load static buffers as an IMeshSceneNode attached to a bone nodes. So:
1, 2 and 4) Load using getMesh(), it returns an IAnimatedMesh and works as usual.
3) Use getMesh() if you don't mind skinning the mesh, or loadScene() if you want to be able to remove/swap the weapon/eyes etc.
5) Use loadScene() if you want to control the doors and platforms manually, otherwise use getMesh()
Finally, the interface for ISceneLoader will look like this-
Code: Select all
class ISceneLoader : public virtual IReferenceCounted
{
public:
//! Destructor
virtual ~ISceneLoader() {}
//! Returns true if the loader might be able to load this file.
/** This decision is based on the file extension (e.g. ".vrml")
\param fileName Name of the file to test.
\return True if the extension is a recognised type. */
virtual bool isALoadableFileExtension(const io::path& filename) const = 0;
//! Loads the scene into the scene manager.
/** \param file File which contains the scene.
\param rootNode The node to load the scene into, usually the root node.
\param userDataSerializer: If you want to load user data which may be attached
to some some scene nodes in the file, implement the ISceneUserDataSerializer
interface and provide it as parameter here. Otherwise, simply specify 0 as this
parameter.
\return Returns true on success, false on failure. */
virtual bool loadScene(io::IReadFile* file, ISceneNode* rootNode,
ISceneUserDataSerializer* userDataSerializer=0) = 0;
};