added all project files

This commit is contained in:
Hannes
2018-03-27 20:27:54 +02:00
parent 528797d9de
commit 2fffd4b7c4
53 changed files with 2064 additions and 0 deletions

12
shaders/cubemap.fs.glsl Normal file
View File

@@ -0,0 +1,12 @@
#version 330
in vec3 texCoord;
out vec4 outputColor;
uniform samplerCube cubemap;
void main()
{
outputColor = texture(cubemap, texCoord);
}

14
shaders/cubemap.vs.glsl Normal file
View File

@@ -0,0 +1,14 @@
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 texturePos;
out vec3 texCoord;
uniform mat4 CameraMatrix;
uniform mat4 ModelMatrix;
void main() {
gl_Position = CameraMatrix * ModelMatrix * vec4(position, 1.0);
texCoord = vec3(texturePos.x, -texturePos.y, texturePos.z);
}

63
shaders/object.fs.glsl Normal file
View File

@@ -0,0 +1,63 @@
#version 400
struct LightSource {
//int type; so far only point lights supported
int enabled;
vec3 position;
};
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
int shininess;
};
in vec2 fragTexCoord;
in vec3 fragNormal;
in vec3 fragPos;
out vec4 outputColor;
uniform mat4 ModelMatrix;
uniform sampler2D textureSampler;
uniform Material material;
uniform vec3 EyePos;
const int MaxLigths = 10;
uniform LightSource lights[MaxLigths];
void main()
{
//calculate normal in world coordinates
mat3 normalMatrix = transpose(inverse(mat3(ModelMatrix)));
vec3 normal = normalize(normalMatrix * fragNormal);
vec3 eyeDir = normalize(EyePos - fragPos);
for(int i = 0; i < MaxLigths; ++i) {
//calculate the vector from this pixels surface to the light source
vec3 lightDir = lights[i].position - fragPos;
float attenuation = 1.0 / length(lightDir);
lightDir = normalize(lightDir);
//Diffuse
float diffuseIntensity = max(0.0, dot(normal, lightDir));
vec3 diffuseLight = attenuation * material.diffuse * diffuseIntensity;
//Specular
vec3 reflection = 2 * dot(lightDir, normal) * normal - lightDir;
float specularIntensity = max(0.0, dot(reflection, eyeDir));
specularIntensity = pow(specularIntensity, material.shininess);
vec3 specularLight = attenuation * specularIntensity * material.specular;
vec4 color = texture(textureSampler, fragTexCoord);
outputColor += lights[i].enabled * color * vec4(material.ambient + diffuseLight, 1.0) + specularLight;
}
}

20
shaders/object.vs.glsl Normal file
View File

@@ -0,0 +1,20 @@
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texturePos;
layout(location = 2) in vec3 normalVec;
out vec2 fragTexCoord;
out vec3 fragNormal;
out vec3 fragPos;
uniform mat4 ModelMatrix;
uniform mat4 CameraMatrix;
void main() {
gl_Position = CameraMatrix * ModelMatrix * vec4(position, 1.0);
fragTexCoord = texturePos;
fragNormal = normalVec;
fragPos = vec3(ModelMatrix * vec4(position, 1));
}

View File

@@ -0,0 +1,135 @@
package org.kuchelmeister.engine;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import org.apache.commons.lang3.time.StopWatch;
import org.kuchelmeister.engine.camera.Camera;
import org.kuchelmeister.engine.geometry.GraphicalObject;
import org.kuchelmeister.engine.geometry.skybox.Skybox;
import org.kuchelmeister.engine.input.CameraKeyListener;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
public class Scene extends JFrame implements GLEventListener {
private final StopWatch stopWatch;
private static final long serialVersionUID = 1L;
protected final Camera camera;
private Skybox skybox;
private final List<GraphicalObject> graphicsObjects;
private final GLCanvas canvas;
private final FPSAnimator animator;
private final CameraKeyListener kListener;
public GLCanvas getCanvas() {
return canvas;
}
public Scene(final int width, final int height, final String title) {
super(title);
this.setSize(width, height);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final GLProfile profile = GLProfile.get(GLProfile.GL3);
final GLCapabilities capabilities = new GLCapabilities(profile);
capabilities.setDoubleBuffered(true);
canvas = new GLCanvas(capabilities);
this.getContentPane().add(canvas);
camera = new Camera();
kListener = new CameraKeyListener(camera);
canvas.addKeyListener(kListener);
canvas.addGLEventListener(this);
canvas.setAutoSwapBufferMode(false);
this.getContentPane().add(canvas);
this.graphicsObjects = new LinkedList<>();
animator = new FPSAnimator(canvas, 60, true);
stopWatch = new StopWatch();
stopWatch.start();
}
public void addGraphicalObject(final GraphicalObject gObject) {
gObject.setCamera(camera);
graphicsObjects.add(gObject);
}
public void setSkybox(final String[] textures) {
this.skybox = new Skybox(this.camera, 10.0f, textures);
}
@Override
public void init(final GLAutoDrawable drawable) {
System.out.println("INFO: init()");
System.setProperty("sun.awt.noerasebackground", "true");
System.setProperty("sun.java2d.noddraw", "true");
final GL3 gl = drawable.getGL().getGL3();
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
if (skybox != null) {
skybox.init(gl);
}
for (final GraphicalObject graphicalObject : graphicsObjects) {
graphicalObject.init(gl);
}
}
public void run() {
this.setVisible(true);
animator.start();
}
public void updateObj() {
for (final GraphicalObject graphicalObject : graphicsObjects) {
graphicalObject.update();
}
}
@Override
public void display(final GLAutoDrawable drawable) {
updateObj();
// System.out.println("INFO: display()");
final GL3 gl = drawable.getGL().getGL3();
gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
if (skybox != null) {
skybox.display(gl);
}
for (final GraphicalObject graphicalObject : graphicsObjects) {
graphicalObject.display(gl);
}
gl.glFlush();
canvas.swapBuffers();
}
@Override
public void dispose(final GLAutoDrawable drawable) {
System.out.println("INFO: dispose()");
}
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
System.out.printf("INFO: reshape(%d, %d, %d, %d)\n", x, y, width, height);
// windowHeight = height;
}
}

View File

@@ -0,0 +1,177 @@
package org.kuchelmeister.engine.camera;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
public class Camera {
public static final float MAX_VERTICAL_ANGLE = 85.0f;
private Vector3f position;
private float fieldOfView;
private float horizontalAngle;
private float verticalAngle;
private float nearPlane;
private float farPlane;
private float viewportAspectRatio;
private Matrix4f view;
private Matrix4f projection;
public Camera() {
this.setPosition(new Vector3f(0.0f, 0.0f, 0.0f));
this.setHorizontalAngle(0.0f);
this.setVerticalAngle(0.0f);
this.setFieldOfView(50.0f);
this.setNearAndFarPlanes(0.01f, 100.0f);
this.setViewportAspectRatio(4.0f / 3.0f);
}
public Camera(final Camera c) {
this.setPosition(new Vector3f(c.getPosition()));
this.setHorizontalAngle(c.getHorizontalAngle());
this.setVerticalAngle(c.getVerticalAngle());
this.setFieldOfView(c.getFieldOfView());
this.setNearAndFarPlanes(c.getNearPlane(), c.getFarPlane());
this.setViewportAspectRatio(c.getViewportAspectRatio());
}
public static float[] toFloatArray(final Matrix4f m) {
final float[] arr = new float[16];
m.get(arr);
return arr;
}
public void lookAt(final Vector3f lookAt) {
assert (!this.position.equals(lookAt));
final Vector3f direction = (new Vector3f(this.position)).negate().add(lookAt);
direction.normalize();
this.verticalAngle = (float) Math.toDegrees(Math.asin(-direction.y));
this.horizontalAngle = (float) Math.toDegrees(-Math.atan2(-direction.x, -direction.z));
normalizeAngles();
}
public void offsetPosition(final Vector3f offset) {
position.add(offset);
}
public void setNearAndFarPlanes(final float nearPlane, final float farPlane) {
assert nearPlane > 0.0f && farPlane > nearPlane;
this.nearPlane = nearPlane;
this.farPlane = farPlane;
}
public Matrix4f getOrientation() {
Matrix4f orientationMatrix = new Matrix4f();
orientationMatrix = orientationMatrix.rotate((float) Math.toRadians(verticalAngle),
new Vector3f(1.0f, 0.0f, 0.0f));
orientationMatrix = orientationMatrix.rotate((float) Math.toRadians(horizontalAngle),
new Vector3f(0.0f, 1.0f, 0.0f));
return orientationMatrix;
}
public void offsetOrientation(final float upAngle, final float rightAngle) {
this.horizontalAngle += rightAngle;
this.verticalAngle += upAngle;
}
public Matrix4f getProjection() {
Matrix4f m = new Matrix4f();
m = m.setPerspective((float) Math.toRadians(fieldOfView), viewportAspectRatio, nearPlane, farPlane);
return m;
}
public Matrix4f getMatrix() {
return getProjection().mul(getView());
}
public Matrix4f getView() {
final Matrix4f m = getOrientation();
Matrix4f p = new Matrix4f();
p = p.translate(new Vector3f(this.getPosition()).negate());
return m.mul(p);
}
public Vector3f forwardVec() {
Vector4f vec = new Vector4f(0.0f, 0.0f, -1.0f, 1.0f);
vec = vec.mul(getOrientation());
return new Vector3f(vec.x, vec.y, vec.z);
}
public Vector3f rightVec() {
Vector4f vec = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f);
vec = vec.mul(getOrientation());
return new Vector3f(vec.x, vec.y, vec.z);
}
public Vector3f upVec() {
Vector4f vec = new Vector4f(0.0f, 1.0f, 0.0f, 1.0f);
vec = vec.mul(getOrientation());
return new Vector3f(vec.x, vec.y, vec.z);
}
public float getFarPlane() {
return farPlane;
}
public float getNearPlane() {
return nearPlane;
}
public Vector3f getPosition() {
return position;
}
public void setPosition(final Vector3f position) {
this.position = position;
}
public float getFieldOfView() {
return fieldOfView;
}
public void setFieldOfView(final float fieldOfView) {
this.fieldOfView = fieldOfView;
}
public float getHorizontalAngle() {
return horizontalAngle;
}
public void setHorizontalAngle(final float horizontalAngle) {
this.horizontalAngle = horizontalAngle;
}
public float getVerticalAngle() {
return verticalAngle;
}
public void setVerticalAngle(final float verticalAngle) {
this.verticalAngle = verticalAngle;
}
public float getViewportAspectRatio() {
return viewportAspectRatio;
}
public void setViewportAspectRatio(final float viewportAspectRatio) {
assert viewportAspectRatio > 0.0f;
this.viewportAspectRatio = viewportAspectRatio;
}
public void normalizeAngles() {
horizontalAngle = horizontalAngle % 360.0f;
if (horizontalAngle < 0) {
horizontalAngle += 360.0f;
}
if (verticalAngle > MAX_VERTICAL_ANGLE) {
verticalAngle = MAX_VERTICAL_ANGLE;
} else if (verticalAngle < -MAX_VERTICAL_ANGLE) {
verticalAngle = -MAX_VERTICAL_ANGLE;
}
}
}

View File

@@ -0,0 +1,193 @@
package org.kuchelmeister.engine.geometry;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.kuchelmeister.engine.camera.Camera;
import org.kuchelmeister.engine.geometry.primitive.Triangle;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.util.GLBuffers;
import shader.Shader;
public abstract class GraphicalObject {
public static final int DRAWING_MODE = GL3.GL_TRIANGLES;
private final StopWatch stopWatch;
protected Shader shader;
protected final List<Triangle> faces;
protected final List<SubGeometry> subGeometry;
private Matrix4f transformation;
private Camera camera;
private float[] floatArray;
private int vaoId;
public GraphicalObject(final Shader shader, final Camera camera) {
this.shader = shader;
this.subGeometry = new LinkedList<>();
this.faces = new LinkedList<>();
this.floatArray = new float[0];
this.transformation = new Matrix4f();
this.camera = camera;
this.stopWatch = new StopWatch();
this.stopWatch.start();
}
public void setPosition(final Vector3f pos) {
this.transformation = transformation.setTranslation(pos);
}
public void setRotation(final float angleX, final float angleY, final float angleZ) {
this.transformation.setRotationXYZ((float) Math.toRadians(angleX), (float) Math.toRadians(angleY),
(float) Math.toRadians(angleZ));
}
public void rotate(final float angleDeg, final Vector3f axis) {
this.transformation.rotate((float) Math.toRadians(angleDeg), axis.x, axis.y, axis.z);
}
public void scale(final Vector3f factor) {
this.transformation.scale(factor.x, factor.y, factor.z);
}
public void translate(final Vector3f vec) {
this.transformation.translate(vec.x, vec.y, vec.z);
}
public void generateFaces() {
faces.clear();
for (final SubGeometry sub : subGeometry) {
faces.addAll(sub.getTriangles());
}
}
public void setCamera(final Camera cam) {
this.camera = cam;
}
public float[] getFloatArray() {
if (this.floatArray.length <= 0) {
generateFaces();
floatArray = new float[0];
for (final Triangle triangle : faces) {
floatArray = ArrayUtils.addAll(floatArray, triangle.getVertices());
}
}
return floatArray;
}
public void init(final GL3 gl) {
// A simple temporary integer buffer to exchange data with the GPU
final int vertexArrayObject[] = new int[1];
// Create a VAO -- Vertex Array Object -- in the GPU's memory
gl.glGenVertexArrays(1, IntBuffer.wrap(vertexArrayObject));
vaoId = vertexArrayObject[0];
// A simple temporary integer buffer to exchange data with the GPU
final int vertexBufferObject[] = new int[1];
// Create a buffer object in the GPU memory
gl.glGenBuffers(1, IntBuffer.wrap(vertexBufferObject));
// Bind our VAO to make it the active VAO in the OpenGL context
gl.glBindVertexArray(vaoId);
{
// Make the buffer the active array buffer:
// e.g. bind the newly created buffer object to the GL_ARRAY_BUFFER
// context
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vertexBufferObject[0]);
{
final FloatBuffer buffer = GLBuffers.newDirectFloatBuffer(this.getFloatArray());
// allocate the required memory on the GPU and copy the data
// from our vertexData-buffer into that memory
gl.glBufferData(GL3.GL_ARRAY_BUFFER, this.getFloatArray().length * Buffers.SIZEOF_FLOAT, buffer,
GL3.GL_STATIC_DRAW);
intiVertexAttributes(gl);
}
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0);
}
gl.glBindVertexArray(vaoId);
shader.compile(gl);
}
public void setShader() {
}
public abstract void intiVertexAttributes(final GL3 gl);
public void display(final GL3 gl) {
preDisplay(gl);
gl.glUseProgram(shader.getProgramId());
{
displayParametersANDUniforms(gl);
gl.glBindVertexArray(vaoId);
gl.glDrawArrays(GraphicalObject.DRAWING_MODE, 0, this.faces.size() * 3);
}
gl.glUseProgram(0);
gl.glFlush();
afterDisplay(gl);
}
public void afterDisplay(final GL3 gl) {
}
public void preDisplay(final GL3 gl) {
}
public void displayParametersANDUniforms(final GL3 gl) {
final int transformationLocation = gl.glGetUniformLocation(this.getShader().getProgramId(), "ModelMatrix");
if (transformationLocation != -1) {
final float[] mat = new float[16];
gl.glUniformMatrix4fv(transformationLocation, 1, false, transformation.get(mat), 0);
}
final int cameraLocation = gl.glGetUniformLocation(this.getShader().getProgramId(), "CameraMatrix");
if (transformationLocation != -1) {
final float[] mat = new float[16];
gl.glUniformMatrix4fv(cameraLocation, 1, false, getCamera().getMatrix().get(mat), 0);
}
}
public Camera getCamera() {
return camera;
}
public Shader getShader() {
return shader;
}
public final void update() {
stopWatch.stop();
updateLogic(stopWatch);
stopWatch.reset();
stopWatch.start();
}
public void updateLogic(final StopWatch sWatch) {
}
}

View File

@@ -0,0 +1,77 @@
package org.kuchelmeister.engine.geometry;
import org.joml.Vector3f;
import org.kuchelmeister.engine.camera.Camera;
import org.kuchelmeister.engine.geometry.texture.Texture;
import org.kuchelmeister.engine.lighting.GlobalLights;
import org.kuchelmeister.engine.lighting.Material;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL3;
import shader.Shader;
public abstract class OrdinaryGraphicalObject extends GraphicalObject {
public static final int VERTEX_FLOAT_COUNT = 8;
private final Texture texture;
private final GlobalLights globalLights;
public GlobalLights getGlobalLights() {
return globalLights;
}
private Material material;
public Material getMaterial() {
return material;
}
public void setMaterial(final Material material) {
this.material = material;
}
public OrdinaryGraphicalObject(final Camera camera, final String textureFile) {
super(new Shader("object.vs.glsl", "object.fs.glsl"), camera);
this.texture = new Texture(textureFile);
this.globalLights = GlobalLights.getInstance();
this.material = Material.getDefault();
}
@Override
public void intiVertexAttributes(final GL3 gl) {
gl.glEnable(GL3.GL_DEPTH_TEST);
texture.loadFromFile(gl);
final int STRIDE = VERTEX_FLOAT_COUNT * Buffers.SIZEOF_FLOAT;
final int posOffset = 0;
final int textureOffset = 3 * Buffers.SIZEOF_FLOAT;
final int normalOffset = 5 * Buffers.SIZEOF_FLOAT;
// position attribute
gl.glVertexAttribPointer(0, 3, GL3.GL_FLOAT, false, STRIDE, posOffset);
gl.glEnableVertexAttribArray(0);
// texture position attribute
gl.glVertexAttribPointer(1, 2, GL3.GL_FLOAT, false, STRIDE,
textureOffset);
gl.glEnableVertexAttribArray(1);
// normal vectors
gl.glVertexAttribPointer(2, 3, GL3.GL_FLOAT, false, STRIDE,
normalOffset);
gl.glEnableVertexAttribArray(2);
}
@Override
public void displayParametersANDUniforms(final GL3 gl) {
texture.bind(gl);
super.displayParametersANDUniforms(gl);
final int eyePosLocation = gl.glGetUniformLocation(this.getShader().getProgramId(), "EyePos");
if (eyePosLocation != -1) {
final Vector3f pos = this.getCamera().getPosition();
gl.glUniform3fv(eyePosLocation, 1, new float[] {pos.x, pos.y, pos.z}, 0);
}
globalLights.glSetUniforms(gl, this.getShader());
material.glSetUniforms(gl, this.getShader());
}
}

View File

@@ -0,0 +1,9 @@
package org.kuchelmeister.engine.geometry;
import java.util.List;
import org.kuchelmeister.engine.geometry.primitive.Triangle;
public interface SubGeometry {
public List<Triangle> getTriangles();
}

View File

@@ -0,0 +1,28 @@
package org.kuchelmeister.engine.geometry.primitive;
import java.util.LinkedList;
import java.util.List;
import org.kuchelmeister.engine.geometry.SubGeometry;
import org.kuchelmeister.engine.geometry.vertex.AbstractVertex;
public class Quadrilateral implements SubGeometry {
public AbstractVertex a, b, c, d;
public Quadrilateral(final AbstractVertex a, final AbstractVertex b, final AbstractVertex c,
final AbstractVertex d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
@Override
public List<Triangle> getTriangles() {
final List<Triangle> list = new LinkedList<>();
list.add(new Triangle(a, b, c));
list.add(new Triangle(c, d, a));
return list;
}
}

View File

@@ -0,0 +1,54 @@
package org.kuchelmeister.engine.geometry.primitive;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.joml.Vector3f;
import org.kuchelmeister.engine.geometry.SubGeometry;
import org.kuchelmeister.engine.geometry.vertex.AbstractVertex;
public class Triangle implements SubGeometry {
private final AbstractVertex a, b, c;
/**
* Initialize new Triangle, a, b and c should be positioned
* counterclockwise.
*/
public Triangle(final AbstractVertex a, final AbstractVertex b, final AbstractVertex c) {
this.a = a;
this.b = b;
this.c = c;
}
public List<Vector3f> getPoints() {
final List<Vector3f> pList = new LinkedList<>();
pList.add(getA());
pList.add(getB());
pList.add(getC());
return pList;
}
public Vector3f getA() {
return a.getPosition();
}
public Vector3f getB() {
return b.getPosition();
}
public Vector3f getC() {
return c.getPosition();
}
public float[] getVertices() {
return ArrayUtils.addAll(ArrayUtils.addAll(a.getFloatArray(), b.getFloatArray()), c.getFloatArray());
}
@Override
public List<Triangle> getTriangles() {
final List<Triangle> list = new LinkedList<>();
list.add(this);
return list;
}
}

View File

@@ -0,0 +1,91 @@
package org.kuchelmeister.engine.geometry.skybox;
import org.joml.Vector3f;
import org.kuchelmeister.engine.camera.Camera;
import org.kuchelmeister.engine.geometry.GraphicalObject;
import org.kuchelmeister.engine.geometry.primitive.Quadrilateral;
import org.kuchelmeister.engine.geometry.texture.CubemapTexture;
import org.kuchelmeister.engine.geometry.vertex.SkyboxVertex;
import org.kuchelmeister.solarsystem.camera.SkyboxCamera;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL3;
import shader.Shader;
public class Skybox extends GraphicalObject {
public static final int VERTEX_FLOAT_COUNT = 6;
private final CubemapTexture cubemap;
public Skybox(final Camera camera, final float size, final String[] textures) {
super(new Shader("cubemap.vs.glsl", "cubemap.fs.glsl"), camera);
cubemap = new CubemapTexture(textures);
final float halfSize = size / 2;
final SkyboxVertex frontTopLeft = new SkyboxVertex(new Vector3f(-halfSize, halfSize, halfSize));
final SkyboxVertex frontTopRight = new SkyboxVertex(new Vector3f(halfSize, halfSize, halfSize));
final SkyboxVertex frontBottomLeft = new SkyboxVertex(new Vector3f(-halfSize, -halfSize, halfSize));
final SkyboxVertex frontBottomRight = new SkyboxVertex(new Vector3f(halfSize, -halfSize, halfSize));
final SkyboxVertex backTopLeft = new SkyboxVertex(new Vector3f(-halfSize, halfSize, -halfSize));
final SkyboxVertex backTopRight = new SkyboxVertex(new Vector3f(halfSize, halfSize, -halfSize));
final SkyboxVertex backBottomLeft = new SkyboxVertex(new Vector3f(-halfSize, -halfSize, -halfSize));
final SkyboxVertex backBottomRight = new SkyboxVertex(new Vector3f(halfSize, -halfSize, -halfSize));
// Front
this.subGeometry.add(new Quadrilateral(frontTopLeft, frontTopRight, frontBottomRight, frontBottomLeft));
// Left
this.subGeometry.add(new Quadrilateral(frontBottomLeft, backBottomLeft, backTopLeft, frontTopLeft));
// Top
this.subGeometry.add(new Quadrilateral(frontTopLeft, backTopLeft, backTopRight, frontTopRight));
// Back
this.subGeometry.add(new Quadrilateral(backBottomRight, backTopRight, backTopLeft, backBottomLeft));
// Down
this.subGeometry.add(new Quadrilateral(backBottomLeft, frontBottomLeft, frontBottomRight, backBottomRight));
// Right
this.subGeometry.add(new Quadrilateral(backBottomRight, frontBottomRight, frontTopRight, backTopRight));
}
@Override
public Camera getCamera() {
final Camera skyboxCam = new SkyboxCamera(super.getCamera());
return skyboxCam;
}
@Override
public void intiVertexAttributes(final GL3 gl) {
cubemap.loadFromFile(gl);
final int STRIDE = VERTEX_FLOAT_COUNT * Buffers.SIZEOF_FLOAT;
final int posOffset = 0;
final int textureOffset = 3 * Buffers.SIZEOF_FLOAT;
// position attribute
gl.glVertexAttribPointer(0, 3, GL3.GL_FLOAT, false, STRIDE, posOffset);
gl.glEnableVertexAttribArray(0);
// texture position attribute
gl.glVertexAttribPointer(1, 3, GL3.GL_FLOAT, false, STRIDE,
textureOffset);
gl.glEnableVertexAttribArray(1);
}
@Override
public void displayParametersANDUniforms(final GL3 gl) {
cubemap.bind(gl);
super.displayParametersANDUniforms(gl);
}
@Override
public void afterDisplay(final GL3 gl) {
gl.glEnable(GL3.GL_DEPTH_TEST);
}
@Override
public void preDisplay(final GL3 gl) {
gl.glDisable(GL3.GL_DEPTH_TEST);
}
}

View File

@@ -0,0 +1,153 @@
package org.kuchelmeister.engine.geometry.sphere;
import org.joml.Vector2f;
import org.joml.Vector3f;
import org.kuchelmeister.engine.camera.Camera;
import org.kuchelmeister.engine.geometry.OrdinaryGraphicalObject;
import org.kuchelmeister.engine.geometry.primitive.Triangle;
import org.kuchelmeister.engine.geometry.vertex.ObjectVertex;
public class Icosahedron extends OrdinaryGraphicalObject {
private final Vector3f centre;
public Icosahedron(final Vector3f centre, final float radius, final String texture) {
this(null, centre, radius, texture);
}
public Icosahedron(final Camera camera, final Vector3f centrePos, final float radius, final String texture) {
super(camera, texture);
this.centre = centrePos;
final float golden = (float) ((1 + Math.sqrt(5d)) / 2);
final Vector3f[] points = new Vector3f[] {
new Vector3f(-1, golden, 0f),
new Vector3f(1, golden, 0f),
new Vector3f(-1, -golden, 0f),
new Vector3f(1, -golden, 0f),
new Vector3f(0f, -1, golden),
new Vector3f(0f, 1, golden),
new Vector3f(0f, -1, -golden),
new Vector3f(0f, 1, -golden),
new Vector3f(golden, 0f, -1),
new Vector3f(golden, 0f, 1),
new Vector3f(-golden, 0f, -1),
new Vector3f(-golden, 0f, 1),
};
final Vector2f[] texturePoints = new Vector2f[points.length];
final Vector3f[] normals = new Vector3f[points.length];
for (int i = 0; i < points.length; i++) {
points[i] = points[i].normalize(radius);
texturePoints[i] = Icosahedron.projectOnTexture(points[i], centre);
normals[i] = points[i];
points[i] = points[i].add(centre);
}
// Calculate Normals
this.subGeometry.add(new Triangle(
new ObjectVertex(points[0], texturePoints[0], normals[0]),
new ObjectVertex(points[11], texturePoints[11], normals[11]),
new ObjectVertex(points[5], texturePoints[5], normals[5])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[0], texturePoints[0], normals[0]),
new ObjectVertex(points[5], texturePoints[5], normals[5]),
new ObjectVertex(points[1], texturePoints[1], normals[1])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[0], texturePoints[0], normals[0]),
new ObjectVertex(points[1], texturePoints[1], normals[1]),
new ObjectVertex(points[7], texturePoints[7], normals[7])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[0], texturePoints[0], normals[0]),
new ObjectVertex(points[7], texturePoints[7], normals[7]),
new ObjectVertex(points[10], texturePoints[10], normals[10])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[0], texturePoints[0], normals[0]),
new ObjectVertex(points[10], texturePoints[10], normals[10]),
new ObjectVertex(points[11], texturePoints[11], normals[11])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[1], texturePoints[1], normals[1]),
new ObjectVertex(points[5], texturePoints[5], normals[5]),
new ObjectVertex(points[9], texturePoints[9], normals[9])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[5], texturePoints[5], normals[5]),
new ObjectVertex(points[11], texturePoints[11], normals[11]),
new ObjectVertex(points[4], texturePoints[4], normals[6])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[11], texturePoints[11], normals[11]),
new ObjectVertex(points[10], texturePoints[10], normals[10]),
new ObjectVertex(points[2], texturePoints[2], normals[2])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[10], texturePoints[10], normals[10]),
new ObjectVertex(points[7], texturePoints[7], normals[7]),
new ObjectVertex(points[6], texturePoints[6], normals[6])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[7], texturePoints[7], normals[7]),
new ObjectVertex(points[1], texturePoints[1], normals[1]),
new ObjectVertex(points[8], texturePoints[8], normals[8])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[3], texturePoints[3], normals[3]),
new ObjectVertex(points[9], texturePoints[9], normals[9]),
new ObjectVertex(points[4], texturePoints[4], normals[4])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[3], texturePoints[3], normals[3]),
new ObjectVertex(points[4], texturePoints[4], normals[4]),
new ObjectVertex(points[2], texturePoints[2], normals[2])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[3], texturePoints[3], normals[3]),
new ObjectVertex(points[2], texturePoints[2], normals[2]),
new ObjectVertex(points[6], texturePoints[6], normals[6])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[3], texturePoints[3], normals[3]),
new ObjectVertex(points[6], texturePoints[6], normals[6]),
new ObjectVertex(points[8], texturePoints[8], normals[8])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[3], texturePoints[3], normals[3]),
new ObjectVertex(points[8], texturePoints[8], normals[8]),
new ObjectVertex(points[9], texturePoints[9], normals[9])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[4], texturePoints[4], normals[4]),
new ObjectVertex(points[9], texturePoints[9], normals[9]),
new ObjectVertex(points[5], texturePoints[5], normals[5])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[2], texturePoints[2], normals[2]),
new ObjectVertex(points[4], texturePoints[4], normals[4]),
new ObjectVertex(points[11], texturePoints[11], normals[11])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[6], texturePoints[6], normals[6]),
new ObjectVertex(points[2], texturePoints[2], normals[2]),
new ObjectVertex(points[10], texturePoints[10], normals[10])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[8], texturePoints[8], normals[8]),
new ObjectVertex(points[6], texturePoints[6], normals[6]),
new ObjectVertex(points[7], texturePoints[7], normals[7])));
this.subGeometry.add(new Triangle(
new ObjectVertex(points[9], texturePoints[9], normals[9]),
new ObjectVertex(points[8], texturePoints[8], normals[8]),
new ObjectVertex(points[1], texturePoints[1], normals[1])));
}
public static Vector2f projectOnTexture(final Vector3f point, final Vector3f centre) {
// https://stackoverflow.com/questions/5674149/3d-coordinates-on-a-sphere-to-latitude-and-longitude#5674243
final double x = point.x - centre.x;
final double y = point.y - centre.y;
final double z = point.z - centre.z;
final double r = Math.sqrt(x * x + y * y + z * z);
final double theta = Math.acos(y / r);
final double phi = Math.atan(x / z);
final float lon = (float) ((180.0d - Math.toDegrees(phi)) / 360.0d);
final float lat = (float) ((180.0d - Math.toDegrees(theta)) / 180.0d);
// System.out.println("(" + x + ", " + y + ", " + z + ") => (" + lon +
// ", " + lat + ")");
return new Vector2f(lon, lat);
}
}

View File

@@ -0,0 +1,76 @@
package org.kuchelmeister.engine.geometry.sphere;
import java.util.LinkedList;
import org.joml.Vector3f;
import org.kuchelmeister.engine.geometry.primitive.Triangle;
import org.kuchelmeister.engine.geometry.vertex.ObjectVertex;
public class Sphere extends Icosahedron {
public Sphere(final Vector3f centre, final float radius, final String texture, final int recursionLevel) {
super(centre, radius, texture);
this.faces.clear();
for (int j = 0; j < recursionLevel; j++) {
final LinkedList<Triangle> tmpList = new LinkedList<>();
for (int i = this.subGeometry.size() - 1; i >= 0; i--) {
final Triangle t = (Triangle) this.subGeometry.get(i);
final Vector3f a = t.getA();
final Vector3f b = t.getB();
final Vector3f c = t.getC();
Vector3f o = Sphere.findMiddle(a, b);
Vector3f p = Sphere.findMiddle(b, c);
Vector3f q = Sphere.findMiddle(c, a);
o = Sphere.setDistanceFromPoint(o, radius, centre);
p = Sphere.setDistanceFromPoint(p, radius, centre);
q = Sphere.setDistanceFromPoint(q, radius, centre);
tmpList.add(new Triangle(
new ObjectVertex(a, Icosahedron.projectOnTexture(a, centre), a),
new ObjectVertex(o, Icosahedron.projectOnTexture(o, centre), o),
new ObjectVertex(q, Icosahedron.projectOnTexture(q, centre), q)));
tmpList.add(new Triangle(
new ObjectVertex(o, Icosahedron.projectOnTexture(o, centre), o),
new ObjectVertex(b, Icosahedron.projectOnTexture(b, centre), b),
new ObjectVertex(p, Icosahedron.projectOnTexture(p, centre), p)));
tmpList.add(new Triangle(
new ObjectVertex(p, Icosahedron.projectOnTexture(p, centre), p),
new ObjectVertex(c, Icosahedron.projectOnTexture(c, centre), c),
new ObjectVertex(q, Icosahedron.projectOnTexture(q, centre), q)));
tmpList.add(new Triangle(
new ObjectVertex(o, Icosahedron.projectOnTexture(o, centre), o),
new ObjectVertex(p, Icosahedron.projectOnTexture(p, centre), p),
new ObjectVertex(q, Icosahedron.projectOnTexture(q, centre), q)));
}
this.subGeometry.clear();
this.subGeometry.addAll(tmpList);
// System.out.println(this.subGeometry.size());
}
}
public static Vector3f findMiddle(final Vector3f a, final Vector3f b) {
// Total calculation a + 0.5*(b - a)
final Vector3f negA = (new Vector3f(a)).negate();
Vector3f tmp = new Vector3f(b);
// b - a
tmp = tmp.add(negA);
// 0.5 * (b-a)
tmp = tmp.mul(0.5f);
// a + 0.5 * (b-a)
tmp = tmp.add(a);
return tmp;
}
public static Vector3f setDistanceFromPoint(final Vector3f a, final float distance, final Vector3f point) {
Vector3f direction = new Vector3f(a);
final Vector3f negPoint = (new Vector3f(point)).negate();
direction = direction.add(negPoint);
direction.mul(distance / direction.length());
return direction.add(point);
}
}

View File

@@ -0,0 +1,59 @@
package org.kuchelmeister.engine.geometry.texture;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.IntBuffer;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
public class CubemapTexture implements ITexture {
private IntBuffer textureID;
private final String[] textures;
/**
*
* @param textures
* path to the textures (Order: right, left, top, bottom, back,
* front)
*/
public CubemapTexture(final String[] textures) {
assert (textures != null && textures.length == 6);
this.textures = textures;
}
public void bind(final GL3 gl) {
gl.glBindTexture(GL3.GL_TEXTURE_CUBE_MAP, textureID.get(0));
}
public boolean loadFromFile(final GL3 gl) {
textureID = IntBuffer.allocate(1);
gl.glGenTextures(1, textureID);
gl.glBindTexture(GL3.GL_TEXTURE_CUBE_MAP, textureID.get(0));
for (int i = 0; i < textures.length; i++) {
try {
final InputStream stream = new FileInputStream(new File(ITexture.TEXTURE_FOLDER + textures[i]));
final TextureData data = TextureIO.newTextureData(gl.getGLProfile(), stream, false, "jpg");
gl.glTexImage2D(GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL3.GL_RGB, data.getWidth(),
data.getHeight(), 0, GL3.GL_RGB, GL3.GL_UNSIGNED_BYTE, data.getBuffer());
} catch (GLException | IOException e) {
System.out.println("Failed to load Texture: " + textures[i]);
}
}
gl.glTexParameteri(GL3.GL_TEXTURE_CUBE_MAP, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_LINEAR);
gl.glTexParameteri(GL3.GL_TEXTURE_CUBE_MAP, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_LINEAR);
gl.glTexParameteri(GL3.GL_TEXTURE_CUBE_MAP, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL3.GL_TEXTURE_CUBE_MAP, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL3.GL_TEXTURE_CUBE_MAP, GL3.GL_TEXTURE_WRAP_R, GL3.GL_CLAMP_TO_EDGE);
return true;
}
}

View File

@@ -0,0 +1,11 @@
package org.kuchelmeister.engine.geometry.texture;
import com.jogamp.opengl.GL3;
public interface ITexture {
public static final String TEXTURE_FOLDER = "textures/";
public void bind(GL3 gl);
public boolean loadFromFile(GL3 gl);
}

View File

@@ -0,0 +1,43 @@
package org.kuchelmeister.engine.geometry.texture;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
public class Texture implements ITexture {
private final String texturePath;
private com.jogamp.opengl.util.texture.Texture texture;
public Texture(final String texture) {
this.texturePath = ITexture.TEXTURE_FOLDER + texture;
}
@Override
public void bind(final GL3 gl) {
// TODO Auto-generated method stub
texture.enable(gl);
texture.bind(gl);
}
@Override
public boolean loadFromFile(final GL3 gl) {
try {
final InputStream stream = new FileInputStream(new File(texturePath));
final TextureData data = TextureIO.newTextureData(gl.getGLProfile(), stream, false, "jpg");
texture = TextureIO.newTexture(data);
gl.glTexParameteri(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_S, GL3.GL_REPEAT);
gl.glTexParameteri(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_T, GL3.GL_REPEAT);
return true;
} catch (GLException | IOException e) {
System.out.println("Failed to load Texture: " + texturePath);
return false;
}
}
}

View File

@@ -0,0 +1,25 @@
package org.kuchelmeister.engine.geometry.vertex;
import org.joml.Vector3f;
public abstract class AbstractVertex implements VertexInterface {
private final Vector3f position;
public AbstractVertex(final Vector3f position) {
this.position = position;
}
@Override
public float[] getFloatArray() {
final float[] fl = new float[3];
fl[0] = position.x;
fl[1] = position.y;
fl[2] = position.z;
return fl;
}
public Vector3f getPosition() {
return position;
}
}

View File

@@ -0,0 +1,28 @@
package org.kuchelmeister.engine.geometry.vertex;
import org.apache.commons.lang3.ArrayUtils;
import org.joml.Vector2f;
import org.joml.Vector3f;
public class ObjectVertex extends AbstractVertex {
private final Vector2f texture;
private final Vector3f normal;
public ObjectVertex(final Vector3f position, final Vector2f texture, final Vector3f normal) {
super(position);
this.texture = texture;
this.normal = normal;
}
@Override
public float[] getFloatArray() {
final float[] arr = new float[5];
arr[0] = texture.x;
arr[1] = texture.y;
arr[2] = normal.x;
arr[3] = normal.y;
arr[4] = normal.z;
return ArrayUtils.addAll(super.getFloatArray(), arr);
}
}

View File

@@ -0,0 +1,27 @@
package org.kuchelmeister.engine.geometry.vertex;
import org.apache.commons.lang3.ArrayUtils;
import org.joml.Vector3f;
public class SkyboxVertex extends AbstractVertex {
Vector3f texture;
public SkyboxVertex(final Vector3f position, final Vector3f texture) {
super(position);
this.texture = texture;
}
public SkyboxVertex(final Vector3f position) {
this(position, position);
}
@Override
public float[] getFloatArray() {
final float[] arr = new float[3];
arr[0] = texture.x;
arr[1] = texture.y;
arr[2] = texture.z;
return ArrayUtils.addAll(super.getFloatArray(), arr);
}
}

View File

@@ -0,0 +1,5 @@
package org.kuchelmeister.engine.geometry.vertex;
public interface VertexInterface {
public float[] getFloatArray();
}

View File

@@ -0,0 +1,70 @@
package org.kuchelmeister.engine.input;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import org.kuchelmeister.engine.camera.Camera;
public class CameraKeyListener implements KeyListener {
Camera camera;
public CameraKeyListener(final Camera camera) {
this.camera = camera;
}
@Override
public void keyPressed(final KeyEvent e) {
final float stepsPosition = 0.1f;
final float stepsRotation = 10.0f;
System.out.println("Key Pressed: " + e.getKeyChar() + " | " + e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
// Rotate up
camera.offsetOrientation(stepsRotation, 0.0f);
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
// Rotate down
camera.offsetOrientation(-stepsRotation, 0.0f);
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
// Rotate left
camera.offsetOrientation(0.0f, stepsRotation);
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
// Rotate right
camera.offsetOrientation(0.0f, -stepsRotation);
}
if (e.getKeyCode() == KeyEvent.VK_A) {
// GO Left
camera.offsetPosition(camera.rightVec().mul(-stepsPosition));
} else if (e.getKeyCode() == KeyEvent.VK_D) {
// Go Right
camera.offsetPosition(camera.rightVec().mul(stepsPosition));
;
}
if (e.getKeyCode() == KeyEvent.VK_W) {
// GO Forward
camera.offsetPosition(camera.forwardVec().mul(stepsPosition));
} else if (e.getKeyCode() == KeyEvent.VK_S) {
// Go Backward
camera.offsetPosition(camera.forwardVec().mul(-stepsPosition));
}
if (e.getKeyCode() == KeyEvent.VK_E) {
// GO UP
camera.offsetPosition(camera.upVec().mul(stepsPosition));
} else if (e.getKeyCode() == KeyEvent.VK_Q) {
// Go Down
camera.offsetPosition(camera.upVec().mul(-stepsPosition));
}
}
@Override
public void keyReleased(final KeyEvent e) {
}
@Override
public void keyTyped(final KeyEvent e) {
}
}

View File

@@ -0,0 +1,56 @@
package org.kuchelmeister.engine.lighting;
import java.util.LinkedList;
import java.util.List;
import com.jogamp.opengl.GL3;
import shader.Shader;
public class GlobalLights {
private static GlobalLights globalLights;
public static GlobalLights getInstance() {
if (globalLights == null) {
globalLights = new GlobalLights();
}
return globalLights;
}
public static int MAX_LIGHTS = 10;
List<Light> lights;
public GlobalLights() {
lights = new LinkedList<>();
}
public void add(final Light light) {
if (lights.size() < MAX_LIGHTS) {
lights.add(light);
}
}
public void glSetUniforms(final GL3 gl, final Shader shader) {
for (int i = 0; i < MAX_LIGHTS; i++) {
final int lightPositionLocation = gl.glGetUniformLocation(shader.getProgramId(),
"lights[" + i + "].position");
final int lightEnabledLocation = gl.glGetUniformLocation(shader.getProgramId(),
"lights[" + i + "].enabled");
if (lights.size() > i) {
if (lightPositionLocation != -1) {
gl.glUniform3f(lightPositionLocation, lights.get(i).position.x, lights.get(i).position.y,
lights.get(i).position.z);
}
if (lightEnabledLocation != -1) {
gl.glUniform1i(lightEnabledLocation, 1);
}
} else {
if (lightEnabledLocation != -1) {
gl.glUniform1i(lightEnabledLocation, 0);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
package org.kuchelmeister.engine.lighting;
import org.joml.Vector3f;
public class Light {
Vector3f position;
public Light(final Vector3f position) {
this.position = position;
}
}

View File

@@ -0,0 +1,52 @@
package org.kuchelmeister.engine.lighting;
import org.joml.Vector3f;
import com.jogamp.opengl.GL3;
import shader.Shader;
public class Material {
Vector3f ambient, diffuse, specular;
int shininess;
public Material(final float ambient, final float diffuse, final float specular) {
this(new Vector3f(ambient, ambient, ambient),
new Vector3f(diffuse, diffuse, diffuse),
new Vector3f(specular, specular, specular),
2);
}
public Material(final Vector3f ambient, final Vector3f diffuse, final Vector3f specular, final int shininess) {
this.ambient = ambient;
this.diffuse = diffuse;
this.specular = specular;
this.shininess = shininess;
}
public static Material getDefault() {
final float ambient = 0.4f;
final float diffuse = 1.0f;
final float specular = 0.5f;
return new Material(ambient, diffuse, specular);
}
public void glSetUniforms(final GL3 gl, final Shader shader) {
final int materialAmbientPos = gl.glGetUniformLocation(shader.getProgramId(), "material.ambient");
if (materialAmbientPos != -1) {
gl.glUniform3f(materialAmbientPos, ambient.x, ambient.y, ambient.z);
}
final int materialDiffuseLocation = gl.glGetUniformLocation(shader.getProgramId(), "material.diffuse");
if (materialDiffuseLocation != -1) {
gl.glUniform3f(materialDiffuseLocation, diffuse.x, diffuse.y, diffuse.z);
}
final int materialSpecularLocation = gl.glGetUniformLocation(shader.getProgramId(), "material.specular");
if (materialSpecularLocation != -1) {
gl.glUniform3f(materialSpecularLocation, specular.x, specular.y, specular.z);
}
final int materialShininessLocation = gl.glGetUniformLocation(shader.getProgramId(), "material.shininess");
if (materialShininessLocation != -1) {
gl.glUniform1i(materialShininessLocation, shininess);
}
}
}

View File

@@ -0,0 +1,15 @@
package org.kuchelmeister.engine.solarsystem;
import org.kuchelmeister.engine.Scene;
public class Main {
public static void main(final String[] args) {
Scene myScene;
myScene = new SolarSystemScene(800, 600, "Solar System Visualisation by Hannes Kuchelmeister!");
myScene.run();
}
}

View File

@@ -0,0 +1,120 @@
package org.kuchelmeister.engine.solarsystem;
import org.joml.Vector3f;
import org.kuchelmeister.engine.Scene;
import org.kuchelmeister.solarsystem.geometry.Moon;
import org.kuchelmeister.solarsystem.geometry.Orbit;
import org.kuchelmeister.solarsystem.geometry.Planet;
import org.kuchelmeister.solarsystem.geometry.Sun;
import org.kuchelmeister.solarsystem.geometry.Universe;
import org.kuchelmeister.solarsystem.input.UniverseKeyListener;
public class SolarSystemScene extends Scene {
public SolarSystemScene(final int width, final int height, final String title) {
super(width, height, title);
camera.setPosition(new Vector3f(0.0f, 8.0f, 0.0f));
camera.lookAt(new Vector3f(0.0f, 0.0f, 0.0f));
final Universe uv = new Universe();
this.getCanvas().addKeyListener(new UniverseKeyListener(uv));
// Mercury
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
0.467f,
0.308f),
uv,
0.38f,
"spheres/mercury.jpg", 115.88f, 57.94f));
// Venus
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
0.723f,
0.718f),
uv,
0.38f,
"spheres/venus.jpg", 224.701f, 243.0f));
// Earth
final Planet earth = new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
0.98f,
1.02f),
uv,
1.0f,
"spheres/earth.jpg", 365.256f, 1.0f);
this.addGraphicalObject(earth);
// Moon
this.addGraphicalObject(new Moon(
earth,
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
2 * Universe.EARTH_RADIUS,
2 * Universe.EARTH_RADIUS),
uv,
0.3f,
"spheres/moon.jpg",
29.530589f,
29.530589f));
// Mars
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
1.5f,
1.4f),
uv,
0.2657f * 2,
"spheres/mars.jpg",
686.971f,
1.0275f));
// Jupiter
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
5.2f - 3.3f,
4.9f - 3.3f),
uv,
12.0f / 12f,
"spheres/jupiter.jpg",
4330.0f,
0.4132f));
// Saturn
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
9.5f - 7f,
9f - 7f),
uv,
10.0f / 10f,
"spheres/saturn.jpg",
10751.805f,
0.45f));
// Uranus
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
19f - 16f,
18f - 16f),
uv,
4.0f / 6,
"spheres/uranus.jpg",
30660.0f,
0.72f));
// Neptun
this.addGraphicalObject(new Planet(
new Orbit(new Vector3f(0.0f, 0.0f, 0.0f),
30f - 26.0f,
29f - 26.0f),
uv,
3.88f / 6,
"spheres/neptune.jpg",
30660.0f,
0.673f));
this.addGraphicalObject(new Sun(new Vector3f(0.0f, 0.0f, 0.0f), 3.0f, "spheres/sun.jpg"));
this.setSkybox(new String[] {
"skybox/space_left_0.png",
"skybox/space_right_1.png",
"skybox/space_down_2.png",
"skybox/space_up_3.png",
"skybox/space_front_4.png",
"skybox/space_back_5.png"});
}
}

View File

@@ -0,0 +1,16 @@
package org.kuchelmeister.solarsystem.camera;
import org.joml.Vector3f;
import org.kuchelmeister.engine.camera.Camera;
public class SkyboxCamera extends Camera {
public SkyboxCamera(final Camera camera) {
super(camera);
}
@Override
public Vector3f getPosition() {
return new Vector3f(0.0f, 0.0f, 0.0f);
}
}

View File

@@ -0,0 +1,21 @@
package org.kuchelmeister.solarsystem.geometry;
import org.apache.commons.lang3.time.StopWatch;
public class Moon extends Planet {
Planet homePlanet;
public Moon(final Planet homePlanter, final Orbit orb, final Universe universe, final float radius,
final String texture, final float yearLength, final float dayLength) {
super(orb, universe, radius, texture, yearLength, dayLength);
this.homePlanet = homePlanter;
}
@Override
public void updateLogic(final StopWatch sWatch) {
super.orbit.setCentre(homePlanet.getCentre());
;
super.updateLogic(sWatch);
}
}

View File

@@ -0,0 +1,30 @@
package org.kuchelmeister.solarsystem.geometry;
import org.joml.Vector3f;
public class Orbit {
private final float width, height;
private Vector3f centre;
public Orbit(final Vector3f centre, final float width, final float height) {
this.height = height;
this.width = width;
this.centre = new Vector3f(centre);
}
public Vector3f getPoint(final float angle) {
return new Vector3f(
(float) (width * Math.cos(Math.toRadians(angle)) + centre.x),
centre.y,
(float) (height * Math.sin(Math.toRadians(angle)) + centre.z));
}
public void setCentre(final Vector3f centre) {
this.centre = centre;
}
public Vector3f getCentre() {
return centre;
}
}

View File

@@ -0,0 +1,54 @@
package org.kuchelmeister.solarsystem.geometry;
import org.apache.commons.lang3.time.StopWatch;
import org.joml.Vector3f;
public class Planet extends SphericalSpaceObject {
/** The length of a year on this planet in hours */
private final float yearLength;
private final float dayLength;
private final Universe universe;
private float orbitDegrees;
private float dayAxisDegrees;
protected final Orbit orbit;
public Planet(final Orbit orb, final Universe universe, final float radius, final String texture,
final float yearLength, final float dayLength) {
super(orb.getCentre(), radius, texture);
this.universe = universe;
this.yearLength = yearLength;
this.orbitDegrees = 0;
this.orbit = orb;
dayAxisDegrees = 0f;
this.dayLength = dayLength * Universe.EART_DAY_LENGTH;
}
public Vector3f getCentre() {
return orbit.getPoint(orbitDegrees);
}
@Override
public void updateLogic(final StopWatch sWatch) {
final double elapsedDays = sWatch.getTime() / 1000.0d * universe.getTimeScale();
final float dayOrbitRoatation = 360.0f / yearLength;
orbitDegrees += (float) (dayOrbitRoatation * elapsedDays);
if (orbitDegrees >= 360.0f) {
orbitDegrees %= 360.0f;
}
// System.out.println("Position of Planet: " +
// orbit.getPoint(orbitDegrees));
// TODO: implement rotattion axis
final float dayAxisRotation = 360f / dayLength;
dayAxisDegrees += (float) (elapsedDays * dayAxisRotation);
this.setRotation(0.0f, dayAxisDegrees, 0.0f);
if (dayAxisDegrees >= 360.0f) {
dayAxisDegrees %= 360.0f;
}
this.setPosition(orbit.getPoint(orbitDegrees));
}
}

View File

@@ -0,0 +1,11 @@
package org.kuchelmeister.solarsystem.geometry;
import org.joml.Vector3f;
import org.kuchelmeister.engine.geometry.sphere.Sphere;
public abstract class SphericalSpaceObject extends Sphere {
public SphericalSpaceObject(final Vector3f centre, final float radius, final String texture) {
super(centre, radius * Universe.EARTH_RADIUS, texture, 3);
}
}

View File

@@ -0,0 +1,13 @@
package org.kuchelmeister.solarsystem.geometry;
import org.joml.Vector3f;
import org.kuchelmeister.engine.lighting.Light;
import org.kuchelmeister.engine.lighting.Material;
public class Sun extends SphericalSpaceObject {
public Sun(final Vector3f centre, final float radius, final String texture) {
super(centre, radius, texture);
this.setMaterial(new Material(1.0f, 1.0f, 0.0f));
this.getGlobalLights().add(new Light(centre));
}
}

View File

@@ -0,0 +1,48 @@
package org.kuchelmeister.solarsystem.geometry;
public class Universe {
/**
* radius of the earth in AU
*/
public static float EARTH_RADIUS = 0.09f;
public static float EART_DAY_LENGTH = 1.0f;
/**
* The timescale multiplyer 1 means one second is one day
*/
private float timeScale;
private boolean paused;
public Universe() {
timeScale = 80.0f;
paused = false;
}
public float getTimeScale() {
if (paused) {
return 0.0f;
}
return timeScale;
}
public void tooglePause() {
paused = !paused;
}
public void doubleTimeScale() {
timeScale *= 2;
}
public void halfTimeScale() {
timeScale /= 2;
}
public boolean isPaused() {
return paused;
}
public void reverseTime() {
timeScale = -timeScale;
}
}

View File

@@ -0,0 +1,50 @@
package org.kuchelmeister.solarsystem.input;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import org.kuchelmeister.solarsystem.geometry.Universe;
public class UniverseKeyListener implements KeyListener {
Universe universe;
public UniverseKeyListener(final Universe universe) {
this.universe = universe;
}
@Override
public void keyPressed(final KeyEvent e) {
final float stepsPosition = 0.1f;
final float stepsRotation = 10.0f;
if (!universe.isPaused()) {
if (e.getKeyCode() == KeyEvent.VK_PLUS) {
// Faster time scale
universe.doubleTimeScale();
System.out.println("Time Scale Doubled to: " + universe.getTimeScale());
} else if (e.getKeyCode() == KeyEvent.VK_MINUS) {
// Slower timescale
universe.halfTimeScale();
System.out.println("Time scale halfed to: " + universe.getTimeScale());
} else if (e.getKeyCode() == KeyEvent.VK_R) {
// Reverse timescale
universe.reverseTime();
System.out.println("Time scale halfed to: " + universe.getTimeScale());
}
}
}
@Override
public void keyReleased(final KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
// Pause
universe.tooglePause();
System.out.println("Toggledpause:" + universe.getTimeScale());
}
}
@Override
public void keyTyped(final KeyEvent e) {
}
}

32
src/shader/Shader.java Normal file
View File

@@ -0,0 +1,32 @@
package shader;
import com.jogamp.opengl.GL3;
import tools.ShaderHelper;
public class Shader {
public static final String SHADER_FOLDER = "shaders/";
private int fsId;
private int vsId;
private int programId;
private final String fsPath;
private final String vsPath;
public Shader(final String vertexShaderName, final String fragmentShaderName) {
this.vsPath = SHADER_FOLDER + vertexShaderName;
this.fsPath = SHADER_FOLDER + fragmentShaderName;
}
public void compile(final GL3 gl) {
vsId = ShaderHelper.createVertexShader(gl, vsPath);
fsId = ShaderHelper.createFragmentShader(gl, fsPath);
programId = ShaderHelper.createProgram(gl, vsId, fsId);
}
public int getProgramId() {
return programId;
}
}

165
src/tools/ShaderHelper.java Normal file
View File

@@ -0,0 +1,165 @@
package tools;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.GL3;
/**
* Helper Class for loading and linking vertex and fragment shaders.
*
* @author Björn Zimmer
*
*/
public class ShaderHelper {
public static String loadShaderFromFile(String fileName) {
// allocate a string builder to add line per line
StringBuilder strBuilder = new StringBuilder();
try {
InputStream stream = new FileInputStream(fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line = reader.readLine();
// get text from file, line per line
while (line != null) {
strBuilder.append(line + "\n");
line = reader.readLine();
}
// close resources
reader.close();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return strBuilder.toString();
}
/**
* Loads and compiles a vertex shader from the given source file. Returns
* the shader ID.
*
* @param gl
* @param fileName
* @return
*/
public static int createVertexShader(GL3 gl, String fileName) {
return createShader(gl, fileName, GL3.GL_VERTEX_SHADER);
}
/**
* Loads and compiles a fragment shader from the given source file. Returns
* the shader ID.
*
* @param gl
* @param fileName
* @return
*/
public static int createFragmentShader(GL3 gl, String fileName) {
return createShader(gl, fileName, GL3.GL_FRAGMENT_SHADER);
}
/**
*
* @param gl
* @param fileName
* @param shaderType
* GL3.GL_VERTEX_SHADER or GL3.GL_FRAGMENT_SHADER
* @return
*/
private static int createShader(GL3 gl, String fileName, int shaderType) {
// load the source
String shaderSource = loadShaderFromFile(fileName);
// create the shader id
int shaderId = gl.glCreateShader(shaderType);
// link the id and the source
gl.glShaderSource(shaderId, 1, new String[] { shaderSource }, null);
// compile the shader
gl.glCompileShader(shaderId);
IntBuffer shaderCompileInfo = Buffers.newDirectIntBuffer(1);
// test if the shader was compiled correctly
gl.glGetShaderiv(shaderId, GL3.GL_COMPILE_STATUS, shaderCompileInfo);
System.out.println("Shader compile info:" + shaderCompileInfo);
if (shaderCompileInfo.get() == GL3.GL_FALSE) {
String logMessage = getProgramInfoLog(gl, shaderId);
System.out.println("Shader compilation failed: " + logMessage);
IntBuffer logLength = Buffers.newDirectIntBuffer(1);
gl.glGetShaderiv(shaderId, GL3.GL_INFO_LOG_LENGTH, logLength);
ByteBuffer log = Buffers.newDirectByteBuffer(logLength.get(0));
gl.glGetShaderInfoLog(shaderId, log.limit(), logLength, log);
final byte[] infoBytes = new byte[logLength.get(0)];
log.get(infoBytes);
System.out.println("Shader compilation failed:\n " + new String(infoBytes));
}
return shaderId;
}
/**
* Retrieves the info log for the program.
*
* @param gl
* @param program
* @return
*/
public static String getProgramInfoLog(GL3 gl, int program) {
// get the GL info log
final int par[] = new int[1];
gl.glGetProgramiv(program, GL3.GL_INFO_LOG_LENGTH, par, 0);
final int logLen = par[0];
// final int logLen = getProgramParameter(gl, obj,
// GL3.GL_INFO_LOG_LENGTH);
if (logLen <= 0)
return "";
// Get the log
final int[] retLength = new int[1];
final byte[] bytes = new byte[logLen + 1];
gl.glGetProgramInfoLog(program, logLen, retLength, 0, bytes, 0);
final String logMessage = new String(bytes);
return logMessage;
}
/**
* Links a vertex- and fragmentshader to the programm.
*
* @param gl
* @param vertexShaderId
* @param fragmentShaderId
* @return
*/
public static int createProgram(GL3 gl, int vertexShaderId, int fragmentShaderId) {
// generate the id of the program
int programId = gl.glCreateProgram();
// attach the two shaders
gl.glAttachShader(programId, vertexShaderId);
gl.glAttachShader(programId, fragmentShaderId);
// link them
gl.glLinkProgram(programId);
IntBuffer linkInfo = Buffers.newDirectIntBuffer(1);
gl.glGetProgramiv(programId, GL3.GL_LINK_STATUS, linkInfo);
System.out.println("Link info: " + linkInfo);
if (linkInfo.get() == GL3.GL_FALSE) {
String logMessage = getProgramInfoLog(gl, programId);
System.out.println("Shader linking failed: " + logMessage);
}
return programId;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
textures/spheres/earth.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

BIN
textures/spheres/mars.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 KiB

BIN
textures/spheres/moon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

BIN
textures/spheres/saturn.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

BIN
textures/spheres/sun.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

BIN
textures/spheres/uranus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
textures/spheres/venus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB