OpenGL透视扭曲场景远远超过预期沿y轴

时间:2016-10-10 03:48:50

标签: java opengl 3d jogl

嘿,我开始使用JOGL了,除了使用FloatBuffer矩阵,我的创作沿着y轴扭曲之外,一切正常。

Picture of y axis distortion

它应该看起来像下面的图片,但目前我不能这样做,同时仍然允许移动。

Picture of what it should look like

几年前我看到有人有这个问题(但关于z轴),但我无法使用他们给出的修正来解决我的问题。这是链接:Link

我认为它与gluPerspective或glFrustrum有关,但我无法弄清楚是什么。以下是绘制3D形状的重要方法:

public static void main(String[]args)
{       
    Frame frame = new Frame("JOGL Events");
    Toolkit t=Toolkit.getDefaultToolkit();
    Image img=new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
    Cursor pointer=t.createCustomCursor(img, new Point(0,0), "none");
    Driver m=new Driver();
    GLCanvas canvas = new GLCanvas();
    canvas.addGLEventListener(m);
    canvas.addKeyListener(m);
    canvas.addMouseListener(m);
    canvas.setFocusable(true);
    canvas.requestFocus();

    frame.add(canvas);
    frame.setUndecorated(true);
    frame.setSize(1024, 768);
    frame.setLocationRelativeTo(null);
    frame.setCursor(pointer);
    frame.setVisible(true);
    GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
    if(fullscreen){
        ge.getDefaultScreenDevice().setFullScreenWindow(frame);
    }
    final Animator animator = new Animator(canvas);
    animator.setRunAsFastAsPossible(true);
    animator.start();
    Rectangle r=frame.getBounds();
    center=new Point(r.x+r.width/2, r.y+r.height/2);
}

public void init(GLAutoDrawable drawable) {
    final GL2 gl = drawable.getGL().getGL2();
    gl.glShadeModel( GL2.GL_SMOOTH );
    gl.glClearColor( 0f, 0f, 0f, 0f );
    gl.glClearDepth( 1.0f );
    gl.glEnable( GL2.GL_DEPTH_TEST );
    gl.glDepthFunc( GL2.GL_LEQUAL );
    gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST );
    gh=new GameHandler(gl);
    gh.setMouseCenter(center);
}

public void dispose(GLAutoDrawable drawable) {

}

public void display(GLAutoDrawable drawable) {
    final GL2 gl = drawable.getGL().getGL2(); 
    gl.glShadeModel( GL2.GL_SMOOTH );
    gl.glClearColor( 0f, 0f, 0f, 0f );
    gl.glClearDepth( 1.0f );
    gl.glEnable( GL2.GL_DEPTH_TEST );
    gl.glDepthFunc( GL2.GL_LEQUAL );
    gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
    //gl.glColor3f(1f,0f,0f);
    gl.glClear (GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );      
    // Clear The Screen And The Depth Buffer 
    gl.glLoadIdentity();

    //gl.glTranslatef( -0.0f, 0.0f, -6f );  // Move the triangle  
    //gl.glRotatef( rotZ+0f, rotX+.5f, rotY+1f, rotX+1.0f ); 


    //gl.glFrustumf(left, right, bottom, top, zNear, zFar);

    gh.run();
    gl.glFlush();
}

public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {

    final GL2 gl = drawable.getGL().getGL2(); 
    if(height <=0) 
    height =1; 
    final float h = ( float ) width / ( float ) height; 
    gl.glViewport( 0, 0, width, height ); 
    gl.glMatrixMode( GL2.GL_PROJECTION ); 
    gl.glLoadIdentity(); 
    glu.gluPerspective( 45.0f, h, 0.01f, 50.0f); 
    glu.gluLookAt(0, 0, 1, 0, 0, 0, 0, 1, 0);
    gl.glMatrixMode( GL2.GL_MODELVIEW ); 
    gl.glLoadIdentity();
        gl.glLoadIdentity();
    center=new Point(x+width/2, y+height/2);
    gh.setMouseCenter(center);
}

从那里,它调用GameHandler类,它使用以下代码来确定要移动的方向,然后调用cube类来绘制背景,然后调用player类来绘制矩阵:

//in GameHandler
public void checkEvents()
{
    long now=System.nanoTime();
    float period=(float)((now-lastTime)*0.000005);
    lastTime=now;

    dx=MouseInfo.getPointerInfo().getLocation().x;
    dy=MouseInfo.getPointerInfo().getLocation().y;
    float head=(mouseCenter.x-dx)/3;
    float pit=(mouseCenter.y-dy)/3;

    if(head!=0) 
        player.setHeading(head*headSens);
    if(pit!=0) 
        player.setPitch(pit*pitchSens);
    if(ford) 
        player.setFord((float)period);
    if(back) 
        player.setBack((float)period);
    if(strafel) 
        player.setStrafel((float)period);
    if(strafer) 
        player.setStrafer((float)period);
    if(jump)
        player.jump("up");
    if(down)
        player.jump("down");
    player.set();

}

public void run()
{
    checkEvents();
    if(robot!=null)
        robot.mouseMove(mouseCenter.x, mouseCenter.y);
    player.draw(gl);
    for(Cube c:getCubes())
        c.draw(gl);

}
//in cube
public void draw(GL2 gl)
{
    gl.glBegin(GL2.GL_QUADS);
     gl.glColor3f(1f,0f,0f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);

     gl.glColor3f(0f,1f,0f);
     gl.glVertex3f(x+-.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);

     gl.glColor3f(1f,0f,0f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+-.5f,y+.5f, z+.5f);


     gl.glColor3f(0f,0f,1f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);

     gl.glColor3f(1f,0f,1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);

     gl.glColor3f(1f,.5f,1f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);

     gl.glEnd();



     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+-.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+-.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+-.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+-.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+-.5f, y+.5f, z+.5f);
     gl.glEnd();

     gl.glBegin(GL2.GL_LINES);
     gl.glColor3f(1f, 1f, 1f);
     gl.glVertex3f(x+.5f, y+.5f, z+-.5f);
     gl.glVertex3f(x+.5f, y+.5f, z+.5f);
     gl.glEnd();
}
//player class
public class Player {

private static final float _90=(float)Math.toRadians(90);
private static final float _maxPitch=(float)Math.toRadians(90);
private float heading=0.0f;
private float pitch=0.0f;
private float cosa, cosb, cosz, sina, sinb, sinz;
private float cosc=1.0f;
private float sinc=0.0f;
private float x,y,z;
private float[] mat={ 1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        0,0,0,1};
private FloatBuffer matrix;

public Player()
{
    matrix=Buffers.newDirectFloatBuffer(mat.length);
    matrix.put(mat);
    x=y=z=0;
}

public void setHeading(float amount){
    heading-=amount;
    cosb=(float)Math.toRadians(Math.cos(heading));
    sinb=(float)Math.toRadians(Math.sin(heading));
    cosz=(float)Math.toRadians(Math.cos(heading+_90));
    sinz=(float)Math.toRadians(Math.sin(heading+_90));
}

public void setPitch(float amount){
    pitch-=amount;
    if(pitch>_maxPitch)pitch=_maxPitch;
    if(pitch<-_maxPitch)pitch=-_maxPitch;
    cosa=(float)Math.cos(pitch);
    sina=(float)Math.sin(pitch);
}

public void setFord(float amount){
    x+=cosz*cosa*amount*2;
    z+=sinz*cosa*amount*2;
    y+=Math.toRadians(sina)*2;

}

public void setBack(float amount){
    x-=cosz*cosa*amount*2;
    z-=sinz*cosa*amount*2;
    y-=Math.toRadians(sina)*2;
}

public void setStrafel(float amount){
    x+=cosb*amount*2;
    z+=sinb*amount*2;
}

public void setStrafer(float amount){
    x-=cosb*amount*2;
    z-=sinb*amount*2;
}

public void set(){
    matrix.put(0, cosc*cosb-sinc*sina*sinb);
    matrix.put(1, sinc*cosb+cosc*sina*sinb);
    matrix.put(2, -cosa*sinb);
    matrix.put(4, -sinc*cosa);
    matrix.put(5, cosc*cosa);
    matrix.put(6, sina);
    matrix.put(8, cosc*sinb+sinc*sina*cosb);
    matrix.put(9, sinc*sinb-cosc*sina*cosb);
    matrix.put(10, cosa*cosb);
    matrix.put(12, matrix.get(0)*x+matrix.get(4)*y+matrix.get(8)*z);
    matrix.put(13, matrix.get(1)*x+matrix.get(5)*y+matrix.get(9)*z);
    matrix.put(14, matrix.get(2)*x+matrix.get(6)*y+matrix.get(10)*z);
}

public void jump(String dir)
{
    if(dir.equals("up"))
        y-=.03;
    else if(dir.equals("down"))
        y+=.03;
}

public void draw(GL2 gl){
    gl.glLoadIdentity();
    gl.glBegin(gl.GL_QUADS);
    gl.glColor3f(5.0f, 0.0f, 3.0f);
    gl.glVertex3f(1.0f, 1.0f, 0.0f);
    gl.glVertex3f(2.0f, 1.0f, 0.0f);
    gl.glVertex3f(2.0f, 1.0f, -5.0f);
    gl.glVertex3f(1.0f, 1.0f, -5.0f);
    gl.glEnd();
    matrix.rewind();
    gl.glLoadMatrixf(matrix);
}

}

为了尽可能清楚,我的问题是我应该添加/删除什么才能避免yAxis出现失真。任何帮助将不胜感激。

感谢您的时间

1 个答案:

答案 0 :(得分:1)

您对不是角度的值调用toRadians

cosb=(float)Math.toRadians(Math.cos(heading));
sinb=(float)Math.toRadians(Math.sin(heading));
cosz=(float)Math.toRadians(Math.cos(heading+_90));
sinz=(float)Math.toRadians(Math.sin(heading+_90));

那是胡说八道。因为你有时只这样做,所以可能会导致失真。