commit e0dbc755aadb94722ea53ebbbfaf75ed68872fa6 Author: austin Date: Mon Mar 15 01:01:42 2021 -0400 First commit diff --git a/nbactions.xml b/nbactions.xml new file mode 100644 index 00000000..63a0e016 --- /dev/null +++ b/nbactions.xml @@ -0,0 +1,17 @@ + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + -classpath %classpath main.Main + java + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..659f1d70 --- /dev/null +++ b/pom.xml @@ -0,0 +1,149 @@ + + + 4.0.0 + orbitalstudio + InfiniteStratos + 0.1 + jar + + UTF-8 + 11 + 11 + 3.2.3 + 1.9.19 + + + + + org.lwjgl + lwjgl + ${lwjgl.version} + + + org.lwjgl + lwjgl-assimp + ${lwjgl.version} + + + org.lwjgl + lwjgl-glfw + ${lwjgl.version} + + + org.lwjgl + lwjgl-opengl + ${lwjgl.version} + + + org.lwjgl + lwjgl-opengles + ${lwjgl.version} + + + org.lwjgl + lwjgl + ${lwjgl.version} + ${lwjgl.natives} + runtime + + + org.lwjgl + lwjgl-assimp + ${lwjgl.version} + ${lwjgl.natives} + runtime + + + org.lwjgl + lwjgl-glfw + ${lwjgl.version} + ${lwjgl.natives} + runtime + + + org.lwjgl + lwjgl-opengl + ${lwjgl.version} + ${lwjgl.natives} + runtime + + + org.lwjgl + lwjgl-opengles + ${lwjgl.version} + ${lwjgl.natives} + runtime + + + org.joml + joml + ${joml.version} + + + com.google.code.gson + gson + 2.8.6 + + + + + + lwjgl-natives-linux + + + unix + + + + natives-linux + + + + lwjgl-natives-macos + + + mac + + + + natives-macos + + + + lwjgl-natives-windows + + + windows + + + + natives-windows + + + + + + + ${basedir}/src/main/resources + + **/* + + + + + + maven-assembly-plugin + + + + main.Main + + + + jar-with-dependencies + + + + + + \ No newline at end of file diff --git a/src/main/java/RendererObjects/AnimChannel.java b/src/main/java/RendererObjects/AnimChannel.java new file mode 100644 index 00000000..74322414 --- /dev/null +++ b/src/main/java/RendererObjects/AnimChannel.java @@ -0,0 +1,184 @@ +package RendererObjects; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.ListIterator; +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class AnimChannel { + double timeCurrent; + double timeTotal; + public String nodeID; + + + public Vector3f startingPosition; + public ArrayList positionFrame; + public ListIterator positionFrameIterator; + Keyframe positionFrameCurrent; + Keyframe positionFrameNext; + double nextPositionTime; + + + public Quaternionf startingRotation; + public ArrayList rotationFrame; + public ListIterator rotationFrameIterator; + Keyframe rotationFrameCurrent; + Keyframe rotationFrameNext; + double nextRotationTime; + + + public ArrayList scaleFrame; + public ListIterator scaleFrameIterator; + Keyframe scaleFrameCurrent; + Keyframe scaleFrameNext; + double nextScaleTime; + + + public AnimChannel(double maxTime){ + timeTotal = maxTime; + } + + public Vector3f getCurrentPosition(){ + Vector3f rVal = new Vector3f(); + if(positionFrameCurrent != null){ + if(positionFrameNext != null){ + double percent_Next = ((timeCurrent - positionFrameCurrent.time) / (positionFrameNext.time - positionFrameCurrent.time)); + rVal = new Vector3f().add(new Vector3f().add(positionFrameCurrent.position).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(positionFrameNext.position).mul((float)(percent_Next))); + } else { + rVal = new Vector3f().add(positionFrameCurrent.position); + } +// rVal.add(new Vector3f().add(positionFrameCurrent.position).mul(()/(positionFrameNext.time - positionFrameCurrent.time))); + } +// rVal = rVal.sub(startingPosition); + return rVal; + } + + public Quaternionf getCurrentRotation(){ + Quaternionf rVal = new Quaternionf(); + if(rotationFrameCurrent != null){ + if(rotationFrameNext != null){ + double percent_Next = ((timeCurrent - rotationFrameCurrent.time) / (rotationFrameNext.time - rotationFrameCurrent.time)); +// rVal = new Quaternionf(rotationFrameCurrent.rotation).normalize();//.add(rotationFrameCurrent.rotation); + rVal = new Quaternionf(rotationFrameCurrent.rotation).slerp(rotationFrameNext.rotation, (float)percent_Next); +// rVal = new Quaternionf(rotationFrameCurrent.rotation).normalize().slerp(new Quaternionf(rotationFrameNext.rotation).normalize(), (float)(percent_Next)).rotateAxis((float)(-Math.PI/2), new Vector3f(1,0,0)); + } else { + rVal = new Quaternionf(rotationFrameCurrent.rotation);//.add(rotationFrameCurrent.rotation); + } + } +// rVal = rVal.mul(new Quaternionf(startingRotation).invert()); + return rVal; + } + + public Vector3f getCurrentScale(){ + Vector3f rVal = new Vector3f(); + if(scaleFrameCurrent != null){ + if(scaleFrameNext != null){ + double percent_Next = ((timeCurrent - scaleFrameCurrent.time) / (scaleFrameNext.time - scaleFrameCurrent.time)); + rVal = new Vector3f().add(new Vector3f().add(scaleFrameCurrent.scale).mul((float)(1.0 - percent_Next))).add(new Vector3f().add(scaleFrameNext.scale).mul((float)(percent_Next))); + } else { + rVal = new Vector3f().add(scaleFrameCurrent.scale); + } +// rVal.add(new Vector3f().add(positionFrameCurrent.position).mul(()/(positionFrameNext.time - positionFrameCurrent.time))); + } + return rVal; + } + + public void incrementTime(double incrementValue){ + timeCurrent = timeCurrent + incrementValue; + while(positionFrameNext != null && timeCurrent > positionFrameNext.time){ + positionFrameCurrent = positionFrameNext; + if(positionFrameIterator.hasNext()){ + positionFrameNext = positionFrameIterator.next(); + } else { + positionFrameNext = null; + } + } + while(rotationFrameNext != null && timeCurrent > rotationFrameNext.time){ + rotationFrameCurrent = rotationFrameNext; + if(rotationFrameIterator.hasNext()){ + rotationFrameNext = rotationFrameIterator.next(); + } else { + rotationFrameNext = null; + } + } + while(scaleFrameNext != null && timeCurrent > scaleFrameNext.time){ + scaleFrameCurrent = scaleFrameNext; + if(scaleFrameIterator.hasNext()){ + scaleFrameNext = scaleFrameIterator.next(); + } else { + scaleFrameNext = null; + } + } + } + + public void rewind(){ + timeCurrent = 0; + + //TODO: Make sure has at least two frames + positionFrameIterator = positionFrame.listIterator(); + if(positionFrameIterator.hasNext()){ + positionFrameCurrent = positionFrameIterator.next(); + if(positionFrameIterator.hasNext()){ + positionFrameNext = positionFrameIterator.next(); + nextPositionTime = positionFrameNext.time; + } else { + positionFrameNext = null; + } + } + + rotationFrameIterator = rotationFrame.listIterator(); + if(rotationFrameIterator.hasNext()){ + rotationFrameCurrent = rotationFrameIterator.next(); + if(rotationFrameIterator.hasNext()){ + rotationFrameNext = rotationFrameIterator.next(); + } else { + rotationFrameNext = null; + } + } + + scaleFrameIterator = scaleFrame.listIterator(); + if(scaleFrameIterator.hasNext()){ + scaleFrameCurrent = scaleFrameIterator.next(); + if(scaleFrameIterator.hasNext()){ + scaleFrameNext = scaleFrameIterator.next(); + } else { + scaleFrameNext = null; + } + } + } + + public void describeChannel(){ + System.out.println("Target object: " + nodeID); + System.out.println("Time: " + timeCurrent + "/" + timeTotal); + System.out.println(positionFrame.size() + " position Frames"); + System.out.println(rotationFrame.size() + " rotation Frames"); + System.out.println(scaleFrame.size() + " scale Frames"); + } + + public void fullDescribeChannel(){ + System.out.println("Target object: " + nodeID); + System.out.println("Time: " + timeCurrent + "/" + timeTotal); + System.out.println(positionFrame.size() + " position Frames"); + Iterator frameIterator = positionFrame.iterator(); + while(frameIterator.hasNext()){ + System.out.println(frameIterator.next()); + } + System.out.println(rotationFrame.size() + " rotation Frames"); + frameIterator = rotationFrame.iterator(); + while(frameIterator.hasNext()){ + System.out.println(frameIterator.next()); + } + System.out.println(scaleFrame.size() + " scale Frames"); + frameIterator = scaleFrame.iterator(); + while(frameIterator.hasNext()){ + System.out.println(frameIterator.next()); + } + } + +} diff --git a/src/main/java/RendererObjects/AnimNode.java b/src/main/java/RendererObjects/AnimNode.java new file mode 100644 index 00000000..583261d6 --- /dev/null +++ b/src/main/java/RendererObjects/AnimNode.java @@ -0,0 +1,26 @@ +package RendererObjects; + +import java.util.ArrayList; +import org.joml.Matrix4f; +import org.lwjgl.assimp.AINode; + +/** + * + * @author amaterasu + */ +public class AnimNode { + public String id; + public Matrix4f transform; + public AnimNode parent; + public ArrayList children; + public boolean is_bone; + public AINode raw_data; + public AnimNode(String id, AnimNode parent, AINode raw_data){ + this.id = id; + this.parent = parent; + this.children = new ArrayList(); + this.transform = new Matrix4f(); + is_bone = false; + this.raw_data = raw_data; + } +} diff --git a/src/main/java/RendererObjects/Animation.java b/src/main/java/RendererObjects/Animation.java new file mode 100644 index 00000000..a8f4656e --- /dev/null +++ b/src/main/java/RendererObjects/Animation.java @@ -0,0 +1,249 @@ +package RendererObjects; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.PriorityQueue; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.lwjgl.PointerBuffer; +import org.lwjgl.assimp.AIAnimation; +import org.lwjgl.assimp.AIMeshAnim; +import org.lwjgl.assimp.AIMeshKey; +import org.lwjgl.assimp.AINodeAnim; +import org.lwjgl.assimp.AIQuatKey; +import org.lwjgl.assimp.AIVectorKey; + +/** + * + * @author satellite + */ +public class Animation { + AIAnimation animData; + public String name; + public int ID; + ArrayList nodeChannelData; + ArrayList meshChannelData; + public ArrayList channels; + public double duration = 0; + public double timeCurrent = 0; + public double ticksPerSecond; + public Animation(AIAnimation animData, int ID){ + // + //Read in metadata + // + this.animData = animData; + name = animData.mName().dataString(); + this.duration = animData.mDuration(); + this.ticksPerSecond = animData.mTicksPerSecond(); + this.ID = ID; + // + //Print metadata + // +// System.out.println("Animation name: \"" + name + "\""); +// System.out.println("ID:(" + ID + ")"); +// System.out.println("Ticks per second: " + ticksPerSecond); +// System.out.println("Anim sizeof: " + animData.sizeof()); +// System.out.println("Duration: " + duration); + // + //Read in anim channels (bone modifications) + // + int channelCount = animData.mNumChannels(); + channels = new ArrayList(); + if(channelCount > 0){ +// System.out.println("Channel count: " + channelCount); + for(int i = 0; i < channelCount; i++){ + AINodeAnim currentChannelData = AINodeAnim.create(animData.mChannels().get(i)); +// System.out.println("Channel[" + (i + 1) + "]: " + currentChannelData.mNodeName().dataString()); + + //Create channel + AnimChannel currentChannel = new AnimChannel(duration); + currentChannel.positionFrame = new ArrayList(); + currentChannel.rotationFrame = new ArrayList(); + currentChannel.scaleFrame = new ArrayList(); + currentChannel.nodeID = currentChannelData.mNodeName().dataString(); + channels.add(currentChannel); + + + //get channel data + + if(currentChannelData.mNumPositionKeys() > 0){ + org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mPositionKeys(); +// Iterator keyIterator = buff.iterator(); +// while (keyIterator.hasNext()) { +// AIVectorKey key = keyIterator.next(); +// Keyframe currentFrame = new Keyframe(key.mTime()); +// currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); +// currentChannel.positionFrame.add(currentFrame); +// } + if(buff != null && buff.hasRemaining()){ +// System.out.println("Position vectors: "); + AIVectorKey key = buff.get(); + Keyframe currentFrame = new Keyframe(key.mTime()); + currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + currentChannel.positionFrame.add(currentFrame); +// System.out.println(currentFrame.position); + currentChannel.startingPosition = currentFrame.position; + + Keyframe previousFrame; + while(buff.hasRemaining()){ + previousFrame = currentFrame; + key = buff.get(); + currentFrame = new Keyframe(key.mTime()); + currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); +// System.out.println(currentFrame.position); + //check if duplicate +// Keyframe previousFrame = currentChannel.positionFrame.get(currentChannel.positionFrame.size() - 1); + if( previousFrame.position.x == currentFrame.position.x && + previousFrame.position.y == currentFrame.position.y && + previousFrame.position.z == currentFrame.position.z + ){ + } else { + currentChannel.positionFrame.add(currentFrame); + } + } + } + } + + if(currentChannelData.mNumRotationKeys() > 0){ + org.lwjgl.assimp.AIQuatKey.Buffer buff = currentChannelData.mRotationKeys(); + if(buff != null && buff.hasRemaining()){ + AIQuatKey key = buff.get(); + Keyframe currentFrame = new Keyframe(key.mTime()); + currentFrame.rotation = new Quaternionf(); + currentFrame.rotation.set(key.mValue().x(), key.mValue().y(), key.mValue().z(), key.mValue().w()); +// currentFrame.rotation = new Quaternionf(key.mValue().x(),key.mValue().y(),key.mValue().z(),key.mValue().w()); + currentChannel.rotationFrame.add(currentFrame); + + currentChannel.startingRotation = currentFrame.rotation; + + Keyframe previousFrame; + while(buff.hasRemaining()){ + previousFrame = currentFrame; + key = buff.get(); + currentFrame = new Keyframe(key.mTime()); + currentFrame.rotation = new Quaternionf(); + currentFrame.rotation.set(key.mValue().x(), key.mValue().y(), key.mValue().z(), key.mValue().w()); +// currentFrame.rotation = new Quaternionf(key.mValue().x(),key.mValue().y(),key.mValue().z(),key.mValue().w()); + //check for duplicate +// Keyframe previousFrame = currentChannel.rotationFrame.get(currentChannel.rotationFrame.size() - 1); + if( previousFrame.rotation.w == currentFrame.rotation.w && + previousFrame.rotation.x == currentFrame.rotation.x && + previousFrame.rotation.y == currentFrame.rotation.y && + previousFrame.rotation.z == currentFrame.rotation.z + ){ + } else { + currentChannel.rotationFrame.add(currentFrame); + } + } + } +// Iterator keyIterator = buff.iterator(); +// while(keyIterator.hasNext()){ +// AIQuatKey key = keyIterator.next(); +// Keyframe currentFrame = new Keyframe(key.mTime()); +// currentFrame.rotation = new Quaternionf(key.mValue().w(),key.mValue().x(),key.mValue().y(),key.mValue().z()); +// currentChannel.rotationFrame.add(currentFrame); +// } + } + + if(currentChannelData.mNumScalingKeys() > 0){ + org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mScalingKeys(); +// Iterator keyIterator = buff.iterator(); +// while (keyIterator.hasNext()) { +// AIVectorKey key = keyIterator.next(); +// Keyframe currentFrame = new Keyframe(key.mTime()); +// currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); +// currentChannel.scaleFrame.add(currentFrame); +// } + if(buff != null && buff.hasRemaining()){ + AIVectorKey key = buff.get(); + Keyframe currentFrame = new Keyframe(key.mTime()); + currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + currentChannel.scaleFrame.add(currentFrame); + Keyframe previousFrame; + while(buff.hasRemaining()){ + previousFrame = currentFrame; + key = buff.get(); + currentFrame = new Keyframe(key.mTime()); + currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + if( currentFrame.scale.x == previousFrame.scale.x && + currentFrame.scale.y == previousFrame.scale.y && + currentFrame.scale.z == previousFrame.scale.z + ){ + } else { + currentChannel.scaleFrame.add(currentFrame); + } + } + } + } + + +// System.out.println("end times"); +// for(int j = 0; j < currentChannelData.mNumPositionKeys(); j++){ +// org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mPositionKeys(); +// Iterator keyIterator = buff.iterator(); +// AIVectorKey posKey = currentChannelData.mPositionKeys().get(i); +// Keyframe currentFrame = new Keyframe(posKey.mTime()); +// currentFrame.position = new Vector3f(posKey.mValue().x(),posKey.mValue().y(),posKey.mValue().z()); +// } +// for(int j = 0; j < currentChannelData.mNumRotationKeys(); j++){ +// AIQuatKey rotKey = currentChannelData.mRotationKeys().get(i); +// HashMap test = new HashMap(); +// System.out.println(new Quaternionf(rotKey.mValue().w(),rotKey.mValue().x(),rotKey.mValue().y(),rotKey.mValue().z())); +// } +// for(int j = 0; j < currentChannelData.mNumScalingKeys(); j++){ +// AIVectorKey scaleKey = currentChannelData.mScalingKeys().get(i); +//// scaleKey.mValue(). +// System.out.println(new Vector3f(scaleKey.mValue().x(),scaleKey.mValue().y(),scaleKey.mValue().z())); +// } + } + } +// int meshChannelCount = animData.mNumMeshChannels(); +// meshChannelData = new ArrayList(); +// if(meshChannelCount > 0){ +// for(int i = 0; i < meshChannelCount; i++){ +// AIMeshAnim test = AIMeshAnim.create(animData.mMeshChannels().get(i)); +// } +// } + //gotta free things + nodeChannelData = null; + meshChannelData = null; + } + public void describeAnimation(){ + System.out.println("====================="); + System.out.println("Name: \"" + name + "\""); + System.out.println("ID: " + ID); + System.out.println("Duration: " + duration); + System.out.println("Ticks per second: " + ticksPerSecond); + Iterator channelIterator = channels.iterator(); + while(channelIterator.hasNext()){ + AnimChannel channelCurrent = channelIterator.next(); + System.out.println("====================="); + channelCurrent.describeChannel(); + } + System.out.println("====================="); + } + public void fullDescribeAnimation(){ + System.out.println("====================="); + System.out.println("Name: " + name); + System.out.println("ID: " + ID); + System.out.println("Duration: " + duration); + System.out.println("Ticks per second: " + ticksPerSecond); + Iterator channelIterator = channels.iterator(); + while(channelIterator.hasNext()){ + AnimChannel channelCurrent = channelIterator.next(); + System.out.println("====================="); + channelCurrent.fullDescribeChannel(); + } + System.out.println("====================="); + } + + public boolean incrementTime(double time){ + timeCurrent += time; + if(timeCurrent > duration){ + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/RendererObjects/Bone.java b/src/main/java/RendererObjects/Bone.java new file mode 100644 index 00000000..a752dc97 --- /dev/null +++ b/src/main/java/RendererObjects/Bone.java @@ -0,0 +1,34 @@ +package RendererObjects; + +import java.util.ArrayList; +import java.util.HashMap; +import org.joml.Matrix4f; +import org.lwjgl.assimp.AIBone; + +/** + * + * @author satellite + */ +public class Bone { + public String boneID; + int numWeights; + HashMap weights; + public Matrix4f inverseBindPoseMatrix; + public Matrix4f deform; + public Matrix4f transform; + public Matrix4f final_transform; + public AIBone raw_data; + public Bone(){ + transform = new Matrix4f(); + deform = new Matrix4f(); + final_transform = new Matrix4f(); + } + public Bone(AIBone raw_data){ + transform = new Matrix4f(); + deform = new Matrix4f(); + final_transform = new Matrix4f(); + boneID = raw_data.mName().dataString(); + inverseBindPoseMatrix = util.util.convertAIMatrix(raw_data.mOffsetMatrix()); + this.raw_data = raw_data; + } +} diff --git a/src/main/java/RendererObjects/Camera.java b/src/main/java/RendererObjects/Camera.java new file mode 100644 index 00000000..a19aaff4 --- /dev/null +++ b/src/main/java/RendererObjects/Camera.java @@ -0,0 +1,39 @@ +package RendererObjects; + +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +/** + * + * @author satellite + */ +public class Camera { + public Vector3f pos_Center = new Vector3f(0,0,0); +// public Vector3f pos_Front = new Vector3f(0,0,0); +// public Vector3f pos_Top = new Vector3f(0,0,0); + public Quaternionf rotation = new Quaternionf(); + public Camera(){ + + } + + public void apply_camera(Camera c){ + pos_Center = new Vector3f(c.pos_Center); + rotation = new Quaternionf(c.rotation); + } + + public Matrix4f get_view_matrix(){ + Matrix4f rVal = new Matrix4f(); +// rVal.setLookAt(pos_Center, pos_Front, pos_Top); + Vector3f up = new Vector3f(pos_Center); + //new Vector3f(pos_Center).add(new Quaternionf(rotation)..transform(new Vector3f(1,0,0))) + Vector3f up_modifier = new Vector3f(1,0,0); + Quaternionf up_transformation = new Quaternionf(rotation); + up_transformation.rotateAxis((float)Math.PI/2.0f, new Vector3f(up).cross(new Vector3f(0,1,0))); // the hard part is getting the axis in this logic to correspond to the vertical + up = up.add(up_transformation.transform(up_modifier)); + rVal.setLookAt(pos_Center, //where our camera is + new Vector3f(pos_Center).add(rotation.transform(new Vector3f(1,0,0))), //where our camera wants to look + up); //where "up" is relative to our camera + return rVal; + } +} diff --git a/src/main/java/RendererObjects/Keyframe.java b/src/main/java/RendererObjects/Keyframe.java new file mode 100644 index 00000000..0b4ea360 --- /dev/null +++ b/src/main/java/RendererObjects/Keyframe.java @@ -0,0 +1,50 @@ +package RendererObjects; + +import org.joml.Quaternionf; +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class Keyframe implements Comparable{ + double time; + Vector3f position; + Quaternionf rotation; + Vector3f scale; + + public Keyframe(double time){ + this.time = time; + } + + @Override + public int compareTo(Object t) { + if(time > ((Keyframe)t).getTime()){ + return 1; + } else if(time < ((Keyframe)t).getTime()){ + return -1; + } else { + return 0; + } + } + + public double getTime(){ + return time; + } + + @Override + public String toString(){ + String rVal = ""; + rVal = rVal + "[" + time + "]"; + if(position != null){ + rVal = rVal + " position:" + position.toString(); + } + if(rotation != null){ + rVal = rVal + " rotation:" + rotation.toString(); + } + if(scale != null){ + rVal = rVal + " scale:" + scale.toString(); + } + return rVal; + } +} diff --git a/src/main/java/RendererObjects/Light/DirectionalLight.java b/src/main/java/RendererObjects/Light/DirectionalLight.java new file mode 100644 index 00000000..567282af --- /dev/null +++ b/src/main/java/RendererObjects/Light/DirectionalLight.java @@ -0,0 +1,74 @@ +/* + * 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. + */ +package RendererObjects.Light; + +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class DirectionalLight { + Vector3f direction; + + Vector3f ambient; + Vector3f diffuse; + Vector3f specular; + + public void setDirection(Vector3f direction) { + this.direction = direction; + } + + public void setAmbient(Vector3f ambient) { + this.ambient = ambient; + } + + public void setDiffuse(Vector3f diffuse) { + this.diffuse = diffuse; + } + + public void setSpecular(Vector3f specular) { + this.specular = specular; + } + + public Vector3f getDirection() { + return direction; + } + + public Vector3f getAmbient() { + return ambient; + } + + public Vector3f getDiffuse() { + return diffuse; + } + + public Vector3f getSpecular() { + return specular; + } + + public DirectionalLight(Vector3f direction){ + this.direction = direction; + ambient = new Vector3f(0.05f, 0.05f, 0.05f); + diffuse = new Vector3f(0.4f, 0.4f, 0.4f); + specular = new Vector3f(0.5f, 0.5f, 0.5f); + this.direction.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } + + public DirectionalLight(Vector3f direction, Vector3f color){ + this.direction = direction; + ambient = new Vector3f( color.x * 0.05f, color.y * 0.05f, color.z * 0.05f); + diffuse = new Vector3f( color.x * 0.4f, color.y * 0.4f, color.z * 0.4f); + specular = new Vector3f(color.x * 0.5f, color.y * 0.5f, color.z * 0.5f); + this.direction.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } +} diff --git a/src/main/java/RendererObjects/Light/LightBuffer.java b/src/main/java/RendererObjects/Light/LightBuffer.java new file mode 100644 index 00000000..984790dd --- /dev/null +++ b/src/main/java/RendererObjects/Light/LightBuffer.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +package RendererObjects.Light; + +import static org.lwjgl.opengl.GL15.*; +import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER; + +/** + * + * @author amaterasu + */ +public class LightBuffer { + int light_uniform_buffer_address; + + public LightBuffer(){ + light_uniform_buffer_address = glGenBuffers(); + glBindBuffer(GL_UNIFORM_BUFFER,light_uniform_buffer_address); + //glBufferData(GL_UNIFORM_BUFFER, , GL_STATIC_DRAW); + } +} diff --git a/src/main/java/RendererObjects/Light/PointLight.java b/src/main/java/RendererObjects/Light/PointLight.java new file mode 100644 index 00000000..425f85ea --- /dev/null +++ b/src/main/java/RendererObjects/Light/PointLight.java @@ -0,0 +1,106 @@ +/* + * 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. + */ +package RendererObjects.Light; + +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class PointLight { + Vector3f position; + float constant; + float linear; + float quadratic; + Vector3f ambient; + Vector3f diffuse; + Vector3f specular; + + public void setPosition(Vector3f position) { + this.position = position; + } + + public void setConstant(float constant) { + this.constant = constant; + } + + public void setLinear(float linear) { + this.linear = linear; + } + + public void setQuadratic(float quadratic) { + this.quadratic = quadratic; + } + + public void setAmbient(Vector3f ambient) { + this.ambient = ambient; + } + + public void setDiffuse(Vector3f diffuse) { + this.diffuse = diffuse; + } + + public void setSpecular(Vector3f specular) { + this.specular = specular; + } + + public Vector3f getPosition() { + return position; + } + + public float getConstant() { + return constant; + } + + public float getLinear() { + return linear; + } + + public float getQuadratic() { + return quadratic; + } + + public Vector3f getAmbient() { + return ambient; + } + + public Vector3f getDiffuse() { + return diffuse; + } + + public Vector3f getSpecular() { + return specular; + } + + public PointLight(Vector3f position){ + this.position = position; + constant = 1.0f; + linear = 0.01f; + quadratic = 0.01f; + ambient = new Vector3f(0.05f, 0.05f, 0.05f); + diffuse = new Vector3f(0.8f, 0.8f, 0.8f); + specular = new Vector3f(1.0f, 1.0f, 1.0f); + this.position.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } + + public PointLight(Vector3f position, Vector3f color){ + this.position = position; + constant = 1.0f; + linear = 0.01f; + quadratic = 0.01f; + ambient = new Vector3f(color.x * 0.05f, color.y * 0.05f, color.z * 0.05f); + diffuse = new Vector3f(color.x * 0.8f, color.y * 0.8f, color.z * 0.8f); + specular = new Vector3f(color.x, color.y, color.z); + this.position.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } +} diff --git a/src/main/java/RendererObjects/Light/SpotLight.java b/src/main/java/RendererObjects/Light/SpotLight.java new file mode 100644 index 00000000..8ccbd174 --- /dev/null +++ b/src/main/java/RendererObjects/Light/SpotLight.java @@ -0,0 +1,143 @@ +/* + * 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. + */ +package RendererObjects.Light; + +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class SpotLight { + Vector3f position; + Vector3f direction; + float cutOff; + float outerCutOff; + + float constant; + float linear; + float quadratic; + + Vector3f ambient; + Vector3f diffuse; + Vector3f specular; + + public void setPosition(Vector3f position) { + this.position = position; + } + + public void setDirection(Vector3f direction) { + this.direction = direction; + } + + public void setCutOff(float cutOff) { + this.cutOff = cutOff; + } + + public void setOuterCutOff(float outerCutOff) { + this.outerCutOff = outerCutOff; + } + + public void setConstant(float constant) { + this.constant = constant; + } + + public void setLinear(float linear) { + this.linear = linear; + } + + public void setQuadratic(float quadratic) { + this.quadratic = quadratic; + } + + public void setAmbient(Vector3f ambient) { + this.ambient = ambient; + } + + public void setDiffuse(Vector3f diffuse) { + this.diffuse = diffuse; + } + + public void setSpecular(Vector3f specular) { + this.specular = specular; + } + + public Vector3f getPosition() { + return position; + } + + public Vector3f getDirection() { + return direction; + } + + public float getCutOff() { + return cutOff; + } + + public float getOuterCutOff() { + return outerCutOff; + } + + public float getConstant() { + return constant; + } + + public float getLinear() { + return linear; + } + + public float getQuadratic() { + return quadratic; + } + + public Vector3f getAmbient() { + return ambient; + } + + public Vector3f getDiffuse() { + return diffuse; + } + + public Vector3f getSpecular() { + return specular; + } + + + + public SpotLight(Vector3f position, Vector3f direction){ + this.position = position; + this.direction = direction; + cutOff = (float)Math.toRadians(12.5f); + outerCutOff = (float)Math.toRadians(15.0f); + constant = 1.0f; + linear = 0.01f; + quadratic = 0.01f; + ambient = new Vector3f(0.05f, 0.05f, 0.05f); + diffuse = new Vector3f(0.8f, 0.8f, 0.8f); + specular = new Vector3f(1.0f, 1.0f, 1.0f); + this.position.normalize(); + this.direction.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } + + public SpotLight(Vector3f position, Vector3f direction, Vector3f color){ + this.position = position; + this.direction = direction; + constant = 1.0f; + linear = 0.01f; + quadratic = 0.01f; + ambient = new Vector3f(color.x * 0.05f, color.y * 0.05f, color.z * 0.05f); + diffuse = new Vector3f(color.x * 0.8f, color.y * 0.8f, color.z * 0.8f); + specular = new Vector3f(color.x, color.y, color.z); + this.position.normalize(); + this.direction.normalize(); + ambient.normalize(); + diffuse.normalize(); + specular.normalize(); + } +} diff --git a/src/main/java/RendererObjects/Material.java b/src/main/java/RendererObjects/Material.java new file mode 100644 index 00000000..59502d92 --- /dev/null +++ b/src/main/java/RendererObjects/Material.java @@ -0,0 +1,67 @@ +/* + * 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. + */ +package RendererObjects; + +import RendererObjects.texture.Texture; +import org.lwjgl.PointerBuffer; +import org.lwjgl.assimp.AIMaterial; +import org.lwjgl.assimp.AIMaterialProperty; + +/** + * + * @author amaterasu + */ +public class Material { + Texture diffuse; + Texture specular; + boolean hasTransparency = false; + public Material(){ + + } + //basically useless because blender doesn't support exporting mats with fbx + public static Material load_material_from_aimaterial(AIMaterial input){ + Material rVal = new Material(); + if(input.mNumProperties() > 0){ + PointerBuffer property_buffer = input.mProperties(); + while(property_buffer.hasRemaining()){ + AIMaterialProperty new_property = AIMaterialProperty.create(property_buffer.get()); +// System.out.println("Property: " + new_property.mKey().dataString()); + } + } + return rVal; + } + public Texture get_diffuse(){ + return diffuse; + } + public Texture get_specular(){ + return specular; + } + public void set_diffuse(Texture t){ + diffuse = t; + if(t.isTransparent()){ + hasTransparency = true; + } + } + public void set_specular(Texture t){ + specular = t; + if(t.isTransparent()){ + hasTransparency = true; + } + } + + public void apply_material(){ + diffuse.bind(0); + specular.bind(1); + } + public void apply_material(int diffuse_channel, int specular_channel){ + diffuse.bind(diffuse_channel); + specular.bind(specular_channel); + } + + public boolean isTransparent(){ + return hasTransparency; + } +} diff --git a/src/main/java/RendererObjects/Mesh.java b/src/main/java/RendererObjects/Mesh.java new file mode 100644 index 00000000..4f100601 --- /dev/null +++ b/src/main/java/RendererObjects/Mesh.java @@ -0,0 +1,537 @@ +package RendererObjects; + +import main.Globals; +import main.Main; +import RendererObjects.Light.LightBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; +import org.lwjgl.PointerBuffer; +import org.lwjgl.assimp.AIBone; +import org.lwjgl.assimp.AIFace; +import org.lwjgl.assimp.AIMesh; +import org.lwjgl.assimp.AIVector2D; +import org.lwjgl.assimp.AIVector3D; +import org.lwjgl.assimp.AIVertexWeight; +import static org.lwjgl.opengl.ARBVertexBufferObject.*; +import org.lwjgl.opengl.GL11; +import static org.lwjgl.opengl.GL11.GL_FALSE; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_INT; +import static org.lwjgl.opengl.GL11.GL_TRIANGLES; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; +import org.lwjgl.opengl.GL15; +import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; +import static org.lwjgl.opengl.GL15.glBindBuffer; +import static org.lwjgl.opengl.GL15.glGenBuffers; +import org.lwjgl.opengl.GL20; +import static org.lwjgl.opengl.GL20.*; +import static org.lwjgl.opengl.GL20.glGetUniformLocation; +import static org.lwjgl.opengl.GL20.glUniform1i; +import static org.lwjgl.opengl.GL20.glUniform3fv; +import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; +import static org.lwjgl.opengl.GL20.glUseProgram; +import static org.lwjgl.opengl.GL20.glVertexAttribPointer; +import static org.lwjgl.opengl.GL30.glBindVertexArray; +import static org.lwjgl.opengl.GL30.glGenVertexArrays; + +/** + * + * @author satellite + */ +public class Mesh { + public Model parent; + public String nodeID; + public AIMesh mesh; + public int vertexBuffer; + public int normalBuffer; + public int elementArrayBuffer; + public int elementCount; + public int faceCount; + public int vertexArrayObject; + public int vertexCount; + public int normalCount; + public int boneWeightBuffer; + public int boneIndexBuffer; + public int boneCount; + public int textureCoordBuffer; + public int textureCoordCount; + public ArrayList bones = new ArrayList(); + public ArrayList bone_id_list = new ArrayList(); + int bone_map_size = 0; + boolean hasBones = true; + public boolean hasTextureCoords = true; + + + public ShaderProgram shader; + + int shaderBoneArrayLocation; + + Material material; + + LightBuffer light_buffer; + + public static Mesh create_mesh_from_aimesh(AIMesh mesh){ + boolean has_bones = false; + boolean apply_lighting = true; + + Mesh rVal = new Mesh(); + rVal.mesh = mesh; + + // + // VAO + // + rVal.vertexArrayObject = glGenVertexArrays(); + glBindVertexArray(rVal.vertexArrayObject); + + + + //Basic checks + //check num vertices + int numVertices = 0; + AIVector3D.Buffer vertexData = mesh.mVertices(); + while(vertexData.hasRemaining()){ + vertexData.get(); + numVertices++; + } + vertexData = vertexData.rewind(); + //check num normals + int numNormals = 0; + AIVector3D.Buffer normalData = mesh.mNormals(); + while(normalData.hasRemaining()){ + normalData.get(); + numNormals++; + } + normalData.rewind(); + if(numVertices != numNormals){ + System.out.println("Catastrophic failure: Number of vertices =/= Number of normals"); + System.exit(1); + } + + + + + + + + + + + + + // + //Buffer data to GPU + // + vertexData.rewind(); + + try { + rVal.vertexCount = mesh.mNumVertices(); + FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(rVal.vertexCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < rVal.vertexCount; i++) { + AIVector3D vertex = vertexData.get(); + temp[0] = vertex.x(); + temp[1] = vertex.y(); + temp[2] = vertex.z(); + VertexArrayBufferData.put(temp); + } + VertexArrayBufferData.flip(); + rVal.buffer_vertices(VertexArrayBufferData); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + // + // NORMALS + // + AIVector3D.Buffer normals = mesh.mNormals(); + try { + rVal.normalCount = mesh.mNumVertices(); + FloatBuffer NormalArrayBufferData; + if(rVal.normalCount > 0){ + NormalArrayBufferData = BufferUtils.createFloatBuffer(rVal.normalCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < rVal.normalCount; i++) { + AIVector3D normal = normals.get(i); + temp[0] = normal.x(); + temp[1] = normal.y(); + temp[2] = normal.z(); + NormalArrayBufferData.put(temp); + } + NormalArrayBufferData.flip(); + rVal.buffer_normals(NormalArrayBufferData); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + // + // FACES + // + rVal.faceCount = mesh.mNumFaces(); + rVal.elementCount = rVal.faceCount * 3; + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(rVal.elementCount); + AIFace.Buffer facesBuffer = mesh.mFaces(); + for(int i = 0; i < rVal.faceCount; i++){ + AIFace face = facesBuffer.get(i); + if(face.mNumIndices() != 3){ + throw new IllegalStateException("AIFace.mNumIndices() != 3"); + } + elementArrayBufferData.put(face.mIndices()); + } + elementArrayBufferData.flip(); + rVal.buffer_faces(elementArrayBufferData); + + + + + + // + // TEXTURE COORDINATES + // + if(mesh.mTextureCoords().capacity() > 0){ + AIVector3D.Buffer texturecoords = mesh.mTextureCoords(0); + try { + rVal.textureCoordCount = mesh.mTextureCoords(0).capacity(); + FloatBuffer TextureArrayBufferData; + if(rVal.textureCoordCount > 0){ + TextureArrayBufferData = BufferUtils.createFloatBuffer(rVal.textureCoordCount * 2); + float[] temp = new float[2]; + for (int i = 0; i < rVal.textureCoordCount; i++) { + AIVector3D normal = texturecoords.get(i); + temp[0] = normal.x(); + temp[1] = normal.y(); +// temp[2] = normal.z(); + TextureArrayBufferData.put(temp); + } + TextureArrayBufferData.flip(); + rVal.buffer_texture_coords(TextureArrayBufferData); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + //System.out.println("Enabled texture coordinates"); + } + + + + + + + + + + + + + + // + //Read in bones + //AND buffer data (weights) to GPU + // + PointerBuffer boneBuffer = mesh.mBones(); + if(boneBuffer != null){ + has_bones = true; + while(boneBuffer.hasRemaining()){ + long currentAddr = boneBuffer.get(); + AIBone currentBoneData = AIBone.createSafe(currentAddr); +// System.out.println("Num weights: " + currentBoneData.mNumWeights()); + Bone currentBone = new Bone(); + currentBone.boneID = currentBoneData.mName().dataString(); + currentBone.inverseBindPoseMatrix = util.util.convertAIMatrix(currentBoneData.mOffsetMatrix()); + currentBone.numWeights = currentBoneData.mNumWeights(); + currentBone.weights = new HashMap(); + Iterator weightIterator = currentBoneData.mWeights().iterator(); + while(weightIterator.hasNext()){ + AIVertexWeight currentWeightData = weightIterator.next(); + currentBone.weights.put(currentWeightData.mVertexId(), currentWeightData.mWeight()); + } + rVal.bones.add(currentBone); + rVal.bone_id_list.add(currentBone.boneID); + } + rVal.boneCount = rVal.bones.size(); + FloatBuffer boneWeightDataBuffer = BufferUtils.createFloatBuffer(4 * rVal.vertexCount);//FloatBuffer.allocate(4 * vertexCount); + FloatBuffer boneIndexDataBuffer = BufferUtils.createFloatBuffer(4 * rVal.vertexCount);//IntBuffer.allocate(4 * vertexCount); + Iterator boneIterator; + for(int i = 0; i < rVal.vertexCount; i++){ + float[] weight = new float[4]; + float[] index = new float[4]; + int boneCounter = 0; + boneIterator = rVal.bones.iterator(); + while(boneIterator.hasNext()){ + Bone currentBone = boneIterator.next(); + float boneVal = 0; + if(currentBone.weights.get(i) != null){ + boneVal = currentBone.weights.get(i); + } + if(boneVal > 0){ + if(boneVal > weight[0]){ + weight[3] = weight[2]; + weight[2] = weight[1]; + weight[1] = weight[0]; + weight[0] = boneVal; + index[3] = index[2]; + index[2] = index[1]; + index[1] = index[0]; + index[0] = boneCounter; + } else if(boneVal > weight[1]){ + weight[3] = weight[2]; + weight[2] = weight[1]; + weight[1] = boneVal; + index[3] = index[2]; + index[2] = index[1]; + index[1] = boneCounter; + } else if(boneVal > weight[2]){ + weight[3] = weight[2]; + weight[2] = boneVal; + index[3] = index[2]; + index[2] = boneCounter; + } else if(boneVal > weight[3]){ + weight[3] = boneVal; + index[3] = boneCounter; + } + } + boneCounter++; + } + float total = weight[0] + weight[1] + weight[2] + weight[3]; + if(total != 1.0f){ + weight[0] = weight[0] * (1.0f / total); + weight[1] = weight[1] * (1.0f / total); + weight[2] = weight[2] * (1.0f / total); + weight[3] = weight[3] * (1.0f / total); + } + boneIndexDataBuffer.put(index); + boneWeightDataBuffer.put(weight); + } + boneIndexDataBuffer.flip(); + boneWeightDataBuffer.flip(); + + + rVal.boneWeightBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, rVal.boneWeightBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, boneWeightDataBuffer, GL_STATIC_DRAW); + glVertexAttribPointer(2, 4, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(2); + + + rVal.boneIndexBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, rVal.boneIndexBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, boneIndexDataBuffer, GL_STATIC_DRAW); + glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(3); + } else { + rVal.hasBones = false; + } + + + + + + + + + + + + + rVal.shader = ShaderProgram.smart_assemble_shader(has_bones, apply_lighting); + + + + + + + + + + + + + + + + + glBindVertexArray(0); + + + + + + + + + + rVal.nodeID = mesh.mName().dataString(); + + + return rVal; + } + + + public Mesh(){ + + } + + public void draw() { + glUseProgram(shader.shaderProgram); + + //Until we switch to uniform buffer objects we will have to buffer lighting data here manually each time we draw + //side note: :( + if(light_buffer == null){ + float temp[] = new float[3]; + temp[0] = 0.2f; + temp[1] = -1.0f; + temp[2] = 0.3f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.direction"), temp); + + temp[0] = 0.1f; + temp[1] = 0.1f; + temp[2] = 0.1f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.ambient"), temp); + + temp[0] = 0.8f; + temp[1] = 0.8f; + temp[2] = 0.8f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.diffuse"), temp); + + temp[0] = 0.1f; + temp[1] = 0.1f; + temp[2] = 0.1f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.specular"), temp); + + temp[0] = 32f; + glUniform1fv(glGetUniformLocation(shader.shaderProgram, "material.shininess"), temp); + + GL20.glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgram, "model"), false, parent.modelMatrix.get(new float[16])); + + Vector3f cam_Loc = Globals.camera_visible.pos_Center; + temp[0] = cam_Loc.x; + temp[1] = cam_Loc.y; + temp[2] = cam_Loc.z; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "viewPos"), temp); + } else { + GL20.glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgram, "model"), false, parent.modelMatrix.get(new float[16])); + } + + + if(material == null){ + Globals.material_default.apply_material(0,1); + GL20.glUniform1i(glGetUniformLocation(shader.shaderProgram, "hasTransparency"), 0); + } else { + material.apply_material(); + if(material.hasTransparency){ + GL20.glUniform1i(glGetUniformLocation(shader.shaderProgram, "hasTransparency"), 1); + } else { + GL20.glUniform1i(glGetUniformLocation(shader.shaderProgram, "hasTransparency"), 1); + } + } + + glBindVertexArray(vertexArrayObject); + + + + + // + //Handle bones + // + if(bones != null && !bones.isEmpty()){ + glUniform1i(shader.shaderVertexHasBonesLoc, 1); + glUniform1i(shader.shaderVertexNumBonesLoc, bones.size()); + Iterator boneIterator = bone_id_list.iterator(); + float bufferarray[] = new float[16]; + int incrementer = 0; + while (boneIterator.hasNext()){ + Bone currentBone = parent.boneMap.get(boneIterator.next()); + Matrix4f currentMat = new Matrix4f(currentBone.final_transform); + currentMat.get(bufferarray); + String currentUniform = "bones[" + incrementer + "]"; + GL20.glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgram, currentUniform), false, bufferarray); + incrementer++; + } + } else { + glUniform1i(shader.shaderVertexHasBonesLoc, 0); + } + + + + //buffer model/view/proj matrices + glUniformMatrix4fv(shader.shaderVertexModelLoc, false, parent.modelMatrix.get(new float[16])); + glUniformMatrix4fv(shader.shaderVertexViewLoc, false, Globals.viewMatrix.get(new float[16])); + glUniformMatrix4fv(shader.shaderVertexProjectionLoc, false, Globals.projectionMatrix.get(new float[16])); + glUniform3fv(shader.shaderVertexViewPosLoc, Globals.camera_visible.pos_Center.get(BufferUtils.createFloatBuffer(3))); + + // + // + //Testing Lights + // + // + float test_Light_Data[] = new float[3]; + test_Light_Data[0] = 0.2f; + test_Light_Data[1] = -1.0f; + test_Light_Data[2] = 0.3f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.direction"), test_Light_Data); + + test_Light_Data = new float[3]; + test_Light_Data[0] = 0.3f; + test_Light_Data[1] = 0.3f; + test_Light_Data[2] = 0.3f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.ambient"), test_Light_Data); + + test_Light_Data = new float[3]; + test_Light_Data[0] = 0.5f; + test_Light_Data[1] = 0.5f; + test_Light_Data[2] = 0.5f; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "dirLight.diffuse"), test_Light_Data); + + Vector3f cam_Loc = Globals.camera_visible.pos_Center; + test_Light_Data = new float[3]; + test_Light_Data[0] = cam_Loc.x; + test_Light_Data[1] = cam_Loc.y; + test_Light_Data[2] = cam_Loc.z; + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "viewPos"), test_Light_Data); + + + GL11.glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); + } + + public void buffer_vertices(FloatBuffer verticies){ + vertexBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, verticies, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(0); + } + + public void buffer_normals(FloatBuffer normals){ + normalBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, normals, GL_STATIC_DRAW); + glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(1); + } + + public void buffer_faces(IntBuffer faces){ + elementArrayBuffer = glGenBuffers(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer); + GL15.glBufferData(GL_ELEMENT_ARRAY_BUFFER, faces, GL_STATIC_DRAW); + elementCount = faces.capacity(); + } + + public void buffer_texture_coords(FloatBuffer coords){ + textureCoordBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, textureCoordBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, coords, GL_STATIC_DRAW); + glVertexAttribPointer(4, 2, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(4); + } + + public void set_material(Material input){ + this.material = input; + } +} diff --git a/src/main/java/RendererObjects/Model.java b/src/main/java/RendererObjects/Model.java new file mode 100644 index 00000000..394aa616 --- /dev/null +++ b/src/main/java/RendererObjects/Model.java @@ -0,0 +1,335 @@ +package RendererObjects; + +import main.Globals; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; +import org.lwjgl.PointerBuffer; +import org.lwjgl.assimp.AIMaterial; +import org.lwjgl.assimp.AIMesh; +import org.lwjgl.assimp.AIScene; +import static org.lwjgl.assimp.Assimp.*; +import static org.lwjgl.opengl.ARBVertexBufferObject.*; +import static org.lwjgl.opengl.ARBVertexProgram.*; +import org.lwjgl.opengl.GL11; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL13.*; +import static org.lwjgl.opengl.GL15.*; +import static org.lwjgl.opengl.GL20.*; +import static org.lwjgl.opengl.GL30.*; +import RendererObjects.texture.TextureMap; +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Stack; +import org.joml.Quaternionf; +import org.lwjgl.assimp.AIAnimation; +import org.lwjgl.assimp.AIBone; +import org.lwjgl.assimp.AINode; + +/** + * + * @author satellite + */ +public class Model { + public boolean is_Ready_To_Display = false; + public AIScene scene; + public ArrayList meshes; + public ArrayList animations; + public ArrayList bones; + public HashMap boneMap; + public HashMap node_map; + public ArrayList materials; + public Matrix4f modelMatrix = new Matrix4f(); + ShaderProgram program; + public Animation currentAnimation; + public Matrix4f globalInverseTransform; + + AnimNode root_anim_node; + + public static Model create_model_from_aiscene(AIScene s){ + Model rVal = new Model(); + // + //set the scene + // + rVal.scene = s; + + // + //load meshes + // + int meshCount = s.mNumMeshes(); + PointerBuffer meshesBuffer = s.mMeshes(); + rVal.meshes = new ArrayList(); + while(meshesBuffer.hasRemaining()){ + Mesh currentMesh = Mesh.create_mesh_from_aimesh(AIMesh.create(meshesBuffer.get())); + rVal.meshes.add(currentMesh); + currentMesh.parent = rVal; + } + // + //register bones + // + rVal.bones = new ArrayList(); + rVal.boneMap = new HashMap(); + meshesBuffer.rewind(); + while(meshesBuffer.hasRemaining()){ + AIMesh currentMeshData = AIMesh.createSafe(meshesBuffer.get()); + PointerBuffer boneBuffer = currentMeshData.mBones(); + for(int j = 0; j < currentMeshData.mNumBones(); j++){ + AIBone currentBone = AIBone.createSafe(boneBuffer.get()); + String currentBoneName = currentBone.mName().dataString(); + if(!rVal.boneMap.containsKey(currentBoneName)){ + Bone boneObject = new Bone(currentBone); + rVal.boneMap.put(currentBoneName, boneObject); + rVal.bones.add(boneObject); + } + } + } + Iterator meshIterator = rVal.meshes.iterator(); + rVal.bones = new ArrayList(); + rVal.boneMap = new HashMap(); + rVal.node_map = new HashMap(); + while(meshIterator.hasNext()){ + Mesh currentMesh = meshIterator.next(); + Iterator boneIterator = currentMesh.bones.iterator(); + ArrayList to_remove_queue = new ArrayList(); + ArrayList to_add_queue = new ArrayList(); + while(boneIterator.hasNext()){ + Bone currentBone = boneIterator.next(); + if(!rVal.boneMap.containsKey(currentBone.boneID)){ + rVal.bones.add(currentBone); + rVal.boneMap.put(currentBone.boneID, currentBone); + } + } + boneIterator = to_remove_queue.iterator(); + while(boneIterator.hasNext()){ + currentMesh.bones.remove(boneIterator.next()); + } + boneIterator = to_add_queue.iterator(); + while(boneIterator.hasNext()){ + currentMesh.bones.add(boneIterator.next()); + } + } + // + //parse animation nodes and form hierarchy + // + AINode rootNode = s.mRootNode(); + rVal.globalInverseTransform = util.util.convertAIMatrix(rootNode.mTransformation()); +// System.out.println("Global inverse transform"); +// System.out.println(globalInverseTransform); + rVal.root_anim_node = rVal.build_anim_node_map(s.mRootNode(),null); + // + //load animations + // + int animCount = s.mNumAnimations(); + PointerBuffer animBuffer = s.mAnimations(); + rVal.animations = new ArrayList(); + for(int i = 0; i < animCount; i++){ + rVal.animations.add(new Animation(AIAnimation.create(animBuffer.get(i)), i)); + } + // + //Load materials + // + if(s.mNumMaterials() > 0){ + rVal.materials = new ArrayList(); + PointerBuffer material_buffer = s.mMaterials(); + while(material_buffer.hasRemaining()){ + rVal.materials.add(Material.load_material_from_aimaterial(AIMaterial.create(material_buffer.get()))); + } + } + //garbage collect + System.gc(); + return rVal; + } + + + + public Model(){ + /* + public boolean is_Ready_To_Display = false; + public AIScene scene; + public ArrayList meshes; + public ArrayList animations; + public ArrayList bones; + public HashMap boneMap; + public HashMap node_map = new HashMap(); + public ArrayList materials; + public Matrix4f modelMatrix = new Matrix4f().translation(new Vector3f(0,0,0)); + ShaderProgram program; + public Animation currentAnimation; + public Matrix4f globalInverseTransform; + */ + scene = null; + meshes = null; + animations = null; + bones = null; + boneMap = null; + node_map = null; + materials = null; + modelMatrix = new Matrix4f(); + program = null; + currentAnimation = null; + globalInverseTransform = null; + } + + public void free() { + aiReleaseImport(scene); + scene = null; + meshes = null; + } + + public void draw(){ + if(node_map != null && !node_map.isEmpty()){ + update_node_transform(root_anim_node); + } + Iterator mesh_Iterator = meshes.iterator(); + while(mesh_Iterator.hasNext()){ + Mesh currentMesh = mesh_Iterator.next(); + currentMesh.draw(); + } + } + + + public void playAnimation(String s){ + this.currentAnimation = null; + Iterator animationIterator = animations.iterator(); + while(animationIterator.hasNext()){ + Animation current_iterator_item = animationIterator.next(); + if(current_iterator_item.name.equals(s)){ + this.currentAnimation = current_iterator_item; + } + } + if(currentAnimation != null){ + currentAnimation.timeCurrent = 0; + Iterator channelIterator = currentAnimation.channels.iterator(); + while(channelIterator.hasNext()){ + AnimChannel currentChannel = channelIterator.next(); + currentChannel.rewind(); + } + } + } + + public void incrementTime(double time){ + boolean isDone = currentAnimation.incrementTime(time); + if(isDone){ + currentAnimation.timeCurrent = 0; + Iterator channelIterator = currentAnimation.channels.iterator(); + while(channelIterator.hasNext()){ + AnimChannel currentChannel = channelIterator.next(); + currentChannel.rewind(); + } + Iterator boneIterator = bones.iterator(); + while(boneIterator.hasNext()){ + Bone currentBone = boneIterator.next(); + currentBone.transform = new Matrix4f(); + } + currentAnimation = null; + } else { + //First we push transformFromParent into deform so that later in the pipeline bones without a current animation take on transformFromParent as their transformation to the hierarchy + //I BELIEVE this is so that control bones still apply their offset to the hierarchy even when they're not animated :tm: + //4/5/20 + Iterator boneIterator = bones.iterator(); + while(boneIterator.hasNext()){ + Bone currentBone = boneIterator.next(); +// currentBone.deform = currentBone.transformFromParent; + } + //Once that's done, for every channel we set the corresponding bone's deform to the channels TRS + Iterator channelIterator = currentAnimation.channels.iterator(); + while(channelIterator.hasNext()){ + AnimChannel currentChannel = channelIterator.next(); + currentChannel.incrementTime(time); + Bone currentBone = boneMap.get(currentChannel.nodeID); + if(currentBone != null){ + //T * S * R + currentBone.deform = new Matrix4f(); + currentBone.deform.translate(currentChannel.getCurrentPosition()); + currentBone.deform.rotate(currentChannel.getCurrentRotation()); + currentBone.deform.scale(currentChannel.getCurrentScale()); + } + } + } + } + + public void describeAllAnimations(){ + if(animations.size() > 0){ + System.out.println("====================="); + System.out.println(animations.size() + " animations available in model!"); + Iterator animIterator = animations.iterator(); + while(animIterator.hasNext()){ + Animation currentAnim = animIterator.next(); + currentAnim.describeAnimation(); + } + } + } + + public final AnimNode build_anim_node_map(AINode node, AnimNode parent){ + AnimNode node_object = new AnimNode(node.mName().dataString(), parent, node); + node_map.put(node_object.id, node_object); + if(boneMap.containsKey(node_object.id)){ + node_object.is_bone = true; + } + int num_children = node.mNumChildren(); + for(int i = 0; i < num_children; i++){ + AnimNode temp_child = build_anim_node_map(AINode.create(node.mChildren().get(i)),node_object); +// if(boneMap.containsKey(node_object.id)){ +// Bone parent_bone = boneMap.get(node_object.id); +// node_object.children.add(temp_child); +// if(boneMap.containsKey(temp_child.id)){ +// Bone child_bone = boneMap.get(temp_child.id); +// parent_bone.children.add(child_bone); +// child_bone.parent = parent_bone; +// } +// } + node_object.children.add(temp_child); + } + return node_object; + } + + public void update_node_transform(AnimNode n){ + if(n.parent != null){ + n.transform = new Matrix4f(n.parent.transform); + } else { + n.transform = new Matrix4f(); + } + if(n.is_bone){ + /* + Bone bone = boneList.get(j); + Node node = rootNode.findByName(bone.getBoneName()); + Matrix4f boneMatrix = Node.getParentTransforms(node, i); + boneMatrix.mul(bone.getOffsetMatrix()); + boneMatrix = new Matrix4f(rootTransformation).mul(boneMatrix); + frame.setMatrix(j, boneMatrix); + */ + Bone target_bone = boneMap.get(n.id); + n.transform = n.transform.mul(target_bone.deform); + Matrix4f bone_matrix = new Matrix4f(n.transform).mul(target_bone.inverseBindPoseMatrix); + bone_matrix = new Matrix4f(globalInverseTransform).mul(bone_matrix); + target_bone.final_transform = bone_matrix; +// if(!toggled){ +// System.out.println(n.id); +// System.out.println("Transform:"); +// System.out.println(n.parent.transform); +// System.out.println(target_bone.deform); +// System.out.println(n.transform); +// System.out.println("Final transform:"); +// System.out.println(globalInverseTransform); +// System.out.println(n.transform); +// System.out.println(target_bone.inverseBindPoseMatrix); +// System.out.println(target_bone.final_transform); +// System.out.println("\n\n\n\n"); +// } + } else { + n.transform = n.transform.mul(util.util.convertAIMatrix(n.raw_data.mTransformation())); + } + Iterator node_iterator = n.children.iterator(); + while(node_iterator.hasNext()){ + AnimNode current_node = node_iterator.next(); + update_node_transform(current_node); + } + } +} diff --git a/src/main/java/RendererObjects/RenderUtils.java b/src/main/java/RendererObjects/RenderUtils.java new file mode 100644 index 00000000..22300950 --- /dev/null +++ b/src/main/java/RendererObjects/RenderUtils.java @@ -0,0 +1,279 @@ +/* + * 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. + */ +package RendererObjects; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import main.Globals; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_INT; +import static org.lwjgl.opengl.GL11.GL_LEQUAL; +import static org.lwjgl.opengl.GL11.GL_LESS; +import static org.lwjgl.opengl.GL11.GL_SHORT; +import static org.lwjgl.opengl.GL11.GL_TRIANGLES; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; +import org.lwjgl.opengl.GL15; +import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; +import static org.lwjgl.opengl.GL15.glBindBuffer; +import static org.lwjgl.opengl.GL15.glGenBuffers; +import org.lwjgl.opengl.GL20; +import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; +import static org.lwjgl.opengl.GL20.glGetUniformLocation; +import static org.lwjgl.opengl.GL20.glUniform1fv; +import static org.lwjgl.opengl.GL20.glUniform1i; +import static org.lwjgl.opengl.GL20.glUniform3fv; +import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; +import static org.lwjgl.opengl.GL20.glUseProgram; +import static org.lwjgl.opengl.GL20.glVertexAttribPointer; +import static org.lwjgl.opengl.GL30.glBindVertexArray; +import static org.lwjgl.opengl.GL30.glGenVertexArrays; + +/** + * + * @author amaterasu + */ +public class RenderUtils { + public static Model createSkyboxModel(Material optionalMaterial){ + Model skybox_model = new Model(); + skybox_model.meshes = new ArrayList(); + + skybox_model.modelMatrix = new Matrix4f(); + + + + boolean apply_lighting = false; + boolean has_bones = false; + + Mesh skyboxmesh = new Mesh(){ + @Override + public void draw(){ + GL11.glDepthFunc(GL_LEQUAL); + glUseProgram(shader.shaderProgram); + + if(material == null){ + Globals.material_default.apply_material(0,1); + Iterator colorIterator = Globals.skybox_colors.iterator(); + int counter = 0; + float[] temp = new float[3]; + while(colorIterator.hasNext()){ + Vector3f colorCurrent = colorIterator.next(); + temp[0] = colorCurrent.x / 255.0f; + temp[1] = colorCurrent.y / 255.0f; + temp[2] = colorCurrent.z / 255.0f; +// System.out.println("colors[" + counter + "] " + temp[0] + " " + temp[1] + " " + temp[2]); + glUniform3fv(glGetUniformLocation(shader.shaderProgram, "colors[" + counter + "]"), temp); + counter++; + } + } + + glBindVertexArray(vertexArrayObject); + + + + + //buffer model/view/proj matrices + glUniformMatrix4fv(shader.shaderVertexModelLoc, false, parent.modelMatrix.get(new float[16])); + glUniformMatrix4fv(shader.shaderVertexViewLoc, false, new Matrix4f(Globals.viewMatrix).scale(100).get(new float[16])); + glUniformMatrix4fv(shader.shaderVertexProjectionLoc, false, Globals.projectionMatrix.get(new float[16])); + glUniform3fv(shader.shaderVertexViewPosLoc, Globals.camera_visible.pos_Center.get(BufferUtils.createFloatBuffer(3))); + + + GL11.glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); + GL11.glDepthFunc(GL_LESS); + } + }; + + + skyboxmesh.mesh = null; + + // + // VAO + // + skyboxmesh.vertexArrayObject = glGenVertexArrays(); + glBindVertexArray(skyboxmesh.vertexArrayObject); + + + + + + + + + + + float[] vertexcoords = { + 1.0f,1.0f,1.0f, + 1.0f,1.0f,-1.0f, + 1.0f,-1.0f,1.0f, + 1.0f,-1.0f,-1.0f, + -1.0f,1.0f,1.0f, + -1.0f,1.0f,-1.0f, + -1.0f,-1.0f,1.0f, + -1.0f,-1.0f,-1.0f, + + }; + + // + //Buffer data to GPU + // + + try { + skyboxmesh.vertexCount = vertexcoords.length / 3; + FloatBuffer VertexArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < skyboxmesh.vertexCount; i++) { + temp[0] = vertexcoords[i * 3 + 0]; + temp[1] = vertexcoords[i * 3 + 1]; + temp[2] = vertexcoords[i * 3 + 2]; + VertexArrayBufferData.put(temp); + } + VertexArrayBufferData.flip(); + skyboxmesh.buffer_vertices(VertexArrayBufferData); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + int[] facedata = { + 0,1,4, + 1,4,5, + 1,3,5, + 3,5,7, + 4,5,7, + 4,6,7, + + 0,2,4, + 2,4,6, + 0,1,2, + 1,2,3, + + 2,3,6, + 3,6,7, + + }; + + // + // FACES + // + skyboxmesh.faceCount = facedata.length / 3; + skyboxmesh.elementCount = facedata.length; + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(skyboxmesh.elementCount); + for(int i = 0; i < skyboxmesh.faceCount; i++){ + int[] temp = new int[3]; + temp[0] = facedata[i * 3 + 0]; + temp[1] = facedata[i * 3 + 1]; + temp[2] = facedata[i * 3 + 2]; + elementArrayBufferData.put(temp); + } + elementArrayBufferData.flip(); + skyboxmesh.buffer_faces(elementArrayBufferData); + + + + + if(optionalMaterial != null){ + // + // NORMALS + // + try { + skyboxmesh.normalCount = vertexcoords.length / 3; + FloatBuffer NormalArrayBufferData; + if(skyboxmesh.normalCount > 0){ + NormalArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.normalCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < skyboxmesh.normalCount; i++) { + temp[0] = vertexcoords[i * 3 + 0]; + temp[1] = vertexcoords[i * 3 + 1]; + temp[2] = vertexcoords[i * 3 + 2]; + NormalArrayBufferData.put(temp); + } + NormalArrayBufferData.flip(); + skyboxmesh.buffer_normals(NormalArrayBufferData); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + // + // TEXTURE COORDINATES + // + /*try { + skyboxmesh.textureCoordCount = mesh.mTextureCoords(0).capacity(); + FloatBuffer TextureArrayBufferData; + if(skyboxmesh.textureCoordCount > 0){ + TextureArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.textureCoordCount * 2); + float[] temp = new float[2]; + for (int i = 0; i < skyboxmesh.textureCoordCount; i++) { + AIVector3D normal = texturecoords.get(i); + temp[0] = normal.x(); + temp[1] = normal.y(); + // temp[2] = normal.z(); + TextureArrayBufferData.put(temp); + } + TextureArrayBufferData.flip(); + skyboxmesh.buffer_texture_coords(TextureArrayBufferData); + } + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + skyboxmesh.shader = ShaderProgram.smart_assemble_shader(has_bones, apply_lighting); + + skybox_model.materials.add(optionalMaterial); + */ + } else { + skyboxmesh.shader = ShaderProgram.loadSpecificShader("/Shaders/skybox/VertexShaderNoTexture.vs", "/Shaders/skybox/FragmentShaderNoTexture.fs"); + try { + FloatBuffer ColorArrayBufferData = BufferUtils.createFloatBuffer(skyboxmesh.vertexCount); + for (int i = 0; i < skyboxmesh.vertexCount; i++) { + ColorArrayBufferData.put(i); + } + ColorArrayBufferData.flip(); + int idBuffer = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, idBuffer); + GL15.glBufferData(GL_ARRAY_BUFFER, ColorArrayBufferData, GL_STATIC_DRAW); + glVertexAttribPointer(1, 1, GL11.GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(1); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + } + + + + + skyboxmesh.hasBones = false; + + + + + glBindVertexArray(0); + + + + + + + + + + skyboxmesh.nodeID = "skybox"; + + skyboxmesh.parent = skybox_model; + + + skybox_model.meshes.add(skyboxmesh); + + + return skybox_model; + } +} diff --git a/src/main/java/RendererObjects/ShaderProgram.java b/src/main/java/RendererObjects/ShaderProgram.java new file mode 100644 index 00000000..fa73c977 --- /dev/null +++ b/src/main/java/RendererObjects/ShaderProgram.java @@ -0,0 +1,374 @@ +package RendererObjects; + +import main.Main; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import org.lwjgl.opengl.GL20; +import static org.lwjgl.opengl.GL20.*; + +/** + * + * @author amaterasu + */ +public class ShaderProgram { + // + //Program stuff + // + int vertexShader; + int fragmentShader; + int shaderProgram; + + + // + //Uniform locations + // + public int shaderVertexModelLoc; + public int shaderVertexViewLoc; + public int shaderVertexProjectionLoc; + public int shaderVertexViewPosLoc; + public int shaderVertexBonesLoc; + public int shaderVertexHasBonesLoc; + public int shaderVertexNumBonesLoc; + + + //Uniforms + //list of names of all uniforms in the shader + public ArrayList uniformList; + //map + //string -> tuple + //tuple: a string describing the type of the data,the current value,location + //ie arrayVec3,[<1,0,0>,<2,0,0>],colors + // Mat4,[Matrix4f],modelMatrix + public HashMap uniformMap; + + public static ShaderProgram smart_assemble_shader(boolean ContainsBones, boolean apply_lighting){ + + String vertex_shader_path = ""; + if(ContainsBones){ + vertex_shader_path = "/Shaders/VertexShader.vs"; + } else { + vertex_shader_path = "/Shaders/VertexShaderNoBones.vs"; + } + + String fragment_shader_path = "/Shaders/FragmentShader.fs"; + // + //Create ShaderProgram object + // + ShaderProgram rVal = new ShaderProgram(); + // + //Read in shader programs + // + String tempForReadingShaders = ""; + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource(vertex_shader_path).getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String vertexShaderSource = tempForReadingShaders; + //This try-catch block reads the FragmentShader source into memory + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource(fragment_shader_path).getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String fragmentShaderSource = tempForReadingShaders; + //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" + rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); + //This alerts openGL to the presence of a vertex shader and points the shader at its source + glShaderSource(rVal.vertexShader, vertexShaderSource); + //Compiles the source for the vertex shader object + glCompileShader(rVal.vertexShader); + //The following tests if the vertex shader compiles successfully + int success; + success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Vertex Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader)); + } + //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader + rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + //This points the opengl shadder object to its proper source + glShaderSource(rVal.fragmentShader, fragmentShaderSource); + //This compiles the shader object + glCompileShader(rVal.fragmentShader); + //This tests for the success of the compile attempt + success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Fragment Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader)); + } + //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram + rVal.shaderProgram = glCreateProgram(); + //This attaches the vertex and fragment shaders to the program + glAttachShader(rVal.shaderProgram, rVal.vertexShader); + glAttachShader(rVal.shaderProgram, rVal.fragmentShader); + //This links the program to the GPU (I think its to the GPU anyway) + glLinkProgram(rVal.shaderProgram); + //Tests for the success of the shader program creation + success = glGetProgrami(rVal.shaderProgram, GL_LINK_STATUS); + if (success != GL_TRUE) { + throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); + } + + //Deletes the individual shader objects to free up memory + glDeleteShader(rVal.vertexShader); + glDeleteShader(rVal.fragmentShader); + + + + // + //Set locations + // + rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderProgram, "model"); + rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderProgram, "view"); + rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderProgram, "projection"); + rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderProgram, "viewPos"); + if(ContainsBones){ + rVal.shaderVertexBonesLoc = glGetUniformLocation(rVal.shaderProgram, "bones"); + rVal.shaderVertexNumBonesLoc = glGetUniformLocation(rVal.shaderProgram, "numBones"); + } + rVal.shaderVertexHasBonesLoc = glGetUniformLocation(rVal.shaderProgram, "hasBones"); + + + + + return rVal; + } + public static ShaderProgram load_default_shader_program(){ + + + // + //Create ShaderProgram object + // + ShaderProgram rVal = new ShaderProgram(); + // + //Read in shader programs + // + String tempForReadingShaders = ""; + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource("/Shaders/VertexShader.vs").getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String vertexShaderSource = tempForReadingShaders; + //This try-catch block reads the FragmentShader source into memory + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource("/Shaders/FragmentShader.fs").getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String fragmentShaderSource = tempForReadingShaders; + //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" + rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); + //This alerts openGL to the presence of a vertex shader and points the shader at its source + glShaderSource(rVal.vertexShader, vertexShaderSource); + //Compiles the source for the vertex shader object + glCompileShader(rVal.vertexShader); + //The following tests if the vertex shader compiles successfully + int success; + success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Vertex Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader)); + } + //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader + rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + //This points the opengl shadder object to its proper source + glShaderSource(rVal.fragmentShader, fragmentShaderSource); + //This compiles the shader object + glCompileShader(rVal.fragmentShader); + //This tests for the success of the compile attempt + success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Fragment Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader)); + } + //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram + rVal.shaderProgram = glCreateProgram(); + //This attaches the vertex and fragment shaders to the program + glAttachShader(rVal.shaderProgram, rVal.vertexShader); + glAttachShader(rVal.shaderProgram, rVal.fragmentShader); + //This links the program to the GPU (I think its to the GPU anyway) + glLinkProgram(rVal.shaderProgram); + //Tests for the success of the shader program creation + success = glGetProgrami(rVal.shaderProgram, GL_LINK_STATUS); + if (success != GL_TRUE) { + throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); + } + + //Deletes the individual shader objects to free up memory + glDeleteShader(rVal.vertexShader); + glDeleteShader(rVal.fragmentShader); + + + + // + //Set locations + // + rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderProgram, "model"); + rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderProgram, "view"); + rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderProgram, "projection"); + rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderProgram, "viewPos"); + rVal.shaderVertexBonesLoc = glGetUniformLocation(rVal.shaderProgram, "bones"); + rVal.shaderVertexNumBonesLoc = glGetUniformLocation(rVal.shaderProgram, "numBones"); + rVal.shaderVertexHasBonesLoc = glGetUniformLocation(rVal.shaderProgram, "hasBones"); + + + + + return rVal; + } + + public static ShaderProgram loadSpecificShader(String vertexPath, String fragmentPath){ + ShaderProgram rVal = new ShaderProgram(); + + String vertex_shader_path = vertexPath; + String fragment_shader_path = fragmentPath; + // + //Read in shader programs + // + String tempForReadingShaders = ""; + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource(vertex_shader_path).getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String vertexShaderSource = tempForReadingShaders; + //This try-catch block reads the FragmentShader source into memory + try { + BufferedReader br = new BufferedReader(new FileReader(Main.class.getResource(fragment_shader_path).getFile())); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + tempForReadingShaders = sb.toString(); + } finally { + br.close(); + } + } catch (IOException e) { + } + String fragmentShaderSource = tempForReadingShaders; + //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" + rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); + //This alerts openGL to the presence of a vertex shader and points the shader at its source + glShaderSource(rVal.vertexShader, vertexShaderSource); + //Compiles the source for the vertex shader object + glCompileShader(rVal.vertexShader); + //The following tests if the vertex shader compiles successfully + int success; + success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Vertex Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader)); + } + //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader + rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + //This points the opengl shadder object to its proper source + glShaderSource(rVal.fragmentShader, fragmentShaderSource); + //This compiles the shader object + glCompileShader(rVal.fragmentShader); + //This tests for the success of the compile attempt + success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); + if (success != GL_TRUE) { + System.out.println("Fragment Shader failed to compile!"); + throw new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader)); + } + //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram + rVal.shaderProgram = glCreateProgram(); + //This attaches the vertex and fragment shaders to the program + glAttachShader(rVal.shaderProgram, rVal.vertexShader); + glAttachShader(rVal.shaderProgram, rVal.fragmentShader); + //This links the program to the GPU (I think its to the GPU anyway) + glLinkProgram(rVal.shaderProgram); + //Tests for the success of the shader program creation + success = glGetProgrami(rVal.shaderProgram, GL_LINK_STATUS); + if (success != GL_TRUE) { + throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); + } + + //Deletes the individual shader objects to free up memory + glDeleteShader(rVal.vertexShader); + glDeleteShader(rVal.fragmentShader); + + + + // + //Set locations + // + rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderProgram, "model"); + rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderProgram, "view"); + rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderProgram, "projection"); + rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderProgram, "viewPos"); + + + + + return rVal; + } + +} diff --git a/src/main/java/RendererObjects/texture/Texture.java b/src/main/java/RendererObjects/texture/Texture.java new file mode 100644 index 00000000..75001661 --- /dev/null +++ b/src/main/java/RendererObjects/texture/Texture.java @@ -0,0 +1,136 @@ +/* + * 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. + */ +package RendererObjects.texture; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.imageio.ImageIO; +import org.lwjgl.BufferUtils; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL14.*; +import static org.lwjgl.opengl.GL30.*; + +/** + * + * @author amaterasu + */ +public class Texture { + int texture_pointer; + int width; + int height; + boolean hasTransparency; + public Texture(){ + + } + public Texture(String path){ + //generate the texture object on gpu + texture_pointer = glGenTextures(); + //bind the new texture + glBindTexture(GL_TEXTURE_2D, texture_pointer); + //how are we gonna wrap the texture?? + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + //set the border color to black + float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + //set magnification and minification operation sampling strategies + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //load the image here + ByteBuffer data; + width = 1; + height = 1; + try { + BufferedImage image_data = ImageIO.read(new File(Thread.currentThread().getContextClassLoader().getResource(path).getFile())); + if ( + image_data.getType() == BufferedImage.TYPE_3BYTE_BGR || + image_data.getType() == BufferedImage.TYPE_INT_RGB + ){ + hasTransparency = false; + } else if( + image_data.getType() == BufferedImage.TYPE_4BYTE_ABGR || + image_data.getType() == BufferedImage.TYPE_INT_ARGB + ){ + hasTransparency = true; + } + width = image_data.getWidth(); + height = image_data.getHeight(); + if(hasTransparency){ + data = BufferUtils.createByteBuffer(width * height * 4); + } else { + data = BufferUtils.createByteBuffer(width * height * 3); + } + /* + imgBuffer = BufferUtils.createByteBuffer(4 * dimX * dimY); + for(int x = 0; x < dimX; x++){ + for(int y = 0; y < dimY; y++){ + Color temp = new Color(image_data.getRGB(x, y)); + data.put((byte)(temp.getRed()); + data.put((byte)(temp.getGreen()); + data.put((byte)(temp.getBlue()); + data.put((byte)(temp.getAlpha()); + } + } + imgBuffer.flip(); + */ + for(int y = height - 1; y > -1; y--){ + for(int x = 0; x < width; x++){ + Color temp = new Color(image_data.getRGB(x, y), true); + + data.put((byte)temp.getRed()); + data.put((byte)temp.getGreen()); + data.put((byte)temp.getBlue()); + if(hasTransparency){ + data.put((byte)temp.getAlpha()); + } +// data[x * y * 3 + 0] = temp.getRed(); +// data[x * y * 3 + 1] = temp.getGreen(); +// data[x * y * 3 + 2] = temp.getBlue(); + } + } + } catch (IOException ex) { + ex.printStackTrace(); + hasTransparency = false; + data = BufferUtils.createByteBuffer(3); + data.put((byte)0); + data.put((byte)0); + data.put((byte)0); + } + data.flip(); + //call if width != height so opengl figures out how to unpack it properly + if(width != height){ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + } + //buffer the texture information + if(hasTransparency){ + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + } + glGenerateMipmap(GL_TEXTURE_2D); + //OPTIONAL free the original image data now that it's on the gpu + System.gc(); + } + + public void bind(){ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_pointer); + } + + public void bind(int attrib_val){ + glActiveTexture(GL_TEXTURE0 + attrib_val); + glBindTexture(GL_TEXTURE_2D, texture_pointer); + } + + public boolean isTransparent(){ + return hasTransparency; + } +} diff --git a/src/main/java/RendererObjects/texture/TextureMap.java b/src/main/java/RendererObjects/texture/TextureMap.java new file mode 100644 index 00000000..d0c87c9f --- /dev/null +++ b/src/main/java/RendererObjects/texture/TextureMap.java @@ -0,0 +1,64 @@ +package RendererObjects.texture; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author amaterasu + */ +public class TextureMap { + //The convention is + //Map of strings (the name of a model) to a model + //each model is a map of a string (the name of a mesh) to a list which contains + //First the model's diffuse, then the model's specular + //always in that order + //if either the diffuse or the specular isn't included then it should + //instead contain and empty string - "" + //this convention must be followed + Map>> texture_map = new HashMap(); + + public Map> get_mesh_map(String name){ + return texture_map.get(name); + } + + public static ArrayList get_mesh_textures(Map> input, String name){ + if(input == null){ + //TODO: Add big fuckin' error here + return null; + } + return input.get(name); + } + + //for the lazy + public static String get_diffuse_path(ArrayList input){ + if(input == null || input.size() < 2){ + //TODO: Add big fuckin' error here + return null; + } + return input.get(0); + } + + //for the lazy + public static String get_specular_path(ArrayList input){ + if(input == null || input.size() < 2){ + //TODO: Add big fuckin' error here + return null; + } + return input.get(1); + } + + public TextureMap(){ + texture_map = new HashMap(); + } + public void add_model(String model_name){ + texture_map.put(model_name, new HashMap()); + } + public void add_mesh_to_model(String model_name, String mesh_name){ + ArrayList temp = new ArrayList(); + temp.add(""); + temp.add(""); + texture_map.get(model_name).put(mesh_name, temp); + } +} diff --git a/src/main/java/audio/AudioEngine.java b/src/main/java/audio/AudioEngine.java new file mode 100644 index 00000000..7fff6414 --- /dev/null +++ b/src/main/java/audio/AudioEngine.java @@ -0,0 +1,14 @@ +/* + * 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. + */ +package audio; + +/** + * + * @author amaterasu + */ +public class AudioEngine { + +} diff --git a/src/main/java/entity/Entity.java b/src/main/java/entity/Entity.java new file mode 100644 index 00000000..1d0ba15f --- /dev/null +++ b/src/main/java/entity/Entity.java @@ -0,0 +1,37 @@ +/* + * 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. + */ +package entity; + +import java.util.HashMap; + +/** + * + * @author amaterasu + */ +public class Entity { + + static int entity_id_iterator = 0; + + int id; + + HashMap data; + + + + public int getId() { + return id; + } + + public HashMap getData() { + return data; + } + + public Entity(){ + data = new HashMap(); + id = entity_id_iterator; + entity_id_iterator++; + } +} diff --git a/src/main/java/entity/EntityUtil.java b/src/main/java/entity/EntityUtil.java new file mode 100644 index 00000000..0276c50f --- /dev/null +++ b/src/main/java/entity/EntityUtil.java @@ -0,0 +1,45 @@ +/* + * 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. + */ +package entity; + +import RendererObjects.Model; +import main.Globals; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +/** + * + * @author amaterasu + */ +public class EntityUtil { + + public static Vector3f getEntityPosition(Entity e){ + return (Vector3f)e.getData().get("position"); + } + + public static Quaternionf getEntityRotation(Entity e){ + return (Quaternionf)e.getData().get("rotation"); + } + + public static Vector3f getEntityScale(Entity e){ + return (Vector3f)e.getData().get("scale"); + } + + public static Model getEntityModel(Entity e){ + return (Model)e.getData().get("model"); + } + + public static Entity spawnDrawableEntity(Model m){ + Entity rVal = new Entity(); + rVal.getData().put("model", m); + rVal.getData().put("position", new Vector3f(0,0,0)); + rVal.getData().put("rotation", new Quaternionf().rotateAxis((float)0, new Vector3f(1,0,0))); + rVal.getData().put("scale", new Vector3f(1,1,1)); + Globals.entity_list.add(rVal); + Globals.drawable_list.add(rVal); + return rVal; + } +} diff --git a/src/main/java/main/Globals.java b/src/main/java/main/Globals.java new file mode 100644 index 00000000..1bb106d9 --- /dev/null +++ b/src/main/java/main/Globals.java @@ -0,0 +1,93 @@ +package main; + +import RendererObjects.Camera; +import RendererObjects.Light.DirectionalLight; +import RendererObjects.Light.PointLight; +import RendererObjects.Light.SpotLight; +import RendererObjects.Material; +import RendererObjects.Model; +import RendererObjects.texture.Texture; +import RendererObjects.texture.TextureMap; +import com.google.gson.Gson; +import entity.Entity; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import util.ModelLoader; + +/** + * + * @author amaterasu + */ +public class Globals { + + // + //OpenGL - Other + // + //Array that holds all models that need to be shoved to the gpu + public static Matrix4f viewMatrix = new Matrix4f(); + public static Matrix4f projectionMatrix; + + + + public static Texture texture_diffuse_default; + public static Texture texture_specular_default; + public static Material material_default; + + public static DirectionalLight light_directional_default; + public static ArrayList light_point_list_default; + public static SpotLight light_spot_default; + + public static TextureMap texture_map_default; + + public static ArrayList entity_list; + public static ArrayList drawable_list; + + public static Camera camera_visible; + + // + //Game specific models + // + + //famous fuckin last words, but temporary solution + //global arraylist of values for the skybox colors + public static ArrayList skybox_colors; + + + + public static void init_globals(){ + //create default textures + texture_diffuse_default = new Texture("Textures/default_diffuse.png"); + texture_specular_default = new Texture("Textures/default_specular.png"); + //create default material + material_default = new Material(); + material_default.set_diffuse(texture_diffuse_default); + material_default.set_specular(texture_specular_default); + //create default lights + light_directional_default = new DirectionalLight(new Vector3f(0,-1f,0)); + //load in default texture map + Gson gson = new Gson(); + try { + //deserializes the texture map from its default path using gson + //also done in one line + texture_map_default = gson.fromJson(Files.newBufferedReader(new File(Thread.currentThread().getContextClassLoader().getResource("Textures/default_texture_map.json").getFile()).toPath()), TextureMap.class); //only the best of coding practices :) + } catch (IOException ex) { ex.printStackTrace(); } //TODO: handle better :tm: + //create entity list + entity_list = new ArrayList(); + drawable_list = new ArrayList(); + //create the camera object that generates view matrix + camera_visible = new Camera(); + //init game specific variables + init_game_specifics(); + //temporary hold for skybox colors + skybox_colors = new ArrayList(); + } + + public static void init_game_specifics(){ + } +} diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java new file mode 100644 index 00000000..c2b27685 --- /dev/null +++ b/src/main/java/main/Main.java @@ -0,0 +1,564 @@ +package main; + +import RendererObjects.Camera; +import RendererObjects.Material; +import RendererObjects.Model; +import RendererObjects.RenderUtils; +import RendererObjects.ShaderProgram; +import RendererObjects.texture.Texture; +import entity.Entity; +import entity.EntityUtil; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import org.joml.Matrix4f; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.lwjgl.glfw.*; +import static org.lwjgl.glfw.GLFW.*; +import org.lwjgl.opengl.*; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL13.*; +import static org.lwjgl.opengl.GL14.*; +import static org.lwjgl.opengl.GL15.*; +import static org.lwjgl.opengl.GL20.*; +import static org.lwjgl.opengl.GL30.*; +import static org.lwjgl.system.MemoryUtil.NULL; +import util.ModelLoader; +import util.util; + + +/** + * + * @author amaterasu + */ +public class Main { + // + //Generic OpenGL Statements + // + //Callback function for opengl errors + private final static GLFWErrorCallback ERROR_CALLBACK = GLFWErrorCallback.createPrint(System.err); + private static long window; + + + + + + + + // + //Visualization Controls + // + //These are used in calculating the time between frames for visualization (camera) control and such + public static float deltaTime = 0.0f; + public static float lastFrame = 0.0f; + //View Controls + public static float view_Range = 2000.0f; + public static Camera camera_Current = new Camera(); + /* + Mouse Controls + */ + static float mouse_lastX = 400; + static float mouse_lastY = 300; + static double xpos = 400; + static double ypos = 300; + static float mouseSensitivity = .1f; + static double mouse_X_Buffer[] = new double[1]; + static double mouse_Y_Buffer[] = new double[1]; + static float cameraSpeed; + static float yaw = 150; + static float pitch = 50; + + + + // + //Player Object Variables + // + public static boolean CAMERA_UNDER_USER_CONTROL = false; + public static boolean CAMERA_UNDER_FREE_CONTROL = false; + public static boolean PLAYER_UNDER_USER_CONTROL = true; + public static boolean CAMERA_IS_ORBIT = true; + public static float camera_Orbit_Length = 1.0f; +// public static Camera cam_Player_Orbit; + //Camera angles using theta-phi system + //Euler angles where theta is applied, then phi + //There is no bank applied to the camera + + public static Model model; + + + + + public static void main(String args[]){ + + // + // + // I N I T I A L I Z A T I O N + // + // + + //run initialization stuff + + //Create opengl + create_opengl_context(); + + //init global variables + Globals.init_globals(); + + + + + initWorld(); + + init_skybox(); + + + + Entity player = new Entity(); + player.getData().put("position", new Vector3f(0f,6f,0f)); + + + + + + /// + /// C A M E R A C R E A T I O N + /// + Camera camera_player_chase = new Camera(); + Camera cam_Player_Orbit = new Camera(); + + + + //main loop + while (!glfwWindowShouldClose(window)) { + + /* + Frame calculation + */ + float currentFrame = (float) glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + + //poll mouse variables and update camera variables + update_mouse_variables(); + + + float cam_Player_Orbit_Magnitude = 1f; + float cam_Player_Orbit_Offset_Height = 1f; + cam_Player_Orbit.pos_Center = new Vector3f(0, 0, 0); + cam_Player_Orbit.pos_Center.x = 0 + (float) Math.cos(yaw / 180.0f * Math.PI) * cam_Player_Orbit_Magnitude; + cam_Player_Orbit.pos_Center.y = 0 + (float) Math.sin(pitch / 180.0f * Math.PI) * cam_Player_Orbit_Magnitude; + cam_Player_Orbit.pos_Center.z = 0 + (float) Math.sin(yaw / 180.0f * Math.PI) * cam_Player_Orbit_Magnitude; + cam_Player_Orbit.pos_Center.normalize(); +// System.out.println(cam_Player_Orbit.pos_Center); + + + + if(CAMERA_IS_ORBIT){ + camera_Current = cam_Player_Orbit; + } + + + + + /// + /// I N P U T C O N T R O L S + /// + cameraSpeed = 2.5f * deltaTime; + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { + break; + } + if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { + if(CAMERA_UNDER_FREE_CONTROL) { + //cameraSpeed = cameraSpeed * 100; + } else if(PLAYER_UNDER_USER_CONTROL) { + + } + } + if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z)); + } + if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(camera_Current.pos_Center.x,0,camera_Current.pos_Center.z)); + } + if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z).rotateY((float)(-90 * Math.PI / 180))); + } + if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z).rotateY((float)(90 * Math.PI / 180))); + } + if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(0,0.6f,0)); + } + if(glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS){ + EntityUtil.getEntityPosition(player).add(new Vector3f(0,-0.6f,0)); + } + + +// camera_player_chase.pos_Center = new Vector3f(EntityUtil.getEntityPosition(player)).sub(EntityUtil.getEntityRotation(player).transform(new Vector3f(-1,1,0))); + + Globals.camera_visible.apply_camera(camera_player_chase); + + Globals.viewMatrix = Globals.camera_visible.get_view_matrix(); + Globals.viewMatrix = new Matrix4f().setLookAt(camera_Current.pos_Center, new Vector3f(0,0,0), new Vector3f(camera_Current.pos_Center).add(new Vector3f(0,1.0f,0))).scale(1.0f, 1.5f, 1.0f); + + //Sets the background color. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + + // + // Draw all entities + // + Iterator entity_iterator = Globals.drawable_list.iterator(); + while(entity_iterator.hasNext()){ + Entity currentEntity = entity_iterator.next(); + Model currentModel = EntityUtil.getEntityModel(currentEntity); + currentModel.modelMatrix = new Matrix4f(); + currentModel.modelMatrix.translate(new Vector3f(EntityUtil.getEntityPosition(currentEntity)).sub(EntityUtil.getEntityPosition(player))); + currentModel.modelMatrix.rotate(EntityUtil.getEntityRotation(currentEntity)); + currentModel.modelMatrix.scale(EntityUtil.getEntityScale(currentEntity)); + currentModel.draw(); + } + + + + //check and call events and swap the buffers + glfwSwapBuffers(window); + glfwPollEvents(); + } + //Terminate the program. + glfwTerminate(); + } + + static void sleep(int i) { + try { + TimeUnit.MILLISECONDS.sleep(i); + } catch (InterruptedException ex) { + System.out.println("Sleep somehow interrupted?!"); + } + } + + + + + + + + + + public static void create_opengl_context(){ + //Sets the variables that control the window sizing + int screenWidth = 1920; + int screenHeight = 1080; + //Initializes opengl + glfwInit(); + //Gives hints to glfw to control how opengl will be used + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + //Creates the window reference object + window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", NULL, NULL); + //Errors for failure to create window (IE: No GUI mode on linux ?) + if (window == NULL) { + System.out.println("Failed to make window."); + glfwTerminate(); + } + //Makes the window that was just created the current OS-level window context + glfwMakeContextCurrent(window); + //Maximize it + glfwMaximizeWindow(window); + //Creates the OpenGL capabilities for the program. + GL.createCapabilities(); + + //This enables Z-buffering so that farther-back polygons are not drawn over nearer ones + glEnable(GL_DEPTH_TEST); + + // Support for transparency + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + //Hide the cursor and capture it + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + + + + + //Points the texture uniforms in the shader programs at the correct variables + + + + + // + // Projection and View matrix creation + // + Globals.projectionMatrix = new Matrix4f(); + Globals.viewMatrix = new Matrix4f(); + float FOV = (float)(120.0f * Math.PI /180.0f); + Globals.projectionMatrix.setPerspective(FOV, 1.0f, 0.1f, view_Range); + Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f)); + } + + + public static void update_mouse_variables(){ + glfwGetCursorPos(window, mouse_X_Buffer, mouse_Y_Buffer); + xpos = mouse_X_Buffer[0]; + ypos = mouse_Y_Buffer[0]; + float xoffset = (float) (xpos - mouse_lastX) * mouseSensitivity; + float yoffset = (float) (mouse_lastY - ypos) * mouseSensitivity; + mouse_lastX = (float) xpos; + mouse_lastY = (float) ypos; + + yaw = yaw + xoffset; + pitch = pitch - yoffset; + + if (pitch > 100.0f) { + pitch = 100.0f; + } + if (pitch < -99.0f) { + pitch = -99.0f; + } + } + + static void init_skybox(){ + Model skyboxModel = RenderUtils.createSkyboxModel(null); + Entity skyboxEntity = EntityUtil.spawnDrawableEntity(skyboxModel); + EntityUtil.getEntityScale(skyboxEntity).mul(100); + + + Globals.skybox_colors.add(new Vector3f(200,200,160)); + Globals.skybox_colors.add(new Vector3f(200,200,160)); + Globals.skybox_colors.add(new Vector3f(200,100,50)); + Globals.skybox_colors.add(new Vector3f(200,100,50)); + Globals.skybox_colors.add(new Vector3f(50,100,150)); + Globals.skybox_colors.add(new Vector3f(50,100,150)); + Globals.skybox_colors.add(new Vector3f(10,10,10)); + Globals.skybox_colors.add(new Vector3f(10,10,10)); + } + + + //I swear it's a temporary function + /* + for(int angle = 0; angle < 45; angle=angle+2){ + for(int radius = 115; radius < 130; radius=radius+2){ + */ +// static float[] getTreePos(){ +// return new float[]{ +// 115.0f,7.0f,0.0f, +// 110.0f,7.0f,10.0f, +// +// 82.0f,7.0f,82.0f, +// }; +// } + + static void initWorld(){ + Model building_model = ModelLoader.load_Model_From_File("Models/arcdock5deg1Try2.fbx"); + Texture whiteTexture = new Texture("Textures/w1.png"); + Material whiteMaterial = new Material(); + whiteMaterial.set_diffuse(whiteTexture); + whiteMaterial.set_specular(whiteTexture); + building_model.meshes.get(0).set_material(whiteMaterial); + for(int i = 0; i < 36; i++){ + Entity arcCurrent = EntityUtil.spawnDrawableEntity(building_model); + float angleRad = i * 10; + float angleDeg = (float)(angleRad * Math.PI / 180); + float posX = (float)(Math.cos(angleDeg) * 100); + float posY = (float)(Math.sin(angleDeg) * 100); + EntityUtil.getEntityPosition(arcCurrent).set(posX, 0.01f, posY); + EntityUtil.getEntityScale(arcCurrent).set(1f); + EntityUtil.getEntityRotation(arcCurrent) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)((180-angleRad) * Math.PI / 180)) + ; + arcCurrent = EntityUtil.spawnDrawableEntity(building_model); + angleRad = i * 10 + 5; + angleDeg = (float)(angleRad * Math.PI / 180); + posX = (float)(Math.cos(angleDeg) * 100); + posY = (float)(Math.sin(angleDeg) * 100); + EntityUtil.getEntityPosition(arcCurrent).set(posX, 5.01f, posY); + EntityUtil.getEntityScale(arcCurrent).set(1f); + EntityUtil.getEntityRotation(arcCurrent) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)((180-angleRad) * Math.PI / 180)) + ; + } + + + Model dirtPlane = ModelLoader.load_Model_From_File("Models/groundplanemassiveuv.fbx"); + Texture dirtTexture = new Texture("Textures/Ground/Dirt1.png"); + Material dirtMaterial = new Material(); + dirtMaterial.set_diffuse(dirtTexture); + dirtMaterial.set_specular(dirtTexture); + dirtPlane.meshes.get(0).set_material(dirtMaterial); + for(int x = -120; x < 120; x=x+20){ + for(int y = -120; y < 120; y=y+20){ + Entity dirtPlaneEntity = EntityUtil.spawnDrawableEntity(dirtPlane); + EntityUtil.getEntityPosition(dirtPlaneEntity).set(x, -1.0f, y); + EntityUtil.getEntityScale(dirtPlaneEntity).set(10f); + EntityUtil.getEntityRotation(dirtPlaneEntity) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + ; + } + } + + Model tree2 = ModelLoader.load_Model_From_File("Models/tree2.fbx"); + Texture leavesTexture = new Texture("Textures/leaves.png"); + Material leavesMaterial = new Material(); + leavesMaterial.set_diffuse(leavesTexture); + leavesMaterial.set_specular(leavesTexture); + Texture trunkTexture = new Texture("Textures/trunk.png"); + Material trunkMaterial = new Material(); + trunkMaterial.set_diffuse(trunkTexture); + trunkMaterial.set_specular(trunkTexture); + tree2.meshes.get(0).set_material(trunkMaterial); + tree2.meshes.get(1).set_material(leavesMaterial); + tree2.meshes.get(2).set_material(leavesMaterial); + Random treeRand = new Random(); + + ArrayList treeList = new ArrayList(); + for(int angle = -105; angle < 45; angle=angle+2){ + for(int radius = 115; radius < 140; radius=radius+2){ + Entity treeEntity = EntityUtil.spawnDrawableEntity(tree2); + EntityUtil.getEntityPosition(treeEntity).set( + (float)Math.cos(angle * Math.PI / 180) * radius + (treeRand.nextFloat() - 0.5f) * 2, + radius - 113 + treeRand.nextFloat(), + (float)Math.sin(angle * Math.PI / 180) * radius + (treeRand.nextFloat() - 0.5f) * 2 + ); + EntityUtil.getEntityScale(treeEntity).set(1f); + EntityUtil.getEntityRotation(treeEntity) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)((treeRand.nextFloat() * 359) * Math.PI / 180)) + ; + treeList.add(treeEntity); + } + } +// float[] treepos = getTreePos(); +// for(int i = 0; i < treepos.length/3; i++){ +// float posX = treepos[i*3]; +// float posY = treepos[i*3+1]; +// float posZ = treepos[i*3+2]; +// Entity treeEntity = EntityUtil.spawnDrawableEntity(tree2); +// EntityUtil.getEntityPosition(treeEntity).set(posX,posY,posZ); +// EntityUtil.getEntityScale(treeEntity).set(1f); +// EntityUtil.getEntityRotation(treeEntity) +// .identity() +// .rotateLocalX((float)(-Math.PI / 2)) +// .rotateLocalY((float)((treeRand.nextFloat() * 359) * Math.PI / 180)) +// ; +// treeList.add(treeEntity); +// } + + Model arenaSpire = ModelLoader.load_Model_From_File("Models/ArenaSpire1.fbx"); + arenaSpire.meshes.get(0).set_material(whiteMaterial); + Entity spireEntity = EntityUtil.spawnDrawableEntity(arenaSpire); + EntityUtil.getEntityRotation(spireEntity) + .identity() + .rotateLocalZ((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(220) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(spireEntity).set(-105, 0, 0); + + Model railTrackModel = ModelLoader.load_Model_From_File("Models/RailTrack1Part1.fbx"); + Texture railTrackTexture = new Texture("Textures/RailTrack1Part1.png"); + Material railTrackMaterial = new Material(); + railTrackMaterial.set_diffuse(railTrackTexture); + railTrackMaterial.set_specular(railTrackTexture); + railTrackModel.meshes.get(0).set_material(railTrackMaterial); + Entity railTrackEntity = EntityUtil.spawnDrawableEntity(railTrackModel); + EntityUtil.getEntityRotation(railTrackEntity) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(0) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railTrackEntity).set(-15, 10, -20); + + Model railSupportModel = ModelLoader.load_Model_From_File("Models/MonorailSupport.fbx"); + Texture railSupportTexture = new Texture("Textures/MonorailSupport.png"); + Material railSupportMaterial = new Material(); + railSupportMaterial.set_diffuse(railSupportTexture); + railSupportMaterial.set_specular(railSupportTexture); + railSupportModel.meshes.get(0).set_material(railSupportMaterial); + + //support 1 + Entity railSupport1 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport1) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(180) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport1).set(0, -71.5f, -125); + + //support 2 + Entity railSupport2 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport2) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(200) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport2).set(30, -69.5f, -115); + + //support 3 + Entity railSupport3 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport3) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(217) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport3).set(62, -65.5f, -95); + + //support 4 + Entity railSupport4 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport4) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(222) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport4).set(90, -61f, -70); + + //support 5 + Entity railSupport5 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport5) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(235) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport5).set(121, -57.5f, -25); + + //support 6 + Entity railSupport6 = EntityUtil.spawnDrawableEntity(railSupportModel); + EntityUtil.getEntityRotation(railSupport6) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(265) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(railSupport6).set(135, -58.5f, 30); + + + Model tallBuildingModel = ModelLoader.load_Model_From_File("Models/tallbuilding1.fbx"); + tallBuildingModel.meshes.get(0).set_material(whiteMaterial); + Entity tallBuildingEntity1 = EntityUtil.spawnDrawableEntity(tallBuildingModel); + EntityUtil.getEntityRotation(tallBuildingEntity1) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(0) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(tallBuildingEntity1).set(200, 0.0f, -80); + EntityUtil.getEntityScale(tallBuildingEntity1).set(0.6f, 0.6f, 1f); + + Entity tallBuildingEntity2 = EntityUtil.spawnDrawableEntity(tallBuildingModel); + EntityUtil.getEntityRotation(tallBuildingEntity2) + .identity() + .rotateLocalX((float)(-Math.PI / 2)) + .rotateLocalY((float)(-(35) * Math.PI / 180)) + ; + EntityUtil.getEntityPosition(tallBuildingEntity2).set(190, 10.0f, 10.0f); + EntityUtil.getEntityScale(tallBuildingEntity2).set(0.5f, 0.5f, 1f); + } + +} diff --git a/src/main/java/net/Client.java b/src/main/java/net/Client.java new file mode 100644 index 00000000..76a14a5d --- /dev/null +++ b/src/main/java/net/Client.java @@ -0,0 +1,14 @@ +/* + * 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. + */ +package net; + +/** + * + * @author amaterasu + */ +public class Client { + +} diff --git a/src/main/java/net/Server.java b/src/main/java/net/Server.java new file mode 100644 index 00000000..6ecf220c --- /dev/null +++ b/src/main/java/net/Server.java @@ -0,0 +1,14 @@ +/* + * 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. + */ +package net; + +/** + * + * @author amaterasu + */ +public class Server { + +} diff --git a/src/main/java/util/ModelLoader.java b/src/main/java/util/ModelLoader.java new file mode 100644 index 00000000..8eae31f7 --- /dev/null +++ b/src/main/java/util/ModelLoader.java @@ -0,0 +1,85 @@ +package util; + +import main.Globals; +import RendererObjects.Material; +import RendererObjects.Mesh; +import RendererObjects.Model; +import RendererObjects.texture.Texture; +import RendererObjects.texture.TextureMap; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.lwjgl.assimp.AIScene; +import static org.lwjgl.assimp.Assimp.*; +import static org.lwjgl.assimp.Assimp.aiImportFile; + +public class ModelLoader { + public static Model load_Model_From_File(String fileName){ + Model rVal; + AIScene scene; + File file = new File(Thread.currentThread().getContextClassLoader().getResource(fileName).getFile()); + scene = aiImportFile(file.getAbsolutePath(), + aiProcess_GenSmoothNormals | + aiProcess_JoinIdenticalVertices | + aiProcess_Triangulate | + aiProcess_FixInfacingNormals | + aiProcess_LimitBoneWeights); + if(scene == null){ + throw new IllegalStateException(aiGetErrorString()); + } + rVal = Model.create_model_from_aiscene(scene); + attempt_add_textures_from_pathname(fileName, rVal); + return rVal; + } + + //TODO: this logic should exclusively use functions provided in the TextureMap class + //this way if we change the underlying structure of the TextureMap it doesn't fuck over this logic + static void attempt_add_textures_from_pathname(String path, Model m){ + //first we get the default texture map that's global + TextureMap global_map = Globals.texture_map_default; + //then we try to get the path of our model from the map + Map> mesh_map = global_map.get_mesh_map(path); + //if it exists.. + if(mesh_map != null){ + //iterate through each mesh in the model that was provided as input + Iterator mesh_iterator = m.meshes.iterator(); + while(mesh_iterator.hasNext()){ + Mesh current_mesh = mesh_iterator.next(); + //if the current iteration is contained within the mesh map we procured from above + if(mesh_map.containsKey(current_mesh.nodeID)){ + //we create a new material, check if the diffuse or specular is not null, + //and if they aren't we add that path as a new texture of respective type to the material + Material final_material = new Material(); + ArrayList texture_path_list = mesh_map.get(current_mesh.nodeID); + String diffuse_path = TextureMap.get_diffuse_path(texture_path_list); + if(diffuse_path != null){ + System.out.println(diffuse_path); + Texture diffuse = new Texture(diffuse_path); + final_material.set_diffuse(diffuse); + System.out.println(diffuse); + } else { + final_material.set_diffuse(Globals.texture_diffuse_default); + } + String specular_path = TextureMap.get_specular_path(texture_path_list); + if(specular_path != null){ + Texture specular = new Texture(specular_path); + final_material.set_specular(specular); + System.out.println(specular); + } else { + final_material.set_specular(Globals.texture_specular_default); + } + //once we've either added default textures or actual textures, + //set the current mesh's material to this new one + current_mesh.set_material(final_material); + } + } + } + } +} diff --git a/src/main/java/util/util.java b/src/main/java/util/util.java new file mode 100644 index 00000000..23a19873 --- /dev/null +++ b/src/main/java/util/util.java @@ -0,0 +1,234 @@ +package util; + +import RendererObjects.Material; +import RendererObjects.Mesh; +import RendererObjects.Model; +import RendererObjects.ShaderProgram; +import RendererObjects.texture.Texture; +import RendererObjects.texture.TextureMap; +import com.google.gson.Gson; +import java.io.File; +import java.io.IOException; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; +import org.lwjgl.assimp.AIMatrix4x4; +import static org.lwjgl.opengl.GL30.glBindVertexArray; +import static org.lwjgl.opengl.GL30.glGenVertexArrays; +/** + * + * @author awhoove + */ +public class util { + + + + public static Matrix4f convertAIMatrix(AIMatrix4x4 mat){ + Matrix4f rVal = new Matrix4f(); + //Old, wrong approach: +// mat.set( +// mat.a1(), +// mat.b1(), +// mat.c1(), +// mat.d1(), +// mat.a2(), +// mat.b2(), +// mat.c2(), +// mat.d2(), +// mat.a3(), +// mat.b3(), +// mat.c3(), +// mat.d3(), +// mat.a4(), +// mat.b4(), +// mat.c4(), +// mat.d4() +// ); + //as demo'd in https://github.com/lwjglgamedev/lwjglbook/blob/master/chapter27/c27-p2/src/main/java/org/lwjglb/engine/loaders/assimp/AnimMeshesLoader.java + rVal.m00(mat.a1()); + rVal.m10(mat.a2()); + rVal.m20(mat.a3()); + rVal.m30(mat.a4()); + rVal.m01(mat.b1()); + rVal.m11(mat.b2()); + rVal.m21(mat.b3()); + rVal.m31(mat.b4()); + rVal.m02(mat.c1()); + rVal.m12(mat.c2()); + rVal.m22(mat.c3()); + rVal.m32(mat.c4()); + rVal.m03(mat.d1()); + rVal.m13(mat.d2()); + rVal.m23(mat.d3()); + rVal.m33(mat.d4()); + return rVal; + } + + public static Model create_terrain_model(float[][] heightfield){ + Model rVal = new Model(); + rVal.meshes = new ArrayList(); + Mesh m = new Mesh(); + int width = heightfield.length; + int height = heightfield[0].length; + FloatBuffer vertices = BufferUtils.createFloatBuffer(width * height * 3); + FloatBuffer normals = BufferUtils.createFloatBuffer(width * height * 3); + IntBuffer faces = BufferUtils.createIntBuffer((width - 1) * (height - 1) * 2 * 3); + FloatBuffer texture_coords = BufferUtils.createFloatBuffer(width * height * 2); + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + //deal with vertex + vertices.put(x); + vertices.put(heightfield[x][y]); + vertices.put(y); + //deal with normal + if(x < width - 1){ + if(y < height - 1){ + float hL; + if(x > 0){ + hL = heightfield[x-1][y]; + } else { + hL = heightfield[x][y]; + } + float hR = heightfield[x+1][y]; + float hD = heightfield[x][y+1]; + float hU; + if(y > 0){ + hU = heightfield[x][y-1]; + } else { + hU = heightfield[x][y]; + } + Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); + Normal.normalize(); + normals.put(Normal.x); + normals.put(Normal.y); + normals.put(Normal.z); + } else { + float hL; + if(x > 0){ + hL = heightfield[x-1][y]; + } else { + hL = heightfield[x][y]; + } + float hR = heightfield[x+1][y]; + float hD = heightfield[x][y]; + float hU = heightfield[x][y-1]; + Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); + Normal.normalize(); + normals.put(Normal.x); + normals.put(Normal.y); + normals.put(Normal.z); + } + } else { + if(y < height - 1){ + float hL = heightfield[x-1][y]; + float hR = heightfield[x][y]; + float hD = heightfield[x][y+1]; + float hU; + if(y > 0){ + hU = heightfield[x][y-1]; + } else { + hU = heightfield[x][y]; + } + Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); + Normal.normalize(); + normals.put(Normal.x); + normals.put(Normal.y); + normals.put(Normal.z); + } else { + float hL = heightfield[x-1][y]; + float hR = heightfield[x][y]; + float hD = heightfield[x][y]; + float hU = heightfield[x][y-1]; + Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU); + Normal.normalize(); + normals.put(Normal.x); + normals.put(Normal.y); + normals.put(Normal.z); + } + } + //deal with texture coordinates + if(x % 2 == 0){ + if(y % 2 == 0){ + texture_coords.put(0); + texture_coords.put(0); + } else { + texture_coords.put(0); + texture_coords.put(1); + } + } else { + if(y % 2 == 0){ + texture_coords.put(1); + texture_coords.put(0); + } else { + texture_coords.put(1); + texture_coords.put(1); + } + } + //deal with faces + if(x < width - 1 && y < height - 1){ + faces.put((x + 0) * height + (y + 0)); + faces.put((x + 0) * height + (y + 1)); + faces.put((x + 1) * height + (y + 0)); + faces.put((x + 1) * height + (y + 0)); + faces.put((x + 0) * height + (y + 1)); + faces.put((x + 1) * height + (y + 1)); + } + } + } + vertices.flip(); + normals.flip(); + faces.flip(); + texture_coords.flip(); + + m.vertexArrayObject = glGenVertexArrays(); + glBindVertexArray(m.vertexArrayObject); + //buffer vertices + m.buffer_vertices(vertices); + //buffer normals + m.buffer_normals(normals); + //buffer faces + m.buffer_faces(faces); + //buffer texture coords + m.buffer_texture_coords(texture_coords); + m.shader = ShaderProgram.smart_assemble_shader(false,true); + glBindVertexArray(0); + m.parent = rVal; + + Material grass_mat = new Material(); + Texture grass_texture = new Texture("Textures/grass_texture.jpg"); + grass_mat.set_diffuse(grass_texture); + grass_mat.set_specular(grass_texture); + m.set_material(grass_mat); + + rVal.meshes.add(m); + return rVal; + } + + public static void save_test_texture_map_to_location(String s){ + TextureMap t = new TextureMap(); + t.add_model("model1"); + t.add_mesh_to_model("model1", "mesh1"); + t.add_mesh_to_model("model1", "mesh2"); + t.add_mesh_to_model("model1", "mesh3"); + t.add_model("model2"); + t.add_mesh_to_model("model2", "mesh1"); + t.add_mesh_to_model("model2", "mesh2"); + t.add_model("model3"); + t.add_mesh_to_model("model3", "mesh1"); + t.add_mesh_to_model("model3", "mesh2"); + t.add_mesh_to_model("model3", "mesh3"); + t.add_mesh_to_model("model3", "mesh4"); + Gson gson = new Gson(); + try { + Files.write(new File(s).toPath(), gson.toJson(t).getBytes()); + } catch (IOException ex) { + ex.printStackTrace(); // just for testing :thinking: + } + } +} diff --git a/src/main/resources/Models/ArenaSpire1.fbx b/src/main/resources/Models/ArenaSpire1.fbx new file mode 100644 index 00000000..d2f5894d Binary files /dev/null and b/src/main/resources/Models/ArenaSpire1.fbx differ diff --git a/src/main/resources/Models/MonorailSupport.fbx b/src/main/resources/Models/MonorailSupport.fbx new file mode 100644 index 00000000..26d349f3 Binary files /dev/null and b/src/main/resources/Models/MonorailSupport.fbx differ diff --git a/src/main/resources/Models/RailTrack1Part1.fbx b/src/main/resources/Models/RailTrack1Part1.fbx new file mode 100644 index 00000000..c9877c2d Binary files /dev/null and b/src/main/resources/Models/RailTrack1Part1.fbx differ diff --git a/src/main/resources/Models/Wheat1.fbx b/src/main/resources/Models/Wheat1.fbx new file mode 100644 index 00000000..ac19fc3d Binary files /dev/null and b/src/main/resources/Models/Wheat1.fbx differ diff --git a/src/main/resources/Models/arcdock5deg1Try2.fbx b/src/main/resources/Models/arcdock5deg1Try2.fbx new file mode 100644 index 00000000..b17f32c1 Binary files /dev/null and b/src/main/resources/Models/arcdock5deg1Try2.fbx differ diff --git a/src/main/resources/Models/arcdock5deg1notex.fbx b/src/main/resources/Models/arcdock5deg1notex.fbx new file mode 100644 index 00000000..95e858d6 Binary files /dev/null and b/src/main/resources/Models/arcdock5deg1notex.fbx differ diff --git a/src/main/resources/Models/groundplanemassiveuv.fbx b/src/main/resources/Models/groundplanemassiveuv.fbx new file mode 100644 index 00000000..302a6a38 Binary files /dev/null and b/src/main/resources/Models/groundplanemassiveuv.fbx differ diff --git a/src/main/resources/Models/plane.fbx b/src/main/resources/Models/plane.fbx new file mode 100644 index 00000000..7c2ca253 Binary files /dev/null and b/src/main/resources/Models/plane.fbx differ diff --git a/src/main/resources/Models/skyscraper1.fbx b/src/main/resources/Models/skyscraper1.fbx new file mode 100644 index 00000000..1f6d3437 Binary files /dev/null and b/src/main/resources/Models/skyscraper1.fbx differ diff --git a/src/main/resources/Models/tallbuilding1.fbx b/src/main/resources/Models/tallbuilding1.fbx new file mode 100644 index 00000000..162ce0f5 Binary files /dev/null and b/src/main/resources/Models/tallbuilding1.fbx differ diff --git a/src/main/resources/Models/test3.fbx b/src/main/resources/Models/test3.fbx new file mode 100644 index 00000000..447c9713 Binary files /dev/null and b/src/main/resources/Models/test3.fbx differ diff --git a/src/main/resources/Models/test5.fbx b/src/main/resources/Models/test5.fbx new file mode 100644 index 00000000..fdf380a3 Binary files /dev/null and b/src/main/resources/Models/test5.fbx differ diff --git a/src/main/resources/Models/tree2.fbx b/src/main/resources/Models/tree2.fbx new file mode 100644 index 00000000..58437755 Binary files /dev/null and b/src/main/resources/Models/tree2.fbx differ diff --git a/src/main/resources/Shaders/FragmentShader.fs b/src/main/resources/Shaders/FragmentShader.fs new file mode 100644 index 00000000..06a3b4ea --- /dev/null +++ b/src/main/resources/Shaders/FragmentShader.fs @@ -0,0 +1,148 @@ + + +#version 430 core +out vec4 FragColor; + +struct Material { + sampler2D diffuse; + sampler2D specular; + float shininess; +}; + +struct DirLight { + vec3 direction; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { + vec3 position; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct SpotLight { + vec3 position; + vec3 direction; + float cutOff; + float outerCutOff; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +#define NR_POINT_LIGHTS 10 + +in vec3 FragPos; +in vec3 Normal; +in vec2 TexCoord; + +uniform vec3 viewPos; +uniform DirLight dirLight; +uniform PointLight pointLights[NR_POINT_LIGHTS]; +uniform SpotLight spotLight; +uniform Material material; + +//texture stuff +uniform sampler2D ourTexture; +uniform int hasTransparency; + + +// function prototypes +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir); + +void main(){ + if(hasTransparency == 1){ + if(texture(material.diffuse, TexCoord).a < 0.1){ + discard; + } + } + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + vec3 result = CalcDirLight(dirLight, norm, viewDir); + //for(int i = 0; i < NR_POINT_LIGHTS; i++){ + // result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); + //} + //result += CalcSpotLight(spotLight, norm, FragPos, viewDir); + FragColor = vec4(result, texture(material.diffuse, TexCoord).a);//texture(ourTexture, TexCoord);//vec4(result, 1.0); +} + +// calculates the color when using a directional light. +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir){ + vec3 lightDir = normalize(-light.direction); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // combine results + vec3 texColor = texture(material.diffuse, TexCoord).rgb; + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord).rgb); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord).rgb); + //vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb); + return (ambient + diffuse);// + specular); +} + + +// calculates the color when using a point light. +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir){ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // combine results + vec3 ambient = light.ambient * vec4(texture(material.diffuse, TexCoord)).xyz; + vec3 diffuse = light.diffuse * diff * vec4(texture(material.diffuse, TexCoord)).xyz; + vec3 specular = light.specular * spec * vec4(texture(material.specular, TexCoord)).xyz; + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + return (ambient + diffuse + specular); +} + +// calculates the color when using a spot light. +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // spotlight intensity + float theta = dot(lightDir, normalize(-light.direction)); + float epsilon = light.cutOff - light.outerCutOff; + float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); + ambient *= attenuation * intensity; + diffuse *= attenuation * intensity; + specular *= attenuation * intensity; + return (ambient + diffuse + specular); +} \ No newline at end of file diff --git a/src/main/resources/Shaders/VertexShader.vs b/src/main/resources/Shaders/VertexShader.vs new file mode 100644 index 00000000..be244168 --- /dev/null +++ b/src/main/resources/Shaders/VertexShader.vs @@ -0,0 +1,56 @@ +//Vertex Shader +#version 430 core + + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec4 aWeights; +layout (location = 3) in vec4 aIndex; +layout (location = 4) in vec2 aTex; + + +//coordinate space transformation matrices +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +//bone related variables +const int MAX_WEIGHTS = 4; +const int MAX_BONES = 100; +uniform mat4 bones[MAX_BONES]; +uniform int hasBones; +uniform int numBones; + + + +//output buffers +out vec3 Normal; +out vec3 FragPos; +out vec2 TexCoord; + + + + +void main() +{ + //calculate bone transform + mat4 BoneTransform = (bones[int(aIndex[0])] * aWeights[0]); + BoneTransform = BoneTransform + (bones[int(aIndex[1])] * aWeights[1]); + BoneTransform = BoneTransform + (bones[int(aIndex[2])] * aWeights[2]); + BoneTransform = BoneTransform + (bones[int(aIndex[3])] * aWeights[3]); + //apply bone transform to position vectors + vec4 FinalVertex = BoneTransform * vec4(aPos, 1.0); + vec4 FinalNormal = BoneTransform * vec4(aNormal, 1.0); + //make sure the W component is 1.0 + FinalVertex = vec4(FinalVertex.xyz, 1.0); + FinalNormal = vec4(FinalNormal.xyz, 1.0); + //push frag, normal, and texture positions to fragment shader + FragPos = vec3(model * FinalVertex); + Normal = mat3(transpose(inverse(model))) * aNormal; + TexCoord = aTex; + //set final position with opengl space + gl_Position = projection * view * model * FinalVertex; +} \ No newline at end of file diff --git a/src/main/resources/Shaders/VertexShaderNoBones.vs b/src/main/resources/Shaders/VertexShaderNoBones.vs new file mode 100644 index 00000000..a7060dd9 --- /dev/null +++ b/src/main/resources/Shaders/VertexShaderNoBones.vs @@ -0,0 +1,39 @@ +//Vertex Shader +#version 430 core + + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 4) in vec2 aTex; + + +//coordinate space transformation matrices +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + + + +//output buffers +out vec3 Normal; +out vec3 FragPos; +out vec2 TexCoord; + + + + +void main() +{ + //normalize posiiton and normal + vec4 FinalVertex = vec4(aPos, 1.0); + vec4 FinalNormal = vec4(aNormal, 1.0); + //push frag, normal, and texture positions to fragment shader + FragPos = vec3(model * FinalVertex); + Normal = mat3(transpose(inverse(model))) * aNormal; + TexCoord = aTex; + //set final position with opengl space + gl_Position = projection * view * model * FinalVertex; +} diff --git a/src/main/resources/Shaders/backup/FragmentShader.fs b/src/main/resources/Shaders/backup/FragmentShader.fs new file mode 100644 index 00000000..b9c17f24 --- /dev/null +++ b/src/main/resources/Shaders/backup/FragmentShader.fs @@ -0,0 +1,165 @@ + + +#version 430 core +out vec4 FragColor; + +struct Material { + sampler2D diffuse; + sampler2D specular; + float shininess; +}; + +struct DirLight { + vec3 direction; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { + vec3 position; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct SpotLight { + vec3 position; + vec3 direction; + float cutOff; + float outerCutOff; + + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +#define NR_POINT_LIGHTS 4 + +in vec3 FragPos; +in vec3 Normal; +in vec2 TexCoords; + + +uniform int fragHasTexture; + +uniform vec3 viewPos; +uniform DirLight dirLight; +uniform PointLight pointLights[NR_POINT_LIGHTS]; +uniform SpotLight spotLight; +uniform Material material; + +// function prototypes +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir); + +void main() +{ + // properties + vec3 norm = normalize(Normal); + vec3 viewDir = normalize(viewPos - FragPos); + + // == ===================================================== + // Our lighting is set up in 3 phases: directional, point lights and an optional flashlight + // For each phase, a calculate function is defined that calculates the corresponding color + // per lamp. In the main() function we take all the calculated colors and sum them up for + // this fragment's final color. + // == ===================================================== + // phase 1: directional lighting + vec3 result = CalcDirLight(dirLight, norm, viewDir); + // phase 2: point lights + //for(int i = 0; i < NR_POINT_LIGHTS; i++) + // result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); + // phase 3: spot light + //result += CalcSpotLight(spotLight, norm, FragPos, viewDir); + + FragColor = vec4(result, 1.0); +} + +// calculates the color when using a directional light. +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) +{ + vec3 lightDir = normalize(-light.direction); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // combine results + vec3 ambient = vec3(1.0,1.0,1.0); + vec3 diffuse = vec3(1.0,1.0,1.0); + vec3 specular = vec3(1.0,1.0,1.0); + if(fragHasTexture == 1){ + ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); + diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); + specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); + } else { + ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); + diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); + specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); + } + //vec3 ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); + //vec3 diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); + //vec3 specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); + return (ambient + diffuse);// + specular); +} + +// calculates the color when using a point light. +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + return (ambient + diffuse + specular); +} + +// calculates the color when using a spot light. +vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attenuation + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); + // spotlight intensity + float theta = dot(lightDir, normalize(-light.direction)); + float epsilon = light.cutOff - light.outerCutOff; + float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); + // combine results + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + ambient *= attenuation * intensity; + diffuse *= attenuation * intensity; + specular *= attenuation * intensity; + return (ambient + diffuse + specular); +} + diff --git a/src/main/resources/Shaders/backup/NewVertexShader.vs b/src/main/resources/Shaders/backup/NewVertexShader.vs new file mode 100644 index 00000000..01885edb --- /dev/null +++ b/src/main/resources/Shaders/backup/NewVertexShader.vs @@ -0,0 +1,97 @@ +//Vertex Shader +#version 430 core + + + + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec4 aWeights; +layout (location = 3) in vec4 aIndex; +layout (location = 4) in vec2 aText; + + + +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + + +const int MAX_BONES = 100; +uniform mat4 bones[MAX_BONES]; +uniform int hasBones; +uniform int numBones; + +uniform int hasTexture; + + + +out vec3 Normal; +out vec3 FragPos; +out vec2 TexCoords; + + + + +void main() +{ + vec4 FinalVertex = vec4(aPos, 1.0); + vec4 FinalNormal = vec4(aNormal, 0.0); + if(hasBones == 1){ + //mat4 BoneTransform; + //for(int i = 0; i < MAX_BONES; i++){ + // if(i < numBones){ + // BoneTransform += bones[i] * aWeights[i]; + // } + //} + //vec4 FinalVertex = vec4(aPos, 1.0); + //vec4 FinalNormal = vec4(aNormal, 1.0); + //mat4 BoneTransform; + //BoneTransform = mat4( + // 1.0,0.0,0.0,0.0, + // 0.0,1.0,0.0,0.0, + // 0.0,0.0,1.0,0.0, + // 0.0,0.0,0.0,1.0); + //BoneTransform = BoneTransform * mat4( + // 1.0,0.0,0.0,0.0, + // 0.0,1.0,0.0,0.0, + // 0.0,0.0,2.0,0.0, + // 0.0,0.0,0.0,1.0); + //BoneTransform = BoneTransform * bones[aIndex[0]] * aWeights[0]; + //BoneTransform += bones[aIndex[0]] * 1.0; + //BoneTransform += bones[aIndex[1]] * aWeights[1]; + //BoneTransform += bones[aIndex[2]] * aWeights[2]; + //BoneTransform += bones[aIndex[3]] * aWeights[3]; + //FinalVertex = BoneTransform * FinalVertex; + vec4 inputVertex = FinalVertex; + vec4 inputNormal = FinalNormal; + //mat4 BoneTransform; + //BoneTransform = bones[int(aIndex[0])] * aWeights[0]; + //BoneTransform += bones[int(aIndex[1])] * aWeights[1]; + //BoneTransform += bones[int(aIndex[2])] * aWeights[2]; + //BoneTransform += bones[int(aIndex[3])] * aWeights[3]; + //FinalVertex = BoneTransform * inputVertex; + //FinalNormal = BoneTransform * inputNormal; + FinalVertex = (bones[int(aIndex[0])] * inputVertex) * aWeights[0]; + FinalVertex = (bones[int(aIndex[1])] * inputVertex) * aWeights[1] + FinalVertex; + FinalVertex = (bones[int(aIndex[2])] * inputVertex) * aWeights[2] + FinalVertex; + FinalVertex = (bones[int(aIndex[3])] * inputVertex) * aWeights[3] + FinalVertex; + FinalNormal = (bones[int(aIndex[0])] * inputNormal) * aWeights[0]; + FinalNormal = (bones[int(aIndex[1])] * inputNormal) * aWeights[1] + FinalNormal; + FinalNormal = (bones[int(aIndex[2])] * inputNormal) * aWeights[2] + FinalNormal; + FinalNormal = (bones[int(aIndex[3])] * inputNormal) * aWeights[3] + FinalNormal; + } else { + //gl_Position = projection * view * model * vec4(aPos, 1.0); + } + + vec2 FinalTexture = vec2(1.0,1.0); + if(hasTexture == 1){ + FinalTexture = aText; + } + TexCoords = FinalTexture; + + FragPos = vec3(model * FinalVertex); + Normal = vec3(transpose(inverse(model)) * FinalNormal); + gl_Position = projection * view * model * FinalVertex; +} \ No newline at end of file diff --git a/src/main/resources/Shaders/old/LampShader.fs b/src/main/resources/Shaders/old/LampShader.fs new file mode 100644 index 00000000..34b7eeca --- /dev/null +++ b/src/main/resources/Shaders/old/LampShader.fs @@ -0,0 +1,13 @@ +//Fragment Shader +#version 330 core + + +out vec4 FragColor; + +uniform vec3 objectColor; +uniform vec3 lightColor; + +void main() +{ +FragColor = vec4(1.0); +} diff --git a/src/main/resources/Shaders/old/VertexShader.vs b/src/main/resources/Shaders/old/VertexShader.vs new file mode 100644 index 00000000..b1013f2a --- /dev/null +++ b/src/main/resources/Shaders/old/VertexShader.vs @@ -0,0 +1,68 @@ +//Vertex Shader +#version 430 core + + + + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec4 aWeights; +layout (location = 3) in ivec4 aIndex; + + + +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + + +const int MAX_BONES = 100; +uniform mat4 bones[MAX_BONES]; +uniform int hasBones; +uniform int numBones; + + + +out vec3 Normal; +out vec3 FragPos; +out vec2 TexCoords; + + + +void main() +{ + if(hasBones == 1){ + //mat4 BoneTransform; + //for(int i = 0; i < MAX_BONES; i++){ + // if(i < numBones){ + // BoneTransform += bones[i] * aWeights[i]; + // } + //} + mat4 BoneTransform; + BoneTransform = mat4( + 1.0,0.0,0.0,0.0, + 0.0,1.0,0.0,0.0, + 0.0,0.0,1.0,0.0, + 0.0,0.0,0.0,1.0); + //BoneTransform = BoneTransform * mat4( + // 1.0,0.0,0.0,0.0, + // 0.0,1.0,0.0,0.0, + // 0.0,0.0,2.0,0.0, + // 0.0,0.0,0.0,1.0); + BoneTransform = BoneTransform * bones[aIndex[0]] * aWeights[0]; + BoneTransform += BoneTransform * bones[aIndex[1]] * aWeights[1]; + BoneTransform += BoneTransform * bones[aIndex[2]] * aWeights[2]; + BoneTransform += BoneTransform * bones[aIndex[3]] * aWeights[3]; + //BoneTransform += bones[aIndex[0]] * 1.0; + //BoneTransform += bones[aIndex[1]] * aWeights[1]; + //BoneTransform += bones[aIndex[2]] * aWeights[2]; + //BoneTransform += bones[aIndex[3]] * aWeights[3]; + gl_Position = projection * view * model * BoneTransform * vec4(aPos, 1.0); + } else { + gl_Position = projection * view * model * vec4(aPos, 1.0); + } + FragPos = vec3(model * vec4(aPos, 1.0)); + Normal = vec3(vec4(aNormal, 1.0)); + TexCoords = vec2(0.5, 0.5); +} \ No newline at end of file diff --git a/src/main/resources/Shaders/old/old shader code b/src/main/resources/Shaders/old/old shader code new file mode 100644 index 00000000..ebace10c --- /dev/null +++ b/src/main/resources/Shaders/old/old shader code @@ -0,0 +1,61 @@ +//Vertex Shader +#version 330 core +layout (location = 0) in vec3 aPos; +//layout (location = 1) in vec3 aColor; +//layout (location = 1) in vec2 aTexCoord; +//layout (location = 2) in vec3 aNormal; + +//out vec3 ourColor; + +//uniform vec3 offset; + +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +//out vec3 ourPos; +//out vec2 TexCoord; +//out vec3 FragPos; +//out vec3 Normal; +void main() +{ +//gl_Position = vec4(aPos, 1.0); +gl_Position = projection * view * model * vec4(aPos, 1.0); +//ourColor = aColor; +//FragPos = vec3(model * vec4(aPos, 1.0)); +//TexCoord = aTexCoord; +//Normal = mat3(transpose(inverse(model))) * aNormal; +} + + + + + +//Fragment Shader +#version 330 core + + +out vec4 FragColor; + +//in vec3 ourColor; + +//in vec2 TexCoord; +//uniform sampler2D ourTexture1; +//uniform sampler2D ourTexture2; +//in vec3 Normal; +//uniform vec3 lightPos; +//in vec3 FragPos; + + +void main() +{ +//vec3 lightColor = vec3(1.0, 1.0, 1.0); +//vec3 norm = normalize(Normal); +//vec3 lightDir = normalize(lightPos - FragPos); +//float diff = max(dot(Normal, lightDir), 0.0); +//vec3 diffuse = diff * lightColor; +//vec3 result = diffuse * objectColor; +//FragColor = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);// - (vec4(diffuse, 1.0)*0.2);// * vec4(ourColor, 1.0); +FragColor = vec4(0.5, 0.5, 0.5, 1.0); +} diff --git a/src/main/resources/Shaders/old/oldFragShader.fs b/src/main/resources/Shaders/old/oldFragShader.fs new file mode 100644 index 00000000..e429040f --- /dev/null +++ b/src/main/resources/Shaders/old/oldFragShader.fs @@ -0,0 +1,34 @@ +//Fragment Shader +#version 330 core + +in vec3 FragPos; +in vec3 Normal; + +uniform vec3 objectColor; +uniform vec3 lightColor; +uniform vec3 lightPos; +uniform vec3 viewPos; + +out vec4 FragColor; + +void main() +{ +//Diffuse calculations.. +vec3 norm = normalize(Normal); +vec3 lightDir = normalize(lightPos - FragPos); +float diff = max(dot(norm, lightDir), 0.0); +vec3 diffuse = diff * lightColor; +//Ambient Light +float ambientStrength = 0.5; +vec3 ambient = ambientStrength * lightColor; +//Specular calculations.. +float specularStrength = 0.5; +vec3 viewDir = normalize(viewPos - FragPos); +vec3 reflectDir = reflect(-lightDir, norm); +float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); +vec3 specular = specularStrength * spec * lightColor; +//result color +vec3 result = (ambient + diffuse + specular) * objectColor; +//push output color +FragColor = vec4(result, 1.0); +} diff --git a/src/main/resources/Shaders/skybox/FragmentShaderNoTexture.fs b/src/main/resources/Shaders/skybox/FragmentShaderNoTexture.fs new file mode 100644 index 00000000..37c682b3 --- /dev/null +++ b/src/main/resources/Shaders/skybox/FragmentShaderNoTexture.fs @@ -0,0 +1,13 @@ + + +#version 430 core +out vec4 FragColor; + + +in vec3 color; + + +void main() +{ + FragColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/src/main/resources/Shaders/skybox/VertexShaderNoTexture.vs b/src/main/resources/Shaders/skybox/VertexShaderNoTexture.vs new file mode 100644 index 00000000..a01f7301 --- /dev/null +++ b/src/main/resources/Shaders/skybox/VertexShaderNoTexture.vs @@ -0,0 +1,34 @@ +//Vertex Shader +#version 430 core + + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in float id; + + +//coordinate space transformation matrices +uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + + + +uniform vec3 colors[8]; + +out vec3 color; + + + +void main() +{ + //normalize posiiton and normal + vec4 FinalVertex = vec4(aPos, 1.0); + //send color to the frag shader + color = colors[int(id)]; + //set final position with opengl space + vec4 pos = projection * view * FinalVertex; + gl_Position = pos.xyww; +} diff --git a/src/main/resources/Textures/Fonts/OpenSansBitmap.bmp b/src/main/resources/Textures/Fonts/OpenSansBitmap.bmp new file mode 100644 index 00000000..f22aaa37 Binary files /dev/null and b/src/main/resources/Textures/Fonts/OpenSansBitmap.bmp differ diff --git a/src/main/resources/Textures/Ground/Dirt1.png b/src/main/resources/Textures/Ground/Dirt1.png new file mode 100644 index 00000000..61b45ccc Binary files /dev/null and b/src/main/resources/Textures/Ground/Dirt1.png differ diff --git a/src/main/resources/Textures/Ground/Road1.png b/src/main/resources/Textures/Ground/Road1.png new file mode 100644 index 00000000..5c85eea9 Binary files /dev/null and b/src/main/resources/Textures/Ground/Road1.png differ diff --git a/src/main/resources/Textures/Ground/RoadIntersection1.png b/src/main/resources/Textures/Ground/RoadIntersection1.png new file mode 100644 index 00000000..3949c97d Binary files /dev/null and b/src/main/resources/Textures/Ground/RoadIntersection1.png differ diff --git a/src/main/resources/Textures/MonorailSupport.png b/src/main/resources/Textures/MonorailSupport.png new file mode 100644 index 00000000..94f7b356 Binary files /dev/null and b/src/main/resources/Textures/MonorailSupport.png differ diff --git a/src/main/resources/Textures/RailTrack1Part1.png b/src/main/resources/Textures/RailTrack1Part1.png new file mode 100644 index 00000000..23fd05e7 Binary files /dev/null and b/src/main/resources/Textures/RailTrack1Part1.png differ diff --git a/src/main/resources/Textures/Spaceplane.png b/src/main/resources/Textures/Spaceplane.png new file mode 100644 index 00000000..90b7626c Binary files /dev/null and b/src/main/resources/Textures/Spaceplane.png differ diff --git a/src/main/resources/Textures/SpaceplaneSpecular.png b/src/main/resources/Textures/SpaceplaneSpecular.png new file mode 100644 index 00000000..801ec85e Binary files /dev/null and b/src/main/resources/Textures/SpaceplaneSpecular.png differ diff --git a/src/main/resources/Textures/Wheat1stretch.png b/src/main/resources/Textures/Wheat1stretch.png new file mode 100644 index 00000000..34fea034 Binary files /dev/null and b/src/main/resources/Textures/Wheat1stretch.png differ diff --git a/src/main/resources/Textures/default_diffuse.png b/src/main/resources/Textures/default_diffuse.png new file mode 100644 index 00000000..391b90ab Binary files /dev/null and b/src/main/resources/Textures/default_diffuse.png differ diff --git a/src/main/resources/Textures/default_specular.png b/src/main/resources/Textures/default_specular.png new file mode 100644 index 00000000..391b90ab Binary files /dev/null and b/src/main/resources/Textures/default_specular.png differ diff --git a/src/main/resources/Textures/default_texture_map.json b/src/main/resources/Textures/default_texture_map.json new file mode 100644 index 00000000..d4e44029 --- /dev/null +++ b/src/main/resources/Textures/default_texture_map.json @@ -0,0 +1,22 @@ +{ + "texture_map": { + "Models/plane.fbx": { + "Cube": [ + "Textures/Ground/Dirt1.png", + "Textures/Ground/Dirt1.png" + ] + }, + "Models/arcdock5deg1notex.fbx": { + "Cube": [ + "Textures/w1.png", + "Textures/w1.png" + ] + }, + "Models/Wheat1.fbx": { + "Stalk": [ + "Textures/Wheat1stretch.png", + "Textures/Wheat1stretch.png" + ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/Textures/leaves.png b/src/main/resources/Textures/leaves.png new file mode 100644 index 00000000..7f1474e1 Binary files /dev/null and b/src/main/resources/Textures/leaves.png differ diff --git a/src/main/resources/Textures/skyscraper1_diffuse.png b/src/main/resources/Textures/skyscraper1_diffuse.png new file mode 100644 index 00000000..f58d3bc2 Binary files /dev/null and b/src/main/resources/Textures/skyscraper1_diffuse.png differ diff --git a/src/main/resources/Textures/trunk.png b/src/main/resources/Textures/trunk.png new file mode 100644 index 00000000..5f7f66a8 Binary files /dev/null and b/src/main/resources/Textures/trunk.png differ diff --git a/src/main/resources/Textures/w1.png b/src/main/resources/Textures/w1.png new file mode 100644 index 00000000..480c4b93 Binary files /dev/null and b/src/main/resources/Textures/w1.png differ