Facepunch / garrysmod-issues

Garry's Mod issue tracker
141 stars 56 forks source link

EyePos() global function does not give reliable output #2516

Open NeatNit opened 8 years ago

NeatNit commented 8 years ago

As discussed on the forum: https://facepunch.com/showthread.php?t=1497739&p=49957704&viewfull=1#post49957704

Video of the issue: I bound a key to print the output to the chat. bind - "lua_run_cl chat.AddText('Global: ', tostring(EyePos()), '\nPlayer: ', tostring(LocalPlayer():EyePos()),'\n')" Format is: Global: EyePos() Player: LocalPlayer():EyePos()

It seems that the EyePos() vector gets updated every time a prop is spawned: https://www.youtube.com/watch?v=CoPzV2AMooU

NeatNit commented 8 years ago

More thorough video (you can ignore the old one): https://youtu.be/Id4hcxmEVXE

Watch in double speed (via youtube's gear icon menu) since it's a little boring otherwise.

ghost commented 8 years ago

Yup, just ran into this issue. On my listen server while in a vehicle global EyePos() returns an incorrect position.

Same thing, I have an audio stream playing, with it's position set to EyePos(). It sets the position to a random one, til I spawn a prop, then it updates.

robotboy655 commented 8 years ago

EyePos() is supposed to be used in rendering hooks. For other uses, use Player:EyePos() or whatever.

ghost commented 8 years ago

Is LocalPlayer():EyePos() not the location of the player's eye attachment though? And also I use it in a rendering hook, it just stopped working in a recent update.

It seems to not be updating at all until a prop is spawned. The whole reason I looked into this is because I was testing an old addon of mine that always worked, and noticed EyePos() suddenly stopped returning correct values. Like NeatNit says it doesn't update at all til you spawn a prop.

Edit: Just tested with LocalPlayer():EyePos(), doesn't do what I need it to. Please look into this because it's not functioning like it used to. The video also pretty clearly shows it's not behaving as it should. And I am positive this wasn't a problem before because I have a few different addons that use it, that all don't function anymore.

I'll make a video of a quick example although I think the OP's should be enough, because I really do need this fixed.

Acecool commented 8 years ago

If I recall correctly, EyePos / EyeAngles is the position of the camera so the camera can be someplace other than where the player is, and EyePos / EyeAngles should return that location. I'd have to double-check, it's been a while since I messed with camera code...

But, make sure you're checking the positions properly and know what the positions mean.. ie Player GetPos is at the players feet while the camera pos is where the camera is while the model eye attachment is something else... etc...

ghost commented 8 years ago

I know what EyePos() is supposed to do, I've been using it forever. It's not behaving like it used to.

It's returns the client's view point. But it doesn't I'll send you a video. sec.

Acecool commented 8 years ago

My mistake then... I'll see about replicating on my end.

robotboy655 commented 8 years ago

It behaves like you think it should on my end, so there's a condition that either breaks it or makes it work. There were no changes to the EyePos() function, so it most likely been always like that.

ghost commented 8 years ago

What sort of changes? I'd like to know so i can figure out what I can use as an alternative to EyePos().

And definitely hasn't always been like that, or I wouldn't have decided to look into it today. The system has worked for the past few years.

Lets say I'm setting a 3d audio stream's position to EyePos() for years I was able to do that fine. (And no, it's not improper because it's much less expensive than killing the 3d stream, and creating a new non 3D one when a player enters a vehicle, and doing he opposite when the player exits.) I can't do that anymore, because EyePos() doesn't change til I spawn a prop.

If the changes made to EyePos() break that functionality they should definitely be un--done unless they have some sort of massive benefits... because you definitely should be-able to do that.

And no, you can't use LocalPlayer():EyePos() because it'd set the audios position to your player model's eye position.

Regardless of what I'm doing with EyePos() it should do what it says it does, return the players view-point calculated by CalcView. It currently doesn't. And as I said, this addon of mine is old, it's worked for years.

robotboy655 commented 8 years ago

I made a typo, there were NO changes to EyePos()

ghost commented 8 years ago

Well something has definitely caused it's behavior to change, please look into it. I'm not lying to you, lol.

The OPs video is a perfect example, EyePos() used to always be correct. Now it only updates after spawning a prop. Was CalcView itself changed? Once this video I have is done uploading I'll post it quickly. It shows that EyePos() doesn't update the audio stream's position til after I spawn a prop. It never used to be like this til March of this year.

Sorry for the delay on the video, my upload speeds are bad. Youtube says 100 minutes on the video. But yeah it'd be really cool if you'd look into this, because it's not behaving as it used to, nor like it's supposed to.

Also I should add, it worked properly the last time I tested it which was December 18th 2015. So it has to have been broken sometime between then and now. I didn't just stumble upon this and decide to comment, I noticed this stopped behaving the way it used to well playing around with an older addon of mine (December 2015 old) and googled it to see if anyone else has ran into the same issue, clearly others have, like NeatNit.

This addon is one I wrote, and I've used on my servers for the last few years, it never was broken I am 110% sure. This is recent, I just didn't notice sooner because just today I started working on my Garry's Mod things again.

ghost commented 8 years ago

https://www.youtube.com/watch?v=dqf5HLFuOew&feature=youtu.be

EyePos() "returns the position of the players view point calculated by GM:CalcView. ", clearly it's not doing that as the video shows (Unless you have the lamp on? lol...). When the OP moves his camera around, EyePos()'s return value doesn't change. When I move my camera around the vehicle, EyePos's return value doesn't change. The only time EyePos's return value changes is when we spawn props. You can't say that's doing what it's supposed to be doing.

Pretty certain that EyePos() isn't supposed to rely on it returning the correct value only after spawning a prop, lol. That function should always return the correct value... and before January 2016 it did.

OPs video is definitely better, but they both make it pretty clear EyePos() is broken..

willox commented 8 years ago

There was probably a call to EyePos every frame in an older version of the game that was removed at some point. The best solution is probably going to be updating EyePos' value internally at the end of each frame.

ghost commented 8 years ago

Yeah, it's updated to the position of the players view point calculated by CalcView. Just should be fixed in Garry's Mod itself.

CapsAdmin commented 8 years ago

If you're looking for an alternative in the meantime you could use the RenderScene hook. It returns: "Vector origin, Angle angles, number fov" which is equivalent to "EyePos(), EyeAng(), GetConVarNumber("cl_fov")"

Bo98 commented 8 years ago

The EyePos call that was removed is probably the one that was in ENT:BeingLookedAtByLocalPlayer in base_gmodentity.

NeatNit commented 8 years ago

The EyePos call that was removed is probably the one that was in ENT:BeingLookedAtByLocalPlayer in base_gmodentity.

No, that was one of the non-render calls which suffered from the inconsistency - this is demonstrated in my video since it used to decide whether to draw the little tooltip thing. It gets updated by accident when a lamp enters the screen because the lamp's draw function uses EyePos.

Bo98 commented 8 years ago

Just noticed when this issue was created. Thought it was the last update and not a previous one.

willox commented 8 years ago

I'll give this at least some level of defined behaviour and also make sure EyeVector and EyeAngles update at the same time

ghost commented 8 years ago

Thanks. But can you please just give it it's original behaviour back? It'd be very easy to do and the wiki makes it very clear on how it's supposed to behave (and how it used to behave.). Every frame EyePos() returns the view point that was calculated by GM:CalcView. it'd be very easy to restore this to it's original behavior and I really hope you do.

willox commented 8 years ago

EyePos never worked that way

ghost commented 8 years ago

It most likely did, because I had a few systems that relied on it working that way. And they used to work, that's why I noticed it was broken in the first place.

And even if it didn't, it used to return the correct view point no matter what, it should do that.

Also, thanks CapsAdmin for the suggestion, ended up doing that.

NeatNit commented 8 years ago

The easiest hack is to just add this:

hook.Add("PreDrawTranslucentRenderables", "FixEyePos", function() EyePos() end)

Fixes EyePos forever ;D

DBotThePony commented 7 years ago

-snip-

see https://github.com/Facepunch/garrysmod-issues/issues/2516#issuecomment-1170837700

FredyH commented 7 years ago

This is still broken and it appears that EyePos(), EyeAngles() and EyeVector() are affected by this bug. The solution by @NeatNit seems to work for all three, if they are all called in that hook. A problem with that solution is that EyePos(), etc. still return wrong values sometimes. A full fix, at least on my end, is changing EyeAngles() to call LocalPlayer():EyeAngles().

Nevertheless, this should still be fixed since it is a nightmare for any developer to debug why EyeAngles is not working correctly in some weird scenarios, when the wiki clearly states that it returns the value of CalcView.

Kefta commented 7 years ago

You still should really not use the functions outside of rendering hooks.

FredyH commented 7 years ago

I am not? And even if I was, that is not documented anywhere on the wiki.

Kefta commented 7 years ago

CalcView isn't in the same category of rendering hooks as any of the *Draw* hooks, but the functions are still bugged either way. Also, I thought the wiki used to have notices about using it outside of rendering hooks, but I could be remembering incorrectly.

mcNuggets1 commented 4 years ago

Doesn't even work in the ENT:Draw functions properly.

jorjic commented 2 years ago

It's probably worth mentioning that it doesn't seem to work with RenderScene -- which is fine since that hook already gives origin, angles, and fov anyways.

MagnumMacKivler commented 2 years ago

As of this comment, it seems to have problems with some rendering hooks too, such as DrawOverlay (I know it's not a 3D rendering hook, but it should still work, no?)

Here's a snippet of code I used to test it.

if CLIENT then
    concommand.Add("debug_spam_eyepos",function()
        debug_spam_eyepos = true
    end)

    hook.Add("DrawOverlay", "debug_spam_eyepos", function()
        if debug_spam_eyepos then
            debug_spam_eyepos = false
            print("EyePos", EyePos(), "EyeVector", EyeVector(), "EyeAngles", EyeAngles())
        end
    end)

    if false then
        hook.Add("PreDrawTranslucentRenderables", "debug_fix_eyepos", function()
            EyePos()
            EyeVector()
            EyeAngles()
        end)
    end

end

Using the command this way seems to either print all zeroes for everything in singleplayer. In multiplayer (tested on a locally hosted server), it shows a value, but it doesn't change regardless of where the player is standing/oriented:

] debug_spam_eyepos 
EyePos  -1081.959229 577.849609 259.356750  EyeVector   0.878752 -0.403805 -0.254433    EyeAngles   14.740 -24.680 0.000
] debug_spam_eyepos 
EyePos  -1081.959229 577.849609 259.356750  EyeVector   0.878752 -0.403805 -0.254433    EyeAngles   14.740 -24.680 0.000
] debug_spam_eyepos 
EyePos  -1081.959229 577.849609 259.356750  EyeVector   0.878752 -0.403805 -0.254433    EyeAngles   14.740 -24.680 0.000

If I enable that workaround in the PreDrawTranslucentRenderables hook, the functions show seemingly correct values again, consistent with the discussion above.

] debug_spam_eyepos 
EyePos  751.179871 -252.253006 257.531250   EyeVector   -0.685355 0.717160 -0.126372    EyeAngles   7.260 133.701 0.000
] debug_spam_eyepos 
EyePos  485.381714 -513.633728 414.910583   EyeVector   -0.827893 0.061943 0.557455 EyeAngles   -33.880 175.721 0.000

So it's good to know that the workaround still works, but why is it suddenly not working in a hook it should work in? The functions worked without issue in DrawOverlay up until recently.

DBotThePony commented 2 years ago

I scratch my last comment here, EyePos() is working correctly, developers are just not expecting it to work this way. EyePos() is actually returning vector of current scene's origin (as clearly stated on wiki), which can (or can not) be position, from where local player might see stuff on screen, depending on when you call it.

Obvious example (without CalcView and RenderScene) where EyePos() can be != LocalPlayer():EyePos() is standing directly under lamp (or putting something in front of it with render hook on it e.g. ENT:Draw), because projected textures are doing shadowmapping (hence redrawing the scene), so a lot of code will be called twice, and second (or first) call to EyePos() will return "weird" result inside render context/hooks.

The same applies to EyeAngles(). That's just very bad function naming, should have been called like RenderOrigin() and RenderAngles().

CapsAdmin commented 2 years ago

I scratch my last comment here, EyePos() is working correctly, developers are just not expecting it to work this way. EyePos() is actually returning vector of current scene's origin (as clearly stated on wiki), which can (or can not) be position, from where local player might see stuff on screen, depending on when you call it.

Obvious example (without CalcView and RenderScene) where EyePos() can be != LocalPlayer():EyePos() is standing directly under lamp (or putting something in front of it with render hook on it e.g. ENT:Draw), because projected textures are doing shadowmapping (hence redrawing the scene), so a lot of code will be called twice, and second (or first) call to EyePos() will return "weird" result inside render context/hooks.

The same applies to EyeAngles(). That's just very bad function naming, should have been called like RenderOrigin() and RenderAngles().

I think it would be less confusing if the functions were chucked into the cam library. Assuming there is an implicit camera view pushed onto whatever the internal stack of the camera library is in various rendering events.