Display 3D text

From JReality Wiki
Jump to: navigation, search

Source file: LabelsOnCube

JavaDoc: DefaultTextShader


Run as Java webstart


jReality 3D text

jReality supports the display of 3D text. What is 3D text, you ask? It's the capability to display text within a 3D scene. jReality 3D text:

  • is always oriented so that it faces the camera, or, what is the same, so that it lies in a plane parallel to the plane of projection.
  • is drawn in perspective so that nearer text is larger, and further is small.
  • can be drawn with any Java font, in the size and color of your choosing.
  • can be scaled by an arbitrary factor in object space.
  • can be offset from its 3D position by an offset -- specified in 3d normalized device coordinates.
  • has an alignment option so that you can attach it at its center, any of its corners, or in the middle of any of its edges (specified by constants in the class SwingConstants).


Attaching the text to a geometry

The text to be displayed must be attached to a PointSet by specifying a vertex attribute named Attributes.LABELS. The following example does this directly. You can also avoid the use of DataList's by using a point set factory, and use setVertexLabel(). There are analogous attributes on line sets and face sets (setEdgeAttribute(Attribute.LABELS, ...), etc). and corresponding methods on line set and face set factories setEdgeLabels() and setFaceLabels(). The labels set in this way are displayed at the edge mid-point and the face mid-point, resp.


Note: Many geometry factories implement methods to automatically generate numbered labels for points, edges, and faces of the underlying geometry. Look for the methods setGenerateVertexLabels, etc.


Rendering the text with a text shader

The display of the text is controlled by an instance of de.jreality.shader.TextShader. This is by default de.jreality.shader.DefaultTextShader. Each point, line, and polygon shader has within it an instance of a text shader, and this is used to control rendering of any text attached to the points, lines, or faces of the geometry (see previous paragraph).

The scaling factor depends on the object coordinate system you're using. With setScale(1.0), 3D text has a height of 1.0 and a width depending on the the length of the text to be displayed.

Finally, if you don't want to see the labels even if you've defined them, use setShowLabels(false).

Hint: To display text on a point set, you must draw the points. But if you don't want to see the points, set the attribute "pointRadius" (or "pointSize" if not drawing spheres) to 0.0.


Example

The following example creates and displays labels on the vertices, edges, and faces of a cube. As you can see, there are convenience mathods to set the attributes of the text shaders; but these can also be set directly via Appearance attributes.


package de.jreality.tutorial.geom;
 
import java.awt.Color;
 
import de.jreality.geometry.GeometryUtility;
import de.jreality.geometry.IndexedFaceSetUtility;
import de.jreality.geometry.Primitives;
import de.jreality.scene.Appearance;
import de.jreality.scene.IndexedFaceSet;
import de.jreality.scene.SceneGraphComponent;
import de.jreality.scene.data.Attribute;
import de.jreality.scene.data.StorageModel;
import de.jreality.shader.DefaultGeometryShader;
import de.jreality.shader.DefaultLineShader;
import de.jreality.shader.DefaultPointShader;
import de.jreality.shader.DefaultPolygonShader;
import de.jreality.shader.DefaultTextShader;
import de.jreality.shader.ShaderUtility;
import de.jreality.plugin.JRViewer;
import de.jreality.util.SystemProperties;
 
public class LabelsOnCube {
 
    public static void label(IndexedFaceSet ps) {
      int n=ps.getNumPoints();
      String[] labels=new String[n];
      for (int i = 0; i<n; i++) labels[i] = "Point "+i;
      ps.setVertexAttributes(Attribute.LABELS, StorageModel.STRING_ARRAY.createReadOnly(labels));
 
      n=ps.getNumEdges();
      labels=new String[n];
      for (int i = 0; i<n; i++) labels[i] = "Edge "+i;
      ps.setEdgeAttributes(Attribute.LABELS, StorageModel.STRING_ARRAY.createReadOnly(labels));
 
      n=ps.getNumFaces();
      labels=new String[n];
      for (int i = 0; i<n; i++) labels[i] = "Face "+i;
      ps.setFaceAttributes(Attribute.LABELS, StorageModel.STRING_ARRAY.createReadOnly(labels));
}
 
public static void main(String[] args) {
 
    IndexedFaceSet ifs = Primitives.cube();
    label(ifs);
    
    SceneGraphComponent cmp = new SceneGraphComponent("Labels on cube");
    Appearance a = new Appearance();
    cmp.setAppearance(a);
    cmp.setGeometry(ifs);
    
    DefaultGeometryShader dgs = ShaderUtility.createDefaultGeometryShader(a, false);
    DefaultTextShader pts = (DefaultTextShader) ((DefaultPointShader)dgs.getPointShader()).getTextShader();
    DefaultTextShader ets = (DefaultTextShader) ((DefaultLineShader)dgs.getLineShader()).getTextShader();
    DefaultTextShader fts = (DefaultTextShader) ((DefaultPolygonShader)dgs.getPolygonShader()).getTextShader();
    
    pts.setDiffuseColor(Color.blue);
    ets.setDiffuseColor(Color.orange);
    fts.setDiffuseColor(Color.green);
    
    Double scale = new Double(0.01);
    pts.setScale(scale);
    ets.setScale(scale);
    fts.setScale(scale);
    
    double[] offset = new double[]{-.1,0,0.3};
    pts.setOffset(offset);
    ets.setOffset(offset);
    fts.setOffset(offset);
    
    dgs.setShowPoints(true);
    
    JRViewer.display(cmp);
  }
 
}


Previous: Use a clipping plane Developer Tutorial: Contents Next: Use a non-default shader