¿Qué es? y como crear aplicaciones de realidad aumentada en Android con Wikitude

Wikitude ya NO esta disponible, es una tecnología deprecated y este artículo es SOLO INFORMATIVO.

Para hablar de Wikitude primero debemos de entender algunos conceptos básicos como la realidad aumentada; la realidad aumentada no es más que una dotación al usuario para que pueda combinar elementos virtuales con su entorno físico para crear una realidad mixta interactiva, en otras palabras añade una capa virtual a los elementos reales:

wikitude developer

La realidad aumentada es la incorporación de datos en un entorno real por medio de otras técnicas utilizadas como la reconocimiento de imágenes.

Wikitude, una herramienta fundamental para crear contenido de Realidad Aumentada

Antes de seguir hablando de Wikitude y todas sus virtudes y facilidades que nos trae para trabajar con la Realidad Aumentada sin necesidad de invertir un dólar o euro; vamos ha hablar un poco sobre este recurso que nos permite crear contenido para la Realidad Aumentada fácilmente y de la Realidad Aumentada como tal.

¿Qué es la Realidad Aumentada?

La Realidad Aumentada es un poderoso recurso que puede ser empleado para distintos fines, que van desde el fines recreativos, como juegos hasta fines educativos, son empleados por museos, museos vivos que podemos interactuar de manera digital con todos los recursos, esculturas y todo lo que hay en el museo mediante una simple tableta como podemos ver en este pequeño museo de México:

Y en juegos como Pokemon Go, que podría considerarse como el éxito más grande que ha tenido la Realidad Aumentada en juegos

Ok, pero que es la Realidad Aumentada

Todo esto que hemos introducido se hace con el propósito de indicar que es la Realidad Aumentada que simplemente la podemos definir como el enriquecimiento, el agregado de contenido digital a un entorno real, así de simple, este contenido digital se agrega mediante una pantalla de un dispositivo que corra un Sistema Operativo que permita tal hazaña, como Android y/o iOS, este contenido agregado no se agrega de manera aleatoria, existen distintas formas de reconocer tu entorno y actuar en consecuencia, uno de los más interesantes y más empleados es el reconocimiento de imágenes, que permite detectar patrones básicos, compararlos con un repositorio de datos en nuestra aplicación y "hacer algo" este algo es desplegar más información, ya sea mediante videos, textos, enlaces, imágenes, etc, en realidad una vez reconocido podemos hacer cualquier cosa que queramos; esto ya lo vamos a introducir en la siguiente sección de manera más técnica con recursos reales.

La Realidad aumentada consiste en enriquecer la experiencia de usuario mediantes imágenes y demás contenido a través de la pantalla y cámara del dispositivo

Por qué desarrollar aplicaciones en realidad aumentada: Usos

Como indicamos antes esta es una tecnología que todavía no ha sido explotada como debe ser, un ejemplo de éxito se lo lleva Niantic con su Pokemon Go, pero también puedes crear tus aplicaciones en realidad aumentada por los siguientes motivos:

  • Promueve tus productos de una forma única: Como todo el la vida, lo único, lo diferente, lo innovador gusta a la gente lo que sale de lo común lo atractivo, ve cómo puedes implementar esta tecnología en tu negocio; por ejemplo Ikea y su genial aplicación para colocar muebles en tu sala:
  • Mayor visualización: Esto es una forma de llamar a otro público, principalmente joven que le encantan estas cosas, acercar la Realidad Aumentada a tu negocio podría atraer a más jóvenes y Aumentar tus ventas.
  • Diferenciarse de la competencia Esto puede ser un resumen de todo lo anterior, una de las virtudes, es diferenciarte de la competencia y marcar tu propio camino, sin hacer siempre lo mismo si no algo diferente.

Conociendo Wikitude

A este punto es probable que ya tengas una idea más clara de la Realidad Aumentada, de como crear aplicaciones, de como funciona y de lo que quieres hacer, así que si estás motivado o motivada para hacer tu aplicación, la siguiente sección es para ti; en esta sección veremos algunas de las características de Wikitude y veremos como iniciar con Wikitude:

Wikitude no es un software para crear realidad aumentada en PC o Mac, es una librería que cuenta con una gran API que nos permite crear contenido enriquecido como hablamos anteriormente para Android, iOS y otras plataformas muy importantes como puedes ver el el site oficial.

Licenciamiento de Wikitude

Wikitude es una SDK gratuita para proyecto no comerciales (paga caso contrario) que permite la creación de aplicaciones de Realidad Aumentada con Android y/o IOS como principales tecnologías y también mediante una extensión en Cordova, Unity entre otras, las cuales puedes consultar en la documentación oficial de la tecnología.

Características de Wikitude para la Realidad Aumentada

La SDK de Wikitude soportan otras tecnologías como geolocalización, reconocimiento de imágenes, reconocimiento en la nube, etc; puede ver el resto de las características en: Powerful Features.

Pero lo que hace verdaderamente especial a esta SDK es que permite que utilicemos tecnologías web (HTML, javaScript, CSS) para desarrollar nuestra aplicaciones de Realidad Aumentada y la SDK se actualizó en las últimas versiones para brindar un soporte Nativo para Android y/o IOS aunque su principal fuerte está en las tecnologías web como se mencionó anteriormente; lo que significa que no tenemos que manejar complejos eventos desde Android si no algo más intuitivo como lo son las tecnologías web del lado del cliente.

Términos fundamentales para poder trabajar y entender Wikitude

Siguiendo con la terminología básica de Wikitude, ya hablamos sobre la RA por las siglas de realidad aumentada, ahora hablaremos un poco sobre algunos términos los cuales son fundamentales para desarrollar en esta plataforma ya sea en Android o en IOS:

  • Target: No es más que un conjunto de datos extraídos de una imagen que es empleado por el tracker o rastreador al momento de reconocer una imagen y realizar alguna acción como mostrar capas de información, etc.
  • Target Collection: Como su nombre indica, es una colección de targets u objetivos que asocia los datos de un conjunto de targets que es empleado por el tracker para reconocer imágenes del mundo real detectadas por la cámara del dispositivo; la extensión de los Target Collection es de wtc y es un archivo que generamos desde el portal de Wikitude.
  • ClientTracker: Es el tracker o rastreador que analiza la cámara en vivo, y obtiene las imágenes 2D, analiza el Target Collection asociado al proyecto y busca coincidencias con la imagen que se obtiene a través de la cámara del dispositivo

Tipos de Realidad Aumentada

En esta sección explicaremos los tipos de realidad aumentada con la cual cuenta Wikitude al momento de construir nuestras aplicaciones para Android; en general podemos decidir trabajar con una API o plataforma web, que nos da todas las bondades de los desarrollos web o nativa que nos da una apariencia más profesional en nuestra aplicación de Realidad Aumentada.

API de JavaScript (web) para crear aplicaciones de RA con Android

Como mencionamos en un inicio existen dos formas con la cual podemos trabajar con Wikitude en Android, la primera es mediante tecnologías web lo cual consiste básicamente en llamar al architectView en nuestro proyecto y este el mismo le notificará sobre el ciclo de vida de todos los eventos que puedan ocurrir; el architectView crea una especie de lente mágico o una superficie en la cámara en donde se manejan los eventos; para incluir el architectView en nuestro proyecto debemos de agregar la siguiente etiqueta dentro de un FrameLayout en nuestro layout:

<com.wikitude.architect.ArchitectView android:id="@+id/architectView"
   android:layout_width="fill_parent" android:layout_height="fill_parent"/>

Luego debemos de crear páginas escritas en HTML ubicadas en la carpeta asset; que utilizan la API de ARchitect de ese directorio; dicho archivo debe de incluir:

<script src="architect://architect.js"></script>

Para poder utilizar dicha API solo necesitamos hacer páginas en HTML que utilizan esta API de Realidad Aumentada (architect) que está hecha en JavaScript para hacer que nuestras aplicaciones funcionen; esta forma de crear aplicaciones con realidad aumentada se le conoce como (al menos así le llaman en la documentación oficial) ARchitect worlds; puedes consultar la documentación oficial en Android JavaScript API.

API nativa para crear aplicaciones de RA con Android

La otra forma que tenemos es empleando código nativo o código java sin necesidad de incorporar código web; esta API es algo pequeña pero bastante interesante dependiendo de lo que queramos hacer ya que todo el prosesamiento de imágenes reconocidas son resueltas en la misma Actividad o Fragment en donde tengamos especificado el reconocimiento de imágenes o traking y podemos realizar fácilemente múltiples acciones dentro de nuestra actividad; puedes consultar la documentación oficial en Android Native API

Dispositivos Soportados para trabajar con Wikitude

Android 4.3 o superior con una alta densidad por pixeles (hdpi) y por supuesto; el equipo debe de tener una cámara trasera.

Desarrollando aplicaciones de Realidad Aumentada con Wikitude

En este punto te daremos algunos recursos que no puedes dejar pasar por alto si quieres iniciarte, daremos una breve introducción a cada uno para que tengas una idea más clara; lo primero que debes es comenzar desde las bases, como indicamos antes, el recurso (o uno de los más populares) más popular con la realidad aumentada es el Reconocimiento de Imágenes, que consiste en que mediante la cámara del dispositivo pueda reconocer objetos del mundo real, pero como reconoce estos objetos...

1. Creando nuestra colección de objetivos para reconocer imágenes del mundo real

esto lo hace mediante una colección de objetivos qué es data acerca de las imágenes y esto lo debes suministrar mediante una aplicación en el portal oficial de Wikidute debes suministrar y de esta forma Wikitude internamente reconoce las imágenes y activa un trigger un disparador o un evento, como lo quieras llamar, así que lo primero que debes entender es cómo crear este paquete con información de las imágenes y en esta entrada se explica todo esto:

2. Reconociendo las imágenes y actuando en consecuencia: RA

Bien, ya en este punto tienes listo tu colección de objetivos, que lo genera Wikitude con las imágenes que suministraste, ahora debes de empezar a codificar, y trabajar, lo primero que debes hacer es reconocer una imagen; este proceso se realiza mediante la cámara del dispositivo empieza a analizar su entorno en busca de coincidencias, algo como ocurre con el a href="/blog/android/como-crear-un-lector-de-codigos-qr-en-android-con-android-studio">código QR que analiza su entorno en busca de un código QR, aquí es lo mismo solo que las coincidencias que busca son en base a las imágenes suministradas en el paso anterior de las cuales Wikitude genera una data y luego es empleado para encontrar coincidencias; para eso te traemos estos estupendos recursos que vamos desde las imágenes a emplear hasta la completa codificación del experimento:

Como puedes ver, Wikitude emplea tecnologías webs, por lo que te será muy fácil de esta forma traer contenido enriquecido que empleamos en todas las webs, videos, imágenes, textos, hacer llamadas Ajax y emplear jQuery si así lo deseas o lo que te venga en gana.

Ubicación geográfica y actuando en consecuencia: RA

La otra forma que tenemos de trabajar, es con el posicionamiento geográfico, los famosos puntos de interés o POIs por sus siglas en inglés, esta es otra forma estupenda de trabajar, aunque debes tener en cuenta que los puntos de interés o POIs deben ser amplios, no es buena idea usar POIs para puntos cerrados, porque esta tecnología funciona mediante el GPS y este no es infalible, tiende a variar por al menos unos metros así que si tu idea es posicionar puntos en concretos de centímetros o metros tal vez no sea gran idea, pero para todo lo demás puedes emplear los POIs como explicamos en esta entrada:

Realidad Aumentada sin tecnologías webs: Apps nativas

Desde un tiempo para aca Wikitude permite trabajar con la Realidad Aumentada empleando tecnologías webs, y si, es un poco más complejo el asunto pero aquí te damos la introducción; con esto podrás hacer muchísimas cosas al igual que antes, pero empleando todos las bondades que nos trae una aplicación nativa, una integración completa en nuestras aplicaciones de Realidad Aumentada:

Video thumbnail

Índice de contenido

Y la segunda parte:

Video thumbnail

Ya con estos estupendos recursos que te traemos podrás empezar a crear tus aplicaciones con la Realidad Aumentada; también te traemos los últimos videos que tenemos en el blog:

Conclusiones

En esta entrada te damos la bienvenida en el mundo de la Realidad Aumentada, desde en qué consiste, hasta algunos ejemplos para que te centres mejores, te damos motivación para que la emplees en tu negocio y te enseñamos a crear tus propias aplicaciones de Realidad Aumentada, porque la RA vino para quedarse y estará mucho más con nosotros, en el transcurso de los años veremos como la RA se va puliendo más y más hasta hacerse más y más inteligente con mejores desempeños.

Desarrollando aplicaciones de Realidad aumentada con Wikitude (parte 1)

En esta primera entrega veremos como configurar nuestro proyecto Android para comenzar a utilizar esta librería de realidad aumentada, para esto utilizaremos Eclipse con el plugin ADT.

Importar Wikitude SDK en nuestro proyecto Android

Primero debemos descargar la SDK de Wikitude; lo podemos hacer dando clic aquí, clic en el boton download; luego de eso basicamente debemos de seguir los mismos pasos explicados en el articulo de ¿Cómo importar una librería (jar) en Android? para importar nuestra librería.

Luego de que hayamos importado correctamente nuestra librería al proyecto debemos de realizar la siguiente configuración en eclipse:

Preferences - Android - Build y asegurate de que la opción Force error when external jars contain native libraries esté deseleccionada (unchecked).

Configurando nuestro proyecto Android

La siguiente configuración será a nivel de nuestro proyecto, específicamente en nuestro androidmanifest.xml; agregaremos los siguientes permisos necesarios para el correcto funcionamiento de la SDK Wikitude:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.location" android:required="true" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
<uses-feature android:name="android.hardware.sensor.compass" android:required="true" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />

La actividad (activity) que vaya a manejar la Realidad Aumentada debe de agregar el siguiente atributo en el androidmanifest.xml:

<activity android:name="com.yourcompany.yourapp.youractivity"
   android:configChanges="screenSize|orientation"/>

El layout, de la actividad que vaya a manejar la Realidad Aumentada deber ser el siguiente; y debe de estar contenido dentro de un FrameLayout:

<com.wikitude.architect.ArchitectView android:id="@+id/architectView"
   android:layout_width="fill_parent" android:layout_height="fill_parent"/>

Estructura básica de Wikitude en nuestro proyecto Android

Por último crearemos la estructura base dentro de la carpeta asset y así tener la estructura de nuestro ARchitect worlds listo; quedando de la siguiente manera:

assets carpeta

Recordar que dentro de nuestro documento HTML debe de incluirse una referencia a la API de ARchitect; quedando de la siguiente manera nuestro index.html:

<!DOCTYPE HTML>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title></title>
	<script src="architect://architect.js"></script>
</head>
<body>
</body>
</html>

Conclusiones

En esta primera entrega solo hemos configurado el ambiente base para utilizar esta librería; si corres el proyecto con las configuraciones explicadas; veras que no aparecerá nada muy emocionante en la pantalla; (una pantalla en negro probablemente); pero no desesperes, en próximas entrega veremos como trabajar con la Realidad Aumentada con esta increíble API; podrás encontrar el ejemplo completo en nuestro repositorio de github Android/WikitudeParteUno o haciendo clic aquí.

Cómo crear un Target collection en Wikitude

En esta entrada explicaremos como crear un Target collection en Wikitude.

¿Qué es el Target collection?

Un Target collection no es más que una colección de Target; un Target es la imagen destino que será utilizada por el Tracker para reconocer una imagen.

Creando nuestro primer Target collection

Ahora procedamos a crear nuestro Target collection; para eso nos vamos al siguiente link:

  • Presionamos la opción Add project.
agregar proyecto
  • Le damos un nombre a nuestro proyecto y presionamos el botón Create.
crear proyecto
  • Clic en nuestro proyecto.
  • Ahora arrastramos (drag and drop) las imágenes a nuestro proyecto; las cuales deben ser PNG (sin pixeles transparentes) o JPG.
agregar imágenes
  • Creamos nuestro Target collection; para eso clickeamos las imágenes que formaran al mismo.
go to overview
  • Le damos un nombre y clic en Generate target collection.
generate target collection
  • Nos mostrará un mensaje como el siguiente; clic en la opción Go to overview y descargamos nuestro target collection.
go to overview

Rango de estrellas

En el punto 6 vemos que Wikitude nos clasifica las imágenes que hemos subido según un rango; veamos que significa:

0 estrellas: No es adecuada para el seguimiento y por lo tanto esta imagen no se puede rastrear.

1 estrellas: La imagen proporciona una capacidad de seguimiento limitada.

2 y 3 estrellas: Ofrecen una buena capacidad de seguimiento.

Consejos generales para las imágenes

Preferiblemente utilizar imágenes con varias texturas con un nivel alto de contraste; también puede aumentar el contraste a la imagen con algún editor de imágenes como gimp.

Evitar imágenes con grandes secciones de colores sólidos o transiciones de colores suaves o patrones repetitivos.

Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 2)

En esta segunda entrega crearemos nuestra primera aplicación funcional que emplee la Realidad Aumentada y el Reconocimiento de Imágenes como tecnologías claves en el desarrollo de la aplicación; esta entrada es la continuación dedonde explicamos cómo integrar la API de Wikitude con un proyecto Android.

Reconocimiento de Imágenes a través de Wikitude

Creando el Target collection de Wikitude

Referenciando el Target collection de Wikitude

Luego de que hayamos creado nuestro Target collection el siguiente paso será guardarlo dentro de nuestro proyecto android, aunque también puede ser alojado dentro de un servidor y ser referenciado via HTTP como explicamos antes:

<NuestroProyecto>/assets/base/assets/<targetcollection.wtc>

En nuestro ejemplo usaremos la siguiente imagen en el Target collection:

caratula java libro

Escribiendo nuestro ARchitect World (JavaScript)

var World = {
	loaded: false,
	init: function initFn() {
		this.createOverlays();
	},
	createOverlays: function createOverlaysFn() {
		// inicializamos el Tracker con el Target collection
		this.tracker = new AR.Tracker("assets/targetcollection.wtc", {
			onLoaded: this.worldLoaded
		});
		// creamos un overlay
		var javaDeitel = new AR.ImageResource("assets/javaDeitel.jpg");
		var overlay = new AR.ImageDrawable(javaDeitel, 0.2, {
			offsetX: -0.15,
			offsetY: 0
		});
 // indicamos el nombre del Target en el Tracker
		var javaLibro = new AR.Trackable2DObject(this.tracker, "javaLibro", {
			drawables: {
				cam: overlay
			}
		});
	}
};
// principal
World.init();

Primero creamos el Tracker llamando al método AR.Tracker pasando como parámetro el Target collection que creamos en el paso anterior.

Lo siguiente será indicarle la imagen que mostrará al momento de que el Tracker reconozca el Target en cuestión; llamando al método AR.ImageResource.

La imagen a mostrar es:

caratula java libro

Por último combinamos los dos pasos anteriores creando el objeto Trackable haciendo una llamada al método Trackable2DObject, los parámetros que reciben son:

  • El Tracker.
  • El nombre del Target en el Tracker.
  • Otras opciones.

Agregando el ARchitectView (código nativo) a nuestro proyecto:

Debemos de notificar al ArchitectView sobre el ciclo de vida en nuestra actividad; para eso podemos hacer algo como lo siguiente:

ArchitectView architectView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// la ruta del architectView en nuestro XML
		this.architectView = (ArchitectView) this
				.findViewById(R.id.architectView);
		final ArchitectConfig config = new ArchitectConfig("" /* license key */);
		this.architectView.onCreate(config);
		
	}
	
	/*
	 * Ciclo de vida en nuestra actividad 
	 */
	
	@Override
	protected void onResume() {
		super.onResume();
		if ( this.architectView != NULL ) {
			this.architectView.onResume();
		}
	}
	@Override
	protected void onPause() {
		super.onPause();
		if ( this.architectView != NULL ) {
			this.architectView.onPause();
		}
	}
	
	@Override
	protected void onStop() {
		super.onStop();
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		if ( this.architectView != NULL ) {
			this.architectView.onDestroy();
		}
	}
	@Override
	public void onLowMemory() {
		super.onLowMemory();
		if ( this.architectView != NULL ) {
			this.architectView.onLowMemory();
		}
	}
	@Override
	protected void onPostCreate( final Bundle savedInstanceState ) {
		super.onPostCreate( savedInstanceState );
		
		// IMPORTANTE cargamos el ARchitect worlds (codigo web: HTML CSS javaScript)
		this.architectView.onPostCreate();
		try {
			this.architectView.load("base/index.html");
			this.architectView.onResume();
		} catch (IOException e) {
			
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

Ejecutando la aplicación basada en Realidad Aumentada y Reconocimiento de Imágenes

Ahora correremos nuestro ejemplo en algún; luego de que "pasemos la cámara" por la siguiente imagen (o la carátula del libro si lo tienes):

caratula java libro

Veremos algo como lo siguiente.

screenshot aplicaciòn wikitude

¿Qué ha pasado?

Simplemente ha reconocido la imagen y a "echo algo", en este caso mostrar un overlay; para este entrada el overlay no es más que una imagen de la carátula del libro reconocido:

screenshot aplicaciòn wikitude

Podrás encontrar la aplicación completo en nuestro repositorio de github Android/WikitudeParteDos o haciendo clic aquí.

Las medidas SDUs en Wikitude

Según Wikitude Developer, en las aplicaciones de Realidad Aumentada, un objeto no puede ser definido en píxeles o medidas similares; el tamaño del objeto depende de la distancia en la que el observador "mire" el objeto del mundo real; la arquitectura de Wikitude utiliza las Scaled Distance Units (SDU), algo así en español como las Unidades de Escalada de Distancia. Las SDUs definen la relación entre el tamaño del objeto real y la distancia en la que se observa.

Vamos a algo un poco más práctico:

  • 1 SDU define que el tamaño de un objeto es exactamente un metro de altura y está situado a 10 metros de distancia.
  • 5 SDU define que el objeto tiene exactamente 5 metros de altura y se encuentra a 10 metros de distancia.

Otro punto importante, es que a medida en que se varía la distancia que hay entre el objeto del mundo físico y el observador, el objeto definido en SDU puede variar su tamaño (más pequeño mientras más lejos se encuentre el observador y más grande en caso contrario) e inclusive desaparecer.

Todo esto puede resultar un poco confuso, lo que recomendamos es utilizar distintos valores del SDUs para así definir el tamaño que consideremos como el más adecuado según el efecto que se desee conseguir .

La documentación oficial la puedes conseguir dando clic aquí.

Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 3)

Siguiendo con los artículos sobre el desarrollo de aplicaciones basadas en la Realidad Aumentada y Reconocimiento de Imágenes con Android y Wikitude SDK; en este artículo veremos cómo agregar capas de información cuando los Targets (Objetivos) sean reconocidos por el Tracker (Rastreador), si no reconoces estos dos términos (Targets y Tracker) le recomendamos leer el artículo pasado.

¿Qué es lo que queremos decir exactamente con "capas de información"?

Simplemente un cuadro (más bien un rectángulo) informativo sobre algún Ítem en particular, esta capa de información no será más que una página web que referenciamos desde el ARchitect World (JavaScript); algo como esto nos servirá como cuadro informativo:

<html>
    <head>
        <meta http-equiv='Content-Type' content='Type=text/html; charset=utf-8'/>
        <style>
            pre {
                font-size:42px;
                color:#FFF;
                text-align: justify;
            }
            .descripcion{
                background: #068;
                border: 10px solid #059;
                border-radius: 5px;
                padding: 5px;
                height: auto;
            }
        </style>
    </head>
    <body>
        <div class="descripcion">
            <pre>Este libro presenta las tecnologías </pre>
            <pre>de vanguardia para estudiantes, </pre> 
            <pre>profesores y desarrolladores de </pre>
            <pre>software.</pre>
            
        </div>
    </body>
</html> 

Cambios en el proyecto

El resto de la estructura del proyecto...

  • Target collection (Colección de objetivos, específicamente nuestras imágenes, si recuerdas la entrega anterior, era una imagen de la carátula del libro "Cómo programar en Java") ver Imagen 1.
  • ARchitectView (Código nativo Java).

...Será exactamente la que utilizamos en la entrega anterior, lo único que modificaremos será nuestro ARchitect World (JavaScript), cuyo contenido que lo compone se encuentra en la carpeta assets de nuestro proyecto:

<NuestroProyecto>/assets/base/

El JavaScript llamado "ra.js" está ubicado en:

<NuestroProyecto>/assets/base/js

Definiendo el nuevo ARchitect worlds (JavaScript)

Modificaremos el contenido del JavaScript "ra.js" por el siguiente:

var World = {
    loaded: false,
    init: function initFn() {
        this.createOverlays();
    },
    createOverlays: function createOverlaysFn() {
	// creamos un objeto de la clase HtmlDrawable
	htmlDrawable = new AR.HtmlDrawable({
	   uri:"http://www.desarrollolibre.net/public/page/wikitude/WIkitudeParte3DescripcionLibroComoProgramarEnJavaDeitel.html"
	}, 1,{offsetX : -1,rotation:90,opacity : 0.8,scale : 2});
        // inicializamos el Tracker con el Target collection (nuestra caratula del libro Deitel)
        this.tracker = new AR.Tracker("assets/targetcollection.wtc", {
            onLoaded: this.worldLoaded
        });
 	// indicamos el nombre del Target en el Tracker, basicamente al momento de que el Target sea rastreado por el Tracker el objeto htmlDrawable sera renderizado en la pantalla del dispositivo
        var javaLibro = new AR.Trackable2DObject(this.tracker, "javaLibro", {
            drawables: {
                cam: htmlDrawable
            }
        });
    }
};
// principal
World.init();

Explicando el nuevo JavaScript

La clase HtmlDrawable sirve para representar objetos a través de la Realidad Aumentada, con objetos nos referimos a elementos HTML, tales como div, textos, imágenes, etc.

La clase HtmlDrawable recibe los siguientes parámetros:

HtmlDrawable( contenido , width , opciones )

  • Un objeto JSON que representa el contenido HTML, el cual puede ser:
    • HTML: un string con todo el contenido HTML: HTML:"<div>Mi Div</div>"
    • URI: un enlace a una página con contenido HTML: URI:"http://www.desarrollolibre.net/public/page/wikitude/WIkitudeParte3DescripcionLibroComoProgramarEnJavaDeitel.html"
  • width: El ancho del objeto, el cual es un número punto flotante en SDUs.
  • opciones: Un objeto JSON que representa las configuraciones opcionales para personalizar el objeto; entre las principales tenemos:
    • offsetX: Medidas en punto flotantes dadas en SDUs, si el valor del mismo es positivo causará que el objeto se mueva a la derecha, caso contrario se moverá a la izquierda.
    • offsetY: Medidas en punto flotantes dadas en SDUs si el valor del mismo es positivo causará que el objeto se mueva hacia arriba, caso contrario se moverá hacia abajo.
    • rotation: Define la rotación del objeto en grados 0-360.
    • scale: Medidas en punto flotante que permite escalar el objeto; en donde 1.0 representa en tamaño del objeto original.
    • opacity: Opacidad del objeto, donde el mayor valor es 1.0 (objeto completamente visible) y el menor es 0.0 (objeto invisible).
    • opacity: Opacidad del objeto, donde el mayor valor es 1.0 (objeto completamente visible) y el menor es 0.0 (objeto invisible). La lista completa la puedes encontrar en la documentación oficial

Probando nuestra aplicación

Ahora proyecta la aplicación hacia esta imagen:

caratula java libro

Imagen 1: Carátula del Libro Cómo programar en Java Deitel.

Y veras algo en la pantalla de tu dispositivo parecido a las siguientes imágenes:

capas de información con Realidad Aumentada y Reconocimiento de Imágenes

Imagen 2: Screenshot de la capa de información superpuesta al Target.

capas de información con Realidad Aumentada y Reconocimiento de Imágenes

Imagen 3: Screenshot de la capa de información superpuesta al Target.

Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 3.2)

Un último detalle que olvide explicar en la entrega anterior: Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 3), es el uso del atributo HTML dentro de la clase HtmlDrawable, en este artículo realizaremos una aplicación para Android con las mismas características de la aplicación creada en el artículo pasado, pero esta vez, usaremos el atributo HTML en vez del atributo URI.

Diferencias entre este entrega y la anterior

¿Cuál vendría siendo la diferencia entre crear un cuadro informativo con el atributo HTML en vez del atributo URI? la diferencia consiste en que todo el contenido (HTML) estará dentro del "ra.js" en vez de estar en un archivo aparte, y digo archivo aparte en vez de un archivo alojado en Internet porque URI puede referenciar tantos elementos dentro de la apk:

uri:"<NuestroProyecto>/assets/base/WIkitudeParte3DescripcionLibroComoProgramarEnJavaDeitel.html"

Como fuera de ella:

uri:"http://www.desarrollolibre.net/public/page/wikitude/WIkitudeParte3DescripcionLibroComoProgramarEnJavaDeitel.html"

Nuestro archivo "ra.js" quedará así:

<html>
var World = {
    loaded: false,
    init: function initFn() {
        this.createOverlays();
    },
    createOverlays: function createOverlaysFn() {
	// creamos un objeto de la clase HtmlDrawable
	htmlDrawable = new AR.HtmlDrawable({
	   html:"<div style='font-size:42px;color:#FFF;background: #068;border: 10px solid #059;border-radius: 5px;padding: 5px;height: auto;'><pre>Este libro presenta las tecnologías </pre><pre>de vanguardia para estudiantes, </pre><pre>profesores y desarrolladores de </pre><pre>software.</pre></div>"
	}, 1,{offsetX : -1,rotation:90,opacity : 0.8,scale : 2});
        // inicializamos el Tracker con el Target collection (nuestra caratula del libro Deitel)
        this.tracker = new AR.Tracker("assets/targetcollection.wtc", {
            onLoaded: this.worldLoaded
        });
	// indicamos el nombre del Target en el Tracker, basicamente al momento de que el Target sea rastreado por el Tracker el objeto htmlDrawable sera renderizado en la pantalla del dispositivo
        var javaLibro = new AR.Trackable2DObject(this.tracker, "javaLibro", {
            drawables: {
                cam: htmlDrawable
            }
        });
    }
};
// principal
World.init();

Como podemos ver, tanto el HTML como el CSS están contenidos dentro del div:

html:"<div style='font-size:42px;color:#FFF;background: #068;border: 10px solid #059;border-radius: 5px;padding: 5px;height: auto;'><pre>Este libro presenta las tecnologías </pre><pre>de vanguardia para estudiantes, </pre><pre>profesores y desarrolladores de </pre><pre>software.</pre></div>"

Esto resulta en algo bastante molesto y poco práctico, podríamos pensar que es posible colocar el CSS en un archivo aparte, como por ejemplo dentro de un .css:

/WikitudeParteTresDos/assets/base/css/style.css

o en el index.html:

/WikitudeParteTresDos/assets/base/index.html

Pero si haces esto, Wikitude no busca los estilos en estos sitios y por lo tanto los elementos no tomaran el estilo.

Conclusiones

Entonces, ¿cuál de los dos atributos usamos el HTML o el URI?; depende de lo que queramos hacer, si vamos a tener un contenido estático que no vamos a actualizar y es bastante pequeño tal vez consideres usar el HTML, podría resultar bastante útil si no queremos tener tantos .html; pero si hay mucho contenido y estilos que deseamos actualizarlos con frecuencia el URI podría resultarnos una mejor opción.

Podrás encontrar la aplicación completa en nuestro repositorio de github Android/WikitudeParteTresDos o haciendo clic aquí.

Target Collection y el ARchitect World en la nube con Wikitude

Una de las cosas que hace grande a la SDK de Wikitude, es la posibilidad de que el Target Collection (Colección de Objetivos) y parte del ARchitect World (JavaScript, CSS y HTML) estén ubicados en algún servidor en Internet (en la nube), en vez de estar instalados en la carpeta assets del proyecto Android; ¿de que podría servirnos de que el Target Collection y parte del ARchitect World estén ubicados en algún servidor aparte en vez de estar dentro de la apk? veamos:

Dividiendo la aplicación en dos

Es posible realizar una administración más flexible de la aplicación: ¿Como es esto?, quiero decir que podemos dividir a la aplicación es dos:

  • La apk: Es el instalador para Android. En fase de desarrollo viene siendo nuestro proyecto en Eclipse, el código nativo de la aplicación, además del index.html, que es el que referencia al JavaScript; el cual (el JavaScript) es el que genera el contenido que será desplegado como capas de Realidad Aumentada.
  • El ARchitect World junto con el Target Collection: Representando el punto de interés para un usuario administrador y las que mayores modificaciones tendrán a lo largo del ciclo de vida de la aplicación.

Específicamente...

Veámoslo de otra forma, imaginemos que nuestro cliente nos pide un módulo administrativo en el cual se desea poder gestionar las imágenes del Target Collection y tal vez configurar la interfaz (El CSS) a cierto grado (colores, tipografía, opacidad, etc), pero hay que recordar que este usuario administrador probablemente no sea programador y por lo tanto no le vamos a obligar a tener que compilar el proyecto para generar la apk y subirla a la Google Play por agregar un par de imágenes y tal vez querer cambiar un color; pasos que debería realizar si tuviera que modificar el contenido de la carpeta assets, que es donde se encuentra instalado el Target Collection y parte del ARchitect World en los ejemplos pasados; Android NO permite modificar el contenido de la carpeta assets una vez que la apk ha sido instalada en el dispositivo, además de que este proceso puede resultar un poco engorroso para un usuario que no sea programador (o que no le interese nada el el área).

¿Qué deberíamos hacer?

Dejar que el administrador haga sus modificaciones en el Target Collection (agregar, eliminar y actualizar imágenes) y en el ARchitect World (modificar el CSS) en una sección aparte que llamaremos módulo administrativo; al estar parte del ARchitect World y el Target Collection en un servidor y NO instalado en el dispositivo, los cambios realizados por el administrador tendrán un efecto inmediato y sin la necesidad de actualizar la apk.

target Collection y parte del ARchitect world en la nube

Target Collection y parte del ARchitect World en la nube; la aplicación se referencia a estos elementos para así poder reconocer imágenes y obtener el contenido a desplegar como capas de Realidad Aumentada.

Suena perfecto ¿verdad?, lo malo, es que la aplicación necesitará de acceso continuo a Internet para funcionar (para "jalar" el JavaScript y el CSS que están en un servidor remoto), pero si el acceso a Internet no es un problema esto no debería de ser considerado como un gran inconveniente; además de esto; es necesario volver a generar el JavaScript cada vez que haya una modificación en la aplicación; recordemos que es el JavaScript el responsable de reconocer las Imágenes del Target Collection y crear las capas de Realidad Aumentada (entre otras cosas); esto vendría siendo nuestro módulo de administración lo cual será tema para otro artículo y que básicamente es el responsable de volver a generar el JavaScript de forma automática para que las nuevas imágenes sean reconocidas por el Tracker.

Veamos las configuraciones que deberíamos realizar en el proyecto Android para que se conecte a un servidor para consultar el Target Collection y parte del ARchitect World, el JavaScript perteneciente al ARchitect World llamado "ra.js" quedará referenciado de la siguiente manera en el index.html; el cual estará ubicado en <NuestroProyecto>/assets/base/assets/index.html):

	<script type="text/javascript" src="http://www.desarrollolibre.net/public/page/wikitude/ra.js"></script>

Los elementos de interés:

1

El Target Collection, ubicado en un servidor y NO instalado en la aplicación junto con el index.html:

        this.tracker = new AR.Tracker("http://www.desarrollolibre.net/public/page/wikitude/targetcollection.wtc", {
            onLoaded: this.worldLoaded
        });

2

Los demás recursos, los Drawables, que sirve para representar objetos a través de la Realidad Aumentada; los recursos (imágenes y páginas web) para crear un objeto Drawable, estarán en un servidor y NO instalado en la aplicación:

	var cuadroInformativo = new AR.HtmlDrawable({
	   uri:"http://www.desarrollolibre.net/public/page/wikitude/90/WIkitudeParte3DescripcionLibroComoProgramarEnJavaDeitel.html"
	}, 1,{offsetX : -1,rotation:90,opacity : 0.8,scale : 2});
	var javaDeitel = new AR.ImageResource("http://www.desarrollolibre.net/public/page/wikitude/90/javaDeitel.png");
	var overlay = new AR.ImageDrawable(javaDeitel, 0.2, {
		offsetX: -0.15,
		offsetY: 0
	});

Conclusiones

Bueno esto es todo, lo importante de este artículo, es el de conocer una gran funcionalidad que nos brinda la SDK de Wikitude que puede pasar desapercibida, que es la de poder conectarse a un servidor para reconocer las imágenes, generar y obtener el contenido a mostrar al usuario a través de la pantalla de su dispositivo.

Podrás encontrar la aplicación completo en nuestro repositorio de github Android/WikitudeParteCuatro o haciendo clic aquí.

Algunas pantallas:

capas de información con Realidad aumentada y Reconocimiento de Imágenes
capas de información con Realidad aumentada y Reconocimiento de Imágenes

Puntos de Interés (POI) con Realidad Aumentada en Wikitude

En este artículo veremos cómo marcar (mostrar los Drawables) un sitio a través de Puntos de Interés (POI); en otras palabras reconocer una zona por su posicionamiento geográfico a través de los llamados Puntos de Interés (POI) en vez de utilizar el Reconocimiento de Imágenes.

Pero, ¿qué es un POI o Punto de Interés?

Un POI no es más que una ubicación o punto en específico; básicamente es un lugar interesante un Punto de Interés catalogado por alguien; los mapas y GPS contienen muchos de estos puntos llamados POI.

Los POIs en Wikitude son manejados por una clase llamada GeoLocation, la cual representa una localización en la tierra en su espacio 3D; como podrás imaginarte, esta recibe tres parametros:

Parámetros de la clase GeoLocation

  • Latitude: Latitud de la localización dada en decimales.
  • Longitude: Longitud de la localización dada en decimales.
  • Altitude (optional): La altitud de la localización dada en metros.

El tercer componente hace posible ubicar un POI en el espacio 3D.

Ejemplo de la clase GeoLocation

var location3D = new AR.GeoLocation(47.77317, 13.069929, 320.0); // latitude, longitude, altitude
var location2D = new AR.GeoLocation(47.77317, 13.069929); // latitude, longitude

Ya sabemos como crear un Punto de Interés o POI en Wikitude, ahora debemos de crear el objeto Drawable para marcar el sitio; recordando los artículos pasados; esto no es más que el contenido que se desea mostrar cuando ocurra el reconocimiento ya sea mediante el Reconocimiento de Imágenes o por la localización (nuestro caso) a través de los POI:

htmlDrawable = new AR.HtmlDrawable({uri:"pagina.html"}, 1);

Ya tenemos el Punto de Interés POI y el contenido a mostrar. ¿Qué ente se encarga de localizar y analizar la zona en donde se encuentra el usuario y de esta forma mostrar los recursos establecidos en el Drawable (si y sólo si el usuario se encuentra dentro de un POI)?; en otras palabras; ¿cómo mostramos los Drawable según la posición del usuario?.

La clase GeoObject

Este clase permite especificar al menos un POI (objetos de la clase GeoLocation) o localización y los recursos Drawable a mostrar:

Parámetros de la clase GeoLocation

  • POI: Referencia al objeto GeoLocation.
  • Opciones (opcional): Otros parámetros para personalizar el objeto; permite definir qué es lo que se desea hacer luego de que el usuario esté dentro de un POI:
    • enabled: Booleano que indica si está o no activo el objeto GeoObject.
    • renderingOrder (por defecto 0): Número que define el orden de prioridad entre varios objetos de la clase GeoObject.
    • onEnterFieldOfVision: Función que se ejecuta cuando el usuario entra dentro de un POI.
    • onExitFieldOfVision: Función que se ejecuta cuando el usuario abandona un POI.
    • onClick: Función que se ejecuta al darle click (tocar la pantalla del dispositivo) a un objeto Drawable.
    • drawables.cam: Son objetos Drawables que se mostrarán en la pantalla del dispositivo.
    • drawables.radar: Radar para que el usuario ubique otros POI de interés cercanos a su posición:
Wikitude Radar
  • drawables.indicator: Son objetos Drawables (como una flecha) que se dibujan en el borde de la pantalla para visualizar la posición de otros objetos fuera de la cámara.

Ejemplo del objeto GeoLocation, Drawable y GeoObject

var location3D = new AR.GeoLocation(47.77317, 13.069929, 320.0); // latitude, longitude, altitude
//recurso Drawable
htmlDrawable = new AR.HtmlDrawable({uri:"pagina.html"}, 1);
//construimos el objeto GeoLocation
var geoObject  = new AR.GeoLocation(location3D,htmlDrawable); // POI -GeoLocation-, opciones

Resumen

Podemos resumir lo visto hasta el momento de la siguiente manera:

  • Definir el POI.
  • Definir el objeto Drawable o lo que nos interesa mostrar cuando el usuario esté ubicado en el POI.
  • El objeto que maneja los dos anteriores; localizar y analizar la zona en donde se encuentra el usuario y si esta coincide con el (los) POI(s) establecido(s) mostrar los recursos establecidos (Drawable). Viene siendo algo así como el Tracker en el Reconocimiento de Imágenes.

Conclusiones

El uso de los POI es algo que se agradece cuando otras tecnologías como el Reconocimiento de Imágenes falla o no se desea utilizar por diversos motivos; cuenta con mayor precisión que el Reconocimiento de Imágenes (ya que es Geográfico y no hay margen de error); sin embargo, podemos utilizar ambas tecnologías (POIs y Reconocimiento de Imágenes) de manera conjunta como veremos en próximos artículos.

Enlaces de Interés

¿Cómo reconocer múltiples Objetivos (Targets) con el Tracker en Wikitude?

Descargar Fuente en GitHub

En este artículo veremos cómo reconocer múltiples Objetivos (Targets) almacenadas en el Target Collection con el Tracker; para ello es necesario seguir tres pasos básicos:

Reconocimiento de Imágenes y Realidad Aumentada en tres pasos...

  • Declarar e inicializar el Tracker.
  • Crear los Drawables.
  • Vinculando los Targets en el Target Collection con los Drawables.

1. Declarar e inicializar el Tracker

En la siguiente sección de código declaramos el Tracker; recordando artículos pasados; el Tracker representa al Target Collection (que es el binario con extensión .wtc; ver como crear el Target Collection); analiza la cámara en busca de Target almacenados en el Target Collection; en otras palabras; busca coincidencias entre lo que "esta viendo" mediante la cámara con lo que hay almacenado en el Target Collection; el Target Collection puede estar local al dispositivo u en un servidor en Internet.

Inicializamos el Tracker pasándole como primer parámetro el Target Collection y como segundo parámetro las opciones (sin opciones para este ejemplo):

      // inicializamos el Tracker con el Target collection
        this.tracker = new AR.Tracker("assets/Targetcollection.wtc", {});

Las imágenes almacenadas en el Tracker lucen de la siguiente manera:

target collection de ejemplo

Importante notar el nombre de las imágenes (Targets) más adelante para vincular el Target con un Drawables:

  • img_uno.png
  • img_dos.png
  • img_tres.png

2. Creando los Drawables

Paso siguiente de creado el Tracker, es crear los recursos; gráficos como imágenes, textos, figuras geométricas, páginas web, botones, etc; los cuales se les conocen con el nombre de Drawables:

Realidad Aumentada para el Target uno

Para el primer Target utilizaremos una imagen:

        // indicamos la imagen recurso
        var imgUno = new AR.ImageResource("assets/img_uno.png");
	// creamos el Drawable usando el recurso
        var drawableImage = new AR.ImageDrawable(imgUno, 0.2, {
            offsetX: -0.15,
            offsetY: 0
        });

Realidad Aumentada para el Target dos

Para el siguiente Target utilizaremos una página web:

        // creamos el Drawable usando una uri
        drawablePageWeb = new AR.HtmlDrawable({
            uri: "assets/pagina1.html"
        }, 1, {});

Realidad Aumentada para el Target tres

Para el último Target utilizaremos una imagen y una página web:

        // creamos el Drawable usando una uri
        drawablePageWebDos = new AR.HtmlDrawable({
            uri: "assets/pagina2.html"
        }, 1, {});
        // indicamos la imagen recurso
        var imgDos = new AR.ImageResource("assets/img_dos.png");
	// creamos el Drawable usando el recurso
        var drawableImageDos = new AR.ImageDrawable(imgDos, 0.2, {
            offsetX: -0.15,
            offsetY: 0
        });

Nota: La imagen almacenada en la ruta assets/img_uno.png o assets/img_dos.png NO es la misma utilizada para crear el Target Collection; utilizo el mismo nombre para tener una convención.

Nota: Fueron creados los Drawables indicando un recurso.

3. Vinculando los Targets en el Target Collection con los Drawables

Ahora ¿Cómo indicamos al Tracker que Drawables va a vincular con los Targets almacenados en el Target Collection?; la siguiente sección de código se encarga de eso:

 // indicamos el nombre del Target en el Tracker
        var TrackableUno = new AR.Trackable2DObject(this.tracker, "img_uno", {
            drawables: {
                cam: drawableImage
            }
        });
        var TrackableDos = new AR.Trackable2DObject(this.tracker, "img_dos", {
            drawables: {
                cam: drawablePageWeb
            }
        });
        var TrackableTres = new AR.Trackable2DObject(this.tracker, "img_tres", {
            drawables: {
                cam: [drawablePageWebDos,drawableImageDos]
            }
        });

Ahora utilizamos el Tracker declarado en el paso 1 para referenciar un Target en específico dentro del Target Collection (un Trackable2DObject) y con este (el Target referenciado) asociamos uno o varios objeto virtuales creados el el paso 2 (la capa de Realidad Aumentada representado por un Drawables) al Target; en otras palabras, el Trackable2DObject vincula un Target en un Target Collection a un Drawables.

En la práctica creamos un Trackable2DObject con el Tracker (primer parámetro, eligiendo un Target por vez dentro del Target Collection (segundo parámetro), el Target al ser rastreado por el Tracker a través de la cámara y el Drawables o el que representa el objeto del mundo real (tercer parámetro), será proyectado sobre el objetivo tan pronto como el Target sea visible y detectado en la escena.

Nota: Indicamos un Drawable y un Target por vez.

Conclusiones

Resulta importante saber como es el proceso básico para adentrarnos en este fascinante mundo de la Realidad Aumentada; además de que en todos los artículos anteriormente señalados sólo empleamos un Trackable2DObject; creando a veces la duda de como referencias a varios Targets en el Target Collection y vincularlos con algún recurso Drawable.

Printscreen o Pantallazos de la aplicación

reconocimiento de imágenes con wikitude ejemplo 1
reconocimiento de imágenes con wikitude ejemplo 2
reconocimiento de imágenes con wikitude ejemplo 3
reconocimiento de imágenes con wikitude ejemplo 1
reconocimiento de imágenes con wikitude ejemplo 2
reconocimiento de imágenes con wikitude ejemplo 3

 

Descargar Fuente en GitHub

Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 1

En las siguientes entradas que escribiré en el blog sobre esta temática estarán orientadas a explicar y mostrar a través de ejemplos ¿cómo mostrar Puntos de Interés (Point of Interest,POI) a través de la Realidad Aumentada con Wikitude?; esta primera entrada esta dedicada a introducir algunos conceptos claves y consideraciones sobre el uso de los proveedores de localización en Android y de los POI en Wikitude.

¿Qué es un Punto de Interés?

Un Punto de Interés es un lugar específico registrable a través de coordenadas geográficas (latitud, longitud y altitud) que es considerado de interesante por alguna persona: restaurantes, hoteles, edificios, etc son ejemplos de sitios de interés; para crear un Punto de Interés (POI) en Wikitude es necesario como mínimo la latitud y la longitud para ubicar un sitio en el espacio 2D, pero también es posible ubicar un sitio en un espacio 3D empleando la altitud.

Consideraciones sobre los proveedores de localización en Android

  • Generalmente todos los dispositivos Android cuentan con al menos dos tipos de proveedores de localización:
    • El conocido GPS: Que determina la ubicación del dispositivo a través de satélites.
    • Por red móvil y WiFi: Que ubica al dispositivo mediante las antenas de telefonía móvil o mediante puntos de acceso Wi-Fi.
    • Estos servicios que permite obtener la localización del dispositivo, en realidad, no devuelven la posición actual del dispositivo, si no la última posición válida que tengan registrado.
  • Debes de habilitar al menos uno de ellos para poder trabajar con los Puntos de Interés, ve a Ajustes >> Acceso a tu ubicación, en tu dispositivo con Android:
  • En todos los proveedores de datos existen márgenes de errores, en otras palabras; la precisión varía en metros e incluso kilómetros y esto puede deberse a muchos factores, cielo nublado, una obstrucción física entre el dispositivo y los satélites etc; por lo tanto no resulta de buena idea si deseas ubicar un sitio que requiera metros de precisión.

Consideraciones sobre los Puntos de Interés en Wikitude

  • La API que permite trabajar con los Punto de Interés en Wikitude, está hecha para actualizarse constantemente según la posición del dispositivo; en otras palabras, debemos de estar cargando constantemente POIs cercanos a la posición del dispositivo, ya que es posible que este se desplace cierta cantidad de metros cada cierto tiempo, la aplicación que vayamos a diseñar debe de estar constantemente preguntando la posición del dispositivo y trayendo los Puntos de Interés cercanos a la posición del dispositivo; este tema lo trataremos en mayor detalle en la próxima entrada.

Primeros pasos con la API de Wikitude para definir un Punto de Interés en el ARchitect worlds

En esta sección creemos y mostraremos un simple POI desde el ARchitect worlds de Wikitude; no es necesario tener ninguno de los proveedores de localización habilitados, debido a que cargaremos sitios ficticios cercanos a la posición del dispositivo (la cual es cero si no hay una posición válida).

El método locationChangedFn para obtener la posición del dispositivo

Este método es invocado cada vez que haya una actualización en la posición del dispositivo; como podrás imaginar, recibe cuatro parámetros:

  • Latitud de la localización.
  • Longitud de la localización.
  • Altitud de la localización.
  • Precisión de la localización.

    locationChanged: function locationChangedFn(lat, lon, alt, acc) {}

A partir de ahí, es posible crear todos los Puntos de Interés que deseamos; consultando mediante Servicios Web, HTTP, etc; para efecto de este artículo simplemente crearemos un Punto de Interés cercana a la posición del dispositivo:

    var poiData = {
       "id": 1,
       "longitude": (lon + (Math.random() / 5 - 0.1)),
       "latitude": (lat + (Math.random() / 5 - 0.1)),
       "altitude": 100.0
    };

Puede darse el caso que deseemos cargar los Puntos de Interés una única vez y que no se actualice sin importar el tiempo o la distancia transcurrida, para ello, empleamos una bandera:

World.initiallyLoadedData

La cual estableceremos en false una vez que se realice la primera (y única) consulta a la posición del dispositivo; nuestro código quedaría de la siguiente manera:

locationChanged: function locationChangedFn(lat, lon, alt, acc) {
    // valido que es la primera vez que estoy recibiendo datos (lat, lon, alt, acc)
    if (!World.initiallyLoadedData) {
        var poiData = {
            "id": 1,
            "longitude": (lon + (Math.random() / 5 - 0.1)),
            "latitude": (lat + (Math.random() / 5 - 0.1)),
            "altitude": 100.0
        };
        World.loadPoisFromJsonData(poiData);
        World.initiallyLoadedData = true;// recibi datos, no me interesa actualizar los datos segun la posicion del dispositivo
    }
}

El método loadPoisFromJsonData para construir y mostrar el Punto de Interés mediante la Realidad Aumentada

La función loadPoisFromJsonData es usada para crear objetos GeoObject, o objetos basados en la Realidad Aumentada según la posición:

	loadPoisFromJsonData: function loadPoisFromJsonDataFn(poiData) {
		World.markerDrawable = new AR.ImageResource("img/marker.png");
		var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);
		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});
		// create GeoObject
		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});
	}

Analizando la función anterior...

Indicamos la imagen que funcionará como marcador o Punto de Interés:

World.markerDrawable = new AR.ImageResource("img/marker.png");

Creamos un objeto con una localización 3D en el espacio basada en coordenadas:

var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);

Encapsulamos la imagen y le aplicamos ciertas operaciones a la misma:

		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});

Creamos un objeto virtual cuya posición está especificada a través del objeto markerLocation:

		// create GeoObject
		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});

Más información en la Wikitude SDK API Reference.

El código completo:

var World = {
	initiallyLoadedData: false,
	markerDrawable: NULL,
	loadPoisFromJsonData: function loadPoisFromJsonDataFn(poiData) {
		World.markerDrawable = new AR.ImageResource("img/marker.png");
		var markerLocation = new AR.GeoLocation(poiData.latitude, poiData.longitude, poiData.altitude);
		var markerImageDrawable = new AR.ImageDrawable(World.markerDrawable, 2.5, {
			zOrder: 0,
			opacity: 1.0
		});
		var markerObject = new AR.GeoObject(markerLocation, {
			drawables: {
				cam: [markerImageDrawable]
			}
		});
	},
	locationChanged: function locationChangedFn(lat, lon, alt, acc) {
		if (!World.initiallyLoadedData) {
			var poiData = {
				"id": 1,
				"longitude": (lon + (Math.random() / 5 - 0.1)),
				"latitude": (lat + (Math.random() / 5 - 0.1)),
				"altitude": 100.0
			};
			World.loadPoisFromJsonData(poiData);
			World.initiallyLoadedData = true;
		}
	},
};
AR.context.onLocationChanged = World.locationChanged;

En la siguiente entrada veremos cómo realizar la primera carga de datos obteniendo la ubicación del dispositivo desde el código nativo Java e invocar al JavaScript (locationChangedFn) desde el código nativo Java con Android.

Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 2

Descargar

Esta entrada corresponde a la continuación del artículo Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 1; en el cual definimos lo que es un Punto de Interés o POI, algunas consideraciones sobre el uso del GPS en un dispositivo Android y definimos parte del Architect World (código JavaScript) empleado para manejar los Puntos de Interés en base a la ubicación del dispositivo.

Creación de la plataforma cruzada para mostrar Puntos de Interés

Ya introduciendo esta entrada, veremos cómo vincular nuestro Architect World (código JavaScript) con el código nativo (código Java) de la aplicación para obtener y actualizar constantemente los Puntos de Interés según la posición del dispositivo:

El código nativo (Java)

Nuestra activity en Android se encargará de obtener la posición del dispositivo al transcurrir un tiempo determinado o desplazarse cierta distancia; una vez que obtenida la posición del dispositivo, la activity invocará un método JavaScript llamado locationChangedFn(lat, lon, alt, acc) que recibe como parámetros la localización del usuario (latitud, longitud, altitud y precisión).

El Architect World (código JavaScript)

Una vez invocado el método locationChangedFn(lat, lon, alt, acc), el mismo se encargará de invocar a las funciones necesarias para obtener los Puntos de Interés cercanos en base a la posición (longitud, latitud y altitud) del dispositivo y de renderizarlos en la pantalla del dispositivo.

Posibilidades Architect World (código JavaScript) para obtener Puntos de Interés cercanos dado la posición del dispositivo

Al ser código web, existen múltiples formas en la que podemos obtener los Puntos de Interés que hayamos definidos según la posición del usuario:

Podemos invocar al método architectView.callJavaScript() para pasar modelos de datos de nuestro código Java hacia el JavaScript; este método permite crear una plataforma cruzada (comunicar el código nativo de una aplicación -por ejemplo la provista en un activity de Android- con el Architect World -código JavaScript-) entre el código nativo y el código web: this.architectView.callJavascript( "newData('" +array.toString() + "');" );
function newData(jsonData){
  jsonObject = JSON.parse(jsonData);
  for(var i = 0; i < jsonObject.length; i++){
    // use jsonObject[i] data to create the AR objects for each POI
  }
}
  • También podemos cargar los Puntos de Interés de un recurso local como un archivo aparte o alguna estructura de datos como un Array: var myJsonData = [{ "id": "1", "longitude": "13.0833", "latitude": "47.75", "description": "This is the description of POI#1", "altitude": "100.0", "name": "POI#1"}, {...}];
  • O usando los Web Services siguiendo un formato como el siguiente: var ServerInformation = {    // sample service returning dummy POIs    POIDATA_SERVER: "http://example.wikitude.com/GetSamplePois/",    POIDATA_SERVER_ARG_LAT: "lat",    POIDATA_SERVER_ARG_LON: "lon",    POIDATA_SERVER_ARG_NR_POIS: "nrPois" };
  • Por supuesto podemos emplear cualquier otra tecnología como AJAX para obtener los Puntos de Interés o inclusive generar Puntos de Interés ficticios cercanos a la posición obtenida del dispositivo para casos de prueba; este último caso es el que emplearemos en nuestro experimento en la siguiente sección para obtener los Puntos de Interés.

Para más información, puedes consultar la documentación oficial RETRIEVING POI DATA

Desarrollando el código nativo (Java) de la aplicación

Ya aclarado ciertos conceptos claves sobre el funcionamiento de la plataforma cruzada en Wikitude para los Puntos de Interés, empecemos a obteniendo la localización del dispositivo.

Como se ha comentado a lo largo de esta entrada, el código nativo (Java) se encarga de obtener la posición del dispositivo mediante el GPS, red de telefonía, puntos de acceso Wi-Fi o alguna tecnología asociada; para poder obtener la ubicación del usuario debemos de tener solicitar los siguientes permisos en el AndroidManifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Una vez solicitados, podemos obtener la última ubicación válida el usuario mediante el método:

getLastKnownLocation(String provider)

Un punto importante es que Android no devuelve la posición actual del dispositivo si no la última registrada; en otras palabras el método llamado getLastKnownLocation(String provider) no devuelve la posición actual, solo se limita a devolver la última posición que se obtuvo a través del proveedor que se le indique como parámetro y esta posición se pudo obtener hace segundos, minutos, horas, días, meses, etc.

Aunque es posible utilizar un "evento escuchador" que permite obtener la posición real del usuario actualizable según los valores de los parámetros suministrador mediante el método requestLocationUpdates() que permite obtener la posición del usuario actualizada en el tiempo; dicho método recibe:

  • Nombre del proveedor de localización.
  • TIempo mínimo entre actualizaciones dadas en milisegundos.
  • Distancia mínima entre actualizaciones dadas en metro.
  • Instancia de un objeto LocationListener el cual definirá las acciones a realizar cuando se actualice la posición.

Definiendo el evento escuchador en nuestra activity

El siguiente fragmento de código será utilizado dentro de nuestra activity para actualizar la posición del usuario:

		LocationListener locationListener = new LocationListener() {
			@Override
			public void onLocationChanged(Location location) {
				if (location != NULL) {
					latitude = location.getLatitude();
					longitude = location.getLongitude();
				}
				architectView.setLocation(latitude, longitude, 1f);
			}
//*** otras validaciones del evento escuchador

Una vez instanciado el "evento escuchador" indicamos que servicios de localización emplearemos; el GPS:

locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)

Y la red de telefonía con los puntos de acceso Wi-Fi:

locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)

A la vez indicamos cada cuanto tiempo y distancia recorrida deseamos que se actualice la posición:

		locationManager.requestLocationUpdates(
					LocationManager.NETWORK_PROVIDER, 80000, 0,
					locationListener);

Finalmente, devolvemos la posición:

Location location = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != NULL) { latitude = location.getLatitude(); longitude = location.getLongitude(); }

Lo versátil de esta tecnología es que podemos cargar sólo los Puntos de Interés cercanos a la posición del dispositivo en base a un rango; los Puntos de Interés se podrían ir actualizando conforme a la posición del dispositivo.

El resto del cuerpo de la activity es exactamente la misma utilizada en entradas anteriores sobre Wikitude; en cuanto al Architect World o código JavaScript es exactamente el mismo explicado en detalle en la parte 1

Al ejecutar la aplicación podrás darte cuenta que pinta un simple POI:

app ANdroid con un PoI - WikiTude SDK

Continuación del uso de los POI con Wikitude

En las siguientes entradas veremos como pintar múltiples Puntos de Interés e interactuar con los mismos; puedes descargar el código completo de la aplicación en nuestro repositorio de GitHub.

Iniciando con Wikitude para Android: instalación de la SDK y primeros pasos en el reconocimiento de imágenes

Ver ejemplo en github

La realidad aumentada en Wikitude, los Puntos de Interés, el reconocimiento de imágenes y mucho más es un tema ya tratado en anteriores entradas que hablamos sobre Wikitude:

Iniciando con Wikitude para Android: instalación de la SDK y primeros pasos en el reconocimiento de imágenes

Primeros pasos con Wikitude en Android (parte 1)

Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 2

Creando un Punto de Interés con Realidad Aumentada en Wikitude Parte 1

¿Cómo reconocer múltiples Objetivos (Targets) con el Tracker en Wikitude?

Puntos de Interés (POI) con Realidad Aumentada en Wikitude

Target Collection y el ARchitect World en la nube con Wikitude

Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 3.2)

Desarrollando aplicaciones de Realidad Aumentada con Wikitude (parte 3)

Las medidas SDUs en Wikitude

En esta entrada veremos cómo crear una aplicación que emplee la SDK de Wikitude naiva para Android y emplee el reconocimiento de imágenes para (valga la redundancia) reconocer una imagen y mostrar un enmarque a su alrededor.

En aquellos tiempos cuando existía el famoso Eclipse con el plugin ADT desde ese tiempo han cambiado varias cosas, muchas versiones de Android han pasado, varias de la SDK de Wikitude hasta estar en la versión 8, que es la actual, e inclusive han extendido su SDK hasta crear una nativa para Android.

La SDK nativa y la SDK web/JavaScript

Recordemos que para versiones anteriores solo estaba disponible una especie de SDK híbrida en donde parte de la SDK era nativa (el uso de la cámara y configuración inicial), pero el fuerte del reconocimiento de imágenes, uso de los POIs o Puntos de Interés, interacción con el usuario, conectarse a otras API para traer o enviar datos y más, se realizaba mediante JavaScript; que a mi humilde opinión me parece excelente este esquema ya que facilita mucho el proceso de creación de las app, podemos trabajar en gran parte con librerías y demás funcionalidades webs que desde Android nos harían pasar más trabajo por cómo está elaborado este.

Sin embargo el talón de aquiles de esta funcionalidad es que las interfaces al ser webs no están a la altura de un desarrollo nativo en Android; para ello Wikitude creó una versión nativa para Android paralela a la de JavaScript que podemos usar según nuestras necesidades:

wikitude javascript y nativa android

Las SDK de Wikitude para Android y otras más las puedes descargar desde el siguiente enlace oficial:

Wikitude SDK para Android

Claro, desarrollar con la SDK nativa puede ser más complejo que con la SDK para web pero todo depende de las ventajas que veamos entre una y otra al momento de realizar un proyecto.

En esta entrada, nos enfocaremos en dar los primeros pasos con el desarrollo de una sencilla aplicación para el reconocimiento de imágenes, para ello haremos uso de los ejemplos oficiales casi en su totalidad, pero la idea de esta entrada es narrar como yo desarrollé y probé estos ejemplos de una manera más limpia, explicar como funciona y cómo nos podemos ayudar con la documentación.

Instalación de la SDK nativa

Lo primeros que debemos hacer es descargar la SDK natíva de Wikitude para Android; para ello puedes descargarlo desde la sección de descargas:

Wikitude SDK para Android

Probablemente debas registrarte, aceptar unas condiciones etc; una vez descargada la misma, las descomprimes y tendremos en la ruta:

WikitudeSDK_NativeAPI_Android_8-X-X_XXXX-XX-XX_XX-XX-XX\Library
aar librería de wikitude

Esta librería o SDK de Wikitude que instalaremos en nuestro Android Studio; el proceso consiste en copiar la librería en la carpeta libs de Android:

árbol de proyecto android studio

Y luego seguir los pasos que narran en la documentación oficial:

Setup Guide Android

Básicamente consiste en agregar las dependencias en nuestro Android Gradle:

android {
    ...
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation (name: 'wikitude-native-sdk', ext:'aar')
    implementation "com.google.ar:core:1.1.0"
    ...
}
repositories {
    flatDir{
        dirs 'libs'
    }
}

Y en solicitar los permisos en nuestro Android Manifest:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature android:name="android.hardware.camera" android:required="true" />

 

Colocar estos atributos en la actividad que emplea la realidad aumentada, que en nuestro ejemplo es nuestro MainActivity:

android:configChanges="orientation|keyboardHidden|screenSize"

Quedando nuestra MainActivity la cual es la que va a mostrar la realidad aumentada mediante la cámara y la pantalla del dispositivo de la siguiente forma:

<activity
   android:name=".MainActivity"
   android:configChanges="orientation|keyboardHidden|screenSize">

Una vez hecho esto, nuestro proyecto debería compilar sin problemas, aunque aún no hemos desarrollado nada.

Iniciando con el Reconocimiento de Imágenes de WIkitude

Como mencionamos antes, vamos a hacer uso de los ejemplos que ofrece Wikitude, y que vienen en el zip que descargamos y descomprimimos antes:

WikitudeSDK_NativeAPI_Android_8-X-X_XXXX-XX-XX_XX-XX-XX\Library\app\src\main\java\com\wikitude\samples\tracking\image\SimpleImageTrackingActivity.java

En la documentación oficial nos podemos guiar por este links que nos van explicando un paso a paso hasta cierto punto:

Simple Image Tracking Android

Nos narra unos pasos que consisten en implementar algunas clases propias de la SDK de Wikitude:

public class MainActivity extends Activity implements ImageTrackerListener, ExternalRendering {...}

Nos indica que en nuestro OnCreate el cual es el método inicial en nuestro ciclo de vida de una aplicación Android realizamos las configuraciones de la aplicación, creando el objeto WikitudeSDK con la cual realizamos las configuraciones para indicar la licencia que descargamos desde el punto anterior, la cámara que vamos ha usar, si la delantera o de la parte posterior, la resolución, y luego creamos una instancia de la SDK de Wikitude con los parámetros configurados:

wikitudeSDK.onCreate(getApplicationContext(), this, startupConfiguration);

Creando el TargetCollection

Paso siguiente es crear el TargetCollection que ya hemos hablado de esto antes en una anterior entrada:

Target Collection y el ARchitect World en la nube con Wikitude

Empleando la API nativa de Wikitude, para referenciar el TargetCollection hacemos:

targetCollectionResource = wikitudeSDK.getTrackerManager().createTargetCollectionResource("file:///android_asset/magazine.wtc");

La ruta android_asset hace referencia al directorio assets de nuestro proyecto que podemos crear desde Android Studio:

arbol proyecto assets carpeta

También agregamos o mejor dicho sobreescribimos algunos métodos del propios de la clase que estamos implementando:

@Override
public void onTargetsLoaded(ImageTracker tracker) {
    Log.v(TAG, "Image tracker loaded");
}
@Override
public void onErrorLoadingTargets(ImageTracker tracker, WikitudeError error) {
    Log.v(TAG, "Unable to load image tracker. Reason: " + error.getMessage());
}
@Override
public void onImageRecognized(ImageTracker tracker, final ImageTarget target) {
    Log.v(TAG, "Recognized target " + target.getName());
    StrokedRectangle strokedRectangle = new StrokedRectangle(StrokedRectangle.Type.STANDARD);
    glRenderer.setRenderablesForKey(target.getName() + target.getUniqueId(), strokedRectangle, NULL);
}
@Override
public void onImageTracked(ImageTracker tracker, final ImageTarget target) {
    StrokedRectangle strokedRectangle = (StrokedRectangle)glRenderer.getRenderableForKey(target.getName() + target.getUniqueId());
    if (strokedRectangle != NULL) {
        strokedRectangle.projectionMatrix = target.getProjectionMatrix();
        strokedRectangle.viewMatrix = target.getViewMatrix();
        strokedRectangle.setXScale(target.getTargetScale().getX());
        strokedRectangle.setYScale(target.getTargetScale().getY());
    }
}
@Override
public void onImageLost(ImageTracker tracker, final ImageTarget target) {
    Log.v(TAG, "Lost target " + target.getName());
    glRenderer.removeRenderablesForKey(target.getName() + target.getUniqueId());
}

Y el siguiente método que es muy importante el permite de hacer de espejo el contenido de la cámara en la pantalla; en otras palabras: renderiza el contenido de la cámara en la pantalla y habilita la Realidad Aumentada:

@Override
public void onRenderExtensionCreated(final RenderExtension renderExtension) {
    glRenderer = new GLRenderer(renderExtension);
    view = new CustomSurfaceView(getApplicationContext(), glRenderer);
    driver = new Driver(view, 30);
    setContentView(view);
}

Aquí como vemos la cosa se complica un poco ya que hacemos uso de otras clases y métodos que de repente aparecieron en la documentación; lo más importante aquí es tener presente los métodos autogenerados por la API de Wikitude que prácticamente se auto explican con su nombre pero aun así vamos a definirlos un poco a continuación:

Ya con esta ayuda, lo mejor que podemos hacer es ir viendo método por método y analizar qué es lo que está haciendo.

Método onCreate

En el método onCreate lo siguiente que hacemos es solicitar permiso para emplear la cámara, ya esto es algo propio de Android desde la versión 6, si la solicitud es rechazada, pues no hay nada que hacer, ya que no podrá funcionar la realidad aumentada de Wikitude y menos reconocer imágenes.

Paso siguiente esta líneas de código que son opcionales:

dropDownAlert = new DropDownAlert(this);
dropDownAlert.setText("Scan Target #1 (surfer):");
dropDownAlert.addImages("surfer.png");
dropDownAlert.setTextWeight(0.5f);
dropDownAlert.show();

Lo que haces es pintar un rectángulo en la parte superior de la pantalla:

panel ra

En los métodos onResume, onPause y onDestroy lo que hacemos es controlar el ciclo de vida de la aplicación y de algunos componentes que son fundamentales para que trabaje y no nos de algún error inesperado cuando la aplicación pase de un estado a otro y pueda destruirse correctamente.

Tipos de renderizado: Externo e Interno

Tenemos dos tipos de renderizado, el interno y el externo y esto es lo que pinta habilita la cámara en la pantalla (fíjese que ahora no empleamos un layout especial que funcionaba como espejo entre la cámara y la pantalla como se hace en la versión web).

El método onRenderExtensionCreated es definido con el renderizado externo ya que estamos pasando nuestro parámetro OpenGL a 30 frames por segundo.

Y en este punto es donde ocurre la magia, en donde Wikitude muestra o espeja el contenido de la cámara en la pantalla del dispositivo y habilita toda la SDK de Wikitude a nuestra disposición (Reconocimiento de imágenes, Puntos de interés, y la realidad aumentada en general).

Clase GLRenderer

En general estas clases no las tenemos que analizar mucho, con saber que es la que nos construye la superficie de vista o SurfaceView nos es suficiente para trabajar con ella; la misma se encarga de construir la vista según el tamaño de la pantalla.

GLRenderer implementa un par de clases, la primera de ellas es GLSurfaceView.Renderer que emplea la librería OpenGL que permite realizar gráficos e interfaces en 2D y 3D; ya con esto puedes suponer que estos graficos en Wikitude se refieren al lente (la pantalla) que refleja el contenido enviado por la cámara del dispositivo.

¿Cómo se comunica Wikitude con esta interfaz GLSurfaceView.Renderer

Pues para eso Wikitude cuenta con su propia interfaz llamada RenderExtension la cual es inicializada en el método GLRenderer como parámetro generado en el método sobrescrito en la actividad principal llamado onRenderExtensionCreated; asi de facil, aunque suene un poco enredado; esta interfaz RenderExtension fue creada específicamente para el renderizado de externo de la SDK de Wikitude.

El método useSeparatedRenderAndLogicUpdates trabaja en conjunto con el método onDrawFrame que permite actualizar el renderizado de la aplicación.

Los métodos onSurfaceCreated, onSurfaceChanged y onDrawFrame son métodos provistos por la misma interfaz GLRenderer que se encargan de realizar los cambios en la pantalla y de dibujar cada frame, de estar realizando cambios cada vez que exista una actualización, etc; con esto ves que es importante realizar las llamadas correspondientes en los onPause y onDestroy de la actividad.

La clase GLES20 junto con los métodos que invoca simplemente se encarga de limpiar buffer; ya esto es algo bastante interno de OpenGL que de nuevo no es necesario trabajar con esto para explotar las funcionalidades básicas del core de la SDK de Wikitude.

Lo demás que vemos es simplemente como la SDK de Wikitude se comunica con los métodos provistos en OpenGL y trabajar correctamente; sin nada de esto No será posible que Wikitude renderice los frames de la cámara en la pantalla en otras palabras, nos quedaría una pantalla en blanco, negro o simplemente la app no funciona; la misma define mediante CameraManager.FovChangedListener el método onFovChanged que vemos al final del código.

La interfaz CameraManager, es provista por Wikitude y permite controlar la cámara que es la entrada de la realidad aumentada que hace posible que todo lo demás trabaje correctamente

Aquí tienes algunos enlaces de interés con la documentación oficial:

Clase CustomSurfaceView: construye la vista a embeber en la actividad

La otra clase que empleamos en el método onRenderExtensionCreated es la de CustomSurfaceView que le pasamos una instancia de la clase glRenderer que explicamos en la sección anterior; esta clase CustomSurfaceView extiende de la clase GLSurfaceView que provee una superficie para mostrar un reenderizado OpenGl (que es el que generamos en el punto anterior), es decir, en una clase la de glRenderer genera,ps el renderizado que queremos mostrar mediante OpenGL y WIkitude y en esta clase simplemente generamos la superficie con este contenido y lo embebemos en la actividad como si de una vista se tratase:

customSurfaceView = new CustomSurfaceView(getApplicationContext(), glRenderer);
***
setContentView(customSurfaceView);

Esta clase en resumidas cuentas lo que haces es crear un contexto para renderizar y sobre esta una superficie para dibujar mediante el "EGL rendering context"; ya aquí están dos grandes factores en juego que hacen todo por nosotros OpenGL-Android y Wikitude.

Aquí en estos últimos puntos vemos el talón de aquiles de la API nativa de Wikitude para Android, y es que algunos componentes son más complejos como estos que vimos, cosa con la cual no tenemos que lidiar en la API web o JavaScript de Wikitude para Android.

Clase StrokedRectangle: Pintar enmarque del target reconocido

Esta clase es invocado desde el MainActivity de nuestra actividad mediante el método onImageTracked que obtiene las dimensiones y posición del objeto reconocido y en el método onImageRecognize que dibuja el rectángulo correspondiente sobre la imagen reconocida (además de que este método nos permite obtener el nombre del target reconocido mediante target.getName()).

Esta clase dibuja el rectángulo en la función onDrawFrame() de dicha clase; todo esto es empleando la API de OpenGL que no es el punto de interés de esta entrada.

Puedes consultar el código completo en los links de descarga ubicados al inicio y final del este tutorial de realidad aumentada con Wikitude native SDK y Android; recuerda copiar el directorio rendering dentro del paquete de tu aplicación con el contenido del mismo:

 rendering external archivos

Finalmente, al ejecutar la aplicación y posicionar la cámara sobre la siguiente foto; vemos que la SDK de Wikitude reconoce dicha imagen y coloca un rectángulo alrededor de la misma:

reconocimiento de imágenes Wikitude

Ver ejemplo en github

Acepto recibir anuncios de interes sobre este Blog.

Qué es la Realidad Aumentada para agregar elementos como imágenes a nuestro entorno, úsala en tu negocio, desarrolla aplicaciones con Wikitude para Android e iOS con tecnologías web (HTML, JavaScript, CSS) o código nativo, geo y reconocimiento de imágenes

| 👤 Andrés Cruz

🇺🇸 In english