Wednesday, December 17, 2014

How easily make a stereoscopic camera for Unity

Last week I ordered a ready to assemble Google Cardboard from ebay and in half an hour I finished watching all demos available so I started to thinking about how to make my own contents for it or even better how to add ability to play our normal games without using Google Cardboard SDK.



I started to look more into it with a very simple approach. My idea was to use two cameras as a single set with a certain distance from each other to mimic the pictures we receive from our eyes. So I tried to make my own 3D stereoscopic camera and replaced it with the normal camera in a free 3D car racing kit that I downloaded from Unity Asset Store and the result was excellent.

I wrote a very small script as bellow :

using System;
using UnityEngine;
using System.Collections;

public class CardboardCamera : MonoBehaviour
{
    public float Distance = 0.1f;
    public float Degree = 0f;

    private GameObject _cameraLeft;
    private GameObject _cameraRight;
    private float leftCameraX;
    private float leftCameraDegree;
    private float rightCameraX;
    private float rightCameraDegree;
    private bool dirty = true;

       // Use this for initialization
       void Start () {
        // Disable screen dimming
        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        _cameraLeft=GameObject.Find("cbCameraLeft");
        _cameraRight=GameObject.Find("cbCameraRight");
       }

    void Awake()
    {
        // Disable screen dimming
        Screen.sleepTimeout = SleepTimeout.NeverSleep;
    }

    // Update is called once per frame
       void Update ()
       {
        leftCameraX = -Distance / 2;
        rightCameraX = Distance / 2;
        leftCameraDegree = Degree / 2;
        rightCameraDegree = -Degree / 2;
        const double tolerance = 0.000000000000000001;
        // Adjust rotations
           if (Math.Abs(leftCameraDegree - _cameraLeft.transform.localRotation.y) > tolerance)
            _cameraLeft.transform.localRotation = new Quaternion(_cameraLeft.transform.localRotation.x, leftCameraDegree, _cameraLeft.transform.localRotation.z, _cameraLeft.transform.localRotation.w);
        if (Math.Abs(rightCameraDegree - _cameraRight.transform.localRotation.y) > tolerance)
            _cameraRight.transform.localRotation = new Quaternion(_cameraRight.transform.localRotation.x, rightCameraDegree, _cameraRight.transform.localRotation.z, _cameraRight.transform.localRotation.w);
        // Adjust x positions of cameras
        if (Math.Abs(leftCameraX - _cameraLeft.transform.localPosition.x) > tolerance)
            _cameraLeft.transform.localPosition = new Vector3(leftCameraX,_cameraLeft.transform.localPosition.y, _cameraLeft.transform.localPosition.z);
        if (Math.Abs(rightCameraX - _cameraRight.transform.localPosition.x) > tolerance)
            _cameraRight.transform.localPosition = new Vector3(rightCameraX, _cameraRight.transform.localPosition.y, _cameraRight.transform.localPosition.z);
    }
}



The script simply adjusts the distance between left and right cameras and also the angle between them in a symmetric way. Then I added this script to my new camera which in fact has 2 cameras inside an empty object. I set all origins to 0 to make sure I can adjust the whole set by adjusting the empty game object position.

To split screen into two equal section you need to tell each camera how to use the screen as bellow:




Here you can see the final result. The remaining step that I might add later could be controling the  rotation of CardboardCamera based on accelerometer or gyroscope 







No comments:

Post a Comment