org.fxyz3d.shapes.primitives.ConeMesh Maven / Gradle / Ivy
The newest version!
/**
* ConeMesh.java
*
* Copyright (c) 2013-2016, F(X)yz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of F(X)yz, any associated website, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.fxyz3d.shapes.primitives;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.shape.TriangleMesh;
/**
*
* @author Birdasaur
* adapted Dub's CapsuleMesh example
*/
public class ConeMesh extends TexturedMesh{
/*
Field vars
*/
private static final int DEFAULT_DIVISIONS = 32;
private static final double DEFAULT_RADIUS = 25.0D;
private static final double DEFAULT_HEIGHT = 50.0D;
/*
Constructors
*/
public ConeMesh() {
this(DEFAULT_DIVISIONS, DEFAULT_RADIUS, DEFAULT_HEIGHT);
}
public ConeMesh(double radius, double height){
this(DEFAULT_DIVISIONS, radius, height);
}
public ConeMesh(int divisions, double radius, double height) {
setDivisions(divisions);
setRadius(radius);
setHeight(height);
setMesh(createCone(getDivisions(), (float)getRadius(), (float)getHeight()));
}
/*
Methods
*/
private TriangleMesh createCone(int divisions, float radius, float height) {
mesh = new TriangleMesh();
//Start with the top of the cone, later we will build our faces from these
mesh.getPoints().addAll(0,0,0); //Point 0: Top of the Cone
//Generate the segments of the bottom circle (Cone Base)
double segment_angle = 2.0 * Math.PI / divisions;
float x, z;
double angle;
double halfCount = (Math.PI / 2 - Math.PI / (divisions / 2));
// Reverse loop for speed!! der
for(int i=divisions+1;--i >= 0; ) {
angle = segment_angle * i;
x = (float)(radius * Math.cos(angle - halfCount));
z = (float)(radius * Math.sin(angle - halfCount));
mesh.getPoints().addAll(x,height,z);
}
mesh.getPoints().addAll(0,height,0); //Point N: Center of the Cone Base
//@TODO Birdasaur for now we'll just make an empty texCoordinate group
//@DUB HELP ME DUBi Wan Kanobi, you are my only hope!
//I'm not good at determining Texture Coordinates
mesh.getTexCoords().addAll(0,0);
//Add the faces "winding" the points generally counter clock wise
//Must loop through each face, not including first and last points
for(int i=1;i<=divisions;i++) {
mesh.getFaces().addAll( //use dummy texCoords, @TODO Upgrade face code to be real
0,0,i+1,0,i,0, // Vertical Faces "wind" counter clockwise
divisions+2,0,i,0,i+1,0 // Base Faces "wind" clockwise
);
}
return mesh;
}
/*
Properties
*/
private final DoubleProperty radius = new SimpleDoubleProperty(){
@Override
protected void invalidated() {
setMesh(createCone(getDivisions(), (float)getRadius(), (float)getHeight()));
}
};
public final double getRadius() {
return radius.get();
}
public final void setRadius(double value) {
radius.set(value);
}
public DoubleProperty radiusProperty() {
return radius;
}
private final DoubleProperty height = new SimpleDoubleProperty(){
@Override
protected void invalidated() {
setMesh(createCone(getDivisions(), (float)getRadius(), (float)getHeight()));
}
};
public final double getHeight() {
return height.get();
}
public final void setHeight(double value) {
height.set(value);
}
public DoubleProperty heightProperty() {
return height;
}
private final IntegerProperty divisions = new SimpleIntegerProperty(){
@Override
protected void invalidated() {
setMesh(createCone(getDivisions(), (float)getRadius(), (float)getHeight()));
}
};
public final int getDivisions() {
return divisions.get();
}
public final void setDivisions(int value) {
divisions.set(value);
}
public IntegerProperty divisionsProperty() {
return divisions;
}
@Override
protected void updateMesh() {
mesh = createCone(getDivisions(), (float)getRadius(), (float)getHeight());
}
}