Slide 1

Slide 1 text

Getting Started with WebVR Contents Creation for Oculus Quest

Slide 2

Slide 2 text

Please Download Sample Data http://arfukuoka.lolipop.jp/quest/Sample.zip

Slide 3

Slide 3 text

What’s A-Frame  JS library to create VR apps which work on web browser.  3D objects can be placed by writing HTML tags.  VR apps work on web browser. (ex. Chrome, Firefox)  Also available on WinMR, HTC Vive and Oculus Quest.

Slide 4

Slide 4 text

Experience Access to the official site of A-Frame (https://aframe.io/)

Slide 5

Slide 5 text

Experience Sample demos are shown on the left column. サンプル

Slide 6

Slide 6 text

Experience Let’s see the most primitive sample Hello WebVR. Hello WebVR

Slide 7

Slide 7 text

Experience See around VR environment by mouse/key controll. Click inside the screen Rotation:drag & move a mouse Left/Right:[←][→] key Forward/Back:[↑][↓] key

Slide 8

Slide 8 text

Another Example 360°Images also work with A-Frame easily. 360°Image RICOH Theta

Slide 9

Slide 9 text

Of course you can play on Oculus Quest

Slide 10

Slide 10 text

The Goal of This Tutorial https://youtu.be/J-AQpvOawJ0

Slide 11

Slide 11 text

Let’s Experience on Oculus Quest! https://quest-demo.glitch.me

Slide 12

Slide 12 text

You can See Also... Primitive sample of getting input from controllers https://github.com/TakashiYoshinaga/Oculus- Quest-Input-Sample Source code of the goal of today’s tutorial. https://github.com/TakashiYoshinaga/Oculus- Quest-Interaction-Sample

Slide 13

Slide 13 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 14

Slide 14 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 15

Slide 15 text

Please log in your account of Glitch https://glitch.com/

Slide 16

Slide 16 text

Getting Sample Code Click the link shown as GET STARTED GET STARTED

Slide 17

Slide 17 text

Remixing the Sample Code Description of Hello WebVR Hello WebVR

Slide 18

Slide 18 text

Remixing the Sample Code Click remix the starter example on Glitch Click

Slide 19

Slide 19 text

Remixing the Sample Code Click “Remix your own” button shown on the right bottom of preview image. Click

Slide 20

Slide 20 text

Click index.html to view the sample code. Click

Slide 21

Slide 21 text

Explanation of the Sample Code Hello, WebVR! - A-Frame Description of 3D contents are written here.  A-Frame library is imported between  Description of 3D objects are written between

Slide 22

Slide 22 text

Explanation of the Sample Code  Primitive objects are defined as a-xxx https://aframe.io/docs/0.9.0/primitives /a-box.html (ex. Detail of a-box)

Slide 23

Slide 23 text

Run ①Show ②Next to The Code

Slide 24

Slide 24 text

Run

Slide 25

Slide 25 text

How to Modify Objects? You can change parameters of components. For example...  position: x y z are used to modify the position of a CG. (0 1.25 -5)

Slide 26

Slide 26 text

How to Modify Objects? Examples of components  position:x y z are used to modify the position.  rotation:x y z means rotation of each axis.  color:color code are used to define the color.  There are some parameters for each primitive object. X Z Y (0 1.25 -5) 【Others】 radius width height depth src (image file) 原点

Slide 27

Slide 27 text

Let’s Try to Edit Components #AAAAAA position="-1 0.5 -2" rotation="0 0 0" position="0 1.25 -4" radius="0.7" position="1 0.75 -2 height="0.7" position="0 0 0" width="10" height="10"

Slide 28

Slide 28 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 29

Slide 29 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 30

Slide 30 text

Applying Texture Image

Slide 31

Slide 31 text

Applying Texture Image ①assets ②Add Asset → Upload

Slide 32

Slide 32 text

Applying Texture Image ①back.png ②Open

Slide 33

Slide 33 text

Applying Texture Image Click

Slide 34

Slide 34 text

Applying Texture Image ①Click ②Click out of the dialog

Slide 35

Slide 35 text

Applying Texture Image index.html

Slide 36

Slide 36 text

Applying Texture Image  Replace the a-sphere’s material to src instead color. To be continued to the next page... Delete color

Slide 37

Slide 37 text

Applying Texture Image Paste the URL Add src  Change the a-sphere’s material to src instead color.  Paste the URL of the texture image on the right side of src.

Slide 38

Slide 38 text

Duplication of Textured Plane Copy & Paste

Slide 39

Slide 39 text

Duplication of Textured Plane Make 4 walls with the same procedure.

Slide 40

Slide 40 text

Modify URL of Your VR Content Click Text Modify a name

Slide 41

Slide 41 text

Modify URL of Your VR Content https://XXXX-XXXX.glitch.me

Slide 42

Slide 42 text

Test on Oculus Quest You will be immersed in the VR space you created.

Slide 43

Slide 43 text

Adding Controller Entity enables us to define original entity instead pre-defined primitive entities.

Slide 44

Slide 44 text

Before Test on Oculus Quest... Reload!

Slide 45

Slide 45 text

Test on Oculus Quest Oculus Touch’s controller, not Quest’s, will appear.

Slide 46

Slide 46 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 47

Slide 47 text

Today’s Tutorial Step1: Learning basic usage of A-Frame Step2: Making the simple VR environment. Step3: Writing script to achieve interaction.

Slide 48

Slide 48 text

Definition of Input Behavior Add input-listen component to describe behavior when input of controller is received. From next page, source code of input-listen is explained.

Slide 49

Slide 49 text

Definition of Input Behavior AFRAME.registerComponent('input-listen', { init:function () { //Initialization } , tick: function () { //Update } }); 1.txt

Slide 50

Slide 50 text

Definition of Input Behavior init:function () { //Initialization //Called when x button begin to be pressed (for Left Hand) this.el.addEventListener('xbuttondown', function (e) { /*Do something*/ }); //Called when x button is released (for Left Hand) this.el.addEventListener('xbuttonup', function (e) { }); //Called when grip button begin to be pressed (for Both Hand) this.el.addEventListener('gripdown', function (e) { }); //Called when grip button released. (for Both Hand) this.el.addEventListener('gripup', function (e) { }); } , 2.txt

Slide 51

Slide 51 text

Visualization of Input Info with Text 3.txt

Slide 52

Slide 52 text

Visualization of Input Info with Text const txt = document.getElementById("txt"); //Called when x button begin to be pressed (for Left Hand) this.el.addEventListener('xbuttondown', function (e) { txt.setAttribute("value", "x pressed"); }); //Called when x button is released (for Left Hand) this.el.addEventListener('xbuttonup', function (e) { txt.setAttribute("value", "x released"); }); //Called when grip button begin to be pressed (for Both Hand) this.el.addEventListener('gripdown', function (e) { txt.setAttribute("value", "grip pressed"); }); //Called when grip button released. (for Both Hand) this.el.addEventListener('gripup', function (e) { txt.setAttribute("value", "grip released"); }); 4.txt

Slide 53

Slide 53 text

Before the Test on Oculus Quest Reload!!

Slide 54

Slide 54 text

Test on Oculus Quest Each action of grip or a-button will appear.

Slide 55

Slide 55 text

Reference https://aframe.io/docs/0.9.0/components/oculus-touch-controls.html ①Oculus-touch-controls ②Events Info of events are explained in the official reference in detail.

Slide 56

Slide 56 text

Duplication of the Project Remix Project I recommend to preserve this code as the primitive project. Click the content name

Slide 57

Slide 57 text

Modification of URL of the New Content Click the content name Replace the name as you like

Slide 58

Slide 58 text

Delete Lines of Visualization of Input const txt = document.getElementById("txt"); //Called when x button begin to be pressed (for Left Hand) this.el.addEventListener('xbuttondown', function (e) { txt.setAttribute("value", "x pressed"); }); //Called when x button is released (for Left Hand) this.el.addEventListener('xbuttonup', function (e) { txt.setAttribute("value", "x released"); }); //Called when grip button begin to be pressed (for Both Hand) this.el.addEventListener('gripdown', function (e) { txt.setAttribute("value", "grip pressed"); }); //Called when grip button released. (for Both Hand) this.el.addEventListener('gripup', function (e) { txt.setAttribute("value", "grip released"); });

Slide 59

Slide 59 text

Enabling Teleportation to the Content Hello, WebVR! • A-Frame 5.txt

Slide 60

Slide 60 text

Enabling Teleportation to the Content Append camera and controller as children of to get them to be allowed jumping together to th destination.

Slide 61

Slide 61 text

Enabling Teleportation to the Content Next, teleportation function will be added to left-hand controller.

Slide 62

Slide 62 text

Enabling Teleportation to the Content Add teleport-controls component to left-hand controller. 6.txt

Slide 63

Slide 63 text

Supplementation 1 It means to allow jumpping #CameraRig and its children from #head

Slide 64

Slide 64 text

Supplementation 2 teleportstart is called to start pointing destination. teleportend is called to jump to pointed position.

Slide 65

Slide 65 text

Enabling Teleportation to the Content init:function () { const txt = document.getElementById("txt"); ////Called when x button begin to be pressed this.el.addEventListener('xbuttondown', function (e) { //Start to point destination this.emit('teleportstart'); }); // //Called when x button is released this.el.addEventListener('xbuttonup', function (e) { //Jump to pointed position. this.emit('teleportend'); }); /*Following code is omitted in this slide.*/ }

Slide 66

Slide 66 text

Check the URL Before Starting Test Remember the project name https://XXX-XXX.glitch.me

Slide 67

Slide 67 text

Test on Oculus Quest Teleportation will be available.

Slide 68

Slide 68 text

Text Step: Manipulation raycaster Checking intersection intersect Gripdown Manipulate!

Slide 69

Slide 69 text

Adding Raycaster Component Find controllers

Slide 70

Slide 70 text

Adding Raycaster Component Raycaster will interact with collidable entity.(see next page) It just works when distance between controller & object is in 1.2m

Slide 71

Slide 71 text

Adding Raycaster Component Raycaster will interact with collidable entity.(see next page) It just works when distance between controller & object is in 1.2m

Slide 72

Slide 72 text

Setting Entities as Collidable Object Checking intersection with raycaster is ON Floor and walls are not checked intersection

Slide 73

Slide 73 text

Condition of Manipulation (1/2) init:function () { const txt = document.getElementById("txt"); this.el.grip=false; this.el.addEventListener('xbuttondown', function (e) { this.emit('teleportstart'); }); this.el.addEventListener('xbuttonup', function (e) { this.emit('teleportend'); }); this.el.addEventListener('gripdown', function (e) { this.grip=true; }); this.el.addEventListener('gripup', function (e) { this.grip=false; }); } , Holding grip is pressed or not.

Slide 74

Slide 74 text

Condition of Manipulation (2/2) init:function () { /*Source code is omitted in this slide.*/ this.el.addEventListener('gripup', function (e) { this.grip=false; }); //called when raycaster intersected with something this.el.addEventListener('raycaster-intersection', function (e) { //Holding 1st object of detected entity as selected object. this.selectedObj = e.detail.els[0]; }); //called when raycaster intersection is cleared. this.el.addEventListener('raycaster-intersection-cleared', function (e) { //Reset selected object. this.selectedObj = null; }); } , Checking raycaster is intersected with CG or not 7.txt

Slide 75

Slide 75 text

Manipulation init:function () { /* Omitted in this slide */ this.el.addEventListener('raycaster-intersection', function (e) { this.selectedObj = event.detail.els[0]; }); this.el.addEventListener('raycaster-intersection-cleared', function (e) { this.selectedObj = null; }); }, //Update tick: function () { if (!this.el.selectedObj) { return; } if (!this.el.grip) { return; } //Make selected object to follow the tip of raycaster when //raycaster intersected object and grip is pressed. }

Slide 76

Slide 76 text

Manipulation //update tick: function () { if (!this.el.selectedObj) { return; } if (this.el.grip == false) { return; } //Getting direction of raycaster attached on this controller. var ray = this.el.getAttribute("raycaster").direction; //Calculate 1.2m forward position relative to controller var p = new THREE.Vector3(ray.x, ray.y, ray.z); p.normalize(); p.multiplyScalar(1.2); //Convert local position to world position. this.el.object3D.localToWorld(p); //put the selected object on the tip of the raycaster this.el.selectedObj.object3D.position.set(p.x, p.y, p.z); } 8.txt

Slide 77

Slide 77 text

Test on Oculus Quest 3D objects will become manipulatable

Slide 78

Slide 78 text

Reference of raycaster https://github.com/aframevr/aframe/blob/master/docs/co mponents/raycaster.md You can read more detail of raycaster below.

Slide 79

Slide 79 text

Next Step:Shooting Bullet(ball) Press Trigger

Slide 80

Slide 80 text

Import Library of Physics Hello, WebVR! • A-Frame All script is omitted in this slide. /*Omitted*/ 9.txt physics="gravity: 0; restitution: 0.9;"

Slide 81

Slide 81 text

Adding Event of Trigger Down init:function () { /*Source code is omitted in this slide.*/ //Raycaster intersected with something. this.el.addEventListener('raycaster-intersection', function (e) { this.selectedObj = event.detail.els[0]; }); //Raycaster intersection is finished. this.el.addEventListener('raycaster-intersection-cleared', function (e) { this.selectedObj = null; }); //Calles when the trigger button begin to be pressed. this.el.addEventListener('triggerdown', function (e) { }); }

Slide 82

Slide 82 text

Instantiation of Ball this.el.addEventListener('triggerdown', function (e) { //Getting the current position of the controller. var point = this.object3D.getWorldPosition(); //Instantiation of ball entity. var ball = document.createElement('a-sphere'); ball.setAttribute('class', 'ball'); ball.setAttribute('scale', '0.2 0.2 0.2'); ball.setAttribute('position', point); //Adding dynamic-body and its property to enable physics. ball.setAttribute('dynamic-body', 'shape: sphere; sphereRadius:0.2; '); //Generate ball entity in a-scene var scene = document.querySelector('a-scene'); scene.appendChild(ball); }); 10.txt

Slide 83

Slide 83 text

Test on Oculus Quest Ball will appear on the hand position but not be shot yet.

Slide 84

Slide 84 text

Calculation of Shooting Vector this.el.addEventListener('triggerdown', function (e) { /*Source code is omitted in this slide.*/ //Generating ball entity in a-scene var scene = document.querySelector('a-scene'); scene.appendChild(ball); //Getting direction of raycaster component of the controller. var dir = this.getAttribute("raycaster").direction; //Setting direction and magnitude of shoot vector. var force = new THREE.Vector3(); force.set(dir.x, dir.y, dir.z); force.multiplyScalar(2000); //Declare and set force vecter. ball.force = this.object3D.localToWorld(force); }); 11.txt

Slide 85

Slide 85 text

Shooting Bullet this.el.addEventListener('triggerdown', function (e) { /*Source code is omitted in this slide.*/ ball.force = this.object3D.localToWorld(force); //Shoot after finishing to load physics on ball ball.addEventListener('body-loaded', function (e) { //Getting position of ball var p = this.object3D.position; //Add force var f = this.force; this.body.applyForce( new CANNON.Vec3(f.x, f.y, f.z), new CANNON.Vec3(p.x, p.y, p.z) ); }); }); 12.txt

Slide 86

Slide 86 text

Test on Oculus Quest Balls are shot but through the wall.

Slide 87

Slide 87 text

Enabling Collision Detection --omitted-- box, sphere, cylinder, planeにstatic-bodyを追加

Slide 88

Slide 88 text

Remove Balls by Pressing A-Button init:function () { /*Source code is omitted in this slide.*/ //called when trigger button is started to be pressed this.el.addEventListener('triggerdown', function (e) { /*Source code is omitted in this slide.*/ }); //Called when pressing a-button is began. this.el.addEventListener('abuttondown', function (e) { //Obtain all entity of being ball class var els = document.querySelectorAll('.ball'); //Remove each balls from a-scene. for (var i = 0; i < els.length; i++) { els[i].parentNode.removeChild(els[i]); } }); } , 13.txt

Slide 89

Slide 89 text

Completed!

Slide 90

Slide 90 text

No content