Page 1 sur 2

Besoin d'aide pour créer un éditeur de carte 3D

Publié : mar. 20/mai/2008 10:57
par Octavius
J'ai déjà un début de code, mais je suis bloqué.

Le principe de mon programme est d'ouvrir une image dans laquelle chaque nuance de gris correspond à une hauteur. Je créé donc un tableau de coordonnées pour les vertex, ainsi qu'un tableau de triangles.

Mon programme fonctionne très bien avec des images de 128*128 pixels. Le problème c'est que je n'arrive pas à dépasser cette limite (la carte que je veux modéliser en 3D fait 591*379 pixels).

Je soupçonne que ce soit dû au fait qu'au-delà de 16384 pixels je dépasse le nombre maximum de vertex ou de triangles autorisé pour un mesh sous PB. Comment dépasser cette limite ?

(PS: la largeur et la hauteur correspondent aux constantes #X et #Y)

Code : Tout sélectionner


;-Initializations

;{
  #Sprite=0
  #Camera=0
  #Terrain=0
  #X=128
  #Y=128
Enumeration
EndEnumeration
;}

;{

;Instructions pour le debug
EnableExplicit
UseTGAImageDecoder()
UsePNGImageDecoder()
UseTIFFImageDecoder()

;Déclarations de fonctions
Declare Error(Text$)
Declare Check()
Declare.l ReverseRGB(Color.l)
Declare CreateWorld()
Declare Keyboard()
Declare Mouse()
Declare Camera(dA.f,dB.f,dR.f)

;Environnement général
If Not InitMouse() Or Not InitKeyboard() Or Not InitEngine3D() Or Not InitSprite() : Error("Impossible d'initialiser le programme.") : EndIf

;Les structures
Structure vtx : X.f : Y.f : Z.f : Color.l : EndStructure
Structure trgl : V1.w : V2.w : V3.w : EndStructure

;Variables
Global Path$,i.l,j.l,k.l
Global Dim Files.s(12)
Global Dim Vertices.vtx(#X*#Y)
Global Dim Triangles.trgl((#X-1)*(#Y-1)*2)

;Choix du mod
Path$=PathRequester("Choisissez le répertoire d'un mod pour le modifier :",GetCurrentDirectory())
If Path$="" : Error("Vous n'avez choisi aucun mod.") : EndIf

;Liste des fichiers traités
Restore Files : For i=0 To 11 : Read Files(i) : Next i
;}

;Vérification des fichiers
Check()

;Ouverture de l'écran
ExamineDesktops() : OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"Geomod")

;Texture blanche 64*64
CreateTexture(0,64,64) : If StartDrawing(TextureOutput(0)) : Box(0,0,64,64,$FFFFFF) : StopDrawing() : EndIf

;Matière
CreateMaterial(0,TextureID(0)) : MaterialAmbientColor(0,#PB_Material_AmbientColors)

CreateWorld()
EntityLocate(0,0,0,0)

;Caméra
AmbientColor($FFFFFF) : CreateCamera(#Camera,0,0,100,100) : CameraBackColor(#Camera,$00FF00) : CameraLocate(#Camera,0,0,300)

Procedure Error(Text$)
  MessageRequester("Fin du programme !",Text$) : End
EndProcedure

Procedure Check()
For i=0 To 11
  If FileSize(Path$+Files(i))<0
    Error("Le fichier "+Files(i)+" est introuvable.")
  EndIf
Next i
EndProcedure

Procedure.l ReverseRGB(Color.l)
  ProcedureReturn RGB(Blue(Color),Green(Color),Red(Color))
EndProcedure

Procedure CreateWorld()
  Protected Color.l
  
  ;On charge l'image
  LoadSprite(#Sprite,"map_heights.png")
  ;On l'affiche
  DisplaySprite(#Sprite,0,0)
  ;On remplit le tableau de vertex en prélevant les couleurs de l'image point par point
  StartDrawing(ScreenOutput())
  For i=0 To #X-1
    For j=0 To #Y-1
      k=j+#Y*i
      Color=Point(i,#Y-j)
      Vertices(k)\X=i
      Vertices(k)\Y=j
      Vertices(k)\Z=Red(Color)/10
      Vertices(k)\Color=ReverseRGB(Color)
    Next j
  Next i
  StopDrawing()
  
  ;On remplit le tableau de triangles
  For i=0 To #X-2
    For j=0 To #Y-2
      k=j+i*(#Y-1)
      Triangles(2*k)\V1=j+1+i*#Y
      Triangles(2*k)\V2=j+i*#Y
      Triangles(2*k)\V3=j+(i+1)*#Y
      Triangles(2*k+1)\V1=j+1+i*#Y
      Triangles(2*k+1)\V2=j+(i+1)*#Y
      Triangles(2*k+1)\V3=j+1+(i+1)*#Y
    Next j
  Next i
  
  ;Création du terrain
  CreateMesh(#Terrain,#X*#Y)
  
  ;On remplit les données du terrain avec les deux tableaux de vertex et de triangles
  SetMeshData(#Terrain,#PB_Mesh_Vertex|#PB_Mesh_Color,@Vertices(),#X*#Y)
  SetMeshData(#Terrain,#PB_Mesh_Face,@Triangles(),(#X-1)*(#Y-1)*2)
  
  ;Création de l'entité du terrain
  CreateEntity(0,MeshID(#Terrain),MaterialID(0))
EndProcedure

Procedure Keyboard()
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape) : End
  ElseIf KeyboardPushed(#PB_Key_Up) : MoveCamera(#Camera,0,1,0)
  ElseIf KeyboardPushed(#PB_Key_Down) : MoveCamera(#Camera,0,-1,0)
  ElseIf KeyboardPushed(#PB_Key_Left) : MoveCamera(#Camera,-1,0,0)
  ElseIf KeyboardPushed(#PB_Key_Right) : MoveCamera(#Camera,1,0,0) : EndIf
EndProcedure

Procedure Mouse()
  ExamineMouse()
;   If MouseButton(1)
; ;    Camera(MouseDeltaX()/1000,MouseDeltaY()/1000,0)
;   ElseIf MouseButton(2)
;     
;   Else
    Camera(0,0,MouseWheel())
;   EndIf
EndProcedure

Procedure Camera(dA.f,dB.f,dR.f)
  Protected X.f,Y.f,Z.f,Rh.f
  ;Calcul des coordonnées
;   ACam+dA
;   BCam+dB
;   Y=RCam*Sin(BCam)
;   Rh=RCam*Cos(BCam)
;   X=Rh*Cos(ACam)
;   Z=Rh*Sin(ACam)
;   ;Placer la caméra au bon endroit !
;   CameraLocate(#Camera,X,Y,Z)
;   RotateCamera(#Camera,dA*180/#PI,dB*180/#PI,0)
  MoveCamera(#Camera,0,0,10*dR)
EndProcedure

;**********************************************************************************************************
;-Main lopp
;**********************************************************************************************************

Repeat
  
  ClearScreen(0)
  
  Keyboard()
  Mouse()
  
  RenderWorld()
  
;   StartDrawing(ScreenOutput())
;   For i=0 To 31
;     For j=0 To 31
;       k=j+32*i
;       Plot(Vertices(k)\X,Vertices(k)\Y,Vertices(k)\Color)
;     Next j
;   Next i
;   StopDrawing()
  
  FlipBuffers()
  
ForEver

;-Data
;{
DataSection

Files:

Data.s "data\text\imperial_campaign_regions_and_settlement_names.txt.strings.bin"
Data.s "data\world\maps\base\descr_regions.txt"
Data.s "data\world\maps\base\descr_sounds_music_types.txt"
Data.s "data\world\maps\base\map_climates.tga"
Data.s "data\world\maps\base\map_features.tga"
Data.s "data\world\maps\base\map_ground_types.tga"
Data.s "data\world\maps\base\map_heights.tga"
Data.s "data\world\maps\base\map_regions.tga"
Data.s "data\world\maps\base\map_roughness.tga"
Data.s "data\world\maps\campaign\imperial_campaign\descr_mercenaries.txt"
Data.s "data\world\maps\campaign\imperial_campaign\descr_strat.txt"
Data.s "data\world\maps\campaign\imperial_campaign\descr_win_conditions.txt"

EndDataSection
;}

Ah au fait, voici la carte :
Image

Publié : mar. 20/mai/2008 12:46
par Ollivier
16384, c'est trop...

Fais des parcelles de 32 par 32 (2048 polygones) , ou 40 par 40 (3200 polygones). Une mesh par parcelle, et roule!

Publié : mar. 20/mai/2008 13:03
par Ollivier
Si je peux te donner un conseil, enlève les tableaux globaux.
Car, par la suite, il seront contraignants quand tu voudras traiter plusieurs formes d'entités ensemble.

Simple exemple de construction avec les pointeurs (sans les structures)

Publié : mar. 20/mai/2008 14:22
par Octavius
Excuse moi, mais je ne comprends pas pourquoi les tableaux sont contraignants ?

(encore un truc simple qu'il comprend pas ce pov' Octavius :oops: )

Il n'y a donc pas d'autres moyens que de découper des parcelles ? Bon eh ben je m'y colle alors. Dommage qu'il n'y ait pas de solution plus élégante.

Publié : mar. 20/mai/2008 16:21
par Ollivier
Les tableaux ne sont pas transformables et leurs pointeurs ne sont pas grandement controlables. Bon courage!

Publié : mar. 20/mai/2008 19:27
par Anonyme
Tu ne fait pas un vertex par pixel , il va te falloir 50 carte graphique en ligne :D

Ton image fait admettons 1000x500 , tu parcours ton image de 10 en 10
se qui fait donc
For next step 10
(1000 / 10) X ( 500 / 10 ) = Nombre de Vertex

donc tu auras 5000 vertex pour cet exemple.

Plus tu auras de vertex , plus le mesh final aura de détails.

je doute qu'avec l'image que tu nous à montrer, que tu obtienne un résultat satisfaisant.

par contre , avec le moteur de base , je ne sais pas si les normale sont calculé automatiquement ou si il faut le faire en manuel.
Attention , pour le rendu , les normales c'est très important !

@++
:wink:

Publié : mar. 20/mai/2008 19:35
par Ollivier
par contre , avec le moteur de base , je ne sais pas si les normale sont calculé automatiquement ou si il faut le faire en manuel.
Attention , pour le rendu , les normales c'est très important !
C'est manuel.

Publié : mar. 20/mai/2008 23:47
par Octavius
Et comment calcule-t-on les normales ?

Je pensais savoir ce qu'étaient des droites normales à un plan, mais quand on renseigne le SetMeshData(), les normales sont liées aux vertex et pas aux triangles (et là mon pov' cerveau il comprend plus rien).

J'ai vu quelques sujets qui parlent des normales, mais je ne trouve pas ce que je cherche, à savoir une formule simple que je puisse appliquer à mon dessin...

PS:
Cpl.Bator a écrit : Ton image fait admettons 1000x500 , tu parcours ton image de 10 en 10
se qui fait donc

(1000 / 10) X ( 500 / 10 ) = Nombre de Vertex

donc tu auras 5000 vertex pour cet exemple.

Plus tu auras de vertex , plus le mesh final aura de détails.
Je travaille sur un éditeur de carte 3D, le but est justement de pouvoir modifier très finement les détails de la carte, il est donc essentiel que je prenne en compte tous les pixels.

J'ai essayé de faire un mesh par triangle, mais ça rame grave (quand ça ne plante pas), et le moteur semble également limité sur le nombre de meshs qu'il peut afficher.

Publié : mer. 21/mai/2008 0:17
par Octavius
J'ai vraiment l'impression de m'être engagé sur une fausse piste... Avez-vous une idée de la façon dont je devrais m'y prendre pour programmer mon logiciel d'éditeur de carte 3D ?

Voilà à peu près à quoi je voudrais faire ressembler mon logiciel :

Image

Image

Est-ce que mes difficultés sont dues au fait que Ogre ou PureBasic ne sont pas adaptés à ce genre de logiciel ? Faut-il que je cherche à programmer plutôt avec DreaMotion3D, ou bien que je change carrément de langage de programmation ? (C ? C++ ? C# ?)

Publié : mer. 21/mai/2008 6:01
par Ollivier
Pour répondre à ta dernière phrase, PureBasic est adapté à exécuter ce type d'application. Par contre, il y a plus à faire qu'il n'y a déjà en bibliothèque Ogre...

Publié : mer. 21/mai/2008 7:32
par Octavius
Ollivier a écrit :Par contre, il y a plus à faire qu'il n'y a déjà en bibliothèque Ogre...
Et avec la bibliothèque DreaMotion3D ?

Publié : mer. 21/mai/2008 7:50
par Ollivier
Dans ton cas particulier, DreamMotion n'y pourra rien. Par contre, DreamMotion est bardé de fonctions inexistantes avec Ogre.

Publié : mer. 21/mai/2008 8:31
par Octavius
Alors qu'est-ce que je dois faire ?

Publié : mer. 21/mai/2008 9:01
par Anonyme
Tourne toi vers dreamotion , regarde les exemples.


Pour les normales , c'est simple , chaque vertex possède une normale , chaque triangle à trois vertex et une normale , cette normale est calculé en fonction des normales des vertices (interpolation)
Regarde les sources de Dreamotion3D , si j'ai le temps se soir , je te sors une formule ici.

il est donc essentiel que je prenne en compte tous les pixels.
il te manque quelques connaissance en 3D , ce que tu dis est impossible à l'heure actuelle pour un moteur de rendu en temps réel , imagine une image (heightmap) de 1024*768 , ca te fera un mesh qui possède 786432 vertices !
un modele haute qualité (Halflife²) possède si mes souvenir sont bon , environ 6000 vertices.
Tu peut à la rigueur faire une moyenne des pixel alentours , mais en aucun cas tu ne pourras les prendre en compte.

Dans tout les Cas , tourne toi vers Dreamotion3D , si tu trouves trop complexe , essaye DarkBasicPro. :)

Publié : mer. 21/mai/2008 10:40
par Octavius
Cpl.Bator a écrit :il te manque quelques connaissance en 3D , ce que tu dis est impossible à l'heure actuelle pour un moteur de rendu en temps réel , imagine une image (heightmap) de 1024*768 , ca te fera un mesh qui possède 786432 vertices !
un modele haute qualité (Halflife²) possède si mes souvenir sont bon , environ 6000 vertices.
Mais HalfLife est un jeu dans lequel il y a plusieurs de ces modèles et un environnement complexe à afficher. Dans mon cas, il n'y a qu'un seul mesh, une seule entité à générer. Je ne pensais pas que 10^6 vertices et triangles ce serait impossible à gérer pour une carte graphique...

Les screenshots que je vous ai montré plus haut correspondent à des éditeurs de carte 3D qui prennent en compte (je ne sais pas comment!!! mais ils sont programmés en Delphi) tous les pixels des cartes 2D. Ainsi il est impossible de modifier finement les hauteurs de chaque vertex.