- 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