Skip to content

Commit

Permalink
Initial commit for Cubes rewrite.
Browse files Browse the repository at this point in the history
TODO: textures, noise, generators, tests
  • Loading branch information
Sleaker committed Feb 14, 2014
0 parents commit 15c688a
Show file tree
Hide file tree
Showing 22 changed files with 1,616 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
build/
nbproject/
.project
MANIFEST.MF
master-application.jnlp
lwjgl64.dll
OpenAL64.dll
.classpath
build.xml
50 changes: 50 additions & 0 deletions src/com/jme3/cubed/Block.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.jme3.cubed;

import com.jme3.math.Vector3f;

public class Block {

/**
* 0, 0, 0
*/
public static final Vector3f FRONT_BOTTOM_LEFT = new Vector3f(0, 0, 0);
/**
* 1, 0, 0
*/
public static final Vector3f FRONT_BOTTOM_RIGHT = new Vector3f(1, 0, 0);
/**
* 0, 0, 1
*/
public static final Vector3f REAR_BOTTOM_LEFT = new Vector3f(0, 0, 1);
/**
* 1, 0, 1
*/
public static final Vector3f REAR_BOTTOM_RIGHT = new Vector3f(1, 0, 1);
/**
* 0, 1, 0
*/
public static final Vector3f FRONT_TOP_LEFT = new Vector3f(0, 1, 0);
/**
* 1, 1, 0
*/
public static final Vector3f FRONT_TOP_RIGHT = new Vector3f(1, 1, 0);
/**
* 0, 1, 1
*/
public static final Vector3f REAR_TOP_LEFT = new Vector3f(0, 1, 1);
/**
* 1, 1, 1
*/
public static final Vector3f REAR_TOP_RIGHT = new Vector3f(1, 1, 1);

private final BlockType type;

public Block() {
this.type = MaterialManager.getInstance().getType(getClass());
}


public BlockType getType() {
return this.type;
}
}
22 changes: 22 additions & 0 deletions src/com/jme3/cubed/BlockMaterial.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.jme3.cubed;

import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.texture.Texture;

/**
*
* @author Carl
*/
public class BlockMaterial extends Material {

public BlockMaterial(AssetManager assetManager, String blockTextureFilePath){
super(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
Texture texture = assetManager.loadTexture(blockTextureFilePath);
texture.setMagFilter(Texture.MagFilter.Nearest);
texture.setMinFilter(Texture.MinFilter.NearestNoMipMaps);
setTexture("ColorMap", texture);
getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}
}
32 changes: 32 additions & 0 deletions src/com/jme3/cubed/BlockSkin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.jme3.cubed;

import com.jme3.cubed.math.Vector2i;

public class BlockSkin {
private Vector2i[] textureLocations;
private boolean isTransparent;

public BlockSkin(Vector2i textureLocation, boolean isTransparent) {
this(new Vector2i[] { textureLocation }, isTransparent);
}

public BlockSkin(Vector2i[] textureLocations, boolean isTransparent) {
this.textureLocations = textureLocations;
this.isTransparent = isTransparent;
}

public Vector2i getTextureLocation(Face face) {
return textureLocations[getTextureLocationIndex(face)];
}

protected int getTextureLocationIndex(Face face) {
if(textureLocations.length == 6) {
return face.ordinal();
}
return 0;
}

public boolean isTransparent(){
return isTransparent;
}
}
24 changes: 24 additions & 0 deletions src/com/jme3/cubed/BlockType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.jme3.cubed;

/**
*
* @author Carl
*/
public class BlockType {

public BlockType(byte type, BlockSkin skin) {
this.type = type;
this.skin = skin;
}

private byte type;
private BlockSkin skin;

public byte getType() {
return type;
}

public BlockSkin getSkin() {
return skin;
}
}
136 changes: 136 additions & 0 deletions src/com/jme3/cubed/ChunkTerrain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.jme3.cubed;

import com.jme3.cubed.math.Vector3i;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import java.io.IOException;

/**
*
* @author Nicholas Minkler <sleaker@gmail.com>
*/
public class ChunkTerrain extends Node {

public static final int C_SIZE = 32; // Length of a chunk
public static final int C_BITS = 5; // Number of Bits allowed per chunk 32 >> 5 == 1;
public static final int X_SHIFT = C_BITS; // Bits offset of the X value when packed into an int.
public static final int Y_SHIFT = 10; // Bit offset of the Y value when packed into an int.
public static final int Z_SHIFT = 0; // Bit offset of the Z value when packed into an int.
public static final int MASK = C_SIZE - 1; // Mask is 1 less than the size.

/**
* Unpacks an int with 5 bits per value into a vector3.
* @param val
* @return Vector3
*/
public static Vector3i vectorFromInt555(int val) {
return new Vector3i((val >> X_SHIFT) & MASK, (val >> Y_SHIFT) & MASK, val & MASK);
}

/**
* unpacks an int with 5 bits per value and stores it in the given Vector3i
* @param val
* @param to
* @return the Vector3i
*/
public static Vector3i vectorFromInt555(int val, Vector3i to) {
return to.setX((val >> X_SHIFT) & MASK).setY((val >> Y_SHIFT) & MASK).setZ(val & MASK);
}

private ChunkTerrainControl chunkControl;
private Vector3i location;
private Vector3i blockLocation;
private Geometry meshData;
private boolean needsMeshUpdate = false;
private byte[] blocks;

ChunkTerrain(ChunkTerrainControl ct, int x, int y, int z) {
this.chunkControl = ct;
this.location = new Vector3i(x, y, z);
this.blockLocation = location.mult(C_SIZE);
this.blocks = new byte[1 << (C_BITS * 3)];
this.setLocalTranslation(location.toVector3f().mult(C_SIZE));
}

protected void update(float tpf) {
if (needsMeshUpdate) {
if (meshData == null) {
meshData = new Geometry("ChunkMesh: " + location.toString());
this.attachChild(meshData);
meshData.setMaterial(chunkControl.getMaterial());
}
Mesh mesh = chunkControl.getMesher().generateMesh(this);
if (mesh != null) {
meshData.setMesh(mesh);
} else {
this.detachChild(meshData);
}
needsMeshUpdate = false;
}
}

public byte[] getBlocks() {
return blocks;
}

public void setBlock(Class<? extends Block> blockClass, Vector3i loc) {
int x = loc.getX();
int y = loc.getY();
int z = loc.getZ();
if (x < C_SIZE && y < C_SIZE && z < C_SIZE && x > -1 && y > -1 && z > -1) {
if (blockClass == null) {
blocks[(x << X_SHIFT) + z + ( y << Y_SHIFT)] = 0;
} else {
blocks[(x << X_SHIFT) + z + ( y << Y_SHIFT)] = MaterialManager.getInstance().getType(blockClass).getType();
}
needsMeshUpdate = true;
}
}

public byte getBlock(Vector3i loc) {
int x = loc.getX();
int y = loc.getY();
int z = loc.getZ();
if (isInChunk(loc)) {
return blocks[(x << X_SHIFT) + z + (y << Y_SHIFT)];
} else {
return 0;
}
}

public boolean isFaceVisible(Vector3i loc, Face face) {
Vector3i vec = loc.add(face.getOffsetVector());
byte type = 0;
if (!isInChunk(vec)) {
type = chunkControl.getBlock(vec.add(blockLocation));
} else {
type = getBlock(loc.add(face.getOffsetVector()));
}
return type == 0 || MaterialManager.getInstance().getType(type).getSkin().isTransparent();
}

private boolean isInChunk(Vector3i vec) {
return vec.getX() < C_SIZE && vec.getY() < C_SIZE && vec.getZ() < C_SIZE && vec.getX() > -1 && vec.getY() > -1 && vec.getZ() > -1;
}

public Vector3i getLocation() {
return this.location;
}

public void scheduleMeshUpdate() {
this.needsMeshUpdate = true;
}

@Override
public void write(JmeExporter e) throws IOException {
super.write(e);
}

@Override
public void read(JmeImporter e) throws IOException {
super.read(e);
}
}
109 changes: 109 additions & 0 deletions src/com/jme3/cubed/ChunkTerrainControl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.jme3.cubed;

import com.jme3.cubed.render.VoxelMesher;
import com.jme3.cubed.math.Vector3i;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.control.AbstractControl;
import java.util.HashMap;
import java.util.Map;

/**
*
* @author Nicholas Minkler <sleaker@gmail.com>
*/
public class ChunkTerrainControl extends AbstractControl {
private Node chunkRoot;
private BlockMaterial blockMaterial;
private Map<Vector3i, ChunkTerrain> chunks;
private boolean greedy = false;
private VoxelMesher mesher;

public ChunkTerrainControl(Node terrainNode, BlockMaterial bm, VoxelMesher mesher) {
chunkRoot = terrainNode;
this.blockMaterial = bm;
this.mesher = mesher;
chunks = new HashMap<>();
}

/**
* Sends an update call to all <code>ChunkTerrain</code>'s attached to the the ChunkControl
*/
@Override
protected void controlUpdate(float tpf) {
for (ChunkTerrain terrain : chunks.values()) {
terrain.update(tpf);
}
}

@Override
protected void controlRender(RenderManager rm, ViewPort vp) {

}

public void setBlock(Class<? extends Block> blockClass, Vector3i loc, boolean gen) {
Vector3i pos = worldToChunkVec(loc);
ChunkTerrain terrain = getTerrain(pos);
if (terrain == null) {
if (gen) {
terrain = new ChunkTerrain(this, pos.getX(), pos.getY(), pos.getZ());
chunkRoot.attachChild(terrain);
chunks.put(pos, terrain);
} else {
return;
}
}
terrain.setBlock(blockClass, new Vector3i(loc.getX() & ChunkTerrain.MASK, loc.getY() & ChunkTerrain.MASK, loc.getZ() & ChunkTerrain.MASK));
}

public BlockMaterial getMaterial() {
return blockMaterial;
}

/**
* Gets a ChunkTerrain from the given chunk vector
* @param vec
* @return
*/
public ChunkTerrain getTerrain(Vector3i vec) {
return chunks.get(vec);
}

/**
* Gets a Chunk from the given Block vector
* @param vec
* @return chunk
*/
public ChunkTerrain getTerrainLocal(Vector3i vec) {
return getTerrain(worldToChunkVec(vec));
}

public byte getBlock(Vector3i vec) {
ChunkTerrain terrain = getTerrainLocal(vec);
if (terrain != null) {
return terrain.getBlock(new Vector3i(vec.getX() & ChunkTerrain.MASK, vec.getY() & ChunkTerrain.MASK, vec.getZ() & ChunkTerrain.MASK));
} else {
return 0;
}
}
private Vector3i worldToChunkVec(Vector3i vec) {
return new Vector3i(vec.getX() >> ChunkTerrain.C_BITS, vec.getY() >> ChunkTerrain.C_BITS, vec.getZ() >> ChunkTerrain.C_BITS);
}

public void setMesher(VoxelMesher mesher) {
this.mesher = mesher;
switchMesher();
}

public VoxelMesher getMesher() {
return this.mesher;
}

public void switchMesher() {
this.greedy = !greedy;
for (ChunkTerrain terrain : chunks.values()) {
terrain.scheduleMeshUpdate();
}
}
}
Loading

0 comments on commit 15c688a

Please sign in to comment.