Creating Terrain In Code

The terrain system works by having separate terrain chunk objects that are lined up in a grid. These have a special type of body called a MeshGenStaticBody. This body is expected to be a mesh that is autogenerated somehow. In the case of terrain, it's generated by a HeightField. The HeightField? can contain a heightGenerator such as a NoiseHeightGenerator. If there is no heightGenerator, then the heights must be set manually. HeightFields? have a resolution and scale as well. The resolution determines how many height points are measured on the x and z axis respectively, and the scale modifies the size of the x, y, and z height points. So, a terrain with a resolution of (20, 20) and a scale of (100, 50, 100) would have 20 x 20 height data points and be 100 units wide, 100 units deep, and 50 * the tallest height high.

Using a NoiseHeightGenerator, the height points can be automatically generated based on PerlinNoise. The generator takes several parameters which should be familiar to anyone who has used perlin noise before. The most important of which is probably the seed, which is the random seed.

Example Code

# Create the object.
terrainID = yield area.newItem(self.position, ClassGenerator("mv3d.server.model.physical.BasicPhysicalObject"))
# Get the newly created  object
terrain = yield sim.getItem(terrainID)
# Set the name
terrain.setName(u"Ground%r" % (terrainID,))
# Create the height generator
hgen = NoiseHeightGenerator(offset=(0, 0.2, 0), seed=self.seed, multiplier=self.multiplier)
# Create the height field
hfield = HeightField(resolution=(20, 20), size=(100, 20, 100), heightGenerator=hgen)
# Create the body for the object.
mgsb = MeshGenStaticBody(meshGen=hfield)
# Add the visual object.
mgsb.addVisualObject(MeshGenVisualObject(meshGen=hfield, materialAssetId=assetId))
# Set the body for the object.
terrain.setBody(mgsb)

Adding Grass

grass = Grass((self.offset[0] * 1000 - (self.terrainWith * 500),
    self.offset[1] * 1000 - (self.terrainWith * 500),
    (self.offset[0] + 1) * 1000 - (self.terrainWith * 500),
    (self.offset[1] + 1) * 1000 - (self.terrainWith * 500)),
    hfield, maxDist=300)
grass.addLayer(self.assets.grass.getID(), density=0.3,
    bounds=grass.bounds,
    colorMapAssetId=self.assets.colormap.getID(),
    heightRange=(0.5, 100.0))
    mgsb.addVisualObject(grass)