Sign in to follow this  
Heelp

How to unproject the center coordinate of my screen to world space?(and why do I need to do that at all? )

Recommended Posts

Guys, I use basic ray casting in order to detect whether I've shot somebody in my first person shooter. But I found out that when I'm really close to the enemy, there are some small inaccuracies ( my crosshair is on the enemy, but there is no collision between the ray and the AABB ).

 

My first step was to actually draw the AABB, and draw the ray that I'm casting on screen in order to try and debug. And to my surprise, the AABB was perfectly fine, but the ray was totally wrong because it doesn't even start from the center of my screen, it starts from some bullsh*t place somewhere around my camera, although I used the camera's position as a startPoint of the ray.

 

Either I'm crazy or the camera position in world space and the center of the screen seem to be two completely different things. I have no idea wtf is happening here. SOMEONE HEEELP!

Share this post


Link to post
Share on other sites
The camera position and the center of the screen are naturally separate places. That's what the "near" value in your projection matrix is for: the distance from the camera to the plane of projection along the view vector.

You're working with a 3D projection. The camera and plane of projection forms a pyramid. Consider i1LDS.png. The plane is the screen and the origin of the rays is the camera position.

That said, you've described very little useful information about your actual problem. The camera location may not really be a problem. Generally the correct way to cast this ray is to start it at the camera position and cast it in the direction of the cross hair, which may not be the same as the camera view direction for off center cross hairs.

So far as the unprojection, you might find guides like http://www.toymaker.info/Games/html/picking.html helpful. (I'm honestly having trouble finding a clear explanation; the Web is saturated these days with tutorials on using engine's builtin screen-to-world functions and few guides on the math. The gist is use the inverse of the projection matrix to convert a coordinate of <x, y, near> in NDC coordinates to world space.)

Share this post


Link to post
Share on other sites
Generally the correct way to cast this ray is to start it at the camera position and cast it in the direction of the cross hair, which may not be the same as the camera view direction for off center cross hairs.

 

Sean, my crosshair is exactly on the center of the screen. I cast the ray from the camera position and it's inaccurate, I'm not sure that this is the correct way, maybe because I did something wrong.

 

I think I did something very wrong, because your explanation doesn't apply to my case.

 

EDIT: You were right, casting from camera position works. I can theoretically get the x and y coordinates of the middle pixel and normalize it openGL screen coordinates and then use all the inverse matrices to unproject it to world space. But actually I don't need that at all. I can just use the camera position. I don't understand why it didn' t work yesterday, but maybe I forgot to put the matrices in the shader or something like that.

 

Nevermind, thanks for the explanation, and the nice picture.

Edited by codeBoggs

Share this post


Link to post
Share on other sites

If it doesn't work, and you don't understand how or why, your setup is too complicated. Simplify it. remove useless clutter, move things to known positions, use known orientations, etc.

Strip the problem until you can do the calculations yourself, and compare those with the computer results. There must be a difference somewhere.

Share this post


Link to post
Share on other sites

Haha, that's exactly what I did. You probably won't believe me, but I was in a mood for debugging.

 

I decided to spend some time to make a DebugDraw class that can draw some points for me on the screen. Then I declared it global, so I can use all variables(coordinates) from all objects and just put them into the global debugDraw object, and then draw whatever points I want in whatever order on the screen.

 

Then I created a Spectator class that basically works as a spectator in counter-strike. I can just fly around the world with w,a,s,d and look at everything from different sides. And it fixed the problem, it was a really stupid problem, I put all my matrices in the shader before assigning them the new values and I fixed it now, thanks guys.

 

 

Random question: Guys, is the thing I use called raycasting?

 

What I do is to cast a line with length 100.0f and then I just calculate at what point the line collided with some plane.

 

And if this is raycasting, then it's not at all as hard as people say. Is this how people make global illumination algorithms, just casting a ray and calculating the reflection? I can even use it for making line of sight for the enemies, if it's dark, for example.

 

If this is raycasting, either I'm doing some very basic stuff, or the term is overrated.

Edited by codeBoggs

Share this post


Link to post
Share on other sites

Haha, that's exactly what I did. You probably won't believe me, but I was in a mood for debugging.

Now you're making me curious, is there any reason why I should not believe you?  :D

 

 

Sounds like a good solution for debugging, I must remember that when I need to debug something 3D-ish. I only recently started using OpenGL, and the scene is just mostly a flat surface so far, I haven't got myself into deep enough trouble yet to have to debug like what you did.

 

 

it was a really stupid problem, I put all my matrices in the shader before assigning them the new values

Yet another form of "save your files before a compile" case

 

Glad you figured it out, and it turned out to be a simple problem.

 

 

What I do is to cast a line with length 100.0f and then I just calculate at what point the line collided with some plane

Don't know exactly, but it sounds like ray-casting to me.

Your "just" is not so "just" for many. If you hate math, don't understand matrices, or have trouble envision how it works in 3 dimensions, ray-casting becomes a dark art quite quickly.

 

Imagine you copy/pasted the code from somewhere without understanding how it works, and it fails. Trial and error fixing doesn't work, as the individual numbers have no meaning. You can spend days trying to make it work, but without deeper understanding of it, the only possible outcome is failure, which is then blamed on complexity of ray-casting.

Share this post


Link to post
Share on other sites
Yet another form of "save your files before a compile" case

 

It wasn't in the shader file(although I've done that too ), it was the function that puts the matrices from the cpu to the gpu. Basically i first put them in the gpu, and them assign them, and I think it's changed but it's not: ( or when I forgot to say what shader I use and I assign to a shader and it doesn't work, need to keep eye on the states, because opengl works like that. )

 

But basically what I did was:

int number = 2;

//some code

shader.get( number ); //send to gpu

number = 5;

 

And I'm thinking the shader has the number 5 until 4 A.M yesterday.

 

What I do is to cast a line with length 100.0f and then I just calculate at what point the line collided with some plane

Don't know exactly, but it sounds like ray-casting to me.

Your "just" is not so "just" for many. If you hate math, don't understand matrices, or have trouble envision how it works in 3 dimensions, ray-casting becomes a dark art quite quickly.

 

Imagine you copy/pasted the code from somewhere without understanding how it works, and it fails. Trial and error fixing doesn't work, as the individual numbers have no meaning. You can spend days trying to make it work, but without deeper understanding of it, the only possible outcome is failure, which is then blamed on complexity of ray-casting.

 

 

True.

 

 

EDIT: There were 2 problems, guys, not one.

 

When I translate an object, I need to multiply the object vertices by some translation matrix in order to get them in world space right? What I did was that I multiplied the plane normal by that same translation matrix. And them from vecNormal( 1.0f, 0.0f, 0.0f ) I get something like ( 0.5312, 0.0f, -0.8621 ). And this is why the AABB was drawn correctly on screen, but it didn't work. Stupid normals. And I actually remember fixing that 2 months ago, but then I messed up my code really hard and had to use a backup code, and I forgot that this error wasn't fixed in the back up code and spend even more amount of time to fix it again, 2 months later. And I just got reminded of that when I already fixed it...brain problems.

Edited by codeBoggs

Share this post


Link to post
Share on other sites

But basically what I did was: int number = 2; //some code shader.get( number ); //send to gpu number = 5;


It's usually a good idea to always declare your variables as const unless you absolutely need them to be mutable. (There's a ton of other benefits, too.)

Share this post


Link to post
Share on other sites
shader.get( number ); //send to gpu

Ah magic numbers eh?

Why don't you use an enum to translate the numbers to names, so you have nice readable names everywhere else?

 

 

 

And I actually remember fixing that 2 months ago, but then I messed up my code really hard and had to use a backup code, and I forgot that this error wasn't fixed in the back up code and spend even more amount of time to fix it again, 2 months later. And I just got reminded of that when I already fixed it...brain problems.

Instead of backup code, use a version control system (VCS), where you can save every little change, and it keeps all history for you.

In addition you can go back to any point in the past, or browse changes, or revert bad changes, or ...

It also supports co-operation between team members, where it handles synchronizing changes between all team members.

 

The popular VCS nowadays is Git, not in the last place due to Github, a git-project hosting site. Plain git is somewhat of a pain to work with if you don't understand how it works. There are also Guis for Git, never used them for real work (they seem to be too primitive), but it may work for you. Also, many development IDEs have git support.

Alternative VCSes are Mercurial (also known as hg), or Subversion (svn). Svn is the simpler solution, but only works in situations where everybody in the project has access to the same machine (with svn on it). hg and git are more comparable, but hg focuses more on the user interaction. It is easier to work with from the command-line. TortoiseHg (a hg Gui frontend) is awesome too, although I mostly use it for browsing and searching history.

Edited by Alberth

Share this post


Link to post
Share on other sites

Haha, I just gave an example with the word "number", actually that was the MVP matrix. :D

 

Yes, version control is on my list, but last time I checked I had to pay in order to have a private project and I kind of didn't like it, that's why I don't use it. Need to check again if some guys offer free private projects. Thanks for the suggestion.

Share this post


Link to post
Share on other sites

The VCS systems themselves (git, hg, and svn) can all run at your local machine without problem (other than you having to wrap your head around this way of working). They are just 1 or 2 command-line programs, that's all.

 

Obviously you won't have off-line storage, or easy sharing with friends (which you get with a hosting site). Just make backups of the repository, like you do with all your data that you like to keep across disk crashes and other hazards.

 

The hosting sites pretend they are crucial for using the VCS (and they are if you need an issue tracker, wiki, and web interface, or want collaborative development in some form).

 

 

Github has paid private projects afaik, but you may also want to try bitbucket, I don't know their requirements.

As said, for single person projects they don't add much other than safe storage and some web-based services.

 

If you just want to experiment with "remote repositories" (in git or hg), a local clone at your disk will work exactly the same, but a lot faster, as the bandwidth of a disk is higher than the bandwidth of the Internet :)

Edited by Alberth

Share this post


Link to post
Share on other sites

Yes, version control is on my list, but last time I checked I had to pay in order to have a private project and I kind of didn't like it, that's why I don't use it. Need to check again if some guys offer free private projects. Thanks for the suggestion.


BitBucket, GitLab, and Visual Studio Online are three examples of VCS services that offer free private repos. I primarily used BitBicket though recently started migrating to GitLab for this reason (GitLab has better continuous integration tools for Windows developers). You can also install your own VCS server if you have a VM or box somewhere that you trust, or as a previous commentator stated you can just use a VCS like Git locally without any server at all (using it for history and change tracking without the offsite backup or sharing capabilities).

Even if you did have to use GitHub and pay (you don't) I'd consider it pretty foolish to not just pay. $7/mo is the price of one-two drinks at Starbucks per month and provides you an awful lot more benefit.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this