Draw an arrow in 3d space, start and end of arrow flexible

good day, I want to create a short arrow in 3d space,
the root can be anywhere in the 3dspace, the start and end of the arrow should be flexible so that I can change them to a different start and end in 3d space, start and end of arrow in whatever parts of the 3d space I like, any suggestions? thank you :slight_smile:

I look for an easy way to do such an arrow, like this three.js helper three.js docs , is there something similar in babylon? or what’s the easiest way to make an arrow in 3d space that points from whatever point I like towards a direction in 3d space I pick with a length I choose, etc, thank you :wink:

You can take the source code from the gizmo class:

@Evgeni_Popov that’s useful thank you, but in my case I will have an initial point and a direction vector. That code uses rotations instead, what about an example that uses a point and a direction vector (like the three.js does), thank you :slight_smile:

@Evgeni_Popov
I tried it on a new playground here:
https://playground.babylonjs.com/#E4PXL4#1

but I cannot manage to make the arrow appear

@Evgeni_Popov ah yes now it appears
https://playground.babylonjs.com/#E4PXL4#2

so now the question is, if what I have is a root point and a direction vector, how could I make it go from an origin point in the direction of a direction vector with whatever length i wanted?

@Evgeni_Popov
so I got the arrow now.
And I Set its origin easily with:
myArrow.position = pickInfo.pickedPoint;

and now I have to set where it points to, and for that it seems I would have to use:
myArrow.rotation = new Vector3(0, 0, 0);

so mmm how would I translate between a 3d gradient direction vector and the rotation angles, I guess that’s the question

I wonder if it would be something related to this:
rx = acos(direction_x); etc
ry = acos(direction_y);
rz = acos(direction_z);
myArrow.rotation = new Vector3(rx, ry, rz);
but not sure…

@Evgeni_Popov
I managed to do it with this that seems to work:
const dirmag= Math.sqrt(dir._x * dir._x + dir._y * dir._y+ dir._z * dir._z);
const rx = Math.acos(dir._x/dirmag);
const ry = Math.acos(dir._y/dirmag);
const rz = Math.acos(dir._z/dirmag);
myArrow.position = pickInfo.pickedPoint;
myArrow.position._x+=normal._x5;
myArrow.position._y+=normal._y
5;
myArrow.position._z+=normal._z*5;
myArrow.rotation = new Vector3(rx, ry, rz);

Two issues that I have now are:

  • sometimes the arrow gets too inside the mesh so i dont know if this is a good idea but basically i push the position of the arrow a bit in the direction of the normal of the point where it is:
    myArrow.position._x+=normal._x *5;
    myArrow.position._y+=normal._y *5;
    myArrow.position._z+=normal._z *5;
    to get it further from the mesh so that it can be seen, not sure if this is the best idea in regards to that. Any other suggestions to make the arrow be attached to the mesh but without going within it so that its still fully visible?

  • and second, I calculate the magnitude of the gradient with:
    const Grad = new Vector2(gp,gq);
    const gradmag= Math.sqrt(Grad.x * Grad.x + Grad.y * Grad.y);

  • and now I need to make the arrow longer or shorter depending on the magnitude of the gradient, this is very important. How can I do that? I tried changing the scaling of the whole arrow but that doesn’t work, how could i make the arrow longer or shorter dynamically all the time depending on how the magnitude of the gradient changes?

thank you :slight_smile:

An alternative to drawing and scaling an arrow. This way the arrow is created from given a start position and a direction

https://www.babylonjs-playground.com/#S2R5PN

Two arrows one half the length of the other, added boxes to check scaling on total arrow length

https://www.babylonjs-playground.com/#S2R5PN#1

Uses Custom Extrusion | Babylon.js Documentation

1 Like

@JohnK thank you John! very interesting, do you mean that with this arrow I could potentially do:
const dir = new Vector3(-gp,-(gpgp+gqgq), -gq);

arrowScale(arrow, myShape, dir , 0.5)

and then the arrow would go from whatever point I want in whatever direction I want,

but I see that internally it uses:
const arrowStart = path[0];
let arrowDirection = path[1].subtract(path[0]);

therefore I don’t have to pass it a vector, but a couple of vectors I see
const myPath = ;
myPath.push(ArrowstartingPositionIn3DSpace);
myPath.push(dir) //gradient direction?

do we really need to also use
myPath.push(arrowBodyEnd)
myPath.push(arrowHeadEnd);
as those should always follow the same pattern really

Each arrow needs a start point and a direction.
You only need the arrowScale if after constructing the arrow you later want to change its size.

The variables used and the split between body and head is so that the extrusion is properly scaled along its length.

1 Like