Perlin et subdivisions, création de terrains
Publié : mar. 05/avr./2011 5:57
Hello !
Je viens de voir que la béta était sortie
.
J'ai rien vu car je faisais mumuse avec les subdivisions.

L'avantage c'est de travailler avec des droites(cf. post suivant pour visualiser le lissage de chaque octave). Pas d'interpolation (bilinéaire, bicubique....). Le seul point délicat, c'est le bricolage avec les subdivisions
.
Au niveau rapidité, sans la moindre optimisation, je peux créer un bruit de Perlin(monochrome) sur tout l'écran assez rapidement !(D'ailleurs, si vous avez des idées d'amélioration, donnez, dododonnez....
)
Avec les couleurs, j'ai un peu fait du n'importe quoi, ça ralentit un peu la bête.
A la suite du programme, je mets un exemple en 2D plus simple (j'ai utilisé une technique voisine)
Pour le principe des subdivisions, j'avais déjà fait quelque chose de détaillé.
Pour obtenir une surface, il a fallu faire deux subdivisions.
Une première pour créer des "lignes de contrôle" horizontales puis une deuxième verticale pour les utiliser.
Pour les couleurs, j'ai fait a pif
Hasta la vista !
PS: A suivre, la même chose en 2D
Je viens de voir que la béta était sortie

J'ai rien vu car je faisais mumuse avec les subdivisions.

L'avantage c'est de travailler avec des droites(cf. post suivant pour visualiser le lissage de chaque octave). Pas d'interpolation (bilinéaire, bicubique....). Le seul point délicat, c'est le bricolage avec les subdivisions

Au niveau rapidité, sans la moindre optimisation, je peux créer un bruit de Perlin(monochrome) sur tout l'écran assez rapidement !(D'ailleurs, si vous avez des idées d'amélioration, donnez, dododonnez....

Avec les couleurs, j'ai un peu fait du n'importe quoi, ça ralentit un peu la bête.

A la suite du programme, je mets un exemple en 2D plus simple (j'ai utilisé une technique voisine)
Pour le principe des subdivisions, j'avais déjà fait quelque chose de détaillé.
Pour obtenir une surface, il a fallu faire deux subdivisions.
Une première pour créer des "lignes de contrôle" horizontales puis une deuxième verticale pour les utiliser.
Pour les couleurs, j'ai fait a pif

Code : Tout sélectionner
;-@@@@@@@@@@@@@@@
;-Bruit de Perlin & Subdivisions
;Auteur Huitbit
;Avril 2011
;PureBasic 4.51 (Windows - x86)
;-@@@@@@@@@@@@@@@
;-Déclarations
#PasInitial =128
#NbreInitialDePicsHorizontaux =6
#NbreInitialDePicsVerticaux =4
#OctaveMax = 5; de l'octave n°1 à #OctaveMax
#Persistance = 0.5
Octave.b
Persistance.f
FacteurNormalisation.f =(1 - Pow(#Persistance,#OctaveMax)) / (1 - #Persistance)
Composante.w
Pas.l
NbreDePicsHorizontaux.l
NbreDePicsVerticaux.l
NbreMaxDePicsHorizontaux.l = #NbreInitialDePicsHorizontaux * Pow(2 , #OctaveMax - 1)
NbreMaxDePicsVerticaux.l = #NbreInitialDePicsVerticaux * Pow(2 , #OctaveMax - 1)
PasMinimal.l = #PasInitial / Pow(2 , #OctaveMax - 1)
LargeurEcran.l = NbreMaxDePicsHorizontaux * PasMinimal
HauteurEcran.l = NbreMaxDePicsVerticaux * PasMinimal
#NbreDeSubdivisions = 3
RapportSubdv.f = 0.25
IndiceMaxDesPtsDeCtrlHorizontaux.l = (NbreMaxDePicsHorizontaux - 2) * Pow(2,#NbreDeSubdivisions) +1
IndiceMaxDesPtsDeCtrlVerticaux.l = (NbreMaxDePicsVerticaux - 2) * Pow(2,#NbreDeSubdivisions) + 1
IndiceDesPtsDeCtrlHorizontaux.l
IndiceDesPtsDeCtrlVerticaux.l
Structure PtDeCtrl
x.l
y.l ; y = a * x + b
z.l
a.f ; pente
b.f ; ordonnée à l'origine
EndStructure
Structure Carte
z.w
EndStructure
Macro affine(a,b,uA,zA,uB,zB)
If (uB-uA)<>0
a = (zB - zA) / (uB - uA)
b = zB - a * uB
EndIf
EndMacro
;tableau des points de contrôle
Dim P.PtDeCtrl(LargeurEcran , IndiceMaxDesPtsDeCtrlVerticaux , #OctaveMax)
Dim carte.Carte(LargeurEcran,HauteurEcran,#OctaveMax)
;-Remplissage du tableau de points de contrôle avec des pics de Perlin
For Octave = 1 To #OctaveMax
Pas = #PasInitial / Pow(2 , Octave - 1)
NbreDePicsHorizontaux = #NbreInitialDePicsHorizontaux * Pow(2 , Octave - 1)
NbreDePicsVerticaux = #NbreInitialDePicsVerticaux * Pow(2 , Octave - 1)
Persistance = Pow(#Persistance , Octave - 1)
For i = 0 To NbreDePicsHorizontaux -1
For j = 0 To NbreDePicsVerticaux -1
P(i , j , Octave)\x = i * Pas
P(i , j , Octave)\y = j * Pas
P(i , j , Octave)\z = Persistance * Random(255)
Next j
Next i
Next Octave
;-Subdivisions
For Octave = 1 To #OctaveMax
NbreDePicsHorizontaux = #NbreInitialDePicsHorizontaux * Pow(2 , Octave - 1)
NbreDePicsVerticaux = #NbreInitialDePicsVerticaux * Pow(2 , Octave - 1)
IndiceDesPtsDeCtrlHorizontaux = NbreDePicsHorizontaux - 1
IndiceDesPtsDeCtrlVerticaux = NbreDePicsVerticaux - 1
Pas = #PasInitial / Pow(2 , Octave - 1)
;- Création des lignes de contrôle horizontales pour chaque octave
;Utilisation du tableau P(i,j,Octave) pour i allant de i=0 à i=NbreDePicsHorizontauxProvisoire
;l'utilisation de i=x=0 à i=x=LargeurEcran se fera dans la deuxième partie
;{
For j = 0 To IndiceDesPtsDeCtrlVerticaux
For SubdivisionEnCours = 0 To #NbreDeSubdivisions - 1
IndiceMaxProvisoire = (NbreDePicsHorizontaux - 2) * Pow(2,SubdivisionEnCours) +1
For i = IndiceMaxProvisoire - 1 To 1 Step - 1
If i = IndiceMaxProvisoire - 1
P(2 * i + 1,j,Octave)\x = LargeurEcran
P(2 * i + 1,j,Octave)\z = P(IndiceMaxProvisoire,j,Octave)\z
P(2 * i,j,Octave)\x = P(i,j,Octave)\x + RapportSubdv * (P(i + 1,j,Octave)\x - P(i,j,Octave)\x)
P(2 * i,j,Octave)\z = P(i,j,Octave)\z + RapportSubdv * (P(i + 1,j,Octave)\z - P(i,j,Octave)\z)
Else
P(2 * i + 1,j,Octave)\x = P(i,j,Octave)\x + (1 - RapportSubdv) * (P(i + 1,j,Octave)\x - P(i,j,Octave)\x)
P(2 * i + 1,j,Octave)\z = P(i,j,Octave)\z + (1 - RapportSubdv) * (P(i + 1,j,Octave)\z - P(i,j,Octave)\z)
P(2 * i,j,Octave)\x = P(i,j,Octave)\x + RapportSubdv * (P(i + 1,j,Octave)\x - P(i,j,Octave)\x)
P(2 * i,j,Octave)\z = P(i,j,Octave)\z + RapportSubdv * (P(i + 1,j,Octave)\z - P(i,j,Octave)\z)
EndIf
Next i
P(1,j,Octave)\x = P(0,j,Octave)\x + (1 - RapportSubdv) * (P(1,j,Octave)\x - P(0,j,Octave)\x)
P(1,j,Octave)\z = P(0,j,Octave)\z + (1 - RapportSubdv) * (P(1,j,Octave)\z - P(0,j,Octave)\z)
Next SubdivisionEnCours
;-calculs des équations affines de chaque segment
x=0
For i = 0 To IndiceMaxDesPtsDeCtrlHorizontaux -1
affine(P(i,j,Octave)\a,P(i,j,Octave)\b,P(i,j,Octave)\x,P(i,j,Octave)\z,P(i + 1,j,Octave)\x,P(i + 1,j,Octave)\z)
;-remplissage du tableau carte(x,y,Octave)
While x<=P(i+1,j,Octave)\x
carte(x,j*Pas,Octave)\z=P(i,j,Octave)\a * x + P(i,j,Octave)\b
x=x+1
Wend
Next i
Next j
;}
;-subdivisions selon y, les points de contrôles sont issus des lignes de contrôle horizontales
;{
For x=0 To LargeurEcran
;Chargement des points de contrôle d'abscisse x
For j = 0 To IndiceDesPtsDeCtrlVerticaux
P(x,j,Octave)\z= carte(x,j*Pas ,Octave)\z
P(x,j,Octave)\y=j*Pas
Next j
For SubdivisionEnCours = 0 To #NbreDeSubdivisions - 1
IndiceMaxProvisoire = (NbreDePicsVerticaux - 2) * Pow(2,SubdivisionEnCours) +1
For j = IndiceMaxProvisoire - 1 To 1 Step - 1
If j = IndiceMaxProvisoire - 1
P(x,2 * j + 1,Octave)\y = HauteurEcran
P(x,2 * j + 1,Octave)\z = P(x,IndiceMaxProvisoire,Octave)\z
P(x,2 * j,Octave)\y = P(x,j,Octave)\y + RapportSubdv * (P(x,j + 1,Octave)\y - P(x,j,Octave)\y)
P(x,2 * j,Octave)\z = P(x,j,Octave)\z + RapportSubdv * (P(x,j+1,Octave)\z - P(x,j,Octave)\z)
Else
P(x,2 * j + 1,Octave)\y = P(x,j,Octave)\y + (1 - RapportSubdv) * (P(x,j+ 1,Octave)\y - P(x,j,Octave)\y)
P(x,2 * j + 1,Octave)\z = P(x,j,Octave)\z + (1 - RapportSubdv) * (P(x,j+ 1,Octave)\z - P(x,j,Octave)\z)
P(x,2 * j,Octave)\y = P(x,j,Octave)\y + RapportSubdv * (P(x,j + 1,Octave)\y - P(x,j,Octave)\y)
P(x,2 * j,Octave)\z = P(x,j,Octave)\z + RapportSubdv * (P(x,j+1,Octave)\z - P(x,j,Octave)\z)
EndIf
Next j
P(x,1,Octave)\y = P(x,0,Octave)\y + (1 - RapportSubdv) * (P(x,1,Octave)\y - P(x,0,Octave)\y)
P(x,1,Octave)\z = P(x,0,Octave)\z + (1 - RapportSubdv) * (P(x,1,Octave)\z - P(x,0,Octave)\z)
Next SubdivisionEnCours
;-calculs des équations affines de chaque segment
y=0
For j = 0 To IndiceMaxDesPtsDeCtrlVerticaux -1
affine(P(x,j,Octave)\a,P(x,j,Octave)\b,P(x,j,Octave)\y,P(x,j,Octave)\z,P(x ,j+1,Octave)\y,P(x,j+1,Octave)\z)
;-remplissage du tableau carte(x,y,Octave)
While y<=P(x,j+1,Octave)\y
carte(x,y,Octave)\z=P(x,j,Octave)\a * y + P(x,j,Octave)\b
y=y+1
Wend
Next j
Next x
;}
Next Octave
;-*************************************************
;-PROGRAMME PRINCIPAL
;-
;-************************************************
InitSprite()
InitKeyboard()
info$=">>INFOS: Pics "+ Str(#NbreInitialDePicsHorizontaux)+" * "+Str(#NbreInitialDePicsVerticaux)+" Oct="+Str(#OctaveMax)+" Subdv="+Str(#NbreDeSubdivisions)
OpenWindow(0,0,0,LargeurEcran,HauteurEcran,"Test Perlin 2D"+info$,#PB_Window_ScreenCentered|#PB_Window_SystemMenu )
OpenWindowedScreen(WindowID(0),0,0,LargeurEcran,HauteurEcran,0,0,0)
;-dessin de la carte
CreateSprite(0,LargeurEcran,HauteurEcran)
StartDrawing(SpriteOutput(0))
If #OctaveMax>1
For Octave = 2 To #OctaveMax
For x=0 To LargeurEcran
For y=0 To HauteurEcran
carte(x,y,1)\z=carte(x,y,1)\z+carte(x,y,Octave)\z
Next y
Next x
Next Octave
EndIf
For x=0 To LargeurEcran
For y=0 To HauteurEcran
Composante=carte(x,y,1)\z/FacteurNormalisation
;-choix des couleurs en fonction de z
Select Composante
Case 0 To 85 ; eaux profondes
Box(x,y,1,1,RGB(0,0,2*Composante))
Case 85 To 100 ; eaux peu profondes
Box(x,y,1,1,RGB(0, Composante*0.4, 2*Composante))
Case 100 To 104 ; plages
Box(x,y,1,1,RGB(2*Composante+25,2*Composante+15,Composante))
Case 104 To 115 ;herbe
Box(x,y,1,1,RGB(0, 2*Composante-Random(40),0))
Case 115 To 130;forêt
Box(x,y,1,1,RGB(0,Composante-Random(20),0))
Case 120 To 150;basse montagne
Box(x,y,1,1,RGB(Composante, Composante*0.7, Random(80)))
Case 150 To 170;haute montagne
Box(x,y,1,1,RGB(Composante, Composante, 20+Random(80)))
Case 170 To 255;neige
Box(x,y,1,1,RGB(Composante, Composante,Composante))
EndSelect
Next y
Next x
StopDrawing()
;-BOUCLE PRINCIPALE
Repeat
FlipBuffers()
DisplaySprite(0,0,0)
Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow
PS: A suivre, la même chose en 2D