From b9518d33845cf23facf10de069d877ac0254d9db Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Tue, 19 May 2020 13:00:21 +0200
Subject: [PATCH] Canvas and GeneralGLEventListener.java returned nack to the
 code

---
 .../java/cz/fidentis/analyst/gui/Canvas.java  | 746 ++++++++++++++++++
 .../analyst/gui/GeneralGLEventListener.java   | 502 ++++++++++++
 2 files changed, 1248 insertions(+)
 create mode 100644 GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java
 create mode 100644 GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java

diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java
new file mode 100644
index 00000000..d43db886
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/gui/Canvas.java
@@ -0,0 +1,746 @@
+package cz.fidentis.analyst.gui;
+
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.awt.GLCanvas;
+import cz.fidentis.analyst.mesh.io.ModelFileFilter;
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.io.MeshObjLoader;
+import com.jogamp.opengl.util.FPSAnimator;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.io.File;
+import java.util.Timer;
+import java.util.TimerTask;
+import javax.swing.ImageIcon;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+/**
+ *
+ * @author Natália Bebjaková 
+ * 
+ * Canvas for displaying models containing GLCanvas and navigation.
+ */
+public class Canvas extends javax.swing.JPanel {
+    protected GLCanvas glCanvas;
+    protected long startClickTime = 0;
+    
+    protected TimerTask task;
+    protected Timer timer;
+    
+    protected GeneralGLEventListener listener;
+
+    /**
+     * animator's target frames per second
+     */
+    private static final int FPS = 60; 
+    private final FPSAnimator animator;
+    
+    /**
+     * decides if model is displayed as wire-frame 
+     */
+    protected boolean drawWireModel;   
+    
+    /**
+     * original model that is loaded from file   
+     */
+    protected MeshModel loadedModel;
+    
+    protected boolean loaded;   
+    
+    /**
+     * 
+     * @return true if model is loaded on canvas, false otherwise
+     */
+    public boolean isLoaded() {
+        return loaded;
+    }
+    
+    /**
+     * Creates new form Canva
+     */
+    public Canvas() {
+        initComponents();
+        
+        // gl version 2 is used
+        GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
+        capabilities.setDoubleBuffered(true);
+       
+        // creates new glCanvas panel for displaying model
+        glCanvas = new GLCanvas(capabilities);
+        jPanel1.add(glCanvas);
+        glCanvas.setVisible(false);     
+        glCanvas.setBackground(Color.black);
+        
+        // enables glCanvas to react to events
+        glCanvas.requestFocusInWindow();        
+        glCanvas.setSize(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom);
+       
+        // enables animated transition 
+        animator = new FPSAnimator(glCanvas, FPS, true);
+        animator.start();
+        listener = new GeneralGLEventListener(this);
+
+        this.validate();   
+    }
+    
+    /**
+     * Changing the size of glCanvas
+     * 
+     * @param d New size of glCanvas
+     */
+    public void resizeCanvas(Dimension d) {
+        jPanel1.setSize(d);
+        glCanvas.setSize(d);
+        this.validate();
+        this.repaint();
+        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
+    }
+    
+    /**
+     * 
+     * @return Original model that is loaded from dile
+     */
+    public MeshModel getLoadedModel() {
+        return loadedModel;
+    }
+    
+    /**
+     * Sets GLListener of the canvas 
+     * 
+     * @param listener GLListener for manipulation with model 
+     */
+    public void setListener(GeneralGLEventListener listener) {
+        this.listener = listener;
+    }
+    
+    
+    /**
+     * 
+     * @param drawWire Decides if model is displayed as wife-frame
+     */
+    public void setDrawWired(boolean drawWire) {
+        drawWireModel = drawWire;
+    }
+    /**
+     * 
+     * @return Returns if model is displayed as wife-frame
+     */
+    public boolean getDrawWired(){
+        return drawWireModel;
+    }
+    
+    /**
+     *
+     * @param v Decides if button for loading model is visible
+     */
+    public void setImportLabelVisible(Boolean v) {
+        loadModelButton.setVisible(v);
+    }
+    
+    /**
+     * Loads model selected in file chooser by user
+     */
+    public void loadModel () {
+        String[] extensions = new String[2];
+        extensions[0] = "obj";
+        extensions[1] = "OBJ";
+        
+        //enables to shows just .obj files in file chooser
+        ModelFileFilter filter = new ModelFileFilter(extensions, "*.obj");
+        JFileChooser jFileChooser1 = new JFileChooser();
+        jFileChooser1.setPreferredSize(new Dimension (800,500));
+       
+        jFileChooser1.addChoosableFileFilter(filter);  
+       
+        //file chooser will appear on top of glCanvas
+        jFileChooser1.showOpenDialog(this);
+        jFileChooser1.setDialogTitle("Import obj file");  
+        
+        File[] fileArray = new File[1];
+        //saves selected file by user as first element in array
+        fileArray[0] = jFileChooser1.getSelectedFile();
+        
+        if (fileArray.length <= 0) {
+            System.out.print("No file chosen.");
+        } else {
+            this.addModel(fileArray[0]);
+        }       
+        glCanvas.setVisible(true);
+    }
+
+    /**
+     * Loads the model in .obj format from file and adds this model to listener for displaying.
+     * If file does not contain 3D model or model is not correct, shows dialog with message
+     *
+     * @param file File from which model will be read
+     */
+    private void addModel (final File file) {
+        try {
+            //static class MeshObjLaoder reads .obj file into model
+            MeshModel model = MeshObjLoader.read(new File (file.getPath()));
+            loadedModel = MeshObjLoader.read(new File (file.getPath()));
+            if (model != null) {
+                // listener enables to manipulate and interact with model
+                listener.setCameraPosition(0, 0, 300);                    
+                glCanvas.addGLEventListener((GLEventListener) listener); 
+                listener.setModel(model);
+                listener.rotationAndSizeRestart();
+                loadModelButton.setVisible(false);
+                loaded = true;
+            }           
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+            JOptionPane.showMessageDialog(this, "File doesn't contain any model", "Model is not loaded.",
+                    0, new ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/notLoadedModel.png")));
+            System.out.println ("File doesn't contain any model");
+            loaded = false;               
+        }
+    }
+    
+    /**
+     * reset position of the displayed model
+     */
+    public void resetPosition(){
+        listener.rotationAndSizeRestart();
+    }
+    
+    /**
+     * Changes the model to be displayed
+     * 
+     * @param model New model that will be displayed on canvas
+     */
+    public void changeModel(MeshModel model) {
+        MeshModel newModel = new MeshModel(model);
+        listener.setModel(newModel);
+    }
+    
+    /**
+     * Returns the model which is displayed on canvas
+     * 
+     * @return Model that is displayed on canvas
+     */
+    public MeshModel getModel() {
+        return listener.getModel();
+    }
+   
+    
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     * 
+     * Generated code from NetBeans
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jLayeredPane1 = new javax.swing.JLayeredPane();
+        resetButton = new javax.swing.JLabel();
+        upNavigationButton = new javax.swing.JButton();
+        leftNavigationButton = new javax.swing.JButton();
+        minusNavigationButton = new javax.swing.JButton();
+        downNavigationButton = new javax.swing.JButton();
+        plusNavigationButton = new javax.swing.JButton();
+        jLabel1 = new javax.swing.JLabel();
+        loadModelButton = new javax.swing.JLabel();
+        rightNavigationButton1 = new javax.swing.JButton();
+        whiteBackroundButton = new javax.swing.JLabel();
+        blackBackroundButton = new javax.swing.JLabel();
+        jPanel1 = new javax.swing.JPanel();
+
+        setBackground(new java.awt.Color(0, 0, 0));
+        setLayout(new java.awt.BorderLayout());
+
+        jLayeredPane1.setBackground(new java.awt.Color(40, 40, 40));
+        jLayeredPane1.setToolTipText("");
+        jLayeredPane1.setOpaque(true);
+        jLayeredPane1.addComponentListener(new java.awt.event.ComponentAdapter() {
+            public void componentResized(java.awt.event.ComponentEvent evt) {
+                jLayeredPane1ComponentResized(evt);
+            }
+            public void componentShown(java.awt.event.ComponentEvent evt) {
+                jLayeredPane1ComponentShown(evt);
+            }
+        });
+
+        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/resetButton.png"))); // NOI18N
+        resetButton.setToolTipText("Reset position of model");
+        resetButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        resetButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
+            public void mouseMoved(java.awt.event.MouseEvent evt) {
+                resetButtonMouseMoved(evt);
+            }
+        });
+        resetButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                resetButtonMouseClicked(evt);
+            }
+            public void mouseExited(java.awt.event.MouseEvent evt) {
+                resetButtonMouseExited(evt);
+            }
+        });
+        jLayeredPane1.add(resetButton);
+        resetButton.setBounds(60, 40, 30, 30);
+
+        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/upButton.png"))); // NOI18N
+        upNavigationButton.setToolTipText("Rotate up");
+        upNavigationButton.setBorderPainted(false);
+        upNavigationButton.setContentAreaFilled(false);
+        upNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        upNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                upNavigationButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                upNavigationButtonMouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(upNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(upNavigationButton);
+        upNavigationButton.setBounds(60, 10, 30, 30);
+
+        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/leftButton.png"))); // NOI18N
+        leftNavigationButton.setToolTipText("Rotate left");
+        leftNavigationButton.setBorderPainted(false);
+        leftNavigationButton.setContentAreaFilled(false);
+        leftNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        leftNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                leftNavigationButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                leftNavigationButtonMouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(leftNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(leftNavigationButton);
+        leftNavigationButton.setBounds(30, 40, 30, 30);
+
+        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/minus.png"))); // NOI18N
+        minusNavigationButton.setToolTipText("Zoom out");
+        minusNavigationButton.setBorderPainted(false);
+        minusNavigationButton.setContentAreaFilled(false);
+        minusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        minusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                minusNavigationButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                minusNavigationButtonMouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(minusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(minusNavigationButton);
+        minusNavigationButton.setBounds(90, 90, 30, 30);
+
+        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/downButton.png"))); // NOI18N
+        downNavigationButton.setToolTipText("Rotate down");
+        downNavigationButton.setBorderPainted(false);
+        downNavigationButton.setContentAreaFilled(false);
+        downNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        downNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                downNavigationButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                downNavigationButtonMouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(downNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(downNavigationButton);
+        downNavigationButton.setBounds(60, 70, 30, 30);
+
+        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/plus.png"))); // NOI18N
+        plusNavigationButton.setToolTipText("Zoom in");
+        plusNavigationButton.setBorderPainted(false);
+        plusNavigationButton.setContentAreaFilled(false);
+        plusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        plusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                plusNavigationButtonMousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                plusNavigationButtonMouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(plusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(plusNavigationButton);
+        plusNavigationButton.setBounds(30, 90, 30, 30);
+
+        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/navigBackground.png"))); // NOI18N
+        jLayeredPane1.add(jLabel1);
+        jLabel1.setBounds(30, 10, 90, 90);
+
+        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/loadCanva.png"))); // NOI18N
+        loadModelButton.setToolTipText("");
+        loadModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        loadModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
+            public void mouseMoved(java.awt.event.MouseEvent evt) {
+                loadModelButtonMouseMoved(evt);
+            }
+        });
+        loadModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                loadModelButtonMouseClicked(evt);
+            }
+            public void mouseExited(java.awt.event.MouseEvent evt) {
+                loadModelButtonMouseExited(evt);
+            }
+        });
+        jLayeredPane1.add(loadModelButton);
+        loadModelButton.setBounds(200, 100, 210, 220);
+
+        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/rightButton.png"))); // NOI18N
+        rightNavigationButton1.setToolTipText("Rotate right");
+        rightNavigationButton1.setBorderPainted(false);
+        rightNavigationButton1.setContentAreaFilled(false);
+        rightNavigationButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        rightNavigationButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mousePressed(java.awt.event.MouseEvent evt) {
+                rightNavigationButton1MousePressed(evt);
+            }
+            public void mouseReleased(java.awt.event.MouseEvent evt) {
+                rightNavigationButton1MouseReleased(evt);
+            }
+        });
+        jLayeredPane1.setLayer(rightNavigationButton1, javax.swing.JLayeredPane.MODAL_LAYER);
+        jLayeredPane1.add(rightNavigationButton1);
+        rightNavigationButton1.setBounds(90, 40, 30, 30);
+
+        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/whiteBackroundCanvas.png"))); // NOI18N
+        whiteBackroundButton.setToolTipText("White backround");
+        whiteBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        whiteBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                whiteBackroundButtonMouseClicked(evt);
+            }
+        });
+        jLayeredPane1.add(whiteBackroundButton);
+        whiteBackroundButton.setBounds(50, 130, 56, 56);
+
+        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/blackBackroundCanvas.png"))); // NOI18N
+        blackBackroundButton.setToolTipText("Dark background");
+        blackBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
+        blackBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                blackBackroundButtonMouseClicked(evt);
+            }
+        });
+        jLayeredPane1.add(blackBackroundButton);
+        blackBackroundButton.setBounds(50, 190, 56, 56);
+
+        jPanel1.setBackground(new java.awt.Color(0, 0, 0));
+        jPanel1.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
+            public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
+                jPanel1MouseWheelMoved(evt);
+            }
+        });
+        jPanel1.setLayout(new java.awt.BorderLayout());
+        jLayeredPane1.add(jPanel1);
+        jPanel1.setBounds(0, 0, 0, 0);
+
+        add(jLayeredPane1, java.awt.BorderLayout.CENTER);
+    }// </editor-fold>//GEN-END:initComponents
+
+    /**
+     * 
+     * @param evt Resizing glCanvas cantaining components
+     */
+    private void jLayeredPane1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentResized
+        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
+        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
+        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
+    }//GEN-LAST:event_jLayeredPane1ComponentResized
+
+    /**
+     * 
+     * @param evt Showing glCanvas cantaining components
+     */
+    private void jLayeredPane1ComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentShown
+        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
+        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
+        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
+    }//GEN-LAST:event_jLayeredPane1ComponentShown
+
+    /**
+     * 
+     * @param evt Enables to rotate left the model when left navigation button is pressed
+     */
+    private void leftNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.rotateLeft(2);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/leftButtonPressed.png")));
+    }//GEN-LAST:event_leftNavigationButtonMousePressed
+
+    /**
+     * 
+     * @param evt Enables to rotate up the model when up navigation button is pressed
+     */
+    private void upNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.rotateUp(2);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/upButtonPressed.png")));
+    }//GEN-LAST:event_upNavigationButtonMousePressed
+
+    /**
+     * 
+     * @param evt Enables to rotate down the model when down navigation button is pressed
+     */
+    private void downNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.rotateDown(2);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/downButtonPressed.png")));
+    }//GEN-LAST:event_downNavigationButtonMousePressed
+
+    /**
+     * 
+     * @param evt Enables to zoom in the model when plus navigation button is pressed
+     */
+    private void plusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.zoomIn(3);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/plusPressed.png")));
+    }//GEN-LAST:event_plusNavigationButtonMousePressed
+ 
+  /**
+  * 
+  * @param evt Enables to zoom out the model when minus navigation button is pressed
+  */
+    private void minusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.zoomOut(3);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/minusPressed.png")));
+    }//GEN-LAST:event_minusNavigationButtonMousePressed
+
+    /**
+     * 
+     * @param evt Stops rotating left
+     */
+    private void leftNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.rotateLeft(22.5);
+        }
+        startClickTime = 0;
+        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/leftButton.png")));
+    }//GEN-LAST:event_leftNavigationButtonMouseReleased
+
+    /**
+     * 
+     * @param evt Stops rotating up
+     */
+    private void upNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.rotateUp(22.5);
+        }
+        startClickTime = 0;
+        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/upButton.png")));
+    }//GEN-LAST:event_upNavigationButtonMouseReleased
+
+    /**
+     * 
+     * @param evt Stops rotating down
+     */
+    private void downNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.rotateDown(22.5);
+        }
+        startClickTime = 0;
+        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/downButton.png")));
+    }//GEN-LAST:event_downNavigationButtonMouseReleased
+
+    /**
+     * 
+     * @param evt Stops zooming in 
+     */
+    private void plusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.zoomIn(30);
+        }
+        startClickTime = 0;
+        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/plus.png")));
+    }//GEN-LAST:event_plusNavigationButtonMouseReleased
+
+    /**
+     * 
+     * @param evt  Stops zooming out
+     */
+    private void minusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.zoomOut(30);
+        }
+        startClickTime = 0;
+        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/minus.png")));
+    }//GEN-LAST:event_minusNavigationButtonMouseReleased
+
+    /**
+     * 
+     * @param evt Laoding the .obj file when button pressed
+     */
+    private void loadModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseClicked
+       loadModel();
+    }//GEN-LAST:event_loadModelButtonMouseClicked
+
+    /**
+     * 
+     * @param evt Enables to zoom in and out the model by mouse wheeling
+     */
+    private void jPanel1MouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_jPanel1MouseWheelMoved
+        if (evt.getWheelRotation() > 0) {
+            listener.zoomIn(-5 * evt.getWheelRotation());
+        } else {
+            listener.zoomOut(5 * evt.getWheelRotation());
+        }
+    }//GEN-LAST:event_jPanel1MouseWheelMoved
+
+    /**
+     * 
+     * @param evt Design is reacting to mouse movement 
+     */
+    private void loadModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseMoved
+        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/loadCanvaClicked.png")));
+    }//GEN-LAST:event_loadModelButtonMouseMoved
+
+    /**
+     * 
+     * @param evt Design is reacting to mouse movement  
+     */
+    private void loadModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseExited
+        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/loadCanva.png")));
+    }//GEN-LAST:event_loadModelButtonMouseExited
+
+    /**
+     * 
+     * @param evt Enables to rotate down the model when down navigation button is pressed
+     */
+    private void rightNavigationButton1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MousePressed
+        timer = new Timer();
+        startClickTime = System.currentTimeMillis();
+        task = new TimerTask() {
+            @Override
+            public void run() {
+                listener.rotateRight(2);
+            }
+        };
+        timer.schedule(task, 500, 100);
+        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/rightButtonPressed.png")));
+    }//GEN-LAST:event_rightNavigationButton1MousePressed
+
+    /**
+     * 
+     * @param evt Stops rotating right
+     */
+    private void rightNavigationButton1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MouseReleased
+        timer.cancel();
+        if ((System.currentTimeMillis() - startClickTime) < 500) {
+            listener.rotateRight(22.5);
+        }
+        startClickTime = 0;
+        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/rightButton.png")));
+    }//GEN-LAST:event_rightNavigationButton1MouseReleased
+
+    /**
+     * 
+     * @param evt Position of model on glCanvas is set to starting position
+     */
+    private void resetButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseClicked
+        listener.rotationAndSizeRestart();
+    }//GEN-LAST:event_resetButtonMouseClicked
+
+    /**
+     * 
+     * @param evt Design is reacting to mouse movement  
+     */
+    private void resetButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseMoved
+        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/resetButtonPressed.png")));
+        resetButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+    }//GEN-LAST:event_resetButtonMouseMoved
+
+    /**
+     * 
+     * @param evt Design is reacting to mouse movement  
+     */
+    private void resetButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseExited
+        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/resetButton.png")));
+    }//GEN-LAST:event_resetButtonMouseExited
+
+    /**
+     * 
+     * @param evt Changes backround of the canvas into white color
+     */
+    private void whiteBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_whiteBackroundButtonMouseClicked
+        listener.setWhiteBackround(true);
+        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/whiteBackroundCanvasPressed.png")));
+        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/blackBackroundCanvas.png")));
+    }//GEN-LAST:event_whiteBackroundButtonMouseClicked
+
+    /**
+     * 
+     * @param evt Changes backround of the canvas into dark color
+     */
+    private void blackBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_blackBackroundButtonMouseClicked
+        listener.setWhiteBackround(false);
+        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/whiteBackroundCanvas.png")));
+        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/cz/fidentis/analyst/gui/resources/blackBackroundCanvasPressed.png")));
+    }//GEN-LAST:event_blackBackroundButtonMouseClicked
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel blackBackroundButton;
+    private javax.swing.JButton downNavigationButton;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLayeredPane jLayeredPane1;
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JButton leftNavigationButton;
+    private javax.swing.JLabel loadModelButton;
+    private javax.swing.JButton minusNavigationButton;
+    private javax.swing.JButton plusNavigationButton;
+    private javax.swing.JLabel resetButton;
+    private javax.swing.JButton rightNavigationButton1;
+    private javax.swing.JButton upNavigationButton;
+    private javax.swing.JLabel whiteBackroundButton;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java b/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java
new file mode 100644
index 00000000..94acd8f1
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java
@@ -0,0 +1,502 @@
+package cz.fidentis.analyst.gui;
+
+import cz.fidentis.analyst.mesh.core.MeshModel;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import com.jogamp.opengl.GL;
+import static com.jogamp.opengl.GL.GL_DEPTH_TEST;
+import static com.jogamp.opengl.GL.GL_FRONT_AND_BACK;
+import static com.jogamp.opengl.GL.GL_VIEWPORT;
+import com.jogamp.opengl.GL2;
+import static com.jogamp.opengl.GL2GL3.GL_FILL;
+import static com.jogamp.opengl.GL2GL3.GL_LINE;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
+import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX;
+import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX;
+import com.jogamp.opengl.glu.GLU;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+
+/**
+ *
+ * @author Natália Bebjaková
+ */
+public class GeneralGLEventListener implements GLEventListener {  
+    /**
+     * MeshModel that is displayed
+     */
+    private MeshModel model = new MeshModel();
+    /**
+     * GLCanvas which listener belongs to 
+     */
+    protected Canvas glCanvas;  
+    /**
+    * GLU object.
+    */
+    protected GLU glu;
+    /**
+     * Usage of openGL version 2
+     */
+    protected GL2 gl;
+    /**
+     * The last viewport.
+     */
+    protected int[] viewport = new int[4];
+     /**
+     * The last model matrix.
+     */
+    protected float[] modelViewMatrix = new float[16];
+    /**
+     * The last projection matrix.
+     */
+    protected float[] projectionMatrix = new float[16];  
+    /**
+     * The X coordinate of the last known mouse position during the scene rotation.
+     */
+    int mouseX = 0;
+    /**
+     * The Y coordinate of the last know mouse position during the scene rotation.
+     */
+    int mouseY = 0;
+    
+    protected Vector3f defaultPosition = new Vector3f(0, 0, 300);
+    protected Vector3f currentPosition = new Vector3f(0, 0, 300);
+
+    protected double zCenter = 0;
+    protected double xCenter = 0;
+    protected double yCenter = 0;
+
+    protected double zCameraPosition;
+    protected double xCameraPosition;
+    protected double yCameraPosition;
+
+    protected double zUpPosition = 0;
+    protected double xUpPosition = 0;
+    protected double yUpPosition = 1;
+    
+    /**
+     * Decides if model is diplayed as wire-frame
+     */  
+    protected boolean wireModel = false;
+    /**
+     * Decides if the backround will be white
+     */
+    protected boolean whiteBackround = false;
+    
+    /**
+     * 
+     * @return is backround white or not
+     */
+    public boolean isWhiteBackround() {
+        return whiteBackround;
+    }
+    
+    /**
+     * 
+     * @return Matrix for model view
+     */
+    public float[] getModelViewMatrix() {
+        return modelViewMatrix;
+    }
+
+    /**
+     * 
+     * @return Matrix for projection
+     */
+    public float[] getProjectionMatrix() {
+        return projectionMatrix;
+    }
+    
+    /**
+     * 
+     * @return GlCanvas for displaying
+     */
+    public Canvas getGlCanvas() {
+        return glCanvas;
+    }
+    
+    /**
+     * 
+     * @param drawWire Decides if model is displayed as wire-frame
+     */
+    public void setWireMode(boolean drawWire) {
+        wireModel = drawWire;
+    }
+       
+    /**
+     * 
+     * @param whiteBackround Is backround white or not
+     */
+    public void setWhiteBackround(boolean whiteBackround) {
+        this.whiteBackround = whiteBackround;
+    }
+
+    /**
+     * Creates new EventListener
+     * @param canvas GLCanvas which listener belongs to
+     */
+    public GeneralGLEventListener(Canvas canvas) {
+        this.glCanvas = canvas;
+    }
+    
+    /**
+     *
+     * @param model Set model to be displayed
+     */
+    public void setModel(MeshModel model) {
+        this.model = model;
+    }
+
+    /**
+     *
+     * @return Returns displayed model 
+     */
+    public MeshModel getModel() {
+        return model;
+    }
+
+    
+    /**
+     * Invoked when main frame is created
+     * @param glad Glad object
+     */
+    @Override
+    public void init(GLAutoDrawable glad) {
+        
+        this.gl = (GL2) glad.getGL();
+        glu = new GLU();
+      
+        gl.setSwapInterval(1);
+        gl.glEnable(GL2.GL_LIGHTING);
+        gl.glEnable(GL2.GL_LIGHT0);
+        gl.glEnable(GL2.GL_DEPTH_TEST);
+        gl.glClearColor(0,0,0,0);     // background for GLCanvas
+        gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
+        
+        gl.glShadeModel(GL2.GL_SMOOTH);    // use smooth shading
+
+        gl.glDepthFunc(GL2.GL_LESS);
+        gl.glDepthRange(0.0, 1.0);
+        gl.glEnable(GL_DEPTH_TEST); 
+
+        gl.glEnable(GL2.GL_NORMALIZE);
+        gl.glDisable(GL2.GL_CULL_FACE);
+    }
+
+    /**
+     * Invoked when main frame is closed
+     * @param glad Glad object
+     */
+    @Override
+    public void dispose(GLAutoDrawable glad) {
+    }
+    
+    /**
+     * Invoked every frame.
+     * @param glad Glad object
+     */
+    @Override
+    public void display(GLAutoDrawable glad) {
+        wireModel = glCanvas.getDrawWired(); // is wire-frame or not
+        if (whiteBackround) {
+            gl.glClearColor(0.9f,0.9f,0.9f,0); 
+        } else {
+            gl.glClearColor(0.25f,0.25f,0.25f,0); 
+        }
+        // background for GLCanvas       
+        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+        gl.glLoadIdentity();
+
+        // sets model to proper position
+        glu.gluLookAt(xCameraPosition, yCameraPosition, zCameraPosition, xCenter, yCenter, zCenter, xUpPosition, yUpPosition, zUpPosition);
+
+        gl.glShadeModel(GL2.GL_SMOOTH);
+        gl.glGetIntegerv(GL_VIEWPORT, viewport, 0);
+        gl.glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
+        gl.glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix, 0);
+        
+        //if there is any model, draw 
+        if (model != null) {
+            if (wireModel) {
+                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); //drawn as wire-frame
+                drawWithoutTextures(model);
+            } else {
+                gl.glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); // drawn as full traingles
+                drawWithoutTextures(model);
+            }
+        } 
+            
+        //gl.glPopMatrix();
+        gl.glFlush();
+    }
+    
+    /**
+     * Loops through the facets and render each of them 
+     * 
+     * @param model model of the face
+     */
+    public void drawWithoutTextures(MeshModel model) {
+        for (int i = 0; i < model.getFacets().size(); i++) {
+            renderFacet(model.getFacets().get(i));
+        }
+    }
+    
+    /**
+     * Loops through the facet and render all the vertices as they are stored in corner table
+     * 
+     * @param facet facet of model
+     */
+    public void renderFacet(MeshFacet facet) {
+        gl.glBegin(GL2.GL_TRIANGLES); //vertices are rendered as triangles
+     
+        // get the normal and tex coords indicies for face i  
+        for (int v = 0; v < facet.getCornerTable().getSize(); v++) { 
+            // render the normals
+            Vector3d norm = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getNormal(); 
+            if(norm != null) {
+                gl.glNormal3d(norm.x, norm.y, norm.z);
+            }
+            // render the vertices
+            Vector3d vert = facet.getVertices().get(facet.getCornerTable().getRow(v).getVertexIndex()).getPosition(); 
+            gl.glVertex3d(vert.x, vert.y, vert.z);
+        }
+        gl.glEnd();
+
+    }
+
+    /**
+     *
+     * @param glad Glad object
+     * @param x x
+     * @param y y
+     * @param width New width
+     * @param height New height
+     */
+    @Override
+    public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
+
+        if (height == 0) {
+            height = 1;    // to avoid division by 0 in aspect ratio below
+        }
+        gl.glViewport(x, y, width, height);  // size of drawing area
+
+        float h = (float) height / (float) width;
+
+        gl.glMatrixMode(GL2.GL_PROJECTION);
+        gl.glLoadIdentity();
+
+        glu.gluPerspective(65, width / (float) height, 5.0f, 1500.0f);
+        gl.glMatrixMode(GL2.GL_MODELVIEW);
+        gl.glLoadIdentity();
+
+        gl.glTranslatef(0.0f, 0.0f, -40.0f);
+    }
+
+    /**
+     *
+     * @param x New x position
+     * @param y New y position
+     * @param z New z position
+     */
+    public void setCameraPosition(float x, float y, float z) {
+        currentPosition.set(x, y, z);
+
+        setNewCameraPosition(currentPosition);
+        zCameraPosition = defaultPosition.z;
+        xCameraPosition = defaultPosition.x;
+        yCameraPosition = defaultPosition.y;
+    }    
+
+    /**
+     *
+     * @param position New position of camera
+     */
+    public void setNewCameraPosition(Vector3f position) {
+        xCameraPosition = position.x;
+        yCameraPosition = position.y;
+        zCameraPosition = position.z;
+    }
+
+    /**
+     *
+     * @param degree degree of rotation
+     */
+    public void rotateUp(double degree) {
+        rotate(-degree, 0);
+    }
+
+    /**
+     *
+     * @param degree degree of rotation
+     */
+    public void rotateDown(double degree) {
+        rotate(degree, 0);
+    }
+
+    /**
+     *
+     * @param degree degree of rotation
+     */
+    public void rotateLeft(double degree) {
+        rotate(0, degree);
+    }
+
+    /**
+     *
+     * @param degree degree of rotation
+     */
+    public void rotateRight(double degree) {
+        rotate(0, -degree);
+    }
+
+    /**
+     * 
+     * @return X axis
+     */
+    private Vector3f getXaxis() {
+        Vector3f xAxis = new Vector3f(
+                (float) ((yCameraPosition - yCenter) *zUpPosition - (zCameraPosition - zCenter) * yUpPosition),
+                (float) ((zCameraPosition - zCenter) * xUpPosition - (xCameraPosition - xCenter) * zUpPosition),
+                (float) ((xCameraPosition - xCenter) * yUpPosition - xUpPosition * (yCameraPosition - yCenter)));
+         
+        float length = (float) Math.sqrt(xAxis.x * xAxis.x +
+                xAxis.y * xAxis.y + xAxis.z * xAxis.z);
+        xAxis.set(xAxis.x / length, xAxis.y / length, xAxis.z / length);
+        return xAxis;
+    }
+
+    /**
+     * 
+     * @return Y axis
+     */
+    private Vector3f getYaxis() {
+         Vector3f yAxis = new Vector3f((float) xUpPosition, (float) yUpPosition, (float) zUpPosition);
+        float length = (float) Math.sqrt(yAxis.x * yAxis.x +
+                yAxis.y * yAxis.y + yAxis.z * yAxis.z);
+        yAxis.set((yAxis.x / length), (yAxis.y / length), (yAxis.z / length));
+        return yAxis;
+    }
+
+    /**
+     * Rotates object around axes that apear as horizontal and vertical axe on
+     * screen (paralel to the sceen edges), intersecting at the center of
+     * screen( i.e head center).
+     *
+     * @param xAngle angle around vertical axe on screen
+     * @param yAngle angle around horizontal axe on screen
+     */
+    public void rotate(double xAngle, double yAngle) {
+        Vector3f xAxis = getXaxis();
+        Vector3f yAxis = getYaxis();
+
+        Vector3f point = new Vector3f((float) xCameraPosition,
+                (float) yCameraPosition, (float) zCameraPosition);
+
+        Vector3f camera = rotateAroundAxe(point, xAxis, Math.toRadians(xAngle));
+        camera = rotateAroundAxe(camera, yAxis, Math.toRadians(yAngle));
+
+        point = new Vector3f((float) xUpPosition, (float) yUpPosition, (float) zUpPosition);
+
+        Vector3f up = rotateAroundAxe(point, xAxis, Math.toRadians(xAngle));
+        up = rotateAroundAxe(up, yAxis, Math.toRadians(yAngle));
+
+        xUpPosition = up.x;
+        yUpPosition = up.y;
+        zUpPosition = up.z;
+
+        setNewCameraPosition(camera);
+    }
+
+    /**
+     * 
+     * @param xShift xShift
+     * @param yShift yShift
+     */
+    public void move(double xShift, double yShift) {
+        Vector3f xAxis = getXaxis();
+        Vector3f yAxis = getYaxis();
+
+        Vector3f shift = new Vector3f((float) (xAxis.x * xShift + yAxis.x * yShift),
+                (float) (xAxis.y * xShift + yAxis.y * yShift), (float) (xAxis.z * xShift + yAxis.z * yShift));
+        Vector3f camera = new Vector3f((float) xCameraPosition + shift.x, (float) yCameraPosition + shift.y,
+                (float) zCameraPosition + shift.z);
+        xCenter += shift.x;
+        yCenter += shift.y;
+        zCenter += shift.z;
+
+        setNewCameraPosition(camera);
+    }
+
+    /**
+     * Calculate the new position f point from given angle and rotation axe.
+     *
+     * @param point original position
+     * @param u vector of rotation axe
+     * @param angle angle of rotation
+     * @return new position
+     */
+    public Vector3f rotateAroundAxe(Vector3f point, Vector3f u, double angle) {
+        Vector3f p;
+        float x = (float) ((Math.cos(angle) + u.x * u.x * (1 - Math.cos(angle))) * point.x
+                + (u.x * u.y * (1 - Math.cos(angle)) - u.z * Math.sin(angle)) * point.y
+                + (u.x * u.z * (1 - Math.cos(angle)) + u.y * Math.sin(angle)) * point.z);
+        float y = (float) ((u.x * u.y * (1 - Math.cos(angle)) + u.z * Math.sin(angle)) * point.x
+                + (Math.cos(angle) + u.y * u.y * (1 - Math.cos(angle))) * point.y
+                + (u.y * u.z * (1 - Math.cos(angle)) - u.x * Math.sin(angle)) * point.z);
+        float z = (float) ((u.x * u.z * (1 - Math.cos(angle)) - u.y * Math.sin(angle)) * point.x
+                + (u.y * u.z * (1 - Math.cos(angle)) + u.x * Math.sin(angle)) * point.y
+                + (Math.cos(angle) + u.z * u.z * (1 - Math.cos(angle))) * point.z);
+        p = new Vector3f(x, y, z);
+
+        return p;
+    }
+
+    /**
+     * Sets model to the starting position
+     */
+    public void rotationAndSizeRestart() {
+        xUpPosition = 0;
+        yUpPosition = 1;
+        zUpPosition = 0;
+
+        setNewCameraPosition(defaultPosition);
+        xCenter = 0;
+        yCenter = 0;
+        zCenter = 0;
+    }
+
+    /**
+     *
+     * @param distance Distance to be zoom in
+     */
+    public void zoomIn(double distance) {
+        double x = xCameraPosition - xCenter;
+        double y = yCameraPosition - yCenter;
+        double z = zCameraPosition - zCenter;
+        double sqrt = Math.sqrt(x * x + y * y + z * z);
+
+        if (sqrt > 0) {
+            xCameraPosition = xCenter + ((sqrt - distance) * x / sqrt);
+            yCameraPosition = yCenter + ((sqrt - distance) * y / sqrt);
+            zCameraPosition = zCenter + ((sqrt - distance) * z / sqrt);
+        }
+    }
+
+    /**
+     *
+     * @param distance Distance to be zoom out
+     */
+    public void zoomOut(double distance) {
+        double x = xCameraPosition - xCenter;
+        double y = yCameraPosition - yCenter;
+        double z = zCameraPosition - zCenter;
+        double sqrt = Math.sqrt(x * x + y * y + z * z);
+
+        if (sqrt == 0) {
+            sqrt = 1;
+        }
+        xCameraPosition = xCenter + ((sqrt + distance) * x / sqrt);
+        yCameraPosition = yCenter + ((sqrt + distance) * y / sqrt);
+        zCameraPosition = zCenter + ((sqrt + distance) * z / sqrt);
+    }
+}
-- 
GitLab