[Solved]Arrow.setLineWidth(10) not to scale when camera moves out ? jme3 r7237

Solved: Lines have no width, therefore they tend to show the same 1 pixel size from whatever distance (anyway this isn't jme3 related)<br /> =========<br /> In other words, the thickness of the arrows grows as the camera moves away from the arrow to a point where the thickness is bigger than the arrow head<br /> I hope it's not my drivers again O_o<br /> zoomed in:<br /> <img src='http://i.imgur.com/yiI1I.png'>http://i.imgur.com/yiI1I.png</img><br /> =====<br /> zooming out:<br /> <img src='http://i.imgur.com/V1OjE.png'>http://i.imgur.com/V1OjE.png</img><br /> ======<br /> zooming out even more:<br /> <img src='http://i.imgur.com/F2oiS.png'>http://i.imgur.com/F2oiS.png</img><br /> and the code that does this:<br /> pre type=“java”`
package org.jme3.tests;

import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Spline;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial.CullHint;

import com.jme3.scene.debug.Arrow;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Curve;

import com.jme3.system.AppSettings;


  • Sample 2 - How to use nodes as handles to manipulate objects in the scene

  • graph. You can rotate, translate, and scale objects by manipulating their

  • parent nodes. The Root Node is special: Only what is attached to the Root

  • Node appears in the scene.


    public class HelloNode5 extends SimpleApplication {

    private static final float lineWidth = 10f;

    private Vector3f cornerPos;

    private Geometry geoCurve;

    private Geometry geoBox;

    private final Spline spline = new Spline();

    private Node coord;

    Box box;

    public static void main(String[] args) {

    HelloNode5 app = new HelloNode5();

    AppSettings aSet = new AppSettings(true);







    • (non-Javadoc)

    • @see com.jme3.app.SimpleApplication#simpleUpdate(float)



      public void simpleUpdate(float tpf) {

      // calculating by how much to rotate now(relative to previous position),

      // not the exact rotation position(as it was in

      // prev. revision)

      float yaw = (FastMath.DEG_TO_RAD * 4 * tpf) % (FastMath.PI * 2);

      float roll = (FastMath.DEG_TO_RAD * 7 * tpf) % (FastMath.PI * 2);

      float pitch = (FastMath.DEG_TO_RAD * 11 * tpf) % (FastMath.PI * 2);

      // rotating the box by this much

      geoBox.rotate(yaw, roll, pitch);

      // move box “forward” too, that is, forward relative to itself ie.

      // spaceship moving forward


      Vector3f clonedCornerPos = cornerPos.clone();

      // now applying the same transform (pos/rot/scale) to the corner as the

      // box has

      geoBox.getLocalTransform().transformVector(clonedCornerPos,// in,

      clonedCornerPos// store


      Vector3f f = box.getCenter().clone();

      geoBox.getLocalTransform().transformVector(f, f);



      // coord.setLocalTransform( geoBox.getLocalTransform() );

      // we have the corner’s exact pos now, relative to the Node the geoBox &

      // geoCurve are both in

      // we add that pos to the curve

      spline.addControlPoint(clonedCornerPos);// must be cloned!

      // we must create new Curve object because we can’t add/update the

      // spline in existing one (?!)

      geoCurve.setMesh(new Curve(spline, 1));



      public void simpleInitApp() {


      Node subNode = new Node();

      subNode.setLocalTranslation(new Vector3f(2, 0.5f, 1));

      subNode.rotate(1f, -2f, 4f);

      // a box with non 0,0,0 center which means a position of x,y,z relative

      // to it’s parent geoBox(below)

      box = new Box(new Vector3f(2, 3, 4), 0.5f, 0.9f, 1.3f);

      geoBox = new Geometry(“Box”, box);

      geoBox.setLocalTranslation(1f, 2f, 3f);

      geoBox.scale(1.3f, 1.2f, 1.1f);// always ok

      geoBox.rotate(2f, -4f, 0.4f);

      Material mat2 = new Material(assetManager,


      mat2.setColor(“Color”, ColorRGBA.Red);


      Material curveMat = new Material(assetManager,


      curveMat.setColor(“Color”, ColorRGBA.Green);

      geoCurve = new Geometry(“trails”);




      rootNode.setLocalTranslation(-1, -2, -4);

      rootNode.rotate(-1f, 2f, -4f);


      rootNode.scale(1.5f);// this is always ok

      subNode.scale(0.4f);// this is always ok too

      // subNode.scale(1.3f, 0.7f, 0.4f);// XXX: bug when uncommented

      // rootNode.scale(0.4f, 1.4f, 1.1f);// XXX: or/and this

      // doing this here only once

      cornerPos = new Vector3f();

      // calculating position of corner, first getting corner as it were if

      // box were at 0,0,0 and no rotation/scale


      box.getXExtent(), box.getYExtent(), box.getZExtent());

      // now considering box may have a different than 0,0,0 center


      coord = new Node();


      attachCoordinateAxes(Vector3f.ZERO, coord);


      // coord.setLocalTranslation( geoBox.getLocalTranslation() );//

      // box.getCenter() );


      private void attachCoordinateAxes(Vector3f pos, Node toNode) {

      Arrow arrow = new Arrow(Vector3f.UNIT_X);

      // make arrow thicker,


      putShape(arrow, ColorRGBA.Red, toNode).setLocalTranslation(pos);

      arrow = new Arrow(Vector3f.UNIT_Y);

      arrow.setLineWidth(lineWidth); // make arrow thicker

      putShape(arrow, ColorRGBA.Green, toNode).setLocalTranslation(pos);

      arrow = new Arrow(Vector3f.UNIT_Z);

      arrow.setLineWidth(lineWidth); // make arrow thicker

      putShape(arrow, ColorRGBA.Blue, toNode).setLocalTranslation(pos);


      private Geometry putShape(Mesh shape, ColorRGBA color, Node onNode) {

      Geometry g = new Geometry(“coordinate axis”, shape);

      Material mat = new Material(assetManager,



      mat.setColor(“Color”, color);




      return g;




A line has no width, thus you can set it globally. Use a lengthy tube.

1 Like
normen said:
A line has no width, thus you can set it globally. Use a lengthy tube.

Too many assumptions :) I mean, I don't understand what you mean by "you can set it globally"
I'm guessing around here, that the Arrow's width is formed of X lines where X is the width of the Arrow, therefore that explains why they don't scale down 'cause a line is always visible as at least 1 pixel no matter at what distance from camera (well maybe if too far it will be 0 pixels obviously)

By tube you mean com.jme3.scene.shape.Cylinder.Cylinder() I'm guessing, if so, maybe Arrow could also use cylinder when width is above 1 ? or maybe that is for me to subclass xD

I guess I understand the big picture of what you said, thank you! ;)

Its a line, it has no width: http://en.wikipedia.org/wiki/Line_(geometry)

So you set some width just so they can be painted at all, if they were really 0 pixels wide you would not see them.

If you want it to be three-dimensional then use a three-dimensional object.

1 Like

The line width is given in pixels, it is not effected by the projection. This is OpenGL behavior and is not related to jME3.

Like normen said, using a cylinder, which is an actual 3D object, is probably better for your needs.

1 Like

roger that, many thanks, too kind xD