Refactoring

This commit is contained in:
Snoweuph 2024-08-28 22:19:35 +02:00 committed by Snoweuph
parent e7336cbf82
commit 9333b11dfe
No known key found for this signature in database
GPG key ID: 4550DEC769DB1E76
36 changed files with 190 additions and 185 deletions

View file

@ -5,3 +5,5 @@ include(":opengl")
project(":opengl").projectDir = file("src/opengl") project(":opengl").projectDir = file("src/opengl")
include(":rendering") include(":rendering")
project(":rendering").projectDir = file("src/rendering") project(":rendering").projectDir = file("src/rendering")
include(":resources")
project(":resources").projectDir = file("src/resources")

View file

@ -33,9 +33,6 @@ dependencies {
implementation("org.lwjgl", "lwjgl-glfw") implementation("org.lwjgl", "lwjgl-glfw")
runtimeOnly("org.lwjgl", "lwjgl-glfw", classifier = lwjglNatives) runtimeOnly("org.lwjgl", "lwjgl-glfw", classifier = lwjglNatives)
implementation("org.lwjgl", "lwjgl-stb")
runtimeOnly("org.lwjgl", "lwjgl-stb", classifier = lwjglNatives)
implementation("org.joml", "joml", jomlVersion) implementation("org.joml", "joml", jomlVersion)
implementation("org.joml", "joml-primitives", jomlPrimitivesVersion) implementation("org.joml", "joml-primitives", jomlPrimitivesVersion)

View file

@ -1,28 +1,35 @@
package dev.euph.engine.core.ecs; package dev.euph.engine.core.ecs;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
import java.util.ArrayList; @Getter
import java.util.List;
public abstract class Component { public abstract class Component {
@Getter
protected Entity entity = null; protected Entity entity = null;
protected List<Class<? extends Component>> requiredComponents = new ArrayList<>();
@SuppressWarnings("EmptyMethod")
public void OnReady() { public void OnReady() {
} }
@SuppressWarnings("EmptyMethod")
public void OnUpdate(float deltaTime) { public void OnUpdate(float deltaTime) {
} }
@SuppressWarnings("EmptyMethod")
public void OnDestroy() { public void OnDestroy() {
} }
protected boolean hasRequiredComponents(Entity entity) { protected boolean hasRequiredComponents(Entity entity) {
return requiredComponents Requires requiresAnnotation = this.getClass().getAnnotation(Requires.class);
.stream()
.allMatch(requiredClass -> entity.getComponent(requiredClass) != null); if (requiresAnnotation != null) {
Class<? extends Component>[] requiredComponents = requiresAnnotation.value();
return Arrays.stream(requiredComponents)
.allMatch(requiredClass -> entity.getComponent(requiredClass) != null);
}
return true;
} }
} }

View file

@ -37,17 +37,12 @@ public class Entity {
} }
public <T extends Component> T getComponent(Class<T> componentClass) { public <T extends Component> T getComponent(Class<T> componentClass) {
for (Component c : components) { return components
if (componentClass.isAssignableFrom(c.getClass())) { .stream()
try { .filter(c -> componentClass.isAssignableFrom(c.getClass()))
return componentClass.cast(c); .findFirst()
} catch (ClassCastException e) { .map(componentClass::cast)
e.printStackTrace(); .orElse(null);
assert false : "Error: Casting component.";
}
}
}
return null;
} }
public <T extends Component> void removeComponent(Class<T> componentClass) { public <T extends Component> void removeComponent(Class<T> componentClass) {

View file

@ -94,7 +94,10 @@ public class Scene {
return filteredEntities; return filteredEntities;
} }
public final Set<Entity> getByName(String name) { public final Entity getByName(String name) {
return entitiesByName.get(name).stream().findFirst().orElse(null);
}
public final Set<Entity> getAllByName(String name) {
return entitiesByName.get(name); return entitiesByName.get(name);
} }

View file

@ -19,9 +19,6 @@ public class EntitiesByNameStorage implements SceneStorage<String, Entity> {
@Override @Override
public void add(Entity entity, Set<Class<? extends Component>> componentClasses) { public void add(Entity entity, Set<Class<? extends Component>> componentClasses) {
Set<Entity> entities = this.entitiesByName.computeIfAbsent(entity.getName(), _ -> new HashSet<>()); Set<Entity> entities = this.entitiesByName.computeIfAbsent(entity.getName(), _ -> new HashSet<>());
if (entities == null) {
entities = new HashSet<>();
}
entities.add(entity); entities.add(entity);
this.entitiesByName.put(entity.getName(), entities); this.entitiesByName.put(entity.getName(), entities);
} }

View file

@ -6,8 +6,6 @@ import lombok.NoArgsConstructor;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import javax.annotation.PostConstruct;
import static java.lang.Math.toRadians; import static java.lang.Math.toRadians;
@Getter @Getter
@ -24,12 +22,14 @@ public class Transform extends Component {
this.position = position; this.position = position;
this.rotation = rotation; this.rotation = rotation;
this.scale = scale; this.scale = scale;
calculateTransformationMatrix();
} }
public Transform(Transform transform) { public Transform(Transform transform) {
this.position = transform.position; this.position = transform.position;
this.rotation = transform.rotation; this.rotation = transform.rotation;
this.scale = transform.scale; this.scale = transform.scale;
calculateTransformationMatrix();
} }
public static Transform FromPosition(float x, float y, float z) { public static Transform FromPosition(float x, float y, float z) {
@ -56,7 +56,6 @@ public class Transform extends Component {
return new Transform(new Vector3f(), new Vector3f(), scale); return new Transform(new Vector3f(), new Vector3f(), scale);
} }
@PostConstruct
private void calculateTransformationMatrix() { private void calculateTransformationMatrix() {
transformationMatrix = new TransformationMatrix(this); transformationMatrix = new TransformationMatrix(this);
} }

View file

@ -119,8 +119,10 @@ public abstract class Window {
} }
@SuppressWarnings("EmptyMethod")
protected abstract void onUpdate(); protected abstract void onUpdate();
@SuppressWarnings("EmptyMethod")
protected abstract void onDestroy(); protected abstract void onDestroy();

View file

@ -27,6 +27,7 @@ dependencies {
implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("javax.annotation:javax.annotation-api:1.3.2")
compileOnly(project(":core", configuration = "shadow")) compileOnly(project(":core", configuration = "shadow"))
compileOnly(project(":resources", configuration = "shadow"))
compileOnly(project(":rendering", configuration = "shadow")) compileOnly(project(":rendering", configuration = "shadow"))
implementation("org.lwjgl", "lwjgl-assimp") implementation("org.lwjgl", "lwjgl-assimp")

View file

@ -1,6 +1,6 @@
package dev.euph.engine.opengl; package dev.euph.engine.opengl;
import dev.euph.engine.rendering.resources.Mesh; import dev.euph.engine.resources.Mesh;
import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glBindVertexArray;

View file

@ -5,14 +5,10 @@ import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL11.GL_FLOAT; import static dev.euph.engine.opengl.GL.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
public class GLMeshHelper { public class GLMeshHelper {
private final static int VERTICE_INDEX = 0; private final static int VERTICES_INDEX = 0;
private final static int TEXTURE_COORDINATE_INDEX = 1; private final static int TEXTURE_COORDINATE_INDEX = 1;
protected static int getVao() { protected static int getVao() {
@ -35,7 +31,7 @@ public class GLMeshHelper {
buffer.put(vertices).flip(); buffer.put(vertices).flip();
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(VERTICE_INDEX, 3, GL_FLOAT, false, 0, 0); glVertexAttribPointer(VERTICES_INDEX, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }

View file

@ -10,7 +10,7 @@ import dev.euph.engine.rendering.Shader;
import dev.euph.engine.rendering.ShaderManager; import dev.euph.engine.rendering.ShaderManager;
import dev.euph.engine.rendering.components.Camera; import dev.euph.engine.rendering.components.Camera;
import dev.euph.engine.rendering.components.MeshRenderer; import dev.euph.engine.rendering.components.MeshRenderer;
import dev.euph.engine.rendering.resources.Mesh; import dev.euph.engine.resources.Mesh;
import dev.euph.engine.rendering.utils.ProjectionMatrix; import dev.euph.engine.rendering.utils.ProjectionMatrix;
import dev.euph.engine.rendering.utils.ViewMatrix; import dev.euph.engine.rendering.utils.ViewMatrix;
import lombok.Getter; import lombok.Getter;

View file

@ -1,7 +1,7 @@
package dev.euph.engine.opengl; package dev.euph.engine.opengl;
import dev.euph.engine.rendering.Shader; import dev.euph.engine.rendering.Shader;
import dev.euph.engine.rendering.resources.Texture; import dev.euph.engine.resources.Texture;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -47,15 +47,10 @@ public class GLShader extends Shader {
private static int loadShader(InputStream shaderStream, int type) throws IOException { private static int loadShader(InputStream shaderStream, int type) throws IOException {
StringBuilder shaderSource = new StringBuilder(); StringBuilder shaderSource = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(shaderStream))) { BufferedReader reader = new BufferedReader(new InputStreamReader(shaderStream));
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n"); shaderSource.append(line).append("\n");
}
} catch (IOException exception) {
System.err.println("Could not read file!");
exception.printStackTrace();
throw exception;
} }
int shaderId = glCreateShader(type); int shaderId = glCreateShader(type);
glShaderSource(shaderId, shaderSource); glShaderSource(shaderId, shaderSource);

View file

@ -1,34 +1,40 @@
package dev.euph.engine.opengl; package dev.euph.engine.opengl;
import dev.euph.engine.core.data.ImageLoader; import dev.euph.engine.resources.Texture;
import dev.euph.engine.rendering.resources.Texture; import lombok.Getter;
import java.net.URL; import java.nio.ByteBuffer;
import static dev.euph.engine.opengl.GL.*; import static dev.euph.engine.opengl.GL.*;
public class GLTextureLoader { @Getter
public static Texture loadTexture(URL imageResource) { public class GLTexture implements Texture {
int textureID = GL.glGenTextures(); private final int id;
glBindTexture(GL_TEXTURE_2D, textureID); private final int height;
private final int width;
public GLTexture(int width, int height, ByteBuffer data) {
this.id = GL.glGenTextures();
glBindTexture(GL_TEXTURE_2D, this.id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ImageLoader.Image image = ImageLoader.loadImage(imageResource.getPath());
glTexImage2D( glTexImage2D(
GL_TEXTURE_2D, GL_TEXTURE_2D,
0, 0,
GL_RGBA, GL_RGBA,
image.width(), image.height(), width, height,
0, 0,
GL_RGBA, GL_RGBA,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
image.data() data
); );
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
return new Texture(textureID, image.width(), image.height()); this.width = width;
this.height = height;
} }
} }

View file

@ -1,6 +1,6 @@
package dev.euph.engine.opengl; package dev.euph.engine.opengl;
import dev.euph.engine.rendering.resources.Mesh; import dev.euph.engine.resources.Mesh;
import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glBindVertexArray;

View file

@ -27,6 +27,7 @@ dependencies {
implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("javax.annotation:javax.annotation-api:1.3.2")
compileOnly(project(":core", configuration = "shadow")) compileOnly(project(":core", configuration = "shadow"))
compileOnly(project(":resources", configuration = "shadow"))
implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion")) implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion"))
shadow(localGroovy()) shadow(localGroovy())

View file

@ -1,6 +1,6 @@
package dev.euph.engine.rendering; package dev.euph.engine.rendering;
import dev.euph.engine.rendering.resources.Texture; import dev.euph.engine.resources.Texture;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View file

@ -1,6 +1,6 @@
package dev.euph.engine.rendering; package dev.euph.engine.rendering;
import dev.euph.engine.rendering.resources.Texture; import dev.euph.engine.resources.Texture;
import lombok.Setter; import lombok.Setter;
@Setter @Setter

View file

@ -1,6 +1,6 @@
package dev.euph.engine.rendering; package dev.euph.engine.rendering;
import dev.euph.engine.rendering.resources.Texture; import dev.euph.engine.resources.Texture;
import lombok.Getter; import lombok.Getter;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;

View file

@ -5,18 +5,19 @@ import dev.euph.engine.core.ecs.Component;
import dev.euph.engine.core.ecs.Requires; import dev.euph.engine.core.ecs.Requires;
import dev.euph.engine.core.window.Window; import dev.euph.engine.core.window.Window;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import java.awt.*; import java.awt.*;
@Getter
@Setter
@Requires(Transform.class) @Requires(Transform.class)
public class Camera extends Component { public class Camera extends Component {
public float fov = 90f; public float fov = 90f;
public float nearPlane = 0.1f; public float nearPlane = 0.1f;
public float farPlane = 500f; public float farPlane = 500f;
public Color backgroundColor = new Color(0, 200, 255); public Color backgroundColor = new Color(0, 200, 255);
@Getter
private Window window; private Window window;
public Camera(Window window) { public Camera(Window window) {
this.window = window; this.window = window;
} }

View file

@ -4,7 +4,7 @@ import dev.euph.engine.core.transform.Transform;
import dev.euph.engine.core.ecs.Component; import dev.euph.engine.core.ecs.Component;
import dev.euph.engine.core.ecs.Requires; import dev.euph.engine.core.ecs.Requires;
import dev.euph.engine.rendering.Material; import dev.euph.engine.rendering.Material;
import dev.euph.engine.rendering.resources.Mesh; import dev.euph.engine.resources.Mesh;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

View file

@ -2,10 +2,14 @@ package dev.euph.engine.rendering.components.lights;
import dev.euph.engine.core.transform.Transform; import dev.euph.engine.core.transform.Transform;
import dev.euph.engine.core.ecs.Requires; import dev.euph.engine.core.ecs.Requires;
import lombok.Getter;
import lombok.Setter;
import org.joml.Vector3f; import org.joml.Vector3f;
import java.awt.*; import java.awt.*;
@Getter
@Setter
@Requires(Transform.class) @Requires(Transform.class)
public class PointLight extends LightSource { public class PointLight extends LightSource {
public Vector3f attenuation; public Vector3f attenuation;

View file

@ -2,10 +2,14 @@ package dev.euph.engine.rendering.components.lights;
import dev.euph.engine.core.transform.Transform; import dev.euph.engine.core.transform.Transform;
import dev.euph.engine.core.ecs.Requires; import dev.euph.engine.core.ecs.Requires;
import lombok.Getter;
import lombok.Setter;
import org.joml.Vector3f; import org.joml.Vector3f;
import java.awt.*; import java.awt.*;
@Getter
@Setter
@Requires(Transform.class) @Requires(Transform.class)
public class SpotLight extends LightSource { public class SpotLight extends LightSource {
public float coneAngle; public float coneAngle;

View file

@ -1,23 +0,0 @@
package dev.euph.engine.rendering.resources;
import lombok.Getter;
@Getter
public class Texture {
public final static int ALBEDO_INDEX = 0;
public final static int NORMAL_INDEX = 1;
public final static int METALLIC_INDEX = 2;
public final static int ROUGHNESS_INDEX = 3;
public final static int AMBIENT_OCCLUSION_INDEX = 4;
private final int id;
private final int height;
private final int width;
public Texture(int id, int width, int height) {
this.id = id;
this.width = width;
this.height = height;
}
}

View file

@ -4,7 +4,7 @@ import dev.euph.engine.core.window.Window;
import dev.euph.engine.rendering.components.Camera; import dev.euph.engine.rendering.components.Camera;
import org.joml.Matrix4f; import org.joml.Matrix4f;
public class ProjectionMatrix extends Matrix4f { public final class ProjectionMatrix extends Matrix4f {
public ProjectionMatrix(Camera camera) { public ProjectionMatrix(Camera camera) {
super(); super();

View file

@ -6,7 +6,7 @@ import org.joml.Math;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f; import org.joml.Vector3f;
public class ViewMatrix extends Matrix4f { public final class ViewMatrix extends Matrix4f {
public ViewMatrix(Camera camera) { public ViewMatrix(Camera camera) {
super(); super();

View file

@ -26,13 +26,14 @@ dependencies {
annotationProcessor("javax.annotation:javax.annotation-api:1.3.2") annotationProcessor("javax.annotation:javax.annotation-api:1.3.2")
implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("javax.annotation:javax.annotation-api:1.3.2")
compileOnly(project(":core", configuration = "shadow"))
implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion")) implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion"))
implementation("org.lwjgl", "lwjgl-stb")
runtimeOnly("org.lwjgl", "lwjgl-stb", classifier = lwjglNatives)
implementation("org.lwjgl", "lwjgl-assimp") implementation("org.lwjgl", "lwjgl-assimp")
runtimeOnly("org.lwjgl", "lwjgl-assimp", classifier = lwjglNatives) runtimeOnly("org.lwjgl", "lwjgl-assimp", classifier = lwjglNatives)
shadow(localGroovy()) shadow(localGroovy())
shadow(gradleApi()) shadow(gradleApi())
} }

View file

@ -1,4 +1,4 @@
package dev.euph.engine.rendering.resources; package dev.euph.engine.resources;
public interface Mesh { public interface Mesh {
void bind(); void bind();

View file

@ -1,6 +1,5 @@
package dev.euph.engine.opengl; package dev.euph.engine.resources;
import dev.euph.engine.rendering.resources.Mesh;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.assimp.*; import org.lwjgl.assimp.*;
@ -10,46 +9,44 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class GLMeshLoader{ public class MeshLoader {
public static Mesh loadMesh(URL modelResource) { @FunctionalInterface
try { public interface meshConstructor {
AIMesh mesh = loadMeshIntoAssimp(modelResource); Mesh create(float[] vertices, int[] indices);
List<Float> verticesList = new ArrayList<>();
for (int i = 0; i < mesh.mNumVertices(); i++) {
loadVertex(mesh, i, verticesList);
}
float[] vertices = listToFloatArray(verticesList);
int[] indices = listToIntArray(loadIndices(mesh));
return new GLMesh(vertices, indices);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error loading mesh: " + modelResource.getPath());
}
} }
public static Mesh loadTexturedMesh(URL modelResource) { @FunctionalInterface
try { public interface texturedMeshConstructor {
AIMesh mesh = loadMeshIntoAssimp(modelResource); Mesh create(float[] vertices, int[] indices, float[] textureCoordinates);
}
List<Float> verticesList = new ArrayList<>(); public static Mesh loadMesh(URL modelResource, meshConstructor constructor) {
List<Float> textureCoordinatesList = new ArrayList<>(); AIMesh mesh = loadMeshIntoAssimp(modelResource);
List<Float> verticesList = new ArrayList<>();
for (int i = 0; i < mesh.mNumVertices(); i++) { for (int i = 0; i < mesh.mNumVertices(); i++) {
loadVertex(mesh, i, verticesList); loadVertex(mesh, i, verticesList);
loadTextureCoordinates(mesh, i, textureCoordinatesList);
}
float[] vertices = listToFloatArray(verticesList);
int[] indices = listToIntArray(loadIndices(mesh));
float[] texCoords = listToFloatArray(textureCoordinatesList);
return new GLTexturedMesh(vertices, indices, texCoords);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Error loading mesh: " + modelResource.getPath());
} }
float[] vertices = listToFloatArray(verticesList);
int[] indices = listToIntArray(loadIndices(mesh));
return constructor.create(vertices, indices);
}
public static Mesh loadTexturedMesh(URL modelResource, texturedMeshConstructor constructor) {
AIMesh mesh = loadMeshIntoAssimp(modelResource);
List<Float> verticesList = new ArrayList<>();
List<Float> textureCoordinatesList = new ArrayList<>();
for (int i = 0; i < mesh.mNumVertices(); i++) {
loadVertex(mesh, i, verticesList);
loadTextureCoordinates(mesh, i, textureCoordinatesList);
}
float[] vertices = listToFloatArray(verticesList);
int[] indices = listToIntArray(loadIndices(mesh));
float[] texCoords = listToFloatArray(textureCoordinatesList);
return constructor.create(vertices, indices, texCoords);
} }
private static void loadTextureCoordinates(AIMesh mesh, int i, List<Float> texCoordsList) { private static void loadTextureCoordinates(AIMesh mesh, int i, List<Float> texCoordsList) {

View file

@ -0,0 +1,13 @@
package dev.euph.engine.resources;
public interface Texture {
int ALBEDO_INDEX = 0;
int NORMAL_INDEX = 1;
int METALLIC_INDEX = 2;
int ROUGHNESS_INDEX = 3;
int AMBIENT_OCCLUSION_INDEX = 4;
int getId();
int getHeight();
int getWidth();
}

View file

@ -1,26 +1,28 @@
package dev.euph.engine.core.data; package dev.euph.engine.resources;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import java.net.URL;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import static org.lwjgl.stb.STBImage.*; import static org.lwjgl.stb.STBImage.*;
public class TextureLoader {
public class ImageLoader { @FunctionalInterface
public record Image(ByteBuffer data, int width, int height) { public interface textureConstructor {
Texture create(int height, int width, ByteBuffer data);
} }
public static Texture loadTexture(URL imageResource, textureConstructor constructor) {
public static Image loadImage(String path) {
IntBuffer width = BufferUtils.createIntBuffer(1); IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1); IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer channels = BufferUtils.createIntBuffer(1); IntBuffer channels = BufferUtils.createIntBuffer(1);
ByteBuffer imageBuffer = stbi_load(path, width, height, channels, 0);
ByteBuffer imageBuffer = stbi_load(imageResource.getPath(), width, height, channels, 0);
if(imageBuffer == null) { if(imageBuffer == null) {
throw new RuntimeException("Failed to load image: " + stbi_failure_reason()); throw new RuntimeException("Failed to load image: " + stbi_failure_reason());
} }
Image image = new Image(imageBuffer, width.get(0), height.get(0)); Texture image = constructor.create(width.get(0), height.get(0), imageBuffer);
stbi_image_free(imageBuffer); stbi_image_free(imageBuffer);
return image; return image;
} }

View file

@ -70,4 +70,5 @@ dependencies {
implementation(project(":core", configuration = "shadow")) implementation(project(":core", configuration = "shadow"))
implementation(project(":rendering", configuration = "shadow")) implementation(project(":rendering", configuration = "shadow"))
implementation(project(":opengl", configuration = "shadow")) implementation(project(":opengl", configuration = "shadow"))
implementation(project(":resources", configuration = "shadow"))
} }

View file

@ -6,3 +6,5 @@ include(":rendering")
project(":rendering").projectDir = file("../Engine/src/rendering") project(":rendering").projectDir = file("../Engine/src/rendering")
include(":opengl") include(":opengl")
project(":opengl").projectDir = file("../Engine/src/opengl") project(":opengl").projectDir = file("../Engine/src/opengl")
include(":resources")
project(":resources").projectDir = file("../Engine/src/resources")

View file

@ -20,9 +20,6 @@ public class CameraController extends Component {
Transform transform; Transform transform;
private static final float THETA = 0.0001f; private static final float THETA = 0.0001f;
private float movementSpeed = 1.0f;
private float mouseSensitivity = 0.2f;
private Vector2f mouseDelta = new Vector2f(); private Vector2f mouseDelta = new Vector2f();
private Vector2f prevMousePos; private Vector2f prevMousePos;
private Vector2f inputVectorWASD = new Vector2f(); private Vector2f inputVectorWASD = new Vector2f();
@ -61,11 +58,11 @@ public class CameraController extends Component {
}); });
// Set up a GLFW cursor position callback to handle mouse input // Set up a GLFW cursor position callback to handle mouse input
GLFW.glfwSetCursorPosCallback(camera.getWindow().getId(), (window, xpos, ypos) -> { GLFW.glfwSetCursorPosCallback(camera.getWindow().getId(), (window, xPos, yPos) -> {
if(GLFW.glfwGetInputMode(camera.getWindow().getId(), GLFW.GLFW_CURSOR) != GLFW.GLFW_CURSOR_DISABLED){ if(GLFW.glfwGetInputMode(camera.getWindow().getId(), GLFW.GLFW_CURSOR) != GLFW.GLFW_CURSOR_DISABLED){
return; return;
} }
Vector2f newMousePos = new Vector2f((float) xpos, (float) ypos); Vector2f newMousePos = new Vector2f((float) xPos, (float) yPos);
if(justCapturedMouse){ if(justCapturedMouse){
mouseDelta = new Vector2f(); mouseDelta = new Vector2f();
justCapturedMouse = false; justCapturedMouse = false;
@ -98,7 +95,7 @@ public class CameraController extends Component {
// Calculate new position based on movement speed and delta time, only if there's input // Calculate new position based on movement speed and delta time, only if there's input
if (movementDir.length() > 0) { if (movementDir.length() > 0) {
Vector3f newPos = transform.getPosition().add(movementDir.mul(movementSpeed * deltaTime * 60)); Vector3f newPos = transform.getPosition().add(movementDir.mul( deltaTime * 60));
transform.setPosition(newPos); transform.setPosition(newPos);
} }
} }

View file

@ -11,8 +11,10 @@ import dev.euph.engine.rendering.components.Camera;
import dev.euph.engine.rendering.components.MeshRenderer; import dev.euph.engine.rendering.components.MeshRenderer;
import dev.euph.engine.rendering.components.lights.DirectionalLight; import dev.euph.engine.rendering.components.lights.DirectionalLight;
import dev.euph.engine.rendering.components.lights.PointLight; import dev.euph.engine.rendering.components.lights.PointLight;
import dev.euph.engine.rendering.resources.Mesh; import dev.euph.engine.resources.Mesh;
import dev.euph.engine.rendering.resources.Texture; import dev.euph.engine.resources.Texture;
import dev.euph.engine.resources.MeshLoader;
import dev.euph.engine.resources.TextureLoader;
import org.joml.Vector3f; import org.joml.Vector3f;
import java.awt.*; import java.awt.*;
@ -21,14 +23,24 @@ import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class Main { public class Main {
private final static String DEFAULT_SHADER_NAME = "default";
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
URL vertexShader = Main.class.getResource("/dev/euph/game/shader/default.vs.glsl");
URL fragmentShader = Main.class.getResource("/dev/euph/game/shader/default.fs.glsl");
URL testTexture = Main.class.getResource("/dev/euph/game/textures/uv.png");
URL testModel = Main.class.getResource("/dev/euph/game/models/human_rigged.obj");
assert vertexShader != null;
assert fragmentShader != null;
Window window = new GLWindow(1200, 720, "Test Window"); Window window = new GLWindow(1200, 720, "Test Window");
window.setVsync(1); window.setVsync(1);
ShaderManager shaderManager = loadShaders(); ShaderManager shaderManager = loadShaders(vertexShader, fragmentShader);
Scene scene = loadScene(window, shaderManager); Scene scene = loadScene(window, shaderManager, testTexture, testModel);
Entity camera = scene.getByName("Camera").stream().findFirst().orElse(null); Entity camera = scene.getByName("Camera");
Entity Model = scene.getByName("Model").stream().findFirst().orElse(null); Entity Model = scene.getByName("Model");
GLRenderer forwardRenderer = new GLRenderer(scene, shaderManager); GLRenderer forwardRenderer = new GLRenderer(scene, shaderManager);
forwardRenderer.activeCamera = camera.getComponent(Camera.class); forwardRenderer.activeCamera = camera.getComponent(Camera.class);
@ -38,9 +50,7 @@ public class Main {
float rotationSpeed = 20f; float rotationSpeed = 20f;
scene.start(); scene.start();
AtomicBoolean running = new AtomicBoolean(true); AtomicBoolean running = new AtomicBoolean(true);
window.addCloseCallback(() -> { window.addCloseCallback(() -> running.set(false));
running.set(false);
});
while (running.get()) { while (running.get()) {
scene.update(window.getTime().getDeltaTime()); scene.update(window.getTime().getDeltaTime());
@ -55,43 +65,38 @@ public class Main {
window.destroy(); window.destroy();
} }
private static ShaderManager loadShaders() throws IOException { private static ShaderManager loadShaders(URL vertexShader, URL fragmentShader) throws IOException {
ShaderManager shaderManager = new ShaderManager(); ShaderManager shaderManager = new ShaderManager();
URL fragmentShader = Main.class.getResource("/dev/euph/game/shader/default.fs.glsl");
URL vertexShader = Main.class.getResource("/dev/euph/game/shader/default.vs.glsl");
assert vertexShader != null;
assert fragmentShader != null;
shaderManager.addShader(new GLShader( shaderManager.addShader(new GLShader(
"default", DEFAULT_SHADER_NAME,
Main.class.getResourceAsStream("/dev/euph/game/shader/default.vs.glsl"), vertexShader,
Main.class.getResourceAsStream("/dev/euph/game/shader/default.fs.glsl") fragmentShader
)); ));
return shaderManager; return shaderManager;
} }
private static Scene loadScene(Window window, ShaderManager shaderManager) { private static Scene loadScene(Window window, ShaderManager shaderManager, URL testTexture, URL testModel) {
Scene scene = new Scene(); Scene scene = new Scene();
Entity cameraEntity = new Entity("Camera") new Entity("Camera")
.addComponent(Transform.FromPosition(0, 0, 3)) .addComponent(Transform.FromPosition(0, 0, 3))
.addComponent(new Camera(window)) .addComponent(new Camera(window))
.addComponent(new CameraController()) .addComponent(new CameraController())
.addToScene(scene); .addToScene(scene);
Entity light1 = new Entity("DirectionalLight") new Entity("DirectionalLight")
.addComponent(Transform.FromRotation(-0.5f, -1.0f, -0.5f)) .addComponent(Transform.FromRotation(-0.5f, -1.0f, -0.5f))
.addComponent(new DirectionalLight(Color.WHITE)) .addComponent(new DirectionalLight(Color.WHITE))
.addToScene(scene); .addToScene(scene);
Entity light2 = new Entity("PointLight") new Entity("PointLight")
.addComponent(Transform.FromRotation(-0.5f, -1.0f, -0.5f)) .addComponent(Transform.FromRotation(-0.5f, -1.0f, -0.5f))
.addComponent(new PointLight(Color.red, new Vector3f(10))) .addComponent(new PointLight(Color.red, new Vector3f(10)))
.addToScene(scene); .addToScene(scene);
Mesh modelMesh = GLMeshLoader.loadTexturedMesh(Main.class.getResource("/dev/euph/game/models/human_rigged.obj")); Texture uvTexture = TextureLoader.loadTexture(testTexture, GLTexture::new);
Texture uvTexture = GLTextureLoader.loadTexture(Main.class.getResource("/dev/euph/game/textures/uv.png")); Mesh modelMesh = MeshLoader.loadTexturedMesh(testModel, GLTexturedMesh::new);
Material modelMaterial = new Material(shaderManager.getShader("default")) Material modelMaterial = new Material(shaderManager.getShader(DEFAULT_SHADER_NAME))
.setColor(new Color(7, 77, 255, 255)) .setColor(new Color(7, 77, 255, 255))
.setAlbedoTexture(uvTexture); .setAlbedoTexture(uvTexture);
new Entity("Model")
Entity modelEntity = new Entity("Model")
.addComponent(Transform.FromPosition(0, -4, -6).setScale(3)) .addComponent(Transform.FromPosition(0, -4, -6).setScale(3))
.addComponent(new MeshRenderer(modelMesh, modelMaterial)) .addComponent(new MeshRenderer(modelMesh, modelMaterial))
.addToScene(scene); .addToScene(scene);

View file

@ -16,7 +16,7 @@ public class OctreeTest {
public static void main(String[] args) { public static void main(String[] args) {
// Create an octree with a center at (0, 0, 0) and a half-size of 20 units // Create an octree with a center at (0, 0, 0) and a half-size of 20 units
Octree<String> octree = new Octree<>(new OctreeNode<String>( Octree<String> octree = new Octree<>(new OctreeNode<>(
8, 8,
new Vector3f(), new Vector3f(),
20 20
@ -92,17 +92,17 @@ public class OctreeTest {
Map<Character, Color> charColorMap = new HashMap<>(); Map<Character, Color> charColorMap = new HashMap<>();
charColorMap.put(' ', Color.BLACK); // Space character charColorMap.put(' ', Color.BLACK); // Space character
charColorMap.put('#', Color.red); // Hash character charColorMap.put('#', Color.red); // Hash character
charColorMap.put('\u2500', new Color(195, 214, 234)); // HORIZONTAL_LINE charColorMap.put('', new Color(195, 214, 234)); // HORIZONTAL_LINE
charColorMap.put('\u2502', new Color(195, 214, 234)); // VERTICAL_LINE charColorMap.put('', new Color(195, 214, 234)); // VERTICAL_LINE
charColorMap.put('\u250C', new Color(195, 214, 234)); // TOP_LEFT_CORNER charColorMap.put('', new Color(195, 214, 234)); // TOP_LEFT_CORNER
charColorMap.put('\u2510', new Color(195, 214, 234)); // TOP_RIGHT_CORNER charColorMap.put('', new Color(195, 214, 234)); // TOP_RIGHT_CORNER
charColorMap.put('\u2514', new Color(195, 214, 234)); // BOTTOM_LEFT_CORNER charColorMap.put('', new Color(195, 214, 234)); // BOTTOM_LEFT_CORNER
charColorMap.put('\u2518', new Color(195, 214, 234)); // BOTTOM_RIGHT_CORNER charColorMap.put('', new Color(195, 214, 234)); // BOTTOM_RIGHT_CORNER
charColorMap.put('\u251C', new Color(195, 214, 234)); // T_INTERSECTION charColorMap.put('', new Color(195, 214, 234)); // T_INTERSECTION
charColorMap.put('\u253C', new Color(195, 214, 234)); // CROSS_INTERSECTION charColorMap.put('', new Color(195, 214, 234)); // CROSS_INTERSECTION
charColorMap.put('\u2524', new Color(195, 214, 234)); // LEFT_T_INTERSECTION charColorMap.put('', new Color(195, 214, 234)); // LEFT_T_INTERSECTION
charColorMap.put('\u252C', new Color(195, 214, 234)); // UP_T_INTERSECTION charColorMap.put('', new Color(195, 214, 234)); // UP_T_INTERSECTION
charColorMap.put('\u2534', new Color(195, 214, 234)); // DOWN_T_INTERSECTION charColorMap.put('', new Color(195, 214, 234)); // DOWN_T_INTERSECTION
return charColorMap; return charColorMap;
} }