diff --git a/src/main/java/io/pyke/vitri/finorza/inference/rpc/RemoteControlService.java b/src/main/java/io/pyke/vitri/finorza/inference/rpc/RemoteControlService.java index 32986e0..81bdb59 100644 --- a/src/main/java/io/pyke/vitri/finorza/inference/rpc/RemoteControlService.java +++ b/src/main/java/io/pyke/vitri/finorza/inference/rpc/RemoteControlService.java @@ -36,7 +36,7 @@ public class RemoteControlService extends RemoteControlServiceGrpc.RemoteControl private ActRequest lastAction = null; public RemoteControlService() { - this(new Screenshot(), Minecraft.getInstance()); + this(new Screenshot(640, 360), Minecraft.getInstance()); } public RemoteControlService(@NotNull Screenshot screenshot, @NotNull Minecraft minecraft) { @@ -144,7 +144,7 @@ public void observe(Empty request, StreamObserver response) { RenderSystem.recordRenderCall(() -> frameFuture.complete(this.screenshot.read())); frameFuture.join(); // just join onto the gRPC thread - builder.setData(ByteString.copyFrom(this.screenshot.resize())); + builder.setData(ByteString.copyFrom(this.screenshot.resize(Screenshot.InterpolationMethod.LINEAR))); } } diff --git a/src/main/java/io/pyke/vitri/finorza/inference/util/Screenshot.java b/src/main/java/io/pyke/vitri/finorza/inference/util/Screenshot.java index 79f87b0..2ae8a98 100644 --- a/src/main/java/io/pyke/vitri/finorza/inference/util/Screenshot.java +++ b/src/main/java/io/pyke/vitri/finorza/inference/util/Screenshot.java @@ -9,19 +9,17 @@ import java.nio.ByteBuffer; public class Screenshot { // NOT thread safe! - public static final int RESIZE_WIDTH = 640; - public static final int RESIZE_HEIGHT = 360; - - private final int resizeWidth, resizeHeight; + private int resizeWidth, resizeHeight; private ByteBuffer resizeBuffer; private int width, height = 0; private ByteBuffer buffer; - public Screenshot() { - this(RESIZE_WIDTH, RESIZE_HEIGHT); + public Screenshot(int resizeWidth, int resizeHeight) { + this.resizeWidth = resizeWidth; + this.resizeHeight = resizeHeight; } - public Screenshot(int resizeWidth, int resizeHeight) { + public void setResizeSize(int resizeWidth, int resizeHeight) { this.resizeWidth = resizeWidth; this.resizeHeight = resizeHeight; } @@ -44,8 +42,12 @@ public Screenshot(int resizeWidth, int resizeHeight) { return this.buffer; } - public @NotNull ByteBuffer resize() { - if (this.resizeBuffer == null) { + private static float lerp(float s, float e, float t) { + return s + (e - s) * t; + } + + public @NotNull ByteBuffer resize(InterpolationMethod interpolationMethod) { + if (this.resizeBuffer == null || this.resizeBuffer.capacity() != this.resizeWidth * this.resizeHeight * 3) { this.resizeBuffer = ByteBuffer.allocateDirect(resizeWidth * resizeHeight * 3); } else { this.resizeBuffer.rewind(); @@ -63,22 +65,56 @@ public Screenshot(int resizeWidth, int resizeHeight) { return this.resizeBuffer; } - final double wr = (double) this.width / this.resizeWidth; - final double hr = (double) this.height / this.resizeHeight; - for (int y = 0; y < this.resizeHeight; y++) { - for (int x = 0; x < this.resizeWidth; x++) { - final int srcX = Math.min((int) (x * wr), this.width - 1); - final int srcY = Math.min(this.height - (int) (y * hr), this.height - 1); // flip Y here, since glReadPixels returns an upside down image - - final int srcIdx = (srcY * this.width + srcX) * 3; - final int destIdx = (y * this.resizeWidth + x) * 3; - - this.resizeBuffer.put(destIdx, this.buffer.get(srcIdx)); - this.resizeBuffer.put(destIdx + 1, this.buffer.get(srcIdx + 1)); - this.resizeBuffer.put(destIdx + 2, this.buffer.get(srcIdx + 2)); + switch (interpolationMethod) { + case LINEAR -> { + throw new UnsupportedOperationException(); + // TODO: unfuck this +// for (int x = 0; x < this.resizeWidth; x++) { +// for (int y = 0; y < this.resizeHeight; y++) { +// float gx = ((float) x + 0.5f) / this.resizeWidth * (this.width - 1); +// float gy = ((float) y + 0.5f) / this.resizeHeight * (this.height - 1); +// int gxi = Math.round(gx); +// int gyi = Math.round(gy); +// float tx = gx - gxi; +// float ty = gy - gyi; +// +// for (int c = 0; c < 3; c++) { +// float c00 = (float)this.buffer.get(((gxi + (gyi * this.width)) * 3) + c); +// float c10 = (float)this.buffer.get(((gxi + 1 + (gyi * this.width)) * 3) + c); +// float c01 = (float)this.buffer.get(((gxi + (Math.min(this.height - 1, (gyi + 1)) * this.width)) * 3) + c); +// float c11 = (float)this.buffer.get(((gxi + 1 + (Math.min(this.height - 1, (gyi + 1)) * this.width)) * 3) + c); +// this.resizeBuffer.put( +// ((x + ((this.resizeHeight - 1 - y) * this.resizeWidth)) * 3) + c, +// (byte)lerp(lerp(c00, c10, tx), lerp(c01, c11, tx), ty) +// ); +// } +// } +// } + } + case NEAREST_NEIGHBOR -> { + final double wr = (double) this.width / this.resizeWidth; + final double hr = (double) this.height / this.resizeHeight; + for (int y = 0; y < this.resizeHeight; y++) { + for (int x = 0; x < this.resizeWidth; x++) { + final int srcX = Math.min((int) (x * wr), this.width - 1); + final int srcY = Math.min(this.height - (int) (y * hr), this.height - 1); // flip Y here, since glReadPixels returns an upside down image + + final int srcIdx = (srcY * this.width + srcX) * 3; + final int destIdx = (y * this.resizeWidth + x) * 3; + + this.resizeBuffer.put(destIdx, this.buffer.get(srcIdx)); + this.resizeBuffer.put(destIdx + 1, this.buffer.get(srcIdx + 1)); + this.resizeBuffer.put(destIdx + 2, this.buffer.get(srcIdx + 2)); + } + } } } return this.resizeBuffer; } + + public enum InterpolationMethod { + LINEAR, + NEAREST_NEIGHBOR + } }