- Home /
(Oculus Rift) Casting a ray from mouse through distortion matrix
Hi everyone. I've searched the board, as well as the oculus board, and stack overflow. Couldn't really find something that helped.
I'm working on a vehicle simulation. Before we started using the oculus, it was just a regular first person perspective. You used a racing wheel/pedals to drive and the mouse to control all the buttons and switches etc. We use raycasting from the mouse point on the screen into the world to interact with the various controls in the vehicle.
Now that we're using the oculus, the raycast isn't taking into account the distortion matrix used on the oculus cameras. So you're not actually casting a ray at what you're visually clicking on. Using Debug.DrawRay I found that it was slightly off. Just to be sure, I disabled the lens correction via inspector on the OVRCameraController and sure enough the raycasting was working again.
The ray itself is calculated the usual way one does when firing from the mouse point: ScreenPointToRay(Input.mousePosition);
Would anyone have any idea how I can adjust my ray so it works with lens correction on?
Cheers, Gordon
Answer by Spinnernicholas · Jan 14, 2014 at 04:59 PM
Oculus requires two cameras right? Are you raycasting from the center of the two cameras? You might have to do some logic to see what camera to use for raycasting, or raycast from the center of the two cameras.
Or, better yet, simulate the mouse in your game from the mouse input. That way, it is under the Oculus Distortion. Then, you can raycast from the simulated cursor.
Use something similar to a fps mouse script, except change it to move a cursor:
using UnityEngine;
using System.Collections;
/// MouseLook rotates the transform based on the mouse delta.
/// Minimum and Maximum values can be used to constrain the possible rotation
/// To make an FPS style character:
/// - Create a capsule.
/// - Add the MouseLook script to the capsule.
/// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
/// - Add FPSInputController script to the capsule
/// -> A CharacterMotor and a CharacterController component will be automatically added.
/// - Create a camera. Make the camera a child of the capsule. Reset it's transform.
/// - Add a MouseLook script to the camera.
/// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationY = 0F;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
}
}
void Start ()
{
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
}
}
I could certainly give this a try, however I do have doubts because as far as I know the cameras are what's being effected by the distortion so physics still happens without distortion. I do have a system in place so it knows which "eye" to fire the raycast from. Also using two different coloured Debug.DrawRays to visually verify it's working. The rays are just always off a little due to you the user seeing something that is actually physically a little ways away from where you clicked. I think it's just a matter of applying some vector or matrix math to the ray's origin and direction after the initial calculation before firing. I'm just not sure what :/
Yeah, sending the vector origin point through the distortion filter would be the best way. Even if you could figure out the filter, they may change the filter down the road and then you would have to fix it again. They need to implement something on their end. Vector2 GetFiltered$$anonymous$$ousePosition(); or something that will be updated if they change their code. Is all of the Unity distortion code exposed? I would love to dig through the code. I couldn't find any good docs about it online. Can you post a link to the Oculus code for me?
I've actually started the 3d mouse thing and it seems to be working so far. Though it would have been nicer to just use the 2d mouse. If you or anyone figures out, I'd love to know. Yes the code is exposed. I spent a good chunk of yesterday and today sifting through it. Tried a number of things, but no dice. I'm not a total nub with linear algebra but also not a pro.
I'm not sure where the code can be obtained. I was just assigned to this project with the task of making the mouse work proper with the oculus, so all the files were already in the project. I imagine whatever software comes with the oculus includes it. Likely even downloadable from their site...possibly even from this site....actually after checking with some people here, you do download it from the oculus site. However I'm not sure if you actually have to have purchased an oculus or if the download's free. You do need to login though.
Can you post the code provided by oculus, or a link to it if it's online. I am an experienced programmer and can $$anonymous$$r through it to pull out just the transformation code.
Alright, what I ended up doing was creating a 3D cursor. I placed a gameobject at the same place as the "head" (between left eye and right eye cameras). It has a script on it that rotates up/down/left/right based on mouse movement. I then temporarily put a spot light with a narrow cone and high intensity on it so it looked like a laser pointer. I figured if the light is hitting things, so should a raycast of the same origin. Which ended up working. However this didn't really solve the issue of using a cursor. I tried a number of things that ultimately didn't work (didn't line up with with where the light/raycast hit). Finally I realized I was overlooking something very simple. I lowered the near clipping plane of the cameras and placed a plane as close as I could to the camera while still being visible. I then rotated it on local y by 180 so it would be invisible to the cameras and not block ray casts. I then added some code so that when a raycast hit something, it would fire a second raycast from the hit point back to the origin. On the way it would have to hit the plane, which was essentially at the near clipping plane. I would then move my 3D cursor to that hit point. Now it works as intended. Where the cursor is, is where the original raycast hit. The cursor now matched the position of the laser dot. So then I removed the light component. Done.
Thanks for all your input.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Playing Oculus VR application built in Unity 5 0 Answers
Distribute terrain in zones 3 Answers
Why is my C# code giving me compatability issues? 0 Answers
Rotation around an object using oculus head tracking. 0 Answers