adding java thing

yeah, i made a voxel engine, it's terrible, enjoy!
master
matortheeternal 2014-05-07 14:40:09 -07:00
parent 89901f63f8
commit ae88b451e5
34 changed files with 1390 additions and 0 deletions

6
VoxelEngine/.classpath Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="output" path="bin"/>
</classpath>

17
VoxelEngine/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>VoxelEngine</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
VoxelEngine/bin/game.au Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
/* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/
/* DO NOT EDIT */
grant {
permission java.security.AllPermission;
};

BIN
VoxelEngine/bin/menu.au Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,35 @@
package store;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Audioapp extends Applet implements ActionListener {
private AudioClip sound;
private Button playSound, loopSound, stopSound;
public void init() {
System.out.println(getCodeBase());
sound = getAudioClip(getCodeBase(), "menu.au");
playSound = new Button("Play");
playSound.addActionListener(this);
add(playSound);
loopSound = new Button("Loop");
loopSound.addActionListener(this);
add(loopSound);
stopSound = new Button("Stop");
stopSound.addActionListener(this);
add(stopSound);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == playSound)
sound.play();
else if (e.getSource() == loopSound)
sound.loop();
else if (e.getSource() == stopSound)
sound.stop();
}
}

View File

@ -0,0 +1,24 @@
package store;
import java.awt.*;
import java.applet.*;
import java.net.*;
public class SimpleImageLoad extends Applet {
Image img;
URL coach;
public void init() {
try {
coach = new URL("http://www.cs.sbcc.cc.ca.us/~rhd/");
} catch (MalformedURLException e) {
showStatus("Exception: " + e.toString());
}
img = getImage(coach, "coach2c.gif");
}
public void paint(Graphics g) {
g.drawImage(img, 0, 0, this);
}
}

View File

@ -0,0 +1,16 @@
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

@ -0,0 +1,20 @@
package voxelengine;
import java.util.ArrayList;
public class BlockLibrary {
private ArrayList<BlockType> library = new ArrayList<BlockType>();
// methods
public void addType(BlockType type) {
library.add(type);
}
public BlockType getType(String id) {
for (int i = 0; i < library.size(); i++)
if ((library.get(i).getId().equals(id)) || (library.get(i).getName().equals(id)))
return library.get(i);
// if not found, return null
return null;
}
}

View File

@ -0,0 +1,34 @@
package voxelengine;
import java.awt.Color;
import java.awt.Image;
public class BlockType {
private Image texture;
private String name;
private String id;
private Color color;
// constructor
public BlockType(Image texture, String name, String id, Color color) {
super();
this.texture = texture;
this.name = name;
this.id = id;
this.color = color;
}
// getters
public Image getTexture() {
return texture;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public Color getColor() {
return color;
}
}

View File

@ -0,0 +1,23 @@
package voxelengine;
public class Camera {
public double x;
public double y;
public double z;
public double rotX;
public double rotY;
public double rotZ;
public double fov;
// constructor
public Camera(double x, double y, double z, double rotY, double rotZ, double rotX, double fov) {
super();
this.x = x;
this.y = y;
this.z = z;
this.rotX = rotX;
this.rotY = rotY;
this.rotZ = rotZ;
this.fov = fov;
}
}

View File

@ -0,0 +1,62 @@
package voxelengine;
public class Chunk {
private static int sz = 16;
private Block[][][] blocks = new Block[sz][sz][sz];
// methods
public void setBlock(BlockType type, int x, int y, int z) {
blocks[x][y][z] = new Block(type);
}
public Block 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)
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

@ -0,0 +1,23 @@
package voxelengine;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Keyboard implements KeyListener {
private boolean[] keys = new boolean[65536];
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
public boolean isKeyDown(int key) {
return keys[key];
}
}

View File

@ -0,0 +1,303 @@
package voxelengine;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
public class Menu extends Applet implements ActionListener, ItemListener {
private Button generateWorld, settings, quit, ok, back, generate;
private TextField size, worldSize, minIt, maxIt, power, zoom, cutoff;
private Label sizeL, colorL, worldSizeL, minItL, maxItL, powerL, zoomL, resL, pixL, castL, cutoffL;
private Choice choice, color;
private AudioClip sound;
private Image background;
private Panel pnl;
public void init() {
this.setSize(784, 562);
background = getImage(getCodeBase(), "background.jpg");
sound = getAudioClip(getCodeBase(), "menu.au");
sound.loop();
mainMenu();
}
public void paint(Graphics g) {
g.drawImage(background, 0, 0, this);
}
@Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == generateWorld) {
clearMenu();
generationMenu();
this.setSize(785, 562);
this.setSize(784, 562);
} else if (src == settings) {
clearMenu();
settingsMenu();
this.setSize(785, 562);
this.setSize(784, 562);
} else if (src == quit) {
clearMenu();
System.exit(0);
this.setSize(785, 562);
this.setSize(784, 562);
} else if (src == back) {
clearMenu();
mainMenu();
this.setSize(785, 562);
this.setSize(784, 562);
} else if (src == generate) {
sound.stop();
clearMenu();
this.setVisible(false);
sound = getAudioClip(getCodeBase(), "game.au");
sound.loop();
SwingInterface.main(new String[]{worldSize.getText(), choice.getSelectedItem(), color.getSelectedItem(), size.getText(), minIt.getText(), maxIt.getText(), power.getText(), zoom.getText(), cutoff.getText()});
}
}
public void clearMenu() {
this.removeAll();
repaint();
}
public void clearPanel() {
pnl.removeAll();
repaint();
}
public void generationMenu() {
pnl = new Panel();
pnl.setMaximumSize(new Dimension(350, 200));
pnl.setPreferredSize(new Dimension(350, 200));
pnl.setBackground(Color.BLACK);
worldSizeL = new Label("World size: ");
worldSizeL.setForeground(Color.LIGHT_GRAY);
worldSizeL.setBackground(Color.BLACK);
worldSizeL.setMaximumSize(new Dimension(70, 20));
worldSize = new TextField("20");
worldSize.setMaximumSize(new Dimension(50, 20));
choice = new Choice();
choice.addItem("Menger Sponge");
choice.addItem("Mandelbulb");
choice.addItem("Mandelbox");
choice.setMaximumSize(new Dimension(140, 40));
choice.setForeground(Color.LIGHT_GRAY);
choice.setBackground(Color.BLACK);
generate = new Button("Generate!");
generate.setMaximumSize(new Dimension(140, 40));
generate.setForeground(Color.LIGHT_GRAY);
generate.setBackground(Color.BLACK);
back = new Button("Back");
back.setMaximumSize(new Dimension(140, 40));
back.setForeground(Color.LIGHT_GRAY);
back.setBackground(Color.BLACK);
generate.addActionListener(this);
back.addActionListener(this);
choice.addItemListener(this);
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
this.add(Box.createRigidArea(new Dimension(0,30)));
add(worldSizeL);
add(worldSize);
this.add(Box.createRigidArea(new Dimension(0,20)));
add(choice);
this.add(Box.createRigidArea(new Dimension(0,30)));
add(pnl);
this.add(Box.createRigidArea(new Dimension(0,50)));
add(generate);
this.add(Box.createRigidArea(new Dimension(0,30)));
add(back);
colorL = new Label("Color: ");
colorL.setForeground(Color.LIGHT_GRAY);
colorL.setBackground(Color.BLACK);
colorL.setPreferredSize(new Dimension(50, 20));
color = new Choice();
color.setPreferredSize(new Dimension(80, 20));
sizeL = new Label("Size: ");
sizeL.setForeground(Color.LIGHT_GRAY);
sizeL.setBackground(Color.BLACK);
sizeL.setPreferredSize(new Dimension(40, 20));
size = new TextField("81");
size.setPreferredSize(new Dimension(50, 20));
minItL = new Label("Minimum Iterations: ");
minItL.setForeground(Color.LIGHT_GRAY);
minItL.setBackground(Color.BLACK);
minItL.setPreferredSize(new Dimension(120, 20));
minIt = new TextField("4");
minIt.setPreferredSize(new Dimension(100, 20));
maxItL = new Label("Maximum Iterations: ");
maxItL.setForeground(Color.LIGHT_GRAY);
maxItL.setBackground(Color.BLACK);
maxItL.setPreferredSize(new Dimension(120, 20));
maxIt = new TextField("16");
maxIt.setPreferredSize(new Dimension(100, 20));
powerL = new Label("Power: ");
powerL.setForeground(Color.LIGHT_GRAY);
powerL.setBackground(Color.BLACK);
powerL.setPreferredSize(new Dimension(50, 20));
power = new TextField("8");
power.setPreferredSize(new Dimension(50, 20));
zoomL = new Label("Zoom: ");
zoomL.setForeground(Color.LIGHT_GRAY);
zoomL.setBackground(Color.BLACK);
zoomL.setPreferredSize(new Dimension(50, 20));
zoom = new TextField("4");
zoom.setPreferredSize(new Dimension(50, 20));
cutoffL = new Label("Cutoff: ");
cutoffL.setForeground(Color.LIGHT_GRAY);
cutoffL.setBackground(Color.BLACK);
cutoffL.setPreferredSize(new Dimension(50, 20));
cutoff = new TextField("5");
cutoff.setPreferredSize(new Dimension(50, 20));
pnl.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
pnl.add(colorL, BorderLayout.CENTER);
pnl.add(color, BorderLayout.CENTER);
pnl.add(Box.createRigidArea(new Dimension(10,0)));
pnl.add(sizeL, BorderLayout.CENTER);
pnl.add(size, BorderLayout.CENTER);
pnl.add(Box.createRigidArea(new Dimension(50,0)));
pnl.add(powerL, BorderLayout.CENTER);
pnl.add(power, BorderLayout.CENTER);
pnl.add(Box.createRigidArea(new Dimension(50,0)));
pnl.add(zoomL, BorderLayout.CENTER);
pnl.add(zoom, BorderLayout.CENTER);
pnl.add(minItL, BorderLayout.CENTER);
pnl.add(minIt, BorderLayout.CENTER);
pnl.add(Box.createRigidArea(new Dimension(80,0)));
pnl.add(maxItL, BorderLayout.CENTER);
pnl.add(maxIt, BorderLayout.CENTER);
pnl.add(Box.createRigidArea(new Dimension(120,0)));
pnl.add(cutoffL, BorderLayout.CENTER);
pnl.add(cutoff, BorderLayout.CENTER);
mengerMenu();
}
public void mengerMenu() {
colorL.setText("Color: ");
color.removeAll();
color.addItem("red");
color.addItem("green");
color.addItem("blue");
color.addItem("yellow");
color.addItem("orange");
color.addItem("magenta");
color.addItem("pink");
color.addItem("cyan");
color.addItem("black");
color.addItem("white");
color.addItem("gray");
color.addItem("darkGray");
power.setEnabled(false);
zoom.setEnabled(false);
minIt.setEnabled(false);
maxIt.setEnabled(false);
cutoff.setEnabled(false);
}
public void bulbMenu() {
colorL.setText("Palette: ");
color.removeAll();
color.addItem("test");
color.addItem("blackNblue");
powerL.setText("Power: ");
power.setEnabled(true);
zoom.setEnabled(false);
minIt.setEnabled(true);
maxIt.setEnabled(true);
cutoff.setEnabled(true);
cutoff.setText("1024");
}
public void boxMenu() {
colorL.setText("Palette: ");
color.removeAll();
color.addItem("test");
color.addItem("blackNblue");
powerL.setText("Scale: ");
power.setEnabled(true);
zoom.setEnabled(true);
minIt.setEnabled(true);
maxIt.setEnabled(true);
cutoff.setEnabled(true);
cutoff.setText("5");
}
public void settingsMenu() {
back = new Button("Back");
back.setMaximumSize(new Dimension(140, 40));
back.setForeground(Color.LIGHT_GRAY);
back.setBackground(Color.BLACK);
back.addActionListener(this);
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
this.add(Box.createRigidArea(new Dimension(0,250)));
add(back, BorderLayout.CENTER);
}
public void mainMenu() {
generateWorld = new Button("Generate World");
generateWorld.setMaximumSize(new Dimension(140, 40));
generateWorld.setForeground(Color.LIGHT_GRAY);
generateWorld.setBackground(Color.BLACK);
settings = new Button("Settings");
settings.setMaximumSize(new Dimension(140, 40));
settings.setForeground(Color.LIGHT_GRAY);
settings.setBackground(Color.BLACK);
quit = new Button("Quit");
quit.setMaximumSize(new Dimension(140, 40));
quit.setForeground(Color.LIGHT_GRAY);
quit.setBackground(Color.BLACK);
generateWorld.addActionListener(this);
settings.addActionListener(this);
quit.addActionListener(this);
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
this.add(Box.createRigidArea(new Dimension(0,170)));
add(generateWorld, BorderLayout.CENTER);
this.add(Box.createRigidArea(new Dimension(0,50)));
add(settings, BorderLayout.CENTER);
this.add(Box.createRigidArea(new Dimension(0,50)));
add(quit, BorderLayout.CENTER);
}
@Override
public void itemStateChanged(ItemEvent arg0) {
if (arg0.getSource() == choice) {
String sel = choice.getSelectedItem();
if (sel.equals("Menger Sponge")) {
mengerMenu();
} else if (sel.equals("Mandelbulb")) {
bulbMenu();
} else if (sel.equals("Mandelbox")){
boxMenu();
}
}
}
}

View File

@ -0,0 +1,25 @@
package voxelengine;
public class Palette {
private String name;
private String[] palette;
// constructor
public Palette(String name, String[] palette) {
super();
this.name = name;
this.palette = palette;
}
// methods
public String get(int index) {
return palette[index];
}
public String getName() {
return name;
}
public void printContents() {
for (int i = 0; i < palette.length; i++)
System.out.println(get(i));
}
}

View File

@ -0,0 +1,266 @@
package voxelengine;
import java.awt.Color;
import java.awt.image.MemoryImageSource;
public class Renderer {
private World world;
private Color SkyboxColor = Color.BLACK;
private double falloff = 8.0;
private double rate = 0.85;
private int renderDistance = 8;
public Camera camera;
// constructor
public Renderer(World world, Camera camera) {
super();
this.world = world;
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];
// 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] = raycastC(px, py, width, height, castScale);
else {
int val = raycastC(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 raycastC(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;
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;
while (inBoundsC(x1, y1, z1)) {
// chunk processing
cx1 = (int) (x1/16.0);
cy1 = (int) (y1/16.0);
cz1 = (int) (z1/16.0);
if (world.getIsEmpty(cx1, cy1, cz1)) {
do {
x1 += xs;
y1 += ys;
z1 += zs;
cx2 = (int) (x1/16.0);
cy2 = (int) (y1/16.0);
cz2 = (int) (z1/16.0);
} while (cx1 == cx2 && cy1 == cy2 && cz1 == cz2);
continue;
}
// block processing
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();
}
private boolean inBoundsC(double x, double y, double z) {
int b = world.getSize() * 16;
int dx = ((int) Math.abs(camera.x - x)) / 16;
int dy = ((int) Math.abs(camera.y - y)) / 16;
int dz = ((int) Math.abs(camera.z - z)) / 16;
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) {
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] = raycastD(px, py, width, height, castScale);
else {
int val = raycastD(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 raycastD(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;
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 x1 = camera.x;
double y1 = camera.y;
double z1 = camera.z;
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;
while (inBoundsC(x1, y1, z1)) {
// chunk processing
cx1 = (int) (x1/16.0);
cy1 = (int) (y1/16.0);
cz1 = (int) (z1/16.0);
if (world.getIsEmpty(cx1, cy1, cz1)) {
do {
x1 += xs;
y1 += ys;
z1 += zs;
cx2 = (int) (x1/16.0);
cy2 = (int) (y1/16.0);
cz2 = (int) (z1/16.0);
} while (cx1 == cx2 && cy1 == cy2 && cz1 == cz2);
continue;
}
// block processing
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();
}
private Color CalculateColor(Color c, double x1, double x2, double y1, double y2, double z1, double z2) {
double distance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + Math.pow(z1 - z2, 2));
double lightIntensity = falloff/Math.pow(distance, rate);
// calculate color components
int red = (int) (c.getRed() * lightIntensity);
red = (red > 255) ? 255 : red;
int green = (int) (c.getGreen() * lightIntensity);
green = (green > 255) ? 255 : green;
int blue = (int) (c.getBlue() * lightIntensity);
blue = (blue > 255) ? 255 : blue;
// return calculated color
return new Color(red, green, blue);
}
}

View File

@ -0,0 +1,165 @@
package voxelengine;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
@SuppressWarnings("serial")
public class SwingInterface extends JPanel {
private static Keyboard keyboard = new Keyboard();
private Image src = null;
private World world;
private Renderer renderer;
private Camera camera = new Camera(0, 0, 0, 0, 0, 0, Math.PI/2);
private static String[] arguments;
private static final int X_SIZE = 800;
private static final int Y_SIZE = 600;
private static int pixelScale = 4;
private static int castScale = 4;
public SwingInterface() {
new Worker().execute();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (src != null)
g.drawImage(src, 0, 0, this);
}
private class Worker extends SwingWorker<Void, Image> {
protected void process(List<Image> chunks) {
for (Image bufferedImage : chunks) {
src = bufferedImage;
repaint();
}
}
protected Void doInBackground() throws Exception {
set_up();
int frames = 0;
long time = System.currentTimeMillis();
while (true) {
frames++;
if (frames == 30) {
double t = System.currentTimeMillis() - time;
double fps = 30 / (t / 1000);
System.out.println(((double) Math.round(fps * 100)/100) + "fps");
frames = 0;
time = System.currentTimeMillis();
}
process_input();
Image img = createImage(renderer.renderC(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);
g2.dispose();
publish(buffer);
}
}
private void set_up() {
int worldSize = Integer.parseInt(arguments[0]);
int offset = (worldSize * 16 - Integer.parseInt(arguments[3]))/2;
world = new World(worldSize);
world.addColorBlockTypes();
world.addPalettes();
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);
} 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]));
} else if (arguments[1].equals("Mandelbox")) {
System.out.println("Generating Mandelbox...");
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);
}
System.out.println((Math.round((System.currentTimeMillis() - time)/10)/100.0)+" seconds spent generating world.");
time = System.currentTimeMillis();
world.updateIsEmptyAll();
System.out.println((Math.round((System.currentTimeMillis() - time)/10)/100.0)+" seconds spent updating isEmpty booleans.");
camera.x = (double) (offset - 2.0);
camera.y = (double) (offset - 2.0);
camera.z = (double) (offset - 2.0);
camera.rotY = 0;
camera.rotX = Math.PI / 2;
renderer = new Renderer(world, camera);
System.out.println("World set up. Now rendering...");
}
private void process_input() {
if (keyboard.isKeyDown('A')) {
camera.x += Math.cos(camera.rotY - Math.PI / 2);
camera.y += Math.sin(camera.rotY - Math.PI / 2);
}
if (keyboard.isKeyDown('D')) {
camera.x += Math.cos(camera.rotY + Math.PI / 2);
camera.y += Math.sin(camera.rotY + Math.PI / 2);
}
if (keyboard.isKeyDown('W')) {
camera.x += Math.cos(camera.rotY);
camera.y += Math.sin(camera.rotY);
}
if (keyboard.isKeyDown('S')) {
camera.x += Math.cos(camera.rotY + Math.PI);
camera.y += Math.sin(camera.rotY + Math.PI);
}
if (keyboard.isKeyDown('Q')) {
camera.z -= 1;
}
if (keyboard.isKeyDown('E')) {
camera.z += 1;
}
if (keyboard.isKeyDown('J')) {
camera.rotY -= Math.PI / 32;
}
if (keyboard.isKeyDown('L')) {
camera.rotY += Math.PI / 32;
}
if (keyboard.isKeyDown('I')) {
camera.rotX -= Math.PI / 32;
}
if (keyboard.isKeyDown('K')) {
camera.rotX += Math.PI / 32;
}
if (keyboard.isKeyDown('T')) {
pixelScale++;
}
if (keyboard.isKeyDown('Y')) {
pixelScale--;
}
if (keyboard.isKeyDown('G')) {
castScale++;
}
if (keyboard.isKeyDown('H')) {
castScale--;
}
camera.rotY = camera.rotY % (Math.PI * 2);
camera.rotX = Math.max(Math.min(camera.rotX, Math.PI), 0);
pixelScale = Math.max(Math.min(pixelScale, 10), 1);
castScale = Math.max(Math.min(castScale, 50), 1);
}
}
public static void main(String[] args) {
arguments = args;
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.addKeyListener(keyboard);
jf.getContentPane().add(new SwingInterface(), BorderLayout.CENTER);
jf.setSize(X_SIZE, Y_SIZE);
jf.setVisible(true);
}
}

View File

@ -0,0 +1,353 @@
package voxelengine;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Random;
public class World {
private int size;
private Chunk[][][] chunks;
private boolean[][][] isEmpty;
private BlockLibrary library = new BlockLibrary();
private ArrayList<Palette> palettes = new ArrayList<Palette>();
// constructor
public World(int size) {
super();
this.size = size;
this.chunks = new Chunk[size][size][size];
this.isEmpty = new boolean[size][size][size];
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for (int z = 0; z < size; z++) {
this.chunks[x][y][z] = new Chunk();
this.isEmpty[x][y][z] = false;
}
}
// methods
public int getSize() {
return size;
}
// chunk/block methods
public Chunk getChunk(int x, int y, int z) {
if ((x < size && x >= 0) && (y < size && y >= 0) && (z < size && z >= 0))
return chunks[x][y][z];
else
return null;
}
public Block getBlock(int x, int y, int z) {
int xChunk = x/16;
int yChunk = y/16;
int zChunk = z/16;
Chunk chunk = getChunk(xChunk, yChunk, zChunk);
if (chunk != null)
return chunk.getBlock(x % 16, y % 16, z % 16);
else
return null;
}
public Block 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) {
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);
}
public void setBlock(String id, double x, double y, double z) {
int xi = (int) x;
int yi = (int) y;
int zi = (int) z;
setBlock(id, xi, yi, zi);
}
// isEmpty methods
public boolean getIsEmpty(int x, int y, int z) {
return isEmpty[x][y][z];
}
public void updateIsEmpty(int x, int y, int z) {
Chunk chunk = getChunk(x, y, z);
isEmpty[x][y][z] = chunk.checkIfEmpty();
}
public void updateIsEmptyAll() {
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
for (int z = 0; z < size; z++)
isEmpty[x][y][z] = getChunk(x,y,z).checkIfEmpty();
}
// block type methods
public void addType(BlockType type) {
library.addType(type);
}
public BlockType getType(String id) {
return library.getType(id);
}
// world generation methods
public void generateMengerSponge(String id, int d0, int xOffset, int yOffset, int zOffset) {
// place block and return if dimension = 1
if (d0 == 1) {
setBlock(id, xOffset, yOffset, zOffset);
return;
}
// 1/3 of dimension
int d1 = d0/3;
// recursion loop
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
if ((y == 1) && (x == 1))
continue;
for (int z = 0; z < 3; z++) {
if (((y == 1) && (z == 1)) || ((x == 1) && (z == 1)))
continue;
// recursion
if (d0 > 3)
generateMengerSponge(id, d1, x*d1 + xOffset, y*d1 + yOffset, z*d1 + zOffset);
else {
setBlock(id, x + xOffset, y + yOffset, z + zOffset);
}
}
}
}
}
public void generateBox(String 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);
setBlock(id, x + xOffset, y + yOffset, (d0 - 1) + zOffset);
}
}
for (int y = 0; y < d0; y++) {
for (int z = 0; z < d0; z++) {
setBlock(id, xOffset, y + yOffset, z + zOffset);
setBlock(id, (d0 - 1) + xOffset, y + yOffset, z + zOffset);
}
}
for (int x = 0; x < d0; x++) {
for (int z = 0; z < d0; z++) {
setBlock(id, x + xOffset, yOffset, z + zOffset);
setBlock(id, x + xOffset, (d0 - 1) + yOffset, z + zOffset);
}
}
}
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);
//palette.printContents();
for (int x = 0; x < d; x++) {
double xc = tf(x, d);
for (int y = 0; y < d; y++) {
double yc = tf(y, d);
for (int z = 0; z < d; z++) {
double zc = tf(z, d);
int iterations = -1;
double[] C = new double[]{xc, yc, zc};
double[] Z = new double[]{0, 0, 0};
// iterate over vectors
while ((mag(Z) <= cutoff) && (iterations < itMax)) {
Z = add(formula(Z, power), C);
iterations++;
}
// place block if cutoff reached in itMin -> itMax range
if ((iterations >= itMin) && (iterations < itMax)) {
String 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);
}
}
}
}
}
private double tf(int v, int d) {
return (2.0 * v)/((double) d) - 1.0;
}
private double mag(double[] vec) {
return Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
}
private double[] add(double[] vec1, double[] vec2) {
return new double[]{vec1[0] + vec2[0], vec1[1] + vec2[1], vec1[2] + vec2[2]};
}
// mandelbulb vector growth formula
// if current vector magnitude > 1 and t is not too close to a multiple of (pi/2)
// this will give a vector of greater magnitude than the vector put in
// n, which is param, is the rate at which vector magnitude grows.
private double[] formula(double[] vec, double n) {
double t = theta(vec);
double p = phi(vec);
double k = Math.pow(mag(vec), n);
return new double[] {
k*Math.sin(n*t)*Math.cos(n*p),
k*Math.sin(n*t)*Math.sin(n*p),
k*Math.cos(n*t)};
}
// theta vector value (arccos)
private double theta(double[] vec) {
return (Math.acos(vec[2]/(mag(vec) + 0.000000001)));
}
// phi vector value (arctan)
private double phi(double[] vec) {
return (Math.atan(vec[1]/(vec[0] + 0.000000001)));
}
// 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);
for (int x = 0; x < d; x++) {
double xc = (tfmult * x)/(d - 1) - tfsub;
for (int y = 0; y < d; y++) {
double yc = (tfmult * y)/(d - 1) - tfsub;
for (int z = 0; z < d; z++) {
double zc = (tfmult * z)/(d - 1) - tfsub;
int iterations = -1;
double[] C = new double[]{xc, yc, zc};
double[] Z = new double[]{0, 0, 0};
while ((mag(Z) < cutoff) && (iterations < itMax)) {
Z = add(mult(scale, boxformula(Z)), C);
iterations++;
}
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);
//System.out.println("Placing block "+id+" at ("+(xOffset + x)+","+(yOffset + y)+","+(zOffset + z)+")");
setBlock(id, xOffset + x, yOffset + y, zOffset + z);
}
}
}
}
}
}
// mandelbox vector growth formula
private double[] boxformula(double[] vec) {
double x = vec[0];
double y = vec[1];
double z = vec[2];
if (x > 1)
x = 2 - x;
else if (x < -1)
x = -2 - x;
if (y > 1)
y = 2 - y;
else if (y < -1)
y = -2 - y;
if (z > 1)
z = 2 - z;
else if (z < -1)
z = -2 - z;
double[] output = new double[]{x, y, z};
double m = mag(output);
if (m < 0.5)
output = mult(4, output);
else if (m < 1)
output = mult(1/(m*m), output);
return output;
}
// multiplies a constant and a vector together
private double[] mult(double c, double[] vec) {
double[] output = new double[]{
c * vec[0],
c * vec[1],
c * vec[2]};
return output;
}
// 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));
}
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"}));
}
public Palette 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) {
}
public void save(String filename) {
}
}