پاسخ کوتاه: با استفاده از یک برنامه واقعیت افزوده مبتنی بر مرورگر. برای پاسخ طولانی ، در زیر بخوانید.
ایده بازی با AR به عنوان یک آزمایش جالب تصادفی شروع شد. در شرکت ما تلاش می کنیم در حاشیه منحنی بمانیم و جدیدترین تکنیکی و فن آوری های جدید را به صورت نیمه منظم با یکدیگر به اشتراک بگذاریم. از آنجا که ما بیشتر با فناوری های وب سروکار داریم ، مفهوم AR در مرورگر واقعاً از بین رفت.
- با این حال ، از آنجا که AR بیشتر یک فناوری سرگرمی است ، یک کاربرد عملی از ابتدا برای ما واضح نبود. خوشبختانه ، دو اتفاق غیر مرتبط در همان زمان اتفاق افتاد: ما به تازگی یک محصول طلسم را ایجاد کرده ایم – Hubert،
- ما مجبور بودیم یک غرفه بازاریابی در devoxxPL 2018 انجام دهیم
ما تصمیم گرفتیم هوبرت را در طول این رویداد زنده کنیم. فرم برنامه AR برای بازی با مردم است. در ذهن ما کاربران باید بتوانند:
- Hubert را بر روی زمینه دیواری در تلفنهای خود
- ارائه دهند و از مدل ارائه شده
- عکس بگیرند (توییتر موضوع این مقاله نیست)
نتیجه نهایی در glitch.com موجود است ، مقیاس بندی شده و چرخش می یابد تا برای یک تجربه دسک تاپ مناسب باشد (همچنین می توانید نگاهی سریع به کد منبع بیندازید).


Rendering Hubert در زمان واقعی
ما از AR.js استفاده کردیم (نسخه از این تعهد) به عنوان بلوک اصلی برنامه AR ما – دسترسی به دوربین webRTC ، تشخیص نشانگر و ارائه صحنه سه بعدی را بسته بندی می کند. ما بیشتر آن را دوست داشتیم زیرا می توانید یک نسخه آزمایشی اساسی را در حدود 20 خط کد اجرا کنید (چقدر جالب است).
تحت کاپوت ، AR.js می تواند از سه پیاده سازی j.j یا یک فریم برای ارائه سه بعدی شما استفاده کند. صحنه ها.
- three.js کنترل ریز رندر سه بعدی را ارائه می دهد ، مبتنی بر جاوا اسکریپت است ، و احتمالاً در مورد ارائه صحنه های 2D و 3 بعدی در مرورگر [مرورگر
- یک فریم یک وب است. چارچوبی که به طور خاص برای ایجاد تجربیات VR و AR طراحی شده است ، دارای یک نشانه مانند html است که از سه.js بیشتر اعلامیه است ، اما برخی از کنترل را به نفع سهولت استفاده قربانی می کند
ما یک VR یا 3D نداشتیم. متخصص (به جز Mrówa ، که مدل 3D را آماده کرده است) و نحوی اعلانی a-frame مانند یک فریم برای ما آشناتر به نظر می رسید ، ما تصمیم گرفتیم فریم را برای انجام کار ارائه دهیم.
در اینجا می توانید مشاهده کنید. کد رده بندی هوبرت ، 20 ردیف روی نقطه (برخی گزینه ها را حذف کردیم و به خاطر سادگی ، یک فریم را تغییر دادیم ، به t مراجعه کنید او برای دیدن همه این موارد repo):
{{کد}}
<a-ակտիվ-مورد
id = 'bercik-obj'
sr = "http://www.voucherify.io/./models/smoothHubert/bercik2.obj"ociation19659012]>
<a-ակտիվ-مورد
id = 'bercik-mtl'
src = "http://www.voucherify.io/./models/smoothHubert/bercik2.mtl"
>
[196590012]
] <a-entbit
obj-model = "obj: # bercik-obj؛ mtl: # bercik-mtl "
scale =" 0.1 0.1 0.1 "
rotation =" – 90 0 0 "
>
{COD ENDCODE}
این به ما می دهد هوبرت به زیبایی در مرورگر وب در زمان واقعی ثبت شود.
یک عکس برای صدای جیر جیر
متأسفانه ، ما هیچ فید ویدیویی را نداریم که کل صحنه را ارائه می دهد. فیلم از دوربین شما و یک صحنه سه بعدی ارائه شده وجود دارد. ما به سرعت فهمیدیم که باید یک قاب را از هر دو منبع بگیریم. و آنها را برای یک عکس خوب از هوبرت در کنار هم قرار دهید.
گرفتن قاب از یک جریان ویدئویی webRTC بسیار ساده است. بهترین ماده در این زمینه می توانید در اینجا بیابید:
https://developer.mozilla.org/ en-US / docs / Web / API / WebRTC_API / Taking_still_photos اگر مرورگر شما API مناسبی دارد ، به 2 عنصر نیاز دارید:
- یک مرجع برای شما urce عنصر مقصد را برچسب گذاری کنید تا قاب خود را در
قرار دهید. سپس ، این فقط یک موضوع ساده برای ترسیم یک تصویر 2 بعدی از فیلم به بوم است. در مورد ما ، هر دو مورد کمی مشکل است.
ویدئویی که ما از آن استفاده می کنیم توسط AR.js تولید و جاسازی شده است و ما هیچ تصوری برای چگونگی دستیابی به آن نداشتیم ، بنابراین راه خود را در اطراف آن با یک حلقه هک کردیم. و یک انتخاب کننده DOM:
{{CODE}
اجازه دهید videoElement = null
const getVideoElement = () => new Promise (وضع => {
videoElement = document.querySelector ('video')
if (videoElement) {
حل (videoElement) ؛
بازگشت
}
setTimeout (() => حل (getVideoElement ()) ، 300)
})
getVideoElement (). سپس (ویدئو => {/ * انجام کار خود را انجام دهید * /})
{{ENDCODE}
چیز دیگری که ما نیاز به هک کردن در اطراف داشتیم مقیاس بندی مقداری است. AR.js خوراک فیلم خام را به کاربر ارائه نمی دهد ، آنها آن را برای پر کردن صفحه نمایش بدون از دست دادن نسبت ابعاد ، مقیاس می کنند. این بدان معنی است که ما باید مقیاس بندی مشابه را بر روی قاب خود اعمال کنیم ، در غیر این صورت ، تصویر ما بیشتر از آنچه در صفحه نمایش داده می شود ، از فیلم نشان می دهد و ما نمی خواهیم کاربران را در اینجا اشتباه بگیریم.
آنچه کاربر می بیند:

اگر یک فریم بدون مقیاس گذاری بگیریم و فقط سعی کنید از نقطه (0) کپی کنید ، حاشیه های تحمیل شده توسط AR.js را از دست می دهیم ، این یک تصویر کاملاً متفاوت است. از آنچه به کاربر ارائه می شود:

کافی است که بگوییم ما مقیاس بندی را دقیقاً معکوس کردیم و از جعبه محدوده آنچه کاربر می بیند فهمیدیم:
{{CODE}}
const topOffset = -parseFloat (video.style [‘margin-top’])
const leftOffset = -parseFloat (video.style [‘margin-left’])
const relativeTopOffset = topOffset / parseFloat (video.style.height)
constarsLeftOset video.style.width)
const {videoWidth، videoHeight video = video
const partPresentedToTheUser = {
x: video عرض eftOffset،
y: videoHeight * relativeTopOffset،
عرض: videoWidth * (1-2 * relativeLeftOffset)،
قد: videoHeight * (1-2 * relativeTopOffset)
}
{{END }}
برای دستیابی به این نتیجه نهایی (همان چیزی که به کاربر ارائه می شود ، لرزش دوربین را بدهید یا بگیرید):

اکنون ما فقط باید هوبرت را در تصویر بدست آوریم. مجدداً ، API برای آن بسیار واضح است: برای گرفتن عکس از یک صحنه فریم رندر شده ، باید بوم صحنه را بگیریم و قسمت مربوطه را بر روی بوم مقصد خود ، در بالای قاب ویدیویی که قبلاً گرفته شده بود کپی کنیم. [19659012] {{CODE}}
const scene = document.querySelector ('a-صحنه')
scene.compectors.screenshot.data.width = عرض
scene.component.screenshot.data.height = قد
const sceneCanvas = scene.compectors.screenshot.getCanvas ("چشم انداز")
const destinationContext = destinationCanvas.getContext ('2d')
destinationContext.drawImage (
] سنساس ، box.y، box.width، box.height، // Source rect
-box.x، 0، box.width، box.height // rect rect
)
{{ENDCODE}
بدست آوردن قسمت مربوطه ، مشکل پیچیده ای است که در پرونده ما وجود دارد. با تشکر از مقیاس AR.js ما به راحتی نمی توانیم از "منظره" عکس استفاده کنیم و از آن استفاده کنیم – بسته به جهت گیری ، بسیار گسترده یا خیلی کوتاه به نظر می رسد.
برای حالت افقی (عرض> ارتفاع) ، روش مقیاس گذاری ما برای فیلمبرداری بسیار خوب کار می کند.
برای حالت عمودی ، روی رایانه عالی کار می کند … با این حال ، وقتی وارد قلمرو دستگاه های تلفن همراه شوید ، مقیاس بندی می شکند و عکس صفحه به نظر خوب نمی رسد ، شما این هوبرت لاغر را بدست آورید:

به جای طلسم دوست داشتنی و حباب در تمام جلال او:

ما هنوز مطمئن نیستیم که چرا دقیقاً اینگونه است و ما اشتباه کردیم که آن را به طور کامل در دستگاه های واقعی موبایل آزمایش نکنیم ، فکر می کنم همان کارهایی را انجام می دهد که روی دستگاه توسعه کار می کند (بله ، ما می دانیم که چقدر بد است اما این واقعیت آن است). در طول کنفرانس واقعی ، ما موفق به فهم فرمول مقیاس بندی پرتره شده و تصحیحی را معرفی کردیم:
{{CODE}
if (portraitMode ()) {[19659012]ext.drawImage (
stageCanvas،
box.x، box.y، box.width، box.height، // Source rect
– (box.width / box.height * box.width * 0.55)، 0، 1.7 * box.width ، box.height // rect rect
]
Return
}
{{ENDCODE}
قشنگ نیست. این یکی از آنهایی است که "دیر شده است ، کار می کند ، فقط بگذارید" رفع شود. مقادیر ارائه شده در بالا نتیجه مطلوبی را به وجود آورد و ما آن را در همان زمان واگذار کردیم.
با آن ، تصویری از هوبرت در دنیای واقعی داریم! می توان آن را از عنصر بوم مقصد بازیابی کرد و در صفحه نمایش داد و یا برای ارسال صدای جیر جیر به سرور ارسال شد.
خلاصه
AR در مرورگر امکان پذیر است. حتی بیشتر ، در سخت افزار موبایل میان رده امکان پذیر است (از ژوئن 2018). استفاده از آن برای کار در هر تلفن و مرورگر هنوز یک عکس طولانی است ، بنابراین برای پایگاه های کاربر گسترده و متنوع روی آن حساب نکنید. با این حال ، اگر شما یک محیط تا حدودی کنترل شده دارید ، واقعیت افزوده از طریق تلفن می تواند مورد استفاده قرار گیرد تا تجربیات منحصر به فردی ایجاد شود که نیازی به سخت افزار یا ایستگاههای کاری خاصی نداشته باشد و این یک امتیاز بزرگ و بزرگ است. فقط مطمئن شوید که آن را قبل از زمان تست در دستگاههای واقعی؛).