[OpenGL-Projekt] Alles auf Anfang [Update 4]

DarkMo

Lötkolbengott/-göttin
huhu, durch unseren Cymes bin ich mal wieder in Schwung gekommen... gott, ich nutz sogar schon shift >< nene, das verbrauch zuviel saft.

also jedenfalls hab ich bei mir jetz mal ne maussteuerung versucht. bedienung soll wie folgt funtzen: rechtsklicke ich mit der maus, kann ich durch die mausbewegung den blickwinkel ändern. durch rollen am mausrad fährt er vor und zurück.

ausgangssituation: ich mach nen kleines array (soviele tasten hat ne maus ja ned ^^) mit erstma 5 plätzen. lmb ist id 0, rmb is die 2 und mausrad vor/zurück is 3 und 4. die 1 is warscheinlich ne mittlere mausstaste - leider geht mausrad klick ned :/ wurscht erstma ^^

hab das ganze jetz so gebaut, dass ich mir den status (geklickt oder aufgehört zu klicken) merke - was beim mausrad schlauerweise ned geht, da es immer den status "aufgehört zu drücken" hat, also sonderlösung >< - sowie die mausposition und die veränderung der mausposition von frame zu frame. joa, und mittels der veränderung der position lass ich dann die ansicht halt rumrotieren (hab da nen cameraFrame vorschlag aus meinem dollen buch da drin). hier mal der code:

PHP:
// Globals
// maus einstellungen
#define MOUSE_BUTTONS    5
int                    mouseX = 0, mouseY = 0;        // mausposition
int                    mChangeX = 0, mChangeY = 0;    // änderung der mausposition
int                    mouseKey = -1;                // maustaste
long                mouseMove = 0;                // bewegt sich die maus? (0 = nein, alles andere = letzter zeitpunkt der bewegung als timestamp)
int                    mouseTresh = 50;            // in ms - zeit bevor mausbewegung negiert wird

GLFrame                cameraFrame;                // global camera instance

struct keyState {
    int key;
    int status;
    int x;
    int y;

    void init(int k, int ks, int kx, int ky) {
        this->key = k;
        this->status = ks;
        this->x = kx;
        this->y = ky;
    }
};
keyState            pressedMouse[MOUSE_BUTTONS];        // platzhalter für maustasten

...

// ----------- Callback functions ----------- //
void mouseClick(int key, int status, int x, int y)
{
    if(key < MOUSE_BUTTONS) {
        if(key == 3 || key == 4) status = 0;
        pressedMouse[key].init(key, status, x, y);
    }
    /*
    0: lmb
    2: rmb
    3: mr hoch
    4: mr runter
    */
}

void mouseActive(int x, int y)
{
    mChangeX = x - mouseX;
    mChangeY = y - mouseY;
    mouseX = x;
    mouseY = y;
    mouseMove = GetTickCount();
}

void mousePassive(int x, int y)
{
    mChangeX = x - mouseX;
    mChangeY = y - mouseY;
    mouseX = x;
    mouseY = y;
    mouseMove = GetTickCount();
}
// ----------- Callback functions ----------- //

void SetupRC(void) {
    for(int i=0; i<MOUSE_BUTTONS; i++) pressedMouse[i].init(i, 1, 0, 0);
    ...
}

void RenderScene(void) {
    long elapsedTime = GetTickCount() - FrameTickCount;
    long FrameTickCount = GetTickCount();

    float linear = 0.2f;
    float angular = float(m3dDegToRad(1.0f));

    if(pressedMouse[3].status == 0) cameraFrame.MoveForward(linear);
    if(pressedMouse[4].status == 0) cameraFrame.MoveForward(-linear);
    if(pressedMouse[2].status == 0) {
        cameraFrame.RotateWorld(-angular, 0.f, (float)(elapsedTime * mChangeX), 0.f);
        cameraFrame.RotateWorld(-angular, (float)(elapsedTime * mChangeY), 0.f, 0.f);
    }

    ...

    long timePassed;
    if(mouseMove == 0) {
        mChangeX = 0;
        mChangeY = 0;
    } else {
        timePassed = FrameTickCount - mouseMove;
        if(timePassed > mouseTresh) mouseMove = 0;
    }
}
so, das sollten alle schnipsel sein. ich hatte erst das problem, dass ohne mausbewegung auch keine berechnung der variablen mChangeX und Y erfolgte, die diese auf 0 setzen. also wenn man RMB gedrückt hatte, die maus bewegte und dann aufhörte, wurden die werte der letzten bewegung immer weiter genutzt. also anstatt anzuhalten, weil auch die maus still steht, hat sichs immer weiter und weiter gedreht ^^ deswegen hab ich das mit mouseMove und mouseTresh eingebaut. bei jeder bewegung bekommt mouseMove den zeitstempel als wert und der wird dann später mit mouseTresh verglichen. nach 50 milisekunden (hatte nachm rumtesten mit werten ganz gut gefunzt) wird dann mChangeX und Y auf 0 resettet. ohne das war die bewegen total ruckhaft und kaum vorhanden. scheinbar fragt der ned so sehr oft bei der maus nach oder so >< ohne diesen treshold wollts jedenfalls garnich so recht klappen (entweder er bewegt und bewegt sich - oder es zuckelt langsam vor sich hin ^^).

gut, also soweit so gut, das funzt. jetz hab ich nur noch ein problem: wenn ich die maus diagonal beweg, also er x UND y drehen muss, dann zuckelts wieder :/ also das bild springt blöde umher, wie wenn er erst eine drehung rendert und dann die nächste >< pausen dazwischen sind ned, is also nen andres ruckeln wie ohne das treshold gedöhns (da bewegt er sich nur alle sekunde ca nen bissl, hier aber is die bewegung stetig, aber zuckelnd).

wie ichs jetz hab is schon die 2. version.
PHP:
if(pressedMouse[2].status == 0) cameraFrame.RotateWorld(-angular, (float)(elapsedTime * mChangeY), (float)(elapsedTime * mChangeX), 0.f);
also beide drehungen in einem befehl - brachte auch kein andres ergebnis. hat irgendwer ne idee, woran das liegt oder sogar, wie ichs lösen könnt? ^^
 
Zuletzt bearbeitet:
AW: Maussteuerung bei meinem Projekt

Hi,

also ich habe mich jetzt nicht sehr eingedacht, da Zeitmangel, aber bei mir mache ich es so (jetzt nur auf die Maus bezogen):

1) Pre-Update-Call
- Mausstatus abrufen (nicht per Callback, sondern jedes Frame immer wieder)
...

2) Update-Call
- Mausdaten berechnen (wo befindet sich gerade der Cursor im aktuellen Window, wo zeigt er im 3-dimensionalen hin etc.
- Szenenkamera mit den berechneten Daten aktualisieren (z.B. rotationsmatrizen anwenden, wie in deinem Code beschrieben)
...
- Alle im Pre-Update-Call erhaltenen Werte resetten (bzw. sicherstellen, dass sie in jedem Call neu überschrieben werden)

3) Render-Call
- Rendern halt^^

________________________________________________
Die Reihenfolge spielt bei solchen Sachen eine große Rolle!
Ggf. kann es sein, dass deine rotate-funktionen mit den werten nicht klarkommt -> zu groß/klein und liefert deshalb immer nur 0,000....000234 oder sowas zurück
 
AW: Maussteuerung bei meinem Projekt

1) Pre-Update-Call
- Mausstatus abrufen (nicht per Callback, sondern jedes Frame immer wieder)
genau den gedanken hatte ich auch schon, also dass die callback funke das garnich jeden frame testet. ohne meinen treshhold wert da würde ers ja nur alle - tjoa muss wohl was unter 50ms sein ^^ - updaten. da die anwendung grad noch sehr spartanisch is, läuftse aber mit 1000+fps, ergo er macht lange zeit garnix ><

nun DIE frage: wie stelle ich das denn ohne die callback funktion fest? ^^ ich war schon froh, diese methode erfahren zu haben :fresse:

und wegen deinem satz am ende: wenn ich die maus nur in x oder y richtung bewege, funzt es schön flüssig/weich, wie ich mir das vorstelle. nur wenn er beide gleichzeitig rotieren soll, macht er hick hack ><

oho: http://nehe.gamedev.net/tutorial/picking_alpha_blending_alpha_testing_sorting/16005/ *les* ^^
 
Zuletzt bearbeitet:
AW: Maussteuerung bei meinem Projekt

hier vllt mal was: OpenGL Mouse, how it works.. | DaniWeb

ginge es nicht sonst auch, dass du den Mausstatus irgendwo speicherst und die callback-funktion den mausstatus einfach immer wieder überschreibt. und in deinem update oder render-call kannst du dann ja den mausstatus nutzen, der gerade gespeichert ist ...
 
AW: Maussteuerung bei meinem Projekt

so mach ichs doch grad, das is ja jetz au ned das prob. das zuckelige drehen der kamera nervt mich xD
 
AW: Maussteuerung bei meinem Projekt

aso, dann hab ich da was verhibbelt :D

Vielleicht kannst du dir ja einen kleinen "Buffer" bauen, in den du die Mausdaten reinspeicherst und für das jeweilige Update nimmst du dann den Durchschnittswert für x und y aus dem Buffer. Würde dort aber erstmal nicht über die Länge 5 hinausgehen, da er dann halt noch 5 Callback-Aufrufe etwas nachruckelt!
Ansonsten ..... kp :ugly: :fresse:
Möglicherweise kannst du ja mal AMD fragen wie er das in seiner 3D-Anwendung gemacht hat ...
 
AW: Maussteuerung bei meinem Projekt

Ähm unter OpenGL gibts für die Maustasten schon fertige Macros. Die sollte man verwenden. Insbesondere für drücken und loslassen der Maustasten gibt es diese Macros schon. Wenn du die Mouse-Callback-Function verwendest, dann brauchst du auch nichts besonderes machen, so lange eben eine Maustaste als Trigger verwendet wird. Nur wenn man sich umsehen will ohne Tastendruck muss ein bischen überlegen.

Also die Sache ist eigentlich ziemlich simpel. Eventuell schaff ich es ja mal meinen Code dazu raus zu suchen.

PS: Du musst natürlich aufpassen, wie du mit den Daten umgehst. Wenn du nur die 2D Daten für eine 2D Bewegung in 3D nutzt über entsprechende Transformationen, dann bekommst du eine Invariante, wenn du dich zu weit drehst. Das ist ein bischen eklig, weil dann plötzlich rechts und links vertauscht, oder oben und unten. Dazu hatte ich auch mal Code, der das eleminiert, aber keine Ahnung wo das grad ist.
 
AW: [update] Framebuffer bei meinem Projekt

huhu, ich mal wieder >< diesmal zu einem anderen problem (daher das update im namen):

ich habe vor 1 2 wochen versucht das ganze von direkter-fenster-bemalung ^^ auf framebuffer-bemalung umzustellen. sprich, ich bau nen framebuffer und klatsche dem nen depthbuffer renderbuffer dran und einen für ne textur. die textur wird am ende als bildschirmfüllendes rechteck ausgegeben. funzt soweit auch ganz gut, nur führt er keine tiefenberechnung aus :/ sieht schrecklich aus ><

habt ihr irgendeinen plan, woran das liegen könnte? ich hab meines erachtens nach scho alles rumprobiert und es wollt ned klappen. bei den beispielen aus meinem buch funzt das einwandfrei, bei mir macht ers einfach ned. hab den code verglichen und geschaut ob da was anders is, ich find nix -.- im endeffekt handelt es sich um diesen code, is ja im endeffekt überall gleich. nur dass ich bei mir all das EXT zeug ned hab *hmm* is das ogl1.0 zeugs oder wieso stand das ned so bei meinem buch (ogl3+) mit bei? ^^

OpenGL Frame Buffer Object 101 - OpenGL - Articles - Articles - GameDev.net
 
AW: [update] Framebuffer bei meinem Projekt

Hast du dran gedacht, dass du glEnable(GL_DEPTH_TEST) machen musst?

Es macht natürlich sinn, das nur da ein zu schalten, wo dus auch wirklich brauchst und danach eben wieder aus zu schalten.

Ich glaub glEnable(GL_BLEND) brauchst du auch noch, bin ich mir aber gerade nicht sicher.
 
AW: [update] Framebuffer bei meinem Projekt

jop, habs auch schon direkt davor explizit nochmal angemacht und alles :/ is alles korrekt gebunden zu den zeitpunkt. wenn ich heut abend wieder an meinen rechner komm, kann ichs ja nochmal reinstellen. aber soweit ich das vergleichen konnte, gibts da keine unterschiede und es geht dennoch nich. das hatte mich dann so demotiviert, das ich erstmal pausiert hatte. aber es beschäftigt mich seitdem laufend und ich will ja auch mal vorran kommen ><
 
AW: [update] Framebuffer bei meinem Projekt

bisher hab ich da keine regel für, das kommt noch irgendwann ^^ aber mE is ja genau dazu der depth buffer gut und ohne fbo (bzw ned in ne textur rendern, in fbo un dann per blitting aufs fenster kopiert funzt auch tadellos) klappt das ja auch wies soll. nur sobald ich in ne textur render, macht er plötzlich fehler.

hier mal fix der code noch:
PHP:
// Globals
int                    screenX = 1440, screenY = 900;    // fenster-maße
GLuint                mainFBO;                    // globaler framebuffer
GLuint                mainRBOdepth;                // globaler tiefenpuffer für frambuffer
GLuint                screenTexture;                // globale textur, in die der framebuffer rendert
GLenum                mainFBObuff[] = { GL_COLOR_ATTACHMENT0 | GL_DEPTH_ATTACHMENT }; // eigentlich nur das erste, aber ich wollts halt mal testen
GLenum                windowBuff[] = { GL_BACK_LEFT };

void checkFBO(GLuint FBO) {
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mainFBO);
    GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(status == GL_FRAMEBUFFER_COMPLETE) cout << "Framebuffer erfolgreich erstellt." << endl;
    else cout << "Framebuffer konnte nicht erstellt werden! Status: " << status << endl;
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

innerhalb des großen (immernoch falsch texturierten ^^) raumschiff dings bumses da is ja noch meine erde mit mond und sonne. die atmosphäre (wolken, transparenz bla) wird ganz am ende gezeichnet - was man ja auch sieht ^^ die is eigentlich innerhalb des raumschiffs wird aber eben dennoch gezeichnet, da kein depthtest gemacht wird. genauso die ganzen kleinen anbauten an der schiffskugel - scheint alles durch :/

PHP:
void SetupRC(void) {
    // FBO erstellen
    glGenFramebuffers(1, &mainFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mainFBO);
    // tiefen renderbuffer erstellen
    glGenRenderbuffers(1, &mainRBOdepth);
    glBindRenderbuffer(GL_RENDERBUFFER, mainRBOdepth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, screenX, screenY);
    // screenTexture erstellen
    glGenTextures(1, &screenTexture);
    glBindTexture(GL_TEXTURE_2D, screenTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screenX, screenY, 0, GL_RGBA, GL_FLOAT, NULL);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenX, screenY);
    // (tiefen)renderbuffer und textur an fbo hängen
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mainRBOdepth);
    glClearColor(0.f, 0.f, 0.f, 1.f);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    checkFBO(mainFBO);
    ...
}

void RenderScene(void) {
    ...
    glEnable(GL_DEPTH_TEST);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mainFBO);
    glDrawBuffers(2, mainFBObuff);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    DrawSpace(elapsedTime);
        
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    DrawScreenTexture();
    DrawHud();   // disabled depth test zum bsp

    glutSwapBuffers();
    glutPostRedisplay();
}

void ShutDownRC(void) {
    ...
    // fbo kram löschen
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    glDeleteFramebuffers(1, &mainFBO);
    glDeleteRenderbuffers(1, &mainRBOdepth);
    glDeleteTextures(1, &screenTexture);
}
 

Anhänge

  • SolarSystem 2012-08-13 14-54-00-87.jpg
    SolarSystem 2012-08-13 14-54-00-87.jpg
    76,2 KB · Aufrufe: 134
  • konsole.jpg
    konsole.jpg
    98,3 KB · Aufrufe: 105
Zuletzt bearbeitet:
AW: [update] Framebuffer bei meinem Projekt

kannst du mal zeigen, wies richtig aussehen soll? Kanns mir grad nicht vorstellen, was genau schief geht.
 
AW: [update] Framebuffer bei meinem Projekt

uff, ich such mal eben mein eines, was ich schonma gemacht hatte *such*
 

Anhänge

  • SolarSystem 2012-07-04 20-39-30-44.jpg
    SolarSystem 2012-07-04 20-39-30-44.jpg
    56,5 KB · Aufrufe: 130
AW: [update] Framebuffer bei meinem Projekt

ähm kanns sein, das du nicht alles gleichzeitig in einen Frambuffer packst, sondern mehrere miteinander kombinieren willst und dabei etwas schief geht?

Sieht so aus, als ob die große Kugel nen Framebuffer wäre, welches dann praktisch wie ein Quad mit TExtur drauf gezeichnet wird und dann die anderen Objekte drum rum. Da stimmt dann ja aber die Perspektive nicht mehr, weil das eine eben 2D und in 3D ist, und die anderen Sachen 3D in 3D. Für mich siehts so aus, als ob dass das Problem wäre, aber mit Framebuffern hab ich selbst noch nicht gearbeitet, daher sind mir die Eigenheiten/typischen Fehler leider nicht geläufig :(
 
AW: [update] Framebuffer bei meinem Projekt

hm nope. ich hab EINEN framebuffer und hänge dem einen renderbuffer mit depth_attachment an und einen mit ner textur. ohne textur (einfach in nen renderbuffer gerendert und dort dann alles ins wondow kopiert) klappt das auch noch super. aber sobald ich die textur nutze isses, als hätte ich den tiefentest garnich drin >< regt mich nur auf, dass ich ned dahinterkomm wieso ^^
 
AW: [update] Framebuffer bei meinem Projekt

kanns sein dass du die Textur erst nochmal mit dem Tiefentestbuffer verknüpfen musst?

EDIT:
Schau dir einfach mal das Tutorial an. Ich weiß nicht, ob du die Seite schon kennst, aber die Beispiele da sind ganz gut. http://wiki.delphigl.com/index.php/Tutorial_Framebufferobject

Ich bin jetzt nur den Anfang deines Codes durchgegangen, und das scheint auch soweit zu stimmen, da steckt irgendwo der Teufel im Detail....
 
Zuletzt bearbeitet:
AW: [update] Framebuffer bei meinem Projekt

ich befürchts auch. die verknüpfung des ganzen sollte meines wissens nach das binden an den framebuffer sein. also im groben gestaltet sich das ja so:
- fbo (framebuffer) erstellen
- 2 rbo's (renderbuffer) erstellen - einen für depth und einen für farbinfos (können später natürlich auch mal mehr werden)
- rbo's an fbo binden

das wars im groben schon. in diesem falle müsste man mittels blitting dann die gerenderten daten ausm fbo ins fenster kopieren, was auch tadellos klappte und so aussah wies soll. wenn ich jetz an das farb rbo aber ne textur hänge, dann rendert er nur die farbinfos da rein, beachtet aber das depth rbo scheinbar ned. hmm, muss man vllt die textur nochma gesondert irgendwie mit dem detph ding verknüpfen? wenn hab ich dazu jedenfalls noch nirgends was gefunden ><
 
AW: [update] Framebuffer bei meinem Projekt

schau dir den obigen Link von mir an. Da besprechen Sie expliziet, wie man sogar mit mehreren Texturen umgeht ;)

Da bin ich aber nur drüber geflogen, da mir dazu zu viel Code bei dir wohl fehlt mit Init usw usw.
 
AW: [update] Framebuffer bei meinem Projekt

Code:
void SetupRC(void) {
    // FBO erstellen
    glGenFramebuffers(1, &mainFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mainFBO);
    // tiefen renderbuffer erstellen
    glGenRenderbuffers(1, &mainRBOdepth);
    glBindRenderbuffer(GL_RENDERBUFFER, mainRBOdepth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, screenX, screenY);
    // screenTexture erstellen
    glGenTextures(1, &screenTexture);
    glBindTexture(GL_TEXTURE_2D, screenTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screenX, screenY, 0, GL_RGBA, GL_FLOAT, NULL);
    [COLOR=red][B]glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenX, screenY);[/B]    // (tiefen)renderbuffer und textur an fbo hängen
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mainRBOdepth);
    glClearColor(0.f, 0.f, 0.f, 1.f);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    checkFBO(mainFBO);
    ...
}
AHAHAHAHHAHAHAHAHAHAHAHAHA

ich hab den sack gefunden >< die rote zeile is die wurzel allen übels. es überschreibt den depthbuffer speicher mit falschen einstellungen und schon is alles dahin -.- war immer der meinung, der textur muss man auch speicher zuweisen, aber das geht scheinbar irgendwie anders :ugly: mr durchblick is wohl noch ned mein zweiter name ^^
 
Zurück