
us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoConeFX3D Maven / Gradle / Ivy
package us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Node;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.Mesh;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import us.ihmc.euclid.axisAngle.AxisAngle;
import us.ihmc.euclid.geometry.tools.EuclidGeometryTools;
import us.ihmc.euclid.tools.EuclidCoreTools;
import us.ihmc.euclid.tuple3D.Point3D;
import us.ihmc.scs2.definition.visual.TriangleMesh3DFactories;
import us.ihmc.scs2.sessionVisualizer.jfx.definition.JavaFXTriangleMesh3DDefinitionInterpreter;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.ReferenceFrameWrapper;
import us.ihmc.scs2.sessionVisualizer.jfx.tools.JavaFXMissingTools;
import us.ihmc.scs2.sessionVisualizer.jfx.yoComposite.Tuple3DProperty;
import us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.color.SimpleColorFX;
public class YoConeFX3D extends YoGraphicFX3D
{
private Tuple3DProperty position = new Tuple3DProperty(null, 0.0, 0.0, 0.0);
private Tuple3DProperty axis = new Tuple3DProperty(null, 0.0, 0.0, 1.0);
private DoubleProperty height = new SimpleDoubleProperty(0.3);
private DoubleProperty radius = new SimpleDoubleProperty(0.05);
private final PhongMaterial material = new PhongMaterial();
private final MeshView coneNode = new MeshView();
private final Translate translate = new Translate();
private final Rotate rotate = new Rotate();
private ConeData newData = null;
private ConeData oldData = null;
private Mesh newMesh = null;
private boolean clearMesh = false;
public YoConeFX3D()
{
drawModeProperty.addListener((o, oldValue, newValue) ->
{
if (newValue == null)
drawModeProperty.setValue(DrawMode.FILL);
coneNode.setDrawMode(newValue);
});
coneNode.setMaterial(material);
coneNode.getTransforms().addAll(translate, rotate);
coneNode.idProperty().bind(nameProperty());
coneNode.getProperties().put(YO_GRAPHICFX_ITEM_KEY, this);
}
public YoConeFX3D(ReferenceFrameWrapper worldFrame)
{
this();
position.setReferenceFrame(worldFrame);
axis.setReferenceFrame(worldFrame);
}
@Override
public void render()
{
if (position.containsNaN() || axis.containsNaN())
{
oldData = null;
coneNode.setMesh(null);
return;
}
newData = newConeData(height, radius);
if (color == null)
color = new SimpleColorFX();
material.setDiffuseColor(color.get());
if (translate != null)
{
Point3D positionInWorld = position.toPoint3DInWorld();
translate.setX(positionInWorld.getX());
translate.setY(positionInWorld.getY());
translate.setZ(positionInWorld.getZ());
}
if (axis != null)
{
AxisAngle axisAngle = EuclidGeometryTools.axisAngleFromZUpToVector3D(axis.toVector3DInWorld());
axisAngle.setAngle(Math.toDegrees(axisAngle.getAngle()));
JavaFXMissingTools.convertAxisAngleToRotate(axisAngle, rotate); // FIXME: The conversion has to handle the change of unit: radians -> degrees
}
if (clearMesh)
{
clearMesh = false;
coneNode.setMesh(null);
}
if (newMesh != null)
{
coneNode.setMesh(newMesh);
newMesh = null;
}
}
@Override
public void computeBackground()
{
ConeData newDataLocal = newData;
newData = null;
if (newDataLocal == null)
{
return;
}
else if (newDataLocal.containsNaN() || EuclidCoreTools.isZero(newDataLocal.height, 1.0e-5) || EuclidCoreTools.isZero(newDataLocal.radius, 1.0e-5))
{
clearMesh = true;
oldData = null;
return;
}
else if (newDataLocal.equals(oldData))
{
return;
}
newMesh = JavaFXTriangleMesh3DDefinitionInterpreter.interpretDefinition(TriangleMesh3DFactories.Cone(newDataLocal.height, newDataLocal.radius, 32));
oldData = newDataLocal;
}
private static ConeData newConeData(DoubleProperty height, DoubleProperty radius)
{
ConeData data = new ConeData();
if (YoGraphicTools.isAnyNull(height, radius))
return data;
data.height = height.get();
data.radius = radius.get();
return data;
}
private static class ConeData
{
private double height, radius;
@Override
public boolean equals(Object object)
{
if (object == this)
{
return true;
}
else if (object instanceof ConeData)
{
ConeData other = (ConeData) object;
if (height != other.height)
return false;
if (radius != other.radius)
return false;
return true;
}
else
{
return false;
}
}
public boolean containsNaN()
{
return Double.isNaN(height) || Double.isNaN(radius);
}
}
public void setPosition(Tuple3DProperty position)
{
this.position = position;
}
public void setAxis(Tuple3DProperty axis)
{
this.axis = axis;
}
public void setHeight(DoubleProperty height)
{
this.height = height;
}
public void setHeight(double height)
{
this.height = new SimpleDoubleProperty(height);
}
public void setRadius(DoubleProperty radius)
{
this.radius = radius;
}
public void setRadius(double radius)
{
this.radius = new SimpleDoubleProperty(radius);
}
@Override
public void clear()
{
position = null;
axis = null;
height = null;
radius = null;
color = null;
}
@Override
public YoConeFX3D clone()
{
YoConeFX3D clone = new YoConeFX3D();
clone.setName(getName());
clone.setPosition(new Tuple3DProperty(position));
clone.setAxis(new Tuple3DProperty(axis));
clone.setHeight(height);
clone.setRadius(radius);
clone.setColor(color);
return clone;
}
public Tuple3DProperty getPosition()
{
return position;
}
public Tuple3DProperty getAxis()
{
return axis;
}
public DoubleProperty getHeight()
{
return height;
}
public DoubleProperty getRadius()
{
return radius;
}
@Override
public Node getNode()
{
return coneNode;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy