在Opengl中使用theta和phi角度进行旋转

时间:2016-12-26 02:24:53

标签: java opengl matrix opengl-es rotation

我正在尝试使用OpenGL移动和旋转球体。为此,我保存我的矩阵状态,我加载单位矩阵,然后我转换到我想要的点,最后,我旋转并推送状态,如上面的代码所示。因为这些过程是从结束到开始完成的,所以旋转是从(0,0,0)开始,只有在此之后,它才会移动到所需的点。翻译很好,但我有旋转问题。为此,我想用2个角度来描述旋转:theta和phi(只需按照你在这里看到的物理惯例https://en.wikipedia.org/wiki/Spherical_coordinate_system)。如果我首先在phi中旋转然后在theta中,则结果与以相反顺序进行的操作不同。我知道这是因为矩阵产品。此外,我已经读过,使用万向节锁定的欧拉角存在问题,我应该使用四元数但是,我还没有这么清楚。我正在查看我的数据作为正视图,由于上述原因,我不确定我所做的是否正确,或者只是我用我试过的角度运气。你会怎么做?

    gl.glPushMatrix();
    gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
    gl.glTranslatef(x, y, z);
    gl.glRotatef(theta, 0,1,0); 
    gl.glRotatef(phi, 0,0,1);

    GLUquadric earth = glu.gluNewQuadric();
    glu.gluQuadricTexture(earth, true);
    glu.gluQuadricDrawStyle(earth, GLU.GLU_FILL);
    glu.gluQuadricNormals(earth, GLU.GLU_FLAT);
    glu.gluQuadricOrientation(earth, GLU.GLU_OUTSIDE);          
    glu.gluSphere(earth, radius, slices, stacks);        
    glu.gluDeleteQuadric(earth);
    gl.glPopMatrix();

2 个答案:

答案 0 :(得分:1)

我怎么理解,旋转后gl.glRotatef(theta,0,1,0)vector(0,0,1)也改变了。对于您的代码,gl.glRotatef(phi,0,0,1)在对象本地坐标中工作。我想你想在全球范围内做这件事。我想如果你将0,1,0周围的矢量(0,0,1)旋转到θ度,并使用新矢量进行第二次旋转。

这是伪代码示例:

gl.glRotatef(theta, 0,1,0); 
glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), theta, glm::vec3(0.0, 1.0, 0.0));
glm::mat4 rotateVector = rotationMatrix * glm::vec4(0.0, 0.0, 1.0));
gl.glRotatef(phi, rotateVector.x, rotateVector.y, rotateVector.z);

我认为这段代码无法编译。我尝试用glm函数来表示我的意思。

答案 1 :(得分:0)

最后我改变主意,而不是使用ortho,我试图通过使用透视来理解问题。起初,我注意到我的粒子是否旋转了一个额外的角度。但最后,我认为这是因为如何将纹理添加到粒子中。我尝试了几个像这里所说的那样的事情:https://stackoverflow.com/a/7725601/1200914但这是不可能的。在尝试了很多东西后,我尝试画出轴线,经过大量的测试后我发现我忘记了Math.sin和Math.cos是弧度的,而不是像OpenGl那样的度数。当我意识到这一点时,我注意到线条很完美。一切都发生在全球坐标上。简而言之:

    gl.glRotatef(theta, 0, 1, 0);
    gl.glRotatef(phi, 0, 0, 1);

没问题。我让我的代码让我理解这一点。请将路径更改为“ROUTE T​​O IMAGE”到png图像,该图像是分为4种不同颜色的正方形(如windows标志)。你可以用油漆来制作。

import java.awt.BorderLayout;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.GLUquadric;
import com.jogamp.opengl.awt.GLCanvas;

import javax.swing.JFrame;

import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;

/**
 * Test developed using:
 * 
 * A minimal JOGL demo.
 * 
 * @author <a href="mailto:kain@land-of-kain.de">Kai Ruhl</a>
 * @since 26 Feb 2009
 */
public class test3d extends GLCanvas implements GLEventListener {

    /** Serial version UID. */
    private static final long serialVersionUID = 1L;

    /** The GL unit (helper class). */
    private GLU glu;

    /** The frames per second setting. */
    private int fps = 24;

    /** The OpenGL animator. */
    private FPSAnimator animator;

    /** The earth texture. */
    private Texture earthTexture;

    private int see_ = 0;

    /**
     * A new mini starter.
     */
    public test3d(int see) {
        addGLEventListener(this);
        see_ = see;
    }

    /**
     * Sets up the screen.
     * 
     * @see javax.media.opengl.GLEventListener#init(javax.media.opengl.GLAutoDrawable)
     */
    public void init(GLAutoDrawable drawable) {
        final GL2 gl = (GL2) drawable.getGL();

        // Enable z- (depth) buffer for hidden surface removal. 
        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glDepthFunc(GL.GL_LEQUAL);

        // Enable smooth shading.
        gl.glShadeModel(GL2.GL_SMOOTH);

        // Define "clear" color.
        gl.glClearColor(0f, 0f, 0f, 0f);

        // We want a nice perspective.
        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);

        // Create GLU.
        glu = new GLU();
        GLProfile profile = GLProfile.get(GLProfile.GL2);
        // Load earth texture.
        try {
            FileInputStream stream = new FileInputStream(ROUTE TO IMAGE);
            TextureData data = TextureIO.newTextureData(profile, stream, false, "png");
            earthTexture = TextureIO.newTexture(data);
        }
        catch (IOException exc) {
            exc.printStackTrace();
            System.exit(1);
        }

        // Start animator.
        animator = new FPSAnimator(this, fps);
        animator.start();
    }

    /**
     * The only method that you should implement by yourself.
     * 
     * @see javax.media.opengl.GLEventListener#display(javax.media.opengl.GLAutoDrawable)
     */
    public void display(GLAutoDrawable drawable) {
        if (!animator.isAnimating()) {
            return;
        }
        final GL2 gl = (GL2) drawable.getGL();

        // Clear screen.
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // Set camera.
        setCamera(gl, glu, 30);

        // Prepare light parameters.
        float SHINE_ALL_DIRECTIONS = 1;
        float[] lightPos = {0, 0, 0, SHINE_ALL_DIRECTIONS};
        float[] lightColorAmbient = {1f, 1f, 1f, 1f};
        float[] lightColorSpecular = {1f, 1f, 1f, 1f};

        // Set light parameters.
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, lightPos, 0);
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_AMBIENT, lightColorAmbient, 0);
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPECULAR, lightColorSpecular, 0);

        // Enable lighting in GL.
        gl.glEnable(GL2.GL_LIGHT1);
        gl.glEnable(GL2.GL_LIGHTING);

        // Set material properties.
        float[] rgba = {1f, 0f, 0f};
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        gl.glBegin(gl.GL_LINES);        //RED == X
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(10, 0, 0);
        gl.glEnd();

        rgba[0] = 0f;
        rgba[1] = 1f;
        rgba[2] = 0f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        gl.glBegin(gl.GL_LINES);        //GREEN == Y
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 10, 0);
        gl.glEnd();


        rgba[0] = 0f;
        rgba[1] = 0f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);
        gl.glBegin(gl.GL_LINES);        //BLUE == Z
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 0, 10);
        gl.glEnd();     

        // Set material properties.
        float theta = 45f;
        float phi = 270f;
        /*
        ////////////////////////////////////////////////////LINES 1 ROT//////////////////////////////////////////////////////////
        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 1f;
        rgba[1] = 0f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //VIOLET == X'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(10, 0, 0);
        gl.glEnd();

        gl.glPopMatrix();


        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 1f;
        rgba[1] = 1f;
        rgba[2] = 0f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //YELLOW == Y'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 10, 0);
        gl.glEnd();

        gl.glPopMatrix();

        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 0f;
        rgba[1] = 1f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f); 

        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //CYAN == Z'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 0, 10);
        gl.glEnd();     

        gl.glPopMatrix();
        */

        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 1f;
        rgba[1] = 1f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f); 

        //gl.glRotatef(theta, (float) Math.sin(phi), (float) Math.cos(phi), 0);
        gl.glTranslatef(3, 0, 0);
        gl.glRotatef(theta, 0, 1, 0);
        gl.glRotatef(phi, 0, 0, 1);
        gl.glBegin(gl.GL_LINES);        //WHITE == NEW Y'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 0, 10.f);
        gl.glEnd();

        gl.glPopMatrix();


        ////////////////////////////////////////////////////LINES 2 ROT//////////////////////////////////////////////////////////
        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 1f;
        rgba[1] = 0f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        //gl.glRotatef(theta, (float) -Math.sin(phi), (float) Math.cos(phi),0); 
        //gl.glRotatef(theta, (float) Math.sin(phi*Math.PI/180), (float) Math.cos(phi*Math.PI/180),0);    
        gl.glRotatef(theta, 0, 1, 0);
        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //VIOLET == X'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(10, 0, 0);
        gl.glEnd();

        gl.glPopMatrix();


        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 1f;
        rgba[1] = 1f;
        rgba[2] = 0f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        //gl.glRotatef(theta, (float) -Math.sin(phi), (float) Math.cos(phi),0); 
        //gl.glRotatef(theta, (float) Math.sin(phi*Math.PI/180), (float) Math.cos(phi*Math.PI/180),0);    
        gl.glRotatef(theta, 0, 1, 0);
        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //YELLOW == Y'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 10, 0);
        gl.glEnd();

        gl.glPopMatrix();

        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        rgba[0] = 0f;
        rgba[1] = 1f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f); 

        //gl.glRotatef(theta, (float) -Math.sin(phi), (float) Math.cos(phi),0); 
        //gl.glRotatef(theta, (float) Math.sin(phi*Math.PI/180), (float) Math.cos(phi*Math.PI/180),0); 
        gl.glRotatef(theta, 0, 1, 0);
        gl.glRotatef(phi, 0, 0, 1);

        gl.glBegin(gl.GL_LINES);        //CYAN == Z'
            gl.glVertex3f(0, 0, 0);
            gl.glVertex3f(0, 0, 10);
        gl.glEnd();     

        gl.glPopMatrix();

        //////////////////////////////////////////SPHERES////////////////////////////////////////////

        // Apply texture.

        rgba[0] = 1f;
        rgba[1] = 1f;
        rgba[2] = 1f;
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 1f);

        earthTexture.enable(gl);
        earthTexture.bind(gl);

        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)

        GLUquadric earth = glu.gluNewQuadric();
        glu.gluQuadricTexture(earth, true);
        glu.gluQuadricDrawStyle(earth, GLU.GLU_FILL);
        glu.gluQuadricNormals(earth, GLU.GLU_FLAT);
        glu.gluQuadricOrientation(earth, GLU.GLU_OUTSIDE);          
        glu.gluSphere(earth, 0.5, 64, 64);        
        glu.gluDeleteQuadric(earth);
        gl.glPopMatrix();

        earthTexture.disable(gl);

        earthTexture.enable(gl);
        earthTexture.bind(gl);



        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        gl.glTranslatef(1.5f, 0, 0);    
        gl.glRotatef(phi, 0,0,1);

        GLUquadric earth1 = glu.gluNewQuadric();
        glu.gluQuadricTexture(earth1, true);
        glu.gluQuadricDrawStyle(earth1, GLU.GLU_FILL);
        glu.gluQuadricNormals(earth1, GLU.GLU_FLAT);
        glu.gluQuadricOrientation(earth1, GLU.GLU_OUTSIDE);         
        glu.gluSphere(earth1, 0.5, 64, 64);        
        glu.gluDeleteQuadric(earth1);
        gl.glPopMatrix();

        earthTexture.disable(gl);

        earthTexture.enable(gl);
        earthTexture.bind(gl);

        gl.glPushMatrix();
        gl.glLoadIdentity();            //I reset the matrix. Now the translation and rotation is from the origin (0,0,0)
        gl.glTranslatef(3.f, 0, 0);         
        gl.glRotatef(theta, 0, 1,0);    
        gl.glRotatef(phi, 0,0,1);

        GLUquadric earth2 = glu.gluNewQuadric();
        glu.gluQuadricTexture(earth2, true);
        glu.gluQuadricDrawStyle(earth2, GLU.GLU_FILL);
        glu.gluQuadricNormals(earth2, GLU.GLU_FLAT);
        glu.gluQuadricOrientation(earth2, GLU.GLU_OUTSIDE);         
        glu.gluSphere(earth2, 0.5, 64, 64);        
        glu.gluDeleteQuadric(earth2);
        gl.glPopMatrix();

        earthTexture.disable(gl);
    }

    /**
     * Resizes the screen.
     * 
     * @see javax.media.opengl.GLEventListener#reshape(javax.media.opengl.GLAutoDrawable,
     *      int, int, int, int)
     */
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        final GL gl = drawable.getGL();
        gl.glViewport(0, 0, width, height);
    }

    /**
     * Changing devices is not supported.
     * 
     * @see javax.media.opengl.GLEventListener#displayChanged(javax.media.opengl.GLAutoDrawable,
     *      boolean, boolean)
     */
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
        throw new UnsupportedOperationException("Changing display is not supported.");
    }

    /**
     * @param gl The GL context.
     * @param glu The GL unit.
     * @param distance The distance from the screen.
     */
    private void setCamera(GL2 gl, GLU glu, float distance) {
        // Change to projection matrix.
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();

        // Perspective.
        float widthHeightRatio = (float) getWidth() / (float) getHeight();
        glu.gluPerspective(45, widthHeightRatio, 1, 10000);
        if (see_ == 0){
            glu.gluLookAt(10, 10, 10, 0, 0, 0, 0, 0, 1);        
        }else if (see_ == 1){
            glu.gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1);      
        }else if (see_ == 2){
            glu.gluLookAt(0, 10, 0, 0, 0, 0, 0, 0, 1);     
        }else if (see_ == 3){
            glu.gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);     
        }
        // Change back to model view matrix.
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    /**
     * Starts the JOGL mini demo.
     * 
     * @param args Command line args.
     */
    public final static void main(String[] args) {
        GLProfile profile = GLProfile.get(GLProfile.GL2);
        GLCapabilities capabilities = new GLCapabilities(profile);
        capabilities.setRedBits(8);
        capabilities.setBlueBits(8);
        capabilities.setGreenBits(8);
        capabilities.setAlphaBits(8);         

        int size = 640;

        test3d canvas = new test3d(0);        
        JFrame frame = new JFrame("Mini JOGL Demo (breed)");
        frame.getContentPane().add(canvas, BorderLayout.CENTER);
        frame.setBounds(0, 200, size, size);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        test3d canvas2 = new test3d(1);        
        JFrame frame2 = new JFrame("Mini JOGL Demo (breed)");
        frame2.getContentPane().add(canvas2, BorderLayout.CENTER);
        frame2.setBounds(0, 200, size, size);
        frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame2.setVisible(true);

        test3d canvas3 = new test3d(2);        
        JFrame frame3 = new JFrame("Mini JOGL Demo (breed)");
        frame3.getContentPane().add(canvas3, BorderLayout.CENTER);
        frame3.setBounds(0, 200, size, size);
        frame3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame3.setVisible(true);

        test3d canvas4 = new test3d(3);        
        JFrame frame4 = new JFrame("Mini JOGL Demo (breed)");
        frame4.getContentPane().add(canvas4, BorderLayout.CENTER);
        frame4.setBounds(0, 200, size, size);
        frame4.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame4.setVisible(true);

    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
        // TODO Auto-generated method stub

    }

}