org.fxyz3d.shapes.primitives.SegmentedDomeMesh Maven / Gradle / Ivy
The newest version!
/**
* SegmentedDomeMesh.java
*
* Copyright (c) 2013-2017, 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.geometry.Point3D;
import javafx.scene.DepthTest;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Translate;
import org.fxyz3d.geometry.Face3;
/**
*
* @author Sean
*/
public class SegmentedDomeMesh extends TexturedMesh {
/*
Field vars
*/
private static final double DEFAULT_RADIUS = 50.0D;
private static final double DEFAULT_PHIMIN = Math.toRadians(0);
private static final double DEFAULT_PHIMAX = Math.toRadians(360);
private static final double DEFAULT_THETAMIN = Math.toRadians(0);
private static final double DEFAULT_THETAMAX = Math.toRadians(90);
private static final int DEFAULT_DIVISIONS = 20;
public SegmentedDomeMesh() {
this(DEFAULT_RADIUS, DEFAULT_PHIMIN, DEFAULT_PHIMAX,
DEFAULT_THETAMIN, DEFAULT_THETAMAX, DEFAULT_DIVISIONS);
}
/**
* @param radius radius of the sphere segment
* @param phimin The starting azimutal angle [rad], 0-2*pi.
* @param phimax The ending azimutal angle [rad], 0-2*pi, phimax >
* phimin.
* @param thetamin The starting polar angle [rad], -pi/2-pi/2.
* @param thetamax The ending polar angle [rad], -pi/2-pi/2, thetamax >
* thetamin.
* @param divisions The number of segments of curves approximations,
* granulariy > 2.
*/
public SegmentedDomeMesh(double radius,
double phimin, double phimax,
double thetamin, double thetamax,
int divisions) {
setRadius(radius);
setPhimin(phimin);
setPhimax(phimax);
setThetamin(thetamin);
setThetamax(thetamax);
setDivisions(divisions);
updateMesh();
setDepthTest(DepthTest.ENABLE);
}
private TriangleMesh createSegmentedDome(double radius,
double phimin, double phimax,
double thetamin, double thetamax,
int divisions){
listVertices.clear();
listTextures.clear();
listFaces.clear();
// Create Points
double phi = phimin;
double theta;
for (int i = 0; i < divisions + 1; i++) {
theta = thetamin;
for (int j = 0; j < divisions + 1; j++) {
org.fxyz3d.geometry.Point3D ta = new org.fxyz3d.geometry.Point3D(
(float) (radius * Math.cos(theta) * Math.sin(phi)),
(float) (radius * Math.cos(theta) * Math.cos(phi)),
(float) (radius * Math.sin(theta)));
listVertices.add(ta);
theta += (thetamax - thetamin) / divisions;
}
phi += (phimax - phimin) / divisions;
}
// Create texture coordinates
createTexCoords(divisions, divisions);
//Add the faces "winding" the points generally counter clock wise
for (int i = 0; i < divisions; i++) {
int multiplier = (i * divisions) + i;
//Up the Outside
for (int j = multiplier; j < divisions + multiplier; j++) {
listFaces.add(new Face3(j, j + 1, j + divisions + 1)); //lower triangle
listTextures.add(new Face3(j, j + 1, j + divisions + 1));
listFaces.add(new Face3(j + divisions + 1, j + 1, j + divisions + 2)); //upper triangle
listTextures.add(new Face3(j + divisions + 1, j + 1, j + divisions + 2));
}
//Down the Inside
for (int j = divisions + multiplier; j > multiplier; j--) {
listFaces.add(new Face3(j, j - 1, j + divisions + 1)); ; //lower triangle
listTextures.add(new Face3(j, j - 1, j + divisions + 1));
listFaces.add(new Face3(j - 1, j + divisions, j + divisions + 1)); //upper triangle
listTextures.add(new Face3(j - 1, j + divisions, j + divisions + 1));
}
}
return createMesh();
}
/*
Properties
*/
private final DoubleProperty radius = new SimpleDoubleProperty(DEFAULT_RADIUS){
@Override
protected void invalidated() {
updateMesh();
}
};
public final double getRadius() {
return radius.get();
}
public final void setRadius(double value) {
radius.set(value);
}
public DoubleProperty radiusProperty() {
return radius;
}
private final DoubleProperty phimin = new SimpleDoubleProperty(DEFAULT_PHIMIN){
@Override
protected void invalidated() {
updateMesh();
}
};
public final double getPhimin() {
return phimin.get();
}
public final void setPhimin(double value) {
phimin.set(value);
}
public DoubleProperty phiminProperty() {
return phimin;
}
private final DoubleProperty phimax = new SimpleDoubleProperty(DEFAULT_PHIMAX){
@Override
protected void invalidated() {
updateMesh();
}
};
public final double getPhimax() {
return phimax.get();
}
public final void setPhimax(double value) {
phimax.set(value);
}
public DoubleProperty phimaxProperty() {
return phimax;
}
private final DoubleProperty thetamax = new SimpleDoubleProperty(DEFAULT_THETAMAX){
@Override
protected void invalidated() {
updateMesh();
}
};
public final double getThetamax() {
return thetamax.get();
}
public final void setThetamax(double value) {
thetamax.set(value);
}
public DoubleProperty thetamaxProperty() {
return thetamax;
}
private final DoubleProperty thetamin = new SimpleDoubleProperty(DEFAULT_THETAMIN){
@Override
protected void invalidated() {
updateMesh();
}
};
public final double getThetamin() {
return thetamin.get();
}
public final void setThetamin(double value) {
thetamin.set(value);
}
public DoubleProperty thetaminProperty() {
return thetamin;
}
private final IntegerProperty divisions = new SimpleIntegerProperty(DEFAULT_DIVISIONS){
@Override
protected void invalidated() {
updateMesh();
}
};
public final int getDivisions() {
return divisions.get();
}
public final void setDivisions(int value) {
divisions.set(value);
}
public IntegerProperty divisionsProperty() {
return divisions;
}
@Override
protected final void updateMesh() {
setMesh(null);
mesh = createSegmentedDome(getRadius(), getPhimin(), getPhimax(), getThetamin(), getThetamax(), getDivisions());
setMesh(mesh);
}
}