Terrain based on Heightmaps





Step 1:
File > Add Project > XNA > Content Pipeline Extension Library

Step 2:
[ContentProcessor(DisplayName = "VikPro")]
public class ContentProcessor1 : ContentProcessor<TInput, TOutput>
TInput will be TextureContent and TOutput will be ModelContent

Step 3:
The Algorithm -
Create an instance of MeshBuilder by calling StartMesh.
MeshBuilder baseBuilder = MeshBuilder.StartMesh("Terrain");

Convert input type for ease of use. We can use it just like it is if we wanted to.
input.ConvertBitmapType(typeof(PixelBitmapContent<float>));
PixelBitmapContent<float> heightFields = (PixelBitmapContent<float>)input.Mipmaps[0];
Now GetPixel will return float values.

Add each pixel as point in the Mesh builder
for (int y = 0; y < heightFields.Height; y++)
{
    for (int x = 0; x < heightFields.Width; x++)
    {                   
         Vector3 tmp;
         tmp.X = xScale * (x - heightFields.Width / 2f);
         tmp.Z = yScale * (y- heightFields.Height / 2f);
         tmp.Y = heightScale * (heightFields.GetPixel(x, y) - 1);
         baseBuilder.CreatePosition(tmp);
    }
}

Create Material content and inform XNA that the vertices will have texture coordinates.
BasicMaterialContent material = new BasicMaterialContent();
material.SpecularColor = new Vector3(.4f, .4f, .4f);
baseBuilder.SetMaterial(material);

int texCoordId = baseBuilder.CreateVertexChannel<Vector2>(VertexChannelNames.TextureCoordinate(0));
Create Triangle based on the points we created.
for (int y = 0; y < heightFields.Height-1; y++)
{
    for (int x = 0; x < heightFields.Width-1; x++)
    {
         AddVertex(baseBuilder, texCoordId, heightFields.Width, x, y);
         AddVertex(baseBuilder, texCoordId, heightFields.Width, x+1, y);
         AddVertex(baseBuilder, texCoordId, heightFields.Width, x+1, y+1);

         AddVertex(baseBuilder, texCoordId, heightFields.Width, x, y);
         AddVertex(baseBuilder, texCoordId, heightFields.Width, x+1, y+1);
         AddVertex(baseBuilder, texCoordId, heightFields.Width, x, y+1);
    }
}








static void AddVertex(MeshBuilder builder, int texCoordId, int w, int x, int y)
{
    builder.SetVertexChannelData(texCoordId, new Vector2(x, y));
    builder.AddTriangleVertex(x + y * w);
}


Call FinishMesh to obtain MeshContent. Use context to convert to ModelContent(output)
MeshContent terrain = baseBuilder.FinishMesh();

Whats the fuss with ContentWriter and Reader?
Model.Tag can have any generic data (object). In case we want some custom information in to be stored for runtime use, add this to Model.Tag. If this data is custom class, then create Reader and Writer to store this information (like a custom Serializer/Deserializer)





Example: Really stupid useless one – Saving information like author, version, name, etc
Suppose I want to save this ModelTag class. I need a writer that will save this info in the XNB File.
public class ModelTag
{
    public string name;
    public string author;
    public string version;

    public ModelTag(string n, string a, string v)
    {
       name = n;
       author = a;
       version = v;
    }
}
   
The writer will be something like this-
[ContentTypeWriter]
public class TagWriter : ContentTypeWriter< ModelTag >
{
   protected override void Write(ContentWriter output, TWrite value)
   {
       output.Write(value.name);
       output.Write(value.author);
       output.Write(value.version);
   }
}

The reader will be like-
protected override TRead Read(ContentReader input, TRead existingInstance)
{
    string n= input.ReadString();
    string a= input.ReadString();
    string v=input.ReadString();

    ModelTag tmp = new ModelTag(n, a, v);
    return tmp;
}

In the Process function I’ll have -
model.Tag = new ModelTag("Terrain", "Vikram", "1.0.0.0");

A very nice and comprehensive sample can be found here at Creators Club.
In this example, find the Terrain Processor. They generate the normals of each tri and save this as Tag info. This can be pretty useful.


NFS: When assigning height values from the image, the Y co-or will get the height value and not the Z component. Otherwise, the terrain will be vertical and you'll end up messing it up using CreateRotation till you finally realize it. Stupid you.





XNA Draw Calls

I've been tampering with how to construct the world.

Base Idea:

Step I:
Create a cube.

StepII:
Save the details in an XML File like -

<Blocks>
  <Block X="0" Y="0" Z="0" Height="1" Color="R" />
  <Block X="0" Y="0" Z="120" Height="1" Color="R" />
  <Block X="80" Y="0" Z="240" Height="1" Color="R" />
  <Block X="0" Y="0" Z="240" Height="1" Color="R" />
  <Block X="160" Y="0" Z="360" Height="1" Color="R" />
  <Block X="80" Y="0" Z="360" Height="1" Color="R" />
  <Block X="240" Y="0" Z="480" Height="1" Color="R" />
  <Block X="160" Y="0" Z="480" Height="1" Color="R" />
  <Block X="240" Y="0" Z="600" Height="1" Color="R" />
  <Block X="240" Y="0" Z="720" Height="1" Color="R" />
  <Block X="240" Y="0" Z="840" Height="1" Color="R" />


Step III:
Create and add blocks based on this. Set scales and Draw

Problem:
The problem with this approach is
I: We'll need around 100 - 300 blocks
II: Call mesh.Draw( ) for each of these
III: mesh.Draw( ) is an expensive operation

Solution:
Use heightmaps to generate terrain.
Although it may have more [lot more] Polys - its still a single mesh. Hence, just one Draw call.

NFS: Always create a single or may be just a few meshes for the level. As per NProf, mesh.Draw will consume 90% more CPU as compared to setting params like World, View, Projection, etc

Final Ship Model

 Well.. The ship model is complete [more like I'm bored].
Final render follows. Looks pretty decent.. So its done.. whew! And a big no-no to texturing.
















Next up.. Terrain Stuff.
Note to Future Self: Im having fun

Few Renders

Have been a bit busy these days... Well here are some of the renders of the design.





Have to say.. pretty ugly from the back. Come to think about it, wings are useless when not flying.. ill try removing them..

Spaceship - Concept Art

Well - This is the concept I could come up with. Actually looks weird from the back, as opposed to what I had mind.. heck, think I can change that during modelling and make it look nice


How I Met Your Mothership - Intro

This series is going to track my first 3D game titled - 
How I Met Your Mothership!

This is going to be a remake(more like a fan game) of SkyRoads! Yup, the classic from Bluemoon Interactive. This was an awesome DOS game in which we drive through roads in space. May be I can spice it up after the base code is stable.

As with all good games - Let me come up with a story.

Story
Dad-Spaceship [to Kid-Spaceship(s)]:
Kids, let me tell you the story of how I met your mother-ship ( No points for guessing where I'm flicking this concept from! ). It was December of 2009. Your uncle BarnShip told me about this beautiful Spaceship who lived near Cigar Galaxy. I was tired of being single and too much of Uranium fuel made me decide to go see her.And Kids, at this point, I would like to tell you that Uranium is bad for your fuel tank.

So I set off on a journey to find this hot ship through the Cigar Galaxy. As you'll come to know later, this journey changed my life... This is where I met your Mothership.

[BG Music: ting ting ting ting ... naa na naa na nana na na naa..]

Kid-Spaceship: Duh..

OK, enough of crap. First off, the original SkyRoads was pseudo-3D (like the original Wolf3D). But here, I'll use actual 3D stuff. Means real models. So, my guess is it's going to be a lot easier than what those people at Bluemoon must have been through (cos XNA alerady has a framework for all this.. I'll just need to use it).

Time for some concept ART!

My First Post

They say that the "Journey of a thousand miles" begins with the first step.. Well here's my first.

Flashback:
This is how I ended up here..
Jul 1st 2008
Completed my Engineering in Computer Science. Got a high paying job
Sep 11th 2008
Training Complete. Bunked 2 weeks to hang out with my girl
Oct 1st 2008
After .NET Training they put me to work on PeopleSoft
Dec 25th 2008
I HATE ERP. Decided to save my 1 year pay and to quit in Aug 2009
Aug 14th 2009
Resigned. Free. Ah! The smell of freedom.
Sep to Nov 2009
Arghhh! The pain of listening to the crap everyone keeps telling me.
Nov 29 2009
Self-Realization. I AM AWESOME-O.

Present Status:
Well.. recession is starting to fade off I think. I've created some rough 2D games. Learnt some Action-scripting and XNA. Just yesterday - I completed a lot of reading about 3D stuff in XNA.

Today, the 29th of November - Is the day (ok, may-be) that is going to change my future. And No, I didn't meet myself from the future. Today is the day I finalized my decision about getting into Game-Dev forever.

Cons
I may end up failing.
I may not get the same pay for another 5 years even if I end up being a web-developer.
I may end up losing everyone I love. [I'll still have myself though]
I may have to start all over again as a fresher

Pros
I may end up following my dream

Ignorance is Bliss. I don't want to shove my dreams up my a** and spend the rest of my life in regret for not trying even once.

So here it goes..