All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoCapsuleFX3D 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 YoCapsuleFX3D extends YoGraphicFX3D
{
   private Tuple3DProperty center = new Tuple3DProperty(null, 0.0, 0.0, 0.0);
   private Tuple3DProperty axis = new Tuple3DProperty(null, 0.0, 0.0, 1.0);
   private DoubleProperty length = new SimpleDoubleProperty(0.3);
   private DoubleProperty radius = new SimpleDoubleProperty(0.05);

   private final PhongMaterial material = new PhongMaterial();
   private final MeshView capsuleNode = new MeshView();
   private final Translate translate = new Translate();
   private final Rotate rotate = new Rotate();

   private CapsuleData newData = null;
   private CapsuleData oldData = null;
   private Mesh newMesh = null;
   private boolean clearMesh = false;

   public YoCapsuleFX3D()
   {
      drawModeProperty.addListener((o, oldValue, newValue) ->
                                   {
                                      if (newValue == null)
                                         drawModeProperty.setValue(DrawMode.FILL);
                                      capsuleNode.setDrawMode(newValue);
                                   });
      capsuleNode.setMaterial(material);
      capsuleNode.getTransforms().addAll(translate, rotate);
      capsuleNode.idProperty().bind(nameProperty());
      capsuleNode.getProperties().put(YO_GRAPHICFX_ITEM_KEY, this);
   }

   public YoCapsuleFX3D(ReferenceFrameWrapper worldFrame)
   {
      this();
      center.setReferenceFrame(worldFrame);
      axis.setReferenceFrame(worldFrame);
   }

   @Override
   public void render()
   {
      if (center.containsNaN() || axis.containsNaN())
      {
         oldData = null;
         capsuleNode.setMesh(null);
         return;
      }

      newData = newCapsuleData(length, radius);

      if (color == null)
         color = new SimpleColorFX();
      material.setDiffuseColor(color.get());

      if (translate != null)
      {
         Point3D centerInWorld = center.toPoint3DInWorld();
         translate.setX(centerInWorld.getX());
         translate.setY(centerInWorld.getY());
         translate.setZ(centerInWorld.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;
         capsuleNode.setMesh(null);
      }

      if (newMesh != null)
      {
         capsuleNode.setMesh(newMesh);
         newMesh = null;
      }
   }

   @Override
   public void computeBackground()
   {
      CapsuleData newDataLocal = newData;
      newData = null;

      if (newDataLocal == null)
      {
         return;
      }
      else if (newDataLocal.containsNaN() || EuclidCoreTools.isZero(newDataLocal.radius, 1.0e-5))
      {
         clearMesh = true;
         oldData = null;
         return;
      }
      else if (newDataLocal.equals(oldData))
      {
         return;
      }

      newMesh = JavaFXTriangleMesh3DDefinitionInterpreter.interpretDefinition(TriangleMesh3DFactories.Capsule(newDataLocal.length,
                                                                                                              newDataLocal.radius,
                                                                                                              newDataLocal.radius,
                                                                                                              newDataLocal.radius,
                                                                                                              32,
                                                                                                              32));
      oldData = newDataLocal;
   }

   private static CapsuleData newCapsuleData(DoubleProperty length, DoubleProperty radius)
   {
      CapsuleData data = new CapsuleData();

      if (YoGraphicTools.isAnyNull(length, radius))
         return data;
      data.length = length.get();
      data.radius = radius.get();
      return data;
   }

   private static class CapsuleData
   {
      private double length, radius;

      @Override
      public boolean equals(Object object)
      {
         if (object == this)
         {
            return true;
         }
         else if (object instanceof CapsuleData)
         {
            CapsuleData other = (CapsuleData) object;
            if (length != other.length)
               return false;
            if (radius != other.radius)
               return false;
            return true;
         }
         else
         {
            return false;
         }
      }

      public boolean containsNaN()
      {
         return Double.isNaN(length) || Double.isNaN(radius);
      }
   }

   public void setCenter(Tuple3DProperty center)
   {
      this.center = center;
   }

   public void setAxis(Tuple3DProperty axis)
   {
      this.axis = axis;
   }

   public void setLength(DoubleProperty length)
   {
      this.length = length;
   }

   public void setLength(double length)
   {
      this.length = new SimpleDoubleProperty(length);
   }

   public void setRadius(DoubleProperty radius)
   {
      this.radius = radius;
   }

   public void setRadius(double radius)
   {
      this.radius = new SimpleDoubleProperty(radius);
   }

   @Override
   public void clear()
   {
      center = null;
      axis = null;
      length = null;
      radius = null;
      color = null;
   }

   @Override
   public YoCapsuleFX3D clone()
   {
      YoCapsuleFX3D clone = new YoCapsuleFX3D();
      clone.setName(getName());
      clone.setCenter(new Tuple3DProperty(center));
      clone.setAxis(new Tuple3DProperty(axis));
      clone.setLength(length);
      clone.setRadius(radius);
      clone.setColor(color);
      return clone;
   }

   public Tuple3DProperty getCenter()
   {
      return center;
   }

   public Tuple3DProperty getAxis()
   {
      return axis;
   }

   public DoubleProperty getLength()
   {
      return length;
   }

   public DoubleProperty getRadius()
   {
      return radius;
   }

   @Override
   public Node getNode()
   {
      return capsuleNode;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy