Making a terrain using L3DT

From Leadwerks Developer Wiki

Jump to: navigation, search

Contents

Introduction

This tutorial will show how to make a terrain suitable for Leadwerks Engine
using the free L3DT Large 3D Terrain Generator tool.

Install L3DT

L3DT is terrain creation tool which can be downloaded for free
from http://www.bundysoft.com/L3DT/downloads

After you've downloaded and installed terragen,
Start the program and this is what you should get.

Image:Terr1.PNG

Background

In Leadwerks Engine there are several ways to present a terrain. In this
tutorial we will concentrate on using a height-map together with an alpha-map
where the RGB and Alpha values defines where 4 layers of texture should be painted.

So we need

  • A heightmap
  • An RGBA alphamap
  • 4 textures including normalmapping, one for each layer

L3DT materials

If you bring up the Material Manager you will find a list of different
materials. Here is the place to add your own materials.

Image:Terr2.PNG

Each material consist of one or more diffuse textures together with it's normal map.
So if you want to use your own textures while working with L3DT this is the place
to either edit an existing material or create a new one.

For this tutorial we will use existing materials though.

L3DT Climates

You may assign different climates to a terrain in L3DT. A Climate is a collection
of Land Types together with settings telling where each Land Type will be painted on the terrain.

A Land Type is a collection of one or several Materials.

If you bring up the 'Climate Manager' you can see all Climates. This is the place to
create your own climates or edit existing ones.

Image:Terr3.PNG

As we only want 4 land types (Leadwerks support of Alphamap layers permits 4 layers) we will
make an new climate to be sure that we only use 4 Land Types and 4 textures.

Fortunately there is already a climate that has exactly 4 Land Types. We can copy that climate
to get a start. In the Climate Manager, copy the climate 'Spring Mars (FA)' and give the copy
some nice name as 'Leadwerks tutorial' or whatever.

Good. Now we have a climate with exactly 4 land types. One Land Type for each Alpha-map channel
Red, Green and Blue channels and one for the transparency channel.

We don't need to bother about which textures the climate uses. The important thing is that
is uses 4 land types.

One important thing we must do is to set the color for each land type. For each land type, double
click and in the 'General' tab change the color

  • Make 'Flatland' red
  • Make 'Rocky ground' green
  • Make 'Rock slope' blue
  • Make 'Cliff face' black

That's all that we need for getting a correct Alpha-map out from our terrain.

Generate the terrain

Time to create a terrain. Click on new map and select 'Design/inflate' which will
produce a random terrain (If you want to build from scratch select Design/inflate (blank)).

Image:Terr5.PNG

  • Set X = Y = 16
  • Horiz. scale(m) = 1

This will give a reasonable big terrain. Feel free to text other combinations.

In next dialog please select our new climate 'Leadwerks tutorial' as Default climate.
Change any other parameters at your desire. For this tutorial I left them at their default positions

Image:Terr6.PNG

Next dialog is the 'Calculation queue'. Mark all check-boxes.

Image:Terr7.PNG

Water flooding

I desired to have a water level at 0. Test with other settings.

Image:Terr8.PNG

Then I left the Water-table modeling values at their default values.

Attributes

Image:Terr9.PNG

Nothing much to add here. Accept and go on.

Normal mapping

Image:Terr10.PNG

Same here. Accept and go on.

Light mapping

Image:Terr11.PNG

Here you may chane the sun direction and elevation. You may also draw the Sun/ambient ratio slider to the left to get softer shadows.

Image:Terr12.PNG

Here I prefer to disable water effect or else the water tends to be to blue.

Image:Terr13.PNG

You can leave the texture settings as they are as we are not going to use the
produced terrain texture image anyway.

Next just sit down and watch L3DT working.

L3DT output

L3DT produces a bunch of maps. We are going to use 3 of them. </div>

Heightfield

Image:Terr14.PNG

This is our heightmap. Let's export it. Press Ctrl+E and select PNG as File format and save as 'terrain_hm.png'
in your application directory or somewhere else where you keep you stuff.

Attributes map

Image:Terr15.PNG

This is our alpha-map. Save it as 'terrain_am.png'.
Before saving click on Options, then double click on
'ColourMapped(bool)' so it becomes true.

Terrain Normals

Image:Terr16.JPG

This is our normal-map. Save it as 'terraindot3.png'

Save

This concludes what's needed in L3DT. Save your work and close L3DT.


Implementing the terrain using LEO

To check how the terrain looks we must write an application to show it.
This application shows the terrain, has a sky (see my Making a sky using Terragen tutorial)
and a spectator that can walk around in the terrain.

Using Visual Studio create a new Win32 Console empty project and give it some nice name.
Add the leo.cpp file to the project and also in Additional Include Directories enter the
path to your CPP directorys.

Add a new file Test.cpp to the project and copy following code to that file.

You can also check LEO - Visual Studio 2008 Setup for instructions on how to create a LEO project with Visual Studio

This code is for LE 2.23

#include "leo.h"
using namespace LEO ;
#pragma warning( disable : 4996 )
 
//  === PROGRAM ENTRY ====
int main(int argc, char **argv)
{
    const float HEIGHT_SCALE = 132 ;
    const float SPECTATOR_LENGTH = 1.8f ;
    #define START_X 64
    #define START_Z 64
 
    bool debugPhysics = false ;
    bool debugGravity = false ;
 
    // ================== INIT ====================
    Engine engine( "LEO testing terrain",800,600);
    Engine::SetFilters();
 
    // ================== WORLD ====================
    // create and init world
    World world( CREATENOW ) ;
    world.Set();
    World::SetCollisions(1,1) ;
    World::SetAmbientLight( Vec3(0) );
 
    // ================== TERRAIN =================
    Terrain	terrain( 1024 );
    terrain.SetType( SLIDINGCOLLISION);
    terrain.SetScale( Vec3(1,HEIGHT_SCALE,1) );
 
    terrain.LoadHeightmap( "abstract::terrain_hm.raw"  );
    terrain.LoadAlphamap ( "abstract::terrain_am.dds"  );
 
    terrain.SetTexture( Texture("abstract::grass.dds") , 0, 0 ) ;
    terrain.SetTexture( Texture("abstract::grassdot3.dds") , 1, 0 ) ;
    terrain.SetTextureMappingMode( HORIZONTAL, 0 ) ;
    terrain.SetTextureScale( 12, 0 ) ;
 
    terrain.SetTexture( Texture("abstract::stone.dds") , 0, 1 ) ;
    terrain.SetTexture( Texture("abstract::stonedot3.dds") , 1, 1 ) ;
    terrain.SetTextureMappingMode( HORIZONTAL, 1 ) ;
    terrain.SetTextureScale( 12, 1 ) ;
 
    terrain.SetTexture( Texture("abstract::dirt.dds") , 0, 2 ) ;
    terrain.SetTexture( Texture("abstract::dirtdot3.dds") , 1, 2 ) ;
    terrain.SetTextureMappingMode( HORIZONTAL, 2 ) ;
    terrain.SetTextureScale( 6, 2 ) ;
 
    terrain.SetTexture( Texture("abstract::mud.dds") , 0, 3 ) ;
    terrain.SetTexture( Texture("abstract::muddot3.dds") , 1, 3 ) ;
    terrain.SetTextureMappingMode( HORIZONTAL, 3 ) ;
    terrain.SetTextureScale( 14, 3 ) ;
 
 
    terrain.UpdateNormals() ;
 
    // ================== SKY =====================
    // create and init sky
    World       sky( CREATENOW )  ;
    Material    skymat( "abstract::sky.mat" );
    Cube        skybox( CREATENOW ) ;
    skybox.Flip() ;
    skybox.Paint( skymat );
    skybox.SetPosition( Vec3(0) ) ;
    skybox.SetScale( Vec3(100) ) ;
 
    // create and init camera for sky
    Camera skycam( CREATENOW ) ;
    skycam.SetClearMode( BUFFER_DEPTH);
 
    // light
    sky.Set() ;
    World::SetAmbientLight( Vec3(1) );
 
    // ================== SPECTATOR ================
    // create a spectactor
    world.Set();
 
    BodySphere spec(1);
    spec.SetGravityMode(false);
    spec.SetMass(1) ;
    spec.SetDamping(1,0);
 
    spec.SetType( SLIDINGCOLLISION );
    spec.SetSweptCollision();
 
    // inital position ;
    TVec3	specposition = Vec3( START_X,
                               terrain.GetElevation(START_X, START_Z)+4*SPECTATOR_LENGTH,
                               START_Z );
    TVec3	specforce = Vec3(0) ;
    spec.SetPosition( specposition ) ;
 
    // ================== CAMERA ================
    // create and init camera for world
    Camera cam( CREATENOW ) ;
    cam.SetClearMode( BUFFER_DEPTH );
    cam.SetRange(0.1f,1000);
 
 
    flt     camspeed = 10.0f;
    TVec3	camrotation = Vec3(0) ;
    TVec3	camposition = specposition ;
    cam.SetPosition( camposition );
    cam.SetRotation( camrotation );
 
    // ================== MOUSE ================
    flt mx=0.0f, my=0.0f;
    int SX = Engine::GetWidth();
    int SY = Engine::GetHeight();
    int CX = SX/2;
    int CY = SY/2;
    Mouse::Hide();
    Mouse::Move(CX,CY);
 
    // ================== LIGHT =====================
    DirectionalLight dirLight(CREATENOW) ;
    flt lightRotX = 0 ;
 
    dirLight.SetRotation( lightRotX, 0, 0 );
 
    // ================== GO! ================
    // keep on until user hits ESC or terminates the window
    while ( !Keyboard::IsHit() && !Engine::IsTerminated())
    {
        if ( !Engine::IsSuspended() )
        {
            // --- Keyboard ---
            if ( Keyboard::IsHit(KEY_P)) Engine::SetDebugPhysics(debugPhysics=!debugPhysics);
            if ( Keyboard::IsHit(KEY_G)) spec.SetGravityMode (debugGravity=!debugGravity);
 
            // --- Mouse ---
            mx=Curve( static_cast<flt>(Mouse::GetX()-CX),mx,4.0f/Engine::GetSpeed());
            my=Curve( static_cast<flt>(Mouse::GetY()-CY),my,4.0f/Engine::GetSpeed());
            Mouse::Move(CX,CY);
 
            // --- Camera ---
            camrotation = cam.GetRotation() ;
            camrotation.X += my*0.25f;
            camrotation.Y -= mx*0.25f;
            cam.SetRotation( camrotation );
 
            // --- Spectator ---
            specforce = Vec3( (Keyboard::IsDown(KEY_D)-Keyboard::IsDown(KEY_A))*camspeed*Engine::GetSpeed(),
                              (Keyboard::IsDown(KEY_Q)-Keyboard::IsDown(KEY_E))*camspeed*Engine::GetSpeed(),
                              (Keyboard::IsDown(KEY_W)-Keyboard::IsDown(KEY_S))*camspeed*Engine::GetSpeed());
 
            specforce = TFormVector( specforce, cam, 0 ) ;
            spec.AddForce( specforce, GLOBAL );
 
            specposition = spec.GetPosition(GLOBAL);
            camposition  = cam.GetPosition();
            cam.SetPosition(Vec3(
                                Curve(specposition.X,camposition.X,4.0f/Engine::GetSpeed()),
                                Curve(specposition.Y,camposition.Y,4.0f/Engine::GetSpeed()),
                                Curve(specposition.Z,camposition.Z,4.0f/Engine::GetSpeed())));
 
            // --- Sky ---
            // rotate sky camera in same direction as main camera and render sky
            skycam.SetRotation( camrotation );
            sky.Set();
            World::Render();
 
            // --- World ---
            // Render world
            world.Set();
            World::Update();
            World::Render();
 
            //	--- Some screen info
            Draw::Text( 0, 0,  "FPS %f", Engine::GetFPS()) ;
            Draw::Text( 0, 20, "%d polys", Engine::GetTrisRendered());
            Draw::Text( 0, 40, "Position %0.2f %0.2f %0.2f",  specposition.X,
                        specposition.Y,
                        specposition.Z);
            Draw::Text( 0, 60, "P = Debug physics" ) ;
            Draw::Text( 0, 80, "G = Enable gravity" ) ;
 
 
            // --- Update screen ---
            Engine::Flip();
        }
    }
 
    // ================== DONE! =============
    return engine.Free();
}

Before compiling be sure to set Linker Output File to the same directory as where your
terrain images are. You also needs the Shader directory copied there, or
at least the 'skybox.frag', 'skybox.vert', 'terrain.vert' and 'terrain.frag'

Compile and check that you have no errors.
Before running you must set the Debugging Working Directory to $(TargetDir), at least
if you are going to run the program from Visual Studio.

Go ahead and run the program by hitting Ctrl+F5.
The result should look something like this if you used my textures.

Image:Terr17.JPG

Image:Terr18.JPG

Textures

If you want to use my textures you can get them here

Image:Dirt.JPG Image:Dirtdot3.JPG

Image:Grass.JPG Image:Grassdot3.JPG

Image:Mud.JPG Image:Muddot3.JPG

Image:Stone.JPG Image:Stonedot3.JPG


Thanks for your time and good luck.

--Rstralberg 07:54, 9 July 2008 (MST)

Personal tools