1. Genel Bakış
ARCore, Android'de artırılmış gerçeklik uygulamaları oluşturmaya yönelik bir platformdur. Artırılmış görüntüler, gerçek dünyada önceden kaydedilmiş 2D görüntüleri tanıyabilen ve sanal içeriği bu görüntülerin üzerine yerleştirebilen AR uygulamaları oluşturmanıza olanak tanır.
Bu codelab, mevcut bir ARCore örnek uygulamasını, hareket eden veya yerinde sabit duran artırılmış görüntüleri içerecek şekilde değiştirme konusunda size yol gösterir.
Ne oluşturacaksınız?
Bu codelab'de, önceden oluşturulmuş bir ARCore örnek uygulamasını temel alarak çalışacaksınız. Codelab'in sonunda uygulamanız şunları yapabilecek:
- Bir resim hedefini algılama ve hedefe sanal labirent ekleme
- Hareket eden hedefi kamera görünümünde olduğu sürece takip etme

İlk ARCore uygulamanızı mı oluşturuyorsunuz?
Bu codelab'de örnek kod yazmayı mı planlıyorsunuz yoksa sadece bu sayfaları okumak mı istiyorsunuz?
Neler öğreneceksiniz?
- Java'da ARCore'da Artırılmış Görüntüler'i kullanma
- Bir resmin ARCore tarafından tanınma özelliğini ölçme
- Resme sanal içerik ekleme ve hareketini izleme
Ön koşullar
Bu codelab'i tamamlamak için belirli donanım ve yazılımlara ihtiyacınız vardır.
Donanım gereksinimleri
- Geliştirme makinenize USB kablosuyla bağlı bir ARCore destekli cihaz
Yazılım gereksinimleri
- ARCore APK 1.9.0 veya sonraki sürümler. Bu APK, normalde Play Store üzerinden cihaza otomatik olarak yüklenir.
- Android Studio (3.1 veya sonraki sürümler) yüklü bir geliştirme makinesi
- Geliştirme sırasında kitaplıkları indirmeniz gerektiğinden internet erişimi
Her şey hazır olduğuna göre başlayalım.
2. Geliştirme ortamını kurma
SDK'yı indir
GitHub'dan en son ARCore Android SDK'sını indirerek başlayacağız. Dosyayı tercih ettiğiniz konuma açın. Bu codelab için en eski SDK sürümü 1.18.1'dir. Klasör arcore-android-sdk-x.xx.x olarak adlandırılır. Tam değer, kullandığınız SDK'nın sürümü olur.
Android Studio'yu başlatın ve Open an existing Android Studio project (Mevcut bir Android Studio projesini aç) seçeneğini tıklayın.

Açılan bu klasöre gidin:
arcore-android-sdk-x.xx.x/samples/augmented_image_java
Aç'ı tıklayın.
Android Studio'nun projeyi senkronize etmesini bekleyin. Android Studio'da gerekli bileşenler yoksa Install missing platform and sync project mesajıyla hata verebilir. Sorunu düzeltmek için talimatları uygulayın.
Örnek uygulamayı çalıştırma
Çalışan bir ARCore uygulama projeniz olduğuna göre şimdi bunu test edelim.
ARCore cihazınızı geliştirme makinesine bağlayın ve cihazda hata ayıklama sürümünü çalıştırmak için Çalıştır > "app" uygulamasını çalıştır menüsünü kullanın. Hangi cihazda çalıştırmak istediğinizi seçmenizi isteyen iletişim kutusunda, bağlı cihazı seçin ve Tamam'ı tıklayın.


Bu örnek proje targetSdkVersion 28 kullanır. Failed to find Build Tools revision 28.0.3 gibi bir derleme hatası alırsanız gerekli Android Build Tools sürümünü indirip yüklemek için Android Studio'da açıklanan talimatları uygulayın.
Her şey başarılı olursa örnek uygulama cihazda başlatılır ve Artırılmış Görüntü'nün fotoğraf ve video çekmesine izin vermeniz istenir. İzin vermek için İZİN VER'e dokunun.
Örnek bir resimle test etme
Geliştirme ortamınızı ayarladığınıza göre artık uygulamaya bakması için bir resim vererek uygulamayı test edebilirsiniz.
Android Studio'ya geri dönün. Project (Proje) penceresinde app > assets'e gidin ve dosyayı açmak için default.jpg çift tıklayın.

Cihazınızın kamerasını ekrandaki Dünya görüntüsüne doğrultun ve taradığınız görüntüyü artı işaretinin içine sığdırmak için talimatları uygulayın.
Resmin üzerine aşağıdaki gibi bir resim çerçevesi yerleştirilir:

Ardından, örnek uygulamada küçük iyileştirmeler yapacağız.
3. 2D görüntüde labirent modeli gösterme
Artırılmış görüntülerin üzerine 3D model yerleştirerek bu özellikten yararlanmaya başlayabilirsiniz.
3D model indirme
Bu codelab'de Evol tarafından oluşturulan ve CC-BY 3.0 lisansı altında sunulan "Circle Maze - Green" adlı resmi kullanacağız. Bu 3D modelin bir kopyasını bu codelab'in GitHub deposunda sakladım. Bu kopyayı burada bulabilirsiniz.
Modeli indirip Android Studio'ya eklemek için aşağıdaki adımları uygulayın.
- Bu codelab'in GitHub deposu olan third_party dizinine gidin.
- GreenMaze_obj.zip'i ve İndir düğmesini tıklayın.
Bu işlem, GreenMaze_obj.zip adlı bir dosyayı indirir.
- Android Studio'da app > assets > models altında
green-mazedizini oluşturun. GreenMaze_obj.zipdosyasını açın ve içeriği şu konuma kopyalayın:arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze- Android Studio'da app > assets > models > green-maze'e (uygulama > öğeler > modeller > yeşil labirent) gidin.
Bu klasörde GreenMaze.obj ve GreenMaze.mtl olmak üzere iki dosya olmalıdır.

Labirent modelini oluşturma
GreenMaze.obj 3D modeli mevcut 2D görüntünün üzerinde göstermek için aşağıdaki adımları uygulayın.
AugmentedImageRenderer.java içinde, labirent modelini oluşturmak için mazeRenderer adlı bir üye değişkeni ekleyin. Labirent resme ekleneceğinden mazeRenderer öğesini AugmentedImageRenderer sınıfının içine yerleştirmek mantıklıdır.
AugmentedImageRenderer.java
// Add a member variable to hold the maze model.
private final ObjectRenderer mazeRenderer = new ObjectRenderer();
createOnGlThread() işlevinde GreenMaze.obj dosyasını yükleyin. İşinizi kolaylaştırmak için dokusuyla aynı çerçeve dokusunu kullanın.
AugmentedImageRenderer.java
// Replace the definition of the createOnGlThread() function with the
// following code, which loads GreenMaze.obj.
public void createOnGlThread(Context context) throws IOException {
mazeRenderer.createOnGlThread(
context, "models/green-maze/GreenMaze.obj", "models/frame_base.png");
mazeRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
draw() işlevinin tanımını aşağıdakiyle değiştirin. Bu işlem, labirenti algılanan resmin boyutuna göre ayarlar ve ekranda oluşturur.
AugmentedImageRenderer.java
// Adjust size of detected image and render it on-screen
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
float[] tintColor =
convertHexToColor(TINT_COLORS_HEX[augmentedImage.getIndex() % TINT_COLORS_HEX.length]);
final float mazeEdgeSize = 492.65f; // Magic number of maze size
final float maxImageEdgeSize = Math.max(augmentedImage.getExtentX(), augmentedImage.getExtentZ()); // Get largest detected image edge size
Pose anchorPose = centerAnchor.getPose();
float mazeScaleFactor = maxImageEdgeSize / mazeEdgeSize; // scale to set Maze to image size
float[] modelMatrix = new float[16];
// OpenGL Matrix operation is in the order: Scale, rotation and Translation
// So the manual adjustment is after scale
// The 251.3f and 129.0f is magic number from the maze obj file
// You mustWe need to do this adjustment because the maze obj file
// is not centered around origin. Normally when you
// work with your own model, you don't have this problem.
Pose mazeModelLocalOffset = Pose.makeTranslation(
-251.3f * mazeScaleFactor,
0.0f,
129.0f * mazeScaleFactor);
anchorPose.compose(mazeModelLocalOffset).toMatrix(modelMatrix, 0);
mazeRenderer.updateModelMatrix(modelMatrix, mazeScaleFactor, mazeScaleFactor/10.0f, mazeScaleFactor); // This line relies on a change in ObjectRenderer.updateModelMatrix later in this codelab.
mazeRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
Artık labirent, default.jpg Dünya resminin üzerinde gösterilir.
Not: Bu örnek 3D model üzerinde tam kontrolünüz olmadığı için yukarıdaki kodda birkaç "sihirli" sayı kullanılmıştır. Labirent modelinin boyutu 492,65 x 120 x 492,65 olup merkezi (251,3, 60, -129,0) konumundadır. Köşelerinin X, Y ve Z koordinat değerleri sırasıyla [5,02, 497,67], [0, 120] ve [-375,17, 117,25] aralığındadır. Bu nedenle, labirent modelinin ölçeği image_size / 492.65 olmalıdır. Labirentin 3D modeli başlangıç noktası (0, 0, 0) etrafında ortalanmadığı için mazeModelLocalOffset değeri kullanılıyor.
Labirenti oluşturan duvar, resmin üst kısmına sığmayacak kadar yüksek. Labirenti 0, 1 oranında ölçeklendirmek için X, Y ve Z'yi eşit olmayan şekilde ölçeklendirebilen bir yardımcı işlev updateModelMatrix() oluşturun. Mevcut updateModelMatrix(float[] modelMatrix, float scaleFactor) işlevini koruyup updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) işlevini yeni bir işlev olarak eklemeniz gerektiğini unutmayın.
common/rendering/ObjectRenderer.java
// Scale X, Y, Z coordinates unevenly
public void updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) {
float[] scaleMatrix = new float[16];
Matrix.setIdentityM(scaleMatrix, 0);
scaleMatrix[0] = scaleFactorX;
scaleMatrix[5] = scaleFactorY;
scaleMatrix[10] = scaleFactorZ;
Matrix.multiplyMM(this.modelMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
}
Kodu çalıştırın. Labirent artık resmin üzerine tam olarak oturmalıdır.

4. Andy'yi labirente ekle
Labirentiniz olduğuna göre şimdi labirentin içinde hareket edecek bir karakter ekleyin. ARCore Android SDK'sında bulunan andy.obj dosyasını kullanın. Resmin üzerinde oluşturulan yeşil labirentten farklı göründüğü için resim çerçevesinin dokusunu olduğu gibi bırakın.
AugmentedImageRenderer.java içinde, Andy'yi oluşturmak için özel bir ObjectRenderer ekleyin.
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
Ardından, createOnGlThread()'ın sonunda andyRenderer'ı başlatın.
AugmentedImageRenderer.java
public void createOnGlThread(Context context) throws IOException {
// Initialize andyRenderer
andyRenderer.createOnGlThread(
context, "models/andy.obj", "models/andy.png");
andyRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
Son olarak, draw() fonksiyonunun sonunda Andy'nin labirenti tepeden gördüğü bir görüntü oluşturun.
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Render Andy, standing on top of the maze
Pose andyModelLocalOffset = Pose.makeTranslation(
0.0f,
0.1f,
0.0f);
anchorPose.compose(andyModelLocalOffset).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f); // 0.05f is a Magic number to scale
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
Kodunuzu çalıştırın. Andy'nin labirentin üzerinde durduğunu görürsünüz.

Hedef resim kalitesini belirleme
ARCore, resimleri tanımak için görsel özelliklerden yararlanır. Kalite farklılıkları nedeniyle tüm resimler kolayca tanınamayabilir.
arcoreimg, bir resmin ARCore tarafından ne kadar tanınacağını belirlemenize olanak tanıyan bir komut satırı aracıdır. 0 ile 100 arasında bir sayı verir. 100, tanınması en kolay olanıdır.
. Örneğin:
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
maze.jpg değeri 100 olduğundan ARCore tarafından kolayca tanınır.
5. İsteğe bağlı: Andy'nin labirentte hareket etmesini sağlayın.
Son olarak, andy'nin labirentte hareket etmesini sağlamak için kod ekleyebilirsiniz. Örneğin, fizik simülasyonunu işlemek için açık kaynaklı fizik motoru jBullet'ı kullanın. Bu bölümü atlamanızda hiçbir sakınca yoktur.
PhysicsController.java dosyasını indirip dizindeki projenize ekleyin.
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
Android Studio'da, çalışma zamanında yüklenebilmesi için Add GreenMaze.obj dosyasını project assets dizinine ekleyin. GreenMaze.obj dosyasını app > assets > models > green-maze konumundan app > assets konumuna kopyalayın.
Uygulamanın build.gradle dosyasına aşağıdaki bağımlılıkları ekleyin.
app/build.gradle
// jbullet library
implementation 'cz.advel.jbullet:jbullet:20101010-1'
Andy'nin mevcut pozunun konumunu depolamak için bir değişken andyPose tanımlayın.
AugmentedImageRenderer.java
// Create a new pose for the Andy
private Pose andyPose = Pose.IDENTITY;
Andy'yi yeni andyPose değişkenini kullanarak oluşturmak için AugmentedImageRenderer.java öğesini değiştirin.
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Use these code to replace previous code for rendering the Andy object
//
// Adjust the Andy's rendering position
// The Andy's pose is at the maze's vertex's coordinate
Pose andyPoseInImageSpace = Pose.makeTranslation(
andyPose.tx() * mazeScaleFactor,
andyPose.ty() * mazeScaleFactor,
andyPose.tz() * mazeScaleFactor);
anchorPose.compose(andyPoseInImageSpace).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f);
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
Andy poz güncellemelerini almak için yeni bir hizmet işlevi olan updateAndyPose()'yı ekleyin.
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
AugmentedImageActivity.java içinde, fizik ile ilgili tüm işlevleri yönetmek için JBullet fizik motorunu kullanan bir PhysicsController nesnesi oluşturun.
AugmentedImageActivity.java
import com.google.ar.core.Pose;
// Declare the PhysicsController object
private PhysicsController physicsController;
Fizik motorunda Andy'yi temsil etmek için aslında sert bir top kullanıyoruz ve topun pozunu kullanarak Andy'nin pozunu güncelliyoruz. Uygulama bir resmi her tanıdığında fiziği güncellemek için PhysicsController işlevini çağırın. Topu gerçek dünyadaymış gibi hareket ettirmek için labirentte topu hareket ettirirken gerçek dünyadaki yer çekimini uygulayın.
AugmentedImageActivity.java
// Update the case clause for TRACKING to call PhysicsController
// whenever the app recognizes an image
private void drawAugmentedImages(
...
case TRACKING:
// Switch to UI Thread to update View
this.runOnUiThread(
new Runnable() {
@Override
public void run() {
fitToScanView.setVisibility(View.GONE);
}
});
// Create a new anchor for newly found images
if (!augmentedImageMap.containsKey(augmentedImage.getIndex())) {
Anchor centerPoseAnchor = augmentedImage.createAnchor(augmentedImage.getCenterPose());
augmentedImageMap.put(
augmentedImage.getIndex(), Pair.create(augmentedImage, centerPoseAnchor));
physicsController = new PhysicsController(this);
} else {
Pose ballPose = physicsController.getBallPose();
augmentedImageRenderer.updateAndyPose(ballPose);
// Use real world gravity, (0, -10, 0), as gravity
// Convert to Physics world coordinate(maze mesh has to be static)
// Use the converted coordinate as a force to move the ball
Pose worldGravityPose = Pose.makeTranslation(0, -10f, 0);
Pose mazeGravityPose = augmentedImage.getCenterPose().inverse().compose(worldGravityPose);
float mazeGravity[] = mazeGravityPose.getTranslation();
physicsController.applyGravityToBall(mazeGravity);
physicsController.updatePhysics();
}
break;
Uygulamayı çalıştırın. Andy, resmi eğdiğinizde artık gerçekçi bir şekilde hareket etmelidir.
Aşağıdaki örnekte resmi göstermek için başka bir telefon kullanılıyor. Tablet, basılı bir kitabın kapağı veya düz bir nesneye iliştirilmiş basılı bir kağıt gibi size uygun olan herhangi bir şeyi kullanabilirsiniz.

İşte bu kadar. Andy'yi labirentten geçirmeye çalışırken iyi eğlenceler. İpucu: Hedef resmi ters çevirerek tuttuğunuzda çıkışı daha kolay bulabilirsiniz.
6. Tebrikler
Tebrikler! Bu codelab'in sonuna geldiniz. Böylece:
- ARCore AugmentedImage Java örneğini oluşturup çalıştırdıysanız.
- Resimde uygun ölçekte bir labirent modeli göstermek için örneği güncelledi.
- Resmin pozunu kullanarak eğlenceli bir şeyler yapın.
Kodun tamamını incelemek isterseniz buradan indirebilirsiniz.