Improve cubic to equirectangular conversion by only computing pixel locations once
Fix empty try-catch in MinecraftTicker
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user