3D Cube soll sich drehen und verschoben werden c++/SDL2/OpenGL-ES



  • Hallo
    Seit einiger zeit versuche ich mithilfe von SDL2 sowie C++ spiele fürs handy
    zu entwickeln -> dabei hab ich sehr sehr viele und gute Resultate gemacht..

    Das ganze mache ich mit dem C4Droid Compiler aus dem Play-Store (kostet aber 3-4€ ).. dieser kann C++/SDL2 programme auf Android ausführen und sogar mithilfe des Export Button - APK erzeugen 🙂 <- tolle Sache

    jetzt hab ich aber gesehn dass man irgendwie mithilfe von SDL auf OpenGL einbinden kann

    STOP! -> hierbei handelt es sich nicht um das übliche OpenGL sondern um OpenGL-Es

    -> hierzu finde ich fast keine tutorials, aber aus einem anderen Android Compiler hab ich diesen einfachen code gefunden:

    /*
      CCTools SDL plugin GLES example
    
      Derived from SDL testgles sources:
    
      Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    
      This software is provided 'as-is', without any express or implied
      warranty.  In no event will the authors be held liable for any damages
      arising from the use of this software.
    
      Permission is granted to anyone to use this software for any purpose,
      including commercial applications, and to alter it and redistribute it
      freely.
    */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    
    #include <SDL2/SDL.h>
    #include <SDL2/SDL_opengles.h>
    
    static SDL_Window *window;
    static SDL_GLContext context;
    
    static void AspectAdjust(int w, int h)
    {
        float aspectAdjust;
    
        aspectAdjust = (4.0f / 3.0f) / ((float)w / h);
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrthof(-2.0, 2.0, -2.0 * aspectAdjust, 2.0 * aspectAdjust, -20.0, 20.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glShadeModel(GL_SMOOTH);
    }
    
    static void Render()
    {
        static GLubyte color[8][4] = { {255, 0, 0, 0},
        {255, 0, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {255, 255, 255, 255},
        {255, 0, 255, 255},
        {0, 0, 255, 255}
        };
    
        static GLfloat cube[8][3] = { {0.5, 0.5, -0.5},
        {0.5f, -0.5f, -0.5f},
        {-0.5f, -0.5f, -0.5f},
        {-0.5f, 0.5f, -0.5f},
        {-0.5f, 0.5f, 0.5f},
        {0.5f, 0.5f, 0.5f},
        {0.5f, -0.5f, 0.5f},
        {-0.5f, -0.5f, 0.5f}
        };
    
        static GLubyte indices[36] = { 0, 3, 4,
            4, 5, 0,
            0, 5, 6,
            6, 1, 0,
            6, 7, 2,
            2, 1, 6,
            7, 4, 3,
            3, 2, 7,
            5, 4, 7,
            7, 6, 5,
            2, 3, 1,
            3, 0, 1
        };
    
        /* Do our drawing, too. */
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        /* Draw the cube */
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
        glEnableClientState(GL_COLOR_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, cube);
    
        glEnableClientState(GL_VERTEX_ARRAY);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
    
        glMatrixMode(GL_MODELVIEW);
       glRotatef(5.0, 1.0, 1.0, 1.0);
    }
    
    int main(int argc, char *argv[])
    {
        int done;
        SDL_DisplayMode mode;
        SDL_Event event;
        Uint32 then, now, frames;
    
        if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { /* Initialize SDL's Video subsystem */
            SDL_Log("Unable to initialize SDL");
            return 1;
        }
    
        SDL_GetDesktopDisplayMode(0, &mode);
    
        SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 16);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
    
        // Create our window centered
        window = SDL_CreateWindow("GLES example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
    	mode.w, mode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
        if (!window) {
    	// Die if creation failed
    	SDL_Log("Unable to create window");
    	return 1;
        }
    
        // Create our opengl context and attach it to our window
        context = SDL_GL_CreateContext(window);
        if (!context) {
    	SDL_Log("Unable to create GL context");
    	return 1;
        }
    
        SDL_GL_MakeCurrent(window, context);
    
        SDL_GL_SetSwapInterval(1);
    
        SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
        SDL_Log("\n");
        SDL_Log("Vendor     : %s\n", glGetString(GL_VENDOR));
        SDL_Log("Renderer   : %s\n", glGetString(GL_RENDERER));
        SDL_Log("Version    : %s\n", glGetString(GL_VERSION));
        SDL_Log("Extensions : %s\n", glGetString(GL_EXTENSIONS));
        SDL_Log("\n");
    
        AspectAdjust(mode.w, mode.h);
    
        /* Main render loop */
        frames = 0;
        then = SDL_GetTicks();
    
        done = 0;
        while (!done)
        {
            /* Check for events */
            ++frames;
            while (SDL_PollEvent(&event)) {
                switch (event.type) {
                case SDL_KEYDOWN:
                    if (event.key.keysym.scancode == SDL_SCANCODE_AC_BACK) {
                        done = 1;
                    }
                    break;
                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_RESIZED:
                            /* Change view port to the new window dimensions */
                            AspectAdjust(event.window.data1, event.window.data2);
                            /* Update window content */
                            Render();
                            SDL_GL_SwapWindow(window);
                            break;
                    }
                }
            }
    
            Render();
            SDL_GL_SwapWindow(window);
        }
    
        /* Print out some timing information */
        now = SDL_GetTicks();
        if (now > then) {
            SDL_Log("%2.2f frames per second\n",
                   ((double) frames * 1000) / (now - then));
        }
    
        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
    
        return 0;
    }
    

    so.. nach sehr sehr langen lesen und verstehn, bin ich dahintergekommen wie das glaub ich so ein bisschen funktionier..

    Jetz wollte ich folgendes machen...
    ein Würfel den man irgendwo Positionieren kann auf dem screen

    void Render_cube(float x, float y, flaot z)
    {
        static GLubyte color[8][4] = { {255, 0, 0, 0},
        {255, 0, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {255, 255, 255, 255},
        {255, 0, 255, 255},
        {0, 0, 255, 255}
        };
    
        static GLfloat cube[8][3] = { {0.5, 0.5, -0.5},
        {0.5f, -0.5f, -0.5f},
        {-0.5f, -0.5f, -0.5f},
        {-0.5f, 0.5f, -0.5f},
        {-0.5f, 0.5f, 0.5f},
        {0.5f, 0.5f, 0.5f},
        {0.5f, -0.5f, 0.5f},
        {-0.5f, -0.5f, 0.5f}
        };
    
        static GLubyte indices[36] = { 0, 3, 4,
            4, 5, 0,
            0, 5, 6,
            6, 1, 0,
            6, 7, 2,
            2, 1, 6,
            7, 4, 3,
            3, 2, 7,
            5, 4, 7,
            7, 6, 5,
            2, 3, 1,
            3, 0, 1
        };
    
        glTranslatef(x,y,z)
        /* Do our drawing, too. */
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        /* Draw the cube */
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
        glEnableClientState(GL_COLOR_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, cube);
    
        glEnableClientState(GL_VERTEX_ARRAY);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
    
        glMatrixMode(GL_MODELVIEW);
        glRotatef(5.0, 1.0, 1.0, 1.0);
    }
    
    //in main...
    Render_Cube(0.5f, 0.0f, 0.0f );
    

    zusätzlich wollte ich diesen Würfel an der stelle mit GL_ROTOATE drehen
    lassen ... problem... der würfel flackert wie sau !

    was mache ich falsch
    - egal ob der cube in einer While schleife oder einmal ausgeführt wird ... er flackert -> ich gehe davon aus es liegt an GL_Translatef , weil ich den würfel ja sage dass er sich immer an dieser stelle aufhalten soll

    achja ich wollte den Würfel mit einer For-Schleife 10mal hinter einander
    zusätzlich darstellen aber dann kommt nicht aus dem screen

    for (i=0; i<10; i++)
    {
     Render_cube(i*0.5f, 0.0f ,0.0f)
    }
    

    könnt ihr mir helfen ???



  • Hi!

    Wenn ich das richtig sehe, dann wird die Transformationsmatrix (Modelview-Matrix) innerhalb der Hauptschliefe nicht zurückgesetzt, d.h. alle Tranformationen ( glTranslatef() und glRotatef() ) addieren sich mit jeden Frame immer weiter auf.
    Versuch mal in Render_cube() die Einheitsmatrix zu laden ( glLoadIdentity() ), bevor du Transformationen anwendest.

    Patty1991 schrieb:

    achja ich wollte den Würfel mit einer For-Schleife 10mal hinter einander
    zusätzlich darstellen aber dann kommt nicht aus dem screen

    for (i=0; i<10; i++)
    {
     Render_cube(i*0.5f, 0.0f ,0.0f)
    }
    

    Das 10mal darstellen würde so funktionieren, wäre da nicht das glClear() in der Render_cube() -Funktion, das dir bei jedem Aufruf erstmal den Bildschirm löscht. Es empfiehlt sich das glClear() auszulagern, vielleicht in eine (oder die) Render() -Funktion?

    static void Render_cube(float x, float y, float z)
    {
       ...
    
       // Hinweis: Transformations-Reihenfolge ist wichtig!
       // Zuerst rotieren, dann verschieben erzeugt einen Würfel der sich
       // an Position x,y,z um sich selbst dreht. Anders herum würde
       // der Würfel um den Nullpunkt des Welt-Koordinatensystems
       // drehen und ganz schön über den Bildschirm flitzen ;-)
    
       // Rotation 
       glRotatef(5.0, 1.0, 1.0, 1.0);
       // Hinweis: Für animierte Rotation sollte der 
       // Rotationswinkel natürlich variabel sein. Vielleicht
       // Winkel als Parameter w übergeben?
       // glRotatef(w, 1.0, 1.0, 1.0);
    
       // Translation
       glTranslatef(x,y,z)
    
       // Würfel zeichnen... glDrawElements() etc.
    
       ...
    }
    
    static void Render()
    {
       // Bildschirm leeren.
       glClearColor(0.0, 0.0, 0.0, 1.0);
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       // Folgende Tranformationen beziehen sich auf Modelview-Matrix.
       glMatrixMode(GL_MODELVIEW);
       // Einheitsmatrix laden -> Erstmal keine Transformation.
       glLoadIdentity();
       // Würfel zeichnen.
       for (i=0; i<10; i++)
       {
          Render_cube(i*0.5f, 0.0f ,0.0f);
       }
    }
    

    Hoffe das löst deine Probleme.

    Gruss,
    Finnegan



  • Wenn ich schon dabei bin, hier noch ein Vorschlag, wie man den Code ein wenig umstrukturieren kann, so dass er etwas besser handhabbar wird - wenn du z.B. eine animierte Rotation haben möchtest. Es ist generell empfehlenswert Modelle wie den Würfel um den Nullpunkt herum zu zeichnen und die Transformationen wie Verschiebung und Rotation nicht als Parameter an Render_cube() zu übergeben, sondern diese "von außen" direkt in die aktuelle Transformationsmatrix (Modelview-Matrix) "einzubacken" (hineinzumultiplizieren). Den Vorteil dieser Vorgehensweise erkennt man spätestens dann, wenn man anfängt, komplexere Modelle aus einfachen Grundformen (wie dem Cube) zusammenzubauen (zwei Beine aus langgezogenen Cubes mit glScalef() , zwei Arme, ein Rumpf, ein kubischer Kopf, etc.):

    static void Render_cube()
    {
        static GLubyte color[8][4] = { {255, 0, 0, 0},
        {255, 0, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {0, 255, 0, 255},
        {255, 255, 255, 255},
        {255, 0, 255, 255},
        {0, 0, 255, 255}
        };
    
        static GLfloat cube[8][3] = { {0.5, 0.5, -0.5},
        {0.5f, -0.5f, -0.5f},
        {-0.5f, -0.5f, -0.5f},
        {-0.5f, 0.5f, -0.5f},
        {-0.5f, 0.5f, 0.5f},
        {0.5f, 0.5f, 0.5f},
        {0.5f, -0.5f, 0.5f},
        {-0.5f, -0.5f, 0.5f}
        };
    
        static GLubyte indices[36] = { 0, 3, 4,
            4, 5, 0,
            0, 5, 6,
            6, 1, 0,
            6, 7, 2,
            2, 1, 6,
            7, 4, 3,
            3, 2, 7,
            5, 4, 7,
            7, 6, 5,
            2, 3, 1,
            3, 0, 1
        };
    
        /* Draw the cube */
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
        glEnableClientState(GL_COLOR_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, cube);
    
        glEnableClientState(GL_VERTEX_ARRAY);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
    }
    
    static void Render(Uint32 time)
    {
       // Bildschirm leeren.
       glClearColor(0.0, 0.0, 0.0, 1.0);
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       // Folgende Tranformationen beziehen sich auf Modelview-Matrix.
       glMatrixMode(GL_MODELVIEW);
       // Einheitsmatrix laden -> Erstmal keine Transformation.
       glLoadIdentity();
       // Eine komplette Rotation je 10 Sekunden (10.000 ms).
       // Die Rechnung sieht etwas komisch aus, das liegt allerdings nur
       // daran, dass ich gewohnheitsmässig Fließkommazahlen nur ungern zu 
       // groß werden lasse (Rundungsfehler).
       float rotation = 360.0f * static_cast<float>(time % 10000) / 10000.0f;
       // Rotation anwenden (mit Modelview-Matrix multiplizieren).
       glRotatef(rotation, 1.0, 1.0, 1.0);
       // Würfel zeichnen.
       for (i=0; i<10; i++)
       {
          // Ja, hier steht jetzt nicht i*0.5f. Hier nutzen wir mal aus,
          // dass sich Transformationen "aufaddieren" wenn wir die Matrix
          // nicht zurücksetzen (hatte das ja eingangs erwähnt).
          glTranslatef(0.5f, 0.0f ,0.0f) 
          Render_cube();
       }
    }
    
    int main(int argc, char *argv[])
    {
       ...
    
       // Es ist nie verkehrt, wenn die Render-Funktion
       // die aktuelle Zeit kennt, wenn man irgendwas
       // animieren möchte. SDL_GetTicks() gibt die seit
       // Programmstart vergangene Zeit in Millisekunden zurück.
       Render(SDL_GetTicks());
       SDL_GL_SwapWindow(window);
    
       ...
    }
    


  • Hi, erstmal danke für so viel ausführliche und verständliche information, nur hab ich noch eine / 2 sachen..

    Die würfel rotiren nich 😞 -> Egal 🙂
    wie bewege ich nicht den würfel sondern michselbst durch den 3d raum ?

    Gibt es da auch so etwas wie glTranslatef oder besser gesagt:

    wie dann ich denn glrotate,glTranslate sagen , dass sich nur das gewünschte object bewegt - dann könnte ich eine kleine camera move funtion schreiben 😉



  • und... wie sage ich meiner forschleife dass sie z.b. länge und breite bestimmen kann..

    ich brauche leider die float übergabe im cube
    nur das problem ist: render ich so:

    static void cube(flaot x,float y,float z)
    {
     glTranslatef(x,y,z)
     ...
    }
    
    static void Render
    {
     int i;,j,k;
     for(i=0; i<5; i++)
     {
      cube(i*0.5f,0.0f,0.0f);
     }
     ...
    }
    

    dann werden zwar 5 cubes erstellt, jedoch nicht hintereinander sondern der 2te ist noch am 1sten.. der 3te hat leichten abstand und der 4te ich nur noch teils im screen zu sehn

    und render ich so:

    static void cube()
    {
    }
    
    static void Render
    {
     int i;,j,k;
     for(i=0; i<5; i++)
     {
      glTranslatef(0.5f,0.0f,0.0f);
      cube();
     }
     ...
    }
    

    dann funtioniert zwar alles einbahnfrei aber wie mache ich denn jetzt wenn ich
    dann ich nicht nur in eine richtung soindern auch nach unten rendere ..

    ich mein:

    ...
    for(i=0; i<5; i++)
     {
      for(i=0; i<5; i++)
      {
      //?? und jetzt ??
      // glTranslate(i*0.5,j*0.0f,0.0f
      // cube();
      )
     }
    ...
    


  • 😛 😎 HABS !!!

    Danke für den Tipp mit dem STACK !!

    hatte glPushMatrix() und glPopMatrix() vergessen

    void Render();
    {
    ...
    glLoadIdentity();
    
    int i,j;
    int chunk = 10;
    float size = 0.5f;
    
       for (i=0; i<chunk; i++)
       {
        for (j=0; j<chunk; j++)
        {
        glPushMatrix();
        glTranslatef(i*size,j*size,0.0f); 
        cube();
       glPopMatrix(); 
        }
     }
    ...
    }
    

Anmelden zum Antworten