WebVR الجزء 5: التصميم والتنفيذ
نشرت: 2022-03-11أحب إنجاز المشاريع. لقد وصلنا إلى نهاية رحلتنا - وولادة محاكاة الجاذبية السماوية الخاصة بنا في WebVR.
في هذا المنشور الأخير ، سنقوم بتوصيل كود المحاكاة عالي الأداء الخاص بنا (المقالات 1،2،3) في متخيل WebVR استنادًا إلى مصور لوحة الرسم (المادة 4).
- "مشكلة الجسم في الجسم" المقدمة والهندسة المعمارية
- يحصل العاملون على الويب على مؤشرات ترابط إضافية في المتصفح
- WebAssembly و AssemblyScript لكود اختناق الأداء O (n²)
- تصور بيانات Canvas
- تصور بيانات WebVR
هذه مقالة أطول ، لذا سنتخطى بعض التفاصيل الفنية التي تمت تغطيتها مسبقًا. تحقق من المشاركات السابقة إذا كنت ترغب في الحصول على توجيه ، أو اقرأ بشكل خطير.
لقد كنا نستكشف النقلة النوعية للمتصفح من وقت تشغيل JavaScript أحادي الترابط إلى وقت تشغيل عالي الأداء متعدد الخيوط (عمال الويب) (WebAssembly). تتوفر ميزات حوسبة سطح المكتب للأداء في تطبيقات الويب التقدمية ونموذج توزيع SaaS.
ستنشئ VR بيئات مبيعات وتسويق مقنعة خالية من التشتيت للتواصل والإقناع وقياس المشاركة (تتبع العين والتفاعل). ستظل البيانات عبارة عن أصفار وآحاد ، ولكن الملخص التنفيذي المتوقع وتجربة المستهلك ستكون WebVR - تمامًا كما نبني تجارب لوحة تحكم للجوال للويب المسطح اليوم.
تعمل هذه التقنيات أيضًا على تمكين الحوسبة الموزعة على حافة المتصفح. على سبيل المثال ، يمكننا إنشاء تطبيق مستند إلى الويب لتشغيل حسابات WebAssembly لملايين النجوم في محاكاة. مثال آخر هو تطبيق الرسوم المتحركة الذي يعرض إبداعات المستخدمين الآخرين أثناء قيامك بتحرير إبداعاتك الخاصة.
يقود المحتوى الترفيهي انتشار الواقع الافتراضي ، تمامًا مثل الترفيه الذي يُقاد على الهاتف المحمول. ومع ذلك ، بمجرد أن يصبح الواقع الافتراضي أمرًا طبيعيًا (مثل تصميم الهاتف المحمول أولاً اليوم) ، ستكون التجربة المتوقعة (تصميم VR الأول). هذا وقت مثير للغاية لأن تكون مصممًا ومطورًا - والواقع الافتراضي هو نموذج تصميم مختلف تمامًا.
أنت لست مصمم VR إذا كنت لا تستطيع السيطرة. هذا بيان جريء ، واليوم هو الغوص العميق في تصميم VR. يتم اختراع هذا المجال وأنت تقرأ هذا. هدفي هو مشاركة خبراتي في البرمجيات والأفلام لبدء محادثة "تصميم الواقع الافتراضي أولاً". نحن جميعا نتعلم من بعضنا البعض.
مع وضع هذه التوقعات العظيمة في الاعتبار ، أردت إكمال هذا المشروع كعرض تقني احترافي - يعد WebVR خيارًا رائعًا لذلك!
WebVR و Google A-Frame
WebVR git repo عبارة عن نسخة متفرعة من إصدار Canvas لعدة أسباب. إنه يجعل استضافة المشروع على صفحات Github أسهل ، وتطلب WebVR إجراء بعض التغييرات التي قد تؤدي إلى تشويش نسخة اللوحة القماشية وهذه المقالات.
إذا كنت تتذكر أول منشور لنا عن الهندسة المعمارية ، فقد فوضنا المحاكاة بأكملها إلى nBodySimulator
.
أظهر منشور عامل الويب أن nBodySimulator
له وظيفة step()
تسمى كل 33 مللي ثانية من المحاكاة. step()
استدعاءات calculateForces()
لتشغيل كود محاكاة WebAssembly O (n²) (المقالة 3) ، ثم تحديث المواضع وإعادة الطلاء. في المنشور السابق الذي أنشأنا تصورًا للوحة القماشية ، قمنا بتنفيذ ذلك باستخدام عنصر لوحة الرسم ، بدءًا من هذه الفئة الأساسية:
/** * Base class that console.log()s the simulation state. */ export class nBodyVisualizer { constructor(htmlElement) { this.htmlElement = htmlElement this.resize() this.scaleSize = 25 // divided into bodies drawSize. drawSize is log10(mass) // This could be refactored to the child class. // Art is never finished. It must be abandoned. } resize() {} paint(bodies) { console.log(JSON.stringify(bodies, null, 2)) } }
حدد تحدي الاندماج
لدينا المحاكاة. الآن ، نريد التكامل مع WebVR - دون إعادة تصميم مشروعنا. مهما كانت التعديلات التي نجريها على المحاكاة ، فإنها تحدث كل 33 مللي ثانية في مؤشر ترابط واجهة المستخدم الرئيسي في paint(bodies)
.
هذه هي الطريقة التي نقيس بها "تم". أنا متحمس - هيا بنا إلى العمل!
كيف تصنع واقع افتراضي
أولاً ، نحتاج إلى تصميم:
- ما هو مصنوع من VR؟
- كيف يتم التعبير عن تصميم WebVR؟
- كيف يمكننا التفاعل معها؟
يعود الواقع الافتراضي إلى فجر التاريخ. كل قصة من روايات المخيم هي عالم افتراضي صغير مليء بالمبالغات الغريبة المغطاة بتفاصيل تافهة.
يمكننا 10 أضعاف قصة إطلاق النار لدينا عن طريق إضافة مرئيات وصوت مجسم ثلاثي الأبعاد. اعتاد مدرب ميزانية إنتاج الأفلام أن يقول ، "نحن ندفع فقط مقابل الملصق. نحن لا نبني الواقع ".
إذا كنت معتادًا على متصفح DOM ، فستعرف أنه ينشئ بنية هرمية تشبه الشجرة.
يشتمل تصميم الويب بشكل ضمني على أن المشاهد يشاهد من "الأمام". إن النظر من الجانب سيكشف عن عناصر DOM كخطوط ، ومن الخلف ، سنرى فقط علامة <body>
لأنها تحجب عناصرها الفرعية.
جزء من التجربة الغامرة للواقع الافتراضي هو السماح للمستخدم بالتحكم في وجهة نظره وأسلوبه ووتيرته وترتيب تفاعلاته. لا يتعين عليهم الانتباه إلى أي شيء على وجه الخصوص. إذا قمت بتحريك الكاميرا أو تدويرها برمجيًا ، فسوف تتقيأ حرفيًا من مرض الواقع الافتراضي.
يرجى ملاحظة أن مرض الواقع الافتراضي ليس مزحة. كل من عيوننا وآذاننا الداخلية تكتشف الحركة. من المهم جدًا للحيوان الذي يمشي في وضع مستقيم. عندما تختلف مستشعرات الحركة هذه ، يفترض دماغنا بشكل طبيعي أن فمنا يأكل الهراء مرة أخرى ويتقيأ. كنا جميعًا أطفالًا مرة واحدة. لقد كتب الكثير عن غريزة البقاء في الواقع الافتراضي بالفعل. عنوان "Epic Fun" مجاني على Steam ، و rollercoaster هو أفضل عرض تجريبي لمرض الواقع الافتراضي وجدته.
يتم التعبير عن الواقع الافتراضي على أنه "رسم بياني للمشهد". الرسم البياني للمشهد له نفس نمط الشجرة مثل DOM لإخفاء تفاصيل وتعقيد بيئة ثلاثية الأبعاد مقنعة. ومع ذلك ، بدلاً من التمرير والتوجيه ، نضع العارض في المكان الذي يريد جذب التجربة تجاهه.
إليك الرسم البياني للمشهد Hello World من إطار عمل WebVR A-Frame من Google:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello, WebVR! • A-Frame</title> <meta name="description" content="Hello, WebVR! • A-Frame"> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> </head> <body> <a-scene background="color: #FAFAFA"> <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box> <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere> <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder> <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane> </a-scene> </body> </html>
ينشئ مستند HTML هذا DOM في المتصفح. تعد العلامات <a-*>
- *> جزءًا من إطار A-Frame ، و <a-scene>
هي جذر الرسم البياني للمشهد. هنا ، نرى أربعة عناصر أولية ثلاثية الأبعاد معروضة في المشهد.
أولاً ، لاحظ أننا نشاهد المشهد من مستعرض ويب مسطح. يدعو القناع الصغير الموجود في أسفل اليمين المستخدم إلى التبديل إلى وضع ثلاثي الأبعاد مجسم.
من الناحية النظرية ، يجب أن تكون قادرًا على:
- افتح هذا على هاتفك
- ضع هاتفك في مواجهة وجهك
- البهجة في روعة الواقع الجديد!
لم أحصل على ذلك مطلقًا بدون العدسات الفاخرة لسماعات رأس VR. يمكنك الحصول على سماعة رأس VR لهاتف Android بسعر رخيص (جهاز أساسي يعتمد على Google Cardboard) ، ومع ذلك ، لتطوير المحتوى ، أقترح جهاز HMD مستقل (شاشة مثبتة على الرأس) مثل Oculus Quest.
مثل الكثير من الغطس أو القفز بالمظلات ، فإن الواقع الافتراضي هو رياضة تروس.
تعلم مصممي VR "Cliff"
لاحظ أن مشهد A-Frame Hello World به إضاءة وكاميرا افتراضية:
- وجوه المكعب بألوان مختلفة - المكعب ذاتي التظليل.
- المكعب يلقي بظلاله على الطائرة - هناك ضوء اتجاهي.
- لا توجد فجوة بين المكعب والمستوى - هذا عالم به جاذبية.
هذه إشارات مهمة تقول للمشاهد ، "استرخي ، هذا الشيء على وجهك طبيعي تمامًا."
لاحظ أيضًا أن هذا الإعداد الافتراضي ضمني في رمز مشهد Hello World أعلاه. يوفر A-Frame بحكمة افتراضيًا معقولًا ، ولكن لاحظ - الكاميرا والإضاءة هما الصدع الذي يجب على مصممي الويب المسطح عبوره لإنشاء VR.
نحن نأخذ إعداد الإضاءة الافتراضي كأمر مسلم به. على سبيل المثال ، الأزرار:
لاحظ مدى انتشار هذه الإضاءة الضمنية في التصميم والتصوير الفوتوغرافي. حتى زر "التصميم المسطح" لا يمكنه الهروب من الإضاءة الافتراضية للويب - إنه يلقي بظلاله على اليمين.
يعد تصميم وتوصيل وتنفيذ إعدادات الإضاءة والكاميرا منحدر التعلم لمصمم WebVR. "لغة الفيلم" عبارة عن مجموعة من المعايير الثقافية - يتم التعبير عنها في صورة إعدادات مختلفة للكاميرا والإضاءة - تنقل القصة عاطفيًا إلى الجمهور. المحترفون في صناعة الأفلام الذين يصممون / ينقلون الأضواء والكاميرا حول المشهد هم قسم القبضة.
العودة إلى واقعنا الافتراضي
الآن بعد ذلك ، دعنا نعود إلى العمل. مشهدنا السماوي WebVR له نمط مماثل:
<!DOCTYPE> <html> <head> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/aframe-event-set-component.min.js"></script> <script src="main.js"></script> </head> <body> <a-scene> <a-sky color="#222"></a-sky> <a-entity geometry="primitive: circle; radius: 12" position="0 0 -.5" material="color: #333; transparent: true; opacity: 0.5"> <a-sphere color="black" radius=."02"></a-sphere> </a-entity> <a-entity></a-entity> <a-entity geometry="primitive: plane; width: 2; height: auto" position="0 -10 .3" rotation="55 0 0" material="color: blue" text="value: Welcome Astronaut!..."> </a-entity> <a-entity position="0 -12 .7" rotation="55 0 0"> <a-camera> <a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor> </a-camera> </a-entity> </a-scene> </body> </html>
يقوم مستند HTML هذا بتحميل إطار A-Frame ومكوِّن إضافي للتفاعل. يبدأ مشهدنا في <a-scene>
.
في الداخل ، نبدأ بعنصر <a-sky color="#222"></a-sky>
إلى لون الخلفية لكل شيء لم نحدده في المشهد.
بعد ذلك ، نقوم بإنشاء "طائرة مدارية" للمشاهد "ليتمسك بها" أثناء طيرانه عبر عالمنا الغريب وغير المعروف. نقوم بإنشاء هذا كقرص وكرة سوداء صغيرة عند (0،0،0). بدون هذا ، شعرت بأن الانعطاف "لا أساس له" بالنسبة لي:
<a-entity geometry="primitive: circle; radius: 12" position="0 0 -.5" material="color: #333; transparent: true; opacity: 0.5"> <a-sphere color="black" radius=."02"></a-sphere> </a-entity>
بعد ذلك ، نحدد مجموعة حيث يمكننا إضافة / إزالة / تغيير موضع كيانات A-Frame.
<a-entity></a-entity>
هذه هي المساحة المخصصة paint(bodies)
nBodyVisualizer
للقيام بعملها.
ثم نخلق العلاقة بين المشاهد وهذا العالم. كعرض تقني ، الغرض من هذا العالم هو السماح للمشاهد باستكشاف WebVR وتقنية المتصفح التي تمكنه. يخلق السرد البسيط لـ "رائد فضاء" إحساسًا باللعب ، وهذه العلامة النجمية هي نقطة مرجعية أخرى للملاحة.
<a-entity geometry="primitive: plane; width: 2; height: auto" position="0 -10 .3" rotation="55 0 0" material="color: blue" text="value: Welcome Astronaut!\n ..."> </a-entity>
هذا يكمل الرسم البياني للمشهد لدينا. أخيرًا ، أردت نوعًا من التفاعل في العرض التوضيحي عبر الهاتف بين المستخدم وهذا العالم الشائك. كيف يمكننا إعادة إنشاء زر "Throw Debris" في VR؟
الزر عنصر أساسي في كل التصميمات الحديثة - أين أزرار الواقع الافتراضي؟
التفاعلات في WebVR
الواقع الافتراضي له "فوق" و "الجزء السفلي غير المرئي من الصفحة". يكون التفاعل الأول للمشاهد من خلال الصورة الرمزية أو الكاميرا. هذه هي كل الضوابط للتكبير.
إذا كنت تقرأ هذا على سطح المكتب ، فيمكنك WASD للتحرك والماوس لتدوير الكاميرا. يكشف هذا الاستكشاف عن معلومات ولكنه لا يعبر عن إرادتك.
للواقع ميزتان مهمتان للغاية لا توجدان غالبًا على الويب:
- المنظور - تصبح الأشياء أصغر بشكل واضح عندما تبتعد عنا.
- الانسداد - يتم إخفاء الأشياء وكشفها بناءً على الموضع.
يحاكي الواقع الافتراضي هذه الميزات لإنشاء التأثير ثلاثي الأبعاد. يمكن استخدامها أيضًا في الواقع الافتراضي للكشف عن المعلومات والواجهة - ولضبط الحالة المزاجية قبل تقديم التفاعلات. لقد وجدت أن معظم الناس يحتاجون فقط إلى دقيقة واحدة للاستمتاع بالتجربة قبل المضي قدمًا.

في WebVR ، نتفاعل في مساحة ثلاثية الأبعاد. لدينا أداتان أساسيتان لهذا:
- تصادم - يتم تشغيل حدث ثلاثي الأبعاد سلبي عندما يتشارك جسمان في نفس المساحة.
- الإسقاط - استدعاء دالة ثنائية الأبعاد نشطة تسرد جميع الكائنات التي تتقاطع مع خط.
التصادم هو أكثر تفاعل "شبيه بالواقع الافتراضي"
في الواقع الافتراضي ، "الاصطدام" هو بالضبط ما يبدو عليه: عندما يتشارك كائنان في نفس المساحة ، يقوم A-Frame بإنشاء حدث.
لكي "يضغط" المستخدم على زر ، يجب أن نعطيهم بيدقًا وشيءًا للضغط على الزر به.
لسوء الحظ ، لا يمكن لـ WebVR تحمل وحدات التحكم حتى الآن - سينظر العديد من الأشخاص إلى إصدار الويب المسطح على سطح المكتب أو الهاتف ، وسيستخدم الكثيرون سماعة رأس مثل Google Cardboard أو Samsung Gear VR لعرض نسخة مجسمة.
إذا لم يكن لدى المستخدم وحدات تحكم ، فلن يتمكن من الوصول إلى الأشياء و "لمسها" ، لذا فإن أي تصادم يجب أن يكون مع "مساحته الشخصية".
يمكننا أن نمنح اللاعب بيدقًا على شكل رائد فضاء ليتحرك ، ولكن يبدو أن إجبار المستخدم على الدوران في وسط من الكواكب أمر بعيد المنال ويتعارض مع اتساع تصميمنا.
الإسقاط هو ثنائي الأبعاد "يشبه الويب" انقر في مساحة ثلاثية الأبعاد
إلى جانب "الاصطدام" ، يمكننا أيضًا استخدام "الإسقاط". يمكننا رسم خط من خلال مشهدنا ورؤية ما يلمسه. المثال الأكثر شيوعًا هو "شعاع النقل عن بعد".
يتتبع شعاع النقل الآني خطًا في العالم لإظهار المكان الذي يمكن للاعب أن يتحرك فيه. يبحث هذا "الإسقاط" عن أماكن للهبوط. تقوم بإرجاع كائن واحد أو أكثر في مسار الإسقاط. هنا مثال شعاع النقل الآني:
لاحظ أن الشعاع يتم تنفيذه فعليًا باعتباره قطع مكافئ يشير إلى أسفل. هذا يعني أنه يتقاطع بشكل طبيعي مع "الأرض" مثل الجسم الذي تم إلقاؤه. هذا أيضًا يحدد بشكل طبيعي مسافة نقل تخاطر قصوى. تعتبر الحدود من أهم خيارات التصميم في الواقع الافتراضي. لحسن الحظ ، للواقع العديد من القيود الطبيعية.
يعمل العرض على "تسطيح" العالم ثلاثي الأبعاد إلى ثنائي الأبعاد بحيث يمكنك الإشارة إلى الأشياء للنقر عليها مثل الماوس. ألعاب إطلاق النار من منظور الشخص الأول هي ألعاب متقنة من "النقر ثنائي الأبعاد" على أزرار محبطة بشكل رائع - غالبًا مع قصة تفصيلية لشرح سبب عدم سماع أزرار الرتق "النقر" مرة أخرى.
هناك الكثير من البنادق في الواقع الافتراضي لأن البنادق قد تم إتقانها باعتبارها فئران ثلاثية الأبعاد دقيقة وموثوقة - والنقر هو ما يعرف المستهلكون كيف يفعلونه دون التعلم.
يوفر الإسقاط أيضًا أمان المسافة في العلاقة مع المشهد. تذكر أن الاقتراب من شيء ما في الواقع الافتراضي سوف يحجب بطبيعة الحال كل الأشياء الأخرى التي ربما لم يتم الكشف عن أهميتها بعد.
إسقاط بدون ضوابط باستخدام "النظرة"
لإنشاء هذا التفاعل البدائي في WebVR بدون وحدات تحكم ، يمكننا عرض "نظرة" المشاهدين كخط رؤية "مؤشر". يمكن استخدام هذا المؤشر برمجيًا للتفاعل مع الكائنات باستخدام "الصمامات". يتم توصيل هذا للمشاهد كدائرة زرقاء صغيرة. نحن الآن نقر!
إذا كنت تتذكر قصص نيران المخيم ، فكلما كانت الكذبة أكبر ، كلما قلت التفاصيل اللازمة لبيعها. تفاعل "النظرة" الواضح والعبثي هو التحديق في الشمس. نستخدم هذا "التحديق" لتحفيز إضافة كواكب "حطام" جديدة إلى محاكاتنا. لم يشكك أي عارض في هذا الاختيار على الإطلاق - الواقع الافتراضي ساحر للغاية عندما يكون سخيفًا.
في A-Frame ، نعبر عن الكاميرا (بيدق اللاعب غير المرئي) وخط الرؤية هذا "المؤشر" باعتباره تزوير الكاميرا. يؤدي وضع <a-cursor>
داخل <a-camera>
إلى تطبيق تحويلات الكاميرا على المؤشر أيضًا. عندما يتحرك اللاعب / يدير البيدق ( a-camera
) ، فإنه يتحرك أيضًا / يدير بصره ( a-cursor
).
// src/index.html <a-entity position="0 -12 .7" rotation="55 0 0"> <a-camera> <a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor> </a-camera> </a-entity>
ينتظر "فتيل" المؤشر حتى مرور ثانية كاملة من "التحديق" قبل إصدار حدث.
لقد استخدمت الإضاءة الافتراضية لذلك قد تلاحظ وجود "خلفية" غير مضاءة للشمس. بينما لم أكن خارج الطائرة المدارية ، لا أعتقد أن هذه هي الطريقة التي تعمل بها الشمس. ومع ذلك ، فهو يعمل مع ملصقنا التجريبي التقني للواقع.
قد يكون الخيار البديل هو وضع الإضاءة داخل عنصر الكاميرا ، بحيث يتحرك مع المستخدم. هذا من شأنه أن يخلق تجربة أكثر حميمية - وربما مخيفة - لعمال منجم كويكب. هذه خيارات تصميم ممتعة.
لدينا خطة تكامل
مع ذلك ، لدينا الآن نقاط التكامل بين A-Frame <a-scene>
ومحاكاة JavaScript الخاصة بنا:
أ- إطار <a-scene>
:
مجموعة مسماة للجثث:
<a-entity></a-entity>
مؤشر سيصدر أحداث الإسقاط:
<a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor>
محاكاة جافا سكريبت لدينا:
nBodyVisWebVR.paint(bodies)
- إضافة / إزالة / تغيير موضع كيانات الواقع الافتراضي من هيئات المحاكاةaddBodyArgs(name, color, x, y, z, mass, vX, vY, vZ)
لإضافة أجسام حطام جديدة إلى المحاكاة
يقوم index.html
بتحميل main.js
، مما يؤدي إلى تهيئة المحاكاة تمامًا مثل إصدار لوحة الرسم:
// src/main.js import { nBodyVisualizer, nBodyVisWebVR } from ."/nBodyVisualizer" import { Body, nBodySimulator } from ."/nBodySimulator" window.onload = function() { // Create a Simulation const sim = new nBodySimulator() // this Visualizer manages the UI sim.addVisualization(new nBodyVisWebVR(document.getElementById("a-bodies"), sim)) // making up stable universes is hard // name color xyzm vz vy vz sim.addBody(new Body("star", "yellow", 0, 0, 1, 1e9)) sim.addBody(new Body("hot-jupiter", "red", -1, -1, 1, 1e4, .24, -0.05, 0)) sim.addBody(new Body("cold-jupiter", "purple", 4, 4, .5, 1e4, -.07, 0.04, 0)) // Start simulation sim.start() // Add another sim.addBody(new Body("saturn", "blue", -8, -8, .1, 1e3, .07, -.035, 0)) }
ستلاحظ هنا أننا قمنا بتعيين htmlElement
الخاص بالمتخيل على a-bodies
لعقد الأجسام.
إدارة كائنات A-Frame برمجيًا من JavaScript
بعد أن أعلنا مشهدنا في index.html
، نحن الآن جاهزون لترميز المتخيل.
أولاً ، قمنا بإعداد nBodyVisualizer
للقراءة من قائمة هيئات nBodySimulation
وإنشاء / تحديث / حذف كائنات A-Frame في مجموعة <a-entity></a-entity>
.
// src/nBodyVisualizer.js /** * This is the WebVR visualizer. * It's responsible for painting and setting up the entire scene. */ export class nBodyVisWebVR extends nBodyVisualizer { constructor(htmlElement, sim) { // HTML Element is a-collection#a-bodies. super(htmlElement) // We add these to the global namespace because // this isn't the core problem we are trying to solve. window.sim = sim this.nextId = 0 } resize() {}
في المُنشئ ، نحفظ مجموعة A-Frame الخاصة بنا ، ونضع متغيرًا عالميًا لحدث النظرة الخاص بنا للعثور على المحاكاة ، وتهيئة عداد معرف سنستخدمه لمطابقة الأجسام بين المحاكاة ومشهد A-Frame.
paint(bodies) { let i // Create lookup table: lookup[body.aframeId] = body const lookup = bodies.reduce( (total, body) => { // If new body, give it an aframeId if (!body.aframeId) body.aframeId = `a-sim-body-${body.name}-${this.nextId++}` total[body.aframeId] = body return total }, {}) // Loop through existing a-sim-bodies and remove any that are not in // the lookup - this is our dropped debris const aSimBodies = document.querySelectorAll(."a-sim-body") for (i = 0; i < aSimBodies.length; i++) { if (!lookup[aSimBodies[i].id]) { // if we don't find the scene's a-body in the lookup table of Body()s, // remove the a-body from the scene aSimBodies[i].parentNode.removeChild(aSimBodies[i]); } } // loop through sim bodies and upsert let aBody bodies.forEach( body => { // Find the html element for this aframeId aBody = document.getElementById(body.aframeId) // If html element not found, make one. if (!aBody) { this.htmlElement.innerHTML += ` <a-sphere class="a-sim-body" dynamic-body ${ (body.name === "star") ? "debris-listener event-set__enter='_event: mouseenter; color: green' event-set__leave='_event: mouseleave; color: yellow'" : ""} position="0 0 0" radius="${body.drawSize/this.scaleSize}" color="${body.color}"> </a-sphere>` aBody = document.getElementById(body.aframeId) } // reposition aBody.object3D.position.set(body.x, body.y, body.z) }) }
أولاً ، نقوم بإجراء حلقة عبر أجسام المحاكاة لتسمية و / أو إنشاء جدول بحث لمطابقة كيانات الإطار A مع أجسام المحاكاة.
بعد ذلك ، نقوم بإجراء حلقة من خلال أجسام A-Frame الحالية وإزالة أي منها تم قطعه بواسطة المحاكاة للسفر خارج الحدود. هذا يزيد من الأداء المتصور للتجربة.
أخيرًا ، نقوم بعمل حلقة عبر أجسام sim لإنشاء <a-sphere>
جديد للأجسام المفقودة ولإعادة وضع الآخرين باستخدام aBody.object3D.position.set(body.x, body.y, body.z)
يمكننا تغيير العناصر برمجيًا في مشهد A-Frame باستخدام وظائف DOM القياسية. لإضافة عنصر إلى المشهد ، نقوم بإلحاق سلسلة إلى HTML الداخلي للحاوية. طعم هذا الرمز غريب بالنسبة لي ولكنه يعمل ، ولم أجد أي شيء أفضل منه.
ستلاحظ عندما أنشأنا السلسلة المراد إلحاقها ، لدينا عامل تشغيل ثلاثي بالقرب من "star" لتعيين سمة.
<a-sphere class="a-sim-body" dynamic-body ${ (body.name === "star") ? "debris-listener event-set__enter='_event: mouseenter; color: green' event-set__leave='_event: mouseleave; color: yellow'" : ""} position="0 0 0" radius="${body.drawSize/this.scaleSize}" color="${body.color}"> </a-sphere>`
إذا كان الجسد "نجمًا" ، فإننا نضيف بعض السمات الإضافية التي تصف أحداثه. إليك كيف يبدو نجمنا عند تثبيته في DOM:
<a-sphere class="a-sim-body" dynamic-body="" debris-listener="" event-set__enter="_event: mouseenter; color: green" event-set__leave="_event: mouseleave; color: yellow" position="0 0 0" radius="0.36" color="yellow" material="" geometry=""></a-sphere>
ثلاث سمات ، debris-listener
، event-set__enter
و event-set__leave
، قم بإعداد تفاعلاتنا وهي آخر لفة في تكاملنا.
تحديد أحداث وتفاعلات الإطار A
نستخدم حزمة NPM "aframe-event-set-component" في سمات الكيان لتغيير لون الشمس عندما "ينظر" العارض إليها.
هذه "النظرة" هي إسقاط من موضع المشاهد ودورانه ، ويوفر التفاعل التغذية الراجعة الضرورية بأن نظراته تفعل شيئًا ما.
يحتوي المجال النجمي لدينا الآن على حدثين مختزلين تم تمكينهما بواسطة المكون الإضافي ، event-set__enter
و event-set__leave
:
<a-sphere ... event-set__enter="_event: mouseenter; color: green" event-set__leave="_event: mouseleave; color: yellow" … ></a-sphere>
بعد ذلك ، نقوم بتزيين الكرة النجمية بمصغي debris-listener
الذي سنقوم بتنفيذه كمكون مخصص للإطار A.
<a-sphere ... debris-listener="" … ></a-sphere>
يتم تعريف مكونات الإطار A على المستوى العالمي:
// src/nBodyVisualizer.js // Component to add new bodies when the user stares at the sun. See HTML AFRAME.registerComponent('debris-listener', { init: function () { // Helper function function rando(scale) { return (Math.random()-.5) * scale } // Add 10 new bodies this.el.addEventListener('click', function (evt) { for (let x=0; x<10; x++) { // name, color, x, y, z, mass, vx, vy, vz window.sim.addBodyArgs("debris", "white", rando(10), rando(10), rando(10), 1, rando(.1), rando(.1), rando(.1)) } }) } })
يعمل مكون A-Frame هذا كمستمع "نقرة" يمكن تشغيله بواسطة مؤشر النظرة لإضافة 10 أجسام عشوائية جديدة إلى مشهدنا.
كي تختصر:
- نعلن مشهد WebVR بإطار A بتنسيق HTML القياسي.
- يمكننا إضافة / إزالة / تحديث كيانات A-Frame برمجيًا في المشهد من JavaScript.
- يمكننا إنشاء تفاعلات في JavaScript مع معالجات الأحداث من خلال المكونات الإضافية والمكونات A-Frame.
WebVR: Veni ، Vidi ، Vici
أتمنى أن تكون قد استفدت من هذا العرض التوضيحي التكنولوجي كما فعلت. حيث قمنا بتطبيق هذه الميزات (عمال الويب و WebAssembly) على WebVR ، يمكن أيضًا تطبيقها على حوسبة حافة المتصفح.
وصلت موجة تكنولوجية ضخمة - الواقع الافتراضي (VR). مهما شعرت في المرة الأولى التي تحمل فيها هاتفًا ذكيًا ، فإن تجربة الواقع الافتراضي لأول مرة توفر تجربة عاطفية 10 مرات في كل جانب من جوانب الحوسبة. لقد مرت 12 عامًا فقط على أول iPhone.
لقد كان الواقع الافتراضي موجودًا لفترة أطول ، ولكن التكنولوجيا اللازمة لجلب الواقع الافتراضي إلى المستخدمين العاديين وصلت عبر ثورة الأجهزة المحمولة و Oculus Quest على Facebook - وليس ثورة الكمبيوتر الشخصي.
يعد الإنترنت والمصدر المفتوح من بين أعظم عجائب البشرية في العالم. إلى جميع الأشخاص الذين ابتكروا الإنترنت المسطح - أرفع نخب شجاعتكم وإحساسكم بالمغامرة.
بيان! سنبني عوالم ، لأن لدينا القدرة على الخلق.