ARKit ، SceneKit ، وكيفية السيطرة على العالم

في الجزء 1 من هذه السلسلة ، مررنا بسير عمل حيث قمنا بمعالجة نموذج ثلاثي الأبعاد ، وأنشأنا مشروع AR في Xcode ، وبدأنا جلسة AR ووضعنا نموذجنا في مشهدنا المعزز.

في هذا المنشور ، سنبدأ في تشغيل نموذجنا ، باستخدام مجموعة متنوعة من أساليب SceneKit ، ونبدأ في التفاعل مع الكائنات في عالمنا.

يمكن العثور على مشروع هذا المنشور على https://github.com/AbovegroundDan/ARTutorial_Part2

إجراءات SceneKit

يوفر SceneKit مجموعة من الإجراءات التي يمكن تطبيقها على عقدة. يمكن استخدام هذه الإجراءات لتحريك الحركة ، الدوران ، التحجيم وخصائص العقدة الأخرى. يمكن تجميعها للتشغيل في نفس الوقت ، بالتسلسل لتشغيل واحد تلو الآخر ، وتكرارها أو عكسها. يمكن العثور على القائمة الكاملة على https://developer.apple.com/documentation/scenekit/scnaction

سنستمر في تعديل المشروع الحالي ، ونبدأ في إضافة بعض الإجراءات إلى كائننا. دعنا نبدأ بإضافة دوران إلى مجالنا.

بعد طريقة addSphere في HoverScene لدينا ، أضف الطريقة التالية:

في هذا الرمز ، نقوم بإنشاء إجراء يصف دوران 180 درجة حول المحور ص. يجب أن يستغرق هذا التناوب 5 ثوانٍ حتى يكتمل. ثم نأخذ هذا الإجراء ونضيفه إلى العقدة التي تم تمريرها. الآن ، نحن بحاجة إلى استدعاء هذه الطريقة من طريقة addSphere الخاصة بنا. في نهاية الطريقة ، بعد السطر الذي نضيف فيه العقدة الفرعية ، أضف السطر التالي:

الآن ، إذا قمنا بتشغيل هذا الرمز ، فسنرى مجالنا يدور لمواجهة الوجه الآخر ثم يتوقف. ما نريد القيام به الآن هو جعل هذه الرسوم المتحركة تتكرر ، لذلك تستمر في الدوران.

دعنا نغير كود addAnimation الخاص بنا إلى ما يلي:

هنا ، قمنا بإضافة تكرار للأبد ، والذي يأخذ في إجراء الدوران كمدخل. ثم بدلاً من إجراء التدوير ، نضيف إجراء تكرار إلى العقدة الخاصة بنا. قم بتشغيل الكود مرة أخرى ، وسوف نرى أن كراتنا تدور الآن بشكل مستمر.

دعنا نضيف قليلا من البيتزا إلى المجال. لنجعلها تحوم لأعلى ولأسفل قليلاً. سنقوم بإضافة إجراء تحويم ، إجراء تحريك لأسفل ، ترتيب تسلسل هذين الإجراءين ، ثم تجميعهم بإجراءات تدوير حالية. هذا ما يجب أن تبدو عليه طريقة addAnimation:

الآن لدينا كرة دوّارة تحوم بحيث يمكننا وضعها في أي مكان في عالمنا.

HitTests والتجريدية

دعنا نضيف بعض التفاعل إلى المشهد. دعونا نضع هدفًا لبدء المشهد عن طريق جعل المستخدم يضع المجالات في العالم ، ثم انقر فوق لتنشيطها. نظرًا لأننا أصبحنا أكثر تعقيدًا مع الشفرة الخاصة بنا ، فقد حان الوقت للبدء في تجريد الطريقة التي نتعامل بها مع كائنات المشهد لدينا. قم بإنشاء مجموعة جديدة في مشروعنا يسمى الكائنات. في هذا المجلد ، سنقوم بإنشاء ملف Swift جديد يسمى SceneObject.swift.

سنقوم بإنشاء فئة أساسية ، SceneObject ، مشتقة من SCNNode.

نريد أن نستخلص تحميل الكائن من بقية الكود ، لذلك يتيح إنشاء طريقة init () تأخذ اسم ملف. في أداة التهيئة هذه ، سننقل الشفرة التي لدينا للتحميل من الملف.

الآن يمكننا إنشاء فئة Sphere مشتقة من SceneObject:

لدينا الآن فئة كائن Sphere يمكنها تحميل نفسها. نظرًا لأننا سنحرك المجالات عندما نضغط عليها ، دعنا نزيل مكالمة addAnimation من طريقة addSphere في HoverScene. أيضًا ، نظرًا لأننا نقلنا الآن كل رمز التحميل إلى فئة Sphere ، فيمكننا فقط تهيئة Sphere وإضافته إلى عقدة الجذر للمشهد مباشرةً. تبدو طريقةنا المبسطة إلى حد كبير الآن كما يلي:

كثير نظافة!

الآن ، سوف نلقي نظرة على كيف يمكننا إجراء اختبار نجاح. لدينا بالفعل أداة التعرف على إيماءات النقر في وحدة تحكم العرض الخاصة بنا ، حتى نتمكن من ربط ذلك ، ولكن كيف نعرف ما إذا كانت صنابيرنا تضرب كرة أو كائنًا آخر أو لا شيء على الإطلاق؟

لحسن الحظ ، يمكن أن يساعدنا ARSCNView في ذلك. لديها الطريقة التالية:

يمكننا إطعام موقع في طريقة العرض ، وسوف يعيدنا مجموعة من العقد التي تقع تحت تلك النقطة ، بغض النظر عن القيمة z أو العمق.

نظرًا لأننا نريد فقط التقاط كائنات Sphere ، يتيح لك إنشاء عامل تصفية سريع يتحقق لمعرفة ما إذا كانت كل عقدة تم إرجاعها في hitTest هي Sphere. للقيام بذلك ، نحن بحاجة إلى الحصول على العقدة الأصل الأعلى لكل عقدة نريد التحقق منها. دعنا نعود إلى ملف Node + Extensions.swift وأضف الطريقة التالية:

نظرًا لأن جميع الكائنات الموجودة في المشهد لدينا هي جزء من عقدة الجذر للمشهد ، فنحن نريد التوقف عندما نصل إلى تلك العقدة ولا نتحقق منها أكثر. نظرًا لأنها طريقة متكررة ، فإننا نتوقف ونعود عندما نجد أن العقدة الجذرية هي أصل عقدتنا.

مع هذا ورائنا ، دعنا نعود إلى ViewController وقمنا بتعديل مندوب أداة التعرف على إشارة النقر. نريد مواصلة إضافة مجالات جديدة إذا نقرت على مساحة فارغة ، ولكن إذا نقرت على مجال موجود ، نريد أن نبدأ الرسوم المتحركة الخاصة بها.

عندما نحصل على نقرة ، نريد أن نوضح النقطة في عرض المشهد لدينا ، وننقل ذلك إلى طريقة hitTest الخاصة بعرض المشهد ، ونرى ما نعود إليه. نظرًا لأننا نريد فقط التعامل مع كائن واحد في وقت واحد ، فإننا نلتقط العنصر الأول (إذا كان هناك عدد من الزيارات) ، ثم نستخدم امتدادنا الأعلى () للاستيلاء على الوالد الأعلى ، والتحقق من وجوده في مجال. إذا كان كذلك ، فإننا نضيف الرسوم المتحركة لدينا. إذا لم نحصل على أي نتائج من اختبارنا ، فسنقوم بذلك كما كان من قبل ، مضيفًا كرة جديدة أمام الكاميرا.

المضي قدما وتشغيل التطبيق مرة أخرى. يمكننا النقر فوق لإضافة كرة ، ثم النقر فوق أي كرة لبدء التحرك. ومع ذلك ، لدينا خطأ قدمنا. يمكننا الاستمرار في التنصت على كرة وستظل الرسوم المتحركة تضاف إلى الكائن في كل مرة. يمكنك اختباره ورؤية الكرة تدور بشكل أسرع وتتحرك لأعلى ولأسفل بشكل أسرع في كل مرة تنقر فيها.

نظرًا لأن الرسوم المتحركة خاصة بالمجال ، دعنا ننقل كود addAnimation إلى Sphere نفسها ، وأعد تسميتها لتحريك فقط (). بدلاً من node.addAnimation ، يمكننا فقط استدعاء addAnimation. سنقوم أيضًا بإضافة علامة إلى فئة Sphere ، والتي سنقوم بفحصها قبل إضافة الرسوم المتحركة ، وتعيينها على "صحيح" عند إضافتها لأول مرة:

كل ما تبقى هو تغيير الكود في رد الاتصال للإيماءات لتشغيل هذه المكالمة الجديدة على الكرة نفسها.

لقد أصبحنا جميعًا مع هذا الجزء الآن. لدينا مجال يمكننا أن نضعه في العالم ، أضفنا بعض التفاعل حتى نتمكن من إطلاق الرسوم المتحركة ، وتنظيف الكود قليلاً.

رصيد إضافي

الطريقة التي نضع بها كرة في العالم مفاجئة للغاية. نقر ، وفجأة هناك. دعنا نضيف القليل من هذه الوظيفة وننشط الكرة عندما نضعها.

في طريقة addSphere الخاصة بنا في HoverScene ، دعنا نضيف تأثير مقياس. عندما نضيف الكرة ، سنقوم بتحريك حجمها ، وبدلاً من استخدام مقياس خطي قياسي ، سنضع تأثيرًا ارتداديًا أو ينبثق.

دعنا نغير طريقة addSphere لدينا إلى ما يلي ، ونضيف في وظيفة توقيت easyOutElastic ، والتي ستوفر لنا هذا الارتداد:

الآن عندما نقر لوضع الكرة ، نحصل على تأثير متحرك رائع.

رصيد إضافي ، جزء deux

لقد فعلنا الكثير من الأشياء باستخدام SceneKit ، لكننا قمنا فقط برعاية سطح بعض الأشياء التي يمكن أن تقوم بها ARKit. كدعابة سريعة قبل أن نحصل على المزيد من وظائف ARKit ، دعونا نضيف بعض المرح إلى المشهد ، من خلال جعل الكرة "تنظر" إلى الكاميرا. لقد وصلنا بالفعل إلى طريقة تحديث وقت تقديم العارض ، ولدينا إشارة إلى الكاميرا هناك أيضًا. لذلك دعونا نبدأ بإضافة طريقة إلى فئة Sphere ، لننظر إلى اتجاه معين. تواجه "عين" الكرة بالفعل Z سالبة ، وهو اتجاه الكائن للأمام. ما سنفعله هو إنشاء طريقة تأخذ متجهًا يشير إلى نقطة في الفضاء ستواجهها "عيننا".

في هذا الرمز ، ننظر إلى المسافة بين الكرة وموضع الهدف (الكاميرا). إذا كان أقل من بعض المبلغ ، فسنحفز العين على مواجهة الهدف. إذا كانت العين تواجه الكاميرا وكان المستخدم يتحرك بعيدًا عن هذه المسافة المحددة ، فسنذهب إلى الرسوم المتحركة "الدورية" الخاصة بنا. شيء واحد يجب أن نلاحظه في هذا الكود هو أنه نظرًا لعدم وجود SCNAction مفيد لتطبيق الرسوم المتحركة "LookAt" ، فإننا نلتف نظرتنا (على :) call في SCNTransaction ، مما يسمح لنا بتنشيط الحركة. تحتوي محركات الألعاب ثلاثية الأبعاد المخصصة مثل Unity أو Unreal على وظائف ملائمة لهذه الأشياء ، لكن SceneKit لم يصل بعد إلى هذا المستوى.

قد تلاحظ وجود مكالمة عن بعد على targetPos SCNVector3 تم تمريرها ، ولكن هذه الطريقة غير موجودة لـ SCNVector3. ما سنفعله هو إضافة امتداد جديد لهذه المكالمة عن بعد.

أضع هذا الرمز في ملف UtilityExtensions.swift جديد ، لكن لا تتردد في وضعه في أي مكان تريد.

بعد ذلك ، سنحتاج إلى تغيير أسلوب updateAtTime الخاص بنا لإزالة التحقق من العلم واستدعاء طريقة في وحدة تحكم المشهد لدينا في كل إطار. سيكون المسؤول عن المشهد لدينا مسؤولاً عن إرسال الرسالة إلى جميع كائنات Sphere في مشهدنا.

في HoverScene الخاص بنا ، سننشئ طريقة makeUpdateCameraPos ، والتي ستقوم بالفلترة على كائنات Sphere فقط ، واستدعاء طريقة الدوريات.

دعنا نغير أيضًا طريقة وضعنا لوضع المجالات بعيدًا بعض الشيء. لنجعل طريقة didTapScreen تضع كرة لدينا على بعد 5 أمتار بدلاً من 1:

في فئة Sphere ، دعنا نجعل عتبتنا لتحفز البصر إلى 4.85 متر:

لنقم أيضًا بتغيير الرسوم المتحركة الخاصة بنا في Sphere بحيث تبدو حولها قليلاً ، ولا تحوم.

فإن Float.random هو امتداد آخر وهو ببساطة:

إعطاء هذا المدى ووضع بعض المجالات. يجب عليهم تحريكها بمفردهم الآن ، دون الحاجة إلى النقر عليها. اقترب أكثر من كل واحد وسترى أنظارها عنك. المشي بعيدا ويجب أن يعودوا للقيام بدوريات في منطقتهم. الآن لدينا مشهد مباشرة من المستقبل المرير ، مع عيون تحوم تراقب كل خطوة لدينا.

ترقبوا المزيد من المرح ARKit!