// Path: src/integeruser/jgltut/commons/LightBlock.java
// public class LightBlock implements Bufferable {
//     public static final int MAX_NUMBER_OF_LIGHTS = 5;
//     public static final int BYTES = Float.BYTES * (4 + 1 + 1 + 2) + PerLight.BYTES * MAX_NUMBER_OF_LIGHTS;
// 
//     public Vector4f ambientIntensity;
//     public float lightAttenuation;
//     public float maxIntensity;
//     public float padding[] = new float[2];
//     public PerLight lights[] = new PerLight[MAX_NUMBER_OF_LIGHTS];
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         ambientIntensity.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         buffer.putFloat(lightAttenuation);
// 
//         buffer.putFloat(maxIntensity);
// 
//         buffer.putFloat(padding[0]);
//         buffer.putFloat(padding[1]);
// 
//         for (PerLight light : lights) {
//             if (light == null) break;
//             light.get(buffer);
//         }
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/MaterialBlock.java
// public class MaterialBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (4 + 4 + 1 + 3);
// 
//     public Vector4f diffuseColor;
//     public Vector4f specularColor;
//     public float specularShininess;
//     public float padding[] = new float[3];
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         diffuseColor.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         specularColor.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         buffer.putFloat(specularShininess);
// 
//         buffer.putFloat(padding[0]);
//         buffer.putFloat(padding[1]);
//         buffer.putFloat(padding[2]);
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/ProjectionBlock.java
// public class ProjectionBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (16);
// 
//     public Matrix4f cameraToClipMatrix;
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         cameraToClipMatrix.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 16);
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/UnprojectionBlock.java
// public class UnprojectionBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (16) + Integer.BYTES * (2);
// 
//     public Matrix4f clipToCameraMatrix;
//     public Vector2i windowSize;
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         clipToCameraMatrix.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 16);
// 
//         windowSize.get(buffer);
//         buffer.position(buffer.position() + Integer.BYTES * 2);
//         return buffer;
//     }
// }


import integeruser.jgltut.commons.LightBlock;
import integeruser.jgltut.commons.MaterialBlock;
import integeruser.jgltut.commons.ProjectionBlock;
import integeruser.jgltut.commons.UnprojectionBlock;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.Platform;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
package integeruser.jgltut;





/**
 * Visit https://github.com/integeruser/jgltut for info and updates.
 */
public abstract class Tutorial {
    protected long window;

    protected DoubleBuffer mouseBuffer1 = BufferUtils.createDoubleBuffer(1);
    protected DoubleBuffer mouseBuffer2 = BufferUtils.createDoubleBuffer(1);

    // Measured in seconds
    protected float elapsedTime;
    protected float lastFrameDuration;

    private double lastFrameTimestamp;

    protected FloatBuffer vec4Buffer = BufferUtils.createFloatBuffer(4);
    protected FloatBuffer mat3Buffer = BufferUtils.createFloatBuffer(9);
    protected FloatBuffer mat4Buffer = BufferUtils.createFloatBuffer(16);
// Path: src/integeruser/jgltut/commons/LightBlock.java
// public class LightBlock implements Bufferable {
//     public static final int MAX_NUMBER_OF_LIGHTS = 5;
//     public static final int BYTES = Float.BYTES * (4 + 1 + 1 + 2) + PerLight.BYTES * MAX_NUMBER_OF_LIGHTS;
// 
//     public Vector4f ambientIntensity;
//     public float lightAttenuation;
//     public float maxIntensity;
//     public float padding[] = new float[2];
//     public PerLight lights[] = new PerLight[MAX_NUMBER_OF_LIGHTS];
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         ambientIntensity.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         buffer.putFloat(lightAttenuation);
// 
//         buffer.putFloat(maxIntensity);
// 
//         buffer.putFloat(padding[0]);
//         buffer.putFloat(padding[1]);
// 
//         for (PerLight light : lights) {
//             if (light == null) break;
//             light.get(buffer);
//         }
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/MaterialBlock.java
// public class MaterialBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (4 + 4 + 1 + 3);
// 
//     public Vector4f diffuseColor;
//     public Vector4f specularColor;
//     public float specularShininess;
//     public float padding[] = new float[3];
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         diffuseColor.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         specularColor.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 4);
// 
//         buffer.putFloat(specularShininess);
// 
//         buffer.putFloat(padding[0]);
//         buffer.putFloat(padding[1]);
//         buffer.putFloat(padding[2]);
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/ProjectionBlock.java
// public class ProjectionBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (16);
// 
//     public Matrix4f cameraToClipMatrix;
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         cameraToClipMatrix.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 16);
//         return buffer;
//     }
// }
// 
// Path: src/integeruser/jgltut/commons/UnprojectionBlock.java
// public class UnprojectionBlock implements Bufferable {
//     public static final int BYTES = Float.BYTES * (16) + Integer.BYTES * (2);
// 
//     public Matrix4f clipToCameraMatrix;
//     public Vector2i windowSize;
// 
//     @Override
//     public ByteBuffer get(ByteBuffer buffer) {
//         clipToCameraMatrix.get(buffer);
//         buffer.position(buffer.position() + Float.BYTES * 16);
// 
//         windowSize.get(buffer);
//         buffer.position(buffer.position() + Integer.BYTES * 2);
//         return buffer;
//     }
// }


// Path: src/integeruser/jgltut/Tutorial.java
import integeruser.jgltut.commons.LightBlock;
import integeruser.jgltut.commons.MaterialBlock;
import integeruser.jgltut.commons.ProjectionBlock;
import integeruser.jgltut.commons.UnprojectionBlock;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.Platform;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;

package integeruser.jgltut;





/**
 * Visit https://github.com/integeruser/jgltut for info and updates.
 */
public abstract class Tutorial {
    protected long window;

    protected DoubleBuffer mouseBuffer1 = BufferUtils.createDoubleBuffer(1);
    protected DoubleBuffer mouseBuffer2 = BufferUtils.createDoubleBuffer(1);

    // Measured in seconds
    protected float elapsedTime;
    protected float lastFrameDuration;

    private double lastFrameTimestamp;

    protected FloatBuffer vec4Buffer = BufferUtils.createFloatBuffer(4);
    protected FloatBuffer mat3Buffer = BufferUtils.createFloatBuffer(9);
    protected FloatBuffer mat4Buffer = BufferUtils.createFloatBuffer(16);
    protected ByteBuffer projectionBlockBuffer = BufferUtils.createByteBuffer(ProjectionBlock.BYTES);