/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */


import com.jogamp.opengl.*;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.GLEventListener;
import static com.jogamp.opengl.GL.*;  // GL constants
import static com.jogamp.opengl.GL2.*; // GL2 constants
import com.jogamp.opengl.awt.GLJPanel;
import java.nio.FloatBuffer;

/**
 *
 * @author hd
 */
public class SceneOGL extends GLJPanel implements GLEventListener {

    public float rotate_x, rotate_y, rotate_z;
    
   // Setup OpenGL Graphics Renderer

    private GLU glu;  // for the GL Utility

    /**
     * Constructor to setup the GUI for this Component
     */
    public SceneOGL() {
        this.addGLEventListener((com.jogamp.opengl.GLEventListener) this);
    }

   // ------ Implement methods declared in GLEventListener ------
    /**
     * Called back immediately after the OpenGL context is initialized. Can be
     * used to perform one-time initialization. Run only once.
     */
    @Override
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();      // get the OpenGL graphics context
        glu = new GLU();                         // get GL Utilities
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color
        gl.glClearDepth(1.0f);      // set clear depth value to farthest
        gl.glEnable(GL_DEPTH_TEST); // enables depth testing
        gl.glEnable(GL_LIGHTING);
        gl.glDepthFunc(GL_LEQUAL);  // the type of depth test to do
        gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // best perspective correction
        gl.glShadeModel(GL_SMOOTH); // blends colors nicely, and smoothes out lighting

      // ----- Your OpenGL initialization code here -----
 
    }

    public void setupLight(GL2 gl, int light_num, float x, float y, float z, float r, float g, float b) {
        gl.glEnable(light_num);
        gl.glLightfv(light_num, GL_AMBIENT, toFloatBuffer(r, g, b, 1));
        gl.glLightfv(light_num, GL_DIFFUSE, toFloatBuffer(r, g, b, 1));
        gl.glLightfv(light_num, GL_POSITION, toFloatBuffer(x, y, z, 1));
    }

    public FloatBuffer toFloatBuffer(float a, float b, float c, float d) {
        FloatBuffer fb;
        fb = FloatBuffer.allocate(4);
        fb.put(0, a);
        fb.put(1, b);
        fb.put(2, c);
        fb.put(3, d);
        return fb;
    }

    public void setupLightning(GL2 gl) {
        gl.glEnable(GL_LIGHTING);

        gl.glLightModelfv(GL_LIGHT_MODEL_AMBIENT, toFloatBuffer(0, 0, 0, 1));
        gl.glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
        gl.glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);

        /* Set the material color to follow the
         * current color.
         */
        gl.glEnable(GL_COLOR_MATERIAL);
        gl.glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
        
        setupLight(gl, GL_LIGHT0, 0, 10, 10, 1f, 1f, 1f);
    }

    /**
     * Call-back handler for window re-size event. Also called when the drawable
     * is first set to visible.
     */
    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        GL2 gl = drawable.getGL().getGL2();  // get the OpenGL 2 graphics context

        if (height == 0) {
            height = 1;   // prevent divide by zero
        }
        float aspect = (float) width / height;

        // Set the view port (display area) to cover the entire window
        gl.glViewport(0, 0, width, height);

        // Setup perspective projection, with aspect ratio matches viewport
        gl.glMatrixMode(GL_PROJECTION);  // choose projection matrix
        gl.glLoadIdentity();             // reset projection matrix
        glu.gluPerspective(55.0, aspect, 0.1, 100.0); // fovy, aspect, zNear, zFar

        // Enable the model-view transform
        gl.glMatrixMode(GL_MODELVIEW);
        gl.glLoadIdentity(); // reset
    }

    /**
     * Called back by the animator to perform rendering.
     */
    @Override
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();  // get the OpenGL 2 graphics context
        gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers
        gl.glLoadIdentity();  // reset the model-view matrix

        // ----- Your OpenGL rendering code here (Render a white triangle for testing) -----
        gl.glTranslatef(0.0f, 0.0f, -1.6f); // translate into the screen

        setupLightning(gl);
        gl.glRotatef(rotate_z, 0, 0, 1);
        gl.glRotatef(rotate_x, 1, 0, 0);
        gl.glRotatef(rotate_y, 0, 1, 0);
        
        // Draw AXIS
        gl.glLineWidth(3.5f);
        gl.glColor3d(1.0, 0.0, 0.0);
        gl.glBegin(GL_LINES);
        gl.glVertex3d(0.0, 0.0, 0.0);
        gl.glVertex3d(0.7, 0, 0);
        gl.glEnd();

        gl.glLineWidth(3.5f);
        gl.glColor3d(0.0, 1.0, 0.0);
        gl.glBegin(GL_LINES);
        gl.glVertex3d(0.0, 0.0, 0.0);
        gl.glVertex3d(0, 0.7, 0);
        gl.glEnd();

        gl.glLineWidth(3.5f);
        gl.glColor3d(0.0, 0.0, 1.0);
        gl.glBegin(GL_LINES);
        gl.glVertex3d(0.0, 0.0, 0.0);
        gl.glVertex3d(0, 0, 0.7);
        gl.glEnd();
        
        gl.glLineWidth(1f);
    }

    /**
     * Called back before the OpenGL context is destroyed. Release resource such
     * as buffers.
     */
    @Override
    public void dispose(GLAutoDrawable drawable) {
    }
}
