parent
89901f63f8
commit
ae88b451e5
|
@ -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>
|
|
@ -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>
|
|
@ -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 |
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
/* AUTOMATICALLY GENERATED ON Tue Apr 16 17:20:59 EDT 2002*/
|
||||
/* DO NOT EDIT */
|
||||
|
||||
grant {
|
||||
permission java.security.AllPermission;
|
||||
};
|
||||
|
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.
Binary file not shown.
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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))));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue