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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[C++] Afficher plusieurs instances d'un cube. [OpenGL 4.x]


Sujet :

OpenGL

  1. #1
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut [C++] Afficher plusieurs instances d'un cube.
    Salut les OpenGL.

    Comme dit dans le titre j'ai créer une classe Cube dont je cherche a afficher 5 instances, toutes a des positions différentes tournant sur leurs axes.
    Et le résultat est que les 5 cubes sont affichés mais pas comment j'aimerai:
    Les cubes s'affichent tout d'abord a la même position le premier tourne sur lui-même et les autres accomplissent une rotation complète autour du premier cube pour revenir a la même position de départ: à la même position que le premier cube.
    Je suppose que le problème vient de mes shaders qui donc je suppose entremêle l'affichage...

    Voici le fichier vertex shader: mv_cube_vertice_shader2.glsl.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #version 420 core                                           
     
    in vec4 position;                                           
     
    out VS_OUT                                                  
    {                                                           
        vec4 color;                                             
    } vs_out;                                                   
     
     
    uniform vec4 mv_color  ;                                                            
    uniform mat4 mv_matrix ;                                                                               
     
    void main(void)                                             
    {                                                           
        gl_Position  = mv_matrix * position ;       
        vs_out.color = mv_color ;  
    }
    Voici le fichier fragment shader: mv_cube_fragment_shader2.glsl.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #version 420 core                                                                                                                       
    out vec4 color;                                               
     
    in VS_OUT                                                     
    {                                                             
        vec4 color;                                               
    } fs_in;                                                      
     
    void main(void)                                               
    {                                                             
        color = fs_in.color ;                                       
    }
    Le fichier: main.cpp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    #include <SDL2/SDL.h>
     
    #include <cstdlib>
    #include <ctime>
     
    #include <iostream>
    #include <vector>
    #include <random>
     
     
    #include <GL/glew.h>
     
     
    #define WIDTH  (int16_t) 800
    #define HEIGHT (int16_t) 600
     
    bool loop ;
     
    #define set_loop(x) (loop=(x))
     
    #include "./Files/SDL2_utils.cpp"
     
    #include "./glutils/Vector.h"
    #include "./glutils/Vertex.h"
    #include "./glutils/Matrix.h"
    #include "./glutils/Color.h"
    #include "./glutils/Cube.h"
    #include "./glutils/gl_data.h"
     
    /** To compil with:
      *
      * $ g++ -std=c++11 main.cpp -lSDL2 -lGL -lGLEW
      *
      ***********************************************/
     
    using namespace std ;
     
    int main(void) {
     
     
      if (sdl_init(SDL_INIT_EVERYTHING) != 0) {
        fprintf(stderr,"Failed to init SDL2 \n") ;
        exit(EXIT_FAILURE) ;
      }
     
      /** Setting GL attribues if not supported the GL context creation will fail. **/
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
     
      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
     
      SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
     
      SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
     
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) ; // SDL_GL_CONTEXT_PROFILE_CORE SDL_GL_CONTEXT_PROFILE_COMPATIBILITY
     
     
      SDL_Window* pWindow = NULL;
      pWindow = sdl_create_window("title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL) ;
     
      if( pWindow == NULL ) {
        fprintf(stderr,"Fail to create SDL window: %s\n", SDL_GetError());
        exit(EXIT_FAILURE) ;
      }
     
     
      /** GL context creation. **/
      SDL_GLContext glcontext ;
     
      if ((glcontext = SDL_GL_CreateContext(pWindow)) == NULL ) {
        fprintf(stderr,"Fail to create SDL GL context: %s\n", SDL_GetError());
        exit(EXIT_FAILURE) ;
      }
     
     
      if (SDL_GL_MakeCurrent(pWindow, glcontext) != 0) {
        fprintf(stderr,"Fail to make current window GL context: %s\n", SDL_GetError());
        exit(EXIT_FAILURE) ;
      }
     
      if (SDL_GL_SetSwapInterval(-1) == -1) {
        fprintf(stderr,"GL swap interval not suppported: %s\n", SDL_GetError());
        exit(EXIT_FAILURE) ;
      }
     
      // Initialize GLEW
      //glewExperimental=true;
      if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return -1;
      }
     
      int maj, min ;
     
      SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj) ;
      SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min) ;
     
      fprintf(stdout,"OpenGL Version %d.%d\n", maj, min) ;
     
      /** Load shaders program: don't know event to load a program id pro Cube instance or not -> the result is the same displaying. **/
      //GLuint program = LoadShaders("./shaders/mv_cube_vertice_shader2.glsl","./shaders/mv_cube_fragment_shader2.glsl") ;
     
      /** Define clear color. **/
      glClearColor(0.0, 0.0, 0.0, 1.0) ;
     
      /** Depth settings (needed because it default to 0.0 to 1.0). **/
      glEnable(GL_DEPTH_TEST) ;
      glDepthRangef(1.0, -1.0) ;
     
     
     
      /** Initialize a random device: **/
      random_device rd;
      mt19937 gen(rd());
     
     
      /** Define some colors. **/
      Color<float> red(1.0, 0.0, 0.0, 1.0) ;
      Color<float> green(0.0, 1.0, 0.0, 1.0) ;
      Color<float> blue(0.0, 0.2, 1.0, 1.0) ;
      Color<float> yellow(1.0, 1.0, 0.0, 1.0) ;
      Color<float> turkish(0.0, 1.0, 1.0, 1.0) ;
      Color<float> pink(1.0, 0.0, 1.0, 1.0) ;
     
      vector<Color<float>> cube_colors ;
     
      cube_colors.push_back(red) ;
      cube_colors.push_back(green) ;
      cube_colors.push_back(blue) ;
      cube_colors.push_back(yellow) ;
      cube_colors.push_back(turkish) ;
      cube_colors.push_back(pink) ;
     
      vector<Cube> cubes ;
     
      vector<Matrix<float>> matrixes ;
     
     
      uniform_real_distribution<float> rand_vertex_pos(-0.5, 0.5) ;
      uniform_real_distribution<float> rand_cube_size(0.25, 0.45) ;
     
      for (int c=0 ; c < 5 ; c++) {
     
        /** Genetrate Cube instance: **/
        Cube cube(Vertex<float>(rand_vertex_pos(gen), rand_vertex_pos(gen), 0.0f), rand_cube_size(gen)) ;
     
        /** Load a program to every instance: it has the same effect as loading one main program. **/
        GLuint program = LoadShaders("./shaders/mv_cube_vertice_shader2.glsl","./shaders/mv_cube_fragment_shader2.glsl") ;
     
     
        /** Parametrize the cube instance: **/
        cube.set_program(program) ;
        cube.set_colors(cube_colors) ;
     
        /** Store cube instance. **/
        cubes.push_back(cube) ;
     
        /** Store a matrix for every Cube instance. **/
        Matrix<float> matrix ;
        matrixes.push_back(matrix) ;
      }
     
     
      /** Executionn speed. **/
      static const int FPS=30 ;
      static const int DELAY=1000/FPS ;
     
      static const unsigned int speed = 75 ;
     
     
      set_loop(true) ;
     
      while (loop) {
     
        long int start_frame = time(0)*1000 ;
     
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
     
        int cntr=0 ;
     
        for (auto &cube : cubes) {
     
          /** Translate cube center to origin. **/
          matrixes.at(cntr).translate(-cube.get_center()) ;
     
          /** Rotate on his own axes because the cube is centered on the origin. **/
          matrixes.at(cntr).rotate_x(1)  ;
          matrixes.at(cntr).rotate_y(1)  ;
          matrixes.at(cntr).rotate_z(1)  ;
     
          /** TYranslate the cube back to his start position. **/
          matrixes.at(cntr).translate(cube.get_center()) ;
     
          /** Apply matrix. **/
          cube.set_matrix(matrixes.at(cntr)) ;
     
          /** Dislaying cube instance . **/
          cube.display() ;
     
          cntr++ ;
        }
     
     
     
        SDL_GL_SwapWindow(pWindow) ;
     
        get_events();
     
     
        long int end_frame=time(0)*1000 ;
     
        if (DELAY > (end_frame-start_frame)) {
          SDL_Delay( DELAY - (end_frame-start_frame) + speed ) ;
        }
     
     
      }
     
      SDL_GL_DeleteContext(glcontext);
      SDL_Quit() ;
     
      return 0 ;
     
    }
    Et les fichiers inclus: Cube.h.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    #ifndef GL_UTILS_CUBE_H
    #define GL_UTILS_CUBE_H
     
     
     
    #include <array>
    #include <vector>
     
    #include <algorithm>
     
    #include <GL/glew.h>
     
    #include "Vertex.h"
    #include "Color.h"
    #include "Matrix.h"
     
     
     
    using namespace std ;
     
    class Quad {
     
        array<float, 4*4> ret ;
     
        vector<Vertex<float>> faces ;
     
      public :
     
        Quad(const Vertex<float> v1, const Vertex<float> v2, const Vertex<float> v3, const Vertex<float> v4) { faces.push_back(v1) ; faces.push_back(v2) ; faces.push_back(v3) ; faces.push_back(v4) ; update_data() ;  } ;
     
        float operator [] (const int idx) { return ret.at(idx) ; }
     
        void update_data() {  int idx=0 ; for ( uint8_t cc=0 ; cc < faces.size() ; cc++) { for ( int8_t c=0 ; c < 4 ; c++) { ret.at(idx)=faces.at(cc)[c] ; idx++ ; }  } } ;
     
        float *get_quad() {  return ret.data() ;   }
     
        Vertex<float> get_vertex(const int idx) { return faces.at(idx) ; } ;
     
    } ;
     
    class Cube {
     
        vector<Quad> faces ;
     
        array<float, 4*4*6> ret ;
     
        unsigned int buffer ;
     
        vector<Color<float>>   colors ;
     
        int                    mv_color  ;
        int                    mv_matrix ;
     
        unsigned int           program  ;
     
        vector<unsigned int> texture_ids ;
     
        Vertex<float> cube_center ;
     
        Matrix<float> matrix ;
     
      public :
     
        static int buffer_counter ;
     
        Cube(Vertex<float> center, float side_length) ;
     
        void display() ;
     
        float *get_cube() {  return ret.data() ;   } ;
     
        void set_colors(vector<Color<float>> col) { copy(col.begin(), col.end(), colors.begin() ) ; }
     
        void set_program(unsigned int prg) { program=prg ; mv_color = glGetUniformLocation(program, "mv_color"); mv_matrix = glGetUniformLocation(program, "mv_matrix") ; }
     
        void set_matrix(Matrix<float> mat) { matrix = mat ; } ;
     
        Vertex<float> get_center() { return cube_center ; } ;
    } ;
     
    int Cube::buffer_counter=0 ;
     
    Cube::Cube(Vertex<float> center, float side_length) {
     
      cube_center=center ;
     
      const Vertex<float> face_front_up_left(center[0]-side_length/2,    center[1]+side_length/2, center[2]-side_length/2) ;
      const Vertex<float> face_front_up_right(center[0]+side_length/2,   center[1]+side_length/2, center[2]-side_length/2) ;
      const Vertex<float> face_front_down_right(center[0]+side_length/2, center[1]-side_length/2, center[2]-side_length/2) ;
      const Vertex<float> face_front_down_left(center[0]-side_length/2,  center[1]-side_length/2, center[2]-side_length/2) ;
     
     
      const Vertex<float> face_back_up_left(center[0]-side_length/2,    center[1]+side_length/2, center[2]+side_length/2) ;
      const Vertex<float> face_back_up_right(center[0]+side_length/2,   center[1]+side_length/2, center[2]+side_length/2) ;
      const Vertex<float> face_back_down_right(center[0]+side_length/2, center[1]-side_length/2, center[2]+side_length/2) ;
      const Vertex<float> face_back_down_left(center[0]-side_length/2,  center[1]-side_length/2, center[2]+side_length/2) ;
     
      Quad face_front(face_front_down_left, face_front_up_left, face_front_up_right, face_front_down_right) ;
     
      Quad face_back(face_back_down_left, face_back_up_left, face_back_up_right, face_back_down_right) ;
     
      Quad face_left(face_front_up_left, face_back_up_left, face_back_down_left, face_front_down_left) ;
     
      Quad face_right(face_front_up_right, face_back_up_right, face_back_down_right, face_front_down_right) ;
     
      Quad face_up(face_front_up_left, face_back_up_left, face_back_up_right, face_front_up_right) ;
     
      Quad face_down(face_front_down_left, face_front_down_right, face_back_down_right, face_back_down_left) ;
     
      faces.push_back(face_front)  ;
      faces.push_back(face_back)   ;
      faces.push_back(face_left)   ;
      faces.push_back(face_right)  ;
      faces.push_back(face_up)     ;
      faces.push_back(face_down)   ;
     
      int c=0  ;
     
      for (auto &val : faces) {
     
        for (int cc=0 ; cc < 4*4 ; cc++) {
          ret.at(c)=val[cc] ;
          c++ ;
        }
     
      }
     
      glGenBuffers(1, &buffer) ;
      glBindBuffer(GL_ARRAY_BUFFER, buffer) ;
      glBufferData(GL_ARRAY_BUFFER, 4*4*6*sizeof(float), get_cube(), GL_STATIC_DRAW) ;
      glVertexAttribPointer(buffer_counter, 4, GL_FLOAT, GL_FALSE,  0, NULL) ;
      glEnableVertexAttribArray(buffer_counter) ;
     
      buffer_counter++ ;
     
      Color<float> dummy(0.0,0.0,0.0) ;
     
      colors.resize(6,dummy) ;
     
    }
     
    void Cube::display() {
     
        glUseProgram(program) ;
     
        glUniformMatrix4fv(mv_matrix, 1, GL_FALSE, matrix.get_matrix());
     
        /** Start draw cube. **/
        glUniform4fv(mv_color, 1, colors.at(0).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4) ;
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
     
        glUniform4fv(mv_color, 1, colors.at(1).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
     
        glUniform4fv(mv_color, 1, colors.at(2).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 8,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        glUniform4fv(mv_color, 1, colors.at(3).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 12,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
     
        glUniform4fv(mv_color, 1, colors.at(4).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
     
        glUniform4fv(mv_color, 1, colors.at(5).get_vector()) ;
        glDrawArrays(GL_TRIANGLE_FAN, 20, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        /** End draw cube. **/
     
    }
     
     
     
     
    #endif
    Et le fichier: Matrix.h.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    #ifndef GL_UTILS_MATRIX
    #define GL_UTILS_MATRIX
     
    #include <array>
    #include <cmath>
     
    #include "Vector.h"
    #include "Vertex.h"
     
     
     
     
    template <typename T>
    class Matrix {
     
      private :
     
        array<T, 4*4> main_matrix        ;
     
        array<T, 4*4> processing_matrix  ;
     
        void multiply() ;
     
      public :
     
        Matrix() ;
     
        Matrix(const Matrix<T> &matrix)  ;
     
        void translate(Vertex<T> vector) ;
     
        void translate(Vector<T> vector) ;
     
        void scale(T factor) ;
     
        void scale(Vector<T> vector) ;
     
        void rotate_x(T degrees) ;
     
        void rotate_y(T degrees) ;
     
        void rotate_z(T degrees) ;
     
        void apply_vertex(Vertex<T> &vertex) ;
     
        const T *get_matrix() const { return main_matrix.data() ; }
    } ;
     
     
    template <typename T>
    Matrix<T>::Matrix() {
     
      main_matrix.at(0) = 1.0 ; main_matrix.at(4) = 0.0 ; main_matrix.at(8)  = 0.0 ; main_matrix.at(12) = 0.0 ;
      main_matrix.at(1) = 0.0 ; main_matrix.at(5) = 1.0 ; main_matrix.at(9)  = 0.0 ; main_matrix.at(13) = 0.0 ;
      main_matrix.at(2) = 0.0 ; main_matrix.at(6) = 0.0 ; main_matrix.at(10) = 1.0 ; main_matrix.at(14) = 0.0 ;
      main_matrix.at(3) = 0.0 ; main_matrix.at(7) = 0.0 ; main_matrix.at(11) = 0.0 ; main_matrix.at(15) = 1.0 ;
     
    }
     
     
    template <typename T>
    Matrix<T>::Matrix(const Matrix<T> &matrix) {
     
      copy(matrix.main_matrix.begin(), matrix.main_matrix.end(), main_matrix.begin()) ;
     
      copy(matrix.processing_matrix.begin(), matrix.processing_matrix.end(), processing_matrix.begin()) ;
    }
     
     
    template <typename T>
    void Matrix<T>::translate(Vertex<T> vector) {
     
      /** Translating trough a given vector. **/
     
      processing_matrix.at(0) = 1.0 ; processing_matrix.at(4) = 0.0 ; processing_matrix.at(8)  = 0.0 ; processing_matrix.at(12) = vector[0] ;
      processing_matrix.at(1) = 0.0 ; processing_matrix.at(5) = 1.0 ; processing_matrix.at(9)  = 0.0 ; processing_matrix.at(13) = vector[1] ;
      processing_matrix.at(2) = 0.0 ; processing_matrix.at(6) = 0.0 ; processing_matrix.at(10) = 1.0 ; processing_matrix.at(14) = vector[2] ;
      processing_matrix.at(3) = 0.0 ; processing_matrix.at(7) = 0.0 ; processing_matrix.at(11) = 0.0 ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::translate(Vector<T> vector) {
     
      /** Translating trough a given vector. **/
     
      processing_matrix.at(0) = 1.0 ; processing_matrix.at(4) = 0.0 ; processing_matrix.at(8)  = 0.0 ; processing_matrix.at(12) = vector[0] ;
      processing_matrix.at(1) = 0.0 ; processing_matrix.at(5) = 1.0 ; processing_matrix.at(9)  = 0.0 ; processing_matrix.at(13) = vector[1] ;
      processing_matrix.at(2) = 0.0 ; processing_matrix.at(6) = 0.0 ; processing_matrix.at(10) = 1.0 ; processing_matrix.at(14) = vector[2] ;
      processing_matrix.at(3) = 0.0 ; processing_matrix.at(7) = 0.0 ; processing_matrix.at(11) = 0.0 ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
     
     
    template <typename T>
    void Matrix<T>::scale(T factor) {
     
      /** Scaling . **/
     
      processing_matrix.at(0) = factor ; processing_matrix.at(4) = 0.0    ; processing_matrix.at(8)  = 0.0    ; processing_matrix.at(12) = 0.0 ;
      processing_matrix.at(1) = 0.0    ; processing_matrix.at(5) = factor ; processing_matrix.at(9)  = 0.0    ; processing_matrix.at(13) = 0.0 ;
      processing_matrix.at(2) = 0.0    ; processing_matrix.at(6) = 0.0    ; processing_matrix.at(10) = factor ; processing_matrix.at(14) = 0.0 ;
      processing_matrix.at(3) = 0.0    ; processing_matrix.at(7) = 0.0    ; processing_matrix.at(11) = 0.0    ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::scale(Vector<T> vector) {
     
      /** Scaling . **/
     
      processing_matrix.at(0) = vector[0] ; processing_matrix.at(4) = 0.0       ; processing_matrix.at(8)  = 0.0       ; processing_matrix.at(12) = 0.0 ;
      processing_matrix.at(1) = 0.0       ; processing_matrix.at(5) = vector[1] ; processing_matrix.at(9)  = 0.0       ; processing_matrix.at(13) = 0.0 ;
      processing_matrix.at(2) = 0.0       ; processing_matrix.at(6) = 0.0       ; processing_matrix.at(10) = vector[2] ; processing_matrix.at(14) = 0.0 ;
      processing_matrix.at(3) = 0.0       ; processing_matrix.at(7) = 0.0       ; processing_matrix.at(11) = 0.0       ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::rotate_x(T degrees) {
     
      T radians = degrees / 180.0 * M_PI ;
     
      T c= (T) cos(radians)  ;  // Compute the cosine from the given angle.
      T s= (T) sin(radians)  ;  // Compute the sine from the given angle.
     
     
      processing_matrix.at(0) = 1.0 ; processing_matrix.at(4) = 0.0 ; processing_matrix.at(8)  = 0.0 ; processing_matrix.at(12) = 0.0 ;
      processing_matrix.at(1) = 0.0 ; processing_matrix.at(5) =  c  ; processing_matrix.at(9)  = -s  ; processing_matrix.at(13) = 0.0 ;
      processing_matrix.at(2) = 0.0 ; processing_matrix.at(6) =  s  ; processing_matrix.at(10) =  c  ; processing_matrix.at(14) = 0.0 ;
      processing_matrix.at(3) = 0.0 ; processing_matrix.at(7) = 0.0 ; processing_matrix.at(11) = 0.0 ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::rotate_y(T degrees) {
     
      T radians = degrees / 180.0 * M_PI ;
     
      T c= (T) cos(radians)  ;  // Compute the cosine from the given angle.
      T s= (T) sin(radians)  ;  // Compute the sine from the given angle.
     
     
      processing_matrix.at(0) =  c  ; processing_matrix.at(4) = 0.0 ; processing_matrix.at(8)  =  s  ; processing_matrix.at(12) = 0.0 ;
      processing_matrix.at(1) = 0.0 ; processing_matrix.at(5) = 1.0 ; processing_matrix.at(9)  = 0.0 ; processing_matrix.at(13) = 0.0 ;
      processing_matrix.at(2) = -s  ; processing_matrix.at(6) = 0.0 ; processing_matrix.at(10) =  c  ; processing_matrix.at(14) = 0.0 ;
      processing_matrix.at(3) = 0.0 ; processing_matrix.at(7) = 0.0 ; processing_matrix.at(11) = 0.0 ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::rotate_z(T degrees) {
     
      T radians = degrees / 180.0 * M_PI ;
     
      T c= (T) cos(radians)  ;  // Compute the cosine from the given angle.
      T s= (T) sin(radians)  ;  // Compute the sine from the given angle.
     
     
      processing_matrix.at(0) = c   ; processing_matrix.at(4) = -s  ; processing_matrix.at(8)  = 0.0 ; processing_matrix.at(12) = 0.0 ;
      processing_matrix.at(1) = s   ; processing_matrix.at(5) =  c  ; processing_matrix.at(9)  = 0.0 ; processing_matrix.at(13) = 0.0 ;
      processing_matrix.at(2) = 0.0 ; processing_matrix.at(6) = 0.0 ; processing_matrix.at(10) = 1.0 ; processing_matrix.at(14) = 0.0 ;
      processing_matrix.at(3) = 0.0 ; processing_matrix.at(7) = 0.0 ; processing_matrix.at(11) = 0.0 ; processing_matrix.at(15) = 1.0 ;
     
      multiply() ;
     
    }
     
    template <typename T>
    void Matrix<T>::multiply() {
     
      array<T, 4*4> tmp_matrix ;
     
      int x=0 ;
      while (x < 16) {
        // Multiply the processing matrix with the main matrix values.
     
        int value1 =  x % 4   ;  // Column value.
     
        int value2 = (x/4)*4  ;  // Row value.
     
        tmp_matrix.at(x) =   processing_matrix.at(value1)    *  main_matrix.at(value2+0)
                         +   processing_matrix.at(value1+4)  *  main_matrix.at(value2+1)
                         +   processing_matrix.at(value1+8)  *  main_matrix.at(value2+2)
                         +   processing_matrix.at(value1+12) *  main_matrix.at(value2+3) ;
     
        x++ ;
      }
     
      for (int c=0 ; c < 16 ; c++) {
        // Copy the result in the main matrix.
        main_matrix[c]=tmp_matrix[c] ;
      }
    }
     
    template <typename T>
    void Matrix<T>::apply_vertex(Vertex<T> &vertex) {
        /** Return an vertex issue from the main matrix multiplying. **/
     
        T x = vertex[0] * main_matrix.at(0) + vertex[1] * main_matrix.at(4) + vertex[2] * main_matrix.at(8)  + main_matrix.at(12) ;
        T y = vertex[0] * main_matrix.at(1) + vertex[1] * main_matrix.at(5) + vertex[2] * main_matrix.at(9)  + main_matrix.at(13) ;
        T z = vertex[0] * main_matrix.at(2) + vertex[1] * main_matrix.at(6) + vertex[2] * main_matrix.at(10) + main_matrix.at(14) ;
     
        vertex[0]=x ;
        vertex[0]=y ;
        vertex[2]=z ;
     
    }
     
     
    #endif
    Et le fichier: Vertex.h.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #ifndef GL_UTILS_VERTEX_H
    #define GL_UTILS_VERTEX_H
     
     
    #include <array>
     
     
    template <typename T>
    class Vertex {
     
      std::array<T, 4> vertex ;
     
      public :
     
        Vertex() {} ;
     
        Vertex(const T x, const T y, const T z, const T w=1) { vertex={x,y,z,w} ;} ;
     
        T& operator [] ( const int idx) { return vertex.at(idx) ; } ;
     
        Vertex& operator -() {
     
          vertex[0] = -vertex[0] ;
          vertex[1] = -vertex[1] ;
          vertex[2] = -vertex[2] ;
     
          return *this ;
        }
     
        const T  *get_vector() const { return vertex.data() ; } ;
     
     
     
    } ;
     
    #endif
    Et finalement le fichier: gl_data.h.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    #ifndef GL_UTILS_DATA_H
    #define GL_UTILS_DATA_H
     
    #include <iostream>
    #include <fstream>
    #include <string>
     
     
    GLuint load_texture(string path) {
     
      string cmd ;
     
      cmd += "python " ;
     
      cmd += "./scripts/generate_texture_datas.py " ;
     
      cmd += path ;
     
      if (system(cmd.c_str()) != 0) {
        cout << "Error launching script generate_texture_datas.py on file:\n" << path << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      ifstream r_file ;
     
      r_file.open("/tmp/texture.px") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.px" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      /** Setting file position to end **/
      r_file.seekg(0, r_file.end) ;
     
      /** Getting the file size. **/
      streampos file_size = r_file.tellg() ;
     
      /** Reset file position to begin to read it entirely thoughhis size know. **/
      r_file.seekg(0, r_file.beg) ;
     
      /** Setting buffer sized as great as the file content. **/
      string data_buffer(file_size,'\0') ;
     
      /** rw operations. (&*buffer.begin()) **/
      r_file.read((&*data_buffer.begin()), file_size) ;
     
      r_file.close() ;
     
     
      r_file.open("/tmp/texture.info") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.info" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
     
     
      string input ;
     
      int mode, byte_count ;
     
      int width, height ;
     
      getline(r_file, input) ;
     
      if (input == "RGB") {
        mode = GL_RGB ;
        byte_count=3 ;
        cout << path << " " << "RGB\n" ;
      }
      else if (input == "RGBA") {
        mode = GL_RGBA ;
        byte_count=4 ;
        cout << path << " " << "RGBA\n" ;
     
      }
      else {
        cout << "Cannot identify mode\n" ;
        exit(EXIT_FAILURE) ;
      }
     
      input.clear();
     
      getline(r_file, input) ;
     
      width = stoi(input) ;
     
      input.clear();
     
      getline(r_file, input) ;
     
      height = stoi(input) ;
     
      r_file.close() ;
     
      cout << path << " " << "width: " << width << " height: " << height << endl ;
     
     
     
     
      GLuint text_id ;
     
      glGenTextures(1, &text_id) ;
      glBindTexture(GL_TEXTURE_2D, text_id);
     
     
      glTexImage2D(GL_TEXTURE_2D, //target
                  0, //level=First mip-level                
                  4, //internal_format=bytes per pixel
                  width,  //image width
                  height, //image height
                  0, //border=texture border set or not 1|0
                  GL_RGBA, //format=GL_RGB|GL_RGBA
                  GL_UNSIGNED_BYTE, //type=storing format
                  (unsigned char *) data_buffer.data()) ;
     
     
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     
     
      cout << "\nSuccess to load texture from file:\n" << path << endl ;
     
      cout.flush() ;
     
      return text_id ;
    }         
     
     
     
     
    GLuint LoadShaders(string vertex_file_path, string fragment_file_path) {
      // Crée les shaders
      GLuint VertexShaderID   = glCreateShader(GL_VERTEX_SHADER)   ;
      GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER) ;
     
      // Lit le code du vertex shader à partir du fichier
      string VertexShaderCode ;
      ifstream VertexShaderStream(vertex_file_path.c_str(), ios::in) ;
     
      if (VertexShaderStream.is_open()) {
        string Line = "";
        while (getline(VertexShaderStream, Line)) {
          VertexShaderCode += "\n" + Line;
        }
     
        VertexShaderStream.close();
     
      }
     
     
      // Lit le code du fragment shader à partir du fichier
      string FragmentShaderCode;
      ifstream FragmentShaderStream(fragment_file_path.c_str(), ios::in);
     
      if (FragmentShaderStream.is_open()) {
     
        string Line = "";
     
        while (getline(FragmentShaderStream, Line)) {
          FragmentShaderCode += "\n" + Line;
        }
     
        FragmentShaderStream.close();
     
      }
     
      GLint Result = GL_FALSE;
      int InfoLogLength;
     
      // Compile le vertex shader
      printf("Compiling shader : %s\n", vertex_file_path.c_str());
      char const * VertexSourcePointer = VertexShaderCode.c_str();
      glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
      glCompileShader(VertexShaderID);
     
      // Vérifie le vertex shader
      glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
      glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      vector<char> VertexShaderErrorMessage(InfoLogLength);
      glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
      fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
     
     
      // Compile le fragment shader
      printf("Compiling shader : %s\n", fragment_file_path.c_str());
      char const * FragmentSourcePointer = FragmentShaderCode.c_str();
      glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
      glCompileShader(FragmentShaderID);
     
      // Vérifie le fragment shader
      glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
      glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      vector<char> FragmentShaderErrorMessage(InfoLogLength);
      glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
      fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
     
      // Lit le programme
      fprintf(stdout, "Linking program\n");
      GLuint ProgramID = glCreateProgram();
      glAttachShader(ProgramID, VertexShaderID);
      glAttachShader(ProgramID, FragmentShaderID);
      glLinkProgram(ProgramID);
     
      // Vérifie le programme
      glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
      glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      vector<char>  ProgramErrorMessage(InfoLogLength,'\0') ;
     
      glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
      fprintf(stdout, "Error message: %s\n", &ProgramErrorMessage[0]);
     
      glDeleteShader(VertexShaderID);
      glDeleteShader(FragmentShaderID);
     
      return ProgramID;
    }
     
    #endif
    Je ne sais précisement d'ou vient le problème et toute aide est la bienvenue.
    Si vous avez des commentaires, conseils, critiques sur mon code ou ma façon de coder ils sont la bienvenue.
    Merci pour vos réponses et votre précieuse aide.

    Luke spywoker.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Bonjour,

    Déjà : aaaaahhhhhhhhh ! du code dans les .h

    Je pense que c'est un souci de matrice (j'en suis sur). Au début, j'ai pensé à de l'accumulation (genre, la transformation de la matrice précédente est ajoutée à la matrice actuelle), mais je ne suis pas sur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /** Rotate on his own axes because the cube is centered on the origin. **/
          matrixes.at(cntr).rotate_x(1)  ;
          matrixes.at(cntr).rotate_y(1)  ;
          matrixes.at(cntr).rotate_z(1)  ;
    Que cherchez vous à faire ?

    Sinon, je ne vois pas encore exactement où est le souci.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    Salut LittleWhite,

    les définitions dans les *.h sont ici soit pour des raisons de déclaration de template (je pense que pour une classe template on ne peut faire autrement) ou pour des raisons de concision du code présenté sur le forum (c'est déjà assez compliquer de chercher quelle variable est locale ou membre avec la multiplicité de fichiers que impose le C++).

    Je pense que c'est un souci de matrice (j'en suis sur). Au début, j'ai pensé à de l'accumulation (genre, la transformation de la matrice précédente est ajoutée à la matrice actuelle), mais je ne suis pas sur.
    Oui chaque opération sur un objet de type Matrix (rotation_x, rotation_y, ...) est directement multiplier par la matrice principale (appel de mulitply()).

    Enfin le résultat de toutes les opérations est sortie comme un pointeur sur la matrice (méthode main_matrix.data()) ce qui équivaut a multiplier plusieurs matrices (a fonction unique entre elles).

    Je cherche a afficher plusieurs instances de Cube a des positions différentes et de différentes tailles, tournant sur eux même ( d'oû la translation vers l'origine puis les rotations et translation au point originel).

    Le résultat est bien l'affichage de 5 cubes le problème est que:

    d'abords il sont tous de la même taille (ce qui n'est pas voulus).
    Un seule cube tourne sur lui même a sa position (sont centre de gravité): le premier de la boucle.
    Les autres cube sont d'abord a la même position que le premier puis se déplace puis reviennent a la position du premier cube.

    Les effets de bords décrit précédemment proviennent vient du fait que chaque instance de cube enregistre son centre et du coup les translation font que ceux ci change de position, je pense.

    Je pense que le problème provient de ma manière d'afficher des buffers différents en même temps.

    Le mieux serai de pouvoir afficher chaque instance sans passer par un buffer par exemple une méthode fictive:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DrawBuffer(GL_enum type, int nb_of_vertex, GL_Enum type, const float *buffer) ;
    exécuté.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DrawBuffer(GL_TRIANGLE_FAN, 4, GL_FLOAT, Quad.get_quad()) ;
    ou une solution ressemblant a celle-ci serai la bienvenue.

    Car le programme semble ne pas tenir compte de la différence de buffer (les vertex de chaque instance) de chaque instance et semble ne tenir compte que de celui de la première instance mais également du centre de chaque instance.



    PS: C'est toi qui m'a dit qu'on faisait du modern OpenGL quand j'ai présenter mon tutoriel Introduction a pyopengl.
    Alors il est vrai que il y a vraiment beaucoup de changement dans la manière d'écrire du code OpenGL notamment l'importance des shaders que l'on pouvait optionnellement ignorer.

    PS2: je posterai au plus vite un lien vers un *.zip contenant tout le code nécessaire a l'exécution du programme ce qui vous permettra de voir par vous même.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Citation Envoyé par Luke spywoker Voir le message
    les définitions dans les *.h sont ici soit pour des raisons de déclaration de template (je pense que pour une classe template on ne peut faire autrement) ou pour des raisons de concision du code présenté sur le forum (c'est déjà assez compliquer de chercher quelle variable est locale ou membre avec la multiplicité de fichiers que impose le C++).
    Oui, mais gl_Data.h et Cube.h n'ont absolument pas besoin d'une telle chose (ne définissent pas de template).

    Oui chaque opération sur un objet de type Matrix (rotation_x, rotation_y, ...) est directement multiplier par la matrice principale (appel de mulitply()).
    Je ne comprend pas pourquoi vous avez fait cela et cela ne devrait pas être le cas. Hum, si je pense avoir compris comment cela fonctionne. Ça doit être ok, j'imagine.

    Je cherche a afficher plusieurs instances de Cube a des positions différentes et de différentes tailles, tournant sur eux même ( d'oû la translation vers l'origine puis les rotations et translation au point originel).
    La translation doit se faire, puis la rotation et hop, ça marche. Pas besoin de faire deux déplacements comme vous le faites.

    d'abords il sont tous de la même taille (ce qui n'est pas voulus).
    Ok, du coup, avez vous déboguer (même avec des print) le constructeur de cube pour voir la position des vertex générés
    Un seule cube tourne sur lui même a sa position (sont centre de gravité): le premier de la boucle.
    Les autres cube sont d'abord a la même position que le premier puis se déplace puis reviennent a la position du premier cube.
    Oui, cela est lié à ce que vous faites comme transformation. La solution est de faire juste la translation pour placer l'objet, puis la rotation, c'est tout.

    Le mieux serai de pouvoir afficher chaque instance sans passer par un buffer par exemple une méthode fictive:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DrawBuffer(GL_enum type, int nb_of_vertex, GL_Enum type, const float *buffer) ;
    exécuté.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DrawBuffer(GL_TRIANGLE_FAN, 4, GL_FLOAT, Quad.get_quad()) ;
    ou une solution ressemblant a celle-ci serai la bienvenue.
    Je n'ai pas compris
    Le meilleur absolument meilleur, c'est d'utiliser l'instanciation (une autre technique OpenGL, un peu plus avancée). Actuellement, une chose que je ne trouve pas "logique", c'est que la dimension du cube n'est pas codé dans sa matrice, tout simplement. Mais bon, ce n'est pas grave, cela le sera un peu plus, pour appliquer l'instanciation, si vous souhaitez l'intégrer

    Car le programme semble ne pas tenir compte de la différence de buffer (les vertex de chaque instance) de chaque instance et semble ne tenir compte que de celui de la première instance mais également du centre de chaque instance.
    On se penchera sur ce point, si vos constructeur fonctionne comme prévu et si les vertex sont correctement générés, aux coordonnées voulues.
    J'ai tout de même regarder tout de suite et en effet, vous ne semblez pas activer le tampon du cube que vous souhaitez afficher. Du coup, je pense que le dernier tampon actif est celui du dernier cube crée et donc, que c'est celui ci qui est utilisé pour tous les cubes.


    PS: C'est toi qui m'a dit qu'on faisait du modern OpenGL quand j'ai présenter mon tutoriel Introduction a pyopengl.
    Alors il est vrai que il y a vraiment beaucoup de changement dans la manière d'écrire du code OpenGL notamment l'importance des shaders que l'on pouvait optionnellement ignorer.
    Ouep, là, je n'ai rien dit sur ce point, vous faites de l'OpenGl moderne et vous êtes sur la bonne voie (sauf celle d'avoir recoder les matrices vous même, mais bon, il semblerai que vous ayez des résultats que moi sur ce point ).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    Salut LittleWhite et merci pour votre aide.
    Oui, mais gl_Data.h et Cube.h n'ont absolument pas besoin d'une telle chose (ne définissent pas de template).
    C'est simplement parce que c'est expérimental et comme le Cube ne fonctionne pas correctement...

    La translation doit se faire, puis la rotation et hop, ça marche. Pas besoin de faire deux déplacements comme vous le faites.
    J'ai appris que pour faire tourner un objet sur ces axes, il faut le translaté selon son centre de gravité a l'origine ( matrix.translate(-cube.get_center() ) puis effectuer les rotations et le retranslaté a selon centre de gravité, bref le remettre a sa place ( matrix.translate(cube.get_center() ) et enfin appliquer la matrice a l'objet.

    Ok, du coup, avez vous déboguer (même avec des print) le constructeur de cube pour voir la position des vertex générés
    Non mais je vais le faire, j'étais désespérer du coup j'ai poster après tout avoir essayer mais je n'ai pas penser a votre suggestion.

    Actuellement, une chose que je ne trouve pas "logique", c'est que la dimension du cube n'est pas codé dans sa matrice, tout simplement. Mais bon, ce n'est pas grave, cela le sera un peu plus, pour appliquer l'instanciation, si vous souhaitez l'intégrer
    Non car la dimension dépends d'un paramètre du constructeur qui en conséquence générera un Cube de la taille voulus.
    Je n'ai pas compris le fait de coder la taille dans la matrice et comment c'est possible ?

    J'ai mis une archive comme promis contenant tout le code ici.

    Il suffit de décompresser sous Linux,
    se rendre dans le dossier et taper make pour compiler le programme.

    Enfin on peut taper make exec pour le lancer.

    Si cela ne fonctionne pas vous aurez un traceback, car il faut la version 4 de OpenGL et comme mineur ont peut le changer a la ligne 49 de main.cpp.

    Merci beaucoup pour votre aide précieuse.

    Bon OpenGL a vous.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  6. #6
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Il me dit failed to init SDL 2. Je ne sais pas pourquoi. Je vous conseille d'utiliser SDL_GetError(). (Désolé, là, je n'ai pas le temps de regarder plus en détails.).

    Citation Envoyé par Luke spywoker Voir le message
    C'est simplement parce que c'est expérimental et comme le Cube ne fonctionne pas correctement...
    Ok


    Citation Envoyé par Luke spywoker Voir le message
    J'ai appris que pour faire tourner un objet sur ces axes, il faut le translaté selon son centre de gravité a l'origine ( matrix.translate(-cube.get_center() ) puis effectuer les rotations et le retranslaté a selon centre de gravité, bref le remettre a sa place ( matrix.translate(cube.get_center() ) et enfin appliquer la matrice a l'objet.
    Pour moi, cela n'a pas de sens. Mais à vrai dire, j'ai un léger doute par rapport à ce que j'ai dit, mais oui, moi, je ferai la translation pour placer l'objet (car je pars du principe que les sommets de l'objet sont centrés en 0,0,0), puis, je fais la rotation (car dans l'autre sens, cela donne un peu n'importe quoi.

    Non car la dimension dépends d'un paramètre du constructeur qui en conséquence générera un Cube de la taille voulus.
    Je n'ai pas compris le fait de coder la taille dans la matrice et comment c'est possible ?
    J'ai bien vu que c'était un paramètre, mais la logique dirait : un objet est constitué d'un Mesh (maillage, les sommets donc) et d'une matrice (pour le positionner, tourner et le redimensionner (fonction scale de votre classe matrice)). Du coup, pour tous les cubes, le maillage est toujours le même (un truc unitaire, centré en 0,0,0) et le paramètre de la taille est utilisé dans le calcul de la matrice.
    C'est une façon de faire (un peu plus courante que la votre, notamment car elle permet l'instanciation GPU (envoyer un unique maillage et l'afficher avec N matrices différentes (changeant ainsi sa taille, position et rotation)). Bien entendu on est pas obliger de suivre cette façon de faire et votre façon marchera aussi, une fois que vous êtes bien sur que vous activer le bon buffer OpenGL avant l'affichage, ou encore, une fois que vous êtes sur que vous générez les bons sommets
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  7. #7
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    Merci pour votre aide LittleWhite,

    concernant le problème d'initialisation de SDL2, c'est simplement une fonction issue d'un de vos nombreux tutoriel.
    Pour y remédié et pour montrer mon avancement dans le problème j'ai fait un update de l'archive téléchargeable ici. (Il y a un target supplémentaire dans le makefile make pb.)
    J'ai remplacer le drapeau SDL_INIT_EVERYTHING par SDL_INIT_VIDEO en espérant que cela fonction fonctionne cette fois ci.

    Concernant mon avancement j'arrive a afficher maximum 16 cubes tournant sur eux même a des positions et de tailles différentes mais le problème est loin d'être résolu.
    Car j'y arrive simplement par le code de génération de buffer pour chaque instance:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
      glGenBuffers(1, &buffer) ;
      glBindBuffer(GL_ARRAY_BUFFER, buffer) ;
      glBufferData(GL_ARRAY_BUFFER, 4*4*6*sizeof(float), get_cube(), GL_DYNAMIC_DRAW) ;
      glVertexAttribPointer(buffer_counter, 4, GL_FLOAT, GL_FALSE,  0, NULL) ; 
     
      /** buffer_counter is a static member and permit me to output GL_MAX_VERTEX_ATTRIBS cubes.
       *  because i output the shader with the following command binded to a 
       *   
       *  layout (location=buffer_counter) in vec4 position.
       *  
       *  uniform mat4 mv_matrix ; 
       *  
       *  void main(void) { 
       *   gl_Position  = mv_matrix * position ;
       *  }
       *  
       *  In the vertex shader.
       * **************************************************************************************/
     
      glEnableVertexAttribArray(buffer_counter) ;
     
      buffer_counter++ ;
    D'ailleurs je n'arrive pas a dessiner autrement que de cette manière précise de créer des buffers.
    Alors quand je voit que dans mon livre d'initiation il est possible de dessiner 3000 astéroïdes.

    Je me dit que: ich nix kapish weil isch sher dûme bisch.

    Je suis parvenus a ce résultat en voyant que dans un tutoriel d'un certains Alexandre Laurent il se sert du premier paramètre de glVertexAttribPointer coupler a une entrer dans le vertex shader:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    layout (location=0) in vec4 position ;
    Donc ce n'est pas ma manière de coder des matrices qui sont le problème et j'ai aussi remarquer qu'on pouvait translater un 'objet' pour en créer une copy.
    Le problème est la limite imposer par ma méthode d'affichage: 16 buffers sur ma machine.
    Il faudrai donc me montrer un peu de code, si vous le désirez bien, pour transmettre les vertex autrement au shader car si l'on garde la même valeurs pour la location et bien le programme fait n'importe quoi.

    Donc il faudrai que je trouve une méthode d'affichage de l'objet Cube qui ne soit pas limité.

    J'arrive a générer mes 16 cubes tournant sur eux même comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
     
     
      /** Define some colors. **/
      Color<float> red(1.0, 0.0, 0.0, 1.0) ;
      Color<float> green(0.0, 1.0, 0.0, 1.0) ;
      Color<float> blue(0.0, 0.2, 1.0, 1.0) ;
      Color<float> yellow(1.0, 1.0, 0.0, 1.0) ;
      Color<float> turkish(0.0, 1.0, 1.0, 1.0) ;
      Color<float> pink(1.0, 0.0, 1.0, 1.0) ;
     
      vector<Color<float>> cube_colors ;
     
      cube_colors.push_back(red) ;
      cube_colors.push_back(green) ;
      cube_colors.push_back(blue) ;
      cube_colors.push_back(yellow) ;
      cube_colors.push_back(turkish) ;
      cube_colors.push_back(pink) ;
     
      vector<Cube> cubes ;
     
      vector<Matrix<float>> matrixes ;
     
      uniform_real_distribution<float> rand_vertex_pos(-0.75, 0.75) ;
      uniform_real_distribution<float> rand_cube_size(0.05, 0.25) ;
      uniform_real_distribution<float> rand_color(0.0, 1.0) ;
     
     
      float start_x= -0.75 ;
      float start_y= -0.75 ;
     
      float size=0.25 ;
     
      int col_counter=0 ;
     
     
      int getit ;
     
      glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &getit) ;
     
      fprintf(stdout,"*** We are limited to %d cubes objets ***\n", getit) ;
     
      #ifndef PB
      for (int c=0 ; c < 16 ; c++) {
     
        /** Generate Cube instance: **/
        Cube cube(Vertex<float>(start_x, start_y, 0.0f), size) ;
     
        col_counter++ ;
     
        start_x += 0.50 ;
     
        if (col_counter % 4 == 0) {
          start_y += 0.50 ;
          start_x = -0.75 ;
        }
     
        /** string type construct contains the vertex shader: **/
        string vs_source ;
     
        vs_source += "#version 430 core\n" ;
     
        /** We are limited to  16 location so objects that's the problem. **/
        vs_source += "layout (location=" ; vs_source +=  to_string(c) ;  vs_source +=  ") in vec4 position ;\n" ;
     
        vs_source += "out VS_OUT                                                          \n" ;
        vs_source += "{                                                                   \n" ;
        vs_source += "    vec4 color;                                                     \n" ;
        vs_source += "} vs_out;                                                           \n" ;
     
        vs_source += "uniform vec4 mv_color  ;                                            \n" ;          
        vs_source += "uniform mat4 mv_matrix ;                                            \n" ;                              
     
        vs_source += "void main(void)                                                     \n" ;
        vs_source += "{                                                                   \n" ;
        vs_source += "    gl_Position  = mv_matrix * position ;                           \n" ;
        vs_source += "    vs_out.color = mv_color ;                                       \n" ;
        vs_source += "}                                                                   \n" ;
     
     
        /** string type construct contains the fragment shader: **/
        string fs_source ;
     
        fs_source += "#version 430 core                                                \n" ;
        fs_source += "out vec4 color;                                                  \n" ;
        fs_source += "in VS_OUT \n                                                     \n" ;
        fs_source += "{                                                                \n" ;
        fs_source += "  vec4 color;                                                    \n" ;
        fs_source += "} fs_in;                                                         \n" ;
        fs_source += "void main(void) \n{ color = fs_in.color ;\n}                     \n" ;
     
     
        char const * VertexSourcePointer = vs_source.c_str()   ;
        char const * FragmentSourcePointer = fs_source.c_str() ;
     
        GLuint VertexShaderID   = glCreateShader(GL_VERTEX_SHADER)   ;
        GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER) ;
     
        glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
        glCompileShader(VertexShaderID);
     
        GLint Result = GL_FALSE;
        int InfoLogLength;
     
        // Vérifie le vertex shader
        glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
        glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
        vector<char> VertexShaderErrorMessage(InfoLogLength, '\0');
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
     
        if (VertexShaderErrorMessage.data()[0] != '\0') {
          fprintf(stdout, "Vertex shader error: %s\n", VertexShaderErrorMessage.data());
        }
     
        glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
        glCompileShader(FragmentShaderID);
     
        // Vérifie le fragment shader
        glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
        glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
        vector<char> FragmentShaderErrorMessage(InfoLogLength, '\0');
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
     
        if (FragmentShaderErrorMessage.data()[0] != '\0') {
          fprintf(stdout, "Fragment shader error: %s\n", FragmentShaderErrorMessage.data());
        }
     
        // Lit le programme
        GLuint ProgramID = glCreateProgram();
        glAttachShader(ProgramID, VertexShaderID);
        glAttachShader(ProgramID, FragmentShaderID);
        glLinkProgram(ProgramID);
     
        // Vérifie le programme
        glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
        glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
        vector<char>  ProgramErrorMessage(InfoLogLength,'\0') ;
     
        glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
     
        if (ProgramErrorMessage.data()[0] != '\0' ) {
          fprintf(stdout, "Error message: %s\n", ProgramErrorMessage.data());
        }
     
        glDeleteShader(VertexShaderID);
        glDeleteShader(FragmentShaderID);
     
     
     
     
     
     
        /** Parametrize the cube instance: **/
        cube.set_program(ProgramID) ;
        cube.set_colors(cube_colors) ;
     
        /** Store cube instance. **/
        cubes.push_back(cube) ;
     
        /** Store a matrix for every Cube instance. **/
        Matrix<float> matrix ;
        matrixes.push_back(matrix) ;
      }
    Un petit coup coup a un certains Alexandre Laurent auteur d'un tutoriel dont est issue le code de compilation des shaders (un peu changé) qui nous aide bien les membres de DEV avec ces tutoriels, templates, etc... et dont il faut saluer le dévouement envers DEV et nous tous de part sa précieuse aide apportée.

    Merci pour votre aide et Bon OpenGL a vous.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Citation Envoyé par Luke spywoker Voir le message
    concernant le problème d'initialisation de SDL2, c'est simplement une fonction issue d'un de vos nombreux tutoriel.
    Pour y remédié et pour montrer mon avancement dans le problème j'ai fait un update de l'archive téléchargeable ici. (Il y a un target supplémentaire dans le makefile make pb.)
    J'ai remplacer le drapeau SDL_INIT_EVERYTHING par SDL_INIT_VIDEO en espérant que cela fonction fonctionne cette fois ci.
    Oui, votre code était juste. Il n'y a pas de souci sur ce point. C'était juste que ma machine n'est pas configurée exactement comme il le faut, donc la SDL ne peux pas s'initialiser (pour une raison quelconque). Pour connaître cette raison, il faut rajouter dans le message d'erreur, une utilisation de SDL_GetError(), afin que la SDL, retourne la raison précise de l'erreur. Sinon, le code était correct.

    Concernant mon avancement j'arrive a afficher maximum 16 cubes tournant sur eux même a des positions et de tailles différentes mais le problème est loin d'être résolu.
    Car j'y arrive simplement par le code de génération de buffer pour chaque instance:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
      glGenBuffers(1, &buffer) ;
      glBindBuffer(GL_ARRAY_BUFFER, buffer) ;
      glBufferData(GL_ARRAY_BUFFER, 4*4*6*sizeof(float), get_cube(), GL_DYNAMIC_DRAW) ;
      glVertexAttribPointer(buffer_counter, 4, GL_FLOAT, GL_FALSE,  0, NULL) ; 
     
      /** buffer_counter is a static member and permit me to output GL_MAX_VERTEX_ATTRIBS cubes.
       *  because i output the shader with the following command binded to a 
       *   
       *  layout (location=buffer_counter) in vec4 position.
       *  
       *  uniform mat4 mv_matrix ; 
       *  
       *  void main(void) { 
       *   gl_Position  = mv_matrix * position ;
       *  }
       *  
       *  In the vertex shader.
       * **************************************************************************************/
     
      glEnableVertexAttribArray(buffer_counter) ;
     
      buffer_counter++ ;
    D'ailleurs je n'arrive pas a dessiner autrement que de cette manière précise de créer des buffers.
    Alors quand je voit que dans mon livre d'initiation il est possible de dessiner 3000 astéroïdes.

    Je me dit que: ich nix kapish weil isch sher dûme bisch.

    Je suis parvenus a ce résultat en voyant que dans un tutoriel d'un certains Alexandre Laurent il se sert du premier paramètre de glVertexAttribPointer coupler a une entrer dans le vertex shader:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    layout (location=0) in vec4 position ;
    Donc ce n'est pas ma manière de coder des matrices qui sont le problème et j'ai aussi remarquer qu'on pouvait translater un 'objet' pour en créer une copy.
    Le problème est la limite imposer par ma méthode d'affichage: 16 buffers sur ma machine.
    Il faudrai donc me montrer un peu de code, si vous le désirez bien, pour transmettre les vertex autrement au shader car si l'on garde la même valeurs pour la location et bien le programme fait n'importe quoi.
    Pour vérifier les limitations, on peut faire des glGet(), ou encore, utiliser des outils comme glView/glInfo. Je ne me rappelle pas d'une limite de 16 tampons, mais peut être.
    Sinon, la technique vous permettez de faire un unique tampon pour tout votre cube est de :
    • utiliser un unique maillage d'un cube unitaire centré en 0,0,0 ;
    • faire N glDraw* en passant à chaque fois une matrice différente.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &getit) ;
     
      fprintf(stdout,"*** We are limited to %d cubes objets ***\n", getit) ;
    Ah non, ça ce n'est pas une limitation du nombre de tampon, ni même d'objet. C'est une limitation du nombre d'attribut (variable de sommet) que l'on peut passer pour chaque sommet.

    Je vois pourquoi vous êtes limitée, mais comme je l'ai dit, la méthode n'est pas correcte. Ici, ce que vous faites, c'est pour un shader (ou un rendu, on peut dire), vous envoyez les 16 cubes et vous les dessinez d'un coup. Bon ça fonctionne, évidemment, car vous avez réussi, mais ce n'est pas cool, à cause des grosses limitations.
    Le principe qu'il faut suivre :
    • on génère les sommets d'un ou N cubes, que l'on va mettre dans un, ou N tampons ;
    • on utilise un shader ultra simpliste qui accepte la position des sommets comme attribut et qui se contente de faire : gl_Position = mvpMatrix * position; (sachant que position, ce sont l'attribut qu'on lui passe) ;
    • on fait un glDraw*() pour chaque cube que l'on veut afficher.


    Vous pouvez suivre cet exemple : http://jeux.developpez.com/telecharg...Exemple-de-FBO qui s'approche de la bonne technique.
    Sinon je tacherai de faire une modification de votre code, ce soir, si je trouve le temps.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Le principe qu'il faut suivre :
    • on génère les sommets d'un ou N cubes, que l'on va mettre dans un, ou N tampons ;
    • on utilise un shader ultra simpliste qui accepte la position des sommets comme attribut et qui se contente de faire : gl_Position = mvpMatrix * position; (sachant que position, ce sont l'attribut qu'on lui passe) ;
    • on fait un glDraw*() pour chaque cube que l'on veut afficher.
    Et si on à beaucoup de cubes à afficher (pour un cube "beaucoup" = plusieurs centaines voir milliers, pour un mesh plus complexe "beaucoup" peut être seulement quelques dizaines) il y à glDrawElementsInstanced .

    @Luke spywoker, Tu n'as clairement pas besoin de bind 16 buffers ici :
    - positions
    - ... rien d'autre (mais tu devrais clairement y ajouter tes couleurs au lieu de faire 6 glDraw / glUniform par cube).

    Çà fait qu'un (disons 2 avec les couleurs).

    Ton shader devrait ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // vertex shader
    #version 430 core
     
    layout (location=0) in vec4 pos;
    layout (location=1) in vec4 c;
     
    uniform mat4 mv_matrix;
     
    out vec4 color;
     
    void main() {
        gl_Position = mv_matrix * pos ;
        color = c;
    }
     
     
    // fragment shader
    #version 430 core
     
    in vec4 color;
    out vec4 out_color;
     
    void main() {
        out_color = color;
    }
    Après tu as 1000 façons différentes de fournir tes cubes à OpenGL :
    - 1 buffer par cube (pour chaque cube : tu bind le buffer en donnant les offsets pour les positions et couleurs, puis glDraw)
    - 2 buffers par cube (1 pour les positions, 1 pour les couleurs, pareil bind les 2, puis glDraw), généralement pas recommandé.
    - 1 buffer pour tous tes cubes : 1 buffer c'est que de la mémoire, tu gère ça comme tu veux, il est possible de mettre les vertices / couleurs (et même des indices ou des matrices) d'un ou de plusieurs objets dans le même buffer. (tu bind ton buffer 1 fois, puis plusieurs glDraw avec différents offsets, ou 1 glDrawInstanced)

    Et même si tu choisi d'avoir un buffer par cube, tu peux avoir 1000 cubes sans problème : il suffit simplement de ne pas bind les 1000 en même temps. Mais tu n'as de toute façon pas besoin : tu n'as besoin que d'1 ou 2 éléments pour chaque cube.

  10. #10
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut résolu mais pas tout a fait.
    Salut les OpenGL,

    J'ai finalement réussis: j'arrive a afficher le nombre de cube que je veux dans les dimensions que je veux, oû je veut, tournant sur eux même en faîtes il suffisait de mettre les fonctions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    GLuint id_position = glGetAttribLocation(program, "position");
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glVertexAttribPointer(id_position, 4, GL_FLOAT, GL_FALSE, 0, NULL) ;
    glEnableVertexAttribArray(id_position);
    Dans la méthode display() de la classe Cube.

    Seulement un problème en appelant un autre j'ai voulus élargir un peu les fonctionnalités de la classe Cube en mettant une texture par face alors j'ai fait une fonction qui charge une texture et qui retourne sont identifiant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    GLuint load_texture(string path) {
     
      string cmd ;
     
      cmd += "python " ;
     
      cmd += "./scripts/generate_texture_datas.py " ;
     
      cmd += path ;
     
      if (system(cmd.c_str()) != 0) {
        cout << "Error launching script generate_texture_datas.py on file:\n" << path << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      ifstream r_file ;
     
      r_file.open("/tmp/texture.px") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.px" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      /** Setting file position to end **/
      r_file.seekg(0, r_file.end) ;
     
      /** Getting the file size. **/
      streampos file_size = r_file.tellg() ;
     
      /** Reset file position to begin to read it entirely thoughhis size know. **/
      r_file.seekg(0, r_file.beg) ;
     
      /** Setting buffer sized as great as the file content. **/
      string data_buffer(file_size,'\0') ;
     
      /** rw operations. (&*buffer.begin()) **/
      r_file.read((&*data_buffer.begin()), file_size) ;
     
      r_file.close() ;
     
     
     
     
      /** Getting mode width and height of the texture file. **/
      r_file.open("/tmp/texture.info") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.info" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
     
     
      string info_buf ;
     
      unsigned int mode ;
      unsigned int byte_count ;
     
      int width, height ;
     
      getline(r_file, info_buf) ;
     
      cout << "\nTry to load texture from file:\n" << path << endl ;
     
      if (info_buf == "RGB") {
        mode = GL_RGB ;
        byte_count=3 ;
        cout << path << " mode: " << info_buf << endl ;
      }
      else if (info_buf == "RGBA") {
        mode = GL_RGBA ;
        byte_count=4 ;
        cout << path << " mode: " << info_buf << endl ;
     
      }
      else {
        cout << "Cannot identify mode\n" ;
        exit(EXIT_FAILURE) ;
      }
     
      info_buf.clear();
     
     
      getline(r_file, info_buf) ;
     
      width = stoi(info_buf) ;
     
      info_buf.clear();
     
     
      getline(r_file, info_buf) ;
     
      height = stoi(info_buf) ;
     
      r_file.close() ;
     
     
      cout << path << " " << "width: " << width << " height: " << height << endl ;
     
     
     
     
      GLuint text_id ;
     
      glGenTextures(1, &text_id) ;
      glBindTexture(GL_TEXTURE_2D, text_id);
     
     
      glTexImage2D(GL_TEXTURE_2D, //target
                  0, //level=First mip-level          
                  byte_count, //internal_format=bytes per pixel
                  width,  //image width
                  height, //image height
                  0, //border=texture border set or not 1|0
                  mode, //format=GL_RGB|GL_RGBA
                  GL_UNSIGNED_BYTE, //type=storing format
                  (unsigned char *) data_buffer.data()) ;
     
     
     
     
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     
      cout << "Success loading texture from file.\n\n" << endl ;
     
      cout.flush() ;
     
      return text_id ;
    }
    Le script python crée 2 fichiers temporaires servant de buffer entre le C++ et le python.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    from PIL import Image
     
    from sys import argv, exit
     
    if len(argv) != 2 :
      print "usage %s imagepath" % argv[0]
      exit(1)
     
    a=Image.open(argv[1])
     
    b=file("/tmp/texture.px","w") ;
    c=file("/tmp/texture.info","w")
     
    c.write(a.mode+"\n") ;
    c.write(str(a.size[0])+"\n") ;
    c.write(str(a.size[1])+"\n") ;
     
    bytes=a.tobytes()
     
    reversed(bytes) # OpenGL texture must be flipped data.
     
    b.write(bytes) ;
     
    c.close()
    b.close()
    Et j'affiche une texture par face grâce a l'identifiant de texture dans la méthode display de l'objet cube:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
        /** Start draw cube. **/
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(0).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(0));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(0));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4) ;
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
    
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(1).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(1));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(1));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
    
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(2).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(2));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(2));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 8,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
    
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(3).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(3));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(3));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 12,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
    
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(4).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(4));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(4));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
    
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(5).get_vector()) ;
        }Salut les OpenGL,
    
    J'ai finalement réussis: j'arrive a afficher le nombre de cube que je veux dans les dimensions que je veux ou je veut tournant sur eux même en faîtes il suffisait de mettre les fonctions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    123456
    GLuint id_position = glGetAttribLocation(program, "position");
     
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glVertexAttribPointer(id_position, 4, GL_FLOAT, GL_FALSE, 0, NULL) ;
     
        glEnableVertexAttribArray(id_position);
    Dans la méthode display() de la classe cube. Seulement un problème en appelant un autre j'ai voulus élargir un peu les fonctionnalités de la classe Cube en mettant une texture par face alors j'ai fait une fonction qui charge une texture et retourne sont identifiant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
    GLuint load_texture(string path) {
     
      string cmd ;
     
      cmd += "python " ;
     
      cmd += "./scripts/generate_texture_datas.py " ;
     
      cmd += path ;
     
      if (system(cmd.c_str()) != 0) {
        cout << "Error launching script generate_texture_datas.py on file:\n" << path << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      ifstream r_file ;
     
      r_file.open("/tmp/texture.px") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.px" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
      /** Setting file position to end **/
      r_file.seekg(0, r_file.end) ;
     
      /** Getting the file size. **/
      streampos file_size = r_file.tellg() ;
     
      /** Reset file position to begin to read it entirely thoughhis size know. **/
      r_file.seekg(0, r_file.beg) ;
     
      /** Setting buffer sized as great as the file content. **/
      string data_buffer(file_size,'\0') ;
     
      /** rw operations. (&*buffer.begin()) **/
      r_file.read((&*data_buffer.begin()), file_size) ;
     
      r_file.close() ;
     
     
     
     
      /** Getting mode width and height of the texture file. **/
      r_file.open("/tmp/texture.info") ;
     
      if (! r_file) {
        cout << "Fail to open file: " << "/tmp/texture.info" << endl ;
        exit(EXIT_FAILURE) ;
      }
     
     
     
      string info_buf ;
     
      unsigned int mode ;
      unsigned int byte_count ;
     
      int width, height ;
     
      getline(r_file, info_buf) ;
     
      cout << "\nTry to load texture from file:\n" << path << endl ;
     
      if (info_buf == "RGB") {
        mode = GL_RGB ;
        byte_count=3 ;
        cout << path << " mode: " << info_buf << endl ;
      }
      else if (info_buf == "RGBA") {
        mode = GL_RGBA ;
        byte_count=4 ;
        cout << path << " mode: " << info_buf << endl ;
     
      }
      else {
        cout << "Cannot identify mode\n" ;
        exit(EXIT_FAILURE) ;
      }
     
      info_buf.clear();
     
     
      getline(r_file, info_buf) ;
     
      width = stoi(info_buf) ;
     
      info_buf.clear();
     
     
      getline(r_file, info_buf) ;
     
      height = stoi(info_buf) ;
     
      r_file.close() ;
     
     
      cout << path << " " << "width: " << width << " height: " << height << endl ;
     
     
     
     
      GLuint text_id ;
     
      glGenTextures(1, &text_id) ;
      glBindTexture(GL_TEXTURE_2D, text_id);
     
     
      glTexImage2D(GL_TEXTURE_2D, //target
                  0, //level=First mip-level          
                  byte_count, //internal_format=bytes per pixel
                  width,  //image width
                  height, //image height
                  0, //border=texture border set or not 1|0
                  mode, //format=GL_RGB|GL_RGBA
                  GL_UNSIGNED_BYTE, //type=storing format
                  (unsigned char *) data_buffer.data()) ;
     
     
     
     
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     
      cout << "Success loading texture from file.\n\n" << endl ;
     
      cout.flush() ;
     
      return text_id ;
    }
    Le script python crée 2 fichiers temporaires servant de buffer entre le C++ et le python.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    12345678910111213141516171819202122232425
    from PIL import Image
     
    from sys import argv, exit
     
    if len(argv) != 2 :
      print "usage %s imagepath" % argv[0]
      exit(1)
     
    a=Image.open(argv[1])
     
    b=file("/tmp/texture.px","w") ;
    c=file("/tmp/texture.info","w")
     
    c.write(a.mode+"\n") ;
    c.write(str(a.size[0])+"\n") ;
    c.write(str(a.size[1])+"\n") ;
     
    bytes=a.tobytes()
     
    reversed(bytes) # OpenGL texture must be flipped data.
     
    b.write(bytes) ;
     
    c.close()
    b.close()
    Et j'affiche une texture par face grâce a l'identifiant de texture dans la méthode display de l'objet cube:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
    /** Start draw cube. **/
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(0).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(0));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(0));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4) ;
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(1).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(1));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(1));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(2).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(2));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(2));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 8,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(3).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(3));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(3));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 12,  4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(4).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(4));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(4));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        if (use_colors) {
          glUniform4fv(mv_color, 1, colors.at(5).get_vector()) ;
        }
        else if (use_textures) {
          glBindTexture(GL_TEXTURE_2D, texture_ids.at(5));
          //glActiveTexture(GL_TEXTURE + texture_ids.at(5));
        }
        glDrawArrays(GL_TRIANGLE_FAN, 20, 4);
        glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ;
     
        /** End draw cube. **/
    Par exemple pour faire un dès avec un chiffre sur chaque face avec des images comme celle-ci: Nom : texture_01.png
Affichages : 1025
Taille : 213 octets Le cube s'affiche avec la couleur de fond de chaque image qui sont différentes, mais les chiffres pourtant contenus dans la même image s'affichent par dessus l'espace que le cube occupe pendant qu'il tourne. Autrement dit les chiffres (en noir) ne sont pas insérer dans chaque face: ce n'est pas comme avec pyopengl ou l'on pouvait fixer les 4 coins de la texture aux vertex de la face... Ou alors avec des images de différentes couleurs comme celle-ci: Nom : texture_turkishscale_mesh.png
Affichages : 1065
Taille : 205 octets Les petits carreaux en plus clair apparaissent aux dessus de l'espace du cube au lieu de s'insérer dans la face, comme la couleur de fond le fait, et ne sont donc pas a parallèle aux côtés de la face... J'ai essayer de faire un buffer pour chaque texture ce ne fonctionne pas non plus, je ne sais si je l'ai fait correctement. Bon je vous laisse une archive avec les sources et un makefile afin que vous pouvez voir de vos propre yeux le problème, ici. Il suffit de taper "make" ou "make pb" puis "make exec" pour lancer le programme. Merci pour vos réponses éclairées et votre aide précieuse. else if (use_textures) { glBindTexture(GL_TEXTURE_2D, texture_ids.at(5)); //glActiveTexture(GL_TEXTURE + texture_ids.at(5)); } glDrawArrays(GL_TRIANGLE_FAN, 20, 4); glMemoryBarrier(GL_UNIFORM_BARRIER_BIT) ; /** End draw cube. **/
    Par exemple pour faire un dès avec un chiffre sur chaque face avec des images comme celle-ci:

    Nom : texture_01.png
Affichages : 1025
Taille : 213 octets

    Le cube s'affiche avec la couleur de fond de chaque image qui sont différentes, mais les chiffres pourtant contenus dans la même image s'affichent par dessus l'espace que le cube occupe pendant qu'il tourne. Autrement dit les chiffres (en noir) ne sont pas insérer dans chaque face: ce n'est pas comme avec pyopengl ou l'on pouvait fixer les 4 coins de la texture aux vertex de la face...

    Ou alors avec des images de différentes couleurs comme celle-ci:

    Nom : texture_turkishscale_mesh.png
Affichages : 1065
Taille : 205 octets

    Les petits carreaux en plus clair apparaissent aux dessus de l'espace du cube au lieu de s'insérer dans la face, comme la couleur de fond le fait, et ne sont donc pas a parallèle aux côtés de la face...

    J'ai essayer de faire un buffer pour chaque texture ca ne fonctionne pas non plus, je ne sais si je l'ai fait correctement.


    Bon je vous laisse une archive avec les sources et un makefile afin que vous pouvez voir de vos propre yeux le problème, ici.


    Il suffit de taper "make" ou "make pb" puis "make exec" pour lancer le programme.

    Merci pour vos réponses éclairées et votre aide précieuse.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  11. #11
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Ah ! Problème amusant. J'ai testé le programme, vu que je n'avais rien compris à l'explication .
    En fait, la texture s'applique sur l'ensemble de la fenêtre. Maintenant que j'ai vu le code du shader, je comprend mieux :
    Code glsl : Sélectionner tout - Visualiser dans une fenêtre à part
    color = texture(s, gl_FragCoord.xy / textureSize(s, 0)  ).rgba ;
    gl_FragCoord.xy -> Position (sur l'écran (en espace homogène, mais à ce niveau, ce n'est qu'un détail)) du pixel actuellement traité par le fragment shader.
    Du coup, le shader repose sur la position réelle (à l'écran) du pixel pour déterminer quel pixel prendre de la texture pour l'afficher. Du coup, ça donne cet effet (qui est sympa). Vous, vous avez besoin de la position du pixel par rapport à la face du carré. Pour cela, vous devez passer de nouvelles informations avec chacun de vos sommets : les coordonnées de texture. Je ne fais pas un cours, tout est indiqué ici : http://jeux.developpez.com/tutoriels...-cube-texture/
    Donc, en plus de la position et de la couleur, vous devez aussi passer les coordonnées de texture pour l'application adéquate de la texture.


    L'attente de 280 milliseconde par image, ça fait comme si cela saccade
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  12. #12
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    Merci pour votre aide Little White,

    J'ai déjà toute la série de tutoriels que vous avez écrit sur l'OpenGL moderne, sur mon disque dur afin de l'avoir en offline depuis longtemps et j'ai déjà parcourus votre tutoriel mais pas regarder le code source.
    je vais le faire et bravo pour l'effort.

    Je pense que je vais publier mes prochaines créations sous la même licence:
    La licence utilisée pour ce code est "DO WHAT THE FUCK YOU WANT TO PUBLIC LICENCE", soit, elle vous permet de faire tout ce que vous voulez.
    Car c'est la bonne philo je pense.

    Et décrire les bibliothèques comme vous:
    SFML, inclut une machine à café, une machine à laver et un téléphone portable.
    Mort de rire...



    J'ai penser a exec() et co. pour lancer le script et|ou le threader pour l'attente et mettre une fenêtre "Loading files... Please wait.".
    Quand ce sera au point. Qu'en pense tu comment tu ferai ?
    Sinon il y a une solution de créer une lib C(++) qui exécute du code python (et non le contraire.) car cela est possible voir Linux Magazine hors série: Langage C page 97-107.


    Merci pour vos réponses et votre aide précieuse.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  13. #13
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut je n'y arrive pas tout a fait, mais j'y suis presque (with a little help from my friends).
    Salut les OpenGL,

    J'ai consciencieusement lu le tutoriel ainsi que le code source.
    Ce que je n'ai pas très bien compris c'est les coordonnées UV que vous avez générer avec Blender.

    Alors j'ai simplement mis les parties X et Y des coordonnées des sommets de mon cube dans un buffer (A la place de coordonnées dites UV ???) puis appliquer le code employer dans le tutoriel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    array<float, 4*2*6> text_coords ; // or 4*4*6*sizeof(float) 
     
      c=0 ;
      for (auto &val : faces) {
     
        for (int cc=0 ; cc < 4*4 ; cc += 4 ) {
          text_coords.at(c)   = val[cc]   ;     // Getting the x coordinate from every face vertex.
          text_coords.at(c+1) = val[cc+1] ;     // Getting the y coordinate from every face vertex.
          //text_coords.at(c+2) = val[cc+2] ;   // Getting the z coordinate from every face vertex.
          //text_coords.at(c+3) = val[cc+3] ;   // Getting the w coordinate from every face vertex.
     
          c += 2  ; // c += 3 or c += 4.        It seems to work better with all coordinate component in the buffer.
        }
     
      }
     
      glBindBuffer(GL_ARRAY_BUFFER, buffers[1]) ;
      glBufferData(GL_ARRAY_BUFFER,
                          4*2*6*sizeof(float), // You can try to set it on 4*4*6*sizeof(float)
                          text_coords.data(),  // And set it on position.data()
                          GL_STATIC_DRAW) ;
    Mais il semble que cela fonctionne mieux avec un buffer contenant X,Y, Z et W et en jouant avec l'argument stride de la fonction glVertexAttribPointer().

    Puis fait insérer le code suivant dans le début de la méthode display().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
        /** The textures **/
        GLuint TextureID  = glGetUniformLocation(program, "myTextureSampler");
     
        GLuint idTexture  = glGetAttribLocation(program,  "vertexUV");
     
        glUniform1i(TextureID, 0);
     
        // The textures (UV) coordinates buffer:
        glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
        glVertexAttribPointer(idTexture,
                              2,         
                              GL_FLOAT,
                              GL_FALSE,
                              0,      // and | or play with this value (the offset) to get differents displays, 
                              NULL) ; // try first to change nothing except to set the stride value on 1 (The UV coordinates seems to be the diagonal from the square).
     
     
     
        glEnableVertexAttribArray(idPosition);
        glEnableVertexAttribArray(idTexture);
    Le vertice shader:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #version 430 core
     
    in vec4 position ;
     
    in vec2 vertexUV;
     
    uniform mat4 mv_matrix ;                                                                   
     
    out vec2 UV;
     
    void main(void)                                              
    {                                                            
        gl_Position   = mv_matrix * vec4(position) ;
        UV = vertexUV ;                                          
    }
    Le fragment shader:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #version 430 core                                        
     
    out vec3 color;                                          
     
    // Interpolated values from the vertex shaders
    in vec2 UV;
     
    // Values that stay constant for the whole mesh.
    uniform sampler2D myTextureSampler;
     
    void main(void) {                                        
      color = texture(myTextureSampler, UV ).rgb ;
    }
    J'ai obtenus comme résultat 2 faces sur les 6 qui semblent correct mais qui ne sont pas tout a fait fidèle a la texture, les autres faces affichant simplement la couleur de fond de la texture.
    Car il semble que dans les deux faces correct la texture semble être coupés en 4 quarts mais découper de manière a ce que le centre de la face du cube semble correspondre a un coin de la texture...???

    Texture dont je parle:


    Il serai grand temps de me corriger. S'il vous plaît aidez moi j'y suis presque !

    Je vous laisse une archive pratiquement identique aux autres de manière a ce que vous voyiez le problème par vous même, ici.

    Merci pour vos réponses et votre aide.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  14. #14
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 045
    Points : 11 368
    Points
    11 368
    Billets dans le blog
    10
    Par défaut
    Salut!

    As-tu compris comment fonctiennent les coordonnées de texture?

    Elles sont généralement comprises entre 0.0 et 1.0 (cf. http://jeux.developpez.com/tutoriels...ation-texture/ pour une explication plus détaillée) et ne sont aucunement relatives à la position des sommets (en tout cas pas directement comme tu as pu l'écrire).

    Donc tu mets les coordonnées de texture dans ton buffer de coordonnées de texture (vu que tu en as fait un séparé), tu laisses le stride à zéro puisque c'est le paramètre qui contrôle l'espacement entre 2 éléments de même type, dans ton buffer (cf. http://jeux.developpez.com/tutoriels...2-hello-point/ pour une explication plus détaillée).

    Et aussi, je pense que plutôt que de tatonner et faire n'importe quoi (pardon pour la rudesse de l'expression) il vaudrait mieux te plonger un peu dans la théorie. sur DVP il y a d'excellents tutoriels/traductions, n'hésite pas à les suivre complètement plutôt que d'en prendre des bribes par-ci par-là sans comprendre ce que tu prends.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  15. #15
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    Salut et merci pour la réponse qui semble bien pouvoir m'aider.

    As-tu compris comment fonctionnent les coordonnées de texture?
    Avant de lire ton lien NON car le tutoriel de Alexandre Laurent sur les textures n'explique en rien la nature des coordonnées de texture ou dîtes UV car il les génère avec blender sans vraiment expliquer (j'ai même crus qu'il faut donner les diagonales dans le cas d'un cube...) SI JE PUIS ME PERMETTRE LA CRITIQUE.

    Et aussi, je pense que plutôt que de tatonner et faire n'importe quoi (pardon pour la rudesse de l'expression) il vaudrait mieux te plonger un peu dans la théorie
    Je sais mais je lis un livre sur OpenGL 4.3 qui n'est pas terriblement écrit côté pratique de OpenGL, et n'explique en rien la théorie sur les textures car le livre utilise une bibilothèque spécialement écrit pour le livre comme support: Ils ont voulus trop bien faire.

    Et je souffre de la maladie de ne rarement chercher les infos dans le net, je préfère les livres papiers, je prends un médicament pour cette maladie dont la molécule est le STFIOTNY (Search The Fucking Information On The Net Yourself) mais ça ne fonctionne pas super, con d'habitude, donc vos liens sont la bienvenue.

    Donc ta critique est parfaitement justifié je pense.

    Brefs mon livre ne m'aide pas a avancer dans mon problème et le tutoriel d'Alex n'a fait que m'embrouiller d'avantage, il faudrait y ajouter un sous chapitre expliquant la nature des coordonnées UV si je puis me permettre, afin d'améliorer la qualité du tutoriel qui m'a quand même permis de résoudre le problème des carreaux de la texture en premier plan.

    Merci pour vos réponses éclairées et votre aide précieuse.

    Je vais explorer ce qui est explorer ce qui est expliquer dans ton lien.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  16. #16
    Membre expérimenté
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Points : 1 742
    Points
    1 742
    Par défaut
    OUAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIIIIIIIIIIISSSSSSSSSSSSSSSSSSSSS,

    J'ai réussis il faut dire que c'est grâce a lien de dragonjoker59 et je comprends mieux la nature des coordonnées UV ne le prends pas mal Little White mais dans ton tutoriel tu n'explique en rien (ou du moins de manière dfifficilement compréhensible) ce que sont réellement les coordonnées UV, il faudrait faire une mise a jours et donc ajouter un paragraphe si tu en a le courage.

    Mais c'est mon avis et je ne désire en rien t'offenser, c'est juste une critique. Quand a moi il faut que je soigne ma maladie du papier... et chercher plus d'infos sur DEV et le web.

    Merci a tous les participants de la discussion le sujet est clos et le problème régler malgré qu'a un moment j'ai perdus patience et même demander a un amis a moi (du forum) de m'aider.

    Pour info j'ai simplement fait un tableau { { 0.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 } } et construit un pointeur pour les faces du cube.

    Il faut dire que dans ce cas un cube et une texture carré c'était simple et voyez vous je le savais que la solution était vraiment simple et vous remercie de m'avoir laisser trouver tout seul: ça permet d'apprendre !!!

    Et a un de ces jours sur le forum OpenGL car l'aventure est loin d'être terminée.
    Pour faire tes armes:
    Use du présent pour construire ton futur sinon use de ce que tu as appris auparavant.
    Et sois toujours bien armé avant de te lancer.
    Le hasard ne sourit qu'aux gens préparés...
    Site: Website programmation international (www.open-source-projects.net)
    Site: Website imagerie 3D (www.3dreaming-imaging.net)
    Testez aux moins pendant une semaine l'éditeur avec terminaux intégrées it-edit Vous l'adopterai sûrement !
    FUN is HARD WORK !!!

  17. #17
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 826
    Points : 218 288
    Points
    218 288
    Billets dans le blog
    117
    Par défaut
    Je tiens juste à préciser que ce n'est pas mon tutoriel, mais un tutoriel que j'ai traduit (et non écrit). Il est certes perfectible, mais sans autorisation de l'auteur, je ne peux pas le modifier.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  18. #18
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 045
    Points : 11 368
    Points
    11 368
    Billets dans le blog
    10
    Par défaut
    A propos du papier.

    Je dois te dire que j'ai commencé comme ça aussi, j'ai juste eu un meilleur bouquin que le tien, on dirait XD (je n'ai su que plus tard que c'était la traduction française du Red Book)
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 13/08/2005, 01h43
  2. Partage de code par plusieurs instances
    Par a.tintin dans le forum MFC
    Réponses: 3
    Dernier message: 08/08/2005, 15h03
  3. Réponses: 3
    Dernier message: 16/10/2003, 11h22
  4. Communiquer entre plusieurs instances d'applications
    Par bourinator dans le forum C++Builder
    Réponses: 5
    Dernier message: 28/09/2003, 12h24
  5. [] plusieurs instances de form avec leur contexte ?
    Par Seb-31 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 11/04/2003, 14h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo