マウス操作まで作る


scalaで書く前にとりあえずjavaで、他の言語で作るときと同様のマウス操作まで作った。
ひとつ前で作ったパーサと合体して頂点配列を描画するようにしたらMQOビューワはできあがり予定。


JOGLAPP.java

import javax.swing.JFrame;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.Action;
import javax.swing.AbstractAction;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;

import javax.media.opengl.awt.GLJPanel;

class MyFrame extends JFrame 
    implements MouseListener, MouseMotionListener, MouseWheelListener {
    GLDriver driver;
    int mouseLastX;
    int mouseLastY;
    boolean mouseMiddlePressed;
    boolean mouseRightPressed;

    public MyFrame(String title){
        super(title);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        driver=new GLDriver();

        // initialize mouse state
        mouseRightPressed=false;
        mouseMiddlePressed=false;
        mouseLastX=0;
        mouseLastY=0;

        // GLJPanel
        GLJPanel glArea=new GLJPanel();
        setContentPane(glArea);
        glArea.addGLEventListener(driver);
        // mouse event
        glArea.addMouseListener(this);
        glArea.addMouseMotionListener(this);
        addMouseWheelListener(this);

        // setup menu
        JMenuBar menuBar=new JMenuBar();
        setJMenuBar(menuBar);

        // file menu
        JMenu menu=new JMenu("File");
        menuBar.add(menu);

        // file open item
        final JFrame parentFrame=this;
        JMenuItem item=new JMenuItem(new AbstractAction(){
            {
                putValue(NAME, "Open");
                putValue(SHORT_DESCRIPTION, "open a file");
                putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_O));
            }
            public void actionPerformed(ActionEvent e){
                final JFileChooser fc = new JFileChooser();
                int returnVal=fc.showOpenDialog(parentFrame);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    driver.openFile(fc.getSelectedFile());
                } 
            }
        });
        menu.add(item);
    }

    ////////////////////////////////////////////////////////////
    // MouseListener
    ////////////////////////////////////////////////////////////
    @Override
        public void mouseClicked(MouseEvent e) {
        }

    @Override
        public void mouseEntered(MouseEvent e) {
        }

    @Override
        public void mouseExited(MouseEvent e) {
        }

    @Override
        public void mousePressed(MouseEvent e) {
            int x=e.getX();
            int y=e.getY();
            switch(e.getButton()){
                case MouseEvent.BUTTON1:
                    break;
                case MouseEvent.BUTTON2:
                    mouseMiddlePressed=true;
                    break;
                case MouseEvent.BUTTON3:
                    mouseRightPressed=true;
                    break;
            }
            mouseLastX=x;
            mouseLastY=y;
        }

    @Override
        public void mouseReleased(MouseEvent e) {
            switch(e.getButton()){
                case MouseEvent.BUTTON1:
                    break;
                case MouseEvent.BUTTON2:
                    mouseMiddlePressed=false;
                    break;
                case MouseEvent.BUTTON3:
                    mouseRightPressed=false;
                    break;
            }
        }

    ////////////////////////////////////////////////////////////
    // MouseMotionListener
    ////////////////////////////////////////////////////////////
    @Override
        public void mouseDragged(MouseEvent e) {
            int x=e.getX();
            int y=e.getY();
            if(mouseMiddlePressed){
                driver.onMouseMiddleDrag(x-mouseLastX, y-mouseLastY);
                repaint();
            }
            if(mouseRightPressed){
                driver.onMouseRightDrag(x-mouseLastX, y-mouseLastY);
                repaint();
            }
            mouseLastX=x;
            mouseLastY=y;
        }

    @Override
        public void mouseMoved(MouseEvent e) {
        }

    ////////////////////////////////////////////////////////////
    // MouseWheelListener
    ////////////////////////////////////////////////////////////
    @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            driver.onMouseWheel(e.getWheelRotation());
            repaint();
        }
}

public class JOGLAPP {
    public static void main(String[] args) {
        // SWING
        JFrame frame=new MyFrame("SWING");
        frame.setSize(300, 300);
        frame.setVisible(true);
    }
}

JOGL2.0ではjavax.media.opengl.GL2を使うのがミソらしい?


GLDriver.java

import java.io.File;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import com.sun.opengl.util.Animator;

class View {
    float head;
    float pitch;
    float distance;
    float shift_x;
    float shift_y;

    float fovy;
    float aspect;
    float near;
    float far;

    public View(){
        head=0.0f;
        pitch=0.0f;
        distance=5.0f;
        shift_x=0.0f;
        shift_y=0.0f;

        fovy=45.0f;
        aspect=1.0f;
        near=1.0f;
        far=20.0f;
    }

    public void resize(GL gl, float width, float height){
        gl.glViewport(0, 0, (int)width, (int)height);
        // avoid a divide by zero error!
        if (height <= 0){
            height = 1;
        }
        aspect = width / height;
        applyProjection(gl.getGL2());
    }

    public void applyProjection(GL2 gl){
        GLU glu=GLU.createGLU();
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(fovy, aspect, near, far);
    }

    public void apply(GL2 gl){
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glTranslated(shift_x, shift_y, -distance);
        gl.glRotated(pitch, 1, 0, 0);
        gl.glRotated(head, 0, 1, 0);
    }

    public void head(float d){
        head+=d;
        while(head>180.0f){
            head-=360.0f;
        }
        while(head<-180.0f){
            head+=360.0f;
        }
    }
    public void pitch(float d){
        pitch+=d;
        if(pitch>90.0f){
            pitch=90.0f;
        }
        if(pitch<-90.0f){
            pitch=-90.0f;
        }
    }
    public void dolly(float d){
        if(d>0){
            distance*=1.1;
        }
        else if(d<0){
            distance*=0.9;
        }
    }
    public void shift(float dx, float dy){
        float FACTOR=0.005f;
        shift_x+=dx*distance*FACTOR;
        shift_y+=dy*distance*FACTOR;
    }
}

class GLDriver implements GLEventListener {
    View view;

    public GLDriver(){
        view=new View();

        Animator anim = new Animator();
        anim.start();
    }

    public void onMouseMiddleDrag(int x, int y){
        view.shift(x, -y);
    }

    public void onMouseRightDrag(int x, int y){
        view.head(x);
        view.pitch(y);
    }

    public void onMouseWheel(int d){
        view.dolly(d);
    }

    public boolean openFile(File f){
        System.out.println("open: "+f);
        return true;
    }

    private void drawCube(GL2 gl){
      gl.glBegin(GL2.GL_QUADS);
      // Front Face
      gl.glColor3f(1.0f, 1.0f, 1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
      // Back Face
      gl.glColor3f(1.0f, 0.0f, 1.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
      // Top Face
      gl.glColor3f(1.0f, 0.0f, 0.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
      // Bottom Face
      gl.glColor3f(1.0f, 1.0f, 0.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
      // Right face
      gl.glColor3f(0.0f, 1.0f, 0.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
      // Left Face
      gl.glColor3f(0.0f, 0.0f, 1.0f);
      gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
      gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
      gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
      gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
      gl.glEnd();
    }

    ////////////////////////////////////////////////////////////
    // GLEventListener
    ////////////////////////////////////////////////////////////
    @Override
        public void init(GLAutoDrawable drawable) {
            // init opengl here
            System.out.println("MyGLEventListener#init");

            GL2 gl = drawable.getGL().getGL2();

            //gl.glShadeModel(GL.GL_SMOOTH);
            gl.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
            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 display(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();

            // clear
            gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
            gl.glMatrixMode(GL2.GL_MODELVIEW);
            gl.glLoadIdentity();

            // draw
            view.apply(gl);
            drawCube(gl);

            gl.glFinish();
        }

    @Override
        public void dispose(GLAutoDrawable drawable) {
        }

    @Override
        public void reshape(GLAutoDrawable drawable, 
                int x, int y, int width, int height) {
            view.resize(drawable.getGL(), width, height);
        }
}