Java tutorial
/* * Copyright 2016 Nathan Howard * * This file is part of OpenGrave * * OpenGrave is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGrave is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGrave. If not, see <http://www.gnu.org/licenses/>. */ package com.opengrave.og; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.nio.FloatBuffer; import java.security.KeyManagementException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import javax.net.ssl.*; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GLUtil; import com.opengrave.common.DebugExceptionHandler; import com.opengrave.common.world.Material; import com.opengrave.common.world.MaterialList; import com.opengrave.og.engine.Camera; import com.opengrave.og.engine.Location; import com.opengrave.og.engine.RenderView; import com.opengrave.og.resources.RenderStyle; import com.opengrave.og.util.Matrix3f; import com.opengrave.og.util.Matrix4f; import com.opengrave.og.util.Vector3f; import com.opengrave.og.util.Vector4f; public class Util { public static float nearZ = .1f, farZ = 50f; // , fov = 60f; public static Matrix4f shadowBiasMatrix; // public static Matrix4f projectionMatrix; // Window to 3D Perspective public static Matrix4f guiMatrix; // Window to 2D Gui // public static Matrix4f viewMatrix; // Perspective to World co-rds public static FloatBuffer matrix44Buffer; public static FloatBuffer matrix33Buffer; private final static double PI = 3.14159265358979323846; public static void initMatrices() { shadowBiasMatrix = new Matrix4f(); Vector3f translate = new Vector3f(0.5f, 0.5f, 0.5f); shadowBiasMatrix.translate(translate, shadowBiasMatrix); shadowBiasMatrix.scale(translate, shadowBiasMatrix); System.out.println(shadowBiasMatrix); // update3DProjection(); update2DProjection(); // viewMatrix = new Matrix4f(); matrix44Buffer = BufferUtils.createFloatBuffer(16); matrix33Buffer = BufferUtils.createFloatBuffer(9); } // public static void updateMatrices() { // update3DProjection(); // update2DProjection(); // } // private static void update3DProjection() { // float fov = 40f; // projectionMatrix = proj(fov, Display.getWidth(), Display.getHeight(), // nearZ, farZ); // } public static void update2DProjection() { guiMatrix = new Matrix4f(); float x_max = MainThread.lastW - 1f; float y_max = MainThread.lastH - 1f; float x_min = 0f; float y_min = 0f; float left = x_min, right = x_max, top = y_min, bottom = y_max; float zFar = 200f, zNear = -0.1f; guiMatrix.set(0, 0, 2f / (right - left)); guiMatrix.set(1, 1, 2f / (top - bottom)); guiMatrix.set(2, 2, -2f / (zFar - zNear)); guiMatrix.set(3, 3, 1f); guiMatrix.set(3, 2, -((zFar + zNear) / (zFar - zNear))); guiMatrix.set(3, 1, -((top + bottom) / (top - bottom))); guiMatrix.set(3, 0, -((right + left) / (right - left))); guiMatrix.translate(new Vector3f(0.35f, 0.35f, 0f), guiMatrix); // Deal with pixel // perfection on // location } public static float degreesToRadians(float f) { return f * (float) (PI / 180d); } public static Matrix4f lookDir(Vector3f eye, Vector3f direction, Vector3f up) { eye.add(direction, eye); Matrix4f mat1 = Matrix4f.lookAt(eye, eye, up); return mat1; } public static void setUniformMat44(int pID, String string, Matrix4f matrix) { matrix.store(matrix44Buffer); matrix44Buffer.flip(); setUniformMat44(pID, string, matrix44Buffer); } public static void setUniformMat33(int pID, String string, Matrix3f matrix) { matrix.store(matrix33Buffer); matrix33Buffer.flip(); setUniformMat33(pID, string, matrix33Buffer); } public static void setUniformMat44(int pID, String string, FloatBuffer matrix44) { // System.out.println("Program "+pID); Util.checkErr(); int i = GL20.glGetUniformLocation(pID, string); Util.checkErr(); if (i == -1) { // System.out.println("Cannot find uniform '"+string+"'"); // Thread.dumpStack(); } else { GL20.glUniformMatrix4fv(i, false, matrix44); Util.checkErr(); } } public static void setUniformMat33(int pID, String string, FloatBuffer matrix33) { // System.out.println("Program "+pID); Util.checkErr(); int i = GL20.glGetUniformLocation(pID, string); Util.checkErr(); if (i == -1) { // System.out.println("Cannot find uniform '"+string+"'"); // Thread.dumpStack(); } else { GL20.glUniformMatrix3fv(i, false, matrix33); Util.checkErr(); } } public static void setUniform(int pID, String string, Vector4f color) { // System.out.println("Program "+pID); Util.checkErr(); int i = GL20.glGetUniformLocation(pID, string); Util.checkErr(); if (i == -1) { // System.out.println("Cannot find uniform '"+string+"'"); // Thread.dumpStack(); } else { GL20.glUniform4f(i, color.x, color.y, color.z, color.w); Util.checkErr(); } } /** * Used for 2D "HUD" Renderables * * @param pID * @param location * @param scale * @param rotate */ public static void setMatrices(int pID, Vector3f location) { Util.checkErr(); GL20.glUseProgram(pID); Matrix4f modelView = new Matrix4f(); modelView.translate(location, modelView); // Matrix4f.scale(location.getScale(), modelView, modelView); // Matrix4f.rotate(degreesToRadians(rotate.z), new Vector3f(0, 0, 1), // modelView, modelView); // Matrix4f.rotate(degreesToRadians(rotate.y), new Vector3f(0, 1, 0), // modelView, modelView); // Matrix4f.rotate(degreesToRadians(rotate.x), new Vector3f(1, 0, 0), // modelView, modelView); Util.checkErr(); guiMatrix.store(matrix44Buffer); matrix44Buffer.flip(); setUniformMat44(pID, "guiMatrix", matrix44Buffer); // projectionMatrix.store(matrix44Buffer); matrix44Buffer.flip(); // setUniform(pID, "projectionMatrix", matrix44Buffer); // viewMatrix.store(matrix44Buffer); matrix44Buffer.flip(); // setUniform(pID, "viewMatrix", matrix44Buffer); modelView.store(matrix44Buffer); matrix44Buffer.flip(); setUniformMat44(pID, "modelMatrix", matrix44Buffer); Util.checkErr(); } public static Matrix4f createMatrixFor(Location location, Matrix4f parent, Matrix4f inside, RenderView context) { Camera cam = null; if (context != null) { cam = context.getCam(); } Vector3f loc = location.toVector3(); if (cam != null) { loc = location.minus(cam.getLocation()); } Matrix4f modelView = new Matrix4f(); // Translate to world co-ords first modelView.translate(loc, modelView); // Then scale/rotate modelView.scale(location.getScale(), modelView); modelView.rotate(degreesToRadians(location.getRotate().z), new Vector3f(0, 0, 1), modelView); modelView.rotate(degreesToRadians(location.getRotate().y), new Vector3f(0, 1, 0), modelView); modelView.rotate(degreesToRadians(location.getRotate().x), new Vector3f(1, 0, 0), modelView); if (parent != null) { // Matrix4f.mul(modelView, parent, modelView); parent.mult(modelView, modelView); // TODO Check Mult ordering. } if (inside != null) { inside.mult(modelView, modelView); } return modelView; } // public static void setMatrices(int pID, Matrix4f parent, Location // location) { // GL20.glUseProgram(pID); // Matrix4f modelView = createMatrixFor(location, parent, null); // modelView.store(matrix44Buffer); // matrix44Buffer.flip(); // setUniformMat44(pID, "M", matrix44Buffer); // Matrix4f MV = Matrix4f.mul(viewMatrix, modelView, null); // MV.store(matrix44Buffer); // matrix44Buffer.flip(); // setUniformMat44(pID, "MV", matrix44Buffer); // Matrix4f MVP = Matrix4f.mul(projectionMatrix, MV, null); // MVP.store(matrix44Buffer); // matrix44Buffer.flip(); // setUniformMat44(pID, "MVP", matrix44Buffer); // if (HGMainThread.config.getBoolean("shadows", true)) { // Matrix4f shadowBMVP = Matrix4f.mul(shadowBiasMatrix, // HGMainThread.main.skyLight.getMVP(modelView), null); // shadowBMVP.store(matrix44Buffer); // matrix44Buffer.flip(); // setUniformMat44(pID, "shadowBMVP", matrix44Buffer); // } // } public static void checkErr(boolean b) { if (!b) { // Throw it away! GL11.glGetError(); } else { checkErr(); } } public static void checkErr() { int errorValue = GL11.glGetError(); if (errorValue != GL11.GL_NO_ERROR) { String err = GLUtil.getErrorString(errorValue); Thread.dumpStack(); System.out.println(err); } } public static String getDigest(String dataFile) { MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { new DebugExceptionHandler(e); } FileInputStream fis = null; try { fis = new FileInputStream(dataFile); } catch (FileNotFoundException e) { return "0"; } byte[] dataBytes = new byte[1024]; int nread = 0; try { while ((nread = fis.read(dataBytes)) != -1) { md.update(dataBytes, 0, nread); } } catch (IOException e) { new DebugExceptionHandler(e, dataFile); } byte[] mdbytes = md.digest(); // convert the byte to hex format StringBuffer sb = new StringBuffer(""); for (int i = 0; i < mdbytes.length; i++) { sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); } try { fis.close(); } catch (IOException e) { new DebugExceptionHandler(e); } return sb.toString(); } public static void downloadAndSave(File cache, String url, String local) { File f = new File(cache, local); File parent = f.getParentFile(); if (parent != null) { parent.mkdirs(); } System.out.println(cache + " " + url); byte[] buffer = new byte[8 * 1024]; InputStream input = null; OutputStream output = null; try { HttpsURLConnection conn = openConnection(url); input = conn.getInputStream(); output = new FileOutputStream(new File(cache, local).getAbsolutePath()); int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); } } catch (FileNotFoundException e) { new DebugExceptionHandler(e, url, local); } catch (MalformedURLException e) { new DebugExceptionHandler(e, url, local); } catch (IOException e) { new DebugExceptionHandler(e, url, local); } finally { try { if (output != null) { output.close(); } if (input != null) { input.close(); } } catch (IOException e) { new DebugExceptionHandler(e, url, local); } } } public static HttpsURLConnection openConnection(String urlS) { if (sslSocketFactory == null) { prepSSL(); } HttpsURLConnection conn = null; try { URL url = new URL(urlS); conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(sslSocketFactory); } catch (IOException e) { new DebugExceptionHandler(e, urlS); } return conn; } public static void prepSSL() { try { final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(final X509Certificate[] chain, final String authType) { } @Override public void checkServerTrusted(final X509Certificate[] chain, final String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } } }; sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); sslSocketFactory = sslContext.getSocketFactory(); } catch (NoSuchAlgorithmException e) { new DebugExceptionHandler(e); } catch (KeyManagementException e) { new DebugExceptionHandler(e); } } private static SSLContext sslContext; private static SSLSocketFactory sslSocketFactory; private static boolean debug; public static void loadMaterials(MaterialList matList, int pID) { int i = 0; for (Material m : matList.all()) { int locCol1 = GL20.glGetUniformLocation(pID, "material[" + i + "].colour"); int locTex = GL20.glGetUniformLocation(pID, "material[" + i + "].textureindex"); int locDTex = GL20.glGetUniformLocation(pID, "material[" + i + "].texturedataindex"); /* * if (locCol == -1) { throw new * RuntimeException("No Material Colour location"); } if (locTex == * -1) { throw new RuntimeException("No Material Texture location"); * } */ GL20.glUniform4f(locCol1, m.getColour().x, m.getColour().y, m.getColour().z, m.getColour().w); GL20.glUniform1f(locTex, (float) m.getTextureIndex()); GL20.glUniform1f(locDTex, (float) m.getTextureDataIndex()); i++; } } public static void setRenderStyle(int pID, RenderStyle style) { int i = 0; if (style == RenderStyle.GRAYSCALE) { i = 1; } else if (style == RenderStyle.SEPIA) { i = 2; } else if (style == RenderStyle.HALO) { i = 3; } GL20.glUniform1i(GL20.glGetUniformLocation(pID, "renderStyle"), i); } public static void toggleDebug() { debug = !debug; if (debug) { MainThread.showDebugWindow(true); } else { MainThread.showDebugWindow(false); } } public static Vector4f unproject(int x, int y, float z, Matrix4f viewM, Matrix4f projM, int totalx, int totaly, int width, int height) { Matrix4f finalM = viewM.mult(projM, null); Vector4f in = new Vector4f(x, y, z, 1f); finalM.inverse(finalM); in.x = (in.x - totalx) / width; in.y = (in.y - totaly) / height; in.x = in.x * 2 - 1; in.y = in.y * 2 - 1; in.z = in.z * 2 - 1; Vector4f out = finalM.mult4(in, null); if (out.w == 0) { return null; } out.x /= out.w; out.y /= out.w; out.z /= out.w; out.w = 1f; return out; } }