diff --git a/src/main/java/engine/application/BasicApplication.java b/src/main/java/engine/application/BasicApplication.java index 3c3dab78..aa70cff2 100644 --- a/src/main/java/engine/application/BasicApplication.java +++ b/src/main/java/engine/application/BasicApplication.java @@ -105,8 +105,8 @@ public void update() { lastZ = input.isKeyPressed(Key.Z); } - timer.update(); + input.update(); fpsGraph.update(timer); debugInfoUpdater.update(timer, activeScene, input); @@ -139,7 +139,6 @@ public void render(Graphics g) { renderUi(g); renderDebugUi(g); - g.enableDepthTest(); } diff --git a/src/main/java/engine/processing/ProcessingMouseInput.java b/src/main/java/engine/processing/ProcessingMouseInput.java index 4799451a..aa89eb23 100644 --- a/src/main/java/engine/processing/ProcessingMouseInput.java +++ b/src/main/java/engine/processing/ProcessingMouseInput.java @@ -10,6 +10,11 @@ public class ProcessingMouseInput implements MouseInput { private final PApplet applet; private float mouseWheelDelta = 0; + + private float mouseX; + private float mouseY; + private float pMouseX; + private float pMouseY; private Robot robot; @@ -51,32 +56,32 @@ public float getScreenHeight() { @Override public float getMouseX() { - return applet.mouseX; + return mouseX; } @Override public float getMouseY() { - return applet.mouseY; + return mouseY; } @Override public float getLastMouseX() { - return applet.pmouseX; + return pMouseX; } @Override public float getLastMouseY() { - return applet.pmouseY; + return pMouseY; } @Override public float getMouseDeltaX() { - return applet.mouseX - applet.pmouseX; + return mouseX - pMouseX; } @Override public float getMouseDeltaY() { - return applet.mouseY - applet.pmouseY; + return mouseY - pMouseY; } @Override @@ -87,7 +92,12 @@ public float getMouseWheelDelta() { } @Override - public void updateMouseState() {} + public void updateMouseState() { + this.mouseX = applet.mouseX; + this.mouseY = applet.mouseY; + this.pMouseX = applet.pmouseX; + this.pMouseY = applet.pmouseY; + } @Override public void center() { diff --git a/src/main/java/engine/processing/ProcessingTexture.java b/src/main/java/engine/processing/ProcessingTexture.java index 585e6b31..3712dcba 100644 --- a/src/main/java/engine/processing/ProcessingTexture.java +++ b/src/main/java/engine/processing/ProcessingTexture.java @@ -1,5 +1,6 @@ package engine.processing; +import engine.resources.FilterMode; import engine.resources.Texture; import processing.core.PImage; @@ -7,8 +8,11 @@ public class ProcessingTexture implements Texture { private final PImage image; + private FilterMode filterMode; + public ProcessingTexture(PImage image) { this.image = image; + this.filterMode = FilterMode.BILINEAR; } @Override @@ -36,7 +40,29 @@ public void delete() { // Processing handles memory management automatically } + @Override + public void setPixels(int[] pixels) { + image.loadPixels(); + image.pixels = pixels; + image.updatePixels(); + } + public PImage getImage() { return image; } + + @Override + public FilterMode getFilterMode() { + return filterMode; + } + + @Override + public void setFilterMode(FilterMode filterMode) { + this.filterMode = filterMode; + } + + @Override + public Texture getBackendTexture() { + return this; + } } diff --git a/src/main/java/engine/processing/ProcessingTextureLoader.java b/src/main/java/engine/processing/ProcessingTextureLoader.java index b1daa208..60fd4991 100644 --- a/src/main/java/engine/processing/ProcessingTextureLoader.java +++ b/src/main/java/engine/processing/ProcessingTextureLoader.java @@ -1,5 +1,7 @@ package engine.processing; +import java.awt.Image; + import engine.resources.Texture; import engine.resources.TextureLoader; import processing.core.PApplet; @@ -24,4 +26,16 @@ public Texture loadTexture(String filePath) { ProcessingTexture texture = new ProcessingTexture(image); return texture; } + + @Override + public Texture createTexture(Image image) { + PImage pImage = new PImage(image); + return new ProcessingTexture(pImage); + } + + @Override + public Texture createTexture(int width, int height) { + PImage pImage = new PImage(width, height); + return new ProcessingTexture(pImage); + } } diff --git a/src/main/java/engine/resources/FilterMode.java b/src/main/java/engine/resources/FilterMode.java new file mode 100644 index 00000000..dd8a8387 --- /dev/null +++ b/src/main/java/engine/resources/FilterMode.java @@ -0,0 +1,51 @@ +package engine.resources; + +/** + * Enum representing the various filter modes available for texture sampling. These filter modes + * determine how textures are sampled and filtered when applied to 3D models or surfaces, affecting + * the appearance of textures when viewed at different distances or angles. + * + *
The available filter modes are: + * + *
The `inverseLerp` function computes the normalized position of a value `t` within the range + * defined by `from` and `to`. It determines how far `t` lies between `from` and `to` on a scale + * from 0 to 1. If `t` is less than `from`, it returns a negative value. If `t` is greater than + * `to`, it returns a value greater than 1. + * + * @param from The start of the range. + * @param to The end of the range. + * @param t The value to normalize within the range. + * @return The normalized position of `t` in the range `[from, to]`. + * @throws IllegalArgumentException if `from` equals `to`, as this would result in division by + * zero. + */ + public static float inverseLerp(float from, float to, float t) { + if (from == to) { + throw new IllegalArgumentException( + "The start and end of the range cannot be the same (division by zero)."); + } + return (t - from) / (to - from); + } + /** * Returns the next power of two greater than or equal to the given value. * diff --git a/src/main/java/math/Plane.java b/src/main/java/math/Plane.java index ae8d5b28..78c07fdd 100644 --- a/src/main/java/math/Plane.java +++ b/src/main/java/math/Plane.java @@ -31,6 +31,27 @@ public Plane() { this.distance = 0; } + /** + * Constructs a plane with a given normal vector and distance. + * + *
The normal vector is automatically normalized during this operation. + * + * @param normal the normal vector of the plane. + * @param distance the distance of the plane from the origin along its normal vector. + */ + public Plane(Vector3f normal, float distance) { + this.normal = new Vector3f(normal); + this.normal.normalizeLocal(); + this.distance = distance; + } + + /** Flips the orientation of the plane by inverting its normal and distance. */ + public void flip() { + normal.negateLocal(); + normal.normalizeLocal(); // Ensure the normal vector is normalized after negation + distance = distance == 0 ? 0 : -distance; // Avoid -0 + } + /** * Sets the plane parameters using its coefficients. * @@ -43,9 +64,10 @@ public Plane() { * @param d the distance from the origin along the plane's normal vector. */ public void set(float a, float b, float c, float d) { - this.normal.set(a, b, c); - normal.normalizeLocal(); - this.distance = d; + float length = (float) Math.sqrt(a * a + b * b + c * c); + if (length == 0) throw new IllegalArgumentException("Plane normal cannot be zero."); + this.normal.set(a / length, b / length, c / length); + this.distance = d / length; // Normalize the distance as well } /** @@ -86,4 +108,9 @@ public Vector3f getNormal() { public float getDistance() { return distance; } + + @Override + public String toString() { + return "Plane [normal=" + normal + ", distance=" + distance + "]"; + } } diff --git a/src/main/java/mesh/Mesh3D.java b/src/main/java/mesh/Mesh3D.java index ede95ebd..e9daa5d5 100644 --- a/src/main/java/mesh/Mesh3D.java +++ b/src/main/java/mesh/Mesh3D.java @@ -272,6 +272,21 @@ public Face3D getFaceAt(int index) { return faces.get(index); } + /** + * Adds a UV coordinate to the mesh. + * + *
This method appends a new UV coordinate, specified by the parameters {@code u} and {@code + * v}, to the list of UV coordinates for this mesh. UV coordinates are used for mapping textures + * to the surface of the mesh, where {@code u} and {@code v} typically represent the horizontal + * and vertical texture coordinates, respectively. + * + * @param u The horizontal component of the UV coordinate. + * @param v The vertical component of the UV coordinate. + */ + public void addUvCoordinate(float u, float v) { + uvs.add(new Vector2f(u, v)); + } + /** * Sets the UV coordinates for this mesh. * diff --git a/src/main/java/workspace/GraphicsPImpl.java b/src/main/java/workspace/GraphicsPImpl.java index 35a234bf..12ceadf2 100644 --- a/src/main/java/workspace/GraphicsPImpl.java +++ b/src/main/java/workspace/GraphicsPImpl.java @@ -6,6 +6,7 @@ import engine.processing.LightRendererImpl; import engine.processing.ProcessingTexture; import engine.render.Material; +import engine.resources.FilterMode; import engine.resources.Image; import engine.resources.Texture; import engine.scene.camera.Camera; @@ -47,7 +48,7 @@ public class GraphicsPImpl implements Graphics { public static int vertexCount = 0; - private PImage texture; + private ProcessingTexture texture; @Override public void setAmbientColor(math.Color ambientColor) { @@ -133,6 +134,62 @@ private void applyTransform(Matrix4f transform) { matrix[15]); } + /** + * Applies the specified texture to the current rendering context, setting the appropriate texture + * sampling mode based on the filter mode of the texture. + * + *
This method checks the texture's filter mode and applies the corresponding texture sampling + * mode. It also ensures that the texture is properly initialized before usage. + * + *
The available filter modes are mapped to the following sampling modes: + * + *
This method renders the provided image at the given position (x, y) on the screen, using the + * image's natural dimensions without scaling. + * + * @param image The {@link Image} object to render. + * @param x The x-coordinate where the image's top-left corner will be placed. + * @param y The y-coordinate where the image's top-left corner will be placed. + */ void drawImage(Image image, float x, float y); + /** + * Draws an image at the specified coordinates (x, y) and scales it to the specified width and + * height. + * + *
This method renders the provided image at the given position (x, y) on the screen, scaling + * the image to fit the specified width and height. The aspect ratio of the image may be distorted + * if the aspect ratio of the width and height differs from the image's natural dimensions. + * + * @param image The {@link Image} object to render. + * @param x The x-coordinate where the image's top-left corner will be placed. + * @param y The y-coordinate where the image's top-left corner will be placed. + * @param width The width to scale the image to. + * @param height The height to scale the image to. + */ void drawImage(Image image, float x, float y, float width, float height); }