Here's my situation: I want to create a text file describing terrain attributes, like heightmap file (raw or an image format), colormap, detailmap and splatting maps. Only the heightmap file and format will be required in this file, so the colormap, detailmap and splatting maps are optional. I then want to add this file to my XNA game project and have it pack a .xnb file containing this data. Ideally, when I do this in my game's LoadContent method:
Terrain t = contentManager.Load<Terrain>(@"Content\Terrain\Test");
I should get the terrain object back ready to use, with whatever options I set in it. I couldn't get custom importers and processors to work, so I'll come back to that later, but I did get XmlImporter working with my custom ContentPipeline writer and reader objects working. I had a few problems though:
1) Every property not marked as [SerializerIgnore] must be specified (request: it might be useful to consider a [SerializerOptional] attribute).
2) In the Xml file, the terrain media files are specified as paths, but I want them to be ExternalReference in the .xnb file, how do I do this
3) Let's say I have a folder 'Content\Terrain\' with a heightmap.bmp, colormap.bmp and test.xml. The Xml file looks like this:
< xml version="1.0">
<XnaContent>
<Asset Type="MyGame.Terrain">
<Heightmap>heightmap.bmp</Heightmap>
<Colormap>colormap.bmp</Colormap>
</Asset>
</XnaContent>
</xml>
In my custom writer, if I write the heightmap and colormap as ExternalReference<Texture2D> I get an exception saying absolute paths must be specified. Does that mean I have to specify the entire path to each file in the Xml file And if so, when I get the files back to I have to specify that absolute path again to get the textures It seems like that approach could cause media problems when I deploy the game to another machine or an Xbox360.
By the way: Nice job on the ContentPipeline, it looks like this will be a useful tool once people understand it better and write more tutorials for it.

Creating a terrain using ContentPipeline and XmlImporter (or a custom importer / processor)
AlexBB
Pooja Katiyar
Wayne Sepega
rajshekar
luca82
To use ExternalReference, you will need a custom processor to build those references. Typically you'd want something like:
In a custom processor:
string absoluteFilename = Path.GetFullPath(relativeFilename);
ExternalReference<TextureContent> reference = new ExternalReference<TextureContent>(absoluteFilename);
// build the texture (this will do all the appropriate incremental rebuild checks)
ExternalReference<TextureContent> builtTexture = context.BuildAsset<TextureContent, TextureContent>(reference, "ModelTextureProcessor");
// now store the builtTexture reference somewhere: this points to the output XNB file produced by building the texture
In your ContentTypeWriter:
In your ContentTypeReader:
The thing to note is that the external reference you write out needs to point to the result of building the texture, rather than to the original source texture file. That being so, you can then read it directly into a runtime Texture object.
Juvefan
You don't need to store absolute paths in your terrain description file, store relative paths and make them absolute (relative to your terrain description file) when you want to create the external references. I've done this before by storing the path of the description file in the object that the custom importer creates - I don't know exactly how you would do that if you are only using the XmlImporter, perhaps you might want to look into getting custom importers working.
Cheers,
Leaf.