From ced45bb66fbf7a3104706da70c00f9b867c8b8fe Mon Sep 17 00:00:00 2001 From: johni0702 Date: Wed, 17 Jun 2015 10:20:44 +0200 Subject: [PATCH] Improve cubic to equirectangular conversion by only computing pixel locations once Fix empty try-catch in MinecraftTicker --- .../events/handlers/MinecraftTicker.java | 5 +- .../frame/EquirectangularFrameRenderer.java | 123 ++++++++++++------ 2 files changed, 89 insertions(+), 39 deletions(-) diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java index a2ea2193..954fd54b 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/MinecraftTicker.java @@ -246,7 +246,10 @@ public class MinecraftTicker { if(mc != null) mc.systemTime = Minecraft.getSystemTime(); - } catch(Exception e) { + } catch (ReportedException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/frame/EquirectangularFrameRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/frame/EquirectangularFrameRenderer.java index f8ab4908..9ef280cc 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/frame/EquirectangularFrameRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/frame/EquirectangularFrameRenderer.java @@ -13,9 +13,20 @@ import static java.lang.Math.PI; public class EquirectangularFrameRenderer extends FrameRenderer { + private static final byte IMAGE_BACK = 0; + private static final byte IMAGE_FRONT = 1; + private static final byte IMAGE_LEFT = 2; + private static final byte IMAGE_RIGHT = 3; + private static final byte IMAGE_TOP = 4; + private static final byte IMAGE_BOTTOM = 5; + private final int frameSize; protected final CubicEntityRenderer entityRenderer; + private byte[][] image; + private double[][] imageX; + private double[][] imageY; + public EquirectangularFrameRenderer(RenderOptions options, boolean stable) { super(options); this.frameSize = options.getWidth() / 4; @@ -23,6 +34,56 @@ public class EquirectangularFrameRenderer extends FrameRenderer { setCustomEntityRenderer(entityRenderer); } + private void computeCubicToEquirectangularTables() { + int rWidth = getVideoWidth(); + int rHeight = getVideoHeight(); + image = new byte[rWidth][rHeight]; + imageX = new double[rWidth][rHeight]; + imageY = new double[rWidth][rHeight]; + for (int i = 0; i < rWidth; i++) { + double yaw = PI * 2 * i / rWidth; + int piQuarter = 8 * i / rWidth - 4; + byte target; + if (piQuarter < -3) { + target = IMAGE_BACK; + } else if (piQuarter < -1) { + target = IMAGE_LEFT; + } else if (piQuarter < 1) { + target = IMAGE_FRONT; + } else if (piQuarter < 3) { + target = IMAGE_RIGHT; + } else { + target = IMAGE_BACK; + } + double fYaw = (yaw + PI/4) % (PI / 2) - PI/4; + double d = 1 / Math.cos(fYaw); + double gcXN = (Math.tan(fYaw) + 1) / 2; + for (int j = 0; j < rHeight; j++) { + double cXN = gcXN; + byte pt = target; + double pitch = PI * j / rHeight - PI / 2; + double cYN = (Math.tan(pitch) * d + 1) / 2; + + if (cYN >= 1) { + double pd = Math.tan(PI/2 - pitch); + cXN = (-Math.sin(yaw) * pd + 1) / 2; + cYN = (Math.cos(yaw) * pd + 1) / 2; + pt = IMAGE_BOTTOM; + } + if (cYN < 0) { + double pd = Math.tan(PI/2 - pitch); + cXN = (Math.sin(yaw) * pd + 1) / 2; + cYN = (Math.cos(yaw) * pd + 1) / 2; + pt = IMAGE_TOP; + } + + image[i][j] = pt; + imageX[i][j] = Math.min(frameSize - 1, (cXN * frameSize)); + imageY[i][j] = Math.min(frameSize - 1, (cYN * frameSize)); + } + } + } + @Override public BufferedImage captureFrame(Timer timer) { BufferedImage top = captureFrame(timer, CubicEntityRenderer.Direction.TOP); @@ -42,50 +103,36 @@ public class EquirectangularFrameRenderer extends FrameRenderer { } protected BufferedImage cubicToEquirectangular(BufferedImage top, BufferedImage bottom, BufferedImage front, BufferedImage back, BufferedImage left, BufferedImage right) { + int[][] images = { + ((DataBufferInt) back.getRaster().getDataBuffer()).getData(), + ((DataBufferInt) front.getRaster().getDataBuffer()).getData(), + ((DataBufferInt) left.getRaster().getDataBuffer()).getData(), + ((DataBufferInt) right.getRaster().getDataBuffer()).getData(), + ((DataBufferInt) top.getRaster().getDataBuffer()).getData(), + ((DataBufferInt) bottom.getRaster().getDataBuffer()).getData() + }; + + int fWidth = frameSize; int rWidth = getVideoWidth(); int rHeight = getVideoHeight(); + if (image == null || image.length != rWidth || image[0].length != rHeight) { + try { + computeCubicToEquirectangularTables(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + BufferedImage result = new BufferedImage(rWidth, rHeight, BufferedImage.TYPE_INT_RGB); int[] resultPixels = ((DataBufferInt) result.getRaster().getDataBuffer()).getData(); + byte[] image; + double[] imageX, imageY; for (int i = 0; i < rWidth; i++) { - double yaw = PI * 2 * i / rWidth; - int piQuarter = 8 * i / rWidth - 4; - BufferedImage target; - if (piQuarter < -3) { - target = back; - } else if (piQuarter < -1) { - target = left; - } else if (piQuarter < 1) { - target = front; - } else if (piQuarter < 3) { - target = right; - } else { - target = back; - } - double fYaw = (yaw + PI/4) % (PI / 2) - PI/4; - double d = 1 / Math.cos(fYaw); - double gcXN = (Math.tan(fYaw) + 1) / 2; + image = this.image[i]; + imageX = this.imageX[i]; + imageY = this.imageY[i]; for (int j = 0; j < rHeight; j++) { - double cXN = gcXN; - BufferedImage pt = target; - double pitch = PI * j / rHeight - PI / 2; - double cYN = (Math.tan(pitch) * d + 1) / 2; - - if (cYN >= 1) { - double pd = Math.tan(PI/2 - pitch); - cXN = (-Math.sin(yaw) * pd + 1) / 2; - cYN = (Math.cos(yaw) * pd + 1) / 2; - pt = bottom; - } - if (cYN < 0) { - double pd = Math.tan(PI/2 - pitch); - cXN = (Math.sin(yaw) * pd + 1) / 2; - cYN = (Math.cos(yaw) * pd + 1) / 2; - pt = top; - } - - int cX = Math.min(frameSize - 1, (int) (cXN * frameSize)); - int cY = Math.min(frameSize - 1, (int) (cYN * frameSize)); - resultPixels[i + j * rWidth] = 0xff000000 | pt.getRGB(cX, cY); // Make sure we got alpha value as well + resultPixels[i + j * rWidth] = images[image[j]][(int) imageX[j] + (int) imageY[j] * fWidth]; } }