Jump to content
sjakal

Weapon IR Laser Ranging

Recommended Posts

So here I proudly present a snippet which should do the job. _perfect_start should be the best start point in players model space for our problem.

_perfect_end = screenToWorld [0.5,0.5];
_err = vectorDiff _perfect_end - _posXhair;

_dir = player weaponDirection (currentWeapon player);

_reverse_start = _perfect_end vectorAdd (_dir vectorMultiply -5000);

_array = lineIntersectsSurfaces [_perfect_end, _reverse_start, objNull,objNull, false, 10, "GEOM","NONE"];

_array_count = count _array;

if (0 < _array_count) then
{ 
 {  
  if((_x select 2) == player)  
  {   
   _perfect_start = player worldToModel(_x select 0);  
  } 
 } forEach _array;
};

I ve calculated _err which is the error vector between actual crosshair and the perfect crosshair position. But I m not using it. It can be used to test if we have a precise crosshair position when the snippet is implemented to code.

 

Upto now there are some problems with that snippet.

 

1. yesterday I tested to use screenToWorld [0.5,0.5]; all the time to draw the crosshair but the command is to slow. crosshair was blinking.

   I suggest this correction could be run one time per second.

 

2. screenToWorld [0.5,0.5]; is working with the surface only. that means you get very wrong values if aiming to heaven.

 

3. screenToWorld [0.5,0.5]; is not working with objects (surface only) that means that the 10 I used at lineintersect command could be to low.

 

4. the snippet has to be implemented as auto correction in the code and yes of cause it has to be tested :-)

Share this post


Link to post
Share on other sites

Whow! Nice stuff - if it has similar precision it is definitely preferable. I also noticed frame drops due to all the vector mumbo jumbo I do every frame.

The auto-correction is just icing on the cake. I'll give it a whirl over the weekend and report back!

On quick inspection the offset seems to work if you permit rangefinding only when the player is aiming their weapon. Lowering the weapon is likely to affect the laser position and precision. You can test this quickly by replacing the (cameraview == "GUNNER") with (true) and engaging freelook.

Will take a closer look in the weekend, and I might be able to improve performance on my own implementation as well. Talk to you later :)

Edited by sjakal

Share this post


Link to post
Share on other sites

_perfect_start = [0.12,0.57,0.52];
_timestamp = diag_tickTime;

while{true} do
{
 while {player isIRLaserOn currentWeapon player} do
 {
  if (cameraView == "GUNNER") then
  {
   _txtXhair = "";
   _posXhair = positionCameraToWorld [0, 0, 10000];

   _dir = player weaponDirection (currentWeapon player);
   _corr = [(_perfect_start select 0), (_perfect_start select 1), ((_dir select 2) * (_perfect_start select 2))];
   _posLaser = AGLToASL (player modelToWorld _corr);
   _posXhair = _posLaser vectorAdd (_dir vectorMultiply 4999);

   _hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player,objNull, true, 1, "GEOM","NONE"];

   if (0 < count _hitLaser) then
   {
    _posXhair = (_hitLaser select 0) select 0;
    _txtXhair = str(round(_posLaser distance _posXhair));
   };
   _posXhair = ASLToAGL _posXhair;

// correction should be calculated every second
   _time = diag_tickTime;
   if((_timestamp + 1) < _time) then
   { 
    _timestamp = _time;

//first test if screenToWorld provides correct values and if _posXhair has a different value
    _perfect_end = screenToWorld [0.5,0.5];
    _verify_STW = screenToWorld [0.5,0.499];
    _verify = _perfect_end distance _verify_STW;
    _err = _perfect_end distance _posXhair;
    if((_verify > 0.04) and (_err > 0)) then
    {

// reverse calculation of perfect start point with use of perfect end point

     _reverse_start = _perfect_end vectorAdd (_dir vectorMultiply -5000);
     _array = lineIntersectsSurfaces [_perfect_end, _reverse_start, objNull,objNull, false, 100, "GEOM","NONE"];

     if (0 < (count _array)) then
     { 
      {  
       if(((_x select 2) == player) or ((_x select 3) == player))  then
       {   
        _perfect_start = player worldToModel ASLToAGL(_x select 0);
        if ((_dir select 2) != 0) then
        {
         _perfect_start = [(_perfect_start select 0), (_perfect_start select 1), ((_perfect_start select 2)/(_dir select 2))];
        };
       };
      } forEach _array;
     };
    }; // check STW and error end
   }; // time check end
  drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [0,0.2,0,1], _posXhair, 1, 1, 0, _txtXhair, 0, 0.02, "TahomaB", "center", false];
  }; // gunner check end
 sleep 0.03;
 }; // while IR on end
sleep 5;
}; 

Status: running but very buggy now.

 

In this version u can see the crosshair only above a distance of 250 m because auto correction is not working until now. (If it ever will?)

 

Main problem is that I cant get an object or its position from lineintersects return array (line 44).

It is always returning only 1 element even if their r some objects in the way.

That element is objNull and the parent object is objNull, too. 

 

Im tired now. goin to bed.

Edited by sarogahtyp

Share this post


Link to post
Share on other sites

Ok guys I think I got it working. But it needs some more optimizing I think.

Its useless below 10 meters too but the crosshair is nearly in the center above 10 m.

I think we should forbid measuring below 50 meters to avoid strange behavior.

But there are some delays sometimes and that shoul be optimized.

Also I didnt test with other weapons but i think it should work for it.

_perfect_start = [0.12,0.57,0.52];

while{true} do
{
 while {player isIRLaserOn currentWeapon player} do
 {
  if (cameraView == "GUNNER") then
  {
   _txtXhair = "";
   _posXhair = positionCameraToWorld [0, 0, 10000];

   _dir = player weaponDirection (currentWeapon player);
   _corr = [(_perfect_start select 0), (_perfect_start select 1), (_perfect_start select 2)];

   _posLaser = AGLToASL (player modelToWorld _corr);
   _posXhair = _posLaser vectorAdd (_dir vectorMultiply 4999);

   _hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player,objNull, true, 1, "GEOM","NONE"];

   if (0 < count _hitLaser) then
   {
    _posXhair = (_hitLaser select 0) select 0;
    _txtXhair = str(round(_posLaser distance _posXhair));
   };

    _perfect_end = AGLToASL screenToWorld [0.5,0.5];

// reverse calculation of perfect start point with use of perfect end point

     _reverse_start = _perfect_end vectorAdd (_dir vectorMultiply -5000);
     _array = lineIntersectsSurfaces [_perfect_end, _reverse_start, objNull,objNull, false, 100, "GEOM","NONE"];

     if (0 < (count _array)) then
     { 
      {  
       if((_x select 2) == player)  then
       {   
        _perfect_start = player worldToModel ASLToAGL(_x select 0);
       };
      } forEach _array;
     };

  _posXhair = ASLToAGL _posXhair;
  drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [0,0.2,0,1], _posXhair, 1, 1, 0, _txtXhair, 0, 0.02, "TahomaB", "center", false];
  }; // gunner check end
 sleep 0.03;
 }; // while IR on end
sleep 5;
};

Status: running with some minor bugs.

EDIT: I ve tested some other weapons now and it works. I think the laserpointer has the same position at every weapon cause i found no weapon where I noticed a different position.

Share this post


Link to post
Share on other sites

Hmm, busy weekend so I haven't had time for testing yet, sorry. Maybe if you have a demo mission I can simply load up?

I updated my own code example above to avoid some confusion over PositionAGL vs PositionASL and slightly improve performance. Turning on the IR laser in my own demo mission costs me roughly 2 frames per second now. I also tried updating the laser position in one loop 20 times per second and redrawing it on screen separately via the eventhandler each frame but did not notice any performance improvement. Of course this slowdown matters most during AI heavy 12v12 firefights or more where FPS is already below 45 without the script running.

 

PS: My demo mission has some other features beside the IR laser rangefinding (see the Briefing section on the Map screen) that are likely to affect the FPS also; Dynamic View Distance increases terrain draw distance and lowers object draw distance the higher up you are flying, and Augmented Reality shows target icons if you wear tactical goggles and a GPS receiver. The Stealth AI part in particular is work in progress; dragging dead bodies has not yet been implemented. Slot up as SUPPORT 1 Squad Leader for Zeus access.

Share this post


Link to post
Share on other sites

i m not at home so i cant upload anything now.

you could just spawn my code from init.sqf and add if(hasInterface) above it.

you can delete line 13 cause its useless. but u have to substitute _corr with _perfect_start in line 15 then.

i ve not realy thought about fps optimizing until npw but i think we should use an eventhandler for drawing as described in draw3dicon biki page.

Share this post


Link to post
Share on other sites
Added event handler for drawing and a barrier to avoid drawing below 20 meters. its tested and running


_perfect_start = [0.18,1,1];
_DRAW_EH_ID = 0;
_DRAW_EH_ADDED = false;
 
while{true} do
{
 while {player isIRLaserOn currentWeapon player} do
 {
  if (cameraView == "GUNNER") then
  {
   _txtXhair = "";
   _posXhair = positionCameraToWorld [0, 0, 10000];
 
   _dir = player weaponDirection (currentWeapon player);
   _posLaser = AGLToASL (player modelToWorld _perfect_start);
   _posXhair = _posLaser vectorAdd (_dir vectorMultiply 4999);
 
  _hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player,objNull, true, 1, "GEOM","NONE"];
 
   if (0 < count _hitLaser) then
   {
    _temppos = (_hitLaser select 0) select 0;
 
    if((_posLaser distance _temppos) > 20) then
    {
     _posXhair = _temppos;
     _txtXhair = str(round(_posLaser distance _posXhair));
    };
   };
 
    _perfect_end = AGLToASL screenToWorld [0.5,0.5];
 
// reverse calculation of perfect start point with use of perfect end point
 
     _reverse_start = _perfect_end vectorAdd (_dir vectorMultiply -1000);
 
     _array = lineIntersectsSurfaces [_perfect_end, _reverse_start, objNull,objNull, false, 100, "GEOM","NONE"];
 
     if (0 < (count _array)) then
     { 
      {  
       if((_x select 2) == player)  then
       {   
        _perfect_start = player worldToModel ASLToAGL(_x select 0);
       };
      } forEach _array;
     };
 
   _posXhair = ASLToAGL _posXhair;
 
  drawpos = _posXhair;
  drawtxt = _txtXhair;
 
   if(!_DRAW_EH_ADDED) then
   {
    _DRAW_EH_ADDED=true;
    _DRAW_EH_ID = addMissionEventHandler ["Draw3D", {
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [0,0.2,0,1], drawpos, 1, 1, 0, drawtxt, 0, 0.02, 
 
"TahomaB", "center", false];
}];
 
   };
  }; // gunner check end
 sleep 0.03;
 }; // while IR on end
 if(_DRAW_EH_ADDED) then
 {
  _DRAW_EH_ADDED=false;
  removeMissionEventHandler["Draw3D", _DRAW_EH_ID];
 }; 
sleep 5;
};


Share this post


Link to post
Share on other sites

Okay sjakal, u r not a speaker, well? doesnt matter so i can flood that topic :-)

 

What I did now is to take the advices from those nice guys at this topic

Translating Direction Vector From World Space to Model Space

and created a fast way for IR laser position correction which is done 30 times per second now.

The reverse calulation method is now used only 3 times per second. I think now the code should have very good performance.

 

What about the behavior? You can kneel, crouch, lean and if u disable the gunner only view, then u can see the crosshair accordingly moving with the bouncing weapon while running. :-D  use 3rd view for that fun.

Thats very cool man.

 

Test it please and tell me what u think about it.

 

And here it comes bro:

 

 

_perfect_start = [0.18,1,1];
_time = 0;
_DRAW_EH_ID = 0;
_DRAW_EH_ADDED = false;
_old_dir = player weaponDirection (currentWeapon player);
_new_dir = _old_dir;

while{true} do
{
 while {player isIRLaserOn currentWeapon player} do
 {
  if (cameraView == "GUNNER") then
  {
   _txtXhair = "";
   _posXhair = positionCameraToWorld [0, 0, 10000];
   _dir = player weaponDirection (currentWeapon player);
   _posLaser = AGLToASL (player modelToWorld _perfect_start);
   _posXhair = _posLaser vectorAdd (_dir vectorMultiply 4999);
   _hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player,objNull, true, 1, "GEOM","NONE"];
   if (0 < count _hitLaser) then
   {
    _temppos = (_hitLaser select 0) select 0;
    _dist = _posLaser distance _temppos;
    if(_dist > 20) then
    {
     _posXhair = _temppos;
     _txtXhair = str(round(_posLaser distance _posXhair));
    };
   };
   if(_time < diag_tickTime) then
   {
    _time = diag_tickTime + 0.333;
//correction of IR laser position with reverse calculation from perfect end point (slow way is dann 3 times per second)
    _perfect_end = AGLToASL screenToWorld [0.5,0.5];
    _reverse_start = _perfect_end vectorAdd (_dir vectorMultiply -5000);
    _array = lineIntersectsSurfaces [_perfect_end, _reverse_start, objNull,objNull, false, 100, "GEOM","NONE"];
     if (0 < (count _array)) then
     { 
      {  
       if((_x select 2) == player)  then
       {   
        _perfect_start = player worldToModel ASLToAGL(_x select 0);
       };
      } forEach _array;
     };
    }
    else // time check
    {
//correction of IR laser position with weapon angle (fast way is done 30 times per second) 
     _weaponpos = player selectionPosition "RightHandMiddle1";
     _new_dir =  (player worldToModel ((player modelToWorld _weaponpos) vectorAdd _dir)) vectorDiff _weaponpos;
     _perfect_start = _perfect_start vectorAdd (_new_dir vectorDiff _old_dir);    
     _old_dir = _new_dir;
    };
   _posXhair = ASLToAGL _posXhair;
   drawpos = _posXhair;
   drawtxt = _txtXhair;
   if(!_DRAW_EH_ADDED) then
   {
    _DRAW_EH_ADDED=true;
    _DRAW_EH_ID = addMissionEventHandler ["Draw3D", 
    {
     drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [0,0.2,0,1], drawpos, 1, 1, 0, drawtxt, 0, 0.02, "TahomaB", "center", false];
    }];
   };
  }; // gunner check end
 sleep 0.033;
 }; // while IR on end
 if(_DRAW_EH_ADDED) then
 {
  _DRAW_EH_ADDED=false;
  removeMissionEventHandler["Draw3D", _DRAW_EH_ID];
 }; 
sleep 5;
};

 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×