Page 1 sur 1

[4.60] Remplacer temporairement CreateTerrain

Publié : jeu. 10/nov./2011 12:37
par kelebrindae
Sault à tous,

Pour remplacer la commande "CreateTerrain" (en attendant qu'elle soit réparée en v4.61 :wink:) , je me suis rapidement bricolé ce matin une procédure "MyCreateTerrain", que vous trouverez dans l'exemple ci-dessous.
Rien de révolutionnaire, mais ça peut dépanner, et puis ça m'a permis de voir comment fonctionne le nouveau "CreateMesh" (conclusion: il marche bien :mrgreen: ).

Code : Tout sélectionner

; ---------------------------------------------------------------------------------------------------------------
; Author: Kelebrindae
; Date: November,10,2011
; PB version: v4.60
; 
;  Temporary replacement for the "CreateTerrain" command (broken in PB v4.60)
; ---------------------------------------------------------------------------------------------------------------
; NB: Don't exceed 255x255 terrains, because the max vertices number in an Ogre mesh is 652235 !
; ---------------------------------------------------------------------------------------------------------------

EnableExplicit
;************************************************************************************
; Name: myCreateTerrain
; Purpose: Create a terrain mesh
; Parameters:
;   - name of the heightmap
;   - terrain size X
;   - terrain size Y
;   - maximum height (= height of the white points in the heightmap)
;   - numbers of cols in the mesh
;   - numbers of rows in the mesh
; Return-Value: mesh number
;************************************************************************************
Procedure.i MyCreateTerrain(heightmap.s,sizeX.f,sizeZ.f,maxHeight.f,nbCols.i,nbRows.i)
  Protected numImage.i,imSizeX.f,imSizeY.f, height.i
  Protected numMesh.i,i.i,j.i
  Protected v0.i,v1.i,v2.i,v3.i
  Protected cellSizeX.f, cellSizeZ.f,scaleY.f
  
  ; Load the heightmap
  numImage = LoadImage(#PB_Any,heightmap)
  If IsImage(numImage) = #False
    ProcedureReturn 0
  EndIf
  imSizeX = ImageWidth(numImage) - 1
  imSizeY = ImageHeight(numImage) - 1
  
  ; Create the mesh
  numMesh = CreateMesh(#PB_Any)
  cellSizeX = sizeX  / nbCols
  cellSizeZ = sizeZ  / nbRows
  scaleY = maxHeight / 255.0
  
  ; Create the vertices, according to heightmap values
  StartDrawing(ImageOutput(numImage))
  For j = 0 To nbCols
    For i = 0 To nbRows
      height = Red( Point(i * (imSizeX/nbCols) , j * (imSizeY/nbRows) ) )
      
      AddMeshVertex(i*cellSizeX,scaleY * height,j*cellSizeZ)
      MeshVertexColor($FFFFFF)
      MeshVertexTextureCoordinate( i * (1 / nbCols),j * (1 / nbRows) )
    Next i
  Next j
  StopDrawing()
  FreeImage(numImage)
  
  ; Create the faces
  For j=0 To nbRows - 1
    For i = 0 To nbCols - 1
      v0 = i + j*(nbRows + 1)
      v1 = i + j*(nbRows + 1) + 1
      v2 = i + (j+1)*(nbRows + 1)
      v3 = i + (j+1)*(nbRows + 1) + 1
      
      AddMeshFace(v0, v2, v3 ) 
      AddMeshFace(v0, v3, v1 )
    Next i
  Next j
  
  ; Finih and compute the normals
  FinishMesh()
  NormalizeMesh(numMesh)
  
  ProcedureReturn numMesh
EndProcedure
DisableExplicit

;- Initialization
Global FullScreen.b
Resultat = MessageRequester("Create terrain","Full Screen ?",#PB_MessageRequester_YesNo)
If Resultat = 6     
  FullScreen=#True
Else           
  FullScreen=#False
EndIf

If InitEngine3D() = 0
  MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
  End
EndIf

If Fullscreen = #True
  OpenScreen(1024,768,32,"Custom Terrain",#PB_Screen_SmartSynchronization)
Else
  OpenWindow(0,0, 0, 800 , 500 ,"Custom Terrain")
  OpenWindowedScreen(WindowID(0),0,0, 800, 500,0,0,0,#PB_Screen_SmartSynchronization)
EndIf

;- Terrain texture
CreateTexture(0,64,64)
StartDrawing(TextureOutput(0))
  Box(0,0,64,64,$FFFFFF)
StopDrawing()

CreateMaterial(2,TextureID(0))
MaterialAmbientColor(2, #PB_Material_AmbientColors)

;- Terrain mesh
UsePNGImageDecoder()
UseJPEGImageDecoder()
heightmap.s = OpenFileRequester("Choisissez une Heightmap","","Images|*.png;*.bmp;*.jpg;*.jpeg",0)
If heightmap = ""
  End
EndIf
numMesh = MyCreateTerrain(heightmap,500,500,50,250,250)

;- Terrain entity
CreateEntity(0,MeshID(numMesh),MaterialID(2))
EntityLocate(0,-50,0,-50)

;- Light
AmbientColor(0)
CreateLight(0,$FFFFFF, 0,500,500)

;- Camera
CreateCamera(0, 0, 0, 100, 100)
CameraBackColor(0,$FF7755)
CameraLocate(0, 400,100,500)
CameraLookAt(0,250,0,250)
#CameraSpeed = 1

;- Main loop
Repeat
  While WindowEvent()
    Delay(1)
  Wend

  If ExamineMouse()
    MouseX = -(MouseDeltaX()/10)*#CameraSpeed
    MouseY = -(MouseDeltaY()/10)*#CameraSpeed
  EndIf
 
  RotateCamera(0, MouseY, MouseX, RollZ, #PB_Relative)
  If ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Up)
      MoveCamera  (0, 0, 0, -#CameraSpeed)
    EndIf
    If KeyboardPushed(#PB_Key_Down)
      MoveCamera  (0, 0, 0, #CameraSpeed)
    EndIf
  EndIf
  
  RenderWorld()    
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1

Vous aurez besoin d'une heightmap, comme celle-ci:
Image

A+

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : jeu. 10/nov./2011 19:01
par comtois
ça fonctionne bien :)

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : jeu. 10/nov./2011 22:36
par kelebrindae
Merci!
Mais j'ai vu (un peu tard) que Huitbit et G-Rom m'avaient devancé dans leur post "Terrain Mesh" ici: http://www.purebasic.fr/french/viewtopi ... 13&t=11797
Tant pis...

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : ven. 11/nov./2011 0:29
par Huitbit
Ca marche !

Questions de super novice.
Si on fait :

Code : Tout sélectionner

numMesh = MyCreateTerrain(heightmap,1500,1500,100,250,250) 
On a terrain de bonne qualité, beaucoup plus grand (dans l'exemple "terrain" de la 4.51, je crois que c'était la technique utilisée pour avoir un grand terrain avec une heightmap de 257*257).
C'est une faute de faire ça ou pas ?
Avec le code de G-rom(cité plus haut) est-ce qu'on pourrait faire la même chose ?

Ma partie de ce code sera, un jour, optimisée(choix "intelligent" du nombre de subdivisions) (je suis en train de faire une procédure "subdivision" avec des variables locales pour l'utiliser dans n'importe quelle situation sans se casser la tête)


Hasta la vista !

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : ven. 11/nov./2011 18:58
par venom
Bonjour,

chez moi il me met ce message d'erreur : Can't initialize 3D, check if engine3D.dll is available c'est du a quoi ?






@++

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : sam. 12/nov./2011 14:47
par kelebrindae
@Venom:
Si tu as cette erreur, c'est que le "InitEngine3D" renvoie 0, c'est-à-dire qu'il ne peut s'initialiser ou que la DLL est absente. C'est assez bizarre; Les exemples 3D fournis avec la 4.60 de PB fonctionnent, chez toi? :?

@HuitBit:
"numMesh = MyCreateTerrain(heightmap,1500,1500,100,250,250)"
va créer un terrain de 1500 unités de long sur 1500 de large, de 100 unités de haut maxi (pour les zones blanches de la heightmap), et le mesh sera constitué d'une grille de 250 x 250 carreaux (mesurant 6 unités chacun), soit 62500 en tout. Pas plus de détails, donc, mais un terrain 3 fois plus grand que dans mon exemple.
A priori, on ne peut dépasser 65535 vertices par mesh dans Ogre. On ne peut donc pas monter au-dessus de 255x255 (sauf le fait de faire des submesh permet de contourner la limitation...)
=> ton idée d'optimiser en faisait des subdivisions plus petites pour les zones détaillées et un seul carreau pour les zones "plates" est donc très intéressante. J'espère voir ça bientôt!

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : sam. 12/nov./2011 17:54
par venom
C'est bon, j'ai remis a jour directx c'est peut etre du a ça. ?

maintenant ça fonctionne.






@++

Re: [4.60] Remplacer temporairement CreateTerrain

Publié : sam. 12/nov./2011 21:27
par Cool Dji
Hello,

Vraiment très cool. Très utile aussi pour faire plusieurs petits morceaux de terrains naturels dans un même monde (jardin, bordure, talus...).
Faute de CreateTerrain j'avais commencé à modéliser un sol avec Deled (j'ai vite arrêté !!).

Merci et bravo