Tags

, , , , , , , , , , , , ,

Hunched round the campfire, the workmen said excitedly, ‘Please, sir, tell us again about the doors you constructed in virtual reality!’

Arnold pretended not to understand. Poking his sausage on the end of a twig into the flames, he replied, ‘What doors?’

The workmen shouted in unison, ‘The doors you constructed with a Microsoft Visual Studio C++ application, using OpenGL graphics library and the Oculus SDK for Windows!’

‘Okay, okay,’ Arnold smiled, laying the twig against a stone to slow cook the meat. ‘Well, it all began with collision detection…’

It’s true. The post Zip wire with OpenGL shows how a simple collision detection struct can be inherited to provide advanced functionality. In that case, a zip wire.

But this time, we extend the collision detection struct to provide the functionality to walk through virtual doors:

#include <ctime>

struct DoorClient : CollisionClient
{
	const Vector3f NewPosition;
	bool IsActive;
	time_t StartTime;

	DoorClient(Vector3f min, Vector3f max, CollisionName name, Vector3f newPosition) :
		CollisionClient(min, max, name),
		NewPosition(newPosition),
		IsActive(false)
	{
	}

	void Start(){
		IsActive = true;
		StartTime = time(0);
	}

	bool IsStopped() {
		double secondsElapsed = difftime(time(0), StartTime);

		if (secondsElapsed < 2.0) {
			return false;
		}

		IsActive = false;
		return true;
	}
};

Quite simple. When we start walking through the door a start time is set, along with an active flag.

And then we check each render cycle to the Oculus Rift virtual reality headset whether the walk through the doors has completed. If two seconds has elapsed, we turn off the active flag and indicate that the door transition is at an end.

But how do we use such a door struct in our render cycle code?

First, we need to determine whether any doors are currently active:

// get an active door
bool isActiveDoor = false;
int activeDoor;
for (int i = 0; i < numMyDoors; ++i) {
	if (MyDoors[i]->IsActive) {
		isActiveDoor = true;
		activeDoor = i;
		break;
	}
}

If so, we check whether we have finished walking through the active door:

// try to get new position from active door...
if (isActiveDoor && MyDoors[activeDoor]->IsStopped()) {
	Pos = MyDoors[activeDoor]->NewPosition;
}

And we shift our player position to the other side of the door.

Otherwise, if we have no active door then we use the inherited collision detection to attempt to find one:

// ...otherwise try to detect a door collision
else if (!isActiveDoor) {
	for (int i = 0; i < numMyDoors; ++i) {
		if (MyDoors[i]->Detect(Pos)) {
			MyDoors[i]->Start();
			break;
		}
	}
}

We are sure to only handle one door at a time, as we can easily trigger logic to walk through a door from both sides at the same time!

Great, but how does the actual walking though a door appear in the virtual reality headset?

Well, as we can see from the door struct, there are two seconds to play with. So we simply update our render function to do nothing if a door is active:

for (int i = 0; i < numMyDoors; ++i) {
	if (MyDoors[i]->IsActive) {
		return;
	}
}

That way, we get a nice soothing void of blackness in our eyes, rather than the sick inducing experience of walking through the mesh of a virtual door. It also allows us to transition between the rooms of our virtual house and the outside, changing lighting, audio and objects.

All that is left is to instantiate our door struct with suitable values:

DoorClient * dc = new DoorClient(Vector3f(-10.0f, 0.0f, 19.0f), Vector3f(-6.0f, 3.8f, 19.5f), CollisionObject, Vector3f(-8.0f, 0.0f, 21.0f));

This door provides a couple of vectors for collision detection, along with a third vector for the new player position in our virtual world, once we walk through the door.

For example, here is Arnold walking up some stairs towards a door:

Next, the soothing blackness as he walks through the door:

And finally he is at the other side of the door, inside a room with lighting and objects (and some audio playing, believe me):

The workmen gasped at every word of Arnold’s story. They drooled as he spoke of the transition through doors without the ugliness of broken meshes and jarring lighting changes.

‘Oh, tell us more uncle Arnold!’ they all cheered.

Arnold furrowed his brow. ‘I am not your uncle, I’m your foreman. Now, back to work you fuckers. Before I dock your pay!’

Arnold straightened his pants and bit down on his sausage.

Advertisements