Optimized worlds, new backgrounds, etc.

Blocks are now bytes!  World size can be much larger now.

Worlds can now be saved and loaded (with GZIP compression because no one
like 1gb world files).

Backgrounds have been updated.  32 new images of a much higher quality
(thanks to sexy drop shadows).  Background is shuffled each time the
program is run.
master
matortheeternal 2014-06-28 21:38:06 -07:00
parent 280fd75c44
commit 3ce968075b
57 changed files with 287 additions and 225 deletions

View File

@ -2,5 +2,6 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="lib" path="libs/commons-io-2.4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1 +0,0 @@
/voxelengine

BIN
VoxelEngine/bin/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

BIN
VoxelEngine/bin/10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

BIN
VoxelEngine/bin/11.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

BIN
VoxelEngine/bin/12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

BIN
VoxelEngine/bin/13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

BIN
VoxelEngine/bin/14.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
VoxelEngine/bin/15.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
VoxelEngine/bin/16.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 KiB

BIN
VoxelEngine/bin/18.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

BIN
VoxelEngine/bin/19.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

BIN
VoxelEngine/bin/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

BIN
VoxelEngine/bin/20.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

BIN
VoxelEngine/bin/21.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

BIN
VoxelEngine/bin/22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 KiB

BIN
VoxelEngine/bin/23.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
VoxelEngine/bin/24.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

BIN
VoxelEngine/bin/25.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

BIN
VoxelEngine/bin/26.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
VoxelEngine/bin/27.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
VoxelEngine/bin/28.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
VoxelEngine/bin/29.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

BIN
VoxelEngine/bin/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

BIN
VoxelEngine/bin/30.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

BIN
VoxelEngine/bin/31.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 KiB

BIN
VoxelEngine/bin/32.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

BIN
VoxelEngine/bin/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

BIN
VoxelEngine/bin/5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
VoxelEngine/bin/6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

BIN
VoxelEngine/bin/7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
VoxelEngine/bin/8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 KiB

BIN
VoxelEngine/bin/9.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

View File

@ -1,8 +0,0 @@
<html>
<Head>
</Head>
<Body>
<applet code="voxelengine.Menu.class" width="800" height="640">
</applet>
</Body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,4 +0,0 @@
<html>
<applet code="voxelengine.Menu.class" width="800" height="640">
</applet>
</html>

View File

@ -1,16 +0,0 @@
package voxelengine;
public class Block {
private BlockType type;
// constructor
public Block(BlockType type) {
super();
this.type = type;
}
// getters
public BlockType getType() {
return type;
}
}

View File

@ -9,9 +9,17 @@ public class BlockLibrary {
public void addType(BlockType type) {
library.add(type);
}
public BlockType getType(String id) {
public BlockType getType(byte id) {
for (int i = 0; i < library.size(); i++)
if ((library.get(i).getId().equals(id)) || (library.get(i).getName().equals(id)))
if (library.get(i).getId() == (id))
return library.get(i);
// if not found, return null
return null;
}
public BlockType getType(String string) {
for (int i = 0; i < library.size(); i++)
if (library.get(i).getName().equals(string))
return library.get(i);
// if not found, return null

View File

@ -6,15 +6,15 @@ import java.awt.Image;
public class BlockType {
private Image texture;
private String name;
private String id;
private byte id;
private Color color;
// constructor
public BlockType(Image texture, String name, String id, Color color) {
public BlockType(Image texture, String name, int id, Color color) {
super();
this.texture = texture;
this.name = name;
this.id = id;
this.id = (byte) id;
this.color = color;
}
@ -25,7 +25,7 @@ public class BlockType {
public String getName() {
return name;
}
public String getId() {
public byte getId() {
return id;
}
public Color getColor() {

View File

@ -1,18 +1,18 @@
package voxelengine;
public class Palette {
public class BytePalette {
private String name;
private String[] palette;
private byte[] palette;
// constructor
public Palette(String name, String[] palette) {
public BytePalette(String name, byte[] palette) {
super();
this.name = name;
this.palette = palette;
}
// methods
public String get(int index) {
public byte get(int index) {
return palette[index];
}
public String getName() {

View File

@ -2,61 +2,24 @@ package voxelengine;
public class Chunk {
private static int sz = 16;
private Block[][][] blocks = new Block[sz][sz][sz];
private byte[][][] blocks = new byte[sz][sz][sz];
// methods
public void setBlock(BlockType type, int x, int y, int z) {
blocks[x][y][z] = new Block(type);
public void setBlock(byte type, int x, int y, int z) {
blocks[x][y][z] = type;
}
public Block getBlock(int x, int y, int z) {
public byte getBlock(int x, int y, int z) {
return blocks[x][y][z];
}
public boolean checkIfEmpty() {
for (int x = 0; x < sz; x++) {
for (int y = 0; y < sz; y++) {
for (int z = 0; z < sz; z++) {
if (blocks[x][y][z] != null)
if (blocks[x][y][z] != 0)
return false;
}
}
}
return true;
}
// saving and loading
public String saveChunk() {
// data header
String data = Integer.toString(sz) + "\n";
// save data
for (int x = 0; x < sz; x++) {
for (int y = 0; y < sz; y++) {
for (int z = 0; z < sz; z++) {
if (blocks[x][y][z] != null)
data += blocks[x][y][z].getType().getId();
else
data += "0";
}
}
}
return data;
}
public void loadChunk(String data, BlockLibrary lib) throws Exception {
// first check if chunk sizes match
int size = Integer.parseInt(data.substring(0, data.indexOf("\n") - 1));
if (size != sz)
throw new Exception();
// then load data
for (int i = 0; i < data.length(); i++) {
if (data.charAt(i) == '0')
continue;
// calculate current 3d location
int z = (int) (i/(sz*sz));
int y = (int) ((i - z)/sz);
int x = i - z - y;
blocks[x][y][z] = new Block(lib.getType(String.valueOf(data.charAt(i))));
}
}
}

View File

@ -37,6 +37,7 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
private long time = System.currentTimeMillis();
private long ttime = 4000;
private Thread rpThread;
private static final int bgcount = 32;
public void start() {
if (rpThread == null) {
@ -47,19 +48,27 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
public void init() {
this.setSize(784, 562);
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};
// load slideshow
slideshow = new Image[bgcount];
for (int i = 0; i < bgcount; i++) {
slideshow[i] = getImage(getCodeBase(), Integer.toString(i+1)+".jpg");
}
// shuffle slideshow
for (int i = 0; i < 3 * bgcount; i++) {
int i1 = i % bgcount;
int i2 = (int) (Math.random() * bgcount);
Image s1 = slideshow[i1];
Image s2 = slideshow[i2];
slideshow[i1] = s2;
slideshow[i2] = s1;
}
// start menu music
sound = getAudioClip(getCodeBase(), "menu.au");
sound.loop();
// create menu
mainMenu();
}
@ -127,6 +136,7 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
choice.addItem("Mandelbox");
choice.addItem("Greek Cross");
choice.addItem("Octahedron");
choice.addItem("Load");
choice.setMaximumSize(new Dimension(140, 40));
choice.setForeground(Color.LIGHT_GRAY);
choice.setBackground(Color.BLACK);
@ -225,6 +235,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
}
public void mengerMenu() {
color.setEnabled(true);
colorL.setEnabled(true);
colorL.setText("Color: ");
color.removeAll();
color.addItem("red");
@ -248,6 +260,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
}
public void crossMenu() {
color.setEnabled(true);
colorL.setEnabled(true);
colorL.setText("Color: ");
color.removeAll();
color.addItem("red");
@ -273,6 +287,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
}
public void octahedronMenu() {
color.setEnabled(true);
colorL.setEnabled(true);
colorL.setText("Color: ");
color.removeAll();
color.addItem("red");
@ -298,6 +314,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
}
public void bulbMenu() {
color.setEnabled(true);
colorL.setEnabled(true);
colorL.setText("Palette: ");
color.removeAll();
color.addItem("test");
@ -309,6 +327,7 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
powerL.setText("Power: ");
size.setText("81");
power.setEnabled(true);
power.setText("8");
zoom.setEnabled(false);
minIt.setEnabled(true);
maxIt.setEnabled(true);
@ -317,6 +336,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
}
public void boxMenu() {
color.setEnabled(true);
colorL.setEnabled(true);
colorL.setText("Palette: ");
color.removeAll();
color.addItem("test");
@ -336,6 +357,17 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
cutoff.setText("5");
}
public void loadMenu() {
color.setEnabled(true);
power.setEnabled(false);
color.removeAll();
color.addItem("test.wrl");
zoom.setEnabled(false);
minIt.setEnabled(false);
maxIt.setEnabled(false);
cutoff.setEnabled(false);
}
public void settingsMenu() {
back = new Button("Back");
back.setMaximumSize(new Dimension(140, 40));
@ -390,6 +422,8 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
crossMenu();
} else if (sel.equals("Octahedron")) {
octahedronMenu();
} else if (sel.equals("Load")) {
loadMenu();
}
}
}
@ -399,7 +433,7 @@ public class Menu extends Applet implements ActionListener, ItemListener, Runnab
while (rpThread != null) {
if (System.currentTimeMillis() - time >= ttime) {
time = System.currentTimeMillis();
ndx = (ndx + 1) % 9;
ndx = (ndx + 1) % bgcount;
}
try {
Thread.sleep(500);

View File

@ -0,0 +1,27 @@
package voxelengine;
public class Octree {
public boolean head;
public Octree[] children;
public Octree() {
this.head = false;
this.children = new Octree[8];
}
public boolean getHead() {
return head;
}
public void setHead(boolean head) {
this.head = head;
}
public Octree getChild(byte ndx) {
return children[ndx];
}
public void setChild(byte ndx, Octree child) {
this.children[ndx] = child;
}
}

View File

@ -1,12 +1,12 @@
package voxelengine;
public class RayCastCollision {
private Block collisionBlock;
private byte collisionBlock;
private int face;
private double x, y, z;
public RayCastCollision(Block collisionBlock, int face, double x, double y, double z) {
public RayCastCollision(byte collisionBlock, int face, double x, double y, double z) {
super();
this.collisionBlock = collisionBlock;
this.face = face;
@ -15,11 +15,11 @@ public class RayCastCollision {
this.z = z;
}
public Block getCollisionBlock() {
public byte getCollisionBlock() {
return collisionBlock;
}
public void setCollisionBlock(Block collisionBlock) {
public void setCollisionBlock(byte collisionBlock) {
this.collisionBlock = collisionBlock;
}

View File

@ -80,9 +80,9 @@ public class Renderer {
}
// block processing
Block block = world.getBlock(x1, y1, z1);
if (block != null) {
Color c = block.getType().getColor();
byte block = world.getBlock(x1, y1, z1);
if (block != 0) {
Color c = world.getType(block).getColor();
c = CalculateColor(c, camera.x, x1, camera.y, y1, camera.z, z1);
return c.getRGB();
}
@ -112,8 +112,22 @@ public class Renderer {
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
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
@ -142,7 +156,8 @@ public class Renderer {
double fovH = camera.fovH / 2;
double fovV = camera.fovV / 2;
double yawr = ((px - w2) / w2) * fovH;
double pitchr = ((py - h2) / h2) * fovV; // correction because view window isn't 1:1
double pitchr = ((py - h2) / h2) * fovV; // correction because view
// window isn't 1:1
double x1 = camera.x;
double y1 = camera.y;
@ -174,9 +189,9 @@ public class Renderer {
}
// block processing
Block block = world.getBlock(x1, y1, z1);
if (block != null) {
Color c = block.getType().getColor();
byte block = world.getBlock(x1, y1, z1);
if (block != 0) {
Color c = world.getType(block).getColor();
c = CalculateColor(c, camera.x, x1, camera.y, y1, camera.z, z1);
return c.getRGB();
}
@ -198,14 +213,17 @@ public class Renderer {
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
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 (camera.rotX != PI/2) System.out.println("Raycasting "+px+","+py);
// if (camera.rotX != PI/2)
// System.out.println("Raycasting "+px+","+py);
if (pixelScale == 1)
mem[px + py * width] = raycastF(px, py, width, height, ref);
else {
@ -240,7 +258,9 @@ public class Renderer {
double i1, i2, i3;
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], };
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];
double ys = ray[1];
double zs = ray[2];
@ -282,9 +302,9 @@ public class Renderer {
}
// block processing
Block block = world.getBlock(x1, y1, z1);
if (block != null) {
Color c = block.getType().getColor();
byte block = world.getBlock(x1, y1, z1);
if (block != 0) {
Color c = world.getType(block).getColor();
c = CalculateColor(c, camera.x, x1, camera.y, y1, camera.z, z1);
return c.getRGB();
}
@ -318,14 +338,15 @@ public class Renderer {
public MemoryImageSource renderG(int width, int height, int pixelScale, int castScale, boolean doShadows) {
if (mem.length != width * height) {
mem = new int[width * height]; // this is very marginally faster than recreating it every frame
mem = new int[width * height]; // this is very marginally faster
// than recreating it every frame
}
double yaw = camera.rotY;
double pitch = camera.rotX;
double[][] ref = new double[][] { { sin(pitch) * cos(yaw), sin(pitch) * sin(yaw), -cos(pitch) },
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
{ cos(pitch) * cos(yaw), cos(pitch) * sin(yaw), 2 * sin(pitch) } // cross product of the two vectors above
};
// raycast for each pixel
@ -333,8 +354,7 @@ public class Renderer {
for (int py = 0; py < height - pixelScale; py += pixelScale) {
for (int px = 0; px < width - pixelScale; px += pixelScale) {
if (pixelScale == 1) {
service.execute(new PixelWorker(mem, new int[] { px + py * width }, px, py, width, height, ref,
doShadows));
service.execute(new PixelWorker(mem, new int[] { px + py * width }, px, py, width, height, ref, doShadows));
} else {
int[] fbIndices = new int[pixelScale * pixelScale];
for (int pys = 0; pys < pixelScale; ++pys) {
@ -448,8 +468,8 @@ public class Renderer {
tMaxZ += tDeltaZ;
}
}
Block block = world.getBlock(x, y, z);
if (block != null) {
byte block = world.getBlock(x, y, z);
if (block != 0) {
double t = 0;
switch (face) {
case 0:
@ -462,8 +482,7 @@ public class Renderer {
t = tMaxZ - tDeltaZ - 0.01;
break;
}
return new RayCastCollision(block, face, t * dx / rayMagnitude + startX,
t * dy / rayMagnitude + startY, t * dz / rayMagnitude + startZ);
return new RayCastCollision(block, face, t * dx / rayMagnitude + startX, t * dy / rayMagnitude + startY, t * dz / rayMagnitude + startZ);
}
}
@ -486,8 +505,7 @@ public class Renderer {
return new Color(red, green, blue);
}
private Color CalculateColor(Color c, double x1, double x2, double y1, double y2, double z1, double z2, int face,
double directionalDot) {
private Color CalculateColor(Color c, double x1, double x2, double y1, double y2, double z1, double z2, int face, double directionalDot) {
double ray[] = { x1 - x2, y1 - y2, z1 - z2 };
double distance = Math.sqrt(ray[0] * ray[0] + ray[1] * ray[1] + ray[2] * ray[2]);
ray[0] /= distance;
@ -533,8 +551,7 @@ public class Renderer {
private double[][] ref;
private boolean doShadows;
public PixelWorker(int[] framebuffer, int[] fbIndices, int px, int py, int width, int height, double[][] ref,
boolean doShadows) {
public PixelWorker(int[] framebuffer, int[] fbIndices, int px, int py, int width, int height, double[][] ref, boolean doShadows) {
this.framebuffer = framebuffer;
this.fbIndices = fbIndices;
this.px = px;
@ -551,17 +568,15 @@ public class Renderer {
public void run() {
RayCastCollision result = Renderer.this.raycastGScreenCoords(px, py, width, height, ref);
Color c;
double lightRayMagnitude = Math.sqrt(lightRay[0] * lightRay[0] + lightRay[1] * lightRay[1] + lightRay[2]
* lightRay[2]);
double lightRayMagnitude = Math.sqrt(lightRay[0] * lightRay[0] + lightRay[1] * lightRay[1] + lightRay[2] * lightRay[2]);
if (result != null) {
Block block = result.getCollisionBlock();
byte block = result.getCollisionBlock();
double x = result.getX();
double y = result.getY();
double z = result.getZ();
double lightDot = 0;
if (doShadows) {
RayCastCollision lightOcclusion = Renderer.this.raycastG(result.getX(), result.getY(),
result.getZ(), lightRay);
RayCastCollision lightOcclusion = Renderer.this.raycastG(result.getX(), result.getY(), result.getZ(), lightRay);
if (lightOcclusion == null) {
switch (result.getFace()) {
case 0:
@ -576,8 +591,7 @@ public class Renderer {
}
}
}
c = Renderer.this.CalculateColor(block.getType().getColor(), camera.x, x, camera.y, y, camera.z, z,
result.getFace(), lightDot);
c = Renderer.this.CalculateColor(world.getType(block).getColor(), camera.x, x, camera.y, y, camera.z, z, result.getFace(), lightDot);
} else {
c = SkyboxColor;
}

View File

@ -82,7 +82,8 @@ public class SwingInterface extends JPanel {
long time = System.currentTimeMillis();
if (arguments[1].equals("Menger Sponge")) {
System.out.println("Generating Menger Sponge...");
world.generateMengerSponge(arguments[2], Integer.parseInt(arguments[3]), offset, offset, offset);
Byte b = (byte) world.getByteFromName(arguments[2]);
world.generateMengerSponge(b, Integer.parseInt(arguments[3]), offset, offset, offset);
} else if (arguments[1].equals("Mandelbulb")) {
System.out.println("Generating Mandelbulb...");
world.generateMandelbulb(arguments[2], Integer.parseInt(arguments[3]), Double.parseDouble(arguments[6]), Double.parseDouble(arguments[8]), offset, offset, offset, Integer.parseInt(arguments[4]), Integer.parseInt(arguments[5]));
@ -91,10 +92,15 @@ public class SwingInterface extends JPanel {
world.generateMandelbox(arguments[2], Integer.parseInt(arguments[3]), Double.parseDouble(arguments[6]), Double.parseDouble(arguments[8]), Integer.parseInt(arguments[4]), Integer.parseInt(arguments[5]), Double.parseDouble(arguments[7]), offset, offset, offset);
} else if (arguments[1].equals("Greek Cross")) {
System.out.println("Generating Greek Cross Fractal...");
world.generateCross(arguments[2], Integer.parseInt(arguments[3]), offset, offset, offset, Integer.parseInt(arguments[6]), 0);
Byte b = (byte) world.getByteFromName(arguments[2]);
world.generateCross(b, Integer.parseInt(arguments[3]), offset, offset, offset, Integer.parseInt(arguments[6]), 0);
} else if (arguments[1].equals("Octahedron")) {
System.out.println("Generating Octahedron Fractal...");
world.generateOctahedron(arguments[2], Integer.parseInt(arguments[3]), offset, offset, offset, Integer.parseInt(arguments[6]));
Byte b = (byte) world.getByteFromName(arguments[2]);
world.generateOctahedron(b, Integer.parseInt(arguments[3]), offset, offset, offset, Integer.parseInt(arguments[6]));
} else if (arguments[1].equals("Load")) {
System.out.println("Loading an existing world...");
world.load(arguments[6]);
}
System.out.println((Math.round((System.currentTimeMillis() - time)/10)/100.0)+" seconds spent generating world.");
time = System.currentTimeMillis();

View File

@ -1,15 +1,21 @@
package voxelengine;
import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Random;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class World {
private int size;
private Chunk[][][] chunks;
private boolean[][][] isEmpty;
private BlockLibrary library = new BlockLibrary();
private ArrayList<Palette> palettes = new ArrayList<Palette>();
private ArrayList<BytePalette> palettes = new ArrayList<BytePalette>();
// constructor
public World(int size) {
@ -38,7 +44,7 @@ public class World {
else
return null;
}
public Block getBlock(int x, int y, int z) {
public byte getBlock(int x, int y, int z) {
int xChunk = x/16;
int yChunk = y/16;
int zChunk = z/16;
@ -46,23 +52,22 @@ public class World {
if (chunk != null)
return chunk.getBlock(x % 16, y % 16, z % 16);
else
return null;
return 0;
}
public Block getBlock(double x, double y, double z) {
public byte getBlock(double x, double y, double z) {
int xi = (int) x;
int yi = (int) y;
int zi = (int) z;
return getBlock(xi, yi, zi);
}
public void setBlock(String id, int x, int y, int z) {
public void setBlock(byte id, int x, int y, int z) {
int xChunk = x/16;
int yChunk = y/16;
int zChunk = z/16;
Chunk chunk = getChunk(xChunk, yChunk, zChunk);
BlockType type = getType(id);
chunk.setBlock(type, x % 16, y % 16, z % 16);
chunk.setBlock(id, x % 16, y % 16, z % 16);
}
public void setBlock(String id, double x, double y, double z) {
public void setBlock(byte id, double x, double y, double z) {
int xi = (int) x;
int yi = (int) y;
int zi = (int) z;
@ -88,12 +93,12 @@ public class World {
public void addType(BlockType type) {
library.addType(type);
}
public BlockType getType(String id) {
public BlockType getType(byte id) {
return library.getType(id);
}
// world generation methods
public void generateMengerSponge(String id, int d0, int xOffset, int yOffset, int zOffset) {
public void generateMengerSponge(byte id, int d0, int xOffset, int yOffset, int zOffset) {
// place block and return if dimension = 1
if (d0 == 1) {
setBlock(id, xOffset, yOffset, zOffset);
@ -122,7 +127,7 @@ public class World {
}
}
public void generateBox(String id, int d0, int xOffset, int yOffset, int zOffset) {
public void generateBox(byte id, int d0, int xOffset, int yOffset, int zOffset) {
for (int x = 0; x < d0; x++) {
for (int y = 0; y < d0; y++) {
setBlock(id, x + xOffset, y + yOffset, zOffset);
@ -143,37 +148,9 @@ public class World {
}
}
public void generateBensWorld() {
for (int i = 0; i < 100; ++i) {
Random r = new Random(i);
for (int j = 0; j < 100; ++j) {
setBlock("blue", i, j, 0);
if ((i + j) % 2 == 0)
setBlock("red", i, 0, j);
else
setBlock("black", i, 0, j);
setBlock("orange", 0, i, j);
setBlock("cyan", i, j, 50);
setBlock("yellow", i, 99, j);
setBlock("pink", 99, i, j);
if (i % 4 == 0) {
int rand = r.nextInt(100);
if (rand < 10)
setBlock("green", i, 70, j);
else if (rand < 50)
setBlock("gray", i, 70, j);
else
setBlock("darkGray", i, 70, j);
} else if (i % 2 == 0)
setBlock("black", i, 70, j);
}
}
}
// generate mandelbulb
public void generateMandelbulb(String name, int d, double power, double cutoff, int xOffset, int yOffset, int zOffset, int itMin, int itMax) {
Palette palette = getPalette(name);
BytePalette palette = getPalette(name);
//palette.printContents();
for (int x = 0; x < d; x++) {
double xc = tf(x, d);
@ -194,7 +171,7 @@ public class World {
// place block if cutoff reached in itMin -> itMax range
if ((iterations >= itMin) && (iterations < itMax)) {
String id = palette.get(iterations - itMin);
byte id = palette.get(iterations - itMin);
//System.out.println("Placing block "+id+" at ("+(xOffset + x)+","+(yOffset + y)+","+(zOffset + z)+")");
setBlock(id, xOffset + x, yOffset + y, zOffset + z);
}
@ -242,7 +219,7 @@ public class World {
// generate mandelbox
public void generateMandelbox(String name, int d, double scale, double cutoff, int itMin, int itMax, double tfmult, int xOffset, int yOffset, int zOffset) {
double tfsub = tfmult/2;
Palette palette = getPalette(name);
BytePalette palette = getPalette(name);
for (int x = 0; x < d; x++) {
double xc = (tfmult * x)/(d - 1) - tfsub;
for (int y = 0; y < d; y++) {
@ -262,7 +239,7 @@ public class World {
if ((iterations >= itMin) && (iterations < itMax)) {
// place block if cutoff reached in itMin -> itMax range
if ((iterations >= itMin) && (iterations < itMax)) {
String id = palette.get(iterations - itMin);
byte id = palette.get(iterations - itMin);
//System.out.println("Placing block "+id+" at ("+(xOffset + x)+","+(yOffset + y)+","+(zOffset + z)+")");
setBlock(id, xOffset + x, yOffset + y, zOffset + z);
}
@ -315,7 +292,7 @@ public class World {
}
// greek cross fractal
public void generateCross(String id, int d0, int xOffset, int yOffset, int zOffset, int scale, int mode) {
public void generateCross(byte id, int d0, int xOffset, int yOffset, int zOffset, int scale, int mode) {
int d1 = (d0 - 1)/2;
if ((Math.floor(d1) - d1 != 0) || (d1 < scale))
return;
@ -353,7 +330,7 @@ public class World {
}
// octahedron fractal
public void generateOctahedron(String id, int d0, int xOffset, int yOffset, int zOffset, int oscale) {
public void generateOctahedron(byte id, int d0, int xOffset, int yOffset, int zOffset, int oscale) {
int d1 = (d0 - 1)/2;
int d2 = (d1 - 1)/2;
// create octahedron when minimum scale reached
@ -385,62 +362,86 @@ public class World {
// palettes and block types
public void addColorBlockTypes() {
library.addType(new BlockType(null, "red", "1", Color.RED));
library.addType(new BlockType(null, "green", "2", Color.GREEN));
library.addType(new BlockType(null, "blue", "3", Color.BLUE));
library.addType(new BlockType(null, "yellow", "4", Color.YELLOW));
library.addType(new BlockType(null, "orange", "5", Color.ORANGE));
library.addType(new BlockType(null, "magenta", "6", Color.MAGENTA));
library.addType(new BlockType(null, "pink", "7", Color.PINK));
library.addType(new BlockType(null, "cyan", "8", Color.CYAN));
library.addType(new BlockType(null, "black", "9", Color.BLACK));
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)));
library.addType(new BlockType(null, "red", 1, Color.RED));
library.addType(new BlockType(null, "green", 2, Color.GREEN));
library.addType(new BlockType(null, "blue", 3, Color.BLUE));
library.addType(new BlockType(null, "yellow", 4, Color.YELLOW));
library.addType(new BlockType(null, "orange", 5, Color.ORANGE));
library.addType(new BlockType(null, "magenta", 6, Color.MAGENTA));
library.addType(new BlockType(null, "pink", 7, Color.PINK));
library.addType(new BlockType(null, "cyan", 8, Color.CYAN));
library.addType(new BlockType(null, "black", 9, Color.BLACK));
library.addType(new BlockType(null, "white", 10, Color.WHITE));
library.addType(new BlockType(null, "gray", 11, Color.GRAY));
library.addType(new BlockType(null, "darkGray", 12, Color.DARK_GRAY));
library.addType(new BlockType(null, "gloriousBlue", 13, new Color(7, 8, 114)));
library.addType(new BlockType(null, "watermelon", 14, new Color(247, 70, 122)));
library.addType(new BlockType(null, "gloriousViolet", 15, new Color(73, 8, 162)));
library.addType(new BlockType(null, "darkBlue", 16, new Color(14, 0, 42)));
library.addType(new BlockType(null, "brownPurple", 17, new Color(40, 0, 22)));
library.addType(new BlockType(null, "turquoise", 18, new Color(85, 135, 136)));
library.addType(new BlockType(null, "lightTurquoise", 19, new Color(136, 181, 178)));
library.addType(new BlockType(null, "klineWhite", 20, new Color(224, 225, 219)));
library.addType(new BlockType(null, "salmon", 21, new Color(255, 179, 158)));
library.addType(new BlockType(null, "rust", 22, new Color(183, 63, 38)));
library.addType(new BlockType(null, "strongCyan", 23, new Color(105, 210, 231)));
library.addType(new BlockType(null, "muddledCyan", 24, new Color(167, 219, 216)));
library.addType(new BlockType(null, "stormyWhite", 25, new Color(224, 228, 204)));
library.addType(new BlockType(null, "goldfish", 26, new Color(243, 134, 48)));
library.addType(new BlockType(null, "strongOrange", 27, new Color(250, 105, 0)));
library.addType(new BlockType(null, "lime", 28, new Color(207, 240, 158)));
library.addType(new BlockType(null, "greenFoam", 29, new Color(168, 219, 168)));
library.addType(new BlockType(null, "seaGreen", 30, new Color(121, 189, 154)));
library.addType(new BlockType(null, "darkTurquoise", 31, new Color(59, 134, 134)));
library.addType(new BlockType(null, "royalBlue", 32, 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"}));
palettes.add(new BytePalette("test", new byte[] { 10, 11, 12, 9, 1, 5, 4, 2, 8, 3, 6, 7 }));
palettes.add(new BytePalette("blackNblue", new byte[] { 10, 11, 12, 9, 3, 8, 10, 11, 12, 3, 8, 10 }));
palettes.add(new BytePalette("glory", new byte[] { 13, 14, 15, 16, 17, 13, 14, 15, 16, 17 }));
palettes.add(new BytePalette("boutique", new byte[] { 18, 19, 20, 21, 22, 18, 19, 20, 21, 22 }));
palettes.add(new BytePalette("goldfish", new byte[] { 23, 24, 25, 26, 27, 23, 24, 25, 26, 27 }));
palettes.add(new BytePalette("dreamy", new byte[] { 28, 29, 30, 31, 32, 28, 29, 30, 31, 32 }));
}
public Palette getPalette(String name) {
public BytePalette getPalette(String name) {
for (int i = 0; i < palettes.size(); i++) {
if (palettes.get(i).getName().equals(name))
return palettes.get(i);
}
return null;
}
// load/save world
public void load(String filename) {
try {
FileInputStream fis = new FileInputStream(filename);
GZIPInputStream gs = new GZIPInputStream(fis);
ObjectInputStream in = new ObjectInputStream(gs);
chunks = (Chunk[][][]) in.readObject();
in.close();
fis.close();
} catch (Exception e) {
System.out.println(e);
}
}
public void save(String filename) {
try {
FileOutputStream fos = new FileOutputStream(filename);
GZIPOutputStream gz = new GZIPOutputStream(fos);
ObjectOutputStream out = new ObjectOutputStream(gz);
out.writeObject(chunks);
out.flush();
out.close();
fos.close();
} catch (IOException e) {
System.out.println(e);
}
}
public byte getByteFromName(String string) {
return library.getType(string).getId();
}
}

View File

@ -0,0 +1,37 @@
package voxelengine;
import java.applet.Applet;
public class WorldTester extends Applet {
private static final long serialVersionUID = 1L;
private static final int worldSize = 64;
private static final int fractalSize = worldSize * 14;
public void init() {
// creating world
System.out.println("Creating world size: "+worldSize);
Long time = System.currentTimeMillis();
World world = new World(worldSize);
time = ((System.currentTimeMillis() - time)/1000);
System.out.println("Time: "+time+"s \n");
// initializing world data
world.addColorBlockTypes();
world.addPalettes();
// generating mandelbox
System.out.println("Generating mandelbox...");
int offset = (worldSize * 16 - fractalSize)/2;
time = System.currentTimeMillis();
world.generateMandelbox("test", fractalSize, 2, 5, 4, 12, 4, offset, offset, offset);
time = ((System.currentTimeMillis() - time)/1000);
System.out.println("Time: "+time+"s \n");
// saving world
System.out.println("Saving world...");
time = System.currentTimeMillis();
world.save("test.wrl");
time = ((System.currentTimeMillis() - time)/1000);
System.out.println("Time: "+time+"s \n");
}
}