2013-05-17 21 views
2

我創建了一個3D代理人,其中代理人可以在多個方向(北,南...)移動。當代理人移動時,旋轉形狀與相機一起移動

它可以正常工作,但是當我向代碼中添加另一個形狀 - 金字塔時,那麼當我移動代理時,金字塔隨着他移動,這意味着它隨代理(也就是相機)的移動而移動。

任何想法如何使形狀靜態?

啓用行gl2.glLoadIdentity();會導致金字塔與相機粘在一起。禁用gl2.glLoadIdentity();會導致金字塔不出現。

CODE:

類: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

LIVE VIDEO這或許可以解釋這個問題http://www.youtube.com/watch?v=zCBqx69b_e4&feature=youtu.be

+0

在代碼中,您是在定位相機嗎?我只看到了繪製金字塔的代碼。 – Amadeus

+0

@TomásBadan:請參閱編輯代碼 – ron

回答

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; 

這並不能徹底解決問題,一旦你沒有告訴你如何控制攝像機。但嘗試把代碼

Ps中所示的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 ...的用途是什麼?這個函數做了什麼?我想你的問題可能在這裏。

+0

按照您的建議更改代碼後,金字塔不會顯示給用戶。請參閱上面的新代碼。如果我啓用了身份矩陣,那麼它會回到最初的問題 - 相機和形狀一起。 – ron

+0

順便提一句,上面提到的'm_center'和'm_glu.gluLookAt(...)'是用於設置代理的視口,所以他很好地從屏幕中心移動,而不是從長方形的房間。 – ron

+0

好的,你的問題是與gluLookAt。它指向一個沒有物體的空間。如果你想測試它,我建議將它修改爲'gluLookAt(m_agent.getX(),m_agent.getY(),m_agent.getZ(),-2,0,-10,m_coordinate2.getX(),m_coordinate2.getY (),m_coordinate2.getZ());'。如您所見,第二個座標指向該對象。 – Amadeus