diff --git a/pom.xml b/pom.xml
index 499eef3..bc10f7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -178,6 +178,14 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 16
+ 16
+
+
\ No newline at end of file
diff --git a/src/main/java/lemon/engine/event/Computable.java b/src/main/java/lemon/engine/async/Computable.java
similarity index 98%
rename from src/main/java/lemon/engine/event/Computable.java
rename to src/main/java/lemon/engine/async/Computable.java
index f0a8149..b1ef314 100644
--- a/src/main/java/lemon/engine/event/Computable.java
+++ b/src/main/java/lemon/engine/async/Computable.java
@@ -1,5 +1,6 @@
-package lemon.engine.event;
+package lemon.engine.async;
+import lemon.engine.event.OneTimeEventWith;
import lemon.engine.toolbox.Lazy;
import java.util.ArrayList;
diff --git a/src/main/java/lemon/engine/draw/UnindexedDrawable.java b/src/main/java/lemon/engine/draw/UnindexedDrawable.java
index 61afb46..9e22c81 100644
--- a/src/main/java/lemon/engine/draw/UnindexedDrawable.java
+++ b/src/main/java/lemon/engine/draw/UnindexedDrawable.java
@@ -27,7 +27,7 @@ public UnindexedDrawable(FloatData[][] vertices, int drawMode) {
for (int i = 0; i < vertices.length; i++) {
int dimensions = vertices[i][0].numDimensions();
GL20.glVertexAttribPointer(i, dimensions, GL11.GL_FLOAT, false,
- stride * BYTES_PER_FLOAT, offset * BYTES_PER_FLOAT);
+ stride * Float.BYTES, offset * BYTES_PER_FLOAT);
offset += dimensions;
}
});
diff --git a/src/main/java/lemon/engine/math/Triangle.java b/src/main/java/lemon/engine/math/Triangle.java
index da8a1e3..d2a1d5a 100644
--- a/src/main/java/lemon/engine/math/Triangle.java
+++ b/src/main/java/lemon/engine/math/Triangle.java
@@ -5,6 +5,12 @@ public static Triangle of(Vector3D a, Vector3D b, Vector3D c) {
return new ConstantTriangle(a, b, c);
}
+ public static Triangle of(float ax, float ay, float az,
+ float bx, float by, float bz,
+ float cx, float cy, float cz) {
+ return of(Vector3D.of(ax, ay, az), Vector3D.of(bx, by, bz), Vector3D.of(cx, cy, cz));
+ }
+
public record ConstantTriangle(Vector3D a, Vector3D b, Vector3D c, Vector3D normal,
float area) implements Triangle {
public ConstantTriangle(Vector3D a, Vector3D b, Vector3D c, DerivedTriangleData data) {
diff --git a/src/main/java/lemon/evolution/Game.java b/src/main/java/lemon/evolution/Game.java
index 5c49d1a..0aa219c 100644
--- a/src/main/java/lemon/evolution/Game.java
+++ b/src/main/java/lemon/evolution/Game.java
@@ -6,6 +6,8 @@
import lemon.engine.draw.CommonDrawables;
import lemon.engine.draw.IndexedDrawable;
import lemon.engine.draw.TextModel;
+import lemon.evolution.fastspheres.FastSphere;
+import lemon.evolution.fastspheres.FastSpheres;
import lemon.futility.FObservable;
import lemon.engine.font.CommonFonts;
import lemon.engine.frameBuffer.FrameBuffer;
@@ -100,6 +102,7 @@ public class Game implements Screen {
private TaskQueue postLoadTasks = TaskQueue.ofConcurrent();
+ private FastSpheres fastSpheres;
private ParticleSystem particleSystem;
private UIScreen uiScreen;
@@ -375,12 +378,17 @@ public float getProgress() {
});
});
+ fastSpheres = disposables.add(new FastSpheres(1000000));
+
var texture = disposables.add(new Texture(new TextureData(Toolbox.readImage("/res/particles/fire_01.png").orElseThrow(), true)));
particleSystem = disposables.add(new ParticleSystem(100000, texture));
disposables.add(world.onExplosion((position, radius) -> particleSystem.addExplosionParticles(position, radius)));
disposables.add(window.input().keyEvent().add(event -> {
if (event.action() == GLFW.GLFW_RELEASE) {
+ if (event.key() == GLFW.GLFW_KEY_G) {
+ fastSpheres.spheres.add(new FastSphere(Vector3D.ofCopy(gameLoop.currentPlayer().position()), Color.GREEN));
+ }
if (event.key() == GLFW.GLFW_KEY_C) {
world.entities().removeIf(x -> x instanceof PuzzleBall || x instanceof ExplodeOnHitProjectile || x instanceof StaticEntity);
}
@@ -557,6 +565,8 @@ public void render() {
particleTime = System.nanoTime() - particleTime;
benchmarker.getLineGraph("particleTime").add(particleTime);
+ fastSpheres.render(gameLoop.currentPlayer().position());
+
GL11.glEnable(GL11.GL_DEPTH_TEST);
for (var player : gameLoop.players()) {
if (!player.alive().getValue()) {
diff --git a/src/main/java/lemon/evolution/cmd/EvolutionOptions.java b/src/main/java/lemon/evolution/cmd/EvolutionOptions.java
index 125a4bd..fa7c384 100644
--- a/src/main/java/lemon/evolution/cmd/EvolutionOptions.java
+++ b/src/main/java/lemon/evolution/cmd/EvolutionOptions.java
@@ -1,6 +1,6 @@
package lemon.evolution.cmd;
public class EvolutionOptions {
- public static final boolean ENABLE_MUSIC = true;
+ public static final boolean ENABLE_MUSIC = false;
public static final boolean ENABLE_ESCAPE = true;
}
diff --git a/src/main/java/lemon/evolution/destructible/beta/TerrainChunk.java b/src/main/java/lemon/evolution/destructible/beta/TerrainChunk.java
index f9be8c6..aaae450 100644
--- a/src/main/java/lemon/evolution/destructible/beta/TerrainChunk.java
+++ b/src/main/java/lemon/evolution/destructible/beta/TerrainChunk.java
@@ -3,7 +3,7 @@
import com.google.common.collect.ImmutableList;
import lemon.engine.draw.DrawableData;
import lemon.engine.draw.DynamicIndexedDrawable;
-import lemon.engine.event.Computable;
+import lemon.engine.async.Computable;
import lemon.engine.math.FloatData;
import lemon.engine.math.Matrix;
import lemon.engine.math.MutableVector3D;
diff --git a/src/main/java/lemon/evolution/fastspheres/FastSphere.java b/src/main/java/lemon/evolution/fastspheres/FastSphere.java
new file mode 100644
index 0000000..f4d113f
--- /dev/null
+++ b/src/main/java/lemon/evolution/fastspheres/FastSphere.java
@@ -0,0 +1,10 @@
+package lemon.evolution.fastspheres;
+
+import lemon.engine.math.*;
+import lemon.engine.toolbox.Color;
+
+public record FastSphere(Vector3D position, float size, Color color) {
+ public FastSphere(Vector3D position, Color color) {
+ this(position, 1f, color);
+ }
+}
diff --git a/src/main/java/lemon/evolution/fastspheres/FastSpheres.java b/src/main/java/lemon/evolution/fastspheres/FastSpheres.java
new file mode 100644
index 0000000..1f3bf62
--- /dev/null
+++ b/src/main/java/lemon/evolution/fastspheres/FastSpheres.java
@@ -0,0 +1,110 @@
+package lemon.evolution.fastspheres;
+
+import lemon.engine.math.Matrix;
+import lemon.engine.math.Vector3D;
+import lemon.engine.model.SphereModelBuilder;
+import lemon.engine.render.MatrixType;
+import lemon.engine.render.VertexArray;
+import lemon.engine.render.VertexBuffer;
+import lemon.engine.toolbox.Color;
+import lemon.engine.toolbox.Disposable;
+import lemon.evolution.util.CommonPrograms3D;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL31;
+import org.lwjgl.opengl.GL33;
+
+import java.nio.FloatBuffer;
+import java.util.*;
+
+public class FastSpheres implements Disposable {
+ private static final Vector3D[] VERTICES = SphereModelBuilder.of(1f, 5).build((indices, vertices) -> {
+ return Arrays.stream(indices).mapToObj(i -> vertices[i]).toArray(Vector3D[]::new);
+ });
+ private static final float[] VERTICES_FLOATS;
+ static {
+ VERTICES_FLOATS = new float[VERTICES.length * 3];
+ for (int i = 0; i < VERTICES.length; i++) {
+ VERTICES_FLOATS[i * 3] = VERTICES[i].x();
+ VERTICES_FLOATS[i * 3 + 1] = VERTICES[i].y();
+ VERTICES_FLOATS[i * 3 + 2] = VERTICES[i].z();
+ }
+ }
+ private static final int FLOATS_PER_PARTICLE = 8;
+ private final VertexArray vertexArray;
+ private VertexBuffer vertexBuffer;
+ private final int maxSpheres;
+ public final List spheres = new ArrayList<>();
+
+ public FastSpheres(int maxSpheres) {
+ spheres.add(new FastSphere(Vector3D.ZERO, Color.BLUE)); // TODO
+ this.maxSpheres = maxSpheres;
+ vertexArray = new VertexArray();
+ vertexArray.bind(vao -> {
+ new VertexBuffer().bind(GL15.GL_ARRAY_BUFFER, (target, vbo) -> { // Quad Vertices
+ GL15.glBufferData(target, VERTICES_FLOATS, GL15.GL_STATIC_DRAW);
+ GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 3 * 4, 0);
+ });
+ vertexBuffer = new VertexBuffer();
+ vertexBuffer.bind(GL15.GL_ARRAY_BUFFER, (target, vbo) -> { // Particle Center [x, y, z] + Size [w] + Color [r, g, b, a]
+ GL15.glBufferData(target, getInitialFloatBuffer(), GL15.GL_STREAM_DRAW);
+ GL20.glVertexAttribPointer(1, 4, GL11.GL_FLOAT, false, 8 * 4, 0);
+ GL20.glVertexAttribPointer(2, 4, GL11.GL_FLOAT, false, 8 * 4, 4 * 4);
+ });
+ GL33.glVertexAttribDivisor(0, 0);
+ GL33.glVertexAttribDivisor(1, 1);
+ GL33.glVertexAttribDivisor(2, 1);
+ GL20.glEnableVertexAttribArray(0);
+ GL20.glEnableVertexAttribArray(1);
+ GL20.glEnableVertexAttribArray(2);
+ });
+ }
+
+ public FloatBuffer getInitialFloatBuffer() {
+ var numFloats = FLOATS_PER_PARTICLE * maxSpheres;
+ var buffer = BufferUtils.createFloatBuffer(numFloats);
+ for (int i = 0; i < numFloats; i++) {
+ buffer.put(0f);
+ }
+ buffer.flip();
+ return buffer;
+ }
+
+ public FloatBuffer getFloatBuffer() {
+ var buffer = BufferUtils.createFloatBuffer(FLOATS_PER_PARTICLE * spheres.size());
+ for (var sphere : spheres) {
+ sphere.position().putInBuffer(buffer);
+ buffer.put(sphere.size()); // size
+ sphere.color().putInBuffer(buffer);
+ }
+ buffer.flip();
+ return buffer;
+ }
+
+ public void render(Vector3D viewPosition) {
+ // Update VBO
+ vertexBuffer.bind(GL15.GL_ARRAY_BUFFER, (target, vbo) -> {
+ GL15.glBufferSubData(target, 0, getFloatBuffer());
+ });
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ CommonPrograms3D.FAST_SPHERES.use(program -> {
+ program.loadMatrix(MatrixType.MODEL_MATRIX, Matrix.IDENTITY_4);
+ program.loadVector("viewPos", viewPosition);
+ vertexArray.bind(vao -> {
+ GL31.glDrawArraysInstanced(GL11.GL_TRIANGLES, 0, VERTICES.length, spheres.size());
+ });
+ });
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+
+ @Override
+ public void dispose() {
+ vertexBuffer.dispose();
+ vertexArray.dispose();
+ }
+}
diff --git a/src/main/java/lemon/evolution/physics/beta/CollisionContext.java b/src/main/java/lemon/evolution/physics/beta/CollisionContext.java
index 07936b7..baf4443 100644
--- a/src/main/java/lemon/evolution/physics/beta/CollisionContext.java
+++ b/src/main/java/lemon/evolution/physics/beta/CollisionContext.java
@@ -12,8 +12,9 @@
public interface CollisionContext {
public void checkCollision(Vector3D position, Vector3D velocity, Consumer checker);
+ // TODO: Mutates force to something arbitrary when it's not supposed to
public default void collideWithWorld(MutableVector3D position, MutableVector3D velocity, MutableVector3D force,
- Vector3D scalar, float dt, BiConsumer onCollide, Supplier responder) {
+ Vector3D scalar, float dt, BiConsumer onCollide, CollisionResponse response) {
var scalarSquared = scalar.multiply(scalar);
var transformed = new MutableTriangle();
position.divide(scalar);
@@ -28,7 +29,7 @@ public default void collideWithWorld(MutableVector3D position, MutableVector3D v
return collision;
}, position, velocity, force, dt, collision -> {
onCollide.accept(collision.intersection().multiply(scalar), collision.negSlidePlaneNormal().multiply(scalar));
- return responder.get();
+ return response;
});
position.multiply(scalar);
velocity.multiply(scalar);
diff --git a/src/main/java/lemon/evolution/util/CommonPrograms3D.java b/src/main/java/lemon/evolution/util/CommonPrograms3D.java
index 1135d9d..eadcb1f 100644
--- a/src/main/java/lemon/evolution/util/CommonPrograms3D.java
+++ b/src/main/java/lemon/evolution/util/CommonPrograms3D.java
@@ -85,7 +85,16 @@ public enum CommonPrograms3D implements ShaderProgramHolder {
program.loadSampler("textureSampler", TextureBank.REUSE);
},
new Shader(GL20.GL_VERTEX_SHADER, Toolbox.getFile("/shaders/textVertexShader").orElseThrow()),
- new Shader(GL20.GL_FRAGMENT_SHADER, Toolbox.getFile("/shaders/textFragmentShader").orElseThrow()));
+ new Shader(GL20.GL_FRAGMENT_SHADER, Toolbox.getFile("/shaders/textFragmentShader").orElseThrow())),
+ FAST_SPHERES(names("position", "particleCenter", "particleColor"), program -> {
+ program.loadMatrix(MatrixType.MODEL_MATRIX, Matrix.IDENTITY_4);
+ program.loadMatrix(MatrixType.VIEW_MATRIX, Matrix.IDENTITY_4);
+ program.loadMatrix(MatrixType.PROJECTION_MATRIX, Matrix.IDENTITY_4);
+ program.loadVector("sunlightDirection", Vector3D.of(0f, 1f, 0f));
+ program.loadVector("viewPos", Vector3D.ZERO);
+ },
+ new Shader(GL20.GL_VERTEX_SHADER, Toolbox.getFile("/shaders/sphereVertexShader").orElseThrow()),
+ new Shader(GL20.GL_FRAGMENT_SHADER, Toolbox.getFile("/shaders/sphereFragmentShader").orElseThrow()));
private ShaderProgram shaderProgram;
private final String[] names;
private final Consumer setDefaultUniformVariables;
diff --git a/src/main/java/lemon/evolution/world/World.java b/src/main/java/lemon/evolution/world/World.java
index 674f0d7..e9aeb4f 100644
--- a/src/main/java/lemon/evolution/world/World.java
+++ b/src/main/java/lemon/evolution/world/World.java
@@ -76,7 +76,7 @@ public void update(float dt) {
entity.scalar(),
dt,
entity.onCollide()::callListeners,
- entity::getCollisionResponse
+ entity.getCollisionResponse()
);
entity.mutableForce().set(entity.getEnvironmentalForce());
});
diff --git a/src/main/resources/shaders/sphereFragmentShader b/src/main/resources/shaders/sphereFragmentShader
new file mode 100644
index 0000000..26d9063
--- /dev/null
+++ b/src/main/resources/shaders/sphereFragmentShader
@@ -0,0 +1,26 @@
+#version 400 core
+
+in vec4 passColor;
+in vec3 passNormal;
+in vec3 fragPos;
+
+out vec4 outColor;
+
+uniform vec3 sunlightDirection;
+uniform vec3 viewPos;
+
+void main(void) {
+ //outColor = passColor;
+
+ vec3 lightColor = vec3(1, 1, 1);
+ float ambientStrength = 0.1;
+ vec3 ambient = ambientStrength * lightColor;
+ float diffuseStrength = max(dot(passNormal, sunlightDirection), 0);
+ vec3 diffuse = diffuseStrength * lightColor;
+ float specularStrength = 5;
+ vec3 viewDirection = normalize(viewPos - fragPos);
+ vec3 reflectDirection = reflect(-sunlightDirection, passNormal);
+ vec3 specular = specularStrength * pow(max(dot(viewDirection, reflectDirection), 0), 32) * lightColor;
+ vec3 result = (ambient + diffuse + specular) * passColor.rgb;
+ outColor = vec4(result, passColor.a);
+}
diff --git a/src/main/resources/shaders/sphereVertexShader b/src/main/resources/shaders/sphereVertexShader
new file mode 100644
index 0000000..c8d1ae1
--- /dev/null
+++ b/src/main/resources/shaders/sphereVertexShader
@@ -0,0 +1,29 @@
+#version 400 core
+
+in vec3 position;
+in vec4 particleCenter;
+in vec4 particleColor;
+
+out vec4 passColor;
+out vec3 passNormal;
+out vec3 fragPos;
+
+uniform mat4 modelMatrix;
+uniform mat4 viewMatrix;
+uniform mat4 projectionMatrix;
+
+void main(void) {
+ //mat4 inverted = inverse(viewMatrix);
+ //vec3 cameraPositiveX = inverted[0].xyz;
+ //vec3 cameraPositiveY = inverted[1].xyz;
+
+ //vec3 vertexPosition = particleCenter.a * (cameraPositiveX * position.x + cameraPositiveY * position.y);
+ vec3 vertexPosition = particleCenter.a * position.xyz;
+
+ vec4 worldPosition = modelMatrix * vec4(vertexPosition + particleCenter.xyz, 1.0);
+
+ gl_Position = projectionMatrix * viewMatrix * worldPosition;
+ passColor = particleColor;
+ passNormal = position;
+ fragPos = worldPosition.xyz;
+}