Jump to content
  • Advertisement
Sign in to follow this  

Finding points to build an Arrow.

This topic is 1247 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts


I recently posted this over in the DirectX part of the forum but figured this would be a better place for this question. I am currently working on trying to visualize a raycast and am trying to draw an arrow to signify the direction they ray is facing. I have it working for when the ray is pointing in a specific direction however, when I have the ray pointing in a different everything blows up. This is how I find the various points to render the raycast.

float fStartX = 0.0f;
float fStartY = 0.0f;
float fStartZ = 0.0f;

float fEndX = fStartX + (v3Dir.X * m_fLength);
float fEndY = fStartY + (v3Dir.Y * m_fLength);
float fEndZ = fStartZ + (v3Dir.Z * m_fLength);

float fCos = cosf(ToRadians(45.0f));
float fSin = sinf(ToRadians(45.0f));
fAngle1X = fEndX + fCos;
fAngle1Y = fEndY + fSin;
fAngle1Z = fEndZ / 2.0f;

fAngle2X = fEndX - fCos;
fAngle2Y = fEndY + fSin;
fAngle2Z = fEndZ / 2.0f;

fAngle3X = fEndX - fCos;
fAngle3Y = fEndY - fSin;
fAngle3Z = fEndZ / 2.0f;

fAngle4X = fEndX + fCos;
fAngle4Y = fEndY - fSin;
fAngle4Z = fEndZ / 2.0f;

I have a feeling that my issue is that I am not taking into account the ray direction. Which is throwing off the position of my angles. My question is what would be the best way to find the correct positions of the arrow based on direction. The only thing that I can think of is throwing in a couple of if statements to figure it out but that seems like a bad idea. I know it can be done with math. I am just not sure what the steps are to find it.

Thank you,
Chaz H.

Share this post

Link to post
Share on other sites

I made such draw function in the past, but in 2D - should be fairly simple to implement this in 3D.

The trick is to use the perpendical direction to calculate the tip left/right position.

    function drawVector(origin, vec, color, title, titleColor, titleIsOppsite, invert) {
        var n = {x: (origin.x + vec.x) - origin.x, y: (origin.y + vec.y) - origin.y};
        var l = Math.sqrt(n.x * n.x + n.y * n.y);
        n.x /= l;
        n.y /= l;
        var t = {x: -n.y, y: n.x};
        var arrowWidth = 12;
        var arrowDepth = 12;
        var textSpace = 20;

        var target = new Vec2(origin.x + vec.x, origin.y + vec.y);

        ctx.lineWidth = 3;
        ctx.moveTo(origin.x, origin.y);
        ctx.lineTo(target.x, target.y);

        if (!invert){
            ctx.moveTo(target.x, target.y);
            ctx.lineTo(target.x + t.x * arrowWidth + n.x * -arrowDepth, target.y + t.y * arrowWidth + n.y * -arrowDepth);
            ctx.moveTo(target.x, target.y);
            ctx.lineTo(target.x + t.x * -arrowWidth + n.x * -arrowDepth, target.y + t.y * -arrowWidth + n.y * -arrowDepth);
        } else {
            ctx.moveTo(origin.x, origin.y);
            ctx.lineTo(origin.x + t.x * arrowWidth + n.x * arrowDepth, origin.y + t.y * arrowWidth + n.y * arrowDepth);
            ctx.moveTo(origin.x, origin.y);
            ctx.lineTo(origin.x + t.x * -arrowWidth + n.x * arrowDepth, origin.y + t.y * -arrowWidth + n.y * arrowDepth);

        ctx.strokeStyle = color || "white";
        ctx.lineWidth = 1;

        if (typeof title != "undefined" && title != null) {
            var rad = Math.atan2(n.y, n.x);
            ctx.fillStyle = titleColor || color || "white";
            ctx.textBaseline = "middle";
            ctx.textAlign = "center";
            ctx.translate(0 + n.x * l * 0.5 + (titleIsOppsite ? t.x : -t.x) * textSpace, 0 + n.y * l * 0.5 + (titleIsOppsite ? t.y : -t.y) * textSpace);
            ctx.rotate(rad > Math.PI / 2 || rad < -Math.PI / 2 ? rad - Math.PI : rad);
            ctx.fillText(title, 0, 0);

Share this post

Link to post
Share on other sites
Its pretty trivial in 2D but for God's sake, get yourself using a Vector class rather than manually doing each per-component operation like that.

Vec2 rayPos, rayDir; // assuming rayDir is normalized
float rayLength;

Vec2 end = rayPos + (rayDir * rayLength);

Vec2 left(rayDir.y, -rayDir.x);
Vec2 right(-rayDir.y, rayDir.x); // may have these wrong way round, might be right then left smile.png but basically the perpendiculars to the ray direction vector

Vec2 p = end - (rayDir * someDistance); // move a bit back from the end
Vec2 arrowA = p + (left * someDistance); // move a bit out from arrow shaft at right angles
Vec2 arrowB = p + (right * someDistance); // move a bit out the opposite way

arrowA and arrowB are now the ends of each arrow line, so the following three lines:

rayPos -> end
arrowA -> end
arrowB -> end

will draw the arrow.

Bear in mind in 3D there are an infinite possible number of answers for arrowA and arrowB as you rotate around the arrow so the answer becomes slightly trickier. Edited by Aardvajk

Share this post

Link to post
Share on other sites

Thank you for the help. I have been trying to figure this out all day. My problem seems to be trying to figure out how to convert the left and right vectors that you used into 3D. Any suggestions on the proper way to format those vectors for 3D?

Share this post

Link to post
Share on other sites
That would depend upon where you want the tips of the arrow heads to be in relation to the arrow shaft - for example aligned to the view in some way? Or aligned to world axes in some way?

Share this post

Link to post
Share on other sites

Honestly, I never thought about that. What would be the easiest to setup? Also, I was thinking. Would't it be easier to find to just find the cross product of the half way point and then use that to build both sides of the arrow head?

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!