Updated Feb 23, 2005.
Realized that without skin weight information there is no way to tell what vertices attach to what bones, I do know what bone is attached to my head though (it's the bone head...).
Updated Feb 20, 2005.
Back from the grave, this project has been updated, and now supports most of the .x file format. This loader will ignore any section of a .x file it doesn't recognize. No support for custom templates is planned, I don't see much reward for the amount of effort required for that.
xloader.jar (includes source) 28k
No demo available at this time, I will probably provide some documentation about the structure of the data at some point, as well as a JME (Java Monkey Engine) example. The Loader.java file contains commented out source that is partially working jme example, a bad example but still may be useful to someone. XModelData is the top level of the data, followed by Frames and AnimationSets. A frame can contain multiple sub-frames (which may also contain subframes), multiple meshes, etc. It's recommended that for static models you recurse through all frames and combine all the mesh information into a single mesh for ease of use. Each frame typically represents a 'bone' which is why you may have a lot of sub-frames to deal with.
Discussion of this code at javagaming.org
What is supported now.
Models can contain multiple frames containing multiple meshes.
Vertex Data and Face Data.
Normal Data and Face Data.
Vertex Colors (not used in the demo).
Materials and texture file names.
Inlined materials, and meshes are supported. It's easy to ad support for inlining other parts of the .x file if needed.
Animation data is read in for AnimationSet, Animation and AnimationKey, SkinWeights, XMeshHeader, etc.
AnimationOptions are ignored as they seem to be specific to directx.
The parser operates on the assumption that files will not be corrupted, that formatting will be correct, and basically a small problem with the structure of a .x file could cause a model to load partially. If an error is encountered, the loader attempts to ignore it and continue on with the next segment. Exceptions shouldn't be thrown. The output data method in the Loader may throw null pointer exceptions if a file doesn't load correctly, this method is intended for debugging only though.