Page 3 sur 4

Re: Créer un monde "à la minecraft"

Publié : mer. 06/nov./2013 21:52
par kelebrindae
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! :twisted:

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!

Re: Créer un monde "à la minecraft"

Publié : jeu. 07/nov./2013 0:38
par stombretrooper
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.

Re: Créer un monde "à la minecraft"

Publié : jeu. 07/nov./2013 2:38
par G-Rom
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 :

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é

Re: Créer un monde "à la minecraft"

Publié : jeu. 07/nov./2013 13:34
par kelebrindae
Super classe! En voilà un code, qu'il est utile; Merci G-Rom! :D

J'intégrerai ça dès que j'aurai ajouté la possibilité d'avoir plusieurs "chunks" simultanément (c'est la prochaine étape).

Re: Créer un monde "à la minecraft"

Publié : ven. 08/nov./2013 18:13
par kelebrindae
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... :wink:

http://keleb.free.fr/codecorner/downloa ... eclone.zip

Re: Créer un monde "à la minecraft"

Publié : ven. 08/nov./2013 18:53
par Fred
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"

Publié : ven. 08/nov./2013 19:07
par G-Rom
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 ^^

Re: Créer un monde "à la minecraft"

Publié : ven. 08/nov./2013 20:35
par MetalOS
Sur Mac je ne constate pas de ralentissement. Je suis à 60fps presque en permanence.

Re: Créer un monde "à la minecraft"

Publié : ven. 08/nov./2013 23:21
par GallyHC
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 ;)

Image

Cordialement,
GallyHC

Re: Créer un monde "à la minecraft"

Publié : ven. 08/nov./2013 23:58
par venom
Chez moi, le compilateur plante direct. (Avec le dernier zip)







@++

Re: Créer un monde "à la minecraft"

Publié : sam. 09/nov./2013 0:00
par falsam
venom a écrit :Chez moi, le compilateur plante direct. (Avec le dernier zip)
Idem pour moi. Runtime erreur du compilateur. J'ai essayé aussi avec le sous systeme OpenGl et j'ai la même erreur.

Re: Créer un monde "à la minecraft"

Publié : sam. 09/nov./2013 0:15
par G-Rom
C'est un bug lié au géométrie statique, c'est de ma faute :oops:
C'est en correction :D

Re: Créer un monde "à la minecraft"

Publié : ven. 22/nov./2013 18:00
par kelebrindae
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... :twisted: ).
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... :oops:

Mais je rencontre des problèmes (je fais appel aux bonnes volontés, là :wink: ):
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:
Image
:| C'est quoi, ce schmurtz? :|

Allez, sur ce, bon week-end!

Re: Créer un monde "à la minecraft"

Publié : ven. 22/nov./2013 20:49
par G-Rom
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 :D

Re: Créer un monde "à la minecraft"

Publié : lun. 25/nov./2013 9:57
par kelebrindae
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à:
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
Je ne suis pas sûr d'avoir compris... 8O
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! :mrgreen:

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..]
ou bien

Code : Tout sélectionner

Stucture vertexInfos_struct
  infos.PB_vertex()
endstructure
Dim vertexInfos.vertexInfos_struct(3)
GetMeshData(cubeMesh(i),0,vertexInfos\infos(), [etc..]
Je ne suis pas parvenu à trouver une solution pour ça. Idem pour "CopyArray". :?
Ce n'est pas possible?