Tag Archives: Programming

Implementing mixed reality with the Samsung Gear VR

The Gear VR as it stands now is one of the most affordable options to experience immersive Virtual Reality. If you own a compatible device then the  Gear VR is a must have.

In this blog I describe a Mixed Reality Android project that  I created to start learning AR/VR development for the Gear VR.

Video of the demo running in development mode.

 

Mixed reality is combining  AR + VR, in this project the AR part consist in displaying animated 3d models on top of tracked images. The VR part consist in proyecting the see-through camera + AR images so we can see the outside when wearing the Gear VR headset.

AR_IMG1

Project overview.

The following image shows the VR Scene setup.

AR_IMG3

In this project I’m working with the GearVR Framework (GearVRf), which is an Open Source framework to create apps for the Samsung Gear VR headset. I highly recommend have a look to the sample Apps, most of the questions regarding how to implement certain functionality with GearVRf are covered in the sample Apps code.

 

I took the vuforia-sample as a base for this project and then added the animated 3d models using .dae files that I exported with blender. As you can tell, the demo makes use of the Vuforia mobile sdk (vuforia-sdk-android-5-5-9) to implement the markerless AR functionality

There are several options to implement AR in mobile;for this project I wanted to track images and then display a 3d model on top of the tracked image. Vuforia already provides out of the box functionality to tag, detect images and track the generated homography; it also provides a free license for personal projects.

OpenCV is also an option, but perhaps  for another project since it will take more effort having to implement a bag-of-words model, and multi-class classification algorithm  and so on (something I’ve been learning from several Computer Vision courses in Coursera).

Required tools to build the project:

In order to build the source code you will need:

 

Loading the 3d models.

I got two animated 3d max models from turbosquid, before loading them using the GearVR framework I first had to import them to blender to align their orientations and then export them to collada format (.dae).

AR_IMG4

The GearVRf can load models from several 3d formats, internally GearVRf wraps the Assimp library, this makes loading 3d models and animations really easy.

Loading the t-rex model:


GVRModelSceneObject rexModel = gvrContext.loadModel("Tyrannosaurus.dae");

 Starting the animation:


List<GVRAnimation> animations = mModel.getAnimations();

if (animations.size() >= 1) {

mAnimation = animations.get(0); //get the first animation
mAnimation.setRepeatMode(GVRRepeatMode.REPEATED).setRepeatCount(-1); //loop the animation
mAnimation.start(mAnimationEngine); //start the animation

}

 

Tracking images with Vuforia.

 

The Vuforia Developer Portal allows you to upload the images you want to track, the online tool will generate a database which is a set of files that contain the feature descriptors of the images,  the Vuforia mobile SDK then utilizes the database file data to detect and classify the tracked  images.

AR_IMG5

The generated database files are located in the App assets folder.

AR_IMG6

Each 3D model must be associated with  the corresponding TrackedImage in the vuforia database, for this I created the class TrackedModel that holds the 3d model and the Image Id; then on each frame it updates the  3d model transform using the transformation matrix returned by Vuforia SDK during the tracking process.


public class TrackedModel extends GVRSceneObject {
...
...
private GVRModelSceneObject mModel; //the animated 3d model
private int mTrackingId; //the TrackedImage
 
//sets the vuforia transform matrix and scale
public void setTrackedPose(float[] matrix, float scale);
...
//updates the Model transform using the most recent vuforia transform and scale
private void updateTrackedPose( );

AR_IMG7

Rendering the camera see-through.

In order to render the camera frame we need to setup a RenderTexture (passThroughTexture), which is an OpenGL ES Frame Buffer Object linked to a OpenGL Texture. The passThroughTexture Id is then passed to the Vuforia Renderer Object to update the texture with the contents of the camera frame.

To render the camera frame in the Scene  a rectangle SceneObject (passThroughObject) is added to the scene and the passThroughTexture is set as the material texture.

AR_IMG8

Creating the passThroughTexture:

passThroughTexture = new GVRRenderTexture(gvrContext,
 VUFORIA_CAMERA_WIDTH, VUFORIA_CAMERA_HEIGHT);

 

Creating the see-through rectangle:

GVRSceneObject passThroughObject = new GVRSceneObject(gvrContext, 16.0f / 9.0f, 1.0f);
…
…
material.setMainTexture(passThroughTexture); //set the passThroughTexture

Assign the passThroughTexture to Vuforia renderer:

TextureData data = new GLTextureData( passThroughTexture.getId());

Renderer.getInstance().setVideoBackgroundTexture(data);

Here we invoke the vuforia Renderer object to update the passThroughTexture. The onStep method is called per-frame by  GearVr framework,

@Override
public void onStep() {
…
…
if (VuforiaSampleActivity.isVuforiaActive())

{

Renderer.getInstance().begin();

Renderer.getInstance().updateVideoBackgroundTexture(); //update passThroughTexture

Renderer.getInstance().end();

}

 

Running the demo.

AR_IMG2

To run the demo just build the Android Studio project, don’t forget to put your oculus osig file in the assets folder so you can test the sideloaded app in your device.

The tracked images are located in the images folder.

Code for this project in github:

Links:

Advertisements
Tagged , , , , ,

Luz y Sombra para mundos 2d. (spanish)

Los efectos de luz y sombra en tiempo real pueden causar un gran impacto en la presentación de tu juego si los sabes usar sabiamente y además se esperan formen parte de cualquier juego moderno.

sc0

En el caso de 3d, los métodos mas comunes para generar sombras en tiempo real son Shadow Mapping y Shadow Volumes (checa la documentación de tu engine favorito), cada uno con sus respectivas ventajas / desventajas y con costo de procesamiento alto si solo se esta haciendo un juego con apariencia 2d (pero con geometría 3d).

Las sombras en tiempo real no tienen por que ser algo exclusivo para mundos con geometría 3d, existen juegos 100% 2D que tienen efectos de luz y sombra en 2D .

Después de repasar varios artículos en internet que describen algunas técnicas y revisar algunas implementaciones existentes (plugins para engines como Game Maker) decidí desarrollar este tutorial que espero les sea útil, en el que describo una implementación (independiente del engine que utilices o si estas evaluando utilizar algún plugin) basada en generación de geometría y shaders simples.


(video del Demo al final del post)

¿Cómo hacemos luces y sombras 2d en tiempo real?

En el caso de 2d podemos usar algo similar a los shadow volumes, ya sea generar la geometría que cubre la luz o generar la geometría que no es cubierta por la luz, nuestro modelo de iluminación no será 100% fiel a los modelos físicos reales pero será una aproximación bastante aceptable.

¿Qué es una sombra?

sc1

La sombra es el área que esta fuera del alcance de la luz , áreas que son bloqueadas por shadow casters. Así que para generar sombras ocupamos primero una fuente de luz y los shadow casters que la bloquean.

Podemos empezar con una fuente de luz simple: una luz omnidireccional que cubre un área cuadrada finita NxN y los shadow casters serán la geometría que compone el nivel del juego.

sc2

Ya tenemos nuestra fuente de luz definida, ahora lo que sigue es generar las sombras.

¿Cómo generar las sombras?

Para esto tenemos 2 opciones:

1. Calcular la región (geometría 2d) que no es iluminada por la luz.

2. Calcular la región (geometría 2d) que es iluminada la luz.

sc3

Cualquiera de las 2 opciones es valida, yo he decidido tomar la opción 2: calcular la geometría que representa el área iluminada por la luz.

¿Cómo calcular la geometria iluminada por la luz?

Nuestro problema ahora consiste detectar los borders de los shadow casters con los cuales colisionan los rayos de luz emitidos por nuestra fuente de luz como se ve en el la siguiente imagen:

sc4

¿Cuántos rayos lanzamos, muchos?¿Que tan eficiente es eso?

Bueno en realidad no necesitamos lanzar rayos para determinar si colisionan con los shadow casters.

Lo que se puede hacer es tomar los vértices de los shadow casters y seleccionar aquellos que generen líneas que van directo al centro de la luz sin toparse con nada de por medio. También hay que tomar en cuenta los puntos de los shadow casters que se intercectan con los borders de la región de luz.

sc5

Para hacer mas eficiente el proceso podemos usar AABB queries para detectar intersecciones con el AABB de la region del luz, y de esta forma reducir la selección de vertices cercanos a la luz.

sc6

Listo, ya tenemos los puntos q conforman el area iluminada por la luz, ahora solo conectamos los puntos para generar el polígono y pintarlo sobre el piso . La ventaja de este polígono es que se puede renderear fácilmente con un triangle strip y reducir la información de vértices que se envía al GPU.

Los siguientes screenshots (tomados del demo anexo) muestran como quedaría con lo que llevamos de momento.

sc7

Ya tenemos luz pero no luce muy bien que digamos pues estamos rendereando el área de la luz con un color constante.Podemos usar una textura con degradado circular para hacer el efecto de desvanecimiento, listo :D.

sc8 sc9

Ahora un poco de color : para esto simplemente pintamos un quad con degradado circular del color de nuestra fuente de luz.

sc10 sc11

Y el truco para que luzca como se ve en el screenshot es el siguiente: al pintar este quad usamos una función de blending que sea equivalente a una multiplicación RGB1 x RGB2. (pixel por pixel). Esto lo que hace es multiplicar el valor de la luz que estamos pintando por el valor del pixel que se encuentra debajo.

En opengl esto se logra usando la funcion glBlendFunc( GL_ZERO, GL_SRC_COLOR).

Se puede experimentar con varios efectos (yo uso por ejemplo GIMP para diseñar y modelar el rendering por capas y posteriormente programar el shader).

Y ahora, ¿cómo hacer muchas luces?

Para pintar multiples luces, solo es cuestión de usar FBOs ( “Frame Buffer Object” o “Render to Texture” o “Post processing” o como quieras llamarlo).

1. Pintamos los colores de las luces en un FBO1 y dejamos que se mezclen los colores usando operaciones de color blending (ADD).

sc12

2. Pintamos la geometría de luz generada por cada una de las luces en un FBO2 y dejamos que se acumulen las intensidades usando alpha blending (ADD).

sc13

3. Procedemos a pintar el suelo (o fondo) del mundo 2d.

4. Pintamos encima el FBO2 (que contiene las regiones de luz en escala de gris / alpha).

5. Pintamos la geometría de nuestro mundo 2d (shadow casters).

6. Finalmente pintamos el FBO1: colores mezclados de cada luz. (usando blending MULTIPLY).

sc14

sc15

Listo! Ya tenemos un implementación de luces y sombras para geometría 2d, simple y de bajo uso de recursos y que funciona además en Openg GL ES 2.0 (que es lo que soportan la mayoría de los dispositivos mobiles actuales).

Screenshot final del demo (3 luces simultáneas).

sc16

Esta técnica es útil si estamos desarrollando un juego2d y queremos evitar generar geometría 3d para cálculos de luz y sombra. si usas box2d puedes reutilizar la geometría de los fixtures y utilizarla como shadow caster, y además se pueden “eficientizar” los cálculos usando AABB queries para solo procesar la geometría dentro del área de luz.

¿Qué mas falta?

+ Las penumbras (soft shadows): ocupamos generar mas geometría para degradar los bordes de las sombras, no es tan complicado, solo un poco de geometría analítica y listo. La otra opción es hacer una especie de blur shader durante el rendering de las sombras.

+ Per-pixel lighting : el piso se ve muy plano no estaría mal agregarle bump mapping.

+ Modelar otros tipos de luz (direccional , lámpara): para esto es solo cambiar la forma de la región de luz (en vez de un cuadro, usar un triángulo), hacer algunas adecuaciones en los cálculos (origen y ángulo de la luz) y usar texturas acordes.

Demo:

Link del demo para win32 : Demo 2d Shadows

(este demo fue desarrollado usando librerías open source multiplataforma irrlicht / sdl 2.0, mismas que he utilizado para varios juegos que he publicado en iOS , Android y Windows phone).

En próximos posts, publicaré otra técnica útil para engines 2d (o quizas continuar una 2ª parte de este articulo con los temas de soft-shadows y per-pixel lighting 2d).

Referencias:

http://archive.gamedev.net/archive/reference/programming/features/2dsoftshadow/

http://www.redblobgames.com/articles/visibility/

Tagged , , , ,

iaco79 blog is starting…

Hi everybody…

This is the very first entry in this blog, my intention is to provide guidance and also to receive feedback for many of you interested in developing mobile applications (mainly the cool stuff  sound, graphics and games) , and perhaps other not game related projects

I’ll start by talking a little bit of myself:

I’m from Monterrey, Mexico and got my Bachelor Degree in Computer Science in 2004 from the “Universidad Autonoma de Nuevo Leon”, throughout my professional career I have participated in several projects mostly working with Object Oriented languages such as c#, c++, java and javascript

I grow up in the 80s and 90s during the golden age of the console wars (nintendo vs sega) and the emerge of the very first 3d consoles, now as a grownup I still recall those good old times and very good old games

So that’s why I’m here as I’ve been trying to release a game of my own, and as of right now it has never been easy than ever before to achieve this:  you have at your disposal google play market, apple store , steam , ouya , all those markets are waiting for you to publish your very own new blockbuster app, there are also available thousands of open source engines and resources on the net that can teach you how to develop your game from the ground up.

At this moment I’m in the final phase of my game project to be released initially for the android market, all the development was done with open source libraries with zlib and mit license (free as free)

In the following posts I’ll describe the basic building blocks that made up this project so you can use it as a base for your own developments,  I’m not going to describe how to build a complete integrated game engine , but an example of how to assemble different open source libraries (listed below) and make a complete mobile application with the following features:

All of the above are c / c++ based and are cross-platform which means that with little effort you can have your game running in android , ios and windows (For instance I do all my development and testing in a windows machine, and then I do an Android APK build to share with my friends so they can give me their feedback)

Also my main goal is to work at a native level to learn as much as possible how thing works under the hood , so I’m avoiding working with complete game development packages such as unity 3d

Well I think that’s it for now…

Tagged , , , , , ,