
Em um artigo anterior, eu já expliquei o que é o ARCore e como ele ajuda os desenvolvedores a criar aplicativos incríveis de realidade aumentada, sem a necessidade de entender matemática e OpenGL.
Se você ainda não o leu, é altamente recomendável fazer isso antes de seguir para este artigo e começar a desenvolver aplicativos ARCore.
Introdução
Para começar a desenvolver aplicativos ARCore, primeiro você precisa adicionar o suporte ARCore ao seu projeto. É muito simples, pois usaremos o Android Studio e o Sceneform SDK. Existem duas operações principais que são executadas automaticamente pelo Sceneform:
- Verifique o ARCore.
- Solicite permissão para usar a câmera.
Você não precisa se preocupar com essas duas etapas ao criar um aplicativo ARCore usando o Sceneform SDK. Você só precisa adicionar o Sceneform SDK ao seu projeto.
Crie um novo projeto do Android Studio com uma atividade vazia.
Inclua a seguinte dependência no arquivo build.gradle
no nível do projeto:
dependencies { classpath 'com.google.ar.sceneform:plugin:1.5.0' }
E inclua esta dependência no arquivo build.gradle
no nível do aplicativo:
implementation "com.google.ar.sceneform.ux:sceneform-ux:1.5.0"
Agora sincronize o projeto com os arquivos Gradle e aguarde até que a compilação seja concluída. Assim, o Sceneform SDK e o plugin Sceneform para Android Studio serão adicionados ao projeto. Isso permitirá que você visualize .sfb
, que são modelos 3D que serão renderizados em sua câmera, além de ajudá-lo a importar, visualizar e criar recursos 3D.
Criando seu primeiro aplicativo ARCore
Agora que a instalação do Android Studio está concluída e o Sceneform SDK está instalado, podemos começar a criar nosso primeiro aplicativo ARCore.
Primeiro, precisamos adicionar um fragmento Sceneform ao nosso layout. Esta é a chamada cena em que todos os nossos modelos 3D serão colocados. O fragmento se encarregará de inicializar a câmera e processar as permissões por conta própria.
Vá para o seu arquivo de layout principal. No meu caso, este é o arquivo activity_main.xml
. E adicione o fragmento Sceneform lá:
<?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>
match_parent
a largura e a altura do match_parent
para que a cena fique em tela cheia. Você pode escolher os tamanhos de acordo com suas necessidades.
Verificação de compatibilidade
Isso é tudo o que você precisa fazer no arquivo de layout. Agora passamos para Activity, no meu caso, é MainActivity
. Adicione um método à Atividade:
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 se o seu dispositivo suporta o Sceneform SDK ou não. O SDK requer a API Android nível 27 ou superior e o OpenGL ES versão 3.0 ou superior. Se o dispositivo não suportar esses dois parâmetros, a cena não será carregada e o aplicativo exibirá uma tela em branco.
No entanto, você ainda pode implementar todas as outras funções do seu aplicativo que não exijam o Sceneform SDK.
Depois de verificar a compatibilidade, podemos criar nosso modelo 3D e anexá-lo à cena.
Adicionando ativos
Agora você precisa adicionar modelos 3D ao projeto que será exibido na sua tela. Você mesmo pode criar esses modelos se estiver familiarizado com o processo de criação deles. Ou você pode ir para Poly .
Lá você encontrará um enorme repositório de recursos 3D para escolher. Além disso, eles são gratuitos para download.

No Android Studio, abra a pasta do aplicativo no painel esquerdo. Você precisa de uma pasta de dados de amostra . Esta pasta conterá todos os seus modelos 3D. Dentro desta pasta, crie uma pasta com o nome do seu modelo.
No arquivo baixado da Poly, você provavelmente encontrará 3 arquivos:
- arquivo
.mtl
- arquivo
.obj
- arquivo
.png
O mais importante desses três arquivos é o arquivo .obj
. Este é o seu modelo. Coloque todos os 3 arquivos em sampledata -> "your model folder" .

Agora clique com o botão direito do mouse no arquivo .obj
. A primeira opção seria Importar ativo da forma de cena . Clique nele, não altere as configurações padrão, apenas clique em Concluir na próxima janela. Depois disso, sincronize o projeto com os arquivos Gradle.
A importação do recurso 3D que será usado no seu projeto está concluída. Em seguida, vamos usar o modelo 3D em nosso código e incluí-lo na cena.
Criação de modelo
Adicione o seguinte código à sua atividade e eu explicarei linha por linha:
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; }); }
Primeiro, encontramos o arFragment
, que adicionamos anteriormente ao layout. Esse fragmento é responsável pelo armazenamento e operação da cena. Você pode imaginar isso como um recipiente para a nossa cena.
Em seguida, usamos a classe ModelRenderable
para criar nosso modelo. Usando o método setSource
carregamos nosso modelo a partir do arquivo .sfb
que foi gerado quando os recursos foram importados. O método thenAccept
obtém o modelo após a criação e definimos o modelo carregado como nossa variável lampPostRenderable
.
Para tratamento de erros, temos um método exceptionally
, chamado se ocorrer uma exceção.
Tudo isso acontece de forma assíncrona, para que você não precise se preocupar com multithreading.
Agora que o modelo está carregado e salvo na variável lampPostRenderable
, vamos adicioná-lo à nossa cena.
Adicionando um modelo à cena
Nossa cena está em arFragment
e receberá eventos de toque do usuário. Portanto, precisamos instalar um ouvinte onTap
para o nosso fragmento para processar toques e colocar objetos onde for necessário. Adicione o seguinte código ao 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(); } );
Definimos o ouvinte onTapArPlaneListener
para o nosso fragmento de AR. A sintaxe a seguir é usada para expressões lambda. Se você não estiver familiarizado com isso, consulte este pequeno guia sobre este tópico.
Primeiro, criamos uma âncora a partir do HitResult
usando hitresult.createAnchor()
e a salvamos no objeto Anchor
.
Em seguida, criamos um nó a partir dessa âncora. Ele será chamado AnchorNode
e será anexado à cena usando o método setParent
.
Em seguida, criamos um TransformableNode
, que será nosso modelo, e o vinculamos ao nosso nó. TransformableNode
ainda não possui nenhuma informação sobre o objeto que ele deve exibir. Passaremos esse objeto para ele usando o método setRenderable
, que usa como parâmetro um objeto do tipo ModelRenderable (lembre-se, obtivemos esse objeto e o lampPostRenderable
?). E, finalmente, chamamos o método lamp.select()
;
Ooh! Muita terminologia. Não se preocupe, vou explicar tudo agora:
Cena : este é o local onde todos os seus objetos 3D serão exibidos. Essa cena está localizada no fragmento de AR que adicionamos ao layout.
HitResult : trata-se de uma linha imaginária (ou raio) vinda do infinito, que fornece o ponto de interseção de si mesmo com um objeto do mundo real.
Âncora : Este é um local e orientação fixos no mundo real. Pode ser entendida como as coordenadas (x, y, z) no espaço tridimensional. Pose é a posição e orientação de um objeto no palco. É usado para converter o espaço de coordenadas local de um objeto em um espaço de coordenadas real.
Nó âncora : este é um nó que se posiciona automaticamente no mundo real. Este é o primeiro nó que é instalado quando um plano é detectado.
TransformableNode : este é o nó com o qual você pode interagir. Pode ser movido, dimensionado, girado e assim por diante. Neste exemplo, podemos escalar nosso objeto e girá-lo. Daí o nome Transformable.
Não há ciência de foguetes. É realmente relativamente simples. A cena inteira pode ser visualizada na forma de um gráfico no qual o pai é a cena e os filhos são nós âncoras, que depois se ramificam em vários outros nós e objetos que serão exibidos na tela.
Como resultado, sua Atividade deve ficar assim:
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; } }
Parabéns! Você acabou de concluir a criação do seu primeiro aplicativo ARCore. Comece adicionando objetos a ele e você verá como eles começam a ganhar vida no mundo real.
Esta foi sua primeira olhada em como criar um aplicativo ARCore simples do zero no Android Studio. Na próxima lição, aprofundarei o ARCore e adicionarei mais funcionalidades ao aplicativo.