1. Genel Bakış
ARCore, Android'de artırılmış gerçeklik uygulamaları geliştirme amaçlı bir platformdur. Artırılmış Resimler, gerçek dünyadaki ön kayıtlı 2D görüntüleri tanıyabilen ve sanal içerikleri bu görüntülerin üzerine sabitleyebilen AR uygulamaları oluşturmanıza olanak tanır.
Bu codelab'de, taşınan veya sabitlenen artırılmış görüntüler eklemek için mevcut bir ARCore örnek uygulamasını değiştirme konusunda size yol gösterilir.
Neler oluşturacaksınız?
Bu codelab'de, mevcut bir ARCore örnek uygulamasını geliştireceksiniz. Codelab'in sonunda uygulamanız şunları yapabilecek:
- Bir görüntü hedefi tespit edin ve hedefe sanal bir labirent ekleyin
- Kamera görüş alanında olduğu sürece hareketli hedefi takip edin
İlk kez bir ARCore uygulaması mı geliştiriyorsunuz?
Bu codelab'de örnek kod yazmayı mı yoksa sadece bu sayfaları mı okumak istiyorsunuz?
Neler öğreneceksiniz?
- Java'da ARCore'da Artırılmış Resimler'i kullanma
- Bir görüntünün ARCore tarafından tanınma yeteneği nasıl ölçülür?
- Bir resme sanal içerik ekleme ve hareketini takip etme
Ön koşullar
Bu codelab'i tamamlamak için belirli donanım ve yazılımlara ihtiyacınız olacaktır.
Donanım gereksinimleri
- USB kablosuyla geliştirme makinenize bağlanmış, 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 (v3.1 veya sonraki sürümler) yüklü bir geliştirme makinesi
- Geliştirme sırasında kitaplıkları indirmeniz gerekeceğinden internete erişim
Artık her şey hazır olduğuna göre, başlayalım.
2. Geliştirme ortamını ayarlama
SDK'yı indir
GitHub'dan en son ARCore Android SDK'sını indirerek başlayacağız. Sıkıştırılmış dosyayı açın ve tercih ettiğiniz konuma getirin. Bu codelab'de en eski SDK sürümü 1.18.1'dir. Klasör arcore-android-sdk-x.xx.x
olarak adlandırılır. Buradaki tam değer, kullandığınız SDK'nın sürümü olur.
Android Studio'yu başlatın ve Mevcut bir Android Studio projesini aç'ı tıklayın.
Sıkıştırılmamış şu klasöre gidin:
arcore-android-sdk-x.xx.x/samples/augmented_image_java
Aç'ı tıklayın.
Android Studio'nun proje senkronizasyonunu tamamlamasını bekleyin. Android Studio'nuz gerekli bileşenlere sahip değilse Install missing platform and sync project
mesajıyla işlem başarısız olabilir. Sorunu gidermek için talimatları uygulayın.
Örnek uygulamayı çalıştırma
Artık çalışan bir ARCore uygulama projeniz olduğuna göre projeyi test edelim.
ARCore cihazınızı geliştirme makinesine bağlayın ve Çalıştır > > Çalıştır menüsünü kullanın. Cihazda hata ayıklama sürümünü çalıştırmak için "app" komutunu çalıştırın. Hangi cihazdan çalıştırılacağını seçmenizi isteyen iletişim kutusunda, bağlı cihazı seçin ve Tamam'ı tıklayın.
Bu örnek projede targetSdkVersion 28
kullanılmıştır. Failed to find Build Tools revision 28.0.3
gibi bir derleme hatasıyla karşılaşırsanız gerekli Android Derleme Araçları 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ış Resim'in resim ve video çekmesine izin vermek için sizden izin ister. İzin vermek için İZİN VER'e dokunun.
Örnek resimle test etme
Artık geliştirme ortamınızı oluşturduğunuza göre, bakılacak bir resim vererek uygulamayı test edebilirsiniz.
Android Studio'ya dönün ve Proje penceresinde uygulama > öğeleri ekleyin ve default.jpg
dosyasını çift tıklayarak açın.
Cihazınızın kamerasını ekrandaki Dünya görüntüsüne doğru tutun ve taradığınız görüntüyü artı işaretine sığdırmak için talimatları uygulayın.
Resmin üzerinde, aşağıdaki gibi bir resim çerçevesi yer alır:
Ardından, örnek uygulamada küçük iyileştirmeler yapacağız.
3. 2D Resimde labirent modelini göster
Üzerinde bir 3D model görüntüleyerek, Artırılmış Resimlerle oynamaya başlayabilirsiniz.
3D model indir
Bu codelab için "Circle Labirent - Yeşil" yöntemini kullanacağız. Evol tarafından sağlanmıştır ve CC-BY 3.0 kapsamında lisanslanmıştır. Bu 3D modelin bir kopyasını, bu codelab'in gitHub deposunda depoladım. Söz konusu depoya buradan ulaşabilirsiniz.
Modeli indirmek ve Android Studio'ya eklemek için aşağıdaki adımları uygulayın.
- Bu codelab'in GitHub deposuna, üçüncü taraf dizinine gidin.
- GreenMaze_obj.zip dosyasını ve ardından İndir düğmesini tıklayın.
Bu işlem, GreenMaze_obj.zip
adlı bir dosya indirir.
- Android Studio'da, app > altında
green-maze
dizini oluşturun. öğeler > modeller GreenMaze_obj.zip
adlı dosyanın sıkıştırması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 uygulama > öğeler > modeller > yeşil-labirent.
Bu klasörde iki dosya olmalıdır: GreenMaze.obj
ve GreenMaze.mtl
.
Labirent modelini oluştur
GreenMaze.obj
3D modelini mevcut 2D görüntünün üzerinde görüntülemek için bu adımları uygulayın.
AugmentedImageRenderer.java
içinde, labirent modelini oluşturmak için mazeRenderer
adlı bir üye değişkeni ekleyin. Labirentin resme eklenmesi gerektiğ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
öğesini yükleyin. Kolaylık sağlaması için dokusuyla aynı kare 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, labirentin boyutunu algılanan resmin boyutuna göre ayarlar ve labirenti ekranda gösterir.
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);
}
Şimdi, labirent Dünya'nın default.jpg
resminin üzerinde görüntülenmelidir.
Not: Bu örnek 3D model üzerinde tam denetime sahip olmadığınız için yukarıdaki kodda birkaç "sihir" numaraları'na dokunun. Labirent modelinin boyutu 492,65 x 120 x 492,65'tir ve ortadaki değer (251,3, 60, -129,0) şeklindedir. Köşelerinin aralığı X, Y ve Z koordinatları değerleri sırasıyla [5,02, 497,67], [0, 120] ve [-375,17, 117,25] şeklindedir. Dolayısıyla, labirent modelinin ölçeğinin image_size / 492.65
olması gerekir. Labirentin 3D modeli başlangıç noktası (0, 0, 0) etrafında ortalanmadığı için mazeModelLocalOffset
başlatılır.
Labirentin duvarı resmin üzerine sığmayacak kadar yüksek. Labirentin yüksekliğini 0,1 ölçeklemek için X, Y, Z'yi eşit olmayan şekilde ölçeklendirebilen updateModelMatrix()
yardımcı işlevi oluşturun. Mevcut updateModelMatrix(float[] modelMatrix, float scaleFactor)
öğesini korumanız ve aşırı yük 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 mükemmel bir şekilde sığmalıdır.
4. Andy'yi labirente ekleyin
Artık bir labirentiniz olduğuna göre labirentin içinde dolaşmak için bir karakter ekleyin. ARCore Android SDK'sında bulunan andy.obj
dosyasını kullanın. Resmin üstünde oluşturulan yeşil labirentten farklı göründüğü için resim çerçevesi dokusunu doku olarak koruyun.
Andy'yi oluşturmak için AugmentedImageRenderer.java
içinde gizli bir ObjectRenderer
ekleyin.
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
Sonra, createOnGlThread()
sonunda andyRenderer
uygulamasını 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()
işlevinin sonunda Andy'yi labirentin tepesinde görün.
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'yi labirentin tepesinde durduğunu göreceksiniz.
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ınmayabilir.
arcoreimg
, bir resmin ARCore'un ne kadar tanınabileceğini belirlemenize olanak tanıyan bir komut satırı aracıdır. 0 ile 100 arasında bir sayı verir. 100, tanınması en kolay değerdir.
, Bir örnek verelim:
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
maze.jpg
, 100 değerine sahip olduğu için ARCore tarafından kolayca tanınır.
5. İsteğe bağlı: Andy'nin labirentte hareket etmesini sağlayın
Son olarak, labirentte andy'nin hareket etmesini sağlayacak birkaç kod ekleyebilirsiniz. Örneğin, fizik simülasyonu yapmak için açık kaynaklı Fizik motoru jBullet'ı kullanın. Bu bölümü atlayabilirsiniz.
PhysicsController.java
dosyasını indirin ve dizindeki projenize ekleyin
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
Çalışma zamanında yüklenebilmesi için Android Studio'da GreenMaze.obj dosyasını proje öğeleri dizinine ekleyin. GreenMaze.obj
öğesini uygulamadan kopyala > öğeler > modeller > yeşil-labirent'i uygulamaya > öğeler.
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'
Anıl'ın mevcut pozunun konumunu depolamak için bir andyPose
değişkeni 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
dosyasını 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 pozu güncellemelerini almak için yeni bir yardımcı program işlevi (updateAndyPose()
) ekleyin.
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
AugmentedImageActivity.java
içinde, fizikle 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 sabit bir top kullanıyoruz ve topun duruşunu kullanarak Andy'nin duruşunu güncelliyoruz. Uygulama bir görüntü algıladığında fizik kurallarını güncellemek için PhysicsController
numaralı telefonu arayın. Topu gerçek dünyadaymış gibi hareket ettirmek için gerçek dünyadan yer çekimini kullanarak topu labirentte hareket ettirin.
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. Artık resmi yatırdığınızda Andy gerçekçi bir şekilde hareket etmelidir.
Aşağıdaki örnekte, resmi görüntülemek için başka bir telefon kullanılmaktadır; tablet, basılı bir kitabın kapağı veya düz bir nesneye yerleştirilmiş basılı bir kağıt gibi size uygun herhangi bir şeyi kullanabilirsiniz.
İşte bu kadar. Andy'yi labirentten başarıyla atlatmaya çalışırken keyfini çıkarın. İpucu: Hedef resmi baş aşağı tuttuğunuzda çıkışı bulmak daha kolay olur.
6. Tebrikler
Tebrikler! Bu codelab'in sonuna geldiniz. Böylece:
- ARCore AugmentedImage Java örneği oluşturup çalıştırdı.
- Örnek, labirent modelini resim üzerinde uygun ölçekte görüntüleyecek şekilde güncellendi.
- Resmin pozunu eğlenceli bir şey yapmak için kullandı.
Kodun tamamına bakmak isterseniz buradan indirebilirsiniz.