当代理移动时,旋转形状与相机一起移动

时间:2013-05-17 18:37:11

标签: java opengl graphics 3d jogl

我创建了一个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();
    }
}

以下是移动时代理的一些图片: enter image description here

enter image description here

可能解释此问题的直播视频http://www.youtube.com/watch?v=zCBqx69b_e4&feature=youtu.be

2 个答案:

答案 0 :(得分:3)

我建议您从显示功能中剥离生成显示列表的代码。将它放在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的目的是什么......?这个功能有什么作用?我想你的问题可能就在这里。

答案 1 :(得分:2)

我的猜测是你在世界坐标和相机坐标之间做了不正确的矩阵变换。所有glLoadIdentity都设置了你对身份矩阵的初始引用,如果你没有正确地进行转换,这可能是你的头脑。

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