Jump to content
sjakal

Weapon IR Laser Ranging

Recommended Posts

Disregarding if this is realistic or not for the year 2035 where ArmA III occurs, how would I go about measuring distance along my rifle's IR laser attachment while active? I already have an eventhandler for drawing text/icons on-screen (or I could use a simple hint message), so all I really need is:

  1. Find primaryWeapon selectionPosition + direction of the IR laser emitter if my weapon has one attached.
  2. Determine if the attachment is currently activated (there should be NO rangefinding while laser is OFF).
  3. Imitate the laser's collision with the environment to find the laser's end-point to measure the distance to.

Scripting hints for any of the three points above will be much appreciated, as will references to similar/related posts and answers. Thanks in advance lads/ladettes!

Share this post


Link to post
Share on other sites

That should work but is not tested.

Give feedback please!

/*
    Author: Sarogahtyp (with help from BIki examples)
    
    Parameter(s):
    0: [OBJECT] - Unit with IR laser designator equipped weapon

    Returns:
    [NUMBER] - distance to object or 4999 if laser disabled or not pointing to an object
*/

params [["_bob",objNull,[objNull]]];

//_bob = _this select 0;   that was bullsh*t i thought I deleted it

_maxdist = 4999; //laser designators range (lineIntersectsSurfaces has a hardcoded limit of 5000 meters)
_distance = _maxdist;

if (isIRLaserOn currentWeapon _bob) then
{
 _beg = eyePos _bob;
 _end = (_beg vectorAdd (_bob weaponDirection currentWeapon _bob vectorMultiply _maxdist));

 _array = lineIntersectsSurfaces [_beg , _end, _bob, objNull, true, 1, "GEOM","NONE"];

 if((count _array) > 0) then
 {
  _endL = _array select 0;
  _distance = _beg distance _endL;
 };
};

_distance
  • Like 2

Share this post


Link to post
Share on other sites

Haha, it works! Excellent answers in both posts, thanks! I can now draw a crosshair where the laser is pointing, indicating range to target. I also have some logic in place to make sure this only happens if I have tactical or VR goggles equipped, but here is the basic "Draw3D" eventhandler code:

_txtXhair = "";
_posXhair = positionCameraToWorld [0, 0, 10000];
if (player isIRLaserOn currentWeapon player) then
{
	_posLaser = eyePos player;
	_posXhair = _posLaser vectorAdd (player weaponDirection currentWeapon player vectorMultiply 5000);

	_hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player];
	if (0 < count _hitLaser) then
	{
		_posXhair = (_hitLaser select 0) select 0;
		_txtXhair = str(round(_posLaser distance _posXhair));
	};
	_posXhair = ASLToAGL _posXhair;
};
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [1, 1, 1, 0.50], _posXhair, 1, 1, 0, _txtXhair, 0, 0.02, "TahomaB", "center", false];
All I am missing now is regarding question 1. As far as I know eyePos returns your eyes' world position but what I need is the laser pointer or weapon muzzle's position, either in model or world space. My best bet for finding this is selectionPosition at the moment, but I struggle to find the correct selectionName matching my current weapon's muzzle.

Currently the crosshair is offset slightly since the line is emitted from my character's eyes along the weapon's aim direction, instead of from the weapon's muzzle/laser emitter along its aim direction. The offset is easy to spot with NVGs at night while aiming the weapon and squeezing off a round; the crosshair is somewhat off to the side of your weapon sight reticule.

Bonus points to anyone who is able to solve this final detail for question 1, then the solution will be perfect! Thanks again for the excellent example and answers already provided.

Share this post


Link to post
Share on other sites

sarogahtyp,

Weapons have "laser pos" memory points and I guess topic starter was referring to getting its exact position. Perfectionism here =) Unfortunately I could not find a way of getting it for player's current weapon.

Either use _this select 0 or params, not both.

You can search for intersections of continuation of the line to go further than 5000m (if really needed). I'd say overall distance sqrt(2)*worldSize would be enough for everyone.

Anyway, good work here.

Share this post


Link to post
Share on other sites

I think the problem with primaryWeaponItems or weaponAccessories is they simply return the classname of the weapon attachment, and not the model's memory point for the laser emitter. I tried this in the in-game debug console, but all I got was position [0, 0, 0]:

systemChat str(player selectionPosition "acc_pointer_IR")
I tried looking at Animations while in-game but as far as I know it only shows the animation names, and does not show the various memory points of my current character model. I would probably have to inspect the actual player/weapon/laser in a model tool/editor to find the memory point. Once that is found, hopefully its name can be used for the selectionPosition.

Share this post


Link to post
Share on other sites

you can get the selectionName with the Dammaged EH its a return value of it. Got that Info from here: selectionPosition

You can get selectionName for unit, i.e. some part of unit's model which was hit. I highly doubt unit can be hit in "laser pos". So the problem is to

1. get memory point "laser pos" location of weapon's model space (how to do it in game?)

2. get weapon's location (probably "Weapon" selectionName will do) and weapon's directions: direction vector (weaponDirection scripting command) and up-vector (how to do it in game?).

3. when weapon position, weapon direction and weapon up vector are acquired, you can transform "laser pos" location (or any other point) from weapon model space to unit's model space (therefore to world space too).

 

Not sure, but "laser pos" is a place on weapon where to place attachment, not the point where laser beam hits from. One should probably analyse attachment's model too :D

Share this post


Link to post
Share on other sites

Yeah, I've been struggling with exactly that. Looking at the IR laser at night on close range walls/targets, it seems the endpoint of the IR laser has no relation to where your optics or iron sights are zeroed, so I get the feeling my best bet is using the muzzle/sights/optics as point of origin instead of the laser emitter.

I read somewhere that weapons or their sight attachments have an "eye" or "opticsView" memory point, but that implies I somehow need to get a reference to the weapon or attachment model in the Cfg hierarchy, starting from the player character.

 

Alternatively I could just start the laser from the current weapon muzzle position in world or player model space, but again I struggle to find that position. Hopefully this is somewhat easier and already possible using standard OPF/ArmA commands, so I can avoid traversing Cfg/model hierarchies on subordinate weapons/attachments.

 

The "Weapon" memory point on the player is a very good suggestion, although it seems to be quite heavily offset from where the weapon actually is. Testing this as Zeus after I kill an AI soldier to drop his weapon, I think the "Weapon" memory point is about ½m to the side of the rifle when it lies flat on the ground. Perhaps I could hardcode an offset from here into the center of the weapon. I will investigate this further tomorrow.

 

Thanks again for the tips and help you've given already guys! This is indeed just perfectionism or nitpicking  :)

Share this post


Link to post
Share on other sites

Quick morning update. According to this reddit it is currently impossible to get a man's current weapon object. It is easy to find the weapon classname, but impossible to get a reference to the weapon object itself.
 
One tedious fallback option then is traversing the configFile hierarchy for currentWeapon and the "acc_pointer_IR" laser to find their proxy/memory point offsets from the weapon/proxy point of origin, and then use their combined offsets from the player selectionPosition "Weapon".

 

To avoid such tedium, a final alternative is simply hardcoding an offset from player selectionPosition "Weapon", but this has obvious disadvantages; you have to hardcode different offsets for each weapon in the game, and any possible modded weapons you wish to support in the future.

 

Guess I'll have to further investigate the cfg hierarchy but I doubt it is even possible to find the proxy/memory point offsets in there. Oh well... You've gotten me very far guys, thanks!

Share this post


Link to post
Share on other sites

One tedious fallback option then is traversing the configFile hierarchy for currentWeapon and the "acc_pointer_IR" laser to find their proxy/memory point offsets from the weapon/proxy point of origin, and then use their combined offsets from the player selectionPosition "Weapon".

Memory points' coordinates are in models, not in configs. More tedious and harder to automatize.

 

To avoid such tedium, a final alternative is simply hardcoding an offset from player selectionPosition "Weapon", but this has obvious disadvantages; you have to hardcode different offsets for each weapon in the game, and any possible modded weapons you wish to support in the future.

I considered such possibility while writing my previous post. You will need dynamic up-vector of weapon for cases when you lean right/left while shooting around the corner. If this is not taken into account, then you laser's start point will (visually) lean in opposite direction and always keep vertical (or whatever offset it will have) relative to "Weapon" selectionPosition.

So yeah. Point and two (non-collinear) vectors: this is what you need to fully define 3d coordinate system (or a matrix to transform to/from).

Share this post


Link to post
Share on other sites

okay, i think i cant help with the start position of that range finding thing but I ve another problem.
 
I used sjakals script and what I dont want is that the range and the crosshair is drawn when the player is not in the sights view by clicking right mouse button.

How do I check if the player uses the weapons sights?

Share this post


Link to post
Share on other sites

I got it with that check:

 if ((player isIRLaserOn currentWeapon player) and (cameraView == "GUNNER")) then

Share this post


Link to post
Share on other sites

Ok, I would say lets do a manual correction for that memory point problem.

if we do a manual correction for an average weapon (average in size and IR lasers mount point) then we have a quite good solution I think.

 

I dont know much about the different weapons in Arma 3 so I could use a hint which weapon we should take.

 

I already began with those manual correction but its far away from being perfect:

 

   _temppos = player selectionPosition "pilot"; // thats the same as eyePos.
   _posLaser = AGLToASL (player modelToWorld ( [((_temppos select 0)+0.05), ((_temppos select 1) + 0.1), ((_temppos select 2) - 0.05)]));

Now I ve to go to work and so I have no time to optimize it more... maybe one of u guys could.

Share this post


Link to post
Share on other sites

At work myself so will follow up later today. Quick thoughts: Using "pilot" position may give issues similar to eyePos if player lowers their weapon while laser is active. The "Weapon" memory point avoids this potential issue.

I also totally agree; investigating models is way too tedious so a good hardcoded default offset is the way forward, with special offsets for special weapons as needed.

Thanks for the rapid responses guys!

Share this post


Link to post
Share on other sites

Okay, we can start that with "Weapon" memory point even if I will not let the crosshair and range show when player is not using sights.

 

Another thing what came in my mind is to add a laser target at end position of the IR laser.

 

So we should implement _target = "LaserTargetW" createVehicle (getpos player);  and set its pos continueously as long as the IR laser is activated.

 

Now back to the memory point. BI is doing the same as we do with the laser itself and it is pointing always to the correct position.

They must have a way to do that without the name of the memory point because every modder can name the memory points as he likes for his custom weapon but the IR laser is always at correct position, isnt it?

So we have to think about how is BI doing that?

Share this post


Link to post
Share on other sites

what about

getPosASL nearestObject [player, "acc_pointer_IR"];

did you guys already try that?

Edited by sarogahtyp

Share this post


Link to post
Share on other sites

Good idea with spawning a lasertarget, and nice find on checking player is aiming!

I tried some variations of nearestObject in Debug Console, sadly to no avail, always resulting in <NULL-OBJECT> most likely since the laser attachment has no logical game object but only a model.

systemChat str(aimPos player nearestObject "acc_pointer_IR")
So it seems hardcoded offsets are still the most valid option, but as pedeathtrian mentions we need two non-colinear and weapon-relative direction vectors to do that, and so far we only have weaponDirection. The eyeDirection vector might be non-colinear, but it is not weapon-relative. A shell casing eject direction would be a good alternative, if such is accessible via scripting commands. Oh! Or maybe a vector from "Weapon" to the "righthand" memory point since it is practically glued to the weapon at most times anyway.

But yeah, the optimal solution of course is somehow reverse engineering the in-game laser beam start or end point.

_posXhair = ASLToAGL _posXhair; // insert the two code lines below here
_posLaser = ASLToAGL _posLaser;
drawLine3D [_posLaser, _posXhair, [1,1,1,1]];
PS: Add the lower two lines above to my previous code to draw the line simulating the laser beam on-screen if you have not done so already, it makes visualizing and offsetting the positions easier.

Share this post


Link to post
Share on other sites

ok, i think now i have the solution. the key is not the start but the end position. we should use

end = screenToWorld [0.5, 0.5];

position format is AGL

but that only is useful if u forbid range finding when player is not aiming

Share this post


Link to post
Share on other sites

Alright, I think I finally have SOMETHING! Try this code in place of my previous examples:

//Default to 5000m in front of camera if laser is disabled
_arXhair = positionCameraToWorld [0.000000, 0.000000, 5000.000000];
_arXtext = "";
_arAngle = 45;

if (player isIRLaserOn currentWeapon player) then
{
	_posXhair = AGLToASL (player modelToWorld (player selectionPosition "Weapon"));

	//Create the three axes from the player character model weapon memory point
	_right = _posXhair vectorFromTo AGLToASL (player modelToWorld (player selectionPosition "righthand"));
	_forward = player weaponDirection currentWeapon player;
	_up = _right vectorCrossProduct _forward;
	_right = _forward vectorCrossProduct _up;

	//Offset the laser start position using the three axes created above
	_posLaser = _posXhair;
	{
		//This default LaserOffset below seems to work OK
		if (isNil "LaserOffset") then
		{
			_posLaser = _posLaser vectorAdd (_x vectorMultiply ([0.700000, 0.770000, 0.100000] select _forEachIndex));
		}
		else
		{
			_posLaser = _posLaser vectorAdd (_x vectorMultiply (LaserOffset select _forEachIndex));

			//These three axis and offset drawlines can be hidden when no longer needed
			if (_forEachIndex == count LaserOffset - 1) then
			{
				drawLine3D [ASLToAGL _posXhair, ASLToAGL (_posXhair vectorAdd _right), [1,0,0,1]];
				drawLine3D [ASLToAGL _posXhair, ASLToAGL (_posXhair vectorAdd _forward), [0,1,0,1]];
				drawLine3D [ASLToAGL _posXhair, ASLToAGL (_posXhair vectorAdd _up), [0,0,1,1]];
				drawLine3D [ASLToAGL _posXhair, ASLToAGL _posLaser, [1,1,0,1]];
			};
		};
	}
	forEach [_right, _forward, _up];

	//Find the laser end position by using a 5000m line intersect check
	_posXhair = _posLaser vectorAdd (_forward vectorMultiply 5000.000000);
	_hitLaser = lineIntersectsSurfaces [_posLaser, _posXhair, player];
	if (0 < count _hitLaser) then
	{
		_arXhair = ASLToAGL ((_hitLaser select 0) select 0);
		_arXtext = str(round(_arXhair distance ASLToAGL _posLaser));
	}
	else
	{
		_arXhair = ASLToAGL _posXhair;
		_arXtext = "";
	};
	_arAngle = 0;
};
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\weapon_ca.paa", [1, 1, 1, 0.5], _arXhair, 1, 1, _arAngle, _arXtext, 0, 0.02, "TahomaB", "center", false];
Then go in-game, activate the weapon IR laser, and then Local Exec the following via Debug Console:

LaserOffset = [0.700000, 0.770000, 0.100000]
You should then see a red, green, blue and yellow guideline somewhere near your player character when in 3rd person, and your crosshair should now be roughly at where the IR laser is pointing. Using the red, green and blue guides, you can now adjust your offset in real-time via the in-game Debug Console until you are satisfied. Notice how the yellow line indicates your offset from the "Weapon" position.

Granted, the axes do not align perfectly with the weapon's right and up axes, but it should still be an improvement over eyePos since that was not weapon-relative but this new position seems to follow the weapon around even when you peek around corners. Once you are satisfied the drawLine3D commands can be commented out to hide the visual guides and increase FPS slightly. Experiment as needed and please post your findings and preferred LaserOffset :)

Edited by sjakal

Share this post


Link to post
Share on other sites

I dont know, I m to tired to test it but here is my solution. 

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

   _dir = player weaponDirection (currentWeapon player);

//EDIT: substituted following line as it is a better solution then

//   _corr = ([0.12,0.57,0.52] vectorAdd [0,0,1.5*(_dir select 2)]);

   _corr = [0.12,0.57,0.52 * (_dir select 2)];

   _temppos = player selectionPosition "pilot";
   _posLaser = AGLToASL (player modelToWorld (_temppos vectorAdd _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;

  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];
  };
 sleep 0.03;
 };
sleep 5;
};
Edited by sarogahtyp

Share this post


Link to post
Share on other sites

okay, i tested both solutions a bit and it turns out they both have advantiges and disadvantages.

I tested with a scope where I now define the horizontal line as x-axis and the vertical line as y-axis to let u know what i found out.
I used this scope: this addPrimaryWeaponItem "optic_SOS";
and that weapon: this addWeapon "arifle_MXM_F";

there are markers at these lines which I used to get a distance when the crosshair reaches em. I used the inner markers for that.

Your solution:

crosshair reached inner x-axis marker at a distance of 7 m
crosshair reached inner y-axis marker at a distance of 10 m

My solution:

crosshair reached inner x-axis marker at a distance of 130 m
crosshair reached inner y-axis marker at a distance of 9 m

So ur solution is much more precise but I ve the problem with your code that it seems to be slow. The crosshair is blinking very much at my slow PC. I tried to compensate that by retracing the crosshair between calculations and it gets a bit better but it is still blinking.

EDIT: i did not test leaning, kneeling and crouching. i assume that my code should cover it cause i use eye position. i dont know if yours do.

Edited by sarogahtyp

Share this post


Link to post
Share on other sites

Now I substituted this line of my code:

_corr = ([0.12,0.57,0.52] vectorAdd [0,0,1.5*(_dir select 2)]);

with that one:

_corr = [0.12,0.57,0.52 * (_dir select 2)];

and now it is as precise as your solution:

 

crosshair reached inner x-axis marker at a distance of 9 m

crosshair reached inner y-axis marker at a distance of 10 m

I prefer my code now for the much better performance.

Share this post


Link to post
Share on other sites

on my way to work now and i m thinking about the hard coded correction values.

now i think its possible to implement an auto correction algorithm which should work with every weapon and would find better values as we are able to. i will work on it.

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

×