little general refactor

treemaps-chunkstates-spacefilling
EmaMaker 2022-08-23 20:25:00 +02:00
parent be8cb056d3
commit daf419ed40
8 changed files with 80 additions and 418 deletions

View File

@ -1,10 +1,8 @@
package com.emamaker.voxeltest.intervaltrees;
import com.emamaker.voxeltest.intervaltrees.data.IntervalMap;
import com.emamaker.voxeltest.intervaltrees.utils.Config;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFilling;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFillingCurve;
import com.emamaker.voxeltest.intervaltrees.world.WorldManager;
import com.emamaker.voxeltest.intervaltrees.world.blocks.Blocks;
import com.jme3.app.SimpleApplication;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
@ -35,7 +33,7 @@ public class Voxel extends SimpleApplication {
getCamera().lookAt(new Vector3f(Config.CHUNK_SIZE,Config.CHUNK_SIZE, Config.CHUNK_SIZE), Vector3f.UNIT_Y);
pos.set(this.getCamera().getLocation());
SpaceFilling.initLUT();
SpaceFillingCurve.initLUT();
worldManager.initWorld();
// worldManager.benchmark();
}

View File

@ -1,63 +0,0 @@
package com.emamaker.voxeltest.intervaltrees.data;
/* When visualizing as a 1D array, high indicates the last index with a valid position (es. if there are 10 values), the interval will be (0,9) */
public class Interval {
int low, high;
public Interval() {
set(0, 0);
}
public Interval(int low_, int high_) {
set(low_, high_);
}
public void set(int low_, int high_) {
this.low = low_;
this.high = high_;
}
public int getLow(){
return low;
}
public int getHigh(){
return high;
}
public boolean isValid() {
return this.low < this.high;
}
// return if is contained in another interval
public boolean contains(Interval i) {
return this.low <= i.low && i.high <= this.high;
}
// if contains another interval
public boolean isContainedBy(Interval i) {
return i.contains(this);
}
public boolean fullyLeftOf(Interval i) {
return this.high <= i.low;
}
public boolean fullyRightOf(Interval i) {
return this.low >= i.high;
}
public boolean partiallyContainsLeft(Interval i) {
return i.low < this.low && i.high >= this.low && i.high < this.high;
}
public boolean partiallyContainsRight(Interval i) {
return this.high >= i.low && this.low < i.low && this.high < i.high;
}
@Override
public String toString() {
return "[" + low + ", " + high + ")";
}
}

View File

@ -1,237 +0,0 @@
package com.emamaker.voxeltest.intervaltrees.data;
import java.util.ArrayList;
import java.util.Arrays;
public class IntervalTree<V> {
TreeNode root = null;
int size = 0;
public void insertValue(V value, Interval i) {
root = insertNode(root, new TreeNode(i, value, null, null));
// if (isEmpty()) {
// root = new TreeNode(i, value, null, null);
// size++;
// } else
// insertValue(root, value, i);
}
public TreeNode getRoot() {
return this.root;
}
// For what we're doing, when we add new values that (partially) overlap old
// ones, we can't have the old ones laying around, so intervals need to be
// readjusted accordingly
public TreeNode insertNode(TreeNode currentNode, TreeNode newNode) {
if (!newNode.interval.isValid()) return null;
if (currentNode == null) return newNode;
// System.out.println(currentNode.interval.toString() +", "+
// newNode.interval.toString());
if (newNode.interval.fullyLeftOf(currentNode.interval)) {
currentNode.setLeft(insertNode(currentNode.left, newNode));
return currentNode;
} else if (newNode.interval.fullyRightOf(currentNode.interval)) {
currentNode.setRight(insertNode(currentNode.right, newNode));
return currentNode;
} else if (newNode.interval.contains(currentNode.interval)) {
// check is they carry the same value
if (newNode.value.equals(currentNode.value)) {
currentNode.interval = newNode.interval;
} else {
TreeNode newLeftNode = new TreeNode(new Interval(newNode.interval.low, currentNode.interval.low), newNode.value, currentNode.left, null);
newNode.setInterval(currentNode.interval.high, newNode.interval.high);
newNode.setRight(currentNode.right);
// Important! otherwhise already existing nodes will node by
// replaced
currentNode.value = newNode.value;
currentNode.setLeft(newLeftNode);
currentNode.setRight(newNode);
}
constrainIntervals(currentNode, currentNode.interval);
return currentNode;
} else if (newNode.interval.isContainedBy(currentNode.interval)) {
if (newNode.value.equals(currentNode.value)) return currentNode;
if (currentNode.interval.low < newNode.interval.low)
newNode.setLeft(new TreeNode(new Interval(currentNode.interval.low, newNode.interval.low), currentNode.value, currentNode.left, null));
else newNode.setLeft(null);
if (newNode.interval.high < currentNode.interval.high)
newNode.setRight(new TreeNode(new Interval(newNode.interval.high, currentNode.interval.high), currentNode.value, null, currentNode.right));
else newNode.setRight(null);
return newNode;
} else if (newNode.interval.partiallyContainsLeft(currentNode.interval)) {
currentNode.setInterval(currentNode.interval.low, newNode.interval.low);
newNode.setLeft(currentNode);
constrainIntervals(currentNode, currentNode.interval);
return newNode;
} else if (newNode.interval.partiallyContainsRight(currentNode.interval)) {
currentNode.setInterval(newNode.interval.high, currentNode.interval.high);
newNode.setRight(currentNode);
constrainIntervals(currentNode, currentNode.interval);
return currentNode;
}
System.out.println("How did we get here?");
return null;
}
// Get the value from n to n+1
public V getSingleValue(int n) {
return getValues(new Interval(n, n + 1)).get(0);
}
public ArrayList<V> getValues(Interval interval) {
ArrayList<V> values = new ArrayList<>();
if (root != null && interval != null)
getValues(interval, root, values);
return values;
}
private void getValues(Interval interval, TreeNode start, ArrayList<V> results) {
System.out.println(interval.toString() + ", " + start.toString() + ", " + Arrays.toString(results.toArray()));
if (interval.fullyLeftOf(start.interval) && start.left != null)
getValues(interval, start.left, results);
else if (interval.fullyRightOf(start.interval) && start.right != null)
getValues(interval, start.right, results);
else if (interval.isContainedBy(start.interval))
results.add(start.value); // base case
else if (interval.contains(start.interval)) {
results.add(start.value);
Interval intLeft = new Interval(interval.low, start.interval.low);
Interval intRight = new Interval(interval.high, start.interval.high);
if (start.left != null && intLeft.isValid())
getValues(intLeft, start.left, results);
if (start.right != null && intRight.isValid())
getValues(intRight, start.right, results);
} else if (interval.partiallyContainsLeft(start.interval)) {
results.add(start.value);
Interval newInt = new Interval(start.interval.high, interval.high);
if (start.right != null && newInt.isValid())
getValues(newInt, start.right, results);
} else if (interval.partiallyContainsRight(start.interval)) {
results.add(start.value);
Interval newInt = new Interval(interval.low, start.interval.low);
if (start.left != null && newInt.isValid())
getValues(newInt, start.left, results);
}
}
public TreeNode constrainIntervals(TreeNode start, Interval i) {
if (start == null)
return null;
start.interval.high = Math.min(start.interval.high, i.high);
start.interval.low = Math.max(start.interval.low, i.low);
if (!start.interval.isValid())
return null;
if (start.left != null)
start.setLeft(constrainIntervals(start.left, new Interval(start.left.interval.low, start.interval.low)));
if (start.right != null)
start.setRight(
constrainIntervals(start.right, new Interval(start.interval.high, start.right.interval.high)));
return start;
}
public void print() {
System.out.println("================");
print(root, 0);
System.out.println("================");
}
private void print(TreeNode tree, int level) {
for (int i = 0; i < level; i++)
System.out.print("\t");
if (level != 0)
System.out.print("|");
for (int i = 0; i < level * 4; i++)
System.out.print("-");
if (tree == null)
System.out.println("NULL");
else {
System.out.println(tree.interval.toString() + ": " + tree.value);
print(tree.left, level + 1);
print(tree.right, level + 1);
}
}
boolean isEmpty() {
return size == 0;
}
public class TreeNode {
V value;
Interval interval;
TreeNode left, right;
public TreeNode(Interval interval_, V value_, TreeNode left_, TreeNode right_) {
this.setInterval(interval_);
this.setValue(value_);
this.setLeft(left_);
this.setRight(right_);
}
public String toString() {
return this.interval.toString() + ": " + this.value.toString();
}
public void setInterval(int low_, int high_) {
this.interval.set(low_, high_);
}
public void setInterval(Interval i) {
this.interval = i;
}
public Interval getInterval() {
return this.interval;
}
public void setValue(V value_) {
this.value = value_;
}
public V getValue() {
return this.value;
}
public void setLeft(TreeNode left_) {
this.left = left_;
}
public void setRight(TreeNode right_) {
this.right = right_;
}
public TreeNode getLeft() {
return this.left;
}
public TreeNode getRight() {
return this.right;
}
}
}

View File

@ -1,6 +1,6 @@
package com.emamaker.voxeltest.intervaltrees.utils;
public class SpaceFilling {
public class SpaceFillingCurve {
// http://and-what-happened.blogspot.com/2011/08/fast-2d-and-3d-hilbert-curves-and.html
public static int[][][] MORTON_XYZ_ENCODE;
public static short[][] MORTON_XYZ_DECODE;

View File

@ -1,16 +1,14 @@
package com.emamaker.voxeltest.intervaltrees.world;
import java.util.HashMap;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import com.emamaker.voxeltest.intervaltrees.Voxel;
import com.emamaker.voxeltest.intervaltrees.renderer.ChunkRenderer;
import com.emamaker.voxeltest.intervaltrees.world.chunk.ChunkGenerator;
import com.emamaker.voxeltest.intervaltrees.world.chunk.ChunkMesher;
import com.emamaker.voxeltest.intervaltrees.utils.Config;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFilling;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFillingCurve;
import com.emamaker.voxeltest.intervaltrees.utils.Utils;
import com.jme3.math.Vector3f;
import com.emamaker.voxeltest.intervaltrees.world.chunk.Chunk;
import com.jme3.scene.Node;
public class WorldManager {
@ -19,7 +17,8 @@ public class WorldManager {
public int camx, camy, camz;
ChunkRenderer chunkRenderer = new ChunkRenderer();
ChunkMesher chunkMesher = new ChunkMesher();
ChunkGenerator chunkGenerator = new ChunkGenerator();
Node worldNode = new Node();
@ -34,32 +33,30 @@ public class WorldManager {
int chunkX, chunkY, chunkZ;
int index;
public boolean generated = false, meshed = false;
public boolean generated = false, meshed = false, worldGenerated = false;
public void update() {
camx = (int) (game.pos.getX());
camy = (int) (game.pos.getY());
camz = (int) (game.pos.getZ());
// // clamp to "chunk" coordinates
// // The chunk with origin at x,y,z in chunk coords actually has the origin at
// clamp to "chunk" coordinates
// The chunk with origin at x,y,z in chunk coords actually has the origin at
// x*chunksize, y*chunksize, z*chunksize in world coords
chunkX = (int) (camx / Config.CHUNK_LENGTH);
chunkY = (int) (camy / Config.CHUNK_LENGTH);
chunkZ = (int) (camz / Config.CHUNK_LENGTH);
// System.out.println("camera at" + game.pos + new Vector3f(chunkX, chunkY,
// chunkZ));
for (int i = Math.max(0, chunkX - Config.RENDER_DISTANCE); i < chunkX + Config.RENDER_DISTANCE; i++) {
for (int j = Math.max(0, chunkY - Config.RENDER_DISTANCE); j < chunkY + Config.RENDER_DISTANCE; j++) {
// for (int j = Math.max(0,chunkY - Config.RENDER_DISTANCE); j < chunkY +
// Config.RENDER_DISTANCE; j++) {
for (int k = Math.max(0, chunkZ - Config.RENDER_DISTANCE); k < chunkZ + Config.RENDER_DISTANCE; k++) {
if(!Utils.withinDistance(chunkX, chunkY, chunkZ, i,j,k,Config.RENDER_DISTANCE)) continue;
index = SpaceFilling.Morton_3D_Encode_10bit((short)i, (short)j, (short)k);
if (!chunks.containsKey(index)) chunks.put(index, new Chunk(i,j,k));
index = SpaceFillingCurve.Morton_3D_Encode_10bit((short)i, (short)j, (short)k);
if (!chunks.containsKey(index)) {
chunks.put(index, new Chunk(i,j,k));
worldGenerated = false;
}
}
}
}
@ -68,20 +65,21 @@ public class WorldManager {
meshed = false;
for(Chunk c : chunks.values()){
if(!generated && !c.bgetState(Chunk.CHUNK_STATE_GENERATED)) {
c.arrayGenerateCorner();
chunkGenerator.arrayGenerateCorner(c);
c.setState(Chunk.CHUNK_STATE_GENERATED, true);
generated = true;
}
if(!meshed && c.bgetState(Chunk.CHUNK_STATE_GENERATED)&& !c.bgetState(Chunk.CHUNK_STATE_MESHED)) {
chunkRenderer.greedyMeshing(this, c);
chunkMesher.greedyMeshing(this, c);
c.setState(Chunk.CHUNK_STATE_MESHED, true);
meshed = true;
}
}
if(!generated && ! meshed) System.out.println("Finished world generation");
if(!generated && !meshed && !worldGenerated){
worldGenerated = true;
System.out.println("Finished world generation");
}
}
public void render(){
@ -90,18 +88,15 @@ public class WorldManager {
game.getRootNode().attachChild(c.chunkNode);
c.setState(Chunk.CHUNK_STATE_LOADED, true);
}
if(!Utils.withinDistance(chunkX, chunkY, chunkZ, (int)c.posx, (int)c.posy, (int)c.posz, Config.RENDER_DISTANCE)){
if(!Utils.withinDistance(chunkX, chunkY, chunkZ, c.posx, c.posy, c.posz, Config.RENDER_DISTANCE)){
c.chunkNode.removeFromParent();
chunks.remove(SpaceFilling.Morton_3D_Encode_10bit((short)c.posx, (short)c.posy, (short)c.posz));
chunks.remove(SpaceFillingCurve.Morton_3D_Encode_10bit((short)c.posx, (short)c.posy, (short)c.posz));
}
}
}
public boolean chunkInCameraLimits(Chunk c) {
int vx = (int) c.posx;
int vy = (int) c.posy;
int vz = (int) c.posz;
return vx >= Math.min(0, chunkX - Config.RENDER_DISTANCE ) && vx < Math.min(0, chunkX + Config.RENDER_DISTANCE) && vy >= chunkY - Config.RENDER_DISTANCE && vy < Math.min(0, chunkY + Config.RENDER_DISTANCE) && vz >= chunkZ - Config.RENDER_DISTANCE && vz < Math.min(0, chunkZ + Config.RENDER_DISTANCE);
return c.posx >= Math.min(0, chunkX - Config.RENDER_DISTANCE ) && c.posx < Math.min(0, chunkX + Config.RENDER_DISTANCE) && c.posy >= chunkY - Config.RENDER_DISTANCE && c.posy < Math.min(0, chunkY + Config.RENDER_DISTANCE) && c.posz >= chunkZ - Config.RENDER_DISTANCE && c.posz < Math.min(0, chunkZ + Config.RENDER_DISTANCE);
}
public void benchmark(){
@ -109,8 +104,8 @@ public class WorldManager {
for(int j = 0; j < Config.RENDER_DISTANCE*2; j++)
for(int k = 0; k < Config.RENDER_DISTANCE*2; k++){
Chunk c = new Chunk(i,j,k);
c.arrayGenerateCorner();
chunkRenderer.greedyMeshing(this, c);
chunkGenerator.arrayGenerateCorner(c);
chunkMesher.greedyMeshing(this, c);
game.getRootNode().attachChild(c.chunkNode);
}
}

View File

@ -1,11 +1,9 @@
package com.emamaker.voxeltest.intervaltrees.world;
package com.emamaker.voxeltest.intervaltrees.world.chunk;
import com.emamaker.voxeltest.intervaltrees.data.IntervalMap;
import com.emamaker.voxeltest.intervaltrees.utils.Config;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFilling;
import com.emamaker.voxeltest.intervaltrees.utils.Utils;
import com.emamaker.voxeltest.intervaltrees.world.blocks.Blocks;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
public class Chunk {
@ -19,6 +17,7 @@ public class Chunk {
public static byte CHUNK_STATE_GENERATED = 1;
public static byte CHUNK_STATE_MESHED = 2;
public static byte CHUNK_STATE_LOADED = 4;
public Chunk() {
this(0,0,0);
}
@ -30,9 +29,6 @@ public class Chunk {
chunkNode.setLocalTranslation(posx, posy, posz);
chunkNode.setLocalTranslation(chunkNode.getLocalTranslation().mult(Config.CHUNK_SIZE).mult(Config.VOXEL_SIZE));
// I still have to decided if this is necessary. With an empty tree this
// takes O(1)
//blocks.insertTerminator(Config.CHUNK_3DCOORD_MAX_INDEX);
blocks.insert(0, Config.CHUNK_3DCOORD_MAX_INDEX, Blocks.AIR);
}
@ -56,8 +52,7 @@ public class Chunk {
}
/*
* Set blocks. Interval to be intended in the same way as in interval tree
* (flatten 1d index of 3d coords)
* Set blocks. Interval to be intended in the same way as in interval maps
*/
public void setBlocks(Blocks block, int intLow, int intHigh) {
this.blocks.insert( Math.max(0,intLow), Math.min(Config.CHUNK_3DCOORD_MAX_INDEX+1, intHigh),block);
@ -67,68 +62,6 @@ public class Chunk {
return blocks.valueAtKey(Chunk.coord3DTo1D(x, y, z));
}
public void generatePlane() {
// blocks.print();
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.STONE, coord3DTo1D(0, 0, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 0, i));
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.DIRT, coord3DTo1D(0, 1, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 1, i));
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.GRASS, coord3DTo1D(0, 2, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 2, i));
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.STONE, coord3DTo1D(0, 3, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 3, i));
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.DIRT, coord3DTo1D(0, 4, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 4, i));
for (int i = 0; i < Config.CHUNK_SIZE; i++)
this.setBlocks(Blocks.GRASS, coord3DTo1D(0, 5, i), coord3DTo1D(Config.CHUNK_SIZE - 1, 5, i));
}
public void generateCube() {
this.setBlocks(Blocks.STONE, 0,
Config.CHUNK_3DCOORD_MAX_INDEX);
}
public void generateStair() {
for (int i = 0; i < Config.CHUNK_SIZE; i++) {
for (int j = 0; j < Config.CHUNK_SIZE; j++) {
this.setBlocks(j < Config.CHUNK_SIZE - i - 1 ? Blocks.STONE : Blocks.GRASS, coord3DTo1D(0, i, j),
coord3DTo1D(Config.CHUNK_SIZE - 1, i, j));
}
}
this.setBlocks(Blocks.DIRT, Chunk.coord3DTo1D(0, 0, 0), Chunk.coord3DTo1D(2, 0, 0));
this.setBlocks(Blocks.DIRT, Chunk.coord3DTo1D(1, 0, 2), Chunk.coord3DTo1D(2, 0, 2));
}
public void arrayGenerateCorner() {
Blocks[] array = new Blocks[Config.CHUNK_3DCOORD_MAX_INDEX + 1];
int dist, hilbert;
for (int i = 0; i < Config.CHUNK_SIZE; i++) {
for (int j = 0; j < Config.CHUNK_SIZE; j++) {
for (int k = 0; k < Config.CHUNK_SIZE; k++) {
// Distance from 0,0,0
dist = (int) Math.sqrt((i * i) + (j * j) + (k * k));
hilbert = SpaceFilling.HILBERT_XYZ_ENCODE[i][j][k];
if (dist <= (int) (Config.CHUNK_SIZE / 3))
array[hilbert] = Blocks.STONE;
else if (dist > (int) (Config.CHUNK_SIZE / 3) && dist <= (int) (2 * Config.CHUNK_SIZE / 3))
array[hilbert] = Blocks.DIRT;
else if (dist > (int) (2 * Config.CHUNK_SIZE / 3) && dist <= (int) (Config.CHUNK_SIZE))
array[hilbert] = Blocks.GRASS;
else
array[hilbert] = Blocks.AIR;
}
}
}
this.treeFrom1DArray(array);
}
public Blocks[] treeTo1DArray() {
// System.out.println(Config.CHUNK_3DCOORD_MAX_INDEX);
Blocks[] result = new Blocks[Config.CHUNK_3DCOORD_MAX_INDEX + 1];

View File

@ -0,0 +1,41 @@
package com.emamaker.voxeltest.intervaltrees.world.chunk;
import com.emamaker.voxeltest.intervaltrees.utils.Config;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFillingCurve;
import com.emamaker.voxeltest.intervaltrees.world.blocks.Blocks;
public class ChunkGenerator {
public void generateCube(Chunk c) {
c.setBlocks(Blocks.STONE, 0,
Config.CHUNK_3DCOORD_MAX_INDEX);
}
public void arrayGenerateCorner(Chunk c) {
Blocks[] array = new Blocks[Config.CHUNK_3DCOORD_MAX_INDEX + 1];
int dist, hilbert;
for (int i = 0; i < Config.CHUNK_SIZE; i++) {
for (int j = 0; j < Config.CHUNK_SIZE; j++) {
for (int k = 0; k < Config.CHUNK_SIZE; k++) {
// Distance from 0,0,0
dist = (int) Math.sqrt((i * i) + (j * j) + (k * k));
hilbert = SpaceFillingCurve.HILBERT_XYZ_ENCODE[i][j][k];
if (dist <= (int) (Config.CHUNK_SIZE / 3))
array[hilbert] = Blocks.STONE;
else if (dist > (int) (Config.CHUNK_SIZE / 3) && dist <= (int) (2 * Config.CHUNK_SIZE / 3))
array[hilbert] = Blocks.DIRT;
else if (dist > (int) (2 * Config.CHUNK_SIZE / 3) && dist <= (int) (Config.CHUNK_SIZE))
array[hilbert] = Blocks.GRASS;
else
array[hilbert] = Blocks.AIR;
}
}
}
c.treeFrom1DArray(array);
}
}

View File

@ -1,9 +1,7 @@
package com.emamaker.voxeltest.intervaltrees.renderer;
package com.emamaker.voxeltest.intervaltrees.world.chunk;
import com.emamaker.voxeltest.intervaltrees.utils.Config;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFilling;
import com.emamaker.voxeltest.intervaltrees.utils.Utils;
import com.emamaker.voxeltest.intervaltrees.world.Chunk;
import com.emamaker.voxeltest.intervaltrees.utils.SpaceFillingCurve;
import com.emamaker.voxeltest.intervaltrees.world.WorldManager;
import com.emamaker.voxeltest.intervaltrees.world.blocks.Blocks;
import com.jme3.material.Material;
@ -17,7 +15,7 @@ import com.jme3.util.BufferUtils;
import java.util.Arrays;
public class ChunkRenderer {
public class ChunkMesher {
Blocks[] blocks;
public void stupidArrayMeshing(WorldManager mgr, Chunk chunk) {
@ -86,8 +84,6 @@ public class ChunkRenderer {
short cIndex = 0;
public void greedyMeshing(WorldManager mgr, Chunk chunk) {
long begin = System.nanoTime();
vIndex = 0;
iIndex = 0;
cIndex = 0;
@ -129,9 +125,9 @@ public class ChunkRenderer {
for (x[v] = 0; x[v] < Config.CHUNK_SIZE; x[v]++) {
for (x[u] = 0; x[u] < Config.CHUNK_SIZE; x[u]++) {
Blocks b1 = (x[dim] >= 0) ? blocks[SpaceFilling.HILBERT_XYZ_ENCODE[x[0]][x[1]][x[2]]] : null;
Blocks b1 = (x[dim] >= 0) ? blocks[SpaceFillingCurve.HILBERT_XYZ_ENCODE[x[0]][x[1]][x[2]]] : null;
Blocks b2 = (x[dim] < Config.CHUNK_SIZE - 1)
? blocks[SpaceFilling.HILBERT_XYZ_ENCODE[x[0] + q[0]][x[1] + q[1]][x[2]+q[2]]]
? blocks[SpaceFillingCurve.HILBERT_XYZ_ENCODE[x[0] + q[0]][x[1] + q[1]][x[2]+q[2]]]
: null;
// This is the original line taken from rob's code, readapted (replace voxelFace
@ -229,9 +225,9 @@ public class ChunkRenderer {
Mesh mesh = new Mesh();
mesh.setBuffer(Type.Position, 3,
BufferUtils.createFloatBuffer((Vector3f[]) Arrays.copyOf(vertices, vIndex)));
mesh.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer((float[]) Arrays.copyOf(colors, cIndex)));
mesh.setBuffer(Type.Index, 3, BufferUtils.createShortBuffer((short[]) Arrays.copyOf(indices, iIndex)));
BufferUtils.createFloatBuffer(Arrays.copyOf(vertices, vIndex)));
mesh.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(Arrays.copyOf(colors, cIndex)));
mesh.setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(Arrays.copyOf(indices, iIndex)));
mesh.updateBound();
Geometry geo = new Geometry("ColoredMesh", mesh);
@ -245,7 +241,6 @@ public class ChunkRenderer {
geo.setMaterial(mat);
chunk.chunkNode.attachChild(geo);
}
System.out.println("Greedy meshing of chunk took " + (System.nanoTime()-begin ) + " ns");
}
final int VOXEL_SIZE = 1;