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 screenvoid 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 sollachja ich wollte den Würfel mit einer For-Schleife 10mal hinter einander
zusätzlich darstellen aber dann kommt nicht aus dem screenfor (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()
undglRotatef()
) addieren sich mit jeden Frame immer weiter auf.
Versuch mal inRender_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 screenfor (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 derRender_cube()
-Funktion, das dir bei jedem Aufruf erstmal den Bildschirm löscht. Es empfiehlt sich dasglClear()
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 mitglScalef()
, 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(); } } ... }