November 28, 2017

Virtual Reality Oral Surgery

A VR based training game for a dentist student.

Virtual Reality Oral Surgery

Background

Virtual Reality Oral Surgery (VROS) Simulation aims to provide an effective, efficient, and economical method for training and practice for medical students, surgeons, and professionals, enabling oral surgery experience in a safe environment. They can also practice a new technique or refresh dormant skills.

Platform Engine Project Time Frame Role
PC Unity VR Commercial Project 2 Months Fullstack

It was my first VR project with Unity. Comparing video games or mobile games, it was much harder to implement particular parts such as UI and input development. Besides, the game needed at least 90FPS to ensure players wouldn't get dizzy. As a result, I needed to deal with some simple performance tuning, such as counting how many polygons would be drawn for one scene and how big those textures would be. In addition, I made a mini framework to help me define "step", "state", and "objective", which allows me to simplify the development a lot.

My Tasks Outline

  1. UI Design
    - Tailored made for VR
  2. Gameplay Implementation
    - Created a state and step system to simplify the development

Highlights

Custom VIVE Controller UI

I developed a custom VIVE controller UI with Unity that allows players to use the touchpad on the VIVE controller to select a menu with a simple touch and click. The receipt behind this is quite simple. I used the touch position from the VR device API and calculated how many sectors were in the menu. After that, use the position to calculate which sector players are pointing to.

Code snippets

The update calls for getting the position from the VR Controller and setting it to the checker.

if (trackedEvent.padTouched) {

    if (!cursor.gameObject.activeSelf) {
        cursor.gameObject.SetActive (true);
    }

    ClickedEventArgs e;
    e.controllerIndex = trackedEvent.controllerIndex;
    e.flags = (uint)trackedEvent.controllerState.ulButtonPressed;
    e.padX = trackedEvent.controllerState.rAxis0.x;
    e.padY = trackedEvent.controllerState.rAxis0.y;

    cursor.SetPosition (e.padX * cursorAreaRidus, e.padY * cursorAreaRidus);

} else {
    if (cursor.gameObject.activeSelf) {
        cursor.gameObject.SetActive (false);
    }
}

In the VRCursor class, the update call will get all clickable buttons on the menu and auto-focus the smallest distance from the touch position.

if (isReady) {
    // Clear result list
    resultList.Clear ();

    // Calculate all the distances
    float dist;
    for (int i = 0; i < targetList.Count; i++) {
        if (targetList [i].gameObject.transform.parent.gameObject.activeSelf) {
            dist = Vector3.Distance (transform.position, targetList [i].transform.position);
            resultList.Add (dist);
        } else {
            resultList.Add (float.PositiveInfinity);
        }
    }

    // Find Min Index
    int minIndex = Helper.FindMinIndexFromList (resultList);

    // Cursor Callback
    OnChangedNearestPadButton (minIndex);
}

Technologies Used

  1. Unity
  2. 3DsMax
  3. Visual Studio
  4. VR / HTC VIVE

Screenshots

Gameplay Video