/*
* Kb9bm9Bn6Xq6
*
*/
package net.anzix.fsz.voxelworld;
import com.ardor3d.extension.model.collada.jdom.ColladaImporter;
import com.ardor3d.extension.model.collada.jdom.data.ColladaStorage;
import net.anzix.fsz.voxelworld.layers.LayerBlockPool;
import net.anzix.fsz.voxelworld.layers.LayerBlockPoolContainer;
import com.ardor3d.image.Texture;
import com.ardor3d.image.TextureStoreFormat;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.Quaternion;
import net.anzix.fsz.sceneComponents.Fog;
import com.ardor3d.math.Vector3;
import com.ardor3d.renderer.Camera;
import com.ardor3d.renderer.ContextCapabilities;
import com.ardor3d.renderer.ContextManager;
import com.ardor3d.renderer.pass.BasicPassManager;
import com.ardor3d.renderer.queue.RenderBucketType;
import com.ardor3d.renderer.state.BlendState;
import com.ardor3d.renderer.state.CullState;
import com.ardor3d.renderer.state.GLSLShaderObjectsState;
import com.ardor3d.renderer.state.TextureState;
import com.ardor3d.renderer.state.WireframeState;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.hint.LightCombineMode;
import com.ardor3d.ui.text.BasicText;
import com.ardor3d.util.ReadOnlyTimer;
import com.ardor3d.util.TextureManager;
import com.ardor3d.util.Timer;
import com.ardor3d.util.resource.ResourceLocatorTool;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.anzix.fsz.sceneComponents.PlainWater;
import net.anzix.fsz.sceneComponents.Shadow;
import net.anzix.fsz.sceneComponents.Sky;
import net.anzix.fsz.voxelworld.features.LayerBasedTerrain;
import net.anzix.fsz.voxelworld.features.RockyMountain;
import net.anzix.fsz.voxelworld.features.Tree;
/**
*
* @author csiga
*/
public class VoxelWorld {
public static final int NUM_OF_BLOCK_LEVELS = 6;
public static final int BLOCK_SIZE = 32;
public static final float FAR_PLANE = BLOCK_SIZE << NUM_OF_BLOCK_LEVELS;
public static final float WATER_HEIGHT = 0.0f;
/** The Constant logger. */
public static final Logger logger = Logger.getLogger(VoxelWorld.class.getName());
private PlainWater water;
private Sky sky;
private Fog fog;
private Shadow shadow;
public Shadow getShadow() {return shadow;}
private Timer timer;
private ArrayList<Feature> features = new ArrayList<Feature>();
private VoxelBlockPoolContainer voxelPoolContainer = new VoxelBlockPoolContainer();
public LayerBlockPoolContainer getLayerPoolContainer() {
return layerPoolContainer;
}
public VoxelBlockPoolContainer getVoxelPoolContainer() {
return voxelPoolContainer;
}
private LayerBlockPoolContainer layerPoolContainer = new LayerBlockPoolContainer();
Node staticObjectNode = new Node();
public void changeWireframeState() {
wireframeState.setEnabled(!wireframeState.isEnabled());
// Either an update or a markDirty is needed here since we did not touch the affected spatial directly.
// blockPool.markDirty(DirtyType.RenderState);
}
private int activePool;
public void nextActivePool() {
activePool = activePool < NUM_OF_BLOCK_LEVELS-1 ? activePool + 1 : 0;
}
public VoxelWorld(Timer timer) {
this.timer = timer;
for (int i = 0; i<NUM_OF_BLOCK_LEVELS; i++) {
LayerBlockPool layerBlockPool = new LayerBlockPool(this, new DetailLevel(i));
VoxelBlockPool voxelBlockPool = new VoxelBlockPool(this, new DetailLevel(i), layerBlockPool);
layerPoolContainer.add(layerBlockPool);
voxelPoolContainer.add(voxelBlockPool);
}
features.add(new LayerBasedTerrain());
//features.add(new RockyMountain());
//features.add(new Tree(new Vector3(-20,0,50),10,3));
//features.add(new Tree(new Vector3(-40,0,-10),10,2));
}
public ArrayList<Feature> getLocalFeatures(final VoxelBlock block, DetailLevel level) {
ArrayList<Feature> localFeatures = new ArrayList<Feature>();
Iterator it = features.iterator();
while(it.hasNext()) {
Feature feature = (Feature)it.next();
if (feature.affectBlock((VoxelBlockPosition) block.getPosition(), block.getRelatedLayerBlock(), level))
localFeatures.add(feature);
}
return localFeatures;
}
long previousTime = 0;
int FrameCounter = 0;
public void update(final ReadOnlyTimer timer, Camera camera) {
long currentTime = System.currentTimeMillis();
if (currentTime - previousTime > 1000) {
previousTime = currentTime;
infoText[0].setText(FrameCounter + " FPS");
FrameCounter = 0;
return;
} else
FrameCounter ++;
VoxelBlockPool infoBlockPool0 = (VoxelBlockPool) voxelPoolContainer.get(0);
for (int i = 0; i< NUM_OF_BLOCK_LEVELS; i++) {
VoxelBlockPool infoBlockPool = (VoxelBlockPool) voxelPoolContainer.get(i);
infoText[i+1].setText(infoBlockPool.toString());
}
infoText[7].setText(infoBlockPool0.getMeshInfo());
infoText[8].setText("MEMORY:" + Runtime.getRuntime().freeMemory()/1024/1024 + "M / " + Runtime.getRuntime().totalMemory()/1024/1024 + "M");
//infoText[7].setText(new VoxelBlockPosition(camera.getLocation(),infoBlockPool0.getLevel()).toString());
//infoText[8].setText(infoBlockPool0.getErrorInfo());
sky.update(timer,camera);
water.update(timer, camera);
fog.update(timer, camera);
float phase = (currentTime % 10000) / 10000.0f ; //* Math.PI * 2;
grassShaderState.setUniform("windPhase",phase); //(float)Math.sin(phase));
foliageShaderState.setUniform("windPhase",phase); //(float)Math.sin(phase));
layerPoolContainer.update(camera);
voxelPoolContainer.update(camera);
}
protected void initCamera(Camera camera) {
camera.setLocation(new Vector3(32, 40, 32));
camera.lookAt(new Vector3(64, 40, 64), Vector3.UNIT_Y);
camera.setFrustumPerspective(70.0, (float) camera.getWidth() / camera.getHeight(), 1.0f, FAR_PLANE);
}
/** Text fields used to present info about the example. */
private final BasicText infoText[] = new BasicText[10];
protected void initText( Node root,Camera camera) {
// Setup labels for presenting example info.
final Node textNodes = new Node("Text");
//root.attachChild(textNodes);
textNodes.getSceneHints().setRenderBucketType(RenderBucketType.Ortho);
textNodes.getSceneHints().setLightCombineMode(LightCombineMode.Off);
//final double infoStartY = camera.getHeight();
for (int i = 0; i < infoText.length; i++) {
infoText[i] = BasicText.createDefaultTextLabel("Text", "", 16);
infoText[i].setTranslation(new Vector3(10, + i * 20, 0));
textNodes.attachChild(infoText[i]);
infoText[i].setText(" ");
}
textNodes.updateGeometricState(0.0);
}
public static TextureState voxelTerrainTextureState = new TextureState();
public static TextureState foliageTextureState = new TextureState();
public static TextureState nonVoxelBranchTextureState = new TextureState();
public static TextureState grassTextureState = new TextureState();
public static GLSLShaderObjectsState voxelTerrainShaderState[] = new GLSLShaderObjectsState[NUM_OF_BLOCK_LEVELS];
public static GLSLShaderObjectsState foliageShaderState = new GLSLShaderObjectsState();
public static GLSLShaderObjectsState nonVoxelBranchShaderState = new GLSLShaderObjectsState();
public static GLSLShaderObjectsState grassShaderState = new GLSLShaderObjectsState();
public static BlendState alphaTestedBlendState = new BlendState();
public static CullState twoSidedFscesCullState = new CullState();
public static WireframeState wireframeState = new WireframeState();
public void addStaticModel(String name, Vector3 position, double scale, Quaternion rotation) {
if (rotation == null)
rotation = new Quaternion(-1,0,0,1);
try {
final ColladaStorage storage = new ColladaImporter().load(name);
Node colladaNode = storage.getScene();
colladaNode.setRotation(rotation);
colladaNode.setTranslation(position);
colladaNode.setScale(scale);
staticObjectNode.attachChild(colladaNode);
} catch (final IOException ex) {
ex.printStackTrace();
}
}
public void init(Camera camera, BasicPassManager passManager, Node root) {
initCamera(camera);
initText(root, camera);
initShaders();
initRenderStates();
addStaticModels();
final Node reflectedNode = new Node("reflectNode");
// SKY
sky = new Sky(WATER_HEIGHT);
reflectedNode.attachChild(sky);
reflectedNode.attachChild(voxelPoolContainer.getNode());
reflectedNode.attachChild(staticObjectNode);
// WATER
water = new PlainWater(camera, reflectedNode, sky, FAR_PLANE, WATER_HEIGHT); //= new Water(camera, reflectedNode, sky, FAR_PLANE, WATER_HEIGHT, timer);
root.attachChild(reflectedNode);
root.attachChild(water);
// FOG
ColorRGBA fogColor = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
fog = new Fog(FAR_PLANE, WATER_HEIGHT, fogColor, new ColorRGBA(0.1f, 0.1f, 0.9f, 1.0f));
root.setRenderState(fog);
// SHADOW
shadow = new Shadow();
shadow.registerPass(passManager);
shadow.addOccluder(staticObjectNode);
shadow.addOccluder(voxelPoolContainer.getPoolNode(0));
shadow.addOccluder(voxelPoolContainer.getPoolNode(1));
shadow.addOccluder(voxelPoolContainer.getPoolNode(2));
shadow.addAccepter(staticObjectNode);
shadow.addAccepter(voxelPoolContainer.getPoolNode(0));
shadow.addAccepter(voxelPoolContainer.getPoolNode(1));
shadow.addAccepter(voxelPoolContainer.getPoolNode(2));
//shadow.addAccepter(water);
// WIRAFRAMESTATE
voxelPoolContainer.getNode().setRenderState(wireframeState);
staticObjectNode.setRenderState(wireframeState);
water.setRenderState(wireframeState);
}
public void addStaticModels() {
//addStaticModel( NÉV ,new Vector3( HELYZET ), SKÁLA, FORGATÁS);
//- HELYZET: x,y,z - y tengely van felfelé
//- FORGATÁS: null helyett lehet: new Quaternion(x,y,z,1); x,y,z közül az egyik lehet 1;
addStaticModel("colladamodels/lighthouse/kopu/models/model.dae",new Vector3(-20.0, 0.0, 200.0), 1.0, null);
//addStaticModel("colladamodels/dinos/diplodocus/models/Diplodocus.dae",new Vector3(-55, -5, 290), .005, null);
//Quaternion q = new Quaternion();
//q.fromEulerAngles(0,Math.PI,Math.PI/2);
//addStaticModel("colladamodels/buildings/archline_splash_building/archline_splash_building.dae",new Vector3(20.0, 5.0, 0.0),0.1,q);
}
public void initShaders() {
final ContextCapabilities caps = ContextManager.getCurrentContext().getCapabilities();
if (caps.isGLSLSupported()) {
try {
for (int i = 0; i<NUM_OF_BLOCK_LEVELS; i++) {
voxelTerrainShaderState[i] = new GLSLShaderObjectsState();
URL vertexShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/voxelTerrain.vert");
URL pixelShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/voxelTerrain.frag");
voxelTerrainShaderState[i].setVertexShader(vertexShader.openStream());
voxelTerrainShaderState[i].setFragmentShader(pixelShader.openStream());
voxelTerrainShaderState[i].setUniform("texGrass1",0);
voxelTerrainShaderState[i].setUniform("texGrass2",1);
voxelTerrainShaderState[i].setUniform("texRock1",2);
voxelTerrainShaderState[i].setUniform("texRock2",3);
voxelTerrainShaderState[i].setUniform("texSand1",4);
voxelTerrainShaderState[i].setUniform("texSand2",5);
voxelTerrainShaderState[i].setUniform("texSnow",6);
voxelTerrainShaderState[i].setUniform("detailLevel",i);
voxelTerrainShaderState[i].setUniform("blockSize",BLOCK_SIZE);
voxelTerrainShaderState[i].setUniform("visibleBlocksOnALevel",2);
}
//GRASS
URL grassVertexShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/grass_billboard.vert");
URL grassPixelShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/grass.frag");
grassShaderState.setVertexShader(grassVertexShader.openStream());
grassShaderState.setFragmentShader(grassPixelShader.openStream());
grassShaderState.setUniform("grassTexture",0);
grassShaderState.setUniform("dudvMap",1);
grassShaderState.setUniform("detailLevel",0);
grassShaderState.setUniform("blockSize",BLOCK_SIZE);
grassShaderState.setUniform("visibleBlocksOnALevel",2);
grassShaderState.setUniform("windPhase",0.0f);
//FOLIAGE
URL foliageVertexShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/foliage.vert");
URL foliagePixelShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/foliage.frag");
foliageShaderState.setVertexShader(foliageVertexShader.openStream());
foliageShaderState.setFragmentShader(foliagePixelShader.openStream());
foliageShaderState.setUniform("foliageTexture",0);
foliageShaderState.setUniform("detailLevel",0);
foliageShaderState.setUniform("blockSize",BLOCK_SIZE);
foliageShaderState.setUniform("visibleBlocksOnALevel",2);
foliageShaderState.setUniform("windPhase",0.0f);
//NON VOXEL BRANCH
URL nonVoxelBranchVertexShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/nonVoxelBranch.vert");
URL nonVoxelBranchPixelShader = ResourceLocatorTool.getClassPathResource(VoxelWorld.class,
"shaders/nonVoxelBranch.frag");
nonVoxelBranchShaderState.setVertexShader(nonVoxelBranchVertexShader.openStream());
nonVoxelBranchShaderState.setFragmentShader(nonVoxelBranchPixelShader.openStream());
nonVoxelBranchShaderState.setUniform("nonVoxelBranchTexture",0);
nonVoxelBranchShaderState.setUniform("detailLevel",0);
nonVoxelBranchShaderState.setUniform("blockSize",BLOCK_SIZE);
nonVoxelBranchShaderState.setUniform("visibleBlocksOnALevel",2);
nonVoxelBranchShaderState.setUniform("windPhase",0.0f);
} catch (final IOException ex) {
VoxelWorld.logger
.logp(Level.SEVERE, getClass().getName(), "init(Renderer)", "Could not load shaders.", ex);
}
}
}
public void initRenderStates() {
//WOXEL TERRAIN TEXTURES
voxelTerrainTextureState.setEnabled(true);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/grass/grass_2.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),0);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/grass/grass_5.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),1);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/rock/stone_big.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),2);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/rock/rock_4.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),3);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/sand/sand.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),4);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/rock/stone_big.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),5);
voxelTerrainTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/snow/snow.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),6);
//FOLIAGE
foliageTextureState.setTexture(TextureManager.load("Textures/foliage/Branch_Summer.png", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),0);
foliageTextureState.setEnabled(true);
//NONVOXELBRANCH
nonVoxelBranchTextureState.setTexture(TextureManager.load("Textures/voxelMaterials/vegetation/bark.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),0);
nonVoxelBranchTextureState.setEnabled(true);
//GRASS
//grassTextureState.setTexture(TextureManager.load("Textures/grasssprite/gras02L.tga", Texture.MinificationFilter.Trilinear,
grassTextureState.setTexture(TextureManager.load("Textures/grasssprite/g2.png", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),0);
grassTextureState.setTexture(TextureManager.load("Textures/grasssprite/dudvmap.jpg", Texture.MinificationFilter.Trilinear,
TextureStoreFormat.GuessCompressedFormat, true),1);
grassTextureState.setEnabled(true);
//GENERAL STATES
alphaTestedBlendState.setBlendEnabled(false);
alphaTestedBlendState.setReference(0.9f);
alphaTestedBlendState.setTestEnabled(true);
wireframeState.setEnabled(false);
twoSidedFscesCullState.setEnabled(true);
twoSidedFscesCullState.setCullFace(CullState.Face.None);
}
}