Et blague à part, effectivement, bravo à Comtois et G-Rom (et au reste de l'équipe PB, ne faites pas les modestes!) : non seulement la 3D en PB tourne bien, mais en plus elle reste assez facile à comprendre; que du bonheur!
Créer un monde "à la minecraft"
-
kelebrindae
- Messages : 579
- Inscription : ven. 11/mai/2007 15:21
Re: Créer un monde "à la minecraft"
Oui: je suis un fétichiste du papier kraft; je m'en colle partout sur le corps et je fais subir des choses innommables à d'innocents rouleaux d'emballage!
Et blague à part, effectivement, bravo à Comtois et G-Rom (et au reste de l'équipe PB, ne faites pas les modestes!) : non seulement la 3D en PB tourne bien, mais en plus elle reste assez facile à comprendre; que du bonheur!
Et blague à part, effectivement, bravo à Comtois et G-Rom (et au reste de l'équipe PB, ne faites pas les modestes!) : non seulement la 3D en PB tourne bien, mais en plus elle reste assez facile à comprendre; que du bonheur!
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
-
stombretrooper
- Messages : 117
- Inscription : dim. 21/déc./2008 18:39
Re: Créer un monde "à la minecraft"
J'ai beaucoup joué à minecraft, et je dois dire que ton code envoie du rêve. Franchement bravo, ça donne envie de se baser dessus pour faire un minecraft like.
http://www.purebasicstreet.com/ - Site dédié à purebasic.
Re: Créer un monde "à la minecraft"
j'ai cherché sur le net des fonctions de perlin, j'en ai trouvé là : http://paulbourke.net/texture_colour/perlin/
un gars sur le forum anglais (http://www.purebasic.fr/english/viewtop ... 12&t=41553) à déjà traduit les sources, c'est très utile pour la génération de terrain :
Tu génères en premier la surface via un perlin 2D que tu places dans un volume 3D ( tableau 3D )
Tu remplis ensuite de ta surface vers le bas de ton tableau 3D que tu as créer pour ta surface
Tu généres ensuite des cavités ( pour faire des grottes ) via un perlin 3D que tu stocke séparément dans un autre tableau 3D
tu applique sur ce tableau de cavité un thresold pour pour avoir que du "blanc" ou du "noir", soit 0 ou 255 donc selon le thresold défini par tes soins
Tu soustrait le tableau de surface & le tableau de cavité pour avoir ton monde final & le tour est joué , un générateur de terrain pour mineclone ^^
Reste plus que l'inventaire des outils maintenant ^^
Tu place ensuite tes arbres de manière aléatoire sur ton terrain selon l'altitude par exemple.
L'idéal serais de pouvoir avoir des "préfab" d'objet dans des fichiers séparé
un gars sur le forum anglais (http://www.purebasic.fr/english/viewtop ... 12&t=41553) à déjà traduit les sources, c'est très utile pour la génération de terrain :
Code : Tout sélectionner
InitEngine3D(#PB_Engine3D_DebugLog )
InitKeyboard()
InitSprite()
#B = $100
#BM = $ff
#N = $1000
#NP = 12 ; 2^N
#NM = $fff
Structure InnerDoubleArray
d.d[0]
EndStructure
Macro Unsigned(value)
((value) + 1) / 2
EndMacro
Macro s_curve(t)
( t * t * ( 3 - 2 * t ) )
EndMacro
Macro lerp(t, a, b)
( a + t * (b - a) )
EndMacro
Macro setup(i,b0,b1,r0,r1)
t = vec(i) + #N
b0 = Int(t) & #BM
b1 = (b0 + 1) & #BM
r0 = t - Int(t)
r1 = r0 - 1.
EndMacro
Macro at2(rx,ry)
( rx * *q\d[0] + ry * *q\d[1] )
EndMacro
Macro at3(rx,ry,rz)
( rx * *q\d[0] + ry * *q\d[1] + rz * *q\d[2] )
EndMacro
Declare init()
Declare.d noise1(arg.d)
Declare.d noise2(Array vec.d(1))
Declare.d noise3(Array vec.d(1))
Declare normalize2(d.i)
Declare normalize3(d.i)
Declare.d PerlinNoise1D(x.d, alpha.d, beta.d, n.i);
Declare.d PerlinNoise2D(x.d, y.d, alpha.d, beta.d, n.i);
Declare.d PerlinNoise3D(x.d, y.d, z.d, alpha.d, beta.d, n.i);
Global Dim p.i(#B + #B + 1)
Global Dim g1.d(#B + #B + 1)
Global Dim g2.d(#B + #B + 1, 1)
Global Dim g3.d(#B + #B + 1, 2)
Global start.i = 1
Procedure.d noise1(arg.d)
Protected bx0.i, bx1.i
Protected rx0.d, rx1.d, sx.d, t.d, u.d, v.d
Dim vec.d(1)
vec(0) = arg
If start
start = 0
init()
EndIf
setup(0,bx0,bx1,rx0,rx1)
sx = s_curve(rx0)
u = rx0 * g1( p( bx0 ) )
v = rx1 * g1( p( bx1 ) )
ProcedureReturn lerp(sx, u, v)
EndProcedure
Procedure.d noise2(Array vec.d(1))
Protected bx0.i, bx1.i, by0.i, by1.i, b00.i, b10.i, b01.i, b11.i
Protected rx0.d, rx1.d, ry0.d, ry1.d, *q.InnerDoubleArray, sx.d, sy.d, a.d, b.d, t.d, u.d, v.d
Protected i.i, j.i
If start
start = 0
init()
EndIf
setup(0, bx0,bx1, rx0,rx1)
setup(1, by0,by1, ry0,ry1)
i = p( bx0 )
j = p( bx1 )
b00 = p( i + by0 )
b10 = p( j + by0 )
b01 = p( i + by1 )
b11 = p( j + by1 )
sx = s_curve(rx0)
sy = s_curve(ry0)
*q = @g2( b00, 0 ) : u = at2(rx0,ry0)
*q = @g2( b10, 0 ) : v = at2(rx1,ry0)
a = lerp(sx, u, v)
*q = @g2( b01, 0 ) : u = at2(rx0,ry1)
*q = @g2( b11, 0 ) : v = at2(rx1,ry1)
b = lerp(sx, u, v)
Protected rv.d = lerp(sy, a, b)
ProcedureReturn rv
EndProcedure
Procedure.d noise3(Array vec.d(1))
Protected bx0.i, bx1.i, by0.i, by1.i, bz0.i, bz1.i, b00.i, b10.i, b01.i, b11.i
Protected rx0.d, rx1.d, ry0.d, ry1.d, rz0.d, rz1.d, *q.InnerDoubleArray, sy.d, sz.d, a.d, b.d, c.d, d.d, t.d, u.d, v.d
Protected i.i, j.i
If (start)
start = 0
init()
EndIf
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
setup(2, bz0,bz1, rz0,rz1);
i = p( bx0 )
j = p( bx1 )
b00 = p( i + by0 )
b10 = p( j + by0 )
b01 = p( i + by1 )
b11 = p( j + by1 )
t = s_curve(rx0)
sy = s_curve(ry0)
sz = s_curve(rz0)
*q = @g3( b00 + bz0, 0 ) : u = at3(rx0,ry0,rz0)
*q = @g3( b10 + bz0, 0 ) : v = at3(rx1,ry0,rz0)
a = lerp(t, u, v)
*q = @g3( b01 + bz0, 0 ) : u = at3(rx0,ry1,rz0);
*q = @g3( b11 + bz0, 0 ) : v = at3(rx1,ry1,rz0);
b = lerp(t, u, v);
c = lerp(sy, a, b);
*q = @g3( b00 + bz1, 0 ) : u = at3(rx0,ry0,rz1);
*q = @g3( b10 + bz1, 0 ) : v = at3(rx1,ry0,rz1);
a = lerp(t, u, v);
*q = @g3( b01 + bz1, 0 ) : u = at3(rx0,ry1,rz1);
*q = @g3( b11 + bz1, 0 ) : v = at3(rx1,ry1,rz1);
b = lerp(t, u, v);
d = lerp(sy, a, b);
ProcedureReturn lerp(sz, c, d);
EndProcedure
Procedure normalize2(*v.InnerDoubleArray)
Protected s.d = Sqr(*v\d[0] * *v\d[0] + *v\d[1] * *v\d[1])
*v\d[0] = *v\d[0] / s
*v\d[1] = *v\d[1] / s
EndProcedure
Procedure normalize3(*v.InnerDoubleArray)
Protected s.d = Sqr(*v\d[0] * *v\d[0] + *v\d[1] * *v\d[1] + *v\d[2] * *v\d[2])
*v\d[0] = *v\d[0] / s
*v\d[1] = *v\d[1] / s
*v\d[2] = *v\d[2] / s
EndProcedure
Procedure init()
Protected i.i, j.i, k.i, tmp.i
Protected *t.InnerDoubleArray
i = 0
While i < #B
p(i) = i
tmp = ((Random(2147483647) % (#B + #B)) - #B)
g1(i) = tmp / #B
For j = 0 To 1
tmp = ((Random(2147483647) % (#B + #B)) - #B)
g2(i, j) = tmp / #B
Next
normalize2(@g2(i, 0))
For j = 0 To 2
tmp = ((Random(2147483647) % (#B + #B)) - #B)
g3(i, j) = tmp / #B
Next
normalize3(@g3(i, 0))
i + 1
Wend
i - 1
While i > 0
i - 1
k = p(i)
j = Random(2147483647) % #B
p(i) = p(j)
p(j) = k;
Wend
i = 0
While i < #B + 2
p(#B + i) = p(i)
g1(#B + i) = g1(i)
For j = 0 To 1
g2(#B + i, j) = g2(i, j)
Next
For j = 0 To 2
g3(#B + i, j) = g3(i, j)
Next
i + 1
Wend
EndProcedure
Procedure.d PerlinNoise1D(x.d, alpha.d, beta.d, interations.i)
Protected i.i
Protected val.d = 0, sum.d = 0
Protected p.d = 1, scale.d = 1
p = x
For i = 1 To interations
val = noise1(p)
sum + val / scale
scale * alpha
p * beta
Next
ProcedureReturn(sum)
EndProcedure
Procedure.d PerlinNoise2D(x.d ,y.d, alpha.d, beta.d, interations.i)
Protected i.i
Protected val.d = 0, sum.d = 0
Protected scale.d = 1
Dim args.d(1)
args(0) = x
args(1) = y
For i = 1 To interations
val = noise2(args())
sum + val / scale
scale * alpha
args(0) * beta
args(1) * beta
Next
ProcedureReturn(sum)
EndProcedure
Procedure.d PerlinNoise3D(x.d, y.d, z.d, alpha.d, beta.d, interations.i)
Protected i.i
Protected val.d = 0, sum.d = 0
Protected scale.d = 1
Dim args.d(2)
args(0) = x
args(1) = y
args(2) = z
For i = 1 To interations
val = noise3(args())
sum = sum + (val / scale)
scale * alpha
args(0) * beta
args(1) * beta
args(2) * beta
Next
ProcedureReturn(sum)
EndProcedure
Global ww = 1024
Global wh = 768
Global window = OpenWindow(#PB_Any,0,0,ww,wh,"")
OpenWindowedScreen(WindowID(window),0,0,ww,wh,1,0,0,#PB_Screen_NoSynchronization)
Global camera = CreateCamera(#PB_Any,0,0,100,100)
MoveCamera(camera,1000,1000,1000)
CameraLookAt(camera,500,500,500)
; CameraRenderMode(camera,#PB_Camera_Wireframe)
CreateNode(0,500,500,500)
AttachNodeObject(0,CameraID(camera))
Global light.i = CreateLight(#PB_Any,$FFFFFF,-2000,2000,2000)
AmbientColor($505050)
Global cube_mesh.i = CreateCube(#PB_Any,10)
Global cube_entity.i = CreateEntity(#PB_Any,MeshID(cube_mesh),#PB_Material_None)
; generate minecraft terrain
;
#CHUNCK_SIZE = 100
Dim world.i(#CHUNCK_SIZE,#CHUNCK_SIZE,#CHUNCK_SIZE)
Dim surface.i(#CHUNCK_SIZE,#CHUNCK_SIZE,#CHUNCK_SIZE)
Dim cave.i(#CHUNCK_SIZE,#CHUNCK_SIZE,#CHUNCK_SIZE)
; generate surface
;
div.f = 2 / #CHUNCK_SIZE
For z = 0 To #CHUNCK_SIZE-1
For x = 0 To #CHUNCK_SIZE-1
noise.d = Unsigned(PerlinNoise2D(div * x, div * z, 4, 4, 10))
height.i = (#CHUNCK_SIZE/2) + Int(noise * (#CHUNCK_SIZE/2))
surface(x,height,z) = 255
;fill internal
;
For fill = height To 0 Step -1
surface(x,fill,z) = 255
Next
Next
Next
; generate cave
;
div.f = 500 / (#CHUNCK_SIZE*10)
For z = 0 To (#CHUNCK_SIZE-1)
For y = 0 To #CHUNCK_SIZE-1
For x = 0 To #CHUNCK_SIZE-1
noise.d = Unsigned(PerlinNoise3D(div * x, div * y, div * z, 2, 2, 5))
value.i = Int(noise * 255)
If value < 128
value = 0
EndIf
cave(x,y,z) = value
Next
Next
Next
; boolean operation : surface - cave = world
;
For z = 0 To (#CHUNCK_SIZE-1)
For y = 0 To #CHUNCK_SIZE-1
For x = 0 To #CHUNCK_SIZE-1
If surface(x,y,z) = 255
world(x,y,z) = surface(x,y,z) - cave(x,y,z)
EndIf
Next
Next
Next
; push world into static geometry
;
static_world.i = CreateStaticGeometry(#PB_Any,#CHUNCK_SIZE*1000,#CHUNCK_SIZE*1000,#CHUNCK_SIZE*1000,#False)
For z = 0 To #CHUNCK_SIZE-1
For y = 0 To #CHUNCK_SIZE-1
For x = 0 To #CHUNCK_SIZE-1
If world(x,y,z) = 255
AddStaticGeometryEntity(static_world, EntityID(cube_entity), x*10, y*10, z*10 )
EndIf
Next
Next
Next
BuildStaticGeometry(static_world)
HideEntity(cube_entity,#True)
While #True
If WindowEvent() = #PB_Event_CloseWindow
Break
EndIf
RotateNode(0,0,1,0,#PB_Relative)
ClearScreen(0)
RenderWorld()
FlipBuffers()
Wend
Tu génères en premier la surface via un perlin 2D que tu places dans un volume 3D ( tableau 3D )
Tu remplis ensuite de ta surface vers le bas de ton tableau 3D que tu as créer pour ta surface
Tu généres ensuite des cavités ( pour faire des grottes ) via un perlin 3D que tu stocke séparément dans un autre tableau 3D
tu applique sur ce tableau de cavité un thresold pour pour avoir que du "blanc" ou du "noir", soit 0 ou 255 donc selon le thresold défini par tes soins
Tu soustrait le tableau de surface & le tableau de cavité pour avoir ton monde final & le tour est joué , un générateur de terrain pour mineclone ^^
Reste plus que l'inventaire des outils maintenant ^^
Tu place ensuite tes arbres de manière aléatoire sur ton terrain selon l'altitude par exemple.
L'idéal serais de pouvoir avoir des "préfab" d'objet dans des fichiers séparé
-
kelebrindae
- Messages : 579
- Inscription : ven. 11/mai/2007 15:21
Re: Créer un monde "à la minecraft"
Super classe! En voilà un code, qu'il est utile; Merci G-Rom!
J'intégrerai ça dès que j'aurai ajouté la possibilité d'avoir plusieurs "chunks" simultanément (c'est la prochaine étape).
J'intégrerai ça dès que j'aurai ajouté la possibilité d'avoir plusieurs "chunks" simultanément (c'est la prochaine étape).
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
-
kelebrindae
- Messages : 579
- Inscription : ven. 11/mai/2007 15:21
Re: Créer un monde "à la minecraft"
Voici une nouvelle version, mais je ne crois pas que je vais la garder. Je m'explique.
Pour afficher un décor plus grand, la solution la plus directe est d'augmenter la taille du morceau de monde (ou "chunk") affiché. Mais voilà: plus le chunk est grand, plus c'est long de le mettre à jour (on le recrée de zéro à chaque fois, car on utilise la géométrie statique), et donc plus la destruction de bloc devient pénible.
Autre solution: avoir plusieurs chunks. C'est ce que fait la version d'aujourd'hui => le chunk central est entouré de chunks de même taille que je crée à la volée quand ils arrivent dans le champs de vision et que je détruis quand ils en sortent.
Mais ça ne me satisfait pas trop, car les perfs tombent assez vite quand on a plusieurs groupes de géométrie statique: en fait, avoir un seul groupe de 90000 polygones tourne plus vite que d'avoir neuf groupes de 10000. De plus, quand un chunk est détruit, les ombres qu'il projetait sur les autres disparaissent et dans certains cas, ça se voit; bof-bof...
=> il faut que je trouve autre chose.
Vous pouvez quand même jeter un oeil sur le truc (en restant sur le chunk vert car sur les autres, les collisions ne sont pas gérées) pour vous rendre compte de ce que ça donne; moi, je retourne me creuser la tête...
http://keleb.free.fr/codecorner/downloa ... eclone.zip
Pour afficher un décor plus grand, la solution la plus directe est d'augmenter la taille du morceau de monde (ou "chunk") affiché. Mais voilà: plus le chunk est grand, plus c'est long de le mettre à jour (on le recrée de zéro à chaque fois, car on utilise la géométrie statique), et donc plus la destruction de bloc devient pénible.
Autre solution: avoir plusieurs chunks. C'est ce que fait la version d'aujourd'hui => le chunk central est entouré de chunks de même taille que je crée à la volée quand ils arrivent dans le champs de vision et que je détruis quand ils en sortent.
Mais ça ne me satisfait pas trop, car les perfs tombent assez vite quand on a plusieurs groupes de géométrie statique: en fait, avoir un seul groupe de 90000 polygones tourne plus vite que d'avoir neuf groupes de 10000. De plus, quand un chunk est détruit, les ombres qu'il projetait sur les autres disparaissent et dans certains cas, ça se voit; bof-bof...
=> il faut que je trouve autre chose.
Vous pouvez quand même jeter un oeil sur le truc (en restant sur le chunk vert car sur les autres, les collisions ne sont pas gérées) pour vous rendre compte de ce que ça donne; moi, je retourne me creuser la tête...
http://keleb.free.fr/codecorner/downloa ... eclone.zip
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Re: Créer un monde "à la minecraft"
C'est vraiment beaucoup plus lent ? Pour les ombres elles devraient etre recalculées à chaque frame alors je ne comprends pas trop pourquoi on le voit..
Re: Créer un monde "à la minecraft"
je jetterais un œil tout a l'heure.
Si j'étais toi, pour géré des mondes immense , je n'aurais qu'un seul morceau que je mettrais à jour en fonction de ma position , je m'explique :
ton monde est représenté par des informations brute dans un tableau en 3 dimensions, pour faire simple , une brique ou pas de brique.
tu te déplaces dans ton mondes via les axes XY & Z, ton affichage affiche le monde selon ces positions, ce qui te force à mettre les morceaux de monde les uns à coté des autres. imagine que tu veuilles représenté un monde immense préfabriqué au préalable d'un million de bloc de coté , comment va tu le représenté ?
mettre des géométrie statique les unes à coté des autres ? ce n'est pas la bonne solution, mais c'est une solution "naturelle".
L'idéal serais que tu ai 2 mondes , un monde affichable, un monde de donnée pure ( l'information des blocs ) et que tu fasses défilé le monde des donnée brute dans le monde affichable afin de donnée l'illusion de déplacement, dans ce cas c'est le monde qui défile et non plus le joueur qui se déplace dans un espace restreint.
Admettons que ton monde ai un horizon maximum de 100 blocs, tu créer un monde affichable alors un peu plus grand de 120 bloc par exemple
et quand ton joueur avance de 20 blocs, tu déplaces ton monde de donnée de 20 blocs , tu met à jour ton monde affichable et tu recule ton joueur de (20 bloc * taille bloc) dans l'espace 3D, ton monde est donc mis à jour tout les 20 blocs et c'est imperceptible par le joueur. j'espère que tu m'as compris ^^
Si j'étais toi, pour géré des mondes immense , je n'aurais qu'un seul morceau que je mettrais à jour en fonction de ma position , je m'explique :
ton monde est représenté par des informations brute dans un tableau en 3 dimensions, pour faire simple , une brique ou pas de brique.
tu te déplaces dans ton mondes via les axes XY & Z, ton affichage affiche le monde selon ces positions, ce qui te force à mettre les morceaux de monde les uns à coté des autres. imagine que tu veuilles représenté un monde immense préfabriqué au préalable d'un million de bloc de coté , comment va tu le représenté ?
mettre des géométrie statique les unes à coté des autres ? ce n'est pas la bonne solution, mais c'est une solution "naturelle".
L'idéal serais que tu ai 2 mondes , un monde affichable, un monde de donnée pure ( l'information des blocs ) et que tu fasses défilé le monde des donnée brute dans le monde affichable afin de donnée l'illusion de déplacement, dans ce cas c'est le monde qui défile et non plus le joueur qui se déplace dans un espace restreint.
Admettons que ton monde ai un horizon maximum de 100 blocs, tu créer un monde affichable alors un peu plus grand de 120 bloc par exemple
et quand ton joueur avance de 20 blocs, tu déplaces ton monde de donnée de 20 blocs , tu met à jour ton monde affichable et tu recule ton joueur de (20 bloc * taille bloc) dans l'espace 3D, ton monde est donc mis à jour tout les 20 blocs et c'est imperceptible par le joueur. j'espère que tu m'as compris ^^
Re: Créer un monde "à la minecraft"
Sur Mac je ne constate pas de ralentissement. Je suis à 60fps presque en permanence.
Re: Créer un monde "à la minecraft"
Bonjour,
Vraiment sympa et rapide pour ma part (moyenne 1000FPS). Par contre des que je vais sur une case autre que de "l'herbe" je tombe dans le vide...
Une petite capture

Cordialement,
GallyHC
Vraiment sympa et rapide pour ma part (moyenne 1000FPS). Par contre des que je vais sur une case autre que de "l'herbe" je tombe dans le vide...
Une petite capture

Cordialement,
GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Re: Créer un monde "à la minecraft"
Chez moi, le compilateur plante direct. (Avec le dernier zip)
@++
@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
- falsam
- Messages : 7336
- Inscription : dim. 22/août/2010 15:24
- Localisation : IDF (Yvelines)
- Contact :
Re: Créer un monde "à la minecraft"
Idem pour moi. Runtime erreur du compilateur. J'ai essayé aussi avec le sous systeme OpenGl et j'ai la même erreur.venom a écrit :Chez moi, le compilateur plante direct. (Avec le dernier zip)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Re: Créer un monde "à la minecraft"
C'est un bug lié au géométrie statique, c'est de ma faute
C'est en correction
C'est en correction
-
kelebrindae
- Messages : 579
- Inscription : ven. 11/mai/2007 15:21
Re: Créer un monde "à la minecraft"
Coucou, me revoilà!
Voici une grosse mise à jour du code, où tous le système d'affichage a été revu: chaque chunk (un bloc de monde) est constitué d'un seul mesh alors qu'avant, j'avais un mesh par cube. De plus, on peut maintenant se balader dans un monde de 100x100 chunks qui sont construits à la volée (mais attention, si vous sortez des limites, ça plante...
).
Par ailleurs, j'ai utilisé le code "Bruit de Perlin" donné par G-Rom pour rendre l'environnement un peu plus intéressant à visiter.
Récupérez le bouzin ici: http://keleb.free.fr/codecorner/downloa ... eclone.zip
Attention, le code n'est pas beau: il y a plein d'endroits où les calculs sont "bruts de fonderie" et pas du tout optimisés. De plus, pour déterminer si un chunk est dans le champ de vision, j'ai utilisé une méthode bourrin (ajout d'une entité + "CheckObjectVisibility") au lieu d'un octree comme il faudrait. Mais comme je n'ai pas encore trop bien compris comment en implémenter un en PB, j'ai remis ça à plus tard...
Mais je rencontre des problèmes (je fais appel aux bonnes volontés, là
):
1) Quand on met l'environnement (les chunks) dans la géométrie statique, on doit le faire d'un seul coup: on ne peut pas les ajouter un par un => chaque mise à jour du décor fait un "CreateStatic...", un "Add..." de tous les chunks visibles, et un "Build...", même si un seul est ajouté/modifié. Les "add" ne coûtent rien, mais le "Build" a un coup incompressible d'environ 50ms sur ma machine, ce qui provoque une saccade. Il y aurait moyen d'éviter ça?
2) S'il y a plus de 65535 polygones dans le groupe statique, les ombres plantent; du coup, je les ai désactivées. Passer par des submeshes résoudrait-il le problème ?
3) Comme chaque chunk est un seul mesh, il n'a qu'un seul material. Je pourrais passer par des submeshes, mais les "addVertex" et "addFace" ne permettent pas de viser un submesh particulier, du coup il faudrait ajouter toute la terre, puis toute l'herbe, puis tous le bois, etc. => plein de boucle en plus! Du coup, j'ai pensé à un truc: je code un n° de matériau dans la couleur des vertex, et c'est le script material qui choisit la texture en fonction de cette couleur. C'est possible, ça?
4) Sur certains PC, j'ai des bugs sur l'affichage:

C'est quoi, ce schmurtz?
Allez, sur ce, bon week-end!
Voici une grosse mise à jour du code, où tous le système d'affichage a été revu: chaque chunk (un bloc de monde) est constitué d'un seul mesh alors qu'avant, j'avais un mesh par cube. De plus, on peut maintenant se balader dans un monde de 100x100 chunks qui sont construits à la volée (mais attention, si vous sortez des limites, ça plante...
Par ailleurs, j'ai utilisé le code "Bruit de Perlin" donné par G-Rom pour rendre l'environnement un peu plus intéressant à visiter.
Récupérez le bouzin ici: http://keleb.free.fr/codecorner/downloa ... eclone.zip
Attention, le code n'est pas beau: il y a plein d'endroits où les calculs sont "bruts de fonderie" et pas du tout optimisés. De plus, pour déterminer si un chunk est dans le champ de vision, j'ai utilisé une méthode bourrin (ajout d'une entité + "CheckObjectVisibility") au lieu d'un octree comme il faudrait. Mais comme je n'ai pas encore trop bien compris comment en implémenter un en PB, j'ai remis ça à plus tard...
Mais je rencontre des problèmes (je fais appel aux bonnes volontés, là
1) Quand on met l'environnement (les chunks) dans la géométrie statique, on doit le faire d'un seul coup: on ne peut pas les ajouter un par un => chaque mise à jour du décor fait un "CreateStatic...", un "Add..." de tous les chunks visibles, et un "Build...", même si un seul est ajouté/modifié. Les "add" ne coûtent rien, mais le "Build" a un coup incompressible d'environ 50ms sur ma machine, ce qui provoque une saccade. Il y aurait moyen d'éviter ça?
2) S'il y a plus de 65535 polygones dans le groupe statique, les ombres plantent; du coup, je les ai désactivées. Passer par des submeshes résoudrait-il le problème ?
3) Comme chaque chunk est un seul mesh, il n'a qu'un seul material. Je pourrais passer par des submeshes, mais les "addVertex" et "addFace" ne permettent pas de viser un submesh particulier, du coup il faudrait ajouter toute la terre, puis toute l'herbe, puis tous le bois, etc. => plein de boucle en plus! Du coup, j'ai pensé à un truc: je code un n° de matériau dans la couleur des vertex, et c'est le script material qui choisit la texture en fonction de cette couleur. C'est possible, ça?
4) Sur certains PC, j'ai des bugs sur l'affichage:

Allez, sur ce, bon week-end!
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Re: Créer un monde "à la minecraft"
C'est du bon boulot.
Pour les quadtree, cela marche en conjonction avec la mise en place d'un frustum culling, ca reviens un peu à refaire le renderer d'ogre.
C'est pas la mère à boire, mais tu peu l'évité. le frustum culling c'est le cone que représente la camera dans ton monde.
Le Quadtree , c'est assez simple à codé, je viens de terminé le miens en C++ pour mon jeu, le miens est en 2D , le principe reste le même pour la 3D.
Si tu ne comprends pas trop , je pourrais t'aidé à l'implémenté.
Tu peu en revanche optimisé encore plus en utilisant qu'un seul mesh par type de bloc, je m'explique :
ton niveau est un "nuage" de point & les blocs on une taille constante. Tu gagnerais donc en performance à supprimé / recréer ton mesh à chaque modification du terrain, ton terrain pourrais être triangulé avec la technique de delaunay. tu auras autant de mesh que de type de bloc, ogre en interne fera le reste du travail ( octree / frustum / backface culling / etc... )
Manque les cavité dans ton exemple
Pour les quadtree, cela marche en conjonction avec la mise en place d'un frustum culling, ca reviens un peu à refaire le renderer d'ogre.
C'est pas la mère à boire, mais tu peu l'évité. le frustum culling c'est le cone que représente la camera dans ton monde.
Le Quadtree , c'est assez simple à codé, je viens de terminé le miens en C++ pour mon jeu, le miens est en 2D , le principe reste le même pour la 3D.
Si tu ne comprends pas trop , je pourrais t'aidé à l'implémenté.
Tu peu en revanche optimisé encore plus en utilisant qu'un seul mesh par type de bloc, je m'explique :
ton niveau est un "nuage" de point & les blocs on une taille constante. Tu gagnerais donc en performance à supprimé / recréer ton mesh à chaque modification du terrain, ton terrain pourrais être triangulé avec la technique de delaunay. tu auras autant de mesh que de type de bloc, ogre en interne fera le reste du travail ( octree / frustum / backface culling / etc... )
Manque les cavité dans ton exemple
-
kelebrindae
- Messages : 579
- Inscription : ven. 11/mai/2007 15:21
Re: Créer un monde "à la minecraft"
Exact, pas de cavernes: je voulais aller au plus simple pour commencer, et puis le monde n'est pas très épais (64 blocs de haut seulement); mais garde précieusement l'idée et le code au chaud!
Par contre là:
Tu proposes de faire un mesh pour l'herbe, un pour la terre, un pour le bois, un pour la pierre, etc. c'est ça? Donc, au pire des cas, je me retrouve avec une centaine de meshes par chunk à garder en mémoire dans un coin, ce qui fait que quand je casse un bloc d'herbe, la mise à jour est moins lourde car je ne touche qu'une partie du chunk...
Ah mais ouais, tiens; en l'écrivant ça me paraît soudain plus clair! Effectivement, c'est une autre idée à creuser. Merci!
Tiens, tant qu'on y est, j'ai d'autres questions:
- Si je fais le "BuildStaticGeometry" dans un thread parallèle à la boucle principale, est-ce que ça me permettrait d'éviter les saccades ? (genre: pendant que le groupe statique n°0 est affiché, je construis un groupe statique n°1 avec le décor mis à jour dans un thread, et dès qu'il est fini j'efface le n°0 et je recommence en inversant le n°1 et le n°0; une sorte de "flipBuffers" avec la géométrie statique, quoi.)
- Est-il possible de faire des "GetMeshDatas" ou des "CopyArray" avec un tableau de tableaux ou un tableau situé dans une structure? Parce que je voulais stocker les infos des meshes élémentaires au lieu de faire des "GetMeshDatas" à chaque fois, et je n'ai pas réussi.
Exemple: ou bien
Je ne suis pas parvenu à trouver une solution pour ça. Idem pour "CopyArray".
Ce n'est pas possible?
Par contre là:
Je ne suis pas sûr d'avoir compris...G-Rom a écrit :Tu peux en revanche optimiser encore plus en utilisant qu'un seul mesh par type de bloc, je m'explique :
ton niveau est un "nuage" de point & les blocs ont une taille constante. Tu gagnerais donc en performance à supprimer / recréer ton mesh à chaque modification du terrain
Tu proposes de faire un mesh pour l'herbe, un pour la terre, un pour le bois, un pour la pierre, etc. c'est ça? Donc, au pire des cas, je me retrouve avec une centaine de meshes par chunk à garder en mémoire dans un coin, ce qui fait que quand je casse un bloc d'herbe, la mise à jour est moins lourde car je ne touche qu'une partie du chunk...
Ah mais ouais, tiens; en l'écrivant ça me paraît soudain plus clair! Effectivement, c'est une autre idée à creuser. Merci!
Tiens, tant qu'on y est, j'ai d'autres questions:
- Si je fais le "BuildStaticGeometry" dans un thread parallèle à la boucle principale, est-ce que ça me permettrait d'éviter les saccades ? (genre: pendant que le groupe statique n°0 est affiché, je construis un groupe statique n°1 avec le décor mis à jour dans un thread, et dès qu'il est fini j'efface le n°0 et je recommence en inversant le n°1 et le n°0; une sorte de "flipBuffers" avec la géométrie statique, quoi.)
- Est-il possible de faire des "GetMeshDatas" ou des "CopyArray" avec un tableau de tableaux ou un tableau situé dans une structure? Parce que je voulais stocker les infos des meshes élémentaires au lieu de faire des "GetMeshDatas" à chaque fois, et je n'ai pas réussi.
Exemple:
Code : Tout sélectionner
Dim vertexInfos.PB_vertex(3,0)
GetMeshData(cubeMesh(i),0,vertexInfos(2, ), [etc..]Code : Tout sélectionner
Stucture vertexInfos_struct
infos.PB_vertex()
endstructure
Dim vertexInfos.vertexInfos_struct(3)
GetMeshData(cubeMesh(i),0,vertexInfos\infos(), [etc..]Ce n'est pas possible?
Les idées sont le souvenir de choses qui ne se sont pas encore produites.