【问题标题】:Rotating shape moves together with the camera when agent moves当代理移动时,旋转形状与相机一起移动
【发布时间】:2013-05-17 18:37:10
【问题描述】:

我创建了一个 3D 游戏,其中代理可以在多个方向(北、南...)移动。

它工作正常,但是当我在代码中添加另一个形状 - 金字塔 - 时,当我 移动代理,金字塔与他一起移动,这意味着它与代理(也称为相机)的移动保持一致。

知道如何使形状静态吗?

启用gl2.glLoadIdentity(); 行会导致金字塔粘在相机上。禁用gl2.glLoadIdentity(); 会导致金字塔不出现。

代码:

类:Pyramid.java

import javax.media.opengl.GL2;


public class Pyramid {


    private int m_pyramid;


    public void createPyramid(GL2 gl2) 
    {
        m_pyramid = gl2.glGenLists(1);
        gl2.glNewList(m_pyramid, GL2.GL_COMPILE);

        //  set texture parameters
        gl2.glTexParameteri ( GL2.GL_TEXTURE_2D,GL2.GL_TEXTURE_WRAP_T,GL2.GL_LINEAR_MIPMAP_LINEAR);
        gl2.glTexParameteri( GL2.GL_TEXTURE_2D,GL2.GL_TEXTURE_WRAP_S,GL2.GL_LINEAR_MIPMAP_LINEAR);

        gl2.glBegin(GL2.GL_TRIANGLES); // of the pyramid

        // Font-face triangle
        gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
        gl2.glVertex3d(0.0f, 1.0f, 0.0f);
        gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
        gl2.glVertex3d(-1.0f, -1.0f, 1.0f);
        gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
        gl2.glVertex3d(1.0f, -1.0f, 1.0f);

        // Right-face triangle
        gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
        gl2.glVertex3d(0.0f, 1.0f, 0.0f);
        gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
        gl2.glVertex3d(1.0f, -1.0f, 1.0f);
        gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
        gl2.glVertex3d(1.0f, -1.0f, -1.0f);

        // Back-face triangle
        gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
        gl2.glVertex3d(0.0f, 1.0f, 0.0f);
        gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
        gl2.glVertex3d(1.0f, -1.0f, -1.0f);
        gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
        gl2.glVertex3d(-1.0f, -1.0f, -1.0f);

        // Left-face triangle
        gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
        gl2.glVertex3d(0.0f, 1.0f, 0.0f);
        gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
        gl2.glVertex3d(-1.0f, -1.0f, -1.0f);
        gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
        gl2.glVertex3d(-1.0f, -1.0f, 1.0f);

        gl2.glEnd(); // of the pyramid
        gl2.glEndList();

    }

}

WorldController.java

class WorldController extends GLCanvas implements GLEventListener, KeyListener 
{
    private Point3D m_agent , m_center , m_coordinate1 , m_coordinate2 , m_coordinate3;
    private GLU m_glu = new GLU();
    private Pyramid m_pyra = new Pyramid();

        public WorldController ()
    {
        this.addGLEventListener(this);

        //  initialize m_agent and axis
        this.m_agent = new Point3D(750,200,1200);
        this.m_coordinate1 = new Point3D(1,0,0);
        this.m_coordinate2 = new Point3D(0,1,0);
        this.m_coordinate3 = new Point3D(0,0,1);
        this.m_center = new Point3D(0,0,0);
    }

        @Override
    public void init (GLAutoDrawable gLDrawable) 
    {

        GL2 gl2 = gLDrawable.getGL().getGL2(); // get the OpenGL graphics context
        gl2.glEnable(GL2.GL_TEXTURE_2D);          // get GL Utilities
        gl2.glShadeModel(GL2.GL_SMOOTH);
        gl2.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        gl2.glClearDepth(1.0f);
        gl2.glEnable(GL2.GL_DEPTH_TEST);
        gl2.glDepthFunc(GL2.GL_LEQUAL);
        gl2.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
        gl2.glShadeModel(GL_SMOOTH); // blends colors nicely, and smoothes out lighting


        // bind the pyramid with the current GL2
        this.m_pyra.createPyramid(gl2);

        /**
         * Creating the listener 
         */
        ((Component) gLDrawable).addKeyListener(this);

    }


        @Override
    public void display(GLAutoDrawable gLDrawable)
    {
        final GL2 gl2 = gLDrawable.getGL().getGL2();
        gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl2.glLoadIdentity();

        //  set m_center and look at
        m_center.setPoint(m_agent.getX() - m_coordinate3.getX() , 
                   m_agent.getY() - m_coordinate3.getY() ,
                   m_agent.getZ() - m_coordinate3.getZ());

        m_glu.gluLookAt(m_agent.getX(),m_agent.getY(),m_agent.getZ(),
                      m_center.getX(),m_center.getY(),m_center.getZ(),
                      m_coordinate2.getX(),m_coordinate2.getY(),m_coordinate2.getZ());


        /**
         * pyramid 
         */

        gl2.glPushMatrix();
        // gl2.glLoadIdentity(); 
        gl2.glTranslatef(-2f, 0.0f, -10.0f); // translate left and into the screen
        gl2.glRotatef(anglePyramid, 0.1f, 1.0f, -0.1f); // rotate about the y-axis
        gl2.glCallList(5);
        gl2.glPopMatrix();   // <-- and here?
        anglePyramid += speedPyramid;

    }


    @Override
    public void reshape(GLAutoDrawable gLDrawable,int x,int y,int width,int height) 
    {

        GL2 gl2 = gLDrawable.getGL().getGL2(); // get the OpenGL 2 graphics context
        if(height <= 0) height = 1;            // prevent divide by zero

        float aspect = (float)width / (float)height;
        gl2.glMatrixMode(GL_PROJECTION);
        gl2.glLoadIdentity();
        m_glu.gluPerspective(50.0f, aspect, 1.0, 10000.0);
        gl2.glMatrixMode(GL_MODELVIEW);
        gl2.glLoadIdentity();
    }
}

以下是代理移动时的一些照片:

可以解释问题的现场视频http://www.youtube.com/watch?v=zCBqx69b_e4&feature=youtu.be

【问题讨论】:

  • 在代码中,您将相机定位在哪里?我只看到了绘制金字塔的代码。
  • @TomásBadan:请看修改后的代码

标签: java opengl graphics 3d jogl


【解决方案1】:

我建议你从 display 函数中剥离生成显示列表的代码。将它放在一个 init 函数或用于初始化对象的任何函数中。

其次,仅在此生成代码中放入对构造对象(金字塔)很重要的转换和定义。不要在其中放入任何与将其定位到世界系统相关的转换。记住,它只需要生成一次,当您的列表名称有效时,您只需一遍又一遍地调用它以将其显示到帧缓冲区中。

不要将 glLoadIdentity() 放在显示列表中,它们会重置您的模型视图矩阵,而且我敢肯定,这不是您想要的。要保留模型视图矩阵的内容,您可以使用矩阵堆栈子系统,通过调用 glPushMatrix 和 glPopMatrix 函数调用。

因此,关于您的代码,我建议进行以下修改:

@Override
public void init (GLAutoDrawable gLDrawable) 
{

    GL2 gl2 = gLDrawable.getGL().getGL2(); // get the OpenGL graphics context
    gl2.glEnable(GL2.GL_TEXTURE_2D);          // get GL Utilities
    gl2.glShadeModel(GL2.GL_SMOOTH);
    gl2.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    gl2.glClearDepth(1.0f);
    gl2.glEnable(GL2.GL_DEPTH_TEST);
    gl2.glDepthFunc(GL2.GL_LEQUAL);
    gl2.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
    gl2.glShadeModel(GL_SMOOTH); // blends colors nicely, and smoothes out lighting
    ((Component) gLDrawable).addKeyListener(this);

    // ADDED HERE, OR IN ANY POSITION THAT MAKE MORE SENSE
    int pyramid = gl2.glGenLists(1);
    gl2.glNewList(pyramid, GL2.GL_COMPILE);
    // gl2.glLoadIdentity();  // reset the model-view matrix  <-- TAKE THIS OFF
    gl2.glBegin(GL2.GL_TRIANGLES); // of the pyramid

    // Font-face triangle
    gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
    gl2.glVertex3d(0.0f, 1.0f, 0.0f);
    gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
    gl2.glVertex3d(-1.0f, -1.0f, 1.0f);
    gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
    gl2.glVertex3d(1.0f, -1.0f, 1.0f);

    // Right-face triangle
    gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
    gl2.glVertex3d(0.0f, 1.0f, 0.0f);
    gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
    gl2.glVertex3d(1.0f, -1.0f, 1.0f);
    gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
    gl2.glVertex3d(1.0f, -1.0f, -1.0f);

    // Back-face triangle
    gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
    gl2.glVertex3d(0.0f, 1.0f, 0.0f);
    gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
    gl2.glVertex3d(1.0f, -1.0f, -1.0f);
    gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
    gl2.glVertex3d(-1.0f, -1.0f, -1.0f);

    // Left-face triangle
    gl2.glTexCoord3f(1.0f, 0.0f, 0.0f);  // Red
    gl2.glVertex3d(0.0f, 1.0f, 0.0f);
    gl2.glTexCoord3f(0.0f, 0.0f, 1.0f);  // Blue
    gl2.glVertex3d(-1.0f, -1.0f, -1.0f);
    gl2.glTexCoord3f(0.0f, 1.0f, 0.0f);  // Green
    gl2.glVertex3d(-1.0f, -1.0f, 1.0f);


    gl2.glEnd(); // of the pyramid
    gl2.glEndList();

    // END HERE
}


@Override
public void display(GLAutoDrawable gLDrawable)
{
    final GL2 gl2 = gLDrawable.getGL().getGL2();
    gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
    gl2.glLoadIdentity();

    // agent and center settings
    m_center.setPoint(m_agent.getX() - m_coordinate3.getX() , 
               m_agent.getY() - m_coordinate3.getY() ,
               m_agent.getZ() - m_coordinate3.getZ());

    m_glu.gluLookAt(m_agent.getX(),m_agent.getY(),m_agent.getZ(),
                  m_center.getX(),m_center.getY(),m_center.getZ(),
                  m_coordinate2.getX(),m_coordinate2.getY(),m_coordinate2.getZ());


     /**
     * pyramid 
     */

    glPushMatrix();  // <-- did you note this function here?

    gl2.glTranslatef(-2f, 0.0f, -10.0f); // translate left and into the screen
    gl2.glRotatef(anglePyramid, 0.1f, 1.0f, -0.1f); // rotate about the y-axis

    gl2.glCallList(pyramid);
    glPopMatrix();   // <-- and here?
    anglePyramid += speedPyramid;

一旦你没有展示你是如何控制相机的,这不会完全解决你的问题。但是尝试按照代码中的指示放置一个 glPushMatrix 和 glPopMatrix

附言。再次查看您的代码后,我注意到了这段代码:

 // agent and center settings
    m_center.setPoint(m_agent.getX() - m_coordinate3.getX() , 
               m_agent.getY() - m_coordinate3.getY() ,
               m_agent.getZ() - m_coordinate3.getZ());

    m_glu.gluLookAt(m_agent.getX(),m_agent.getY(),m_agent.getZ(),
                  m_center.getX(),m_center.getY(),m_center.getZ(),
                  m_coordinate2.getX(),m_coordinate2.getY(),m_coordinate2.getZ());

m_center.setPoint...的目的是什么?这个函数有什么作用?我想你的问题可能在这里。

【讨论】:

  • 按照您的建议更改代码后,金字塔不会显示给用户。请参阅上面的新代码。如果我启用单位矩阵,那么它会回到最初的问题 - 相机和形状一起。
  • 顺便说一句,您上面提到的m_centerm_glu.gluLookAt(...) 是用于设置代理的视口,因此他可以从屏幕中心开始移动,而不是从屏幕的某个随机侧开始移动长方形的房间。
  • 好的,你的问题是 gluLookAt。它指向一个没有物体的空间。如果你想测试它,我建议将它修改为gluLookAt(m_agent.getX(),m_agent.getY(),m_agent.getZ(), -2, 0, -10, m_coordinate2.getX(),m_coordinate2.getY(),m_coordinate2.getZ());。如您所见,第二个坐标指向对象。
  • 请看上面的图片:第一个是你要求的更改,第二个是“常规”行。在这两种情况下,金字塔都会和我一起旅行,前提是我允许gl2.glLoadIdentity();
  • 启用 glLoadIdentity 时,您将删除 glLookAt 设置的效果。如果您没有看到此对象,可能是因为您正在绘制视图之外的点。从您的代码中,代理出生在点 (500, 100, 1000) 并正在寻找点 (500, 100, 999),而您的金字塔位于位置 (-2, 0, -10)。你甚至看不到它。把你的代理放在 (0, 0, 10) 你会看到它。
【解决方案2】:

我的猜测是您在世界坐标和相机坐标之间进行了不正确的矩阵转换。 glLoadIdentity 所做的只是将您的初始引用设置为单位矩阵,如果您没有正确进行转换,这可能会在您的头顶上。

看到这个: http://www.matrix44.net/cms/notes/opengl-3d-graphics/coordinate-systems-in-opengl

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多