0
\$\begingroup\$

I am trying to convert screen point (mouse position) to ray in world space. It works, but it lacks precision.

Here is the code:

public Vector3 ScreenToWorld(Vector2 ndc)
        {
            var far = new Vector4(ndc.X, ndc.Y, 1, 1);
            var near = new Vector4(ndc.X, ndc.Y, 0, 1);

            var projI = projectionMatrixInverse;
            projI.Transpose();
            var camI = cameraMatrixInverse;
            camI.Transpose();

            far = Vector4.Transform(projI, far);
            far = Vector4.Transform(camI, far);

            near = Vector4.Transform(projI, near);
            near = Vector4.Transform(camI, near);

            return ((far.Xyz / far.W) - (near.Xyz / near.W)).Normalized();
        }

Usage:

var ray = EditorSystem.GetInstance().EditorCamera.ScreenToWorld(Input.GetInstance().GetMousePositionNDC());

            RaycastHit hit;
            if (PhysicsSystem.GetInstance().Raycast(EditorSystem.GetInstance().EditorCamera.myEntity.Transform.Position, ray * 1000.0f, out hit))
            {
                DebugS.GetInstance().DrawLine(hit.hitPoint, hit.hitPoint + hit.normal * 1.5f, Vector3.UnitX);

                if (Input.GetInstance().GetMouseKeyDown(MouseButton.Right))
                {
                    hit.cfRigidbody.AddForce(new BulletSharp.Math.Vector3(ray.X, ray.Y, ray.Z) * 1000.0f, new BulletSharp.Math.Vector3(hit.hitPoint.X, hit.hitPoint.Y, hit.hitPoint.Z));

                    var cloneE = metalBox.Clone();
                    cloneE.Transform.SetScale(new Vector3(0.2f, 0.2f, 0.2f));
                    cloneE.Transform.SetPosition(hit.hitPoint);

                }
            }

Input.GetMousePosNDC (conversion of mouse position in screen space to ndc space):

public Vector2 GetMousePositionNDC()
        {
            var ss = Graphics.GetInstance().WindowSize;
            var mp = GetMousePosition();

            float xNDC = mp.X / ss.X;
            float yNDC = mp.Y / ss.Y;
            yNDC = 1.0f - yNDC;

            return new Vector2(xNDC * 2.0f - 1.0f, yNDC * 2.0f - 1.0f);
        }

Here is the picture:

enter image description here

The red cross is where mouse pointer is, red line is hit normal at hit point from bullet physics. I am using openGL, openTK, bullet sharp on c#. Matrices are transposed because openTK math lib uses row-major order.

I did something similar in c++ a while ago and it worked, the only difference being that i used custom raycast and not bullet physics.

So is it something wrong with bullets raycast witch is unlikely or my screen to world?

Here is raycast from bullet:

public bool Raycast(BulletSharp.Math.Vector3 start, BulletSharp.Math.Vector3 direction, out RaycastHit hit)
        {
            hit = new RaycastHit(Vector3.Zero, Vector3.Zero, null);


            ClosestRayResultCallback rayCallback = new ClosestRayResultCallback(ref start, ref direction);
            bulletWorld.RayTest(start, direction, rayCallback);
            if (rayCallback.HasHit)
            {
                hit.hitPoint = new Vector3(rayCallback.HitPointWorld.X, rayCallback.HitPointWorld.Y, rayCallback.HitPointWorld.Z);
                hit.normal = new Vector3(rayCallback.HitNormalWorld.X, rayCallback.HitNormalWorld.Y, rayCallback.HitNormalWorld.Z);
                hit.cfRigidbody = (CFRigidbody)rayCallback.CollisionObject.UserObject;

                return true;
            }

            return false;
        }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.