Jump to content
miguel93041

modelToWorld used with worldToScreen = bad position given

Recommended Posts

 
Description
 

When we use the modelToWorld combined with worldToScreen in moving vehicles the position given its not the correct one.
Its caused by a velocity error acting with worldToScreen causing for example:

If our modelToWorld is at [0,2,0] // In a AH-9 helicopter
and we use worldToScreen to transform the coordinates into x,y positions and it give us 1,1... when the vehicle starts to move it changes to 1.5,1.5 or 2,2 and not in 1,1 then we cant use them.

This video is not the bug that im having but it describes how the worldToScreen x,y positions are moving into a bad one.
**https://www.youtube.com/watch?v=NH-2uRq_VEg**

 

STEPS TO REPRODUCE

You can create an script like this one that is an interaction cockpit system.

1. Create a sqf file and name it to pfh_click.sqf

Put this in:

//if the player isn't in a helicopter then we don't run this
if(vehicle player iskindof "Helicopter") then
{
_heli = vehicle player;
if(isNil "button_clicked") then {button_clicked = 0;}; //keeps our key from constantly having an effect - that is, press it once and it won't do anything again until released and pressed again

_controlpos = worldToScreen (_heli modelToWorldVisual [0,2,0]);

if(count _controlpos < 2) then {_controlpos = [-100,-100];}; //if the point is outside of our FOV then set it to something ridiculous
_hinttext = "No Action"; //basic hint to indicate what we're looking at

player sidechat format ["%1",_controlpos]; //debugging - shows position of a control on screen coordinates; the closer to 0.5,0.5, the closer it is to the center of the screen

if(_controlpos distance [0.5,0.5] < 0.025) then {_hinttext = "Toggle Engine";}; //change hint to engine on

if(!(_hinttext == "")) then {hintsilent format ["%1",_hinttext];}; //set our hint text

if(_hinttext == "No Action") exitwith {}; //if no action available then we don't need to do anything so quit

//check to see if our action is within the right parameters and that the key has been pressed, then do something
if(inputaction "User20" > 0.1 && button_clicked == 0 && _controlpos distance [0.5,0.5] < 0.01) then
{
    if(isengineon _heli) then
    {
        player action ["EngineOff", _heli];
    } else {
        player action ["EngineOn", _heli];
    };
button_clicked = 1;
};

//clear our key press if it's not being pressed
if(inputaction "User20" < 0.5) then
{
button_clicked = 0;
};
};

What it does, it takes a model position to a world one then it takes the world position to screen coordinates, so when aim with your screen (0.5,0.5) at that point it hint you "Toggle engine" and if you press the "Custom key 20" it starts the engine.
But if you arent aiming at the point it hint you "No action"

2. Spawn an AH-9 helicopter

3. Put this in the debug console (ESC) and execute it

my_clickaction = compile preprocessFileLineNumbers "pfh_click.sqf"; ["my_clickid", "onEachFrame", "my_clickaction"] call BIS_fnc_addStackedEventHandler;
ADDITIONAL INFORMATION

Its good to have this working correctly so people can create interaction systems

 

Share this post


Link to post
Share on other sites

I assume you are trying to make a vehicle interaction script? I've ran into so many issues with this too and tried so many different things until I finally came up with something with the help of Bohemia! :)

 

In 1.58 they added getCameraViewDirection for us to get the view direction. Now it is possible to calculate the camera vector difference between the helicopter/plane and the camera. Simply create a big array with vectors to check for and see if the vector is near the vector you have defined in the config.

 

One downside: There is no compatibility with trackIR, and if any of the proxy positions change you have to get the new vectors again and enter them in the config.

 

This is part of the code that should help you:

_cameraVector = vectorNormalized ((vectorDirVisual _obj) vectorDiff (getCameraViewDirection player));

You can also do something like this but it's less accurate:

{
	private ["_name"];
	_name = _x select 0;
	_configVec = _x select 4;
	_playerVec = ((vectorDirVisual _obj) vectorDotProduct (getCameraViewDirection player)) - 0.05;
		
	if ((_configVec > _playerVec) && (_configVec < (_playerVec + 0.1))) exitwith
	{
		_interactWith = _name;
	};
} foreach _config;

Demonstration of it can be seen here:

 

 

But like you said, this is only a work around and I would rather see this fixed as well :)

 

-Kane

  • Like 1

Share this post


Link to post
Share on other sites

I assume you are trying to make a vehicle interaction script? I've ran into so many issues with this too and tried so many different things until I finally came up with something with the help of Bohemia! :)

 

In 1.58 they added getCameraViewDirection for us to get the view direction. Now it is possible to calculate the camera vector difference between the helicopter/plane and the camera. Simply create a big array with vectors to check for and see if the vector is near the vector you have defined in the config.

 

One downside: There is no compatibility with trackIR, and if any of the proxy positions change you have to get the new vectors again and enter them in the config.

 

This is part of the code that should help you:

_cameraVector = vectorNormalized ((vectorDirVisual _obj) vectorDiff (getCameraViewDirection player));
Demonstration of it can be seen here:

 

 

But like you said, this is only a work around and I would rather see this fixed as well :)

 

-Kane

Yes I'm trying to make one haha, i've tried different methods with visual commands too but i never get a good way.

I'm actually travelling so i let you know what i get when i arrive at home. Thank You on advantage.

PD: Are You part of project life? I admire your work so hard keep continuing

Share this post


Link to post
Share on other sites

Yes I'm trying to make one haha, i've tried different methods with visual commands too but i never get a good way.

I'm actually travelling so i let you know what i get when i arrive at home. Thank You on advantage.

PD: Are You part of project life? I admire your work so hard keep continuing

 

Thanks! Yeah I'm the co-owner/head dev, I am not around here very often but I stumbled upon your post and thought I'd help you out :)

 

-Kane.

Share this post


Link to post
Share on other sites

Thanks! Yeah I'm the co-owner/head dev, I am not around here very often but I stumbled upon your post and thought I'd help you out :)

 

-Kane.

So what You say is that i can create something like this:

_cameraVector = vectorNormalized ((vectorDirVisual _obj) vectorDiff (getCameraViewDirection player));

_controlpos = worldToScreen (_heli modelToWorldVisual [0,2,0]);

if(_controlpos distance _cameraVector < 0.025) then {_hinttext = "Toggle Engine";}; //change hint to engine on

Or change the _controlpos to create a vector at 0,2,0 and check if the camera direction is near that one?

Share this post


Link to post
Share on other sites

So what You say is that i can create something like this:

_cameraVector = vectorNormalized ((vectorDirVisual _obj) vectorDiff (getCameraViewDirection player));

_controlpos = worldToScreen (_heli modelToWorldVisual [0,2,0]);

if(_controlpos distance _cameraVector < 0.025) then {_hinttext = "Toggle Engine";}; //change hint to engine on

Or change the _controlpos to create a vector at 0,2,0 and check if the camera direction is near that one?

You can make a config with the dot product of two vectors. You have to get the vectors first so in order to that you have to do something like this.

 

1. Get in the pilot seat and aim the center of your camera at a button you want to interact with

2. Enter the following code and save the vector somewhere

(getCameraViewDirection player) vectorDotProduct (vectorDirVisual (vehicle player))

Lets assume I get 0.648556.

 

Now we create a config to define the interaction

Config_CockpitInteractions =
[
	//[Name of text to display, vector, code to check, memory point to display text on]
	["Switch engine",0.648556,{(vehicle player) isKindOf "Some_Classname"},"memoryPoint"]
];	 

Now we can do something like this to check what we are interacting with and then you can draw icons/text using drawIcon3D if you haven't. You can create memory points on the button and use selectionPosition for this in addition to modelToWorld.

private ["_newConfig","_interactWith"];
_obj = vehicle player;

_newConfig = [];
{
	if (call (_x select 2)) then
	{
		_newConfig pushback _x;
	};
} foreach Config_CockpitInteractions;
	
{
	private ["_name"];
	_name = _x select 0;
	_configVec = _x select 1;
	_playerVec = ((vectorDirVisual _obj) vectorDotProduct (getCameraViewDirection player)) - 0.05;
		
	if ((_configVec > _playerVec) && (_configVec < (_playerVec + 0.1))) exitwith
	{
		_interactWith = _name;
	};
} foreach _newConfig;

if (isNil "_interactWith") exitwith {hint "Not interacting with anything"};

hint format ["You are interacting with: %1",_interactWith];

Did not test that at all but I hope you get the point, my own script is a little more complicated though.

 

-Kane.

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

×