/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.anzix.fsz.voxelworld.features.components;
import com.ardor3d.math.FastMath;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyVector3;
import net.anzix.fsz.voxelworld.BasicFeature;
import net.anzix.fsz.voxelworld.DetailLevel;
import net.anzix.fsz.voxelworld.VoxelBlock;
import net.anzix.fsz.voxelworld.VoxelBlockPosition;
import net.anzix.fsz.voxelworld.FszMatrix4;
import net.anzix.fsz.voxelworld.layers.LayerBlock;
/**
*
* @author csiga
*/
public class Branch extends BasicFeature {
private final FszMatrix4 transform = new FszMatrix4();
private static Noise trunkNoise = new Noise(1, 0.5, 1);;
private double length;
private double startRadius;
private double endRadius;
private Vector3 startPoint;
private Vector3 endPoint;
public Vector3 getEndPoint() {
return endPoint;
}
public double getEndRadius() {
return endRadius;
}
public double getLength() {
return length;
}
public Vector3 getStartPoint() {
return startPoint;
}
public double getStartRadius() {
return startRadius;
}
public FszMatrix4 getTransform() {
return transform;
}
public Branch(FszMatrix4 position, double length, double startRadius, double endRadius) {
this.length = length;
this.startRadius = startRadius;
this.endRadius = endRadius;
this.startPoint = position.getTranslation();
this.endPoint = new Vector3 (0,length,0);
position.applyPost(endPoint, endPoint);
//position.invert(this.transform);
transform.set(position);
}
public void shiftPositionToEndpoint (FszMatrix4 position) {
position.setTranslation(endPoint);
}
public boolean affectBlock(VoxelBlockPosition p) {
return true;
}
@Override
public boolean hasBoundingBox() {
return true;
}
@Override
public Vector3 getLowerBound() {
return new Vector3(
Math.min(startPoint.getX() - startRadius, endPoint.getX() - endRadius),
Math.min(startPoint.getY() - startRadius, endPoint.getY() - endRadius),
Math.min(startPoint.getZ() - startRadius, endPoint.getZ() - endRadius) );
}
@Override
public Vector3 getUpperBound() {
return new Vector3(
Math.max(startPoint.getX() + startRadius, endPoint.getX() + endRadius),
Math.max(startPoint.getY() + startRadius, endPoint.getY() + endRadius),
Math.max(startPoint.getZ() + startRadius, endPoint.getZ() + endRadius) );
}
@Override
public void attachAdditionalNonVoxelModels(DetailLevel level, VoxelBlock block) {
super.attachAdditionalNonVoxelModels(level, block);
}
public float getDensity(ReadOnlyVector3 point, LayerBlock layerBlock, int lx, int ly, int lz, DetailLevel level) {
Vector3 pointLocal = transform.applyPost(point, null);
double y = pointLocal.getY();
double x = pointLocal.getX();
double z = pointLocal.getZ();
double localRadius;
double distance;
if (y <= 0) {
localRadius = startRadius;
distance = FastMath.sqrt(x*x+y*y+z*z);
} else if (y >= length) {
localRadius = endRadius;
y-=length;
distance = FastMath.sqrt(x*x+y*y+z*z);
} else {
distance = FastMath.sqrt(x*x+z*z);
double f = y/length;
localRadius = startRadius * (1-f) + endRadius * f;
}
double density = (localRadius - distance);
double frequency = 5/localRadius;
double amplitude = localRadius / 5;
double noise = amplitude * trunkNoise.getDensity(x*frequency,y*0.1*frequency,z*frequency);
return (float) (density + noise);
}
}