Improve cubic to equirectangular conversion by only computing pixel locations once

Fix empty try-catch in MinecraftTicker
This commit is contained in:
johni0702
2015-06-17 10:20:44 +02:00
parent b463dcaa4d
commit ced45bb66f
2 changed files with 89 additions and 39 deletions

View File

@@ -246,7 +246,10 @@ public class MinecraftTicker {
if(mc != null) if(mc != null)
mc.systemTime = Minecraft.getSystemTime(); mc.systemTime = Minecraft.getSystemTime();
} catch(Exception e) { } catch (ReportedException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
} }
} }
} }

View File

@@ -13,9 +13,20 @@ import static java.lang.Math.PI;
public class EquirectangularFrameRenderer extends FrameRenderer { 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; private final int frameSize;
protected final CubicEntityRenderer entityRenderer; protected final CubicEntityRenderer entityRenderer;
private byte[][] image;
private double[][] imageX;
private double[][] imageY;
public EquirectangularFrameRenderer(RenderOptions options, boolean stable) { public EquirectangularFrameRenderer(RenderOptions options, boolean stable) {
super(options); super(options);
this.frameSize = options.getWidth() / 4; this.frameSize = options.getWidth() / 4;
@@ -23,6 +34,56 @@ public class EquirectangularFrameRenderer extends FrameRenderer {
setCustomEntityRenderer(entityRenderer); 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 @Override
public BufferedImage captureFrame(Timer timer) { public BufferedImage captureFrame(Timer timer) {
BufferedImage top = captureFrame(timer, CubicEntityRenderer.Direction.TOP); 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) { 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 rWidth = getVideoWidth();
int rHeight = getVideoHeight(); 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); BufferedImage result = new BufferedImage(rWidth, rHeight, BufferedImage.TYPE_INT_RGB);
int[] resultPixels = ((DataBufferInt) result.getRaster().getDataBuffer()).getData(); int[] resultPixels = ((DataBufferInt) result.getRaster().getDataBuffer()).getData();
byte[] image;
double[] imageX, imageY;
for (int i = 0; i < rWidth; i++) { for (int i = 0; i < rWidth; i++) {
double yaw = PI * 2 * i / rWidth; image = this.image[i];
int piQuarter = 8 * i / rWidth - 4; imageX = this.imageX[i];
BufferedImage target; imageY = this.imageY[i];
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;
for (int j = 0; j < rHeight; j++) { for (int j = 0; j < rHeight; j++) {
double cXN = gcXN; resultPixels[i + j * rWidth] = images[image[j]][(int) imageX[j] + (int) imageY[j] * fWidth];
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
} }
} }