Jump to content

Question about HUD and line between two Coordinates


ValKalAstra
 Share

You are about to reply to a thread that has been inactive for 379 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

This is another one of those conceptual questions where I am running into my failed math education and need help, a reality check or a smack with a wiki entry. Imagine the following scenario:

  • Attached HUD Object. Say - a simple thin cube prim attached as a child to a root prim.
  • Got two coordinates in Screen Space Coordinates (from a llDetectedTouchPos).
  • Want to draw Line between both coordinates using the child prim.

I'm a bit stuck on a conceptual level. I've kicked around a few ideas. I assume llLookAt wouldn't work because the rotation isn't meant for the root prim but the child prim and also because it needs region coordinates, not screen space coordinates. I thought I could use the pythagorean theorem to figure out the angle but - my math fails me spectacularly and i don't even dare show the resulting attempt.

Thus I come to you with a plea for a pointer: What's a sane way to go about this? Namely: Attached HUD, Child Prim pointing from A to B based on supplied set of coordinates. I'll take anything at this point, from script example snippet to simple pointer or even a wiki entry to a function I hadn't considered.

 

 

  • Like 1
Link to comment
Share on other sites

So, a big practical complication is that coordinates can be different depending on which HUD attach point your HUD is attached to. For getting a 'first try' working, make sure your HUD is attached to the "HUD_CENTER" attach point, and set its location to <0,0,0>.

Second conceptual hurdle is transforming the 'linguistically obvious' notion of "pointing at" to something that is actionable in LSL. I think the easiest 'pointer' to work with is a half-sliced cone, in which case the actual action would be something like 'move the cone to point A and point the z-axis of the cone at point B'

In that case, because a cone is symmetrical about its z-axis, we can use llRotBetween() to find a rotation which will move an object's z-axis from pointing in the z direction, to pointing at any arbitrary vector, for example, the vector pointing from point a to point b which is just (point_b-point_a);

<script example when I get a chance to test in-world>

ETA: I was going to do a write-up of successive changes to make it work in succssively more 'interesting' cases, but that would take a bit of work. I'll just copy-paste a beginning and ending and note the major differences:

1) Only works when the HUD is at ZERO_ROTATION on the center attach point:

//Pointer orientation on a HUD 1: basics.
//
//Setup:
//  -Create a box and a cone. 
//  -set the x,y,z size of the box to 0.25, 
//  -set the cone's size ot 0.125,0.125,0.25 and link it to the box.
//  -make the cone red (for visibility)
//  -take the box-cone into inventory and attach it to hud->center (or center 2)
//  -edit the HUD and set the position of the box to 0,0,0, 
//      and the position of the cone to -0.5,0,0

integer gLinkPointer = 2; // link # of the pointer prim.
vector gPosPointer = <-1,0,0>; // where is the pointer?
vector gPosTarget  = <-1,0,0.5>;  // where should it point to?


integer gMode = 0; // 0: move the base of the pointer. 1: move the pointed ad position.

point_at_target()
{   llSetLinkPrimitiveParamsFast(gLinkPointer,
    [   PRIM_POSITION, gPosPointer - llGetLocalPos(),
        PRIM_ROT_LOCAL, llRotBetween(<0,0,1>,gPosTarget-gPosPointer),
        // there is a bug with PRIM_ROTATION; you should never use it for a child prim.
        PRIM_SIZE, <0.125,0.125,2*llVecMag(gPosTarget-gPosPointer)>
        // double the length of the pointer, because it is sliced in half.

    ]);
}

default
{
    touch_start(integer n)
    {
        vector touch_pos = llDetectedTouchPos(0);
        gMode=!gMode;
        if(gMode)  
        {   gPosTarget=touch_pos;
        }else
        {   gPosPointer=touch_pos;
        }
        point_at_target();
    }
}

Making things work when it's attached to a different attach point, or when the HUD is in a different orientation, is actually somewhat involved.

For other attach points, you need to find an 'offset' between the local coordinates of the HUD and screen coordinates. If the user's window is wider than it is tall (a rather reasonable assumption) the offsets for the top and bottom HUD attach points will be constant, but unfortunately, you can't figure out the width for the offset without some interesting guesswork.

that guesswork is easiest to do if the HUD is in a sane orientation (the HUD face is parallel to the screen) and the user is touching the root prim. That calculation (see 'black magic' below) is valid unless/until the HUD is attached to a different attach point, or the user's window size ratio changes. As written, that calculation is a bit 'at odds' with the heuristic values gathered by the attach() even t procedure. I'll leave logic for not overwriting gOffset in the attach event, if it was set while the HUD was attached to the same attach point as an 'exercise' :P

For other orientations, you need (or at least it makes the math and conceptualization actually easier) to abandon llRotBetween() (which is kind of a crutch in any case) and learn about llAtan2, which is basically the only trig function you should ever need in LSL: if you give it x,y coordinates, (the wiki says y,x order, because in math land, people like their clocks with noon facing right and 3pm facing up :P) it tells you in (radian) angles how far around a clock would need to turn to make that angle. 0x,1y = 0 degrees, 0.5x,0.5y = 45 degrees etc.  If you zero out the orientation of the root prim, and then turn by the correct angle about an intrinsic axis of the pointer, it should point in a sane direction.

//Pointer orientation on a HUD lesson 4: llAtan2
//
//Setup:
//  -Create a box and a cone. 
//  -set the x,y,z size of the box to 0.25, 
//  -set the cone's size ot 0.125,0.125,0.25 and link it to the box.
//  -make the cone red (for visibility)
//  -take the box-cone into inventory and attach it to hud->center (or center 2)
//  -edit the HUD and set the position of the box to 0,0,0, 
//      and the position of the cone to -0.5,0,0
//  -set the path cut of the cone to 0,0.5; and texture the (new) open faces green.

rotation gRotPointerBase = <0,0,-0.71,0.71>;
integer gLinkPointer = 2; // link # of the pointer prim.
vector gPosPointer = <-1,0,0>; // where is the pointer?
vector gPosTarget  = <-1,0,0.5>;  // where should it point to?

vector gHUDOffset;
list gHUDOffsets = 
// * left&right only valid for 1920x1080 ratio monitors!
[   <-0.5,0,0>,         // center_2.
    <-0.5,0.95,-0.5>, // top right
    <-0.5,0,-0.5>,     // top center
    <-0.5,-0.95,-0.5>,  // top left
    <-0.5,0,0>,         // center 1
    <-0.5,-0.95,0.5>,   // bottom left
    <-0.5,0,0.5>,      // bottom
    <-0.5,0.95,0.5>   // bottom right
];

integer gMode = 0; // 0: move the base of the pointer. 1: move the pointed at position.

point_at_target()
{   vector diff = gPosTarget-gPosPointer;
    float angle = llAtan2(diff.y,diff.z); // because the pointer starts 'up' it's easier to think in 'clock angles', which, interestingly, are the same as math angles with x,y flipped.
    llSetLinkPrimitiveParamsFast(gLinkPointer,
    [   PRIM_POSITION, ( gHUDOffset +gPosPointer-llGetLocalPos() )/llGetLocalRot(),
        PRIM_ROT_LOCAL, llAxisAngle2Rot(<0,-1,0>,angle)*(gRotPointerBase/llGetLocalRot()),
        // there is a bug with PRIM_ROTATION; you should never use it for a child prim.
        // <0,-1,0> is an intrinsic axis of the pointer.
        PRIM_SIZE, <0.125,0.125,2*llVecMag(gPosTarget-gPosPointer)>
        // double the length of the pointer, because it is sliced in half.

    ]);
}

default
{
    state_entry()
    {   integer point = llGetAttached()-31;
        if(point<0)
        {   llOwnerSay("Error: I am not atached to a HUD point!");
        }else
        {   gHUDOffset = llList2Vector(gHUDOffsets,point);
        }
    }
    touch_start(integer n)
    {
        vector touch_pos = llDetectedTouchPos(0);
        if(ZERO_ROTATION==llGetLocalRot())
        {if(4==llDetectedTouchFace(0))
        {if(1==llDetectedLinkNumber(0))
        {   // use black magic to find the user's screen ratio.
            vector st = llDetectedTouchST(0);
            vector scale = llGetScale(); 
            vector local_pos = llGetLocalPos();

            vector touch_estimate = local_pos + ((<0,-scale.y*(st.x-0.5),scale.z*(st.y-0.5)>));
            vector difference = touch_estimate-touch_pos;

            llOwnerSay("Estimate touch_pos:"+(string)touch_estimate);
            llOwnerSay("Difference: "+(string)(touch_estimate-touch_pos));
            difference.x = -0.5;
            gHUDOffset = difference;
        }}}
        
        //llOwnerSay((string)touch_pos);
        //llOwnerSay((string)(RAD_TO_DEG*llRot2Euler(llGetLocalRot())));
        gMode=!gMode;
        if(gMode)  
        {   gPosTarget=touch_pos;
        }else
        {   gPosPointer=touch_pos;
        }
        point_at_target();
    }
    attach(key ID)
    {   if(ID)
        {   integer point = llGetAttached()-31;
            if(point<0)
            {   llOwnerSay("Error: I am not atached to a HUD point!");
            }else
            {   gHUDOffset = llList2Vector(gHUDOffsets,point);
            }
        }
    }
}

ETA2: For a pointer which isn't sliced, you can move it to the middle of the two points and not double the length. The point between 2 points is 0.5*(point_a+point_b);.

Edited by Quistess Alpha
  • Like 2
  • Thanks 2
Link to comment
Share on other sites

Wow, I'm floored. Thank you so much for going above and beyond for the answer. From walking me through the aspects of it to giving me examples to work with. I even think I understood something my math teachers didn't get through my skull all those years ago.

This is perfect, thanks.

 

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 379 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...