gluLookAt在选择时出现问题

时间:2011-05-26 11:23:24

标签: c# opengl select

您好
这是我的功能,可以检测命中。

private int[] GetSelected(int x, int y)
{
    const int max = 512;
    var Hit_Buffer = new int[max];
    var viewport = new int[4];

    Gl.glSelectBuffer(max, Hit_Buffer);
    Gl.glRenderMode(Gl.GL_SELECT);

    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPushMatrix();
    Gl.glLoadIdentity();

    Glu.gluLookAt(Distance * Math.Cos(beta) * Math.Cos(alpha)
        , Distance * Math.Cos(beta) * Math.Sin(alpha)
        , Distance * Math.Sin(beta)
        , 0, 0, 0
        , -Math.Sin(beta) * Math.Cos(alpha)
        , -Math.Sin(beta) * Math.Sin(alpha)
        , Math.Cos(beta));

    Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
    Glu.gluPickMatrix(x, viewport[3] - y, 1, 1, viewport);

    Glu.gluPerspective(fovY, ogl1.Width / (double)(ogl1.Height != 0 ? ogl1.Height : 1), 0.1, 100.0);
    Gl.glMatrixMode(Gl.GL_MODELVIEW);

    Gl.glInitNames();
    // render scene: a TRIANGLE
    Gl.glPushName(1);
    Gl.glBegin(Gl.GL_TRIANGLES);
    Gl.glVertex3d(0, 0, 0);
    Gl.glVertex3d(0, 1, 0);
    Gl.glVertex3d(1, 0, 0);
    Gl.glEnd();
    Gl.glPopName();
    //

    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPopMatrix();
    Gl.glMatrixMode(Gl.GL_MODELVIEW);
    Gl.glFlush();

    var hits = Gl.glRenderMode(Gl.GL_RENDER);
    Array.Resize(ref Hit_Buffer, hits);

    return Hit_Buffer;
}

我在xy平面上绘制一个三角形 在gluLookAt中,beta是来自xy平面的摄像机角度,alpha是摄像机角度约为z 但是,如果beta很小(-15 <β<15度),它就会起作用! 这有什么不对?

3 个答案:

答案 0 :(得分:0)

在OpenGL中,Y已启动

对于前3个参数,我宁愿说:

      Distance * Math.Cos(beta) * Math.Cos(alpha)
    , Distance * Math.Sin(beta)
    , Distance * Math.Cos(beta) * Math.Sin(alpha)

对于最后的3个,首先尝试使用(0,1,0)。

答案 1 :(得分:0)

您是否故意在gluPickMatrix之前调用gluLookAt?您想将翻译应用于您的选择矩阵吗?如果没有,你可以在glLoadIdentity之后立即移动gluPickMatrix并尝试解决你的问题吗?

答案 2 :(得分:0)

再次问好 我终于找到了自己的答案! (通过谷歌搜索)
这是我更正后的代码

private int[] GetSelected(int x, int y, bool debug)
{
    var hits = 0; // number of hits

    // Define select buffer
    const int max = 512;
    var Hit_buffer = new int[max];
    Gl.glSelectBuffer(max, Hit_buffer);

    var viewport = new int[4];
    Gl.glViewport(0, 0, Width, (Height != 0 ? Height : 1));
    Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);

    if (debug)// show real scene in debug mode
        GlDraw();

    if(!debug)
        Gl.glRenderMode(Gl.GL_SELECT);

    int s = debug ? 60 : 3; // test region size

    Gl.glLoadIdentity();
    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPushMatrix();
    Gl.glLoadIdentity();

    Glu.gluPickMatrix(x, viewport[3] - y, s, s, viewport);

    Glu.gluPerspective(fovY, Width / (double)(Height != 0 ? Height : 1), 0.1, 1000.0);
    Gl.glMatrixMode(Gl.GL_MODELVIEW);

    if (debug) // test region will be shown in left-bottom corner
        Gl.glViewport(0, 0, s, s);

    #region camera
    Gl.glTranslated(Dx, Dy, 0);
    var Distance = this.Distance;// *ogl1.Height / 60.0;
    var CenterView = this.CenterView.Duplicate();
    Glu.gluLookAt(Distance * Math.Cos(beta) * Math.Cos(alpha) + CenterView.x
        , Distance * Math.Cos(beta) * Math.Sin(alpha) + CenterView.y
        , Distance * Math.Sin(beta) + CenterView.z
        , CenterView.x
        , CenterView.y
        , CenterView.z
        , -Math.Sin(beta) * Math.Cos(alpha)
        , -Math.Sin(beta) * Math.Sin(alpha)
        , Math.Cos(beta));
    #endregion

    if (debug) // draw a bacground in left-bottom corner
    {
        ChangeColor(Color.Blue);
        Glu.gluSphere(Glu.gluNewQuadric(), 50, 50, 50);
        Gl.glBegin(Gl.GL_QUADS);
        Gl.glVertex3d(-10, -10, -10);
        Gl.glVertex3d(-10, 10, -10);
        Gl.glVertex3d(10, 10, -10);
        Gl.glVertex3d(10, -10, -10);
        Gl.glEnd();
    }

    Gl.glInitNames();

    // render scene
    foreach (var b in Bodies)
    {
        Gl.glPushName(b.id);
        var bb = b.Duplicate();
        bb.color = Color.Red;
        bb.Draw();
        Gl.glPopName();
    }
    //

    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPopMatrix();
    Gl.glMatrixMode(Gl.GL_MODELVIEW);
    Gl.glFlush();

    if (!debug) 
        hits = Gl.glRenderMode(Gl.GL_RENDER);

    // process hits
    int[] Res = { };
    int startRecord = 0;
    for (int i = 0; i < hits; i++)
    {
        for (int j = 0; j < Hit_buffer[startRecord]; j++)
        {
            Array.Resize(ref Res, Res.Length + 1);
            Res[Res.Length - 1] = Hit_buffer[startRecord + 3 + j];
        }
        startRecord += 3 + Hit_buffer[startRecord];
    }

    return Res;
}

如果设置debug参数= true,它将在左下角绘制选择区域 代码可能很无聊,所以我将在这里编写主要部分

    // Define select buffer
    const int max = 512;
    var Hit_buffer = new int[max];
    Gl.glSelectBuffer(max, Hit_buffer);

    var viewport = new int[4];
    Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);

    Gl.glRenderMode(Gl.GL_SELECT);

    Gl.glLoadIdentity();
    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPushMatrix();
    Gl.glLoadIdentity();

    Glu.gluPickMatrix(x, viewport[3] - y, 3, 3, viewport);

    Glu.gluPerspective(fovY, Width / (double)(Height != 0 ? Height : 1), 0.1, 1000.0);
    Gl.glMatrixMode(Gl.GL_MODELVIEW);

    Gl.glInitNames();

    // set camera (gluLookAt, ...) & draw scene

    Gl.glMatrixMode(Gl.GL_PROJECTION);
    Gl.glPopMatrix();
    Gl.glMatrixMode(Gl.GL_MODELVIEW);
    Gl.glFlush();

    var hits = Gl.glRenderMode(Gl.GL_RENDER);

    // process hits