
En un artículo anterior, ya expliqué qué es ARCore y cómo ayuda a los desarrolladores a crear increíbles aplicaciones de realidad aumentada sin la necesidad de comprender las matemáticas y OpenGL.
Si aún no lo ha leído, le recomiendo hacerlo antes de pasar a este artículo y comenzar a desarrollar aplicaciones ARCore.
Empezando
Para comenzar a desarrollar aplicaciones ARCore, primero debe agregar soporte ARCore a su proyecto. Es muy simple, ya que usaremos Android Studio y Sceneform SDK. Hay dos operaciones principales que Sceneform realiza automáticamente:
- Verifique ARCore.
- Solicitar permiso para usar la cámara.
No necesita preocuparse por estos dos pasos al crear una aplicación ARCore utilizando el SDK de Sceneform. Solo necesita agregar el SDK de Sceneform a su proyecto.
Cree un nuevo proyecto de Android Studio con una Actividad vacía.
Agregue la siguiente dependencia al archivo build.gradle
en el nivel del proyecto:
dependencies { classpath 'com.google.ar.sceneform:plugin:1.5.0' }
Y agregue esta dependencia al archivo build.gradle
en el nivel de aplicación:
implementation "com.google.ar.sceneform.ux:sceneform-ux:1.5.0"
Ahora sincronice el proyecto con los archivos de Gradle y espere hasta que se complete la compilación. Por lo tanto, el SDK de Sceneform y el complemento de Sceneform para Android Studio se agregarán al proyecto. Esto le permitirá ver .sfb
, que son modelos 3D que se renderizarán en su cámara, además de ayudarlo a importar, ver y crear recursos 3D.
Creando su primera aplicación ARCore
Ahora que la configuración de Android Studio está completa y el Sceneform SDK está instalado, podemos comenzar a crear nuestra primera aplicación ARCore.
Primero, necesitamos agregar un fragmento de Sceneform a nuestro diseño. Esta es la llamada escena donde se colocarán todos nuestros modelos 3D. El fragmento se encargará de inicializar la cámara y procesar los permisos por sí solo.
Vaya a su archivo de diseño principal. En mi caso, este es el archivo activity_main.xml
. Y agregue el fragmento de Sceneform allí:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <fragment android:name="com.google.ar.sceneform.ux.ArFragment" android:id="@+id/ux_fragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
Configuré el ancho y la altura de match_parent
para que la escena esté en pantalla completa. Puede elegir los tamaños según sus requisitos.
Comprobación de compatibilidad
Esto es todo lo que necesita hacer en el archivo de diseño. Ahora pasamos a Actividad, en mi caso es MainActivity
. Agregar un método a la actividad:
public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.e(TAG, "Sceneform requires Android N or later"); Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show(); activity.finish(); return false; } String openGlVersionString = ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE)) .getDeviceConfigurationInfo() .getGlEsVersion(); if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later"); Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) .show(); activity.finish(); return false; } return true; }
Este método verifica si su dispositivo admite el SDK de Sceneform o no. El SDK requiere Android API nivel 27 o superior y OpenGL ES versión 3.0 o superior. Si el dispositivo no admite estos dos parámetros, la escena no se cargará y su aplicación mostrará una pantalla en blanco.
Sin embargo, aún puede implementar todas las demás funciones de su aplicación que no requieren Sceneform SDK.
Después de verificar la compatibilidad, podemos crear nuestro modelo 3D y adjuntarlo a la escena.
Agregar activos
Ahora necesita agregar modelos 3D al proyecto que se mostrarán en su pantalla. Puede crear estos modelos usted mismo si está familiarizado con el proceso de crearlos. O puedes ir a Poly .
Allí encontrará un gran depósito de recursos 3D para elegir. Además, son de descarga gratuita.

En Android Studio, abra la carpeta de su aplicación en el panel izquierdo. Necesita una carpeta de datos de muestra . Esta carpeta contendrá todos sus modelos 3D. Dentro de esta carpeta, cree una carpeta con el nombre de su modelo.
En el archivo que descargue de Poly, lo más probable es que encuentre 3 archivos:
- archivo
.mtl
- archivo
.obj
- archivo
.png
El más importante de estos tres archivos es el archivo .obj
. Este es tu modelo. Coloque los 3 archivos en datos de muestra -> "la carpeta de su modelo" .

Ahora haga clic derecho en el archivo .obj
. La primera opción sería Importar activo de forma de escena . Haga clic en él, no cambie la configuración predeterminada, solo haga clic en Finalizar en la siguiente ventana. Después de eso, sincronice el proyecto con los archivos de Gradle.
Se completa la importación del recurso 3D que se utilizará en su proyecto. A continuación, usemos el modelo 3D en nuestro código e incluyémoslo en la escena.
Creación de modelos
Agregue el siguiente código a su Actividad, y lo explicaré línea por línea:
private static final String TAG = MainActivity.class.getSimpleName(); private static final double MIN_OPENGL_VERSION = 3.0; ArFragment arFragment; ModelRenderable lampPostRenderable; @Override @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"}) protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!checkIsSupportedDeviceOrFinish(this)) { return; } setContentView(R.layout.activity_main); arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment); ModelRenderable.builder() .setSource(this, Uri.parse("LampPost.sfb")) .build() .thenAccept(renderable -> lampPostRenderable = renderable) .exceptionally(throwable -> { Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; }); }
Primero encontramos arFragment
, que previamente agregamos al diseño. Este fragmento es responsable del almacenamiento y operación de la escena. Puedes imaginarlo como un contenedor para nuestra escena.
Luego, usamos la clase ModelRenderable
para construir nuestro modelo. Usando el método setSource
nuestro modelo desde el archivo .sfb
que se generó cuando se importaron los recursos. El método thenAccept
obtiene el modelo después de thenAccept
, y establecemos el modelo cargado en nuestra variable lampPostRenderable
.
Para el manejo de errores, tenemos un método exceptionally
, que se llama si ocurre una excepción.
Todo esto sucede de forma asíncrona, por lo que no tiene que preocuparse por el subprocesamiento múltiple.
Ahora que el modelo está cargado y guardado en la variable lampPostRenderable
, lo agregaremos a nuestra escena.
Agregar un modelo a la escena
Nuestra escena está en arFragment
y recibirá eventos táctiles del usuario. Por lo tanto, necesitamos instalar un oyente onTap
para nuestro fragmento a fin de procesar toques y colocar objetos donde sea necesario. Agregue el siguiente código al método onCreate
:
arFragment.setOnTapArPlaneListener( (HitResult hitresult, Plane plane, MotionEvent motionevent) -> { if (lampPostRenderable == null){ return; } Anchor anchor = hitresult.createAnchor(); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arFragment.getArSceneView().getScene()); TransformableNode lamp = new TransformableNode(arFragment.getTransformationSystem()); lamp.setParent(anchorNode); lamp.setRenderable(lampPostRenderable); lamp.select(); } );
Configuramos el oyente onTapArPlaneListener
para nuestro fragmento AR. La siguiente sintaxis se usa para expresiones lambda. Si no está familiarizado con él, consulte esta pequeña guía sobre este tema.
Primero, creamos un ancla desde HitResult
usando hitresult.createAnchor()
y la hitresult.createAnchor()
en el objeto Anchor
.
Luego creamos un nodo a partir de este ancla. Se llamará AnchorNode
y se adjuntará a la escena utilizando el método setParent
.
A continuación, creamos un Nodo TransformableNode
, que será nuestro modelo, y lo vinculamos a nuestro nodo. TransformableNode
todavía no tiene ninguna información sobre el objeto que debería mostrar. Le pasaremos este objeto usando el método setRenderable
, que toma un objeto de tipo ModelRenderable como parámetro (recuerde, obtuvimos dicho objeto y lo lampPostRenderable
?). Y finalmente, llamamos al método lamp.select()
;
Ooh! Demasiada terminología. No te preocupes, te lo explicaré todo ahora:
Escena : este es el lugar donde se mostrarán todos sus objetos 3D. Esta escena se encuentra en el fragmento AR que agregamos al diseño.
HitResult : esta es una línea (o rayo) imaginaria que viene del infinito, lo que da el punto de intersección de sí mismo con un objeto del mundo real.
Ancla : Esta es una ubicación fija y orientación en el mundo real. Se puede entender como las coordenadas (x, y, z) en el espacio tridimensional. Pose es la posición y orientación de un objeto en el escenario. Se utiliza para convertir el espacio de coordenadas local de un objeto en un espacio de coordenadas real.
Nodo de anclaje : es un nodo que se posiciona automáticamente en el mundo real. Este es el primer nodo que se instala cuando se detecta un plano.
Nodo transformable : este es el nodo con el que puede interactuar. Se puede mover, escalar, rotar, etc. En este ejemplo, podemos escalar nuestro objeto y rotarlo. De ahí el nombre Transformable.
No hay ciencia de cohetes. Es realmente relativamente simple. Toda la escena se puede ver en forma de un gráfico en el que el padre es la escena, y los hijos son nodos de anclaje, que luego se ramifican en varios otros nodos y objetos que se mostrarán en la pantalla.
Como resultado, su Actividad debería verse así:
package com.ayusch.arcorefirst; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.net.Uri; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.widget.Toast; import com.google.ar.core.Anchor; import com.google.ar.core.HitResult; import com.google.ar.core.Plane; import com.google.ar.sceneform.AnchorNode; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private static final double MIN_OPENGL_VERSION = 3.0; ArFragment arFragment; ModelRenderable lampPostRenderable; @Override @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"}) protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!checkIsSupportedDeviceOrFinish(this)) { return; } setContentView(R.layout.activity_main); arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment); ModelRenderable.builder() .setSource(this, Uri.parse("LampPost.sfb")) .build() .thenAccept(renderable -> lampPostRenderable = renderable) .exceptionally(throwable -> { Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; }); arFragment.setOnTapArPlaneListener( (HitResult hitresult, Plane plane, MotionEvent motionevent) -> { if (lampPostRenderable == null){ return; } Anchor anchor = hitresult.createAnchor(); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arFragment.getArSceneView().getScene()); TransformableNode lamp = new TransformableNode(arFragment.getTransformationSystem()); lamp.setParent(anchorNode); lamp.setRenderable(lampPostRenderable); lamp.select(); } ); } public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.e(TAG, "Sceneform requires Android N or later"); Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show(); activity.finish(); return false; } String openGlVersionString = ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE)) .getDeviceConfigurationInfo() .getGlEsVersion(); if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later"); Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) .show(); activity.finish(); return false; } return true; } }
Felicidades Acaba de completar la creación de su primera aplicación ARCore. Comience a agregarle objetos y verá cómo comienzan a cobrar vida en el mundo real.
Este fue su primer vistazo a cómo crear una aplicación ARCore simple desde cero en Android Studio. En la próxima lección, profundizaré en ARCore y agregaré más funcionalidades a la aplicación.