2

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

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

知道如何使形状静态吗?

启用线gl2.glLoadIdentity();会导致金字塔与相机保持一致。禁用gl2.glLoadIdentity();会导致金字塔不出现。

代码:

类:金字塔.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();

    }

}

世界控制器.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

4

2 回答 2

3

我建议您从 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 ...的目的是什么?这个函数有什么作用?我想你的问题可能在这里。

于 2013-05-17T21:03:49.787 回答
2

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

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

于 2013-05-17T18:53:24.523 回答