IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Découvrez OpenGL 1.1 en VB6/VBA

Image non disponible


précédentsommairesuivant

XV. Utilisation des listes et des tableaux

Consultez le tutoriel La géométrie en OpenGL : vers les VertexBufferObject.
Il traite notamment des tableaux et des listes, ainsi que des VertexBufferObjets que nous ne verrons pas dans ce tutoriel (c'est une extension).

XV-A. Utilisation des tableaux

Pour dessiner notre cube, nous avons envoyé chaque information une par une.
Il est possible de définir des tableaux d'informations pour réduire les appels aux fonctions.

En VB, nous ne pouvons pas définir des tableaux fixes préremplis.
Pour simplifier un peu le code, nous définissons une petite fonction pour remplir nos tableaux :

Fonction de remplissage de tableau
Sélectionnez
' Fonction de remplissage de tableau 
Public Function BuildArray(pArray, pValues As Variant)
Dim lCpt As Long
Dim lIndice As Long
lIndice = LBound(pArray)
For lCpt = LBound(pValues) To UBound(pValues)
    pArray(lIndice) = pValues(lCpt)
    lIndice = lIndice + 1
Next
End Function

On donnera à la fonction un paramètre pValues contenant les valeurs sous forme de tableau dynamique (Array).
On recevra dans le paramètre pArray le tableau rempli.

Ajoutons la définition des tableaux en en-tête de module :

En en-tête de module
Sélectionnez
' Tableaux pour le cube
Private VertexArray(1 To 72) As Single  ' 24 vertices * 3 coordonnées
Private ColorArray(1 To 72) As Single  ' 24 couleurs * 3 composantes
Private NormalArray(1 To 72) As Single  ' 24 normales * 3 coordonnées
Private TexCoordArray(1 To 48) As Single  ' 24 texels * 2 coordonnées
Private IndiceArray(1 To 24) As Long  ' 6 faces * 4 vertex

Les tableaux sont initialisés dans la fonction InitScene :

Initialise les tableaux pour le cube
Sélectionnez
' Initialise les tableaux pour le cube
Const cT As Long = 5
BuildArray VertexArray, Array( _
                1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, _
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, _
                1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, _
                -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, _
                -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, _
                1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1)
BuildArray ColorArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, _
                1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, _
                1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1)
BuildArray NormalArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, _
                0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, _
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0)
BuildArray TexCoordArray, Array( _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                cT, cT, 0, cT, 0, 0, cT, 0)
BuildArray IndiceArray, Array( _
                0, 1, 2, 3, _
                4, 5, 6, 7, _
                8, 9, 10, 11, _
                12, 13, 14, 15, _
                16, 17, 18, 19, _
                20, 21, 22, 23)

Il y a un tableau par information :

  • les vertices ;
  • les couleurs ;
  • les normales ;
  • les coordonnées de texture.

Et un tableau d'indices qui définit les faces.
Ces indices démarrent à partir de 0.

Pour dessiner le cube à partir des tableaux il faut :

  • activer chacun des tableaux utilisés avec la fonction glEnableClientState ;
  • définir chaque tableau avec la fonction gl*pointer correspondante ;
  • dessiner les éléments avec la fonction glDrawElements ;
  • désactiver les tableaux avec la fonction glDisableClientState.

Le code de dessin du cube devient :

Code de dessin du cube avec les tableaux
Sélectionnez
glEnableClientState GL_VERTEX_ARRAY
glEnableClientState GL_COLOR_ARRAY
glEnableClientState GL_NORMAL_ARRAY
glEnableClientState GL_TEXTURE_COORD_ARRAY

glVertexPointer 3, GL_FLOAT, 0, VertexArray(1)
glColorPointer 3, GL_FLOAT, 0, ColorArray(1)
glNormalPointer GL_FLOAT, 0, NormalArray(1)
glTexCoordPointer 2, GL_FLOAT, 0, TexCoordArray(1)

glDrawElements GL_QUADS, 24, GL_UNSIGNED_INT, IndiceArray(1)

glDisableClientState GL_VERTEX_ARRAY
glDisableClientState GL_COLOR_ARRAY
glDisableClientState GL_NORMAL_ARRAY
glDisableClientState GL_TEXTURE_COORD_ARRAY

Dans l'appel à glDrawElements on précise qu'on définit des quads, et qu'il y a 24 vertices.

Dans notre exemple, nous n'avons pas réduit le nombre d'informations, chaque vertice possédant ses propres informations.
Quel intérêt alors d'utiliser les tableaux ?
Avec les tableaux, on peut réduire le nombre d'informations si plusieurs vertices sont identiques (mêmes coordonnées, même couleur…).
Il suffit alors d'utiliser plusieurs fois le même indice dans le tableau IndiceArray.
Nous pouvons également facilement modifier l'objet dynamiquement, en modifiant les informations dans les tableaux.

XV-B. Utilisation des listes

Les listes d'affichage permettent de stocker des instructions de dessin.
On peut ainsi utiliser une liste d'affichage pour dessiner rapidement un même objet plusieurs fois.

Il est possible de combiner les tableaux et les listes, ce que nous allons faire.

Une liste est créée à l'aide de la fonction glGenLists, en donnant en paramètre le nombre de listes à créer.
La fonction renvoie le numéro de la première liste créée.

Ajoutons une variable en en-tête pour sauvegarder cet identifiant :

En en-tête de module
Sélectionnez
' Identifiant de la liste pour le cube
Private gListCube As Long

Les déclarations de tableaux n'ont plus besoin d'être globales, on peut les déplacer dans la fonction InitScene.

On commence ensuite une liste avec la fonction glNewList.
On la termine avec la fonction glEndList.
Entre ces deux fonctions, on place le code de dessin du cube.

Voici le code de création de la liste d'affichage du cube :

Création de la liste d'affichage du cube
Sélectionnez
' Crée la liste pour le cube
Const cT As Long = 5
Dim VertexArray(1 To 72) As Single  ' 24 vertices * 3 coordonnées
Dim ColorArray(1 To 72) As Single  ' 24 couleurs * 3 composantes
Dim NormalArray(1 To 72) As Single  ' 24 normales * 3 coordonnées
Dim TexCoordArray(1 To 48) As Single  ' 24 texels * 2 coordonnées
Dim IndiceArray(1 To 24) As Long  ' 6 faces * 4 vertex
BuildArray VertexArray, Array( _
                1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, _
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, _
                1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, _
                -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, _
                -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, _
                1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1)
BuildArray ColorArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, _
                1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, _
                1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1)
BuildArray NormalArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, _
                0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, _
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0)
BuildArray TexCoordArray, Array( _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                cT, cT, 0, cT, 0, 0, cT, 0)
BuildArray IndiceArray, Array( _
                0, 1, 2, 3, _
                4, 5, 6, 7, _
                8, 9, 10, 11, _
                12, 13, 14, 15, _
                16, 17, 18, 19, _
                20, 21, 22, 23)
gListCube = glGenLists(1)
glNewList gListCube, GL_COMPILE
    glEnableClientState GL_VERTEX_ARRAY
    glEnableClientState GL_COLOR_ARRAY
    glEnableClientState GL_NORMAL_ARRAY
    glEnableClientState GL_TEXTURE_COORD_ARRAY
            
    glVertexPointer 3, GL_FLOAT, 0, VertexArray(1)
    glColorPointer 3, GL_FLOAT, 0, ColorArray(1)
    glNormalPointer GL_FLOAT, 0, NormalArray(1)
    glTexCoordPointer 2, GL_FLOAT, 0, TexCoordArray(1)
            
    glDrawElements GL_QUADS, 24, GL_UNSIGNED_INT, IndiceArray(1)
            
    glDisableClientState GL_VERTEX_ARRAY
    glDisableClientState GL_COLOR_ARRAY
    glDisableClientState GL_NORMAL_ARRAY
    glDisableClientState GL_TEXTURE_COORD_ARRAY
glEndList

Une fois la liste créée, il suffit de l'appeler avec la fonction glCallList pour effectuer le dessin.

Dessin du cube
Sélectionnez
' Dessin du cube
glCallList gListCube

Il est également possible d'afficher plusieurs listes en un seul appel à la fonction glCallLists (nous l'utiliserons pour l'affichage des textes).

Avec les listes d'affichage, il devient facile (et rapide) de dessiner plusieurs fois le même objet.
Dessinons 10 cubes en les décalant légèrement :

Dessin de 10 cubes
Sélectionnez
' Dessin de 10 cubes
Dim lCptCube As Long
For lCptCube = 1 To 10
    glCallList gListCube
    glTranslated 0, 0, -3
Next
Image non disponible

Par contre, les listes d'affichage ne conviennent pas si on souhaite modifier dynamiquement l'objet.
La liste ainsi créée est statique.

XVI. Rappel du code complet

Un rappel du contenu du module VB à ce stade du tutoriel, avec l'affichage de dix cubes en utilisant les listes et les tableaux :

Rappel du code complet
Sélectionnez
Option Explicit

' Temps écoulé pour calcul du frame rate
Private gElapsedTime As Long
' Nombre d'affichages pour calcul du frame rate
Private gDisplayCount As Long
' RotationX
Private gRotateX As Double
' RotationY
Private gRotateY As Double
' Zoom
Private gZoom As Double
' RotationY de la lampe
Private gLightRotate As Double
' Identifiant de la texture plancher
Private gTexturePlancher As Long
' Identifiant de la texture de la sphère
Private gTextureSphere As Long
' Identifiant de la liste pour le cube
Private gListCube As Long

Function FonctionOpenGL()
' Chargement de freeGLUT
If Not LoadFreeGlut(CurrentProject.Path) Then
    MsgBox "Impossible de charger la bibliothèque freeGLUT"
    Exit Function
End If
' Initialisation de la bibliothèque
glutInit 0&, ""
' Initialisation du mode d'affichage
glutInitDisplayMode GLUT_RGBA Or GLUT_DOUBLE Or GLUT_DEPTH
' Définition de l'option de sortie de boucle
glutSetOption GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS
' Création d'une fenêtre
glutCreateWindow "Tutoriel fenêtre GLUT"
' Fonction d'affichage
glutDisplayFunc AddressOf CallBackDraw
' Fonctions de rappel clavier
glutSpecialFunc AddressOf CallBackSpecial
' Fonction de rappel molette de souris
glutMouseWheelFunc AddressOf CallBackMouseWheel
' Appel de la fonction d'initialisation
InitScene
' Fonction d'attente
glutTimerFunc 1000 / 50, AddressOf CallBackTimer, 0
' Boucle principale
glutMainLoop
End Function

' Fonction d'attente
Public Sub CallBackTimer(ByVal value As Long)
' Rappel de la fonction d'attente
glutTimerFunc 1000 / 50, AddressOf CallBackTimer, 0
' Rafraichir l'affichage si une fenêtre openGL est active
If glutGetWindow <> 0 Then glutPostRedisplay
End Sub

' Fonction d'affichage
Public Sub CallBackDraw()
' Appel de la fonction de rendu
Call Render
' Échange les buffers
glutSwapBuffers
' Calcul et affichage du frame rate
gDisplayCount = gDisplayCount + 1
If gDisplayCount = 100 Then
    glutSetWindowTitle "Frame rate : " & format(gDisplayCount / (glutGet(GLUT_ELAPSED_TIME) - gElapsedTime) * 1000, "0,0")
    gDisplayCount = 0
    gElapsedTime = glutGet(GLUT_ELAPSED_TIME)
End If
End Sub

' Fonction d'initialisation
Public Sub InitScene()
' Mode d'affichage = remplissage
glPolygonMode GL_FRONT_AND_BACK, GL_FILL
' Tests de profondeur
glEnable GL_DEPTH_TEST
glDepthFunc GL_LEQUAL
' Initialisation des variables de visualisation
gRotateX = 0
gRotateY = 0
gZoom = 10
' Initialisation de l'éclairage
glEnable GL_LIGHTING
glEnable GL_LIGHT0
' Ajout d'une lumière diffuse
Dim lColor(1 To 4) As Single
lColor(1) = 2
lColor(2) = 2
lColor(3) = 2
lColor(4) = 1
glLightfv GL_LIGHT0, GL_DIFFUSE, lColor(1)
' Active la coloration des matériaux
glEnable GL_COLOR_MATERIAL
' Active les textures 2D
glEnable GL_TEXTURE_2D
' Charge les textures
gTexturePlancher = TextureAddFromFile(CurrentProject.Path & "\plancher.jpg")
gTextureSphere = TextureAddFromFile(CurrentProject.Path & "\terre.jpg")
' Crée la liste pour le cube
Const cT As Long = 5
Dim VertexArray(1 To 72) As Single  ' 24 vertices * 3 coordonnées
Dim ColorArray(1 To 72) As Single  ' 24 couleurs * 3 composantes
Dim NormalArray(1 To 72) As Single  ' 24 normales * 3 coordonnées
Dim TexCoordArray(1 To 48) As Single  ' 24 texels * 2 coordonnées
Dim IndiceArray(1 To 24) As Long  ' 6 faces * 4 vertex
BuildArray VertexArray, Array( _
                1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, _
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, _
                1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, _
                -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, _
                -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, _
                1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1)
BuildArray ColorArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, 1, 0.5, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, _
                1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, _
                1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1)
BuildArray NormalArray, Array( _
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, _
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, _
                0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, _
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, _
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, _
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0)
BuildArray TexCoordArray, Array( _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                0, 0, cT, 0, cT, cT, 0, cT, _
                cT, cT, 0, cT, 0, 0, cT, 0, _
                cT, cT, 0, cT, 0, 0, cT, 0)
BuildArray IndiceArray, Array( _
                0, 1, 2, 3, _
                4, 5, 6, 7, _
                8, 9, 10, 11, _
                12, 13, 14, 15, _
                16, 17, 18, 19, _
                20, 21, 22, 23)
gListCube = glGenLists(1)
glNewList gListCube, GL_COMPILE
    glEnableClientState GL_VERTEX_ARRAY
    glEnableClientState GL_COLOR_ARRAY
    glEnableClientState GL_NORMAL_ARRAY
    glEnableClientState GL_TEXTURE_COORD_ARRAY
            
    glVertexPointer 3, GL_FLOAT, 0, VertexArray(1)
    glColorPointer 3, GL_FLOAT, 0, ColorArray(1)
    glNormalPointer GL_FLOAT, 0, NormalArray(1)
    glTexCoordPointer 2, GL_FLOAT, 0, TexCoordArray(1)
            
    glDrawElements GL_QUADS, 24, GL_UNSIGNED_INT, IndiceArray(1)
            
    glDisableClientState GL_VERTEX_ARRAY
    glDisableClientState GL_COLOR_ARRAY
    glDisableClientState GL_NORMAL_ARRAY
    glDisableClientState GL_TEXTURE_COORD_ARRAY
glEndList
End Sub

' Fonction de rendu
Public Sub Render()
' Passage en matrice de projection
glMatrixMode GL_PROJECTION
' Initialisation de la matrice
glLoadIdentity
' Définition de la perspective
gluPerspective 45, 1, 0.1, 100
' Passage en matrice de modélisation-visualisation
glMatrixMode GL_MODELVIEW
' Initialisation de la matrice
glLoadIdentity
' Position de la caméra
gluLookAt 0, 0, gZoom, 0, 0, 0, 0, 1, 0
glRotated gRotateX, 1, 0, 0
glRotated gRotateY, 0, 1, 0
' Vide les buffers couleur et profondeur
glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
' Positionne la lampe
gLightRotate = gLightRotate + 
Dim lposition(1 To 4) As Single
lposition(1) = 3 * Cos(gLightRotate)
lposition(2) = 0
lposition(3) = 3 * Sin(gLightRotate)
lposition(4) = 1
glLightfv GL_LIGHT0, GL_POSITION, lposition(1)
' Dessine une sphère à l'endroit où se trouve la lampe
#If VBA7 Then
Dim lQuad As LongPtr
#Else
Dim lQuad As Long
#End If
glPushMatrix
glColor3VB vbYellow
glTranslated 3 * Cos(gLightRotate), 0, 3 * Sin(gLightRotate)
lQuad = gluNewQuadric
gluQuadricOrientation lQuad, GLU_INSIDE
gluSphere lQuad, 0.5, 20, 15
gluDeleteQuadric lQuad
glPopMatrix
' Dessine une sphère à l'opposé de la lampe
#If VBA7 Then
Dim lQuad2 As LongPtr
#Else
Dim lQuad2 As Long
#End If 
glPushMatrix
glColor3VB vbWhite
glTranslated -3 * Cos(gLightRotate), 0, -3 * Sin(gLightRotate)
glRotated -90, 1, 0, 0
glBindTexture GL_TEXTURE_2D, gTextureSphere
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
lQuad2 = gluNewQuadric
gluQuadricTexture lQuad2, GL_TRUE
gluSphere lQuad2, 1, 20, 15
gluDeleteQuadric lQuad2
glPopMatrix
' Sauvegarde la matrice
glPushMatrix
' Rotation du cube
glRotated 30, 1, 1, 1
' Affecte la texture
glBindTexture GL_TEXTURE_2D, gTexturePlancher
' Filtrage de la texture
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
' Dessin de 10 cubes
Dim lCptCube As Long
For lCptCube = 1 To 10
    glCallList gListCube
    glTranslated 0, 0, -3
Next
' N'affecte aucune texture
glBindTexture GL_TEXTURE_2D, 0
' Restaure la matrice
glPopMatrix
End Sub

' Gestion du clavier
Public Sub CallBackSpecial(ByVal key As Long, ByVal X As Long, ByVal y As Long)
Select Case key
    Case GLUT_KEY_LEFT
        gRotateY = gRotateY - 10
    Case GLUT_KEY_RIGHT
        gRotateY = gRotateY + 10
    Case GLUT_KEY_UP
        gRotateX = gRotateX - 10
    Case GLUT_KEY_DOWN
        gRotateX = gRotateX + 10
End Select
End Sub

' Gestion de la molette de la souris
Public Sub CallBackMouseWheel(ByVal wheel As Long, ByVal direction As Long, ByVal X As Long, ByVal y As Long)
gZoom = gZoom + direction
End Sub

' Fonction de remplissage de tableau
Public Function BuildArray(pArray, pValues As Variant)
Dim lCpt As Long
Dim lIndice As Long
lIndice = LBound(pArray)
For lCpt = LBound(pValues) To UBound(pValues)
    pArray(lIndice) = pValues(lCpt)
    lIndice = lIndice + 1
Next
End Function

précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.