/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.anzix.fsz.voxelworld.features;
import com.ardor3d.math.FastMath;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyVector3;
import com.ardor3d.renderer.IndexMode;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.scenegraph.MeshData;
import com.ardor3d.util.geom.BufferUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.anzix.fsz.voxelworld.VoxelBlockPosition;
import net.anzix.fsz.voxelworld.DetailLevel;
import net.anzix.fsz.voxelworld.Feature;
import net.anzix.fsz.voxelworld.FszMatrix4;
import net.anzix.fsz.voxelworld.VoxelBlock;
import net.anzix.fsz.voxelworld.VoxelWorld;
import net.anzix.fsz.voxelworld.layers.LayerBlock;
import net.anzix.fsz.voxelworld.features.components.Branch;
/**
*
* @author csiga
*/
public class Tree extends Feature {
private ArrayList<Branch> branches = new ArrayList<Branch>();
private ArrayList<FszMatrix4> foliagePositions = new ArrayList<FszMatrix4>();
private int numOfNonVoxelBranches = 0;
private Vector3 trunkStartpoint;
public Tree(Vector3 trunkStartpoint, double trunkLength, double trunkRadius) {
this.trunkStartpoint = trunkStartpoint;
FszMatrix4 position = new FszMatrix4();
position.setTranslation(trunkStartpoint);
AddBranch(position, 1, trunkLength, trunkRadius);
}
/*public Tree(FszMatrix4 position, double trunkLength, double trunkRadius) {
AddBranch(position, 1, trunkLength, trunkRadius);
}*/
@Override
public void attachAdditionalNonVoxelModels(DetailLevel level, VoxelBlock block) {
if (block.getPosition().isInBlock(trunkStartpoint, level)) {
generateFoliage(level, block);
generateNonVoxelBranches(level, block);
}
}
public void generateFoliage(DetailLevel level, VoxelBlock block) {
Mesh mesh = new Mesh();
MeshData meshData = mesh.getMeshData();
int numOfLeafs = foliagePositions.size();
Vector3[] points = new Vector3[8];
for (int i = 0; i<8; i++)
points[i] = new Vector3();
FloatBuffer vertexBuffer = BufferUtils.createVector3Buffer(numOfLeafs*8);
FloatBuffer textureCoordBuffer = BufferUtils.createVector2Buffer(numOfLeafs*8);
IntBuffer indexBuffer = BufferUtils.createIntBuffer(numOfLeafs * 12);
//FloatBuffer normalBuffer = BufferUtils.createVector3Buffer(numOfLeafs*4);
for (int i = 0; i<foliagePositions.size(); i++) {
FszMatrix4 position = foliagePositions.get(i);
points[0].set(-14, -1, 0);
points[1].set(-14, 20, 0);
points[2].set(14, 20, 0);
points[3].set(14, -1, 0);
points[4].set(0, -1, -14);
points[5].set(0, 20, -14);
points[6].set(0, 20, 4);
points[7].set(0, -1, 4);
for (Vector3 p : points) {
position.applyPost(p,p);
vertexBuffer.put(p.getXf());
vertexBuffer.put(p.getYf());
vertexBuffer.put(p.getZf());
}
int i8 = i*8;
indexBuffer.put(i8+0);
indexBuffer.put(i8+1);
indexBuffer.put(i8+2);
indexBuffer.put(i8+2);
indexBuffer.put(i8+3);
indexBuffer.put(i8+0);
indexBuffer.put(i8+0+4);
indexBuffer.put(i8+1+4);
indexBuffer.put(i8+2+4);
indexBuffer.put(i8+2+4);
indexBuffer.put(i8+3+4);
indexBuffer.put(i8+0+4);
textureCoordBuffer.put(0);textureCoordBuffer.put(0);
textureCoordBuffer.put(0);textureCoordBuffer.put(1);
textureCoordBuffer.put(1);textureCoordBuffer.put(1);
textureCoordBuffer.put(1);textureCoordBuffer.put(0);
textureCoordBuffer.put(0);textureCoordBuffer.put(0);
textureCoordBuffer.put(0);textureCoordBuffer.put(1);
textureCoordBuffer.put(1);textureCoordBuffer.put(1);
textureCoordBuffer.put(1);textureCoordBuffer.put(0);
}
//indexBuffer.rewind();
meshData.setVertexBuffer(vertexBuffer);
meshData.setIndexBuffer(indexBuffer);
meshData.setTextureBuffer(textureCoordBuffer, 0);
//meshData.setNormalBuffer(normalBuffer);
block.getFoliageNode().attachChild(mesh);
}
public void generateNonVoxelBranches(DetailLevel level, VoxelBlock block) {
Mesh mesh = new Mesh();
MeshData meshData = mesh.getMeshData();
int numOfSegments = 6;
Vector3 point1 = new Vector3();
Vector3 point2 = new Vector3();
Vector3 normal = new Vector3();
FloatBuffer vertexBuffer = BufferUtils.createVector3Buffer(numOfNonVoxelBranches * numOfSegments * 2);
FloatBuffer textureCoordBuffer = BufferUtils.createVector2Buffer(numOfNonVoxelBranches * numOfSegments * 2);
IntBuffer indexBuffer = BufferUtils.createIntBuffer(numOfNonVoxelBranches * (numOfSegments + 1) * 2);
FloatBuffer normalBuffer = BufferUtils.createVector3Buffer(numOfNonVoxelBranches * numOfSegments * 2);
for (int i = 0; i<branches.size(); i++) {
Branch branch = branches.get(i);
FszMatrix4 transform = branch.getTransform();
double startRadius = branch.getStartRadius();
double endRadius = branch.getEndRadius();
double length = branch.getLength();
int ii = i* numOfSegments * 2;
Vector3 startPoint = branch.getStartPoint();
for (int s = 0; s<numOfSegments; s++) {
double angle = s * Math.PI * 2 /numOfSegments ;
float texCoordX = s/(float)numOfSegments;
double ux = Math.cos(angle);
double uz = Math.sin(angle);
VoxelWorld.logger.info("SZOG " + angle +" "+ ux +" "+uz);
point1.set( ux*startRadius, 0, uz*startRadius);
point2.set( ux*endRadius, length, uz*endRadius);
transform.applyPost(point1,point1);
transform.applyPost(point2,point2);
vertexBuffer.put(point1.getXf());
vertexBuffer.put(point1.getYf());
vertexBuffer.put(point1.getZf());
vertexBuffer.put(point2.getXf());
vertexBuffer.put(point2.getYf());
vertexBuffer.put(point2.getZf());
point1.subtract(startPoint,normal);
normalBuffer.put(normal.getXf());
normalBuffer.put(normal.getYf());
normalBuffer.put(normal.getZf());
normalBuffer.put(normal.getXf());
normalBuffer.put(normal.getYf());
normalBuffer.put(normal.getZf());
textureCoordBuffer.put(texCoordX);
textureCoordBuffer.put(0);
textureCoordBuffer.put(texCoordX);
textureCoordBuffer.put(1);
indexBuffer.put(ii + s*2);
indexBuffer.put(ii + s*2 + 1);
}
indexBuffer.put(ii + 0);
indexBuffer.put(ii + 1);
}
//String log = "INDEXBUFFER: ";
//for (int i=0; i<numOfNonVoxelBranches * (numOfSegments + 1) * 2; i++)
// log += ", " + indexBuffer.get(i);
//VoxelWorld.logger.info(log);
meshData.setVertexBuffer(vertexBuffer);
meshData.setIndexBuffer(indexBuffer);
IndexMode[] indexModes = new IndexMode[numOfNonVoxelBranches];
int[] indexLengths = new int[numOfNonVoxelBranches];
for (int i = 0; i<numOfNonVoxelBranches; i++ ) {
indexModes[i] = IndexMode.TriangleStrip;
indexLengths[i] = (numOfSegments+1)*2;
}
//meshData.setIndexMode(IndexMode.TriangleStrip);
meshData.setIndexModes(indexModes);
meshData.setIndexLengths(indexLengths);
meshData.setTextureBuffer(textureCoordBuffer, 0);
meshData.setNormalBuffer(normalBuffer);
block.getNonVoxelTreeBranchNode().attachChild(mesh);
}
private FszMatrix4 rotation = new FszMatrix4();
private void AddBranch(FszMatrix4 position, double factor, double length, double startRadius) {
rotation.setRotation(Math.PI*2*Math.random(), (1.0-factor)*1.2 + Math.random()*0.2-0.1 ,0);
position.multiplyLocal(rotation);
if (startRadius > 0.75) { //voxel branmch
double endRadius = startRadius * factor;
Branch branch = new Branch(position, length, startRadius, endRadius);
branches.add(branch);
numOfNonVoxelBranches++;
branch.shiftPositionToEndpoint(position);
FszMatrix4 position2 = new FszMatrix4 (position);
double divisionFactor = Math.random();
AddBranch(position2, divisionFactor, length, endRadius);
AddBranch(position, 1.0-divisionFactor, length, endRadius);
} else {
foliagePositions.add(position);
}
}
@Override
public void applyDensities(ReadOnlyVector3 basePosition, float densities[][][], Feature densitySources[][][], DetailLevel level, LayerBlock layerBlock) {
//for (Branch branch : branches)
// branch.applyDensities(basePosition, densities, densitySources,level, layerBlock);
}
@Override
public boolean affectBlock(final VoxelBlockPosition p, final LayerBlock layerBlock, final DetailLevel level) {
if (level.getLevelID() == 0)
return true;
else
return false;
}
}