Package fcagnin.jgltut.tut08

Source Code of fcagnin.jgltut.tut08.Interpolation$Orientation$Animation

package fcagnin.jgltut.tut08;

import fcagnin.jglsdk.glm.Glm;
import fcagnin.jglsdk.glm.Mat4;
import fcagnin.jglsdk.glm.Quaternion;
import fcagnin.jglsdk.glm.Vec4;
import fcagnin.jglsdk.glutil.MatrixStack;
import fcagnin.jgltut.LWJGLWindow;
import fcagnin.jgltut.framework.Framework;
import fcagnin.jgltut.framework.Mesh;
import fcagnin.jgltut.framework.Timer;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;

import java.nio.FloatBuffer;
import java.util.ArrayList;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;


/**
* Visit https://github.com/integeruser/jgltut for info, updates and license terms.
* <p/>
* Part II. Positioning
* Chapter 8. Getting Oriented
* http://www.arcsynthesis.org/gltut/Positioning/Tutorial%2008.html
* <p/>
* SPACE            - toggles between regular linear interpolation and slerp.
* Q,W,E,R,T,Y,U    - cause the ship to interpolate to a new orientation.
*
* @author integeruser
*/
public class Interpolation extends LWJGLWindow {
    public static void main(String[] args) {
        Framework.CURRENT_TUTORIAL_DATAPATH = "/fcagnin/jgltut/tut08/data/";

        new Interpolation().start();
    }


    @Override
    protected void init() {
        initializeProgram();

        try {
            ship = new Mesh( "Ship.xml" );
        } catch ( Exception exception ) {
            exception.printStackTrace();
            System.exit( -1 );
        }

        glEnable( GL_CULL_FACE );
        glCullFace( GL_BACK );
        glFrontFace( GL_CW );

        glEnable( GL_DEPTH_TEST );
        glDepthMask( true );
        glDepthFunc( GL_LEQUAL );
        glDepthRange( 0.0f, 1.0f );
    }

    @Override
    protected void display() {
        orient.updateTime();

        glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
        glClearDepth( 1.0f );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        MatrixStack currMatrix = new MatrixStack();
        currMatrix.translate( 0.0f, 0.0f, -200.0f );
        currMatrix.applyMatrix( Glm.matCast( orient.getOrient() ) );

        glUseProgram( theProgram );

        currMatrix.scale( 3.0f, 3.0f, 3.0f );
        currMatrix.rotateX( -90.0f );

        // Set the base color for this object.
        glUniform4f( baseColorUnif, 1.0f, 1.0f, 1.0f, 1.0f );
        glUniformMatrix4( modelToCameraMatrixUnif, false, currMatrix.top().fillAndFlipBuffer( mat4Buffer ) );

        ship.render( "tint" );

        glUseProgram( 0 );
    }

    @Override
    protected void reshape(int w, int h) {
        cameraToClipMatrix.set( 0, 0, frustumScale * (h / (float) w) );
        cameraToClipMatrix.set( 1, 1, frustumScale );

        glUseProgram( theProgram );
        glUniformMatrix4( cameraToClipMatrixUnif, false, cameraToClipMatrix.fillAndFlipBuffer( mat4Buffer ) );
        glUseProgram( 0 );

        glViewport( 0, 0, w, h );
    }

    @Override
    protected void update() {
        while ( Keyboard.next() ) {
            if ( Keyboard.getEventKeyState() ) {
                for ( int orientIndex = 0; orientIndex < orientKeys.length; orientIndex++ ) {
                    if ( Keyboard.getEventKey() == orientKeys[orientIndex] ) {
                        applyOrientation( orientIndex );
                        break;
                    }
                }

                switch ( Keyboard.getEventKey() ) {
                    case Keyboard.KEY_SPACE:
                        boolean slerp = orient.toggleSlerp();
                        System.out.printf( slerp ? "Slerp\n" : "Lerp\n" );
                        break;

                    case Keyboard.KEY_ESCAPE:
                        leaveMainLoop();
                        break;
                }
            }
        }
    }


    ////////////////////////////////
    private int theProgram;

    private int modelToCameraMatrixUnif;
    private int cameraToClipMatrixUnif;
    private int baseColorUnif;

    private Mat4 cameraToClipMatrix = new Mat4( 0.0f );
    private FloatBuffer mat4Buffer = BufferUtils.createFloatBuffer( Mat4.SIZE );

    private final float frustumScale = calcFrustumScale( 20.0f );


    private void initializeProgram() {
        ArrayList<Integer> shaderList = new ArrayList<>();
        shaderList.add( Framework.loadShader( GL_VERTEX_SHADER, "PosColorLocalTransform.vert" ) );
        shaderList.add( Framework.loadShader( GL_FRAGMENT_SHADER, "ColorMultUniform.frag" ) );

        theProgram = Framework.createProgram( shaderList );

        modelToCameraMatrixUnif = glGetUniformLocation( theProgram, "modelToCameraMatrix" );
        cameraToClipMatrixUnif = glGetUniformLocation( theProgram, "cameraToClipMatrix" );
        baseColorUnif = glGetUniformLocation( theProgram, "baseColor" );

        float zNear = 1.0f;
        float zFar = 600.0f;

        cameraToClipMatrix.set( 0, 0, frustumScale );
        cameraToClipMatrix.set( 1, 1, frustumScale );
        cameraToClipMatrix.set( 2, 2, (zFar + zNear) / (zNear - zFar) );
        cameraToClipMatrix.set( 2, 3, -1.0f );
        cameraToClipMatrix.set( 3, 2, (2 * zFar * zNear) / (zNear - zFar) );

        glUseProgram( theProgram );
        glUniformMatrix4( cameraToClipMatrixUnif, false, cameraToClipMatrix.fillAndFlipBuffer( mat4Buffer ) );
        glUseProgram( 0 );
    }


    private float calcFrustumScale(float fovDeg) {
        final float degToRad = 3.14159f * 2.0f / 360.0f;
        float fovRad = fovDeg * degToRad;
        return (float) (1.0f / Math.tan( fovRad / 2.0f ));
    }


    ////////////////////////////////
    private Mesh ship;

    private Quaternion orients[] = {
            new Quaternion( 0.7071f, 0.7071f, 0.0f, 0.0f ),
            new Quaternion( 0.5f, 0.5f, -0.5f, 0.5f ),
            new Quaternion( -0.4895f, -0.7892f, -0.3700f, -0.02514f ),
            new Quaternion( 0.4895f, 0.7892f, 0.3700f, 0.02514f ),

            new Quaternion( 0.3840f, -0.1591f, -0.7991f, -0.4344f ),
            new Quaternion( 0.5537f, 0.5208f, 0.6483f, 0.0410f ),
            new Quaternion( 0.0f, 0.0f, 1.0f, 0.0f )
    };

    private int orientKeys[] = {
            Keyboard.KEY_Q,
            Keyboard.KEY_W,
            Keyboard.KEY_E,
            Keyboard.KEY_R,

            Keyboard.KEY_T,
            Keyboard.KEY_Y,
            Keyboard.KEY_U
    };

    private Orientation orient = new Orientation();

    private class Orientation {
        boolean isAnimating;
        boolean slerp;
        int currOrientIndex;

        Animation anim = new Animation();

        class Animation {
            int finalOrientIndex;
            Timer currTimer;


            boolean updateTime() {
                return currTimer.update( getElapsedTime() );
            }

            void startAnimation(int destinationIndex, float duration) {
                finalOrientIndex = destinationIndex;
                currTimer = new Timer( Timer.Type.SINGLE, duration );
            }


            Quaternion getOrient(Quaternion initial, boolean slerp) {
                if ( slerp ) {
                    return slerp( initial, orients[finalOrientIndex], currTimer.getAlpha() );
                } else {
                    return lerp( initial, orients[finalOrientIndex], currTimer.getAlpha() );
                }
            }

            int getFinalIndex() {
                return finalOrientIndex;
            }
        }


        void updateTime() {
            if ( isAnimating ) {
                boolean isFinished = anim.updateTime();
                if ( isFinished ) {
                    isAnimating = false;
                    currOrientIndex = anim.getFinalIndex();
                }
            }
        }

        void animateToOrient(int destinationIndex) {
            if ( currOrientIndex == destinationIndex ) { return; }

            anim.startAnimation( destinationIndex, 1.0f );
            isAnimating = true;
        }


        boolean toggleSlerp() {
            slerp = !slerp;
            return slerp;
        }

        Quaternion getOrient() {
            if ( isAnimating ) {
                return anim.getOrient( orients[currOrientIndex], slerp );
            } else {
                return orients[currOrientIndex];
            }
        }

        boolean isAnimating() {
            return isAnimating;
        }
    }


    private void applyOrientation(int orientationIndex) {
        if ( !orient.isAnimating() ) {
            orient.animateToOrient( orientationIndex );
        }
    }


    private Quaternion slerp(Quaternion v0, Quaternion v1, float alpha) {
        float dot = Glm.dot( v0, v1 );

        final float DOT_THRESHOLD = 0.9995f;
        if ( dot > DOT_THRESHOLD ) {
            return lerp( v0, v1, alpha );
        }

        Glm.clamp( dot, -1.0f, 1.0f );
        float theta_0 = (float) Math.acos( dot );
        float theta = theta_0 * alpha;

        Quaternion v2 = Quaternion.add( v1, Quaternion.negate( Quaternion.scale( v0, dot ) ) );
        v2 = Glm.normalize( v2 );

        return Quaternion.add( Quaternion.scale( v0, (float) Math.cos( theta ) ),
                Quaternion.scale( v2, (float) Math.sin( theta ) ) );
    }

    private Quaternion lerp(Quaternion v0, Quaternion v1, float alpha) {
        Vec4 start = vectorize( v0 );
        Vec4 end = vectorize( v1 );
        Vec4 interp = Glm.mix( start, end, alpha );

        System.out.printf( "alpha: %f, (%f, %f, %f, %f)\n", alpha, interp.w, interp.x, interp.y, interp.z );

        interp = Glm.normalize( interp );
        return new Quaternion( interp.w, interp.x, interp.y, interp.z );
    }

    private Vec4 vectorize(Quaternion theQuat) {
        Vec4 vec = new Vec4();
        vec.x = theQuat.x;
        vec.y = theQuat.y;
        vec.z = theQuat.z;
        vec.w = theQuat.w;
        return vec;
    }
}
TOP

Related Classes of fcagnin.jgltut.tut08.Interpolation$Orientation$Animation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.