
في مقالة سابقة ، شرحت بالفعل ما هو ARCore وكيف يساعد المطورين على إنشاء تطبيقات مدهشة للواقع المعزز دون الحاجة إلى فهم الرياضيات و OpenGL.
إذا لم تقرأها بعد ، فأنا أوصي بشدة بذلك قبل الانتقال إلى هذه المقالة والبدء في تطوير تطبيقات ARCore.
الابتداء
لبدء تطوير تطبيقات ARCore ، تحتاج أولاً إلى إضافة دعم ARCore إلى مشروعك. الأمر بسيط للغاية ، حيث سنستخدم Android Studio و Sceneform SDK. هناك عمليتان رئيسيتان يتم تنفيذها تلقائيًا بواسطة Sceneform:
- تحقق من وجود ARCore.
- طلب إذن لاستخدام الكاميرا.
لا داعي للقلق بشأن هاتين الخطوتين عند إنشاء تطبيق ARCore باستخدام Sceneform SDK. تحتاج فقط إلى إضافة Sceneform SDK إلى مشروعك.
قم بإنشاء مشروع Android Studio جديد به نشاط فارغ.
أضف التبعية التالية إلى ملف build.gradle
على مستوى المشروع:
dependencies { classpath 'com.google.ar.sceneform:plugin:1.5.0' }
وأضف هذه التبعية إلى ملف build.gradle
على مستوى التطبيق:
implementation "com.google.ar.sceneform.ux:sceneform-ux:1.5.0"
الآن قم بمزامنة المشروع مع ملفات Gradle وانتظر حتى يكتمل الإنشاء. وبالتالي ، ستتم إضافة Sceneform SDK ومكوِّن Sceneform لبرنامج Android Studio إلى المشروع. سيتيح لك ذلك عرض .sfb
، وهي نماذج ثلاثية الأبعاد سيتم عرضها في الكاميرا ، بالإضافة إلى مساعدتك في استيراد الموارد ثلاثية الأبعاد وعرضها وإنشائها.
إنشاء أول تطبيق ARCore الخاص بك
الآن وبعد اكتمال إعداد Android Studio وتثبيت Sceneform SDK ، يمكننا البدء في إنشاء أول تطبيق ARCore.
أولاً ، نحتاج إلى إضافة جزء Sceneform إلى تخطيطنا. هذا هو المشهد المسمى حيث سيتم وضع جميع النماذج ثلاثية الأبعاد. ستهتم القطعة بتهيئة الكاميرا ومعالجة الأذونات من تلقاء نفسها.
انتقل إلى ملف التخطيط الرئيسي. في حالتي ، هذا هو ملف activity_main.xml
. وإضافة جزء Sceneform هناك:
<?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
بحيث يكون المشهد ممتلئًا. يمكنك اختيار الأحجام وفقا لمتطلباتك.
التحقق من التوافق
هذا هو كل ما عليك القيام به في ملف التخطيط. الآن ننتقل إلى النشاط ، وفي حالتي ، يكون هذا هو MainActivity
. إضافة طريقة إلى النشاط:
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; }
تتحقق هذه الطريقة مما إذا كان جهازك يدعم Sceneform SDK أم لا. يتطلب SDK أندرويد API المستوى 27 أو أعلى و OpenGL ES الإصدار 3.0 أو أعلى. إذا كان الجهاز لا يدعم هاتين المعلمتين ، فلن يتم تحميل المشهد ، وسيعرض التطبيق شاشة فارغة.
ومع ذلك ، لا يزال بإمكانك تنفيذ جميع الوظائف الأخرى للتطبيق التي لا تتطلب Sceneform SDK.
بعد التحقق من التوافق ، يمكننا إنشاء نموذج ثلاثي الأبعاد وإرفاقه بالمشهد.
إضافة الأصول
تحتاج الآن إلى إضافة نماذج ثلاثية الأبعاد إلى المشروع والتي سيتم عرضها على الشاشة. يمكنك إنشاء هذه النماذج بنفسك إذا كنت معتادًا على عملية إنشائها. أو يمكنك الذهاب إلى بولي .
هناك ستجد مستودعًا كبيرًا للموارد ثلاثية الأبعاد للاختيار من بينها. بالإضافة إلى ذلك ، فهي مجانية لتحميل.

في Android Studio ، افتح مجلد التطبيق الخاص بك في الجزء الأيمن. تحتاج إلى مجلد sampledata . سيحتوي هذا المجلد على جميع النماذج ثلاثية الأبعاد. داخل هذا المجلد ، قم بإنشاء مجلد باسم النموذج الخاص بك.
في الأرشيف الذي تقوم بتنزيله من Poly ، ستجد على الأرجح 3 ملفات:
.mtl
ملف.obj
ملف.png
الملف
أهم هذه الملفات الثلاثة هو ملف .obj
. هذا هو النموذج الخاص بك. ضع جميع الملفات الثلاثة في sampledata -> "مجلد النموذج الخاص بك" .

الآن انقر بزر الماوس الأيمن على ملف .obj
. الخيار الأول سيكون " استيراد أصول المشهد" . انقر فوقه ، لا تقم بتغيير الإعدادات الافتراضية ، فقط انقر فوق " إنهاء" في الإطار التالي. بعد ذلك ، قم بمزامنة المشروع مع ملفات Gradle.
اكتمال استيراد المورد ثلاثي الأبعاد الذي سيتم استخدامه في مشروعك. بعد ذلك ، دعنا نستخدم النموذج ثلاثي الأبعاد في الكود الخاص بنا وندرجه في المشهد.
خلق نموذج
أضف الكود التالي إلى نشاطك ، وسأشرح ذلك سطراً بسطر:
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
، الذي arFragment
سابقًا إلى التصميم. هذه القطعة هي المسؤولة عن تخزين وتشغيل المشهد. يمكنك أن تتخيلها كحاوية لمشهدنا.
بعد ذلك ، نستخدم فئة ModelRenderable
لبناء نموذجنا. باستخدام طريقة setSource
نقوم بتحميل نموذجنا من ملف .sfb
الذي تم إنشاؤه عند استيراد الموارد. تحصل طريقة thenAccept
على النموذج بعد إنشائه ، وقمنا بتعيين النموذج المحمّل على lampPostRenderable
المتغير.
لمعالجة الأخطاء ، لدينا طريقة exceptionally
، تسمى في حالة حدوث استثناء.
كل هذا يحدث بشكل غير متزامن ، لذلك لا داعي للقلق بشأن تعدد العمليات.
الآن وبعد أن تم تحميل النموذج وحفظه في متغير lampPostRenderable
، lampPostRenderable
إلى lampPostRenderable
.
إضافة نموذج إلى المشهد
arFragment
في وضع arFragment
وسوف يستقبل أحداث لمسة المستخدم. لذلك ، نحتاج إلى تثبيت مستمع onTap
أجل معالجة اللمسات ووضع الكائنات حيثما onTap
الحاجة. أضف الكود التالي إلى طريقة 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(); } );
وضعنا مستمع onTapArPlaneListener
AR الخاص بنا. يتم استخدام بناء الجملة التالي لتعبيرات lambda. إذا لم تكن معتادًا عليها ، فراجع هذا الدليل الصغير حول هذا الموضوع.
أولاً ، نقوم بإنشاء مرساة من HitResult
باستخدام hitresult.createAnchor()
وحفظه في كائن Anchor
.
ثم نقوم بإنشاء عقدة من هذا المرساة. سوف يطلق عليه AnchorNode
وسيتم إرفاقه بالمشهد باستخدام طريقة setParent
.
بعد ذلك ، نقوم بإنشاء TransformableNode
، والذي سيكون نموذجنا ، ونربطه بالعقدة الخاصة بنا. لا يزال TransformableNode
لا يحتوي على أي معلومات حول الكائن الذي يجب عرضه. سنقوم بتمرير هذا الكائن إليه باستخدام طريقة setRenderable
، والتي تأخذ كائنًا من النوع ModelRenderable كمعلمة (تذكر ، حصلنا على مثل هذا الكائن واسمه lampPostRenderable
؟). وأخيراً ، نحن نسمي الأسلوب lamp.select()
؛
اوه! الكثير من المصطلحات. لا تقلق ، سأشرح لك كل شيء الآن:
المشهد : هذا هو المكان الذي سيتم فيه عرض جميع الكائنات ثلاثية الأبعاد. يقع هذا المشهد في جزء AR الذي أضفناه إلى التصميم.
HitResult : هذا خط وهمي (أو شعاع) قادم من اللانهاية ، والذي يعطي نقطة تقاطع نفسه مع كائن من العالم الحقيقي.
مرساة : هذا هو موقع ثابت والتوجه في العالم الحقيقي. يمكن فهم الإحداثيات (س ، ص ، ض) في الفضاء ثلاثي الأبعاد. الوضع هو موضع واتجاه كائن ما على المسرح. يتم استخدامه لتحويل مساحة الإحداثيات المحلية للكائن إلى مساحة إحداثية حقيقية.
مرساة العقدة : هذا هو العقدة التي تضع نفسها تلقائيا في العالم الحقيقي. هذه هي العقدة الأولى التي يتم تثبيتها عند اكتشاف الطائرة.
TransformableNode : هذه هي العقدة التي يمكنك التفاعل معها. يمكن تحريكه ، تحجيمه ، تدويره ، وهكذا. في هذا المثال ، يمكننا تغيير حجم كائننا وتدويره. ومن هنا جاء اسم Transformable.
لا يوجد علم الصواريخ. انها حقا بسيطة نسبيا. يمكن عرض المشهد بأكمله في شكل رسم بياني يكون فيه الأصل هو المشهد ، والأطفال هم نقاط ربط ، والتي تتفرع بعد ذلك إلى العديد من العقد والكائنات الأخرى التي سيتم عرضها على الشاشة.
نتيجة لذلك ، يجب أن يبدو نشاطك كما يلي:
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; } }
مبروك! لقد أكملت للتو إنشاء أول تطبيق ARCore. ابدأ في إضافة كائنات إليها ، وسوف ترى كيف تبدأ في الظهور في الحياة الواقعية.
كانت هذه أول نظرة لك على كيفية إنشاء تطبيق ARCore بسيط من البداية في Android Studio. في الدرس التالي ، سوف أتعمق في ARCore وأضف المزيد من الوظائف إلى التطبيق.