WebXRããŒãºïŒäœçœ®ã»åããã©ããã³ã°ïŒã®å æ¬çã¬ã€ãããŠã§ãçšã®æ²¡å ¥åã»å¯Ÿè©±åVR/ARäœéšã®äœææ¹æ³ã解説ããŸãã
WebXRããŒãºïŒæ²¡å ¥åäœéšã®ããã®äœçœ®ãšåãã®ãã©ããã³ã°ãè§£æãã
WebXRã¯ããŠã§ããšã®å¯Ÿè©±æ¹æ³ã«é©åœãããããããã©ãŠã¶å ã§çŽæ¥ãæ²¡å ¥åã®ä»®æ³çŸå®ïŒVRïŒããã³æ¡åŒµçŸå®ïŒARïŒäœéšãå¯èœã«ããŠããŸãããããã®äœéšã®äžå¿ã«ããã®ãããŒãºã®æŠå¿µã§ããããã¯3D空éã«ãããããã€ã¹ãæã®äœçœ®ãšåããæããŸããããŒãºããŒã¿ãçè§£ãã广çã«æŽ»çšããããšã¯ãé åçã§ã€ã³ã¿ã©ã¯ãã£ããªWebXRã¢ããªã±ãŒã·ã§ã³ãäœæããããã«äžå¯æ¬ ã§ãã
WebXRããŒãºãšã¯ïŒ
WebXRã«ãããŠãããŒãºã¯ãªããžã§ã¯ãïŒãããã»ãããã³ã³ãããŒã©ãŒã远跡ãããæãªã©ïŒãšå®çŸ©ããã座æšç³»ãšã®ç©ºéçãªé¢ä¿ã衚ããŸãããã®æ å ±ã¯ããŠãŒã¶ãŒã®èŠç¹ããä»®æ³äžçãæ£ããã¬ã³ããªã³ã°ããä»®æ³ãªããžã§ã¯ããšèªç¶ã«å¯Ÿè©±ããããã«äžå¯æ¬ ã§ããWebXRããŒãºã¯ã次ã®2ã€ã®äž»èŠãªèŠçŽ ã§æ§æãããŠããŸãïŒ
- äœçœ®ïŒ 空éå ã®ãªããžã§ã¯ãã®å Žæã衚ã3Dãã¯ãã«ïŒéåžžã¯ã¡ãŒãã«åäœã§æž¬å®ïŒã
- åãïŒ ãªããžã§ã¯ãã®å転ã衚ãã¯ã©ãŒã¿ããªã³ãã¯ã©ãŒã¿ããªã³ã¯ãå転ã衚çŸããéã«ãªã€ã©ãŒè§ã§ããåé¡ãšãªããžã³ãã«ããã¯ãé¿ããããã«äœ¿çšãããŸãã
WebXR APIã®XRViewerPoseããã³XRInputSourceã€ã³ã¿ãŒãã§ãŒã¹ã¯ããã®ããŒãºæ
å ±ãžã®ã¢ã¯ã»ã¹ãæäŸããŸãã
座æšç³»ã®çè§£
ã³ãŒãã«å ¥ãåã«ãWebXRã§äœ¿çšããã座æšç³»ãçè§£ããããšãéèŠã§ããäž»èŠãªåº§æšç³»ã¯'local'åç §ç©ºéã§ãããããã¯ãŠãŒã¶ãŒã®ç©ççãªç°å¢ã«çµã³ã€ããŠããŸãããã®ç©ºéã®åç¹ïŒ0, 0, 0ïŒã¯ãéåžžXRã»ãã·ã§ã³ãéå§ããããšãã«å®çŸ©ãããŸãã
'viewer'ã'bounded-floor'ãªã©ã®ä»ã®åç §ç©ºéã¯ã远å ã®ã³ã³ããã¹ããæäŸããŸãã'viewer'空éã¯é ã®äœçœ®ã衚ãã'bounded-floor'ã¯åºé¢ã§è¿œè·¡ããããšãªã¢ã衚ããŸãã
ç°ãªã座æšç³»ãæ±ãéã«ã¯ããã空éããå¥ã®ç©ºéãžããŒãºã倿ããããšããããããŸããããã¯éåžžãè¡å倿ã䜿çšããŠè¡ãããŸãã
WebXRã§ã®ããŒãºããŒã¿ãžã®ã¢ã¯ã»ã¹
WebXRã»ãã·ã§ã³ãå®è¡ãããŠãããšä»®å®ããŠãWebXRã¢ããªã±ãŒã·ã§ã³ã§ããŒãºããŒã¿ã«ã¢ã¯ã»ã¹ããæ¹æ³ã®ã¹ããããã€ã¹ãããã¬ã€ãã以äžã«ç€ºããŸãïŒ
- XRFrameã®ååŸïŒ
XRFrameã¯ãç¹å®ã®æç¹ã§ã®WebXRç°å¢ã®ã¹ãããã·ã§ããã衚ããŸããããã¯ã¢ãã¡ãŒã·ã§ã³ã«ãŒãå ã§ååŸããŸãã - XRViewerPoseã®ååŸïŒ
XRFrameã®getViewerPose()ã¡ãœããã䜿çšããŠããã¥ãŒã¢ïŒãããã»ããïŒã®ããŒãºãååŸããŸãããã®ã¡ãœããã«ã¯åŒæ°ãšããŠXRReferenceSpaceãå¿ èŠã§ãããŒãºã®åºæºãšããã座æšç³»ãæå®ããŸãã - å
¥åãœãŒã¹ã®ããŒãºååŸïŒ
XRSessionã®getInputSources()ã¡ãœããã䜿çšããŠãå ¥åãœãŒã¹ïŒã³ã³ãããŒã©ãŒã远跡ãããæïŒã®ããŒãºã«ã¢ã¯ã»ã¹ããŸããæ¬¡ã«ãåXRInputSourceã®getPose()ã¡ãœããã䜿çšããããã§ãXRReferenceSpaceãæäŸããŸãã - äœçœ®ãšåãã®æœåºïŒ
XRViewerPoseãŸãã¯XRInputSourceã®ããŒãºãããäœçœ®ãšåããæœåºããŸããäœçœ®ã¯é·ã3ã®Float32Arrayã§ãããåãã¯é·ã4ã®Float32ArrayïŒã¯ã©ãŒã¿ããªã³ïŒã§ãã
ã³ãŒãäŸïŒThree.jsã䜿çšïŒïŒ
ãã®äŸã§ã¯ããã¥ãŒã¢ã®ããŒãºã«ã¢ã¯ã»ã¹ãããããThree.jsã®ã«ã¡ã©ã«é©çšããæ¹æ³ã瀺ããŸãïŒ
async function onXRFrame(time, frame) {
const session = frame.session;
const pose = frame.getViewerPose(xrRefSpace);
if (pose) {
const x = pose.transform.position.x;
const y = pose.transform.position.y;
const z = pose.transform.position.z;
const quaternionX = pose.transform.orientation.x;
const quaternionY = pose.transform.orientation.y;
const quaternionZ = pose.transform.orientation.z;
const quaternionW = pose.transform.orientation.w;
camera.position.set(x, y, z);
camera.quaternion.set(quaternionX, quaternionY, quaternionZ, quaternionW);
}
renderer.render(scene, camera);
session.requestAnimationFrame(onXRFrame);
}
説æïŒ
onXRFrame颿°ã¯ãWebXRäœéšã®ã¡ã€ã³ã¢ãã¡ãŒã·ã§ã³ã«ãŒãã§ããframe.getViewerPose(xrRefSpace)ã¯ãæå®ãããxrRefSpaceãåºæºãšãããã¥ãŒã¢ã®ããŒãºãååŸããŸãã- äœçœ®ãšåãã®ã³ã³ããŒãã³ãã¯ã
pose.transformãªããžã§ã¯ãããæœåºãããŸãã - ãã®åŸãäœçœ®ãšåããThree.jsã®ã«ã¡ã©ã«é©çšãããŸãã
WebXRããŒãºã®å¿çš
ããŒãºããŒã¿ãçè§£ãæŽ»çšããããšã§ãWebXRã¢ããªã±ãŒã·ã§ã³ã®å¯èœæ§ã¯å€§ããåºãããŸãïŒ
- ä»®æ³çŸå®ïŒVRïŒã²ãŒã ïŒ æ£ç¢ºãªããããã©ããã³ã°ã«ããããã¬ã€ã€ãŒã¯åšããèŠæž¡ããŠã²ãŒã ã®äžçã«æ²¡å ¥ã§ããŸããã³ã³ãããŒã©ãŒãã©ããã³ã°ã¯ãä»®æ³ãªããžã§ã¯ããšã®å¯Ÿè©±ãå¯èœã«ããŸããBeat SaberãSuperhot VRã®ãããªã²ãŒã ãããã€ãã£ãããã©ãŒãã³ã¹ã«å¹æµããå¿ å®åºŠã§ãã©ãŠã¶å ã§ãã¬ã€å¯èœã«ãªãããšãèããŠã¿ãŠãã ããã
- æ¡åŒµçŸå®ïŒARïŒãªãŒããŒã¬ã€ïŒ ããŒãºããŒã¿ã¯ãä»®æ³ãªããžã§ã¯ããçŸå®äžçã«åºå®ããããã«äžå¯æ¬ ã§ããARã䜿ã£ãŠãªãã³ã°ã«ãŒã ã«å®¶å ·ã®ã¢ãã«ãéããŠè¡šç€ºããããããŒãã®ãŠã©ãŒãã³ã°ãã¢ãŒäžã«ã©ã³ãããŒã¯ã«é¢ãããªã¢ã«ã¿ã€ã æ å ±ãæäŸãããããããšãæ³åããŠã¿ãŠãã ããã
- 3Dã¢ããªã³ã°ãšãã¶ã€ã³ïŒ ãŠãŒã¶ãŒã¯ããã³ããã©ããã³ã°ãã³ã³ãããŒã©ãŒã䜿çšããŠ3Dã¢ãã«ãæäœã§ããŸãã建ç¯å®¶ãå ±æã®ä»®æ³ç©ºéã§å»ºç©ã®èšèšã«å ±åã§åãçµãããã®ãã¹ãŠãWebXRã䜿çšããŠè¡ãããšãèããŠã¿ãŠãã ããã
- ãã¬ãŒãã³ã°ãšã·ãã¥ã¬ãŒã·ã§ã³ïŒ ãã€ãããã®èšç·Žãå»çåŠçœ®ã®ãããªã·ããªãªã®ããã«ãããŒãºããŒã¿ã䜿çšããŠãªã¢ã«ãªã·ãã¥ã¬ãŒã·ã§ã³ãäœæã§ããŸããäŸãšããŠã¯ãè€éãªæ©æ¢°ã®æäœãå€ç§æè¡ã®ã·ãã¥ã¬ãŒã·ã§ã³ãæãããããããã¯ãã©ãŠã¶ããããã°ã©ãããã§ãã¢ã¯ã»ã¹å¯èœã§ãã
- ãªã¢ãŒãã³ã©ãã¬ãŒã·ã§ã³ïŒ å ±æãããæ¡åŒµãŸãã¯ä»®æ³ç©ºéã§ããªã¢ãŒãããŒã ãä»®æ³ãããžã§ã¯ãã§å ±åäœæ¥ã§ããããã«ããŸãã
課é¡ãšèæ ®äºé
WebXRããŒãºã¯å€§ããªå¯èœæ§ãç§ããŠããŸãããèæ ®ãã¹ãããã€ãã®èª²é¡ããããŸãïŒ
- ããã©ãŒãã³ã¹ïŒ ããŒãºããŒã¿ã®ã¢ã¯ã»ã¹ãšåŠçã¯ãç¹ã«è€æ°ã®è¿œè·¡ãªããžã§ã¯ããããå Žåãèšç®è² è·ãé«ããªãå¯èœæ§ããããŸããã³ãŒããæé©åããå¹ççãªã¬ã³ããªã³ã°æè¡ã䜿çšããããšãéèŠã§ãã
- 粟床ãšé å»¶ïŒ ããŒãºãã©ããã³ã°ã®ç²ŸåºŠãšé å»¶ã¯ãããŒããŠã§ã¢ãç°å¢ã«ãã£ãŠç°ãªãå ŽåããããŸãããã€ãšã³ãã®VR/ARãããã»ããã¯éåžžãã¢ãã€ã«ããã€ã¹ãããé«ç²ŸåºŠã§äœé å»¶ã®ãã©ããã³ã°ãæäŸããŸãã
- ãŠãŒã¶ãŒã®å¿«é©æ§ïŒ äžæ£ç¢ºãŸãã¯é«é å»¶ã®ãã©ããã³ã°ã¯ãä¹ãç©é ããåŒãèµ·ããå¯èœæ§ããããŸããã¹ã ãŒãºã§å¿çæ§ã®é«ãäœéšã確ä¿ããããšãæãéèŠã§ãã
- ã¢ã¯ã»ã·ããªãã£ïŒ é害ãæã€ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ã§ããããã«ãæ éãªèšèšäžã®é æ ®ãå¿ èŠã§ãã代æ¿ã®å ¥åæ¹æ³ãä¹ãç©é ãã軜æžããæ¹æ³ãæ€èšããŠãã ããã
- ãã©ã€ãã·ãŒïŒ ããŒãºããŒã¿ãåéã»äœ¿çšããéã¯ããŠãŒã¶ãŒã®ãã©ã€ãã·ãŒã«æ³šæãæã£ãŠãã ãããããŒã¿ãã©ã®ããã«äœ¿çšããããã«ã€ããŠæç¢ºãªèª¬æãæäŸããã€ã³ãã©ãŒã ãã³ã³ã»ã³ããåŸãŠãã ããã
WebXRããŒãºã䜿çšããããã®ãã¹ããã©ã¯ãã£ã¹
é«å質ãªWebXRäœéšãäœæããã«ã¯ã以äžã®ãã¹ããã©ã¯ãã£ã¹ã«åŸã£ãŠãã ããïŒ
- ããã©ãŒãã³ã¹ã®æé©åïŒ ã¢ãã¡ãŒã·ã§ã³ã«ãŒãã§è¡ãããåŠçéãæå°éã«æããŸãããªããžã§ã¯ãããŒãªã³ã°ããã©ã¹ã¿ã ã«ãªã³ã°ãªã©ã®æè¡ã䜿çšããŠãã¬ã³ããªã³ã°ããã©ãŒãã³ã¹ãåäžãããŸãã
- ãã©ããã³ã°åªå€±ãžã®åªé ãªå¯Ÿå¿ïŒ ãã©ããã³ã°ã倱ãããç¶æ³ïŒäŸïŒãŠãŒã¶ãŒã远跡ãšãªã¢å€ã«ç§»åããïŒã«å¯Ÿå¿ããã¡ã«ããºã ãå®è£ ããŸãããã©ããã³ã°ãä¿¡é Œã§ããªãå Žåã«èŠèŠçãªåå³ãæäŸããŸãã
- ã¹ã ãŒãžã³ã°ãšãã£ã«ã¿ãªã³ã°ã®äœ¿çšïŒ ãžãã¿ãŒãæžãããããŒãºããŒã¿ã®å®å®æ§ãåäžãããããã«ãã¹ã ãŒãžã³ã°ããã£ã«ã¿ãªã³ã°æè¡ãé©çšããŸããããã¯ãããå¿«é©ãªãŠãŒã¶ãŒäœéšãçã¿åºãã®ã«åœ¹ç«ã¡ãŸãã
- ç°ãªãå ¥åæ¹æ³ãèæ ®ããïŒ ã³ã³ãããŒã©ãŒã远跡ãããæãé³å£°ã³ãã³ããªã©ãããŸããŸãªå ¥åæ¹æ³ããµããŒãããããã«ã¢ããªã±ãŒã·ã§ã³ãèšèšããŸãã
- ç°ãªãããã€ã¹ã§ãã¹ãããïŒ äºææ§ãšããã©ãŒãã³ã¹ã確ä¿ããããã«ãããŸããŸãªVR/ARããã€ã¹ã§ã¢ããªã±ãŒã·ã§ã³ããã¹ãããŸãã
- ãŠãŒã¶ãŒã®å¿«é©æ§ãåªå ããïŒ ãŠãŒã¶ãŒã®å¿«é©æ§ã念é ã«çœ®ããŠã¢ããªã±ãŒã·ã§ã³ãèšèšããŸããä¹ãç©é ããåŒãèµ·ããå¯èœæ§ã®ããæ¥ãªåããäžå¿«ãªé·ç§»ãé¿ããŸãã
- ãã©ãŒã«ããã¯ã®å®è£ ïŒ WebXRããµããŒãããŠããªããã©ãŠã¶ãã远跡æ©èœãéãããŠããããã€ã¹ã®ããã«ãåªé ãªãã©ãŒã«ããã¯ãæäŸããŸãã
ç°ãªããã¬ãŒã ã¯ãŒã¯ã§ã®WebXRããŒãº
å€ãã®JavaScriptãã¬ãŒã ã¯ãŒã¯ãWebXRéçºãç°¡çŽ åããŠããŸãã以äžã¯ãã®äžéšã§ãïŒ
- Three.jsïŒ åºç¯ãªWebXRãµããŒããåãã人æ°ã®3Dã°ã©ãã£ãã¯ã¹ã©ã€ãã©ãªãThree.jsã¯ãã¬ã³ããªã³ã°ãã·ãŒã³ç®¡çãå ¥åãã³ããªã³ã°ã®ããã®æœè±¡åãæäŸããŸãã
- Babylon.jsïŒ å ç¢ãªWebXRæ©èœãåããããäžã€ã®åŒ·åãª3Dãšã³ãžã³ãBabylon.jsã¯ãé«åºŠãªã¬ã³ããªã³ã°æ©èœãšãæ²¡å ¥åäœéšãäœæããããã®å æ¬çãªããŒã«ã»ãããæäŸããŸãã
- A-FrameïŒ Three.jsäžã«æ§ç¯ããã宣èšçãªãã¬ãŒã ã¯ãŒã¯ã§ãHTMLã©ã€ã¯ãªæ§æã䜿çšããŠWebXRäœéšãç°¡åã«äœæã§ããŸããA-Frameã¯åå¿è ãã©ããããããã¿ã€ãã³ã°ã«æé©ã§ãã
- React Three FiberïŒ Three.jsçšã®Reactã¬ã³ãã©ãŒã§ãReactã³ã³ããŒãã³ãã䜿çšããŠWebXRäœéšãæ§ç¯ã§ããŸãã
åãã¬ãŒã ã¯ãŒã¯ã¯ãWebXRããŒãºããŒã¿ã«ã¢ã¯ã»ã¹ãæäœããããã®ç¬èªã®æ¹æ³ãæäŸããŠããŸããå ·äœçãªæé ãäŸã«ã€ããŠã¯ãåãã¬ãŒã ã¯ãŒã¯ã®ããã¥ã¡ã³ããåç §ããŠãã ããã
WebXRããŒãºã®æªæ¥
WebXRããŒãºæè¡ã¯çµ¶ããé²åããŠããŸããå°æ¥ã®é²æ©ã«ã¯ä»¥äžã®ãããªãã®ãå«ãŸããå¯èœæ§ããããŸãïŒ
- ãã©ããã³ã°ç²ŸåºŠã®åäžïŒ æ°ããã»ã³ãµãŒãšè¿œè·¡ã¢ã«ãŽãªãºã ã«ãããããæ£ç¢ºã§ä¿¡é Œæ§ã®é«ãããŒãºãã©ããã³ã°ãå®çŸããŸãã
- AIãšã®ããæ·±ãçµ±åïŒ AIãæŽ»çšããããŒãºæšå®ã«ãããä»®æ³ç°å¢ãšã®ããæŽç·Žããã察話ãå¯èœã«ãªãå¯èœæ§ããããŸãã
- æšæºåããããã³ããã©ããã³ã°ïŒ ãã³ããã©ããã³ã°æšæºã®æ¹åã«ãããç°ãªãããã€ã¹éã§ããäžè²«æ§ã®ããçŽæçãªæã®å¯Ÿè©±ãå®çŸããŸãã
- äžççè§£ã®åŒ·åïŒ ããŒãºããŒã¿ãšç°å¢çè§£æè¡ïŒäŸïŒSLAMïŒãçµã¿åãããããšã§ãããçŸå®çã§æ²¡å ¥æã®ããæ¡åŒµçŸå®äœéšãå¯èœã«ãªããŸãã
- ã¯ãã¹ãã©ãããã©ãŒã äºææ§ïŒ WebXRããã³é¢é£æè¡ãå¯èœãªéãã¯ãã¹ãã©ãããã©ãŒã ã§ããããšãä¿èšŒããããã®ç¶ç¶çãªéçºã«ãããã°ããŒãã«ãªã¢ã¯ã»ã·ããªãã£ãå®çŸããŸãã
çµè«
WebXRããŒãºã¯ããŠã§ãäžã§é åçã§ã€ã³ã¿ã©ã¯ãã£ããªä»®æ³çŸå®ããã³æ¡åŒµçŸå®äœéšãäœæããããã®åºæ¬çãªæ§æèŠçŽ ã§ããäœçœ®ãšåãã®ãã©ããã³ã°ã®ååãçè§£ãããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãéçºè ã¯WebXRã®å¯èœæ§ãæå€§éã«åŒãåºããå¯èœãªããšã®éçãæŒãåºããæ²¡å ¥åã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸããæè¡ã鲿©ããæ¡çšãåºããã«ã€ããŠãWebXRã®å¯èœæ§ã¯ç¡é倧ãšãªãããŠã§ããäžçäžã®ãŠãŒã¶ãŒã«ãšã£ãŠçã«æ²¡å ¥åã§ã€ã³ã¿ã©ã¯ãã£ããªã¡ãã£ã¢ãšãªãæªæ¥ãçŽæããŸãã