5

glutSolidTeapot(opengl.orgに従って自動的に生成された表面法線を持つ)と拡散光を放出する光源があります。ティーポットを回転させようとすると問題が発生します。光源も回転を行っているようで、定義したのと同じ位置に留まっていません(基本的にティースポットに従います)。私のコードでわかるように、初期化時に照明位置を変更するだけなので、照明位置を設定したに呼び出されるため、glRotatef()の対象にはなりません。

この問題を解決するために何時間も費やしたにもかかわらず、私はこの種の行動が何に起因するのか本当にわかりません。

glEnable(GL_NORMALIZE);を貼り付けます。初期化でも問題は解決しません。

ティーポットをどの角度で回転させても、右側が光沢のあるティーポット(光はその方向から来るため)が望ましい出力になると思います。

コードをテストする場合は、スペースキーを押してティーポットを回転させます。

#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;
}
4

6 に答える 6

2

また、アプリケーションはモデルビューマトリックスを「破壊」すると思います。ゼロから再計算されることはありません。各フレームをLoadIdentity()で開始し、光源を放出し、必要に応じて回転させ、最後にジオメトリを放出する必要があります。

これは機能しません、これは機能しません、これは機能しません、lalalalalalalala、そしてFAQは明らかに間違っており、明白で単純です。

glLoadIdentity()の直後にライトを放出して、カメラにバインドされたライトを取得することは、単純なケースでは、モデルを平行移動するか、原点を中心に回転させるだけで機能します。しかし、原点とは異なる点を中心にオブジェクトを回転させて(translate(-v)、rotate(angle)、translate(v))、オブジェクトを移動して回転中心がカメラの前に来ると「アイデンティティをロードし、光を当てる」テクニックが見事に失敗し始め、何が起こっているのかを推測するのが非常に困難になります。

いいえ、解決策はわかりません。

于 2009-12-06T13:09:12.877 に答える
2

変わると思います

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

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

始めるのに良い場所です。

于 2009-11-18T18:41:32.813 に答える
1

私は同じ問題に遭遇し、解決策を得ました。問題は、プログラムのOnLoad部分でのみライトの位置を設定することでした...コードを投稿するのが最善だと思います。私はOpenTKを使用してC#で作業しています。これは、グラフィックビジネスに参入することは決してないことを認識しているためです。:)

その結果、固定位置のライトで回転しているティーポットまたはその他のオブジェクトが作成されます。目の位置を動かすことができ(LookAtメソッド)、光源は静止したままです。それは本当の言葉のようです:オブジェクトは回転できますが、太陽は回転しません。:)また、オブジェクトの周りを歩くことはできますが、太陽はまだ印象に残っておらず、静止しています。このコードはそのトリックを行います。

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();
    }

私はこれを自分のプログラムから取り出し、ここでは重要ではないものをたくさん削除したので、少し奇妙に見えるかもしれません。お役に立てば幸いです。

于 2012-02-20T19:53:20.437 に答える
1

各頂点の通常の値を手動で設定してみてください。

于 2012-02-12T13:26:08.857 に答える
0

FAQには次のように記載されています。

ライトの位置は、glLight *()の呼び出しで位置が指定された時点で、現在のModelViewマトリックスによって変換されます。

言い換えれば、ライトはある種の魔法の静的な「世界座標系」に配置されていません。他のジオメトリと同じように、モデルビューマトリックスが乗算されます。意味あり; 多くの場合、ライトをジオメトリにロックする必要があります。

また、アプリケーションはモデルビューマトリックスを「破壊」すると思います。ゼロから再計算されることはありません。各フレームをLoadIdentity()で開始し、光源を放出し、必要に応じて回転させ、最後にジオメトリを放出する必要があります。

于 2009-11-18T18:18:18.877 に答える
0

私の意見では、レンダリングルーチンの開始時にglLoadIdentity()を呼び出すだけでなく、modelviewマトリックスをプッシュおよびポップする必要があります。

グローバルに固定された光源と、独立して配置および回転された2つのオブジェクトがあるシーンの場合、この擬似コードでうまくいきます。

glLoadIdentity();

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

// second object
glPushMatrix();
glTranslate(...);
glRotate(...);
glPopMatrix();
于 2009-12-08T15:29:39.307 に答える