updating voxelengine
my voxel engine now has a proper raycasting routine which allows you to look up and down without any unwanted distortion. in addition, it now has 10 background images it will cycle through on the menu and a bunch of new palettes.master
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 145 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 20 KiB |
|
@ -21,25 +21,54 @@ import java.awt.event.ItemListener;
|
|||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
|
||||
public class Menu extends Applet implements ActionListener, ItemListener {
|
||||
@SuppressWarnings("serial")
|
||||
public class Menu extends Applet implements ActionListener, ItemListener, Runnable {
|
||||
@SuppressWarnings("unused")
|
||||
private Button generateWorld, settings, quit, ok, back, generate;
|
||||
private TextField size, worldSize, minIt, maxIt, power, zoom, cutoff;
|
||||
@SuppressWarnings("unused")
|
||||
private Label sizeL, colorL, worldSizeL, minItL, maxItL, powerL, zoomL, resL, pixL, castL, cutoffL;
|
||||
private Choice choice, color;
|
||||
private AudioClip sound;
|
||||
private Image background;
|
||||
private Image bg1, bg2, bg3, bg4, bg5, bg6, bg7, bg8, bg9, bg10;
|
||||
private Image[] slideshow;
|
||||
private Panel pnl;
|
||||
private int ndx = 0;
|
||||
private long time = System.currentTimeMillis();
|
||||
private long ttime = 4000;
|
||||
private Thread rpThread;
|
||||
|
||||
public void start() {
|
||||
if (rpThread == null) {
|
||||
rpThread = new Thread(this, "repaint");
|
||||
rpThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.setSize(784, 562);
|
||||
background = getImage(getCodeBase(), "background.jpg");
|
||||
bg1 = getImage(getCodeBase(), "bg1.jpg");
|
||||
bg2 = getImage(getCodeBase(), "bg2.jpg");
|
||||
bg3 = getImage(getCodeBase(), "bg3.jpg");
|
||||
bg4 = getImage(getCodeBase(), "bg4.jpg");
|
||||
bg5 = getImage(getCodeBase(), "bg5.jpg");
|
||||
bg6 = getImage(getCodeBase(), "bg6.jpg");
|
||||
bg7 = getImage(getCodeBase(), "bg7.jpg");
|
||||
bg8 = getImage(getCodeBase(), "bg8.jpg");
|
||||
bg9 = getImage(getCodeBase(), "bg9.jpg");
|
||||
bg10 = getImage(getCodeBase(), "bg10.jpg");
|
||||
slideshow = new Image[]{bg1, bg2, bg3, bg4, bg5, bg6, bg7, bg8, bg9, bg10};
|
||||
sound = getAudioClip(getCodeBase(), "menu.au");
|
||||
sound.loop();
|
||||
mainMenu();
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
g.drawImage(background, 0, 0, this);
|
||||
if (System.currentTimeMillis() - time >= ttime) {
|
||||
time = System.currentTimeMillis();
|
||||
ndx = (ndx + 1) % 9;
|
||||
}
|
||||
g.drawImage(slideshow[ndx], 0, 0, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -224,6 +253,10 @@ public class Menu extends Applet implements ActionListener, ItemListener {
|
|||
color.removeAll();
|
||||
color.addItem("test");
|
||||
color.addItem("blackNblue");
|
||||
color.addItem("glory");
|
||||
color.addItem("boutique");
|
||||
color.addItem("goldfish");
|
||||
color.addItem("dreamy");
|
||||
powerL.setText("Power: ");
|
||||
power.setEnabled(true);
|
||||
zoom.setEnabled(false);
|
||||
|
@ -238,6 +271,10 @@ public class Menu extends Applet implements ActionListener, ItemListener {
|
|||
color.removeAll();
|
||||
color.addItem("test");
|
||||
color.addItem("blackNblue");
|
||||
color.addItem("glory");
|
||||
color.addItem("boutique");
|
||||
color.addItem("goldfish");
|
||||
color.addItem("dreamy");
|
||||
powerL.setText("Scale: ");
|
||||
power.setEnabled(true);
|
||||
zoom.setEnabled(true);
|
||||
|
@ -300,4 +337,15 @@ public class Menu extends Applet implements ActionListener, ItemListener {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (rpThread != null) {
|
||||
repaint();
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package voxelengine;
|
|||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.MemoryImageSource;
|
||||
import static java.lang.Math.*;
|
||||
|
||||
public class Renderer {
|
||||
private World world;
|
||||
|
@ -18,71 +19,6 @@ public class Renderer {
|
|||
this.camera = camera;
|
||||
}
|
||||
|
||||
// rendering methods
|
||||
public MemoryImageSource render(int width, int height, int pixelScale, int castScale) {
|
||||
int[] mem = new int[width*height];
|
||||
|
||||
// raycast for each pixel
|
||||
for (int py = 0; py < height - pixelScale; py += pixelScale) {
|
||||
for (int px = 0; px < width - pixelScale; px += pixelScale) {
|
||||
if (pixelScale == 1)
|
||||
mem[px + py * width] = raycast(px, py, width, height, castScale);
|
||||
else {
|
||||
int val = raycast(px, py, width, height, castScale);
|
||||
for (int pys = 0; pys < pixelScale; ++pys) {
|
||||
for (int pxs = 0; pxs < pixelScale; ++pxs) {
|
||||
mem[px + pxs + (py + pys) * width] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return image source
|
||||
return new MemoryImageSource(width, height, mem, 0, width);
|
||||
}
|
||||
|
||||
private int raycast(int px, int py, int width, int height, int castScale) {
|
||||
double w2 = width/2;
|
||||
double h2 = height/2;
|
||||
double yaw = camera.rotY + ((px - w2) / w2) * Math.PI / 4;
|
||||
double pitch = camera.rotX + ((py - h2) / h2) * Math.PI / 4;
|
||||
|
||||
double x1 = camera.x;
|
||||
double y1 = camera.y;
|
||||
double z1 = camera.z;
|
||||
int x2, y2, z2;
|
||||
|
||||
double xs = Math.sin(pitch) * Math.cos(yaw) / castScale;
|
||||
double ys = Math.sin(pitch) * Math.sin(yaw) / castScale;
|
||||
double zs = Math.cos(pitch) / castScale;
|
||||
|
||||
while (inBoundsC(x1, y1, z1)) {
|
||||
Block block = world.getBlock(x1, y1, z1);
|
||||
if (block != null) {
|
||||
Color c = block.getType().getColor();
|
||||
c = CalculateColor(c, camera.x, x1, camera.y, y1, camera.z, z1);
|
||||
return c.getRGB();
|
||||
}
|
||||
x2 = (int) x1;
|
||||
y2 = (int) y1;
|
||||
z2 = (int) z1;
|
||||
do {
|
||||
x1 += xs;
|
||||
y1 += ys;
|
||||
z1 += zs;
|
||||
} while ((int) x1 == x2 && (int) y1 == y2 && (int) z1 == z2);
|
||||
}
|
||||
|
||||
return SkyboxColor.getRGB();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private boolean inBounds(double x, double y, double z) {
|
||||
int b = world.getSize() * 16;
|
||||
return x >= 0 && x < b && y >= 0 && y < b && z >= 0 && z < b;
|
||||
}
|
||||
|
||||
public MemoryImageSource renderC(int width, int height, int pixelScale, int castScale) {
|
||||
int[] mem = new int[width*height];
|
||||
|
||||
|
@ -168,16 +104,23 @@ public class Renderer {
|
|||
return x >= 0 && x < b && y >= 0 && y < b && z >= 0 && z < b && dx < renderDistance && dy < renderDistance && dz < renderDistance;
|
||||
}
|
||||
|
||||
public MemoryImageSource renderD(int width, int height, int pixelScale, int castScale) {
|
||||
public MemoryImageSource renderE(int width, int height, int pixelScale, int castScale) {
|
||||
int[] mem = new int[width*height];
|
||||
double yaw = camera.rotY;
|
||||
double pitch = camera.rotX;
|
||||
double[][] ref = new double[][] {
|
||||
{sin(pitch)*cos(yaw), sin(pitch)*sin(yaw), -cos(pitch)},
|
||||
{-sin(yaw), cos(yaw), 0}, // equal to cos(yaw + PI/2), sin(yaw + PI/2), 0
|
||||
{cos(pitch)*cos(yaw), cos(pitch)*sin(yaw), 2*sin(pitch)} // cross product of the two vectors above
|
||||
};
|
||||
|
||||
// raycast for each pixel
|
||||
for (int py = 0; py < height - pixelScale; py += pixelScale) {
|
||||
for (int px = 0; px < width - pixelScale; px += pixelScale) {
|
||||
if (pixelScale == 1)
|
||||
mem[px + py * width] = raycastD(px, py, width, height, castScale);
|
||||
mem[px + py * width] = raycastE(px, py, width, height, castScale, ref);
|
||||
else {
|
||||
int val = raycastD(px, py, width, height, castScale);
|
||||
int val = raycastE(px, py, width, height, castScale, ref);
|
||||
for (int pys = 0; pys < pixelScale; ++pys) {
|
||||
for (int pxs = 0; pxs < pixelScale; ++pxs) {
|
||||
mem[px + pxs + (py + pys) * width] = val;
|
||||
|
@ -190,15 +133,13 @@ public class Renderer {
|
|||
// return image source
|
||||
return new MemoryImageSource(width, height, mem, 0, width);
|
||||
}
|
||||
|
||||
private int raycastD(int px, int py, int width, int height, int castScale) {
|
||||
|
||||
private int raycastE(int px, int py, int width, int height, int castScale, double[][] ref) {
|
||||
double w2 = width/2;
|
||||
double h2 = height/2;
|
||||
double yaw = camera.rotY + ((px - w2) / w2) * Math.PI / 4;
|
||||
double pitch = camera.rotX + ((py - h2) / h2) * Math.PI / 4;
|
||||
yaw = (pitch < 0 || pitch > Math.PI) ? (yaw + Math.PI) % (2*Math.PI): yaw;
|
||||
pitch = (pitch < 0) ? Math.abs(pitch) : pitch;
|
||||
pitch = (pitch > Math.PI) ? 2*Math.PI - pitch : pitch;
|
||||
double fov = camera.fov/2;
|
||||
double yawr = ((px - w2) / w2) * fov;
|
||||
double pitchr = ((py - h2) / h2) * fov * 0.5; // correction because view window isn't 1:1
|
||||
|
||||
double x1 = camera.x;
|
||||
double y1 = camera.y;
|
||||
|
@ -206,9 +147,15 @@ public class Renderer {
|
|||
int x2, y2, z2;
|
||||
int cx1, cy1, cz1, cx2, cy2, cz2;
|
||||
|
||||
double xs = Math.sin(pitch) * Math.cos(yaw) / castScale;
|
||||
double ys = Math.sin(pitch) * Math.sin(yaw) / castScale;
|
||||
double zs = Math.cos(pitch) / castScale;
|
||||
double[] ray = new double[]{ cos(pitchr)*cos(yawr), cos(pitchr)*sin(yawr), -sin(pitchr) };
|
||||
ray = new double[] {
|
||||
ray[0] * ref[0][0] + ray[1] * ref[1][0] + ray[2] * ref[2][0],
|
||||
ray[0] * ref[0][1] + ray[1] * ref[1][1] + ray[2] * ref[2][1],
|
||||
ray[0] * ref[0][2] + ray[1] * ref[1][2] + ray[2] * ref[2][2],
|
||||
};
|
||||
double xs = ray[0]/castScale;
|
||||
double ys = ray[1]/castScale;
|
||||
double zs = ray[2]/castScale;
|
||||
|
||||
while (inBoundsC(x1, y1, z1)) {
|
||||
// chunk processing
|
||||
|
|
|
@ -23,7 +23,7 @@ public class SwingInterface extends JPanel {
|
|||
|
||||
private static final int X_SIZE = 800;
|
||||
private static final int Y_SIZE = 600;
|
||||
private static int pixelScale = 4;
|
||||
private static int pixelScale = 2;
|
||||
private static int castScale = 4;
|
||||
|
||||
public SwingInterface() {
|
||||
|
@ -60,7 +60,7 @@ public class SwingInterface extends JPanel {
|
|||
time = System.currentTimeMillis();
|
||||
}
|
||||
process_input();
|
||||
Image img = createImage(renderer.renderC(X_SIZE, Y_SIZE, pixelScale, castScale));
|
||||
Image img = createImage(renderer.renderE(X_SIZE, Y_SIZE, pixelScale, castScale));
|
||||
BufferedImage buffer = new BufferedImage(X_SIZE, Y_SIZE, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2 = buffer.createGraphics();
|
||||
g2.drawImage(img, 0, 0, null);
|
||||
|
|
|
@ -328,11 +328,35 @@ public class World {
|
|||
library.addType(new BlockType(null, "white", "A", Color.WHITE));
|
||||
library.addType(new BlockType(null, "gray", "B", Color.GRAY));
|
||||
library.addType(new BlockType(null, "darkGray", "C", Color.DARK_GRAY));
|
||||
library.addType(new BlockType(null, "gloriousBlue", "D", new Color(7,8,114)));
|
||||
library.addType(new BlockType(null, "watermelon", "E", new Color(247,70,122)));
|
||||
library.addType(new BlockType(null, "gloriousViolet", "F", new Color(73,8,162)));
|
||||
library.addType(new BlockType(null, "darkBlue", "G", new Color(14,0,42)));
|
||||
library.addType(new BlockType(null, "brownPurple", "H", new Color(40,0,22)));
|
||||
library.addType(new BlockType(null, "turquoise", "I", new Color(85,135,136)));
|
||||
library.addType(new BlockType(null, "lightTurquoise", "J", new Color(136,181,178)));
|
||||
library.addType(new BlockType(null, "klineWhite", "K", new Color(224,225,219)));
|
||||
library.addType(new BlockType(null, "salmon", "L", new Color(255,179,158)));
|
||||
library.addType(new BlockType(null, "rust", "M", new Color(183,63,38)));
|
||||
library.addType(new BlockType(null, "strongCyan", "N", new Color(105,210,231)));
|
||||
library.addType(new BlockType(null, "muddledCyan", "O", new Color(167,219,216)));
|
||||
library.addType(new BlockType(null, "stormyWhite", "P", new Color(224,228,204)));
|
||||
library.addType(new BlockType(null, "goldfish", "Q", new Color(243,134,48)));
|
||||
library.addType(new BlockType(null, "strongOrange", "R", new Color(250,105,0)));
|
||||
library.addType(new BlockType(null, "lime", "S", new Color(207,240,158)));
|
||||
library.addType(new BlockType(null, "greenFoam", "T", new Color(168,219,168)));
|
||||
library.addType(new BlockType(null, "seaGreen", "U", new Color(121,189,154)));
|
||||
library.addType(new BlockType(null, "darkTurquoise", "V", new Color(59,134,134)));
|
||||
library.addType(new BlockType(null, "royalBlue", "W", new Color(11,72,107)));
|
||||
}
|
||||
|
||||
public void addPalettes() {
|
||||
palettes.add(new Palette("test", new String[]{"white", "gray", "darkGray", "black", "red", "orange", "yellow", "green", "cyan", "blue", "magenta", "pink"}));
|
||||
palettes.add(new Palette("blackNblue", new String[]{"white", "gray", "darkGray", "black", "blue", "cyan", "white", "gray", "darkGray", "blue", "cyan", "white"}));
|
||||
palettes.add(new Palette("glory", new String[]{"gloriousBlue", "watermelon", "gloriousViolet", "darkBlue", "brownPurple", "gloriousBlue", "watermelon", "gloriousViolet", "darkBlue", "brownPurple"}));
|
||||
palettes.add(new Palette("boutique", new String[]{"turquoise", "lightTurquoise", "klineWhite", "salmon", "rust", "turquoise", "lightTurquoise", "klineWhite", "salmon", "rust"}));
|
||||
palettes.add(new Palette("goldfish", new String[]{"strongCyan", "muddledCyan", "stormyWhite", "goldfish", "strongOrange", "strongCyan", "muddledCyan", "stormyWhite", "goldfish", "strongOrange"}));
|
||||
palettes.add(new Palette("dreamy", new String[]{"lime", "greenFoam", "seaGreen", "darkTurquoise", "royalBlue", "lime", "greenFoam", "seaGreen", "darkTurquoise", "royalBlue"}));
|
||||
}
|
||||
|
||||
public Palette getPalette(String name) {
|
||||
|
|