- Home /
screen space to world using camera.projectionMatrix
Hi, consider this is what I have:
     private void Rotate(Vector3 mouseMoveDelta)
     {
         Vector3 oldPos = Input.mousePosition + mouseMoveDelta;
         Vector3 newPos = Input.mousePosition;
         
         Vector3 oldSwipe = cam.ScreenToWorldPoint(new Vector3(oldPos.x, oldPos.y, 15f));
         Vector3 prevSwipe = cam.ScreenToWorldPoint(new Vector3(newPos.x, newPos.y, 15f));
 
         swipeDir = (oldSwipe - prevSwipe)  * swipeSensetivity ;
    }
This is a usual approach to get world spaced mouse movement delta. So the idea is to do the same thing, but in a proper way - using projection matrix. You can see a lot of problems in the previous snippet: I already have the delta as input, so i don't want to recalculate it but in the world space. I am trying to get rid of Input.mousePosition here. The value is just a delta, meaning that we don't actually need to consider the camera's location and rotation. Meaning that only projection must be applied. Basically, what should be working - is this:
 Vector3 worldSpacedDelta = Camera.main.projectionMatrix.inverse.MultiplyPoint( new Vector3(delta.x, delta.y, 15f) );
But I can't get it right, it's quite hard trying to make sense of random values. Maybe anyone already has the right solution to this?
I am trying to achieve the same thing. I want to compute a world point from viewport (or screen) space according to a matrix. I don't want to use the camera to compute this for me because I would have to set some specific parameters to the camera, compute the points, and revert the parameters afterwards.
The final rendering performed by a camera uses three matrices:
- World - $$anonymous$$atrix taking the vertices in object space and transforms them to world space. It is the combined transforms of all objects in a hierarchy. 
- View - $$anonymous$$atrix transfor$$anonymous$$g world space point into view/camera space. 
- Projection (and clip) - Defines the 'distortion' (for lack of a better word) to apply to the vertices to simulate viewing something with human eyes (perspective) or orthographically. It also defines the clipping rectangle (the screen). 
Source: https://www.reddit.com/r/Unity3D/comments/1pws40/cameraprojectionmatrix_vs/
I've tried to do this but without success:
 $$anonymous$$atrix4x4 matrix = ($$anonymous$$atrix4x4.Ortho(left, right, top, bottom, nearClipPlane, farClipPlane) * cameraTransform.worldToLocal$$anonymous$$atrix).inverse;
 Vector3 point = matrix.$$anonymous$$ultiplyPoint3x4(new Vector3(1, 1, distFromCamera));
 // C++ : compute the matrix
 glm::mat4 $$anonymous$$VPmatrix = projection * view * model; // Remember : inverted !
I'm not sure if you have seen this question. Also make sure you read the comment below my answer. It should cover this question as well ^^. Note that the viewport position is specified in viewport coordinates (0 to 1) and not NDC coordinates (-1 to 1) for all 3 coordinates.
The important parts are that the worldToCamera$$anonymous$$atrix does a left to right hand conversion since the projection matrix is in OpenGL format and therefore in a right handed system. That means your view direction is the negative z axis unlike Unity's lefthanded space.
Also note that the z value is also the normalized z position unlike Unity's ViewportToWorldPoint method. Finally keep in $$anonymous$$d that the projection matrix outputs NDC coordinates (-1 to 1) in all 3 axis. So a z position of -1 in NDC coordinate relates to a position on the near clipping plane. A z position of 1 relates to a position on the far clipping plane.
$$anonymous$$y "CalculateUnproject$$anonymous$$atrix" method creates a matrix which does convert viewport coordinates (all axis 0 to 1) into worldspace coordinates. Next thing is you used "$$anonymous$$ultiplyPoint3x4" which does only work for transformation matrices (rotation, translation, scale). If a projection is involved you actually need to use the full homogeneous space and normalize the result. This is automatically done by the $$anonymous$$ultiplyPoint method.
If you have trouble understanding how the projection matrix works, someone asked that already over here.
I saw the question being active the last few days but I didn't think about looking at it.
The comment you have posted below your answer has been very helpful, and I've managed to achieve what I wanted. Thanks a lot Bunny83.
Here is an overview of how I've used your code:
 private void OnDrawGizmosSelected()
 {
     $$anonymous$$atrix4x4 matrix = $$anonymous$$atrix4x4.Ortho(left, right, bottom, top, camera.nearClipPlane, camera.farClipPlane);
     $$anonymous$$atrix4x4 unproject$$anonymous$$atrix = CalculateUnproject$$anonymous$$atrix(matrix, camera.worldToCamera$$anonymous$$atrix);
     Vector3 a = ViewportPointToWorld(new Vector3(0, 0, 1), unproject$$anonymous$$atrix);
     Vector3 b = ViewportPointToWorld(new Vector3(1, 1, 1), unproject$$anonymous$$atrix);
     Gizmos.DrawLine( $$anonymous$$, max );
 }
 private $$anonymous$$atrix4x4 viewToNormalizedDeviceCoordinates$$anonymous$$atrix = $$anonymous$$atrix4x4.Translate(-Vector3.one) * $$anonymous$$atrix4x4.Scale(Vector3.one * 2);
 private $$anonymous$$atrix4x4 CalculateUnproject$$anonymous$$atrix( $$anonymous$$atrix4x4 projection$$anonymous$$atrix, $$anonymous$$atrix4x4 worldToCamera$$anonymous$$atrix )
 {
     $$anonymous$$atrix4x4 matrix = projection$$anonymous$$atrix * worldToCamera$$anonymous$$atrix;
     return matrix.inverse * viewToNormalizedDeviceCoordinates$$anonymous$$atrix;
 }
 private Vector3 ViewportPointToWorld( Vector3 viewportPoint, $$anonymous$$atrix4x4 unproject$$anonymous$$atrix )
 {
     float distanceFromCamera = viewportPoint.z;
     viewportPoint.z = 0;
     var p0 = unproject$$anonymous$$atrix.$$anonymous$$ultiplyPoint(viewportPoint);
     viewportPoint.z = 1;
     var p1 = unproject$$anonymous$$atrix.$$anonymous$$ultiplyPoint(viewportPoint);
     return p0 + ( p1 - p0 ).normalized * distanceFromCamera;
 }
Your answer
 
 
             Follow this Question
Related Questions
Need help putting an object at a point based on screen coordinates 1 Answer
mouse position on terrain 1 Answer
Sprite Not Displaying In-game 0 Answers
Indicate with markers the direction of Gameobjects which are outside of the camerafield. 0 Answers
Orthographic camera with rotation and ScreenToWorldPoint 2 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                