added all project files
12
shaders/cubemap.fs.glsl
Normal 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
@@ -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
@@ -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
@@ -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));
|
||||
}
|
||||
135
src/org/kuchelmeister/engine/Scene.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
177
src/org/kuchelmeister/engine/camera/Camera.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
193
src/org/kuchelmeister/engine/geometry/GraphicalObject.java
Normal 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
9
src/org/kuchelmeister/engine/geometry/SubGeometry.java
Normal 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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
91
src/org/kuchelmeister/engine/geometry/skybox/Skybox.java
Normal 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);
|
||||
}
|
||||
}
|
||||
153
src/org/kuchelmeister/engine/geometry/sphere/Icosahedron.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
76
src/org/kuchelmeister/engine/geometry/sphere/Sphere.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
11
src/org/kuchelmeister/engine/geometry/texture/ITexture.java
Normal 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);
|
||||
}
|
||||
43
src/org/kuchelmeister/engine/geometry/texture/Texture.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.kuchelmeister.engine.geometry.vertex;
|
||||
|
||||
public interface VertexInterface {
|
||||
public float[] getFloatArray();
|
||||
}
|
||||
70
src/org/kuchelmeister/engine/input/CameraKeyListener.java
Normal 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
56
src/org/kuchelmeister/engine/lighting/GlobalLights.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
src/org/kuchelmeister/engine/lighting/Light.java
Normal 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;
|
||||
}
|
||||
}
|
||||
52
src/org/kuchelmeister/engine/lighting/Material.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/org/kuchelmeister/engine/solarsystem/Main.java
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
120
src/org/kuchelmeister/engine/solarsystem/SolarSystemScene.java
Normal 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"});
|
||||
}
|
||||
|
||||
}
|
||||
16
src/org/kuchelmeister/solarsystem/camera/SkyboxCamera.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
21
src/org/kuchelmeister/solarsystem/geometry/Moon.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
30
src/org/kuchelmeister/solarsystem/geometry/Orbit.java
Normal 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;
|
||||
}
|
||||
}
|
||||
54
src/org/kuchelmeister/solarsystem/geometry/Planet.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
13
src/org/kuchelmeister/solarsystem/geometry/Sun.java
Normal 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));
|
||||
}
|
||||
}
|
||||
48
src/org/kuchelmeister/solarsystem/geometry/Universe.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
textures/skybox/space_back_5.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
textures/skybox/space_down_2.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
textures/skybox/space_front_4.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
textures/skybox/space_left_0.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
textures/skybox/space_right_1.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
textures/skybox/space_up_3.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
textures/spheres/earth.jpg
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
textures/spheres/jupiter.jpg
Normal file
|
After Width: | Height: | Size: 487 KiB |
BIN
textures/spheres/mars.jpg
Normal file
|
After Width: | Height: | Size: 733 KiB |
BIN
textures/spheres/mercury.jpg
Normal file
|
After Width: | Height: | Size: 852 KiB |
BIN
textures/spheres/moon.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
textures/spheres/neptune.jpg
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
textures/spheres/saturn.jpg
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
textures/spheres/sun.jpg
Normal file
|
After Width: | Height: | Size: 803 KiB |
BIN
textures/spheres/uranus.jpg
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
textures/spheres/venus.jpg
Normal file
|
After Width: | Height: | Size: 224 KiB |