mathrotationplaycanvas

2d screen velocity to 3d world velocity while camera is rotated


I am creating a small demo game where you can rotate around earth and launch satellites into space. But I have some trouble with the calculations.

You can drag the mouse from the platform to a direction. This is the direction you shoot the satellite to. Because the camera is rotated around the planet, up isn't the same as forward. For the direction of the satellite, I need a Vector3 (direction/velocity).

So data I have is the forward of the platform on screen and the mosue drag direction.

enter image description here So When the user drags it to (-0.7, 0.7) it means the satilatie launch direction should be (0, 0, 1). The global/World Forward direction.

So how can I translate those 2d screen position and direction to the world direction?


Solution

  • PlayCanvas has a very useful function we could make use of. The implementation is as follows:

     * @description Convert a point from 2D canvas pixel space to 3D world space.
     * @param {Number} x x coordinate on PlayCanvas' canvas element.
     * @param {Number} y y coordinate on PlayCanvas' canvas element.
     * @param {Number} z The distance from the camera in world space to create the new point.
     * @param {Number} cw The width of PlayCanvas' canvas element.
     * @param {Number} ch The height of PlayCanvas' canvas element.
     * @param {pc.Vec3} [worldCoord] 3D vector to receive world coordinate result.
     * @returns {pc.Vec3} The world space coordinate.
     */
    screenToWorld: function (x, y, z, cw, ch, worldCoord) {
      ...
    

    We can use this function to convert the start and end points (A and B respectively in the diagram) of the mouse drag line to 3D lines in world space. After the conversion we must subtract the camera's world position from the two projected points, and normalize the resulting vectors.

    [The z parameter is irrelevant for this purpose because we are only interested in a direction vector and not an actual point, so just set it to e.g. 1. ]

    So what does this give us? A plane spanned by these two vectors:

    enter image description here

    There are three criteria that the velocity direction must satisfy:

    Let:

    Finally, the (un-normalized) velocity direction is simply given by cross(N, cross(A, B)). Note that the order of operations matters.

    To visualize this:

    enter image description here

    EDIT:

    1. Small mistake in the second diagram: U×V should be V×U, but the expected result N×(U×V) is still correct.

    2. Note that UxV is not necessarily perpendicular to N. When it is parallel to N, the blue plane "scrapes" the surface, i.e. the green line AB is tangent to the Earth's surface as per rendered on-screen, at the launch site.