Почему вращение по оси Z ведет себя иначе, чем вращение по осям X и Y?

Я возился с JOGL и пытаюсь понять это. Я сделал несколько кубов, но мне нужно, чтобы вращение по оси z работало так же, как вращение по осям x и y, и мне также нужна помощь, чтобы заставить его вращаться вокруг центра центрального куба, а не вокруг начала координат. Как я могу сделать обе эти вещи?

import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.*;
import com.jogamp.opengl.glu.*;
import com.jogamp.opengl.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
public class test4 implements KeyListener, GLEventListener{
    public static DisplayMode dm, dm_old;
    private GLU glu = new GLU();
    private float angle1 = 0f;
    private float angle2 = 0f;
    private float angle3 = 0f;
    private boolean right = false;
    private boolean left = false;
    private boolean up = false;
    private boolean down = false;
    private boolean zup = false;
    private boolean zdown = false;
    public void cube(GL2 gl, float x, float y, float z){
        gl.glEnable(GL2.GL_LIGHTING);  
        gl.glEnable(GL2.GL_LIGHT0);  
        gl.glEnable(GL2.GL_NORMALIZE); 
        float[] diffuseLight = {1f, 1f, 1f, 0f};
        float[] position = {10f, 10f, 10f, 1f};
        gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, diffuseLight, 0);
        gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, position, 0);
        gl.glEnable(GL2.GL_LIGHTING);  
        gl.glEnable(GL2.GL_LIGHT1);  
        gl.glEnable(GL2.GL_NORMALIZE);
        gl.glEnable(GL2.GL_COLOR_MATERIAL);
        float[] position1 = {-10f, -10f, -10f, 1f};
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, diffuseLight, 0);
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, position1, 0);
        gl.glLoadIdentity();
        gl.glTranslatef(x, y, z - 5.0f);
        gl.glRotatef(angle2, 1f, 0f, 0f);
        gl.glRotatef(angle1, 0f, 1f, 0f);
        gl.glRotatef(angle3, 0f, 0f, 1.0f);
        gl.glTranslatef(0f, 0f, -5f);
        gl.glBegin(GL2.GL_QUADS);
        gl.glColor3f(0f,0f,1f);
        gl.glVertex3f(0.5f,0.5f,0.5f);
        gl.glVertex3f(.5f,.5f,-0.5f);
        gl.glVertex3f(.5f,-.5f,-.5f);
        gl.glVertex3f(.5f,-.5f,.5f);
        gl.glColor3f(1f,1f,0f);
        gl.glVertex3f(.5f,.5f,.5f);
        gl.glVertex3f(-.5f,.5f,.5f);
        gl.glVertex3f(-.5f,-.5f,.5f);
        gl.glVertex3f(.5f,-.5f,.5f);
        gl.glColor3f(1f,0f,0f);
        gl.glVertex3f(.5f,.5f,.5f);
        gl.glVertex3f(-.5f,.5f,.5f);
        gl.glVertex3f(-.5f,.5f,-.5f);
        gl.glVertex3f(.5f,.5f,-.5f);
        gl.glColor3f(0f,1f,0f);
        gl.glVertex3f(-.5f,-.5f,-.5f);
        gl.glVertex3f(-.5f,-.5f,.5f);
        gl.glVertex3f(-.5f,.5f,.5f);
        gl.glVertex3f(-.5f,.5f,-.5f);
        gl.glColor3f(0f,1f,1f);
        gl.glVertex3f(-.5f,-.5f,-.5f);
        gl.glVertex3f(-.5f,.5f,-.5f);
        gl.glVertex3f(.5f,.5f,-.5f);
        gl.glVertex3f(.5f,-.5f,-.5f);
        gl.glColor3f(1f,0f,1f);
        gl.glVertex3f(-.5f,-.5f,-.5f);
        gl.glVertex3f(-.5f,-.5f,.5f);
        gl.glVertex3f(.5f,-.5f,.5f);
        gl.glVertex3f(.5f,-.5f,-.5f);
        gl.glEnd();
        gl.glFlush();
    }
    @Override
    public void display( GLAutoDrawable drawable ) {
        final GL2 gl = drawable.getGL().getGL2();
        gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );     
        gl.glLoadIdentity();
        if(up)
            angle2 -= 0.5f;
        if(down)
            angle2 += 0.5f;
        if(left)
            angle1 -= 0.5f;
        if(right)
            angle1 += 0.5f;
        if(zup)
            angle3 -= 0.5f;
        if(zdown)
            angle3 += 0.5f;
        cube(gl, 0f, 0f, 0f);
        cube(gl, 1.5f, 1.5f, 1.5f);
        cube(gl, 1.5f, 1.5f, -1.5f);
        cube(gl, 1.5f, -1.5f, 1.5f);
        cube(gl, 1.5f, -1.5f, -1.5f);
        cube(gl, -1.5f, 1.5f, 1.5f);
        cube(gl, -1.5f, 1.5f, -1.5f);
        cube(gl, -1.5f, -1.5f, 1.5f);
        cube(gl, -1.5f, -1.5f, -1.5f);
    }
    @Override
    public void dispose( GLAutoDrawable drawable ) {
    }
    @Override
    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 );
    }
    @Override
    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( 45f, h, 1, 20.0 );
       gl.glMatrixMode( GL2.GL_MODELVIEW );
       gl.glLoadIdentity();
    }
    public static void main( String[] args ) {
       final GLProfile profile = GLProfile.get( GLProfile.GL2 );
       GLCapabilities capabilities = new GLCapabilities( profile );
       // The canvas 
       final GLCanvas glcanvas = new GLCanvas( capabilities );
       test4 cube = new test4();
       glcanvas.addGLEventListener( cube );
       glcanvas.setSize( 800, 800 );
       final JFrame frame = new JFrame ("Arrow keys cubed");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.getContentPane().add( glcanvas );
       frame.setSize( frame.getContentPane().getPreferredSize() );
       frame.setFocusable(true);
       frame.addKeyListener(cube);
       glcanvas.setFocusable(false);
       frame.setVisible( true );
       final FPSAnimator animator = new FPSAnimator( glcanvas, 300,true );
       animator.start();
    }
 
    @Override
    public void keyTyped(KeyEvent e) {
 
    }
 
    @Override
    public void keyPressed(KeyEvent e) {
         int x = e.getKeyCode();
            switch (x) {
                case 37:
                    left = true;
                    break;
                case 39:
                    right = true;
                    break;
                case 38:
                    up = true;
                    break;
                case 40:
                    down = true;
                    break;
                case 96:
                    zup = true;
                    break;
                case 110:
                    zdown = true;
                    break;
                case 81:
                  System.exit(0);
          }
    }
 
    @Override
    public void keyReleased(KeyEvent e) {
      int x = e.getKeyCode();
            switch (x) {
               case 37:
                  left = false;
                  break;
               case 39:
                  right = false;
                  break;
               case 38:
                  up = false;
                  break;
               case 40:
                  down = false;
                  break;
                case 96:
                    zup = false;
                    break;
                case 110:
                    zdown = false;
                    break;
            }
    }
}

person ssddf    schedule 27.03.2021    source источник
comment
Примечание: программа называется test4, так как это моя четвертая программа, чтобы выяснить, как использовать JOGL.   -  person ssddf    schedule 28.03.2021
comment
Привет @ssddf, так в чем конкретно проблема с осью Z? для другой вашей проблемы - вращайте вокруг центра объекта - не комбинируйте перевод (получите центр до 0,0), поворот, а затем обратный перевод (обратно к исходным координатам).   -  person Mr R    schedule 28.03.2021
comment
Умножение матриц не является коммутативным. Порядок имеет значение.   -  person Rabbid76    schedule 28.03.2021
comment
Я хочу, чтобы оси x, y и z вращались вокруг точки (0, 0, -5). Ось z заставляет кубы вращаться вокруг своих центров, а оси x и y вращаются вокруг (0, 0, 0) и заставляют кубы перемещаться за пределы экрана. Я хочу, чтобы вращение по оси z работало так же, как вращение по осям x и y, но центрировало бы их все на (0, 0, -5), где находятся кубы.   -  person ssddf    schedule 29.03.2021
comment
@MrR Это сработало, но ось z все еще барахлит. Если я поверну куб так, чтобы синяя грань была обращена к дисплею, а затем поверну по оси Z, это будет иметь тот же эффект, что и вращение по оси Y.   -  person ssddf    schedule 29.03.2021
comment
Помогает ли это stackoverflow.com/a/39813107? ИЛИ, возможно, точка зрения - это то, что вы думаете?   -  person Mr R    schedule 29.03.2021
comment
Если я правильно понял, мне нужно определить свою собственную функцию ротатора, чтобы она работала?   -  person ssddf    schedule 30.03.2021