Come faccio a fissare una sorgente di luce in OpenGL durante la rotazione di un oggetto?

StackOverflow https://stackoverflow.com/questions/1757958

  •  20-09-2019
  •  | 
  •  

Domanda

Ho una glutSolidTeapot (che ha le sue normali alla superficie generate automaticamente secondo opengl.org) e una sorgente di luce che sta emettendo luce diffusa. Il problema nasce quando si tenta di ruotare la teiera: sembra che la sorgente di luce sta facendo la rotazione pure, non rimanendo nella stessa posizione ho definita (segue essenzialmente teaspot). Come si può vedere nel mio codice, modifico solo la posizione di illuminazione al momento dell'inizializzazione, quindi non è sottoposto a glRotatef (), dal momento che la sua chiamata dopo impostare la posizione della luce.

Nonostante la spesa numerose ore cercando di risolvere questo problema, ho veramente idea di cosa questo tipo di comportamento può essere attribuito a.

Incolla glEnable (GL_NORMALIZE); nell'inizializzazione non risolve il problema né.

Credo l'output desiderato dovrebbe essere una teiera con un lato lucido destra (poiché la luce proviene da quella direzione), indipendentemente dall'angolo teiera viene ruotato.

Se si desidera verificare il mio codice, premere la barra spaziatrice per ruotare la teiera.

#include <math.h>
#include <stdlib.h>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#include <windows.h>     
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>     

void onInitialization( ) { //creating the light source
 glEnable(GL_LIGHTING);
 glEnable(GL_DEPTH_TEST); 

 GLfloat diffuse[]={0.8, 0.8, 0.8, 1.0};
 GLfloat pos[]={0.5, 0.0, 0.8, 0.0};

 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
 glLightfv(GL_LIGHT0, GL_POSITION, pos);

 glEnable(GL_LIGHT0);

 glRotatef(-90, 1, 0, 0); //we want to see the top of the teapot
}

void onDisplay( ) {
    glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 //rotating on every frame (for testing purposes only)
 glRotatef(5, 0,1,0);
 glutSolidTeapot(0.4);

    glFinish();
    glutSwapBuffers();
}


void onKeyboard(unsigned char key, int x, int y) {
 if (key==32){ //do rotation upon hitting the Space key
  glutPostRedisplay();
 }
}

int main(int argc, char **argv) {
    glutInit(&argc, argv); 
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(100, 100);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("Teapot");

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    onInitialization();

    glutDisplayFunc(onDisplay);
    glutKeyboardFunc(onKeyboard);

    glutMainLoop();

    return 0;
}
È stato utile?

Soluzione

Credo che cambia

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

a

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

è un buon punto di partenza.

Altri suggerimenti

  

Credo anche che l'applicazione "distrugge" la modelview   matrice; non è mai ri-calcolata da zero. Dovresti   iniziare ogni telaio con una LoadIdentity (), allora emettere il   lightsource, quindi ruotare come desiderato e infine emettere   la geometria.

Questo non funziona, questo non funziona, questo non funziona, lalalalalalalala, e la FAQ è palesemente sbagliato , puro e semplice.

che emette la luce subito dopo glLoadIdentity () al fine di ottenere una luce fotocamera-bound lavorerà nei casi più semplici quando si traducono solo, o ruotare solo il modello attorno all'origine. Ma quando si inizia a fare le cose non banali, non-ciao-mondo come rotazione di un oggetto attorno a un punto diverso da quello di origine (tradurre (-v), ruotare (angolo), tradurre (v)) e poi si spostano in modo che il centro di rotazione viene portato davanti alla macchina fotografica, poi l ' "identità di carico, posto luce" tecnica inizia non aver spettacolare e in modi che rendono molto difficile dedurre ciò che è ancora in corso.

No, non so la soluzione.

Prova a impostare manualmente i valori normali per ogni vertice.

Ho incontrato lo stesso problema e ho la soluzione. Il problema è stato che ho impostato la posizione della luce solo in OnLoad parte del programma ... penso che sia il migliore per pubblicare un certo codice. Io lavoro in C # utilizzando OpenTK perche 'sono a conoscenza non potrò mai entrare aziendale grafica. :)

Il risultato è una teiera o qualche altro oggetto che ruota con la luce che ha posizione fissa. Posso spostare la posizione degli occhi ( LookAt metodo) e la sorgente luminosa rimane ancora. E 'proprio come nel mondo reale: L'oggetto può girare, ma il sole non lo farà. :) Inoltre, siamo in grado di andare in giro l'oggetto, ma il sole ancora rimane indifferente e rimane ancora. Questo codice farà quel trucco.

protected override void OnRenderFrame(FrameEventArgs e)
 {
        base.OnRenderFrame(e);

        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        System.Threading.Thread.Sleep(10); //useful thing to lower CPU usage

        //I can set the eye position at runtime, it's not necessary to have this
        modelview = Matrix4.LookAt(this.eye, Vector3.Zero, Vector3.UnitY);

        GL.MatrixMode(MatrixMode.Modelview);                       
        GL.LoadMatrix(ref modelview);           

        //**this is the key - you have to set the light position every time**
        GL.Light(LightName.Light0, LightParameter.Position, new float[4] { 1000, 1000, 0, 0 });


        // We don't want the walls to rotate so we push the current matrix
        GL.PushMatrix();

         GL.Rotate(move, Vector3.UnitY);
         move += 0.5f;

         GL.Color3(1.0f, 1.0f, 1.0f);

           GL.Begin(BeginMode.Triangles);
           //the object that will rotate             
           GL.End();
        GL.PopMatrix();              


        GL.Begin(BeginMode.Quads);
        //some quads (walls) in the background that will stay still
        GL.End();                                                

        SwapBuffers();
    }

Ho preso questo dal mio programma e cancellato un sacco di roba che è qui rilevante, forse sembra un po 'strano. Spero che aiuta.

Il frequenti stati :

  

La posizione di una luce si trasforma grazie   la matrice modelview corrente al   momento la posizione è specificato con un   chiamare per GLLight * ().

In altre parole, le luci non sono posizionati in una sorta di magia statica "Sistema di Coordinate"; stanno moltiplicato per la matrice modelview proprio come qualsiasi geometria sarebbe. Questo ha senso; spesso si desidera avere le luci bloccate alla geometria.

Credo anche che l'applicazione "distrugge" la matrice modelview; non è mai ri-calcolata da zero. Si dovrebbe iniziare ogni frame con un LoadIdentity (), allora emettere la sorgente di luce, quindi ruotare come desiderato, e infine emettere la geometria.

A mio parere ciò che si dovrebbe fare è non solo di chiamare glLoadIdentity () all'inizio della vostra routine di rendering, ma a spingere e pop la matrice modelview.

per una scena con una fonte di illuminazione fissata globalmente e due oggetti che sono indepently posizionati e ruotati questo codice pseudo farà il trucco:

glLoadIdentity();

// first object
glPushMatrix();
glTranslate(...);
glRotate(...)
glPopMatrix();

// second object
glPushMatrix();
glTranslate(...);
glRotate(...);
glPopMatrix();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top