Simplest way to create a 3D terrain?

Everything related to 3D programming
User avatar
paravantis
New User
New User
Posts: 4
Joined: Fri Jun 03, 2016 3:34 pm

Simplest way to create a 3D terrain?

Post by paravantis »

Although I am an old hand at programming, I struggle with 3D and I am somewhat ashamed to admit that I cannot create a simple 3D terrain.

I have read the documentation (help file) and have looked at the terrain.pb but I cannot create a working code from what I see there. I have also tried to replicate the terrain code of the Purebasic book (A Beginner's Guide to Computer Programming) but there are syntax changes that prevent me from making that code work (it seems to refer to an older version of Purebasic).

I need something very simple, even minimal: a terrain based on a heighmap jpg file, with a single texture layer. In my efforts, I call the following commands in the specified order (parameters etc. omitted)

Code: Select all

SetupTerrains
CreateTerrain
DefineTerrainTile
AddTerrainTexture
BuildTerrain
In particular, I am confused about the world size. How does that relate to the texture size and in what coordinates is it expressed?

I am also confused about the filename and extension required by the CreateTerrain command. Should they point to an existing heighmap file (I am guessing not) or to a file that will be created by the pb code as it runs? Or something else?

Finally, I am confused by the DefineTerrainTile command: what are the TileX and TileY indexes and how do they relate to the worldsize and the size of the texture (that will be used to paint the heighmap) in pixels?

Your help would be appreciated and, please, do forgive my ignorance.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Simplest way to create a 3D terrain?

Post by Samuel »

Welcome to the forums. :)

It's been a few years since I've worked with PB's terrain system, but I'll try to help.
In particular, I am confused about the world size. How does that relate to the texture size and in what coordinates is it expressed?
The world size is in units which can be treated as any type of unit of measurement (inches, feet, meters, etc).
I believe the texture size is how large the texture is in comparison to the terrain. With it you should be able to stretch or shrink the texture repetition. For example if you set the texture size to 1/4 the size of the world then that texture will be repeated 4 times across the world.
I am also confused about the filename and extension required by the CreateTerrain command.
I believe they are used to save the created terrain to a file. Which allows faster loading because terrain creation can be slow sometimes. Not positive on all the needed commands for saving/loading.
Finally, I am confused by the DefineTerrainTile command: what are the TileX and TileY indexes and how do they relate to the worldsize and the size of the texture (that will be used to paint the heighmap) in pixels?
I'm not really sure on this one too. :?


I think someone with more experience using PB's terrain system would be better at this because I don't think I'm of much use on this subject.


If you're interested I created a terrain generator that's (in my opinion) easier to use, but it doesn't have all the features Purebasic's has.
http://www.purebasic.fr/english/viewtop ... 36&t=59954
User avatar
paravantis
New User
New User
Posts: 4
Joined: Fri Jun 03, 2016 3:34 pm

Re: Simplest way to create a 3D terrain?

Post by paravantis »

Many thanks for your post Samuel! The explanations you provided were very helpful, Sir!

Turns out the key thing I was missing, that prevented my program from showing anything, was that the size parameter of the CreateTerrain command, should equal the size of the terrain plus 1, e.g. for a 512x512 terrain, it should equal 513! Although this is discussed in other posts in this forum, I had somehow missed it, and found it thanks to your post and the ideas you have me.

Will get back with any additional questions; I have a working program now and I may experiment.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Simplest way to create a 3D terrain?

Post by applePi »

Hi
look my experiments about terrain here http://purebasic.fr/english/viewtopic.php?f=36&t=60685
updated to PB 5.42.
I need something very simple, even minimal: a terrain based on a heighmap jpg file, with a single texture layer
many users are using mesh as a terrain, i suggest the simplest terrain is made from a plane mesh (CreatePlane) and its vertices deformed vertically according to height map picture. the interpretation of the color is the choice of the programmer. it is in fact a severe abstraction of the terrain generator by Samuel.
save this image as terrain.png to the same folder as the code
Image

Code: Select all

UsePNGImageDecoder()
UseJPEGImageDecoder()

Enumeration
  #Window
  #Camera
  #sphere
  #plane
         
EndEnumeration

Global Dim MeshData.PB_MeshVertex(0)

#CameraSpeed = 1

Declare Terrain()

Define.f KeyX, KeyY, MouseX, MouseY

If InitEngine3D()
  
  Add3DArchive(".", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "W wire/solid Frame ....mouse+arrow keys for the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 110, 140, #PB_Absolute)
    ;MoveCamera(#Camera, 0, 170, 20, #PB_Absolute)
    CameraLookAt(#Camera,0,0,0)
    CameraBackColor(#Camera, RGB(254,236,186)) ;RGB(200,155,40)
    
    CreateMaterial(1, LoadTexture(1, "Geebee2.bmp"))
    MaterialCullingMode(1, #PB_Material_NoCulling)
    
    CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
    ;CreateMaterial(0, LoadTexture(0, "white.jpg"))
    MaterialCullingMode(0, #PB_Material_NoCulling)
    
    CreateLight(0, RGB(255, 255, 255), 100, 100, 0)
    AmbientColor(RGB(100, 100, 100))
  
  EndIf
EndIf

Global TileCountX = 99, TileCountZ = 99 ; number of squares acroos x, and acroos z
Global Dim TerrainData.l(TileCountX, TileCountZ)
LoadImage(0, "terrain.png")
ResizeImage(0, TileCountX+1, TileCountZ+1)
StartDrawing(ImageOutput(0))
 For z=0 To TileCountZ
   For x=0 To TileCountX
   colr=Point(x,z)
     TerrainData(x,z)=Red(colr)
   Next
 Next
 StopDrawing()
 
 ;*******************************************

;CreatePlane(#Mesh, TileSizeX, TileSizeZ, TileCountX, TileCountZ, TextureRepeatCountX, TextureRepeatCountZ)
CreatePlane(#plane,100, 100, TileCountX, TileCountZ, 1,1)
CreateEntity(#plane,MeshID(#plane),MaterialID(0), 0, 0, 0)

;MaterialShadingMode(0, #PB_Material_Wireframe)
wireFrame = 1

Terrain()
CreateEntityBody(#plane, #PB_Entity_StaticBody ,1,1,1)
UpdateMeshBoundingBox(#plane)

WorldShadows(#PB_Shadow_Modulative) ;#PB_Shadow_Additive) 
CreateSphere(#sphere,3)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(1), 0,35,0)
CreateEntityBody(#sphere, #PB_Entity_ConvexHullBody  ,1,0.5,1)
WorldGravity(-20) ; the gravity here is twice the normal


Repeat
  Repeat 
  Until WindowEvent()=0
          
      If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
                
      If ExamineKeyboard()
           
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
                
        If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(0, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
            MaterialShadingMode(0, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
            
      EndIf
      DisableEntityBody(#plane, #False)
            
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      
      RotateEntity(#plane, 0,0.1,0, #PB_Relative)
      RenderWorld()
           
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End

  
 Procedure Terrain()

 GetMeshData(#plane,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal  , 0, MeshVertexCount(#plane)-1)
   
 c=0 : dist.f : u.f: v.f
 For y = 0 To TileCountZ
       For x = 0 To TileCountX
         height.f = TerrainData(x,y)/10
         MeshData(c)\y =  height 
         c+1
       Next
 Next 
     
   SetMeshData(#plane,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal, 0, MeshVertexCount(#plane)-1)     
   NormalizeMesh(#plane)
   UpdateMeshBoundingBox(#plane)
        
 EndProcedure
 
 
Last edited by applePi on Sun Jun 05, 2016 12:31 pm, edited 1 time in total.
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Simplest way to create a 3D terrain?

Post by Comtois »

paravantis wrote:Finally, I am confused by the DefineTerrainTile command: what are the TileX and TileY indexes and how do they relate to the worldsize and the size of the texture (that will be used to paint the heighmap) in pixels?
TileX and TileY are the coordinates of a terrain on a grid (TerrainGroup). there is no actual limit of how many terrains it can have.

Example with 3 terrains

Code: Select all

; It can take few minutes to build all terrains (it will be more faster after saving it)
MessageRequester("Warning !", "It can take a few minutes to build all terrains...", 0)

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

#CameraSpeed = 2


Define.f KeyX, KeyY, MouseX, MouseY
Declare InitBlendMaps()

; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default)
;
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
  Flags = #PB_Engine3D_EnableCG
CompilerEndIf

If InitEngine3D(Flags)
 
  InitSprite()
  InitKeyboard()
  InitMouse()
 
  If Screen3DRequester()
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/nvidia", #PB_3DArchive_FileSystem)
    Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/desert.zip", #PB_3DArchive_Zip)
   
    ;- Light
    ;
    light = CreateLight(#PB_Any ,RGB(190, 190, 190), 4000, 1200, 1000,#PB_Light_Directional)
    SetLightColor(light, #PB_Light_SpecularColor, RGB(255*0.4, 255*0.4,255*0.4))
    LightDirection(light ,0.55, -0.3, -0.75)
    AmbientColor(RGB(255*0.2, 255*0.2,255*0.2))
   
    ;- Camera
    ;
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0,  80, 40, 80, #PB_Absolute)
    CameraBackColor(0, RGB(5, 5, 10))
   
   
    ;- Terrain definition
    SetupTerrains(LightID(Light), 300, #PB_Terrain_NormalMapping)
    ; initialize terrain
    CreateTerrain(0, 513, 120, 4, 1, "TerrainGroup", "dat")
    ; set all texture will be use when terrrain will be constructed
    AddTerrainTexture(0,  0, 100, "dirt_grayrocky_diffusespecular.jpg",  "dirt_grayrocky_normalheight.jpg")

    ; Build terrains
    DefineTerrainTile(0, -1, -1, "terrain513.png", 0, 0) 
    DefineTerrainTile(0, 0, 0, "MRAMOR6X6.jpg", 0, 0) 
    DefineTerrainTile(0, 1, 1, "smoke.png", 0, 0) 
    BuildTerrain(0) 
      
    ; SkyBox
    ;
    SkyBox("desert07.jpg")
   
    Repeat
      Screen3DEvents()
     
      If ExamineKeyboard()       
       
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
       
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
       
      EndIf
     
      If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = -MouseDeltaY() * #CameraSpeed * 0.05
      EndIf
      MoveCamera(0, CameraX(0), TerrainHeight(0, CameraX(0), CameraZ(0)) + 20, CameraZ(0), #PB_Absolute)
      MoveCamera  (0, KeyX, 0, KeyY)
      RotateCamera(0,  MouseY, MouseX, 0, #PB_Relative) 
     
      RenderWorld()
      FlipBuffers()
     
    Until KeyboardPushed(#PB_Key_Escape)   
   
    End
   
  EndIf
Else
  CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL")
    ;
    ; Terrain on Linux/OSX and Windows with OpenGL needs CG toolkit from nvidia
    ; It can be freely downloaded and installed from this site: https://developer.nvidia.com/cg-toolkit-download
    ;
    MessageRequester("Error","Can't initialize engine3D (Please ensures than CG Toolkit from nvidia is correcly installed)")
  CompilerElse
    MessageRequester("Error","Can't initialize engine3D")
  CompilerEndIf
EndIf 
 
Please correct my english
http://purebasic.developpez.com/
User avatar
paravantis
New User
New User
Posts: 4
Joined: Fri Jun 03, 2016 3:34 pm

Re: Simplest way to create a 3D terrain?

Post by paravantis »

Awesome material gentlemen, thank you very much!

applePi, I did look at your post, and the text (although confusing at some points) was a great help. Thanks for pointing it out!

I shall be poring over the two programs you provided over the weekend and will get back if I have any further questions.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Simplest way to create a 3D terrain?

Post by applePi »

paravantis, the following is more natural and basic, i should posted it before, it depends on the official example MeshManualFlag.pb, look procedure DrawMatrix(). we just replace the height y.f = ... with y.f = red color value of the corresponding height map image (or whatever idea we choose)
note that it draw vertices one by one with MeshVertexPosition() in a sequence like this : (suppose 6X6 grid):
00- 01- 02- 03 -04 -05 -06
07 -08 -09 -10- 11 -12 -13
.....
every MeshVertexPosition() store internally an index number for the vertex from 0 to the end
with this index info we can later connect these vertices with triangles, in our case it is for the first 2 triangle:
MeshFace(7,1,0)
MeshFace(1,7,8)
note it is anti clockwise
look also this thread http://purebasic.fr/english/viewtopic.php?f=36&t=61396
note: the virtue of this way is that vertex 0 is in the upper left, while in native CreatePlane() it is in the Upper Right, we can see that by replacing terrain.png with purebasic.png, it is displayed here correctly while it is reversed with CreatePlane() :
Image

terrain.png
Image

Code: Select all

UsePNGImageDecoder()
UseJPEGImageDecoder()

Enumeration
  #Window
  #Camera
  #sphere
  #terrain
         
EndEnumeration

Global Dim MeshData.PB_MeshVertex(0)

#CameraSpeed = 1

Declare DrawMatrix()

Define.f KeyX, KeyY, MouseX, MouseY

If InitEngine3D()
  
  Add3DArchive(".", #PB_3DArchive_FileSystem)
  Add3DArchive(#PB_Compiler_Home + "examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
ExamineDesktops()
DesktopW = DesktopWidth(0)
DesktopH = DesktopHeight(0)

If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "W wire/solid Frame ....mouse+arrow keys for the camera ")
  If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
    
    CreateCamera(#Camera, 0, 0, 100, 100)
    MoveCamera(#Camera, 0, 110, 140, #PB_Absolute)
    CameraLookAt(#Camera,0,0,0)
    CameraBackColor(#Camera, RGB(254,236,186)) ;RGB(200,155,40)
    
    CreateMaterial(1, LoadTexture(1, "Geebee2.bmp"))
    MaterialCullingMode(1, #PB_Material_NoCulling)
    
    CreateMaterial(0, LoadTexture(0, "terrain_texture.jpg"))
    ;CreateMaterial(0, LoadTexture(0, "white.jpg"))
    MaterialCullingMode(0, #PB_Material_NoCulling)
    
    CreateLight(0, RGB(255, 255, 255), 100, 100, 0)
    AmbientColor(RGB(250, 250, 250))
  
  EndIf
EndIf
 
 ;*******************************************

DrawMatrix() ; call the terrain mesh building proc

wireFrame = 1

CreateEntityBody(#terrain, #PB_Entity_StaticBody ,1,1,1)
EntityRenderMode(#terrain, 0 ) ; to not casting shadow by hills and valleys since it is uggly
WorldShadows(#PB_Shadow_Modulative)

CreateSphere(#sphere,2)
CreateEntity(#sphere, MeshID(#sphere), MaterialID(1), 0,35,0)
CreateEntityBody(#sphere, #PB_Entity_ConvexHullBody  ,1,0.5,1)
WorldGravity(-20) ; the gravity here is twice the normal


Repeat
  Repeat 
  Until WindowEvent()=0
          
      If ExamineMouse()
        MouseX = -MouseDeltaX()/20 
        MouseY = -MouseDeltaY()/20
      EndIf
                
      If ExamineKeyboard()
           
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
                
        If KeyboardReleased(#PB_Key_W)
          If wireFrame
            MaterialShadingMode(0, #PB_Material_Wireframe)
          wireFrame ! 1
        Else 
            MaterialShadingMode(0, #PB_Material_Solid)
          wireFrame ! 1
        EndIf
        EndIf
            
      EndIf
      DisableEntityBody(#terrain, #False)
            
      RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera(#Camera, KeyX, 0, KeyY)
      
      RotateEntity(#terrain, 0,0.1,0, #PB_Relative)
      RenderWorld()
           
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
    
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
  
End


Procedure DrawMatrix()
#NbX = 100: #NbZ = 100 ; number of squares acroos x, and acroos z
Dim TerrainData.l(#NbX, #NbZ) ; to fill it with red color values of the height map image.
LoadImage(0, "terrain.png")
ResizeImage(0, #NbX+1, #NbZ+1) ; just for resizing images bigger than 100x100
StartDrawing(ImageOutput(0))
 For z=0 To #NbZ
   For x=0 To #NbX
   colr=Point(x,z)
     TerrainData(x,z)=Red(colr)
   Next
 Next
 StopDrawing()
 
 ; now building the terrain mesh
  CreateMesh(#terrain, #PB_Mesh_TriangleList, #PB_Mesh_Static)
  Protected.l a, b, Nb
  Protected.w P1, P2, P3, P4
  TileSize = 1 ; the size of every square in the grid, make it bigger for less squares number in #NbX, #NbZ
  ; as an example for #NbX=10: #NbZ=10 let TileSize = 10 to get the same visual terrain size as before
  For b=0 To #NbZ
    For a=0 To #NbX
      ;les coordonnées de vertex
      y.f = TerrainData(a,b)/10 ; divide by 10 is just a choice  
      MeshVertexPosition(TileSize*(a - #NbX/2), y, TileSize*(b - #NbZ/2) )
      MeshVertexNormal(0,1,0) 
      MeshVertexTextureCoordinate(a/#NbX, b/#NbZ)
    Next a
  Next b
    
  Nb=#NbX+1
  For b=0 To #NbZ-1
    For a=0 To #NbX-1
      P1=a+(b*Nb)
      P2=P1+1
      P3=a+(b+1)*Nb
      P4=P3+1
  
      MeshFace(P3, P2, P1) ; creating the triangle
      MeshFace(P2, P3, P4)
      ;so now every 2 triangle make a square 
    Next
  Next
  ; at the end we have made a big grid deformed up and down according to y in line 149
  FinishMesh(#True)
  UpdateMeshBoundingBox(#terrain)
  SetMeshMaterial(#terrain, MaterialID(0))
    
  CreateEntity(#terrain, MeshID(#terrain), #PB_Material_None)
  
EndProcedure  


Last edited by applePi on Mon Jun 06, 2016 10:27 am, edited 1 time in total.
User avatar
paravantis
New User
New User
Posts: 4
Joined: Fri Jun 03, 2016 3:34 pm

Re: Simplest way to create a 3D terrain?

Post by paravantis »

Thank you again applePi!

For the benefit of other visitors of this thread, for applePi's programs to compile without errors, the terrain.png file must be in the same directory as the program code.

Have a great week, everybody!
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Simplest way to create a 3D terrain?

Post by SeregaZ »

it is passilbe with your code make some kind of this images?

Image


i mean set some 2D map file and it will create some kind of on my image?

Image
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Simplest way to create a 3D terrain?

Post by applePi »

@SeregaZ , yes we can convert the image to terrain, by supposing one of its colors represent hight, it is a kind of taste or experimentation, if someone have more info please report. here i have rescale your 16_colors.png to 100x100 pixels, and makes it gray color and have smoothed it with irvanveiw, and then considered only its Red color component to represent the hight look procedure DrawMatrix() in the code below, remember the white color have red as one of its components. make more tests and research about what to represent the height ??!!.
and then we apply your original 16_colors.png as map.png to the whole terrain
save these pictures to same folder as your code
Image
Image

it is not obligatory to resize the 16_colors.png to 100x100 it is just for not making huge arrays. you can invent other ways
Edit: look https://en.wikipedia.org/wiki/Heightmap about the Height maps, it is not correct to change the colored map to gray to use as height map, i have done this for your picture because i don't have a height map for it, it is usually done by a radar on airplanes or satellites or surface surveying or by a game developer using height map designer ...

Code: Select all

    UsePNGImageDecoder()
    UseJPEGImageDecoder()

    Enumeration
      #Window
      #Camera
      #sphere
      #terrain
             
    EndEnumeration

    Global Dim MeshData.PB_MeshVertex(0)

    #CameraSpeed = 1

    Declare DrawMatrix()

    Define.f KeyX, KeyY, MouseX, MouseY

    If InitEngine3D()
     
      Add3DArchive(".", #PB_3DArchive_FileSystem)
      Add3DArchive(#PB_Compiler_Home + "examples/3D/Data/Textures", #PB_3DArchive_FileSystem)
     
      InitSprite()
      InitKeyboard()
      InitMouse()
     
    ExamineDesktops()
    DesktopW = DesktopWidth(0)
    DesktopH = DesktopHeight(0)

    If OpenWindow(#Window, 0, 0, DesktopW, DesktopH, "W wire/solid Frame ....mouse+arrow keys for the camera ")
      If OpenWindowedScreen(WindowID(#Window), 0, 0, DesktopW, DesktopH, 0, 0, 0)
       
        CreateCamera(#Camera, 0, 0, 100, 100)
        MoveCamera(#Camera, 0, 110, 140, #PB_Absolute)
        CameraLookAt(#Camera,0,0,0)
        CameraBackColor(#Camera, RGB(254,236,186)) ;RGB(200,155,40)
       
               
        CreateMaterial(0, LoadTexture(0, "map.png"))
        ;CreateMaterial(0, LoadTexture(0, "white.jpg"))
        MaterialCullingMode(0, #PB_Material_NoCulling)
       
        CreateLight(0, RGB(255, 255, 255), 100, 100, 0)
        AmbientColor(RGB(250, 250, 250))
     
      EndIf
    EndIf
     
     ;*******************************************

    DrawMatrix() ; call the terrain mesh building proc

    wireFrame = 1

    EntityRenderMode(#terrain, 0 ) ; to not casting shadow by hills and valleys since it is uggly
    WorldShadows(#PB_Shadow_Modulative)

    
    Repeat
      Repeat
      Until WindowEvent()=0
             
          If ExamineMouse()
            MouseX = -MouseDeltaX()/20
            MouseY = -MouseDeltaY()/20
          EndIf
                   
          If ExamineKeyboard()
               
            If KeyboardPushed(#PB_Key_Left)
              KeyX = -#CameraSpeed
            ElseIf KeyboardPushed(#PB_Key_Right)
              KeyX = #CameraSpeed
            Else
              KeyX = 0
            EndIf
           
            If KeyboardPushed(#PB_Key_Up)
              KeyY = -#CameraSpeed
            ElseIf KeyboardPushed(#PB_Key_Down)
              KeyY = #CameraSpeed
            Else
              KeyY = 0
            EndIf
                   
            If KeyboardReleased(#PB_Key_W)
              If wireFrame
                MaterialShadingMode(0, #PB_Material_Wireframe)
              wireFrame ! 1
            Else
                MaterialShadingMode(0, #PB_Material_Solid)
              wireFrame ! 1
            EndIf
            EndIf
               
          EndIf
          DisableEntityBody(#terrain, #False)
               
          RotateCamera(#Camera, MouseY, MouseX, 0, #PB_Relative)
          MoveCamera(#Camera, KeyX, 0, KeyY)
         
          RotateEntity(#terrain, 0,0.1,0, #PB_Relative)
          RenderWorld()
               
          FlipBuffers()
        Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
       
    Else
      MessageRequester("Error", "The 3D Engine can't be initialized",0)
    EndIf
     
    End


    Procedure DrawMatrix()
    #NbX = 100: #NbZ = 100 ; number of squares acroos x, and acroos z
    Dim TerrainData.l(#NbX, #NbZ) ; to fill it with red color values of the height map image.
    LoadImage(0, "16_colors.png")
    ResizeImage(0, #NbX+1, #NbZ+1) ; just for resizing images bigger than 100x100
    StartDrawing(ImageOutput(0))
     For z=0 To #NbZ
       For x=0 To #NbX
       colr=Point(x,z)
         TerrainData(x,z)=Red(colr)
       Next
     Next
     StopDrawing()
     
     ; now building the terrain mesh
      CreateMesh(#terrain, #PB_Mesh_TriangleList, #PB_Mesh_Static)
      Protected.l a, b, Nb
      Protected.w P1, P2, P3, P4
      TileSize = 1 ; the size of every square in the grid, make it bigger for less squares number in #NbX, #NbZ
      ; as an example for #NbX=10: #NbZ=10 let TileSize = 10 to get the same visual terrain size as before
      For b=0 To #NbZ
        For a=0 To #NbX
          ;les coordonnées de vertex
          y.f = TerrainData(a,b)/10 ; divide by 10 is just a choice 
          MeshVertexPosition(TileSize*(a - #NbX/2), y, TileSize*(b - #NbZ/2) )
          MeshVertexNormal(0,1,0)
          MeshVertexTextureCoordinate(a/#NbX, b/#NbZ)
        Next a
      Next b
       
      Nb=#NbX+1
      For b=0 To #NbZ-1
        For a=0 To #NbX-1
          P1=a+(b*Nb)
          P2=P1+1
          P3=a+(b+1)*Nb
          P4=P3+1
     
          MeshFace(P3, P2, P1) ; creating the triangle
          MeshFace(P2, P3, P4)
          ;so now every 2 triangle make a square
        Next
      Next
      ; at the end we have made a big grid deformed up and down according to y in line 149
      FinishMesh(#True)
      UpdateMeshBoundingBox(#terrain)
      SetMeshMaterial(#terrain, MaterialID(0))
       
      CreateEntity(#terrain, MeshID(#terrain), #PB_Material_None)
     
    EndProcedure 


look also at previous post about spherical terrains:
viewtopic.php?f=36&t=66817&p=496109
since some pictures there removed , this is the source code and the pictures for the spherical terrain :
http://s000.tinyupload.com/index.php?fi ... 9565912169

Image
SeregaZ
Enthusiast
Enthusiast
Posts: 617
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: Simplest way to create a 3D terrain?

Post by SeregaZ »

thanks. not many i am understand :) idea was - making some 3D image, set it at some special angle and make screenshot, then repaint it into 7 colors for making image closer to original, for users, who want to change default map in their romhack for that old game.

probably i will make 2 colors image and then convert it into 3D model, then by mouse over some area and use dragndrop make some mountains. then set angle, like original, then repaint into 7 colors. and probably image will looks like original.

it need to study that 3D part of PB. i thought PB cant create his own model, just can use another programm's model.
User avatar
Comtois
Addict
Addict
Posts: 1429
Joined: Tue Aug 19, 2003 11:36 am
Location: Doubs - France

Re: Simplest way to create a 3D terrain?

Post by Comtois »

I tested terrain.party "The easiest way to get real-world height maps", work fine with PB, the disadvantage is that it is limited to a maximum area of 60km.

Readme file

terrain.party README
====================
Hooray! You've exported some stuff from terrain.party v1.2!

If you should want to export this again for any reason:
http://terrain.party/api/export?name=ba ... ,47.715926

Now: what did you get?


Height Maps
-----------

* ballon Height Map (ASTER 30m).png

ASTER is the most recent public survey of elevation on Earth. It has high
coverage and high (~30m) resolution. However, the instrument can get
confused by high concentraions of clouds and mountains, creating gaps in
the data that need to be repaired by hand.
http://asterweb.jpl.nasa.gov/gdem.asp


* ballon Height Map (Merged).png

[!] If you look at one height map, look at this one. [!]

This is a mix of ASTER (~30m), USGS NED (~10m), and SRTM30+ (~900m). It
provides good global elevation data (ASTER) and better US elevation data
(USGS NED) with hole-filling and bathymetry from SRTM30+.


* ballon Height Map (SRTM3 v4.1).png

SRTM data was originally provided by the Shuttle Radar Topography Mission
but SRTM3 v4.1 is the result of considerable effort from CGIAR-CSI. It has
a ~30m resolution in the US and a ~90m resolution elsewhere.
http://www.cgiar-csi.org/data/srtm-90m- ... abase-v4-1


* ballon Height Map (SRTM30 Plus).png

SRTM30+ data is very, very coarse (~900m). This might be useful if you'd
like to follow the general contours of the land (and seafloor!) without
having every single contour. (But really, it's here because... why not?)
http://topex.ucsd.edu/WWW_html/srtm30_plus.html


Elevation Adjustment
--------------------

The original elevation models for this area contained elevations ranging from
369 through 1250 meters.

These elevation values need to get transformed into a grayscale images. This
section describes how that translation was done in this particular case.

(The game isn't yet released, so what follows is a guess, but I think it's a
pretty good guess. If this turns out to be wrong, please use the link above to
re-export this data once we figure out what the deal is.)

Cities: Skylines supports terrain from 0m to 1024m. It represents elevations as
16-bit unsigned integers, which can be read directly from 16-bit height maps.
Each level therefore corresponds to 1/64th of a meter: 0 is 0m, 64 is 1m, etc.
Cities: Skylines maps default to having sea level at 40m, with typical terrain
starting at 60m.

These heightmaps were adjusted such that 369m (actual) is equal to 40m in
game. All other elevations are relative to that.

Again, the lowest point in these height maps is now 40m in game; all other
terrain is even higher. You will likely want to adjust the water level as a
result.


Enjoy!
http://terrain.party/
Please correct my english
http://purebasic.developpez.com/
Post Reply