Creating terrains manually

In the Terrain (Heightmap) tutorial we used GB.Scene.TerrainSceneNode to create the terrain for us based on a heightmap. However, any surface can be used as the ground plane of a game. In this tutorial we will be creating a plane mesh and placing models on it. The following topics are covered in this tutorial:

  1. Creating a project
  2. Using GB.Scene.SceneManager.GeometryCreator

The tutorial's code files and media files are installed along with Ginjo-Builder and can be accessed from the 'Project' window that is shown when the editor starts. This tutorial is called '07_ManualTerrain' in the 'Tutorials' tab.

1. Creating a project

First we create a project and compiler options XML file. (See Render loop for a more detailed description of creating a project.)

  1. Create a new project through the Project menu.
  2. Right click on project's top level tree node named "New GBP(Unsaved)" and select Rename folder. Rename the folder to "BuildTerrain".
  3. Save the project as "Movement.gbp" from the Project menu.
  4. Add a new file to the project tree and save it as "ManualTerrain.gbc"
  5. Add a new file to the project tree and save it as "BuildTerrain.xml". (The XML file must have the same name as the top level tree node.)

Open "BuildTerrain.xml" and just like in Render loop add the <exe> and <startup> elements. We will also import the GB namespace so we don't have to type it out every time. (For the full list of XML tags see Compiler options.)

<?xml version="1.0" encoding="utf-8"?>
   <exe path=".\game.exe" />
   <startup name="ManualTerrain.main" />
      <namespace name="GB"  />

2. Using GB.Scene.SceneManager.GeometryCreator

In our XML file we specified the startup function as "ManualTerrain.main". Double-click on "ManualTerrain.gbc" in the project tree to open it, and create a "main" function with the Irrlicht engine initialization code and a render loop as in the first tutorial.

function main(var:string cmdArgs[]) returns Int32
   var:gb.IrrlichtCreationParameters options=new gb.IrrlichtCreationParameters()
   //Without anti-aliasing our model edges would be jagged 
   //Tell Irrlicht to use OpenGL for graphics
   //Turn off logging, we won't be using it for now
   var:gb.IrrlichtDevice engine = gb.IrrlichtDevice.CreateDevice(options)
   //Also set our window's title
   engine.SetWindowCaption('Building Terrains')
   var:video.VideoDriver driver=engine.VideoDriver
   var:Scene.SceneManager smgr=engine.SceneManager
   var:video.Color background=new video.Color(160, 160, 160)
   while (engine.Run()){
      driver.BeginScene(video.ClearBufferFlag.All, background)

Next we will create a plane mesh using GB.Scene.SceneManager.GeometryCreator and add it to the scene. A plane mesh consists of tiles that are repeated in the X and Z directions. The first parameter is the tile size, while the second is the tile count. We also set the Wireframe material flag to true so that we can see the terrain (we haven't specified a texture for the terrain yet.) We also add a Maya camera from the Cameras tutorial. Note that the camera is set to point slightly above the center of our plane mesh. Add the following code before the render loop:

var:scene.Mesh plane = smgr.GeometryCreator.CreatePlaneMesh(new core.Dimension2Df(20,20), new core.Dimension2Di(100,100))
var:scene.SceneNode terrain = smgr.AddMeshSceneNode(plane)
terrain.SetMaterialFlag(video.MaterialFlag.Lighting, false)
terrain.SetMaterialFlag(video.MaterialFlag.Wireframe, true)

//add camera
var:gb.scene.CameraSceneNode camera = smgr.AddCameraSceneNodeMaya()
camera.Position = terrain.BoundingBoxTransformed.Center + new core.Vector3Df(300)
camera.Target = terrain.BoundingBoxTransformed.Center + new core.Vector3Df(0,20,0)

We now remove the wireframe and replace the GeometryCreator.CreatePlaneMesh with GeometryCreator.CreateHillPlaneMesh, which creates a pseudo-random mesh representing a hilly terrain. We set the height of the generated hills to rather small, otherwise repeating pattern's may become recognizable in the hill plane mesh. We also add a model for a stone house:

var:video.Material mossTile=new video.Material()
mossTile.SetTexture(0, driver.GetTexture('..\media\mossGrass.jpg'))
//var:scene.Mesh plane=smgr.GeometryCreator.CreatePlaneMesh(new core.Dimension2Df(20,20), new core.Dimension2Di(100,100))
var:scene.Mesh plane=smgr.GeometryCreator.CreateHillPlaneMesh(new core.Dimension2Df(4,4), new core.Dimension2Di(100,100), mossTile, -1, new core.Dimension2Df(1,12), new core.Dimension2Df(6,6))
var:scene.SceneNode terrain=smgr.AddMeshSceneNode(plane)
terrain.SetMaterialFlag(video.MaterialFlag.Lighting, false)
//terrain.SetMaterialFlag(video.MaterialFlag.Wireframe, true)
var:scene.Mesh houseMesh=smgr.GetMesh('..\media\stonehouse.obj')
var:scene.MeshSceneNode house=smgr.AddMeshSceneNode(houseMesh)
house.Position=terrain.BoundingBoxTransformed.Center + new core.Vector3Df(-20,2,40)
house.Scale=new core.Vector3Df(10)
house.Rotation=new core.Vector3Df(0,155,0)
house.SetMaterialFlag(video.MaterialFlag.Lighting, false)

Note that you can use the IntelliDoc Symbol Info feature to look-up symbol types and definitions. The 'lightbulb' button on the toolbar looks-up the symbol type for the current cursor location and displays it in a tooltip. Pressing F1 also shows the tooltip.

Next we will create a wall next to the stone house by creating a thin rectangular mesh using GeometryCreator.CreateCubeMesh and applying a stone texture to that mesh. Note that in the code we also rescale the texture to an appropriate size. Add the following after the code for the stone house:

var:scene.Mesh wallMesh=smgr.GeometryCreator.CreateCubeMesh(new core.Vector3Df(0.6,12,100))
var:scene.MeshSceneNode wall=smgr.AddMeshSceneNode(wallMesh)
wall.Position=new core.Vector3Df(terrain.BoundingBoxTransformed.Center.X-30,6,terrain.BoundingBoxTransformed.Center.Z)
wall.SetMaterialFlag(, false)