Blender shapes in Oculus Rift

Tags

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

I cranked open the Oculus Rift PC SDK in my last post, and used OpenGL to render a textured triangle into a virtual world. The virtual world in question is the SDK’s OculusRoomTiny(GL) Visual Studio project.

Now, everyone knows that triangles are mystical and sexual. Deviants, even. But, nevertheless, it would be nice if our C++ code could handle more complex objects such as a sphere and cylinder. Here’s how…

Blender

First, we will use Blender – the free and open source 3D creation suite – to create our shapes.

oculusrift_spherecylinder_blender

We add and position a sphere and cylinder mesh, and export it as a Wavefront .obj file.

Assimp

Armed with our .obj file, it’s time to import it into our Visual Studio project. For that, we will use Assimp, the Open Asset Import Library.

The Learn OpenGL site has some top instructions on adding Assimp to Visual Studio, with the help of CMake. Once done, we can add the includes to our OculusRoomTiny(GL) project’s Win32_GLAppUtil.h file:

#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

And import our sphere and cylinder meshes:

Assimp::Importer import;
const aiScene* scene = import.ReadFile("C:/Blender/sphere_and_cylinder.obj", aiProcess_Triangulate | aiProcess_FlipUVs);

Oculus Rift

Great. Now that we have access to our Blender shapes in the Oculus Rift PC SDK’s OculusRoomTiny(GL) project, it’s time to write some C++ code to build vertices and indices out of ’em:

void LoadModel()
{
	Assimp::Importer import;
	const aiScene* scene = import.ReadFile("C:/Blender/sphere_and_cylinder.obj", aiProcess_Triangulate | aiProcess_FlipUVs);
		
	processNode(scene->mRootNode, scene);
}

void processNode(aiNode* node, const aiScene* scene)
{
	for (GLuint i = 0; i < node->mNumMeshes; i++)
	{
		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
		processMesh(mesh);
	}

	for (GLuint i = 0; i < node->mNumChildren; i++)
	{
		processNode(node->mChildren[i], scene);
	}
}

void processMesh(aiMesh* mesh)
{
	for (GLuint i = 0; i < mesh->mNumFaces; i++)
	{
		aiFace face = mesh->mFaces[i];

		for (GLuint j = 0; j < face.mNumIndices; j++)
			AddIndex(GLushort(face.mIndices[j] + GLushort(numVertices)));
	}

	for (GLuint i = 0; i < mesh->mNumVertices; i++)
	{
		Vertex vertex;
			
		vertex.Pos = Vector3f(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
		vertex.C = 0xff202050;;

		AddVertex(vertex);
	}
}

Learn OpenGL guides us on how to iterate over the nodes in our Assimp imported scene and build vertices and indices. For now, we will use a simple colour for our vertices – later, we can try adding textures.

We disable cull face when rendering our meshes to the virtual reality headset (we don’t want our shapes missing bits) and notice that we are drawing with GL_TRIANGLES (hence the need to use the aiProcess_Triangulate option when importing our meshes via Assimp)

glDisable(GL_CULL_FACE);
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, NULL);
glEnable(GL_CULL_FACE);

With our code in place, let’s run the project and render our shapes to the Oculus Rift headset:

oculusrift_spherecylinder_sdk

Terrific! We have successfully imported our Blender shapes using Assimp, and rendered the vertices to each eyeball.

But can Assimp handle even more complex meshes? Let’s grab the Crysis Nanosuit obj file and throw it at our project:

oculusrift_spherecylinder_nanosuit_boots

Hmm. That’s strange. I can only see the boots of the dude. Ah, wait a minute – I need to get rid of the ceiling!

oculusrift_spherecylinder_nanosuit

There the dude be, towering over the room and crushing all the furniture.

Next up, let’s plaster him in texture.

Ciao!