├── .gitattributes ├── 9781484263174.jpg ├── Contributing.md ├── LICENSE.txt ├── README.md ├── ch10_ex9 ├── assets │ ├── attribution.txt │ ├── city │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ │ ├── World_ap.11_baseColor.jpeg │ │ │ ├── World_ap.15_baseColor.jpeg │ │ │ ├── World_ap.16_baseColor.jpeg │ │ │ ├── World_ap.17_baseColor.jpeg │ │ │ ├── World_ap.19_baseColor.jpeg │ │ │ ├── World_ap.8_baseColor.jpeg │ │ │ ├── World_ap.9_baseColor.jpeg │ │ │ └── World_ap_baseColor.jpeg │ └── dragon │ │ ├── scene.bin │ │ ├── scene.gltf │ │ └── textures │ │ ├── material_0_diffuse.png │ │ ├── material_0_normal.png │ │ ├── material_0_occlusion.png │ │ └── material_0_specularGlossiness.png └── index.html ├── ch2 └── index.html ├── ch3 ├── ex2_part1 │ ├── index.html │ └── index.js.js ├── ex2_part2 │ ├── index.html │ └── lesson2-2.js ├── ex2_part3 │ ├── index.html │ └── lesson2-3.js └── webGLtemplate.js ├── ch4 ├── index.html ├── lesson3-1.js └── lesson3-2.js ├── ch5_ex4 ├── index.html ├── index_ex4_final.js ├── modules │ └── three.module.js └── textures │ ├── pebbies_gray.png │ ├── pebbles.jpg │ ├── pebbles_height.png │ ├── pebbles_normal.png │ └── sphere_normal.png ├── ch6_ex5 ├── VRButton.js ├── index.html ├── index_xr.js └── textures │ ├── pebbles.png │ ├── pebbles_normal.png │ └── sphere_normal.png ├── ch7_ex6 ├── Part1_Floating-Cube │ ├── index.html │ └── index.js └── Part2_Hit-Test │ ├── hit_test.js │ └── index.html ├── ch8_Ex7_Parts_1_2 ├── index.html └── textures │ ├── brick_mat.jpg │ ├── grass-nm.jpg │ └── grass.jpg ├── ch8_Ex7_Parts_3_4 ├── index.html └── textures │ ├── brick_mat.jpg │ ├── grass-nm.jpg │ └── grass.jpg ├── ch9_ex8 ├── assets │ ├── oculus-touch-controller-left.mtl │ ├── oculus-touch-controller-left.obj │ ├── oculus-touch-controller-right.mtl │ └── oculus-touch-controller-right.obj ├── index.html └── package-lock.json └── errata.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /9781484263174.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/9781484263174.jpg -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Freeware License, some rights reserved 2 | 3 | Copyright (c) 2021 Rakesh Baruah 4 | 5 | Permission is hereby granted, free of charge, to anyone obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to work with the Software within the limits of freeware distribution and fair use. 8 | This includes the rights to use, copy, and modify the Software for personal use. 9 | Users are also allowed and encouraged to submit corrections and modifications 10 | to the Software for the benefit of other users. 11 | 12 | It is not allowed to reuse, modify, or redistribute the Software for 13 | commercial use in any way, or for a user’s educational materials such as books 14 | or blog articles without prior permission from the copyright holder. 15 | 16 | The above copyright notice and this permission notice need to be included 17 | in all copies or substantial portions of the software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*AR and VR Using the WebXR API*](https://www.apress.com/9781484263174) by Rakesh Baruah (Apress, 2021). 4 | 5 | [comment]: #cover 6 | ![Cover image](9781484263174.jpg) 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. -------------------------------------------------------------------------------- /ch10_ex9/assets/attribution.txt: -------------------------------------------------------------------------------- 1 | "City" by antonmoek 2 | https://sketchfab.com/antonmoek 3 | CC BY 4.0 4 | https://creativecommons.org/licenses/by/4.0/ 5 | 6 | "Dragon" by elly77ellison 7 | https://sketchfab.com/3d-models/animated-dragon-0ea921bb3d504023b891bba3fb8e6111 8 | CC BY 4.0 9 | https://creativecommons.org/licenses/by/4.0/ -------------------------------------------------------------------------------- /ch10_ex9/assets/city/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/scene.bin -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.11_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.11_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.15_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.15_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.16_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.16_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.17_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.17_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.19_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.19_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.8_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.8_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap.9_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap.9_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/city/textures/World_ap_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/city/textures/World_ap_baseColor.jpeg -------------------------------------------------------------------------------- /ch10_ex9/assets/dragon/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/dragon/scene.bin -------------------------------------------------------------------------------- /ch10_ex9/assets/dragon/textures/material_0_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/dragon/textures/material_0_diffuse.png -------------------------------------------------------------------------------- /ch10_ex9/assets/dragon/textures/material_0_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/dragon/textures/material_0_normal.png -------------------------------------------------------------------------------- /ch10_ex9/assets/dragon/textures/material_0_occlusion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/dragon/textures/material_0_occlusion.png -------------------------------------------------------------------------------- /ch10_ex9/assets/dragon/textures/material_0_specularGlossiness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch10_ex9/assets/dragon/textures/material_0_specularGlossiness.png -------------------------------------------------------------------------------- /ch10_ex9/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | WebXR API: Ch.10 Ex.9 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ch2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebGL: Canvas Context 7 | 14 | 15 | 16 | 17 | 24 | 31 | 32 | 116 | 117 | -------------------------------------------------------------------------------- /ch3/ex2_part1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebGL: Lesson 2 Creating 2D 7 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch3/ex2_part1/index.js.js: -------------------------------------------------------------------------------- 1 | main(); 2 | 3 | function main() { 4 | /*========== Create a WebGL Context ==========*/ 5 | const canvas = document.querySelector("#c"); 6 | const gl = canvas.getContext('webgl'); 7 | if (!gl) { 8 | console.log('WebGL unavailable'); 9 | } else { 10 | console.log('WebGL is good to go'); 11 | } 12 | 13 | /*========== Define and Store the Geometry ==========*/ 14 | const firstSquare = [ 15 | // front face 16 | -0.3 , -0.3, -0.3, 17 | 0.3, -0.3, -0.3, 18 | 0.3, 0.3, -0.3, 19 | 20 | -0.3, -0.3, -0.3, 21 | -0.3, 0.3, -0.3, 22 | 0.3, 0.3, -0.3, 23 | ]; 24 | 25 | // buffer 26 | const origBuffer = gl.createBuffer(); 27 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 28 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(firstSquare), gl.STATIC_DRAW); 29 | 30 | /*========== Shaders ==========*/ 31 | 32 | const vsSource = ` 33 | attribute vec4 aPosition; 34 | 35 | void main() { 36 | gl_Position = aPosition; 37 | } 38 | `; 39 | 40 | const fsSource = ` 41 | void main() { 42 | gl_FragColor = vec4(1, 0, 0, 1); 43 | } 44 | `; 45 | //create shaders 46 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); 47 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 48 | gl.shaderSource(vertexShader, vsSource); 49 | gl.shaderSource(fragmentShader, fsSource); 50 | 51 | // compile shaders 52 | gl.compileShader(vertexShader); 53 | gl.compileShader(fragmentShader); 54 | 55 | // create program 56 | const program = gl.createProgram(); 57 | gl.attachShader(program, vertexShader); 58 | gl.attachShader(program, fragmentShader); 59 | 60 | // link program 61 | gl.linkProgram(program); 62 | gl.useProgram(program); 63 | 64 | /*========== Connect the attribute with the vertex shader ==========*/ 65 | const posAttribLocation = gl.getAttribLocation(program, "aPosition"); 66 | gl.vertexAttribPointer(posAttribLocation, 3, gl.FLOAT, false, 0, 0); 67 | gl.enableVertexAttribArray(posAttribLocation); 68 | 69 | /*========== Drawing ========== */ 70 | gl.clearColor(1, 1, 1, 1); 71 | 72 | // gl.enable(gl.DEPTH_TEST); 73 | // gl.depthFunc(gl.LEQUAL); 74 | 75 | // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 76 | gl.clear(gl.COLOR_BUFFER_BIT); 77 | // Draw the points on the screen 78 | const mode = gl.TRIANGLES; 79 | const first = 0; 80 | const count = 6; 81 | gl.drawArrays(mode, first, count); 82 | } 83 | -------------------------------------------------------------------------------- /ch3/ex2_part2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebGL: Lesson 2-2 Creating Squares 7 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch3/ex2_part2/lesson2-2.js: -------------------------------------------------------------------------------- 1 | main(); 2 | 3 | function main() { 4 | /*========== Create a WebGL Context ==========*/ 5 | const canvas = document.querySelector("#c"); 6 | const gl = canvas.getContext('webgl'); 7 | if (!gl) { 8 | console.log('WebGL unavailable'); 9 | } else { 10 | console.log('WebGL is good to go'); 11 | } 12 | 13 | /*========== Define and Store the Geometry ==========*/ 14 | const squares = [ 15 | // front face 16 | -0.3 , -0.3, -0.3, 17 | 0.3, -0.3, -0.3, 18 | 0.3, 0.3, -0.3, 19 | 20 | -0.3, -0.3, -0.3, 21 | -0.3, 0.3, -0.3, 22 | 0.3, 0.3, -0.3, 23 | 24 | // back face 25 | -0.2, -0.2, 0.3, 26 | 0.4, -0.2, 0.3, 27 | 0.4, 0.4, 0.3, 28 | 29 | -0.2, -0.2, 0.3, 30 | -0.2, 0.4, 0.3, 31 | 0.4, 0.4, 0.3, 32 | ]; 33 | 34 | // buffer 35 | const origBuffer = gl.createBuffer(); 36 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 37 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squares), gl.STATIC_DRAW); 38 | 39 | const squareColors = [ 40 | 0.0, 0.0, 1.0, 1.0, 41 | 0.0, 0.0, 1.0, 1.0, 42 | 0.0, 0.0, 1.0, 1.0, 43 | 0.0, 0.0, 1.0, 1.0, 44 | 0.0, 0.0, 1.0, 1.0, 45 | 0.0, 0.0, 1.0, 1.0, 46 | 47 | 1.0, 0.0, 0.0, 1.0, 48 | 1.0, 0.0, 0.0, 1.0, 49 | 1.0, 0.0, 0.0, 1.0, 50 | 1.0, 0.0, 0.0, 1.0, 51 | 1.0, 0.0, 0.0, 1.0, 52 | 1.0, 0.0, 0.0, 1.0, 53 | ]; 54 | 55 | const colorBuffer = gl.createBuffer(); 56 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 57 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squareColors), gl.STATIC_DRAW); 58 | 59 | /*========== Shaders ==========*/ 60 | 61 | const vsSource = ` 62 | attribute vec4 aPosition; 63 | attribute vec4 aVertexColor; 64 | 65 | varying lowp vec4 vColor; 66 | 67 | void main() { 68 | gl_Position = aPosition; 69 | vColor = aVertexColor; 70 | } 71 | `; 72 | 73 | const fsSource = ` 74 | varying lowp vec4 vColor; 75 | 76 | void main() { 77 | gl_FragColor = vColor; 78 | } 79 | `; 80 | 81 | //create shaders 82 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); 83 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 84 | gl.shaderSource(vertexShader, vsSource); 85 | gl.shaderSource(fragmentShader, fsSource); 86 | 87 | // compile shaders 88 | gl.compileShader(vertexShader); 89 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 90 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vertexShader)); 91 | gl.deleteShader(vertexShader); 92 | return null; 93 | } 94 | gl.compileShader(fragmentShader); 95 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 96 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fragmentShader)); 97 | gl.deleteShader(fragmentShader); 98 | return null; 99 | } 100 | 101 | // create program 102 | const program = gl.createProgram(); 103 | gl.attachShader(program, vertexShader); 104 | gl.attachShader(program, fragmentShader); 105 | 106 | // link program 107 | gl.linkProgram(program); 108 | gl.useProgram(program); 109 | 110 | /*========== Connect the attribute with the vertex shader ==========*/ 111 | const posAttribLocation = gl.getAttribLocation(program, "aPosition"); 112 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 113 | gl.vertexAttribPointer(posAttribLocation, 3, gl.FLOAT, false, 0, 0); 114 | gl.enableVertexAttribArray(posAttribLocation); 115 | 116 | const colorAttribLocation = gl.getAttribLocation(program, "aVertexColor"); 117 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 118 | gl.vertexAttribPointer(colorAttribLocation, 4, gl.FLOAT, false, 0, 0); 119 | gl.enableVertexAttribArray(colorAttribLocation); 120 | 121 | /*========== Drawing ========== */ 122 | gl.clearColor(1, 1, 1, 1); 123 | 124 | gl.enable(gl.DEPTH_TEST); 125 | //gl.depthFunc(gl.LEQUAL); 126 | 127 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 128 | //gl.clear(gl.COLOR_BUFFER_BIT); 129 | // Draw the points on the screen 130 | const mode = gl.TRIANGLES; 131 | const first = 0; 132 | const count = 12; 133 | gl.drawArrays(mode, first, count); 134 | } 135 | -------------------------------------------------------------------------------- /ch3/ex2_part3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebGL: Lesson 2-3 Creating 3D 7 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch3/ex2_part3/lesson2-3.js: -------------------------------------------------------------------------------- 1 | main(); 2 | 3 | function main() { 4 | /*========== Create a WebGL Context ==========*/ 5 | const canvas = document.querySelector("#c"); 6 | const gl = canvas.getContext('webgl'); 7 | if (!gl) { 8 | console.log('WebGL unavailable'); 9 | } else { 10 | console.log('WebGL is good to go'); 11 | } 12 | 13 | /*========== Define and Store the Geometry ==========*/ 14 | const squares = [ 15 | // front face 16 | -0.3 , -0.3, -0.3, 17 | 0.3, -0.3, -0.3, 18 | 0.3, 0.3, -0.3, 19 | 20 | -0.3, -0.3, -0.3, 21 | -0.3, 0.3, -0.3, 22 | 0.3, 0.3, -0.3, 23 | 24 | // back face 25 | -0.2, -0.2, 0.3, 26 | 0.4, -0.2, 0.3, 27 | 0.4, 0.4, 0.3, 28 | 29 | -0.2, -0.2, 0.3, 30 | -0.2, 0.4, 0.3, 31 | 0.4, 0.4, 0.3, 32 | 33 | // top face 34 | -0.3, 0.3, -0.3, 35 | 0.3, 0.3, -0.3, 36 | -0.2, 0.4, 0.3, 37 | 38 | 0.4, 0.4, 0.3, 39 | 0.3, 0.3, -0.3, 40 | -0.2, 0.4, 0.3, 41 | ]; 42 | 43 | // buffer 44 | const origBuffer = gl.createBuffer(); 45 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 46 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squares), gl.STATIC_DRAW); 47 | 48 | const squareColors = [ 49 | 0.0, 0.0, 1.0, 1.0, 50 | 0.0, 0.0, 1.0, 1.0, 51 | 0.0, 0.0, 1.0, 1.0, 52 | 0.0, 0.0, 1.0, 1.0, 53 | 0.0, 0.0, 1.0, 1.0, 54 | 0.0, 0.0, 1.0, 1.0, 55 | 1.0, 0.0, 0.0, 1.0, 56 | 1.0, 0.0, 0.0, 1.0, 57 | 1.0, 0.0, 0.0, 1.0, 58 | 1.0, 0.0, 0.0, 1.0, 59 | 1.0, 0.0, 0.0, 1.0, 60 | 1.0, 0.0, 0.0, 1.0, 61 | 0.0, 1.0, 0.0, 1.0, 62 | 0.0, 1.0, 0.0, 1.0, 63 | 0.0, 1.0, 0.0, 1.0, 64 | 0.0, 1.0, 0.0, 1.0, 65 | 0.0, 1.0, 0.0, 1.0, 66 | 0.0, 1.0, 0.0, 1.0, 67 | ]; 68 | 69 | const colorBuffer = gl.createBuffer(); 70 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 71 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squareColors), gl.STATIC_DRAW); 72 | 73 | /*========== Shaders ==========*/ 74 | 75 | const vsSource = ` 76 | attribute vec4 aPosition; 77 | attribute vec4 aVertexColor; 78 | 79 | varying lowp vec4 vColor; 80 | 81 | void main() { 82 | gl_Position = aPosition; 83 | vColor = aVertexColor; 84 | } 85 | `; 86 | 87 | const fsSource = ` 88 | varying lowp vec4 vColor; 89 | 90 | void main() { 91 | gl_FragColor = vColor; 92 | } 93 | `; 94 | 95 | //create shaders 96 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); 97 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 98 | gl.shaderSource(vertexShader, vsSource); 99 | gl.shaderSource(fragmentShader, fsSource); 100 | 101 | // compile shaders 102 | gl.compileShader(vertexShader); 103 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 104 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vertexShader)); 105 | gl.deleteShader(vertexShader); 106 | return null; 107 | } 108 | gl.compileShader(fragmentShader); 109 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 110 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fragmentShader)); 111 | gl.deleteShader(fragmentShader); 112 | return null; 113 | } 114 | 115 | // create program 116 | const program = gl.createProgram(); 117 | gl.attachShader(program, vertexShader); 118 | gl.attachShader(program, fragmentShader); 119 | 120 | // link program 121 | gl.linkProgram(program); 122 | gl.useProgram(program); 123 | 124 | /*========== Connect the attribute with the vertex shader ==========*/ 125 | const posAttribLocation = gl.getAttribLocation(program, "aPosition"); 126 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 127 | gl.vertexAttribPointer(posAttribLocation, 3, gl.FLOAT, false, 0, 0); 128 | gl.enableVertexAttribArray(posAttribLocation); 129 | 130 | const colorAttribLocation = gl.getAttribLocation(program, "aVertexColor"); 131 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 132 | gl.vertexAttribPointer(colorAttribLocation, 4, gl.FLOAT, false, 0, 0); 133 | gl.enableVertexAttribArray(colorAttribLocation); 134 | 135 | /*========== Drawing ========== */ 136 | gl.clearColor(1, 1, 1, 1); 137 | 138 | gl.enable(gl.DEPTH_TEST); 139 | //gl.depthFunc(gl.LEQUAL); 140 | 141 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 142 | //gl.clear(gl.COLOR_BUFFER_BIT); 143 | // Draw the points on the screen 144 | const mode = gl.TRIANGLES; 145 | const first = 0; 146 | const count = 18; 147 | gl.drawArrays(mode, first, count); 148 | } 149 | -------------------------------------------------------------------------------- /ch3/webGLtemplate.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | /*========== Create a WebGL Context ==========*/ 3 | 4 | 5 | /*========== Define and Store the Geometry ==========*/ 6 | 7 | 8 | /*========== Shaders ==========*/ 9 | 10 | 11 | /*========== Connect the attribute with the vertex shader ===================*/ 12 | 13 | 14 | /*========== Drawing ======================== */ 15 | 16 | 17 | 18 | } -------------------------------------------------------------------------------- /ch4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebGL: Lesson 3 Rotating 3D 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch4/lesson3-1.js: -------------------------------------------------------------------------------- 1 | main(); 2 | 3 | function main() { 4 | /*========== Create a WebGL Context ==========*/ 5 | const canvas = document.querySelector("#c"); 6 | const gl = canvas.getContext('webgl'); 7 | if (!gl) { 8 | console.log('WebGL unavailable'); 9 | } else { 10 | console.log('WebGL is good to go'); 11 | } 12 | 13 | /*========== Define and Store the Geometry ==========*/ 14 | const squares = [ 15 | // front face 16 | -0.3 , -0.3, -0.3, 17 | 0.3, -0.3, -0.3, 18 | 0.3, 0.3, -0.3, 19 | 20 | -0.3, -0.3, -0.3, 21 | -0.3, 0.3, -0.3, 22 | 0.3, 0.3, -0.3, 23 | 24 | // back face 25 | -0.2, -0.2, 0.3, 26 | 0.4, -0.2, 0.3, 27 | 0.4, 0.4, 0.3, 28 | 29 | -0.2, -0.2, 0.3, 30 | -0.2, 0.4, 0.3, 31 | 0.4, 0.4, 0.3, 32 | 33 | // top face 34 | -0.3, 0.3, -0.3, 35 | 0.3, 0.3, -0.3, 36 | -0.2, 0.4, 0.3, 37 | 38 | 0.4, 0.4, 0.3, 39 | 0.3, 0.3, -0.3, 40 | -0.2, 0.4, 0.3, 41 | ]; 42 | 43 | // buffer 44 | const origBuffer = gl.createBuffer(); 45 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 46 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squares), gl.STATIC_DRAW); 47 | 48 | const squareColors = [ 49 | 0.0, 0.0, 1.0, 1.0, 50 | 0.0, 0.0, 1.0, 1.0, 51 | 0.0, 0.0, 1.0, 1.0, 52 | 0.0, 0.0, 1.0, 1.0, 53 | 0.0, 0.0, 1.0, 1.0, 54 | 0.0, 0.0, 1.0, 1.0, 55 | 1.0, 0.0, 0.0, 1.0, 56 | 1.0, 0.0, 0.0, 1.0, 57 | 1.0, 0.0, 0.0, 1.0, 58 | 1.0, 0.0, 0.0, 1.0, 59 | 1.0, 0.0, 0.0, 1.0, 60 | 1.0, 0.0, 0.0, 1.0, 61 | 0.0, 1.0, 0.0, 1.0, 62 | 0.0, 1.0, 0.0, 1.0, 63 | 0.0, 1.0, 0.0, 1.0, 64 | 0.0, 1.0, 0.0, 1.0, 65 | 0.0, 1.0, 0.0, 1.0, 66 | 0.0, 1.0, 0.0, 1.0, 67 | ]; 68 | 69 | const colorBuffer = gl.createBuffer(); 70 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 71 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squareColors), gl.STATIC_DRAW); 72 | 73 | /*========== Shaders ==========*/ 74 | 75 | const vsSource = ` 76 | attribute vec4 aPosition; 77 | attribute vec4 aVertexColor; 78 | 79 | uniform mat4 uModelViewMatrix; 80 | 81 | varying lowp vec4 vColor; 82 | 83 | void main() { 84 | gl_Position = uModelViewMatrix * aPosition; 85 | vColor = aVertexColor; 86 | } 87 | `; 88 | 89 | const fsSource = ` 90 | varying lowp vec4 vColor; 91 | 92 | void main() { 93 | gl_FragColor = vColor; 94 | } 95 | `; 96 | 97 | //create shaders 98 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); 99 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 100 | gl.shaderSource(vertexShader, vsSource); 101 | gl.shaderSource(fragmentShader, fsSource); 102 | 103 | // compile shaders 104 | gl.compileShader(vertexShader); 105 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 106 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vertexShader)); 107 | gl.deleteShader(vertexShader); 108 | return null; 109 | } 110 | gl.compileShader(fragmentShader); 111 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 112 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fragmentShader)); 113 | gl.deleteShader(fragmentShader); 114 | return null; 115 | } 116 | 117 | // create program 118 | const program = gl.createProgram(); 119 | gl.attachShader(program, vertexShader); 120 | gl.attachShader(program, fragmentShader); 121 | 122 | // link program 123 | gl.linkProgram(program); 124 | gl.useProgram(program); 125 | 126 | let cubeRotation = 0.0; 127 | let then = 0; 128 | 129 | /*========== Connect the attribute with the vertex shader ==========*/ 130 | function render(now){ 131 | now *= 0.001; 132 | const deltaTime = now - then; 133 | then = now; 134 | 135 | const posAttribLocation = gl.getAttribLocation(program, "aPosition"); 136 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 137 | gl.vertexAttribPointer(posAttribLocation, 3, gl.FLOAT, false, 0, 0); 138 | gl.enableVertexAttribArray(posAttribLocation); 139 | 140 | const colorAttribLocation = gl.getAttribLocation(program, "aVertexColor"); 141 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 142 | gl.vertexAttribPointer(colorAttribLocation, 4, gl.FLOAT, false, 0, 0); 143 | gl.enableVertexAttribArray(colorAttribLocation); 144 | 145 | const modelMatrixLocation = gl.getUniformLocation(program, 'uModelViewMatrix'); 146 | 147 | const modelViewMatrix = mat4.create(); 148 | 149 | mat4.rotate(modelViewMatrix, // destination matrix 150 | modelViewMatrix, // matrix to rotate 151 | cubeRotation, // amount to rotate in radians 152 | [0, 0, 1]); // axis to rotate around (Z) 153 | 154 | gl.uniformMatrix4fv(modelMatrixLocation, false, modelViewMatrix); 155 | 156 | /*========== Drawing ========== */ 157 | gl.clearColor(1, 1, 1, 1); 158 | 159 | gl.enable(gl.DEPTH_TEST); 160 | //gl.depthFunc(gl.LEQUAL); 161 | 162 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 163 | 164 | // Draw the points on the screen 165 | const mode = gl.TRIANGLES; 166 | const first = 0; 167 | const count = 18; 168 | gl.drawArrays(mode, first, count); 169 | cubeRotation += deltaTime; 170 | requestAnimationFrame(render); 171 | } 172 | requestAnimationFrame(render); 173 | } 174 | -------------------------------------------------------------------------------- /ch4/lesson3-2.js: -------------------------------------------------------------------------------- 1 | main(); 2 | 3 | function main() { 4 | /*========== Create a WebGL Context ==========*/ 5 | const canvas = document.querySelector("#c"); 6 | const gl = canvas.getContext('webgl'); 7 | if (!gl) { 8 | console.log('WebGL unavailable'); 9 | } else { 10 | console.log('WebGL is good to go'); 11 | } 12 | 13 | /*========== Define and Store the Geometry ==========*/ 14 | const squares = [ 15 | // front face 16 | -0.3 , -0.3, -0.3, 17 | 0.3, -0.3, -0.3, 18 | 0.3, 0.3, -0.3, 19 | 20 | -0.3, -0.3, -0.3, 21 | -0.3, 0.3, -0.3, 22 | 0.3, 0.3, -0.3, 23 | 24 | // back face 25 | -0.2, -0.2, 0.3, 26 | 0.4, -0.2, 0.3, 27 | 0.4, 0.4, 0.3, 28 | 29 | -0.2, -0.2, 0.3, 30 | -0.2, 0.4, 0.3, 31 | 0.4, 0.4, 0.3, 32 | 33 | // top face 34 | -0.3, 0.3, -0.3, 35 | 0.3, 0.3, -0.3, 36 | -0.2, 0.4, 0.3, 37 | 38 | 0.4, 0.4, 0.3, 39 | 0.3, 0.3, -0.3, 40 | -0.2, 0.4, 0.3, 41 | ]; 42 | 43 | // buffer 44 | const origBuffer = gl.createBuffer(); 45 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 46 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squares), gl.STATIC_DRAW); 47 | 48 | const squareColors = [ 49 | 0.0, 0.0, 1.0, 1.0, 50 | 0.0, 0.0, 1.0, 1.0, 51 | 0.0, 0.0, 1.0, 1.0, 52 | 0.0, 0.0, 1.0, 1.0, 53 | 0.0, 0.0, 1.0, 1.0, 54 | 0.0, 0.0, 1.0, 1.0, 55 | 1.0, 0.0, 0.0, 1.0, 56 | 1.0, 0.0, 0.0, 1.0, 57 | 1.0, 0.0, 0.0, 1.0, 58 | 1.0, 0.0, 0.0, 1.0, 59 | 1.0, 0.0, 0.0, 1.0, 60 | 1.0, 0.0, 0.0, 1.0, 61 | 0.0, 1.0, 0.0, 1.0, 62 | 0.0, 1.0, 0.0, 1.0, 63 | 0.0, 1.0, 0.0, 1.0, 64 | 0.0, 1.0, 0.0, 1.0, 65 | 0.0, 1.0, 0.0, 1.0, 66 | 0.0, 1.0, 0.0, 1.0, 67 | ]; 68 | 69 | const colorBuffer = gl.createBuffer(); 70 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 71 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(squareColors), gl.STATIC_DRAW); 72 | 73 | /*========== Shaders ==========*/ 74 | 75 | const vsSource = ` 76 | attribute vec4 aPosition; 77 | attribute vec4 aVertexColor; 78 | 79 | uniform mat4 uModelViewMatrix; 80 | uniform mat4 uProjectionMatrix; 81 | 82 | varying lowp vec4 vColor; 83 | 84 | void main() { 85 | gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition; 86 | vColor = aVertexColor; 87 | } 88 | `; 89 | 90 | const fsSource = ` 91 | varying lowp vec4 vColor; 92 | 93 | void main() { 94 | gl_FragColor = vColor; 95 | } 96 | `; 97 | 98 | //create shaders 99 | const vertexShader = gl.createShader(gl.VERTEX_SHADER); 100 | const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 101 | gl.shaderSource(vertexShader, vsSource); 102 | gl.shaderSource(fragmentShader, fsSource); 103 | 104 | // compile shaders 105 | gl.compileShader(vertexShader); 106 | if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { 107 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vertexShader)); 108 | gl.deleteShader(vertexShader); 109 | return null; 110 | } 111 | gl.compileShader(fragmentShader); 112 | if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { 113 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fragmentShader)); 114 | gl.deleteShader(fragmentShader); 115 | return null; 116 | } 117 | 118 | // create program 119 | const program = gl.createProgram(); 120 | gl.attachShader(program, vertexShader); 121 | gl.attachShader(program, fragmentShader); 122 | 123 | // link program 124 | gl.linkProgram(program); 125 | gl.useProgram(program); 126 | 127 | let cubeRotation = 0.0; 128 | let then = 0; 129 | 130 | /*========== Connect the attribute with the vertex shader ==========*/ 131 | function render(now){ 132 | now *= 0.001; 133 | const deltaTime = now - then; 134 | then = now; 135 | 136 | const posAttribLocation = gl.getAttribLocation(program, "aPosition"); 137 | gl.bindBuffer(gl.ARRAY_BUFFER, origBuffer); 138 | gl.vertexAttribPointer(posAttribLocation, 3, gl.FLOAT, false, 0, 0); 139 | gl.enableVertexAttribArray(posAttribLocation); 140 | 141 | const colorAttribLocation = gl.getAttribLocation(program, "aVertexColor"); 142 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 143 | gl.vertexAttribPointer(colorAttribLocation, 4, gl.FLOAT, false, 0, 0); 144 | gl.enableVertexAttribArray(colorAttribLocation); 145 | 146 | 147 | const modelMatrixLocation = gl.getUniformLocation(program, 'uModelViewMatrix'); 148 | const projMatrixLocation = gl.getUniformLocation(program, 'uProjectionMatrix'); 149 | 150 | const fieldOfView = 45 * Math.PI / 180; // in radians 151 | const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; 152 | const zNear = 0.1; 153 | const zFar = 100.0; 154 | const projectionMatrix = mat4.create(); 155 | 156 | // note: glmatrix.js always has the first argument 157 | // as the destination to receive the result. 158 | mat4.perspective(projectionMatrix, 159 | fieldOfView, 160 | aspect, 161 | zNear, 162 | zFar); 163 | 164 | const modelViewMatrix = mat4.create(); 165 | 166 | mat4.translate(modelViewMatrix, // destination matrix 167 | modelViewMatrix, // matrix to translate 168 | [-0.0, 0.0, -2.0]); // amount to translate 169 | mat4.rotate(modelViewMatrix, // destination matrix 170 | modelViewMatrix, // matrix to rotate 171 | cubeRotation, // amount to rotate in radians 172 | [0, 0, 1]); // axis to rotate around (Z) 173 | mat4.rotate(modelViewMatrix, // destination matrix 174 | modelViewMatrix, // matrix to rotate 175 | cubeRotation,// amount to rotate in radians 176 | [0, 1, 0]); // axis to rotate around (X) 177 | 178 | gl.uniformMatrix4fv(projMatrixLocation, false, projectionMatrix); 179 | gl.uniformMatrix4fv(modelMatrixLocation, false, modelViewMatrix); 180 | 181 | /*========== Drawing ========== */ 182 | gl.clearColor(1, 1, 1, 1); 183 | 184 | gl.enable(gl.DEPTH_TEST); 185 | //gl.depthFunc(gl.LEQUAL); 186 | 187 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 188 | 189 | // Draw the points on the screen 190 | const mode = gl.TRIANGLES; 191 | const first = 0; 192 | const count = 18; 193 | gl.drawArrays(mode, first, count); 194 | cubeRotation += deltaTime; 195 | requestAnimationFrame(render); 196 | } 197 | requestAnimationFrame(render); 198 | } 199 | -------------------------------------------------------------------------------- /ch5_ex4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | WebXR Ch. 5 Ex. 4 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch5_ex4/index_ex4_final.js: -------------------------------------------------------------------------------- 1 | import * as THREE from './modules/three.module.js'; 2 | 3 | main(); 4 | 5 | function main() { 6 | // create context 7 | const canvas = document.querySelector("#c"); 8 | const gl = new THREE.WebGLRenderer({ 9 | canvas, 10 | antialias: true 11 | }); 12 | 13 | // create camera 14 | const angleOfView = 55; 15 | const aspectRatio = canvas.clientWidth / canvas.clientHeight; 16 | const nearPlane = 0.1; 17 | const farPlane = 100; 18 | const camera = new THREE.PerspectiveCamera( 19 | angleOfView, 20 | aspectRatio, 21 | nearPlane, 22 | farPlane 23 | ); 24 | camera.position.set(0, 8, 30); 25 | 26 | // create the scene 27 | const scene = new THREE.Scene(); 28 | scene.background = new THREE.Color(0.3, 0.5, 0.8); 29 | const fog = new THREE.Fog("grey", 1,90); 30 | scene.fog = fog; 31 | 32 | // GEOMETRY 33 | // create the cube 34 | const cubeSize = 4; 35 | const cubeGeometry = new THREE.BoxGeometry( 36 | cubeSize, 37 | cubeSize, 38 | cubeSize 39 | ); 40 | 41 | // Create the Sphere 42 | const sphereRadius = 3; 43 | const sphereWidthSegments = 32; 44 | const sphereHeightSegments = 16; 45 | const sphereGeometry = new THREE.SphereGeometry( 46 | sphereRadius, 47 | sphereWidthSegments, 48 | sphereHeightSegments 49 | ); 50 | 51 | // Create the upright plane 52 | const planeWidth = 256; 53 | const planeHeight = 128; 54 | const planeGeometry = new THREE.PlaneGeometry( 55 | planeWidth, 56 | planeHeight 57 | ); 58 | 59 | // MATERIALS 60 | const textureLoader = new THREE.TextureLoader(); 61 | 62 | const cubeMaterial = new THREE.MeshPhongMaterial({ 63 | color: 'pink' 64 | }); 65 | 66 | const sphereNormalMap = textureLoader.load('textures/sphere_normal.png'); 67 | sphereNormalMap.wrapS = THREE.RepeatWrapping; 68 | sphereNormalMap.wrapT = THREE.RepeatWrapping; 69 | const sphereMaterial = new THREE.MeshStandardMaterial({ 70 | color: 'tan', 71 | normalMap: sphereNormalMap 72 | }); 73 | 74 | 75 | const planeTextureMap = textureLoader.load('textures/pebbles.jpg'); 76 | planeTextureMap.wrapS = THREE.RepeatWrapping; 77 | planeTextureMap.wrapT = THREE.RepeatWrapping; 78 | planeTextureMap.repeat.set(16, 16); 79 | //planeTextureMap.magFilter = THREE.NearestFilter; 80 | planeTextureMap.minFilter = THREE.NearestFilter; 81 | planeTextureMap.anisotropy = gl.getMaxAnisotropy(); 82 | const planeNorm = textureLoader.load('textures/pebbles_normal.png'); 83 | planeNorm.wrapS = THREE.RepeatWrapping; 84 | planeNorm.wrapT = THREE.RepeatWrapping; 85 | planeNorm.minFilter = THREE.NearestFilter; 86 | planeNorm.repeat.set(16, 16); 87 | const planeMaterial = new THREE.MeshStandardMaterial({ 88 | map: planeTextureMap, 89 | side: THREE.DoubleSide, 90 | normalMap: planeNorm 91 | }); 92 | 93 | // MESHES 94 | const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); 95 | cube.position.set(cubeSize + 1, cubeSize + 1, 0); 96 | scene.add(cube); 97 | 98 | const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); 99 | sphere.position.set(-sphereRadius - 1, sphereRadius + 2, 0); 100 | scene.add(sphere); 101 | 102 | const plane = new THREE.Mesh(planeGeometry, planeMaterial); 103 | plane.rotation.x = Math.PI / 2; 104 | //scene.add(plane); 105 | 106 | //LIGHTS 107 | const color = 0xffffff; 108 | const intensity = .7; 109 | const light = new THREE.DirectionalLight(color, intensity); 110 | light.target = plane; 111 | light.position.set(0, 30, 30); 112 | scene.add(light); 113 | scene.add(light.target); 114 | 115 | const ambientColor = 0xffffff; 116 | const ambientIntensity = 0.2; 117 | const ambientLight = new THREE.AmbientLight(ambientColor, ambientIntensity); 118 | scene.add(ambientLight); 119 | 120 | // DRAW 121 | function draw(time){ 122 | time *= 0.001; 123 | 124 | if (resizeGLToDisplaySize(gl)) { 125 | const canvas = gl.domElement; 126 | camera.aspect = canvas.clientWidth / canvas.clientHeight; 127 | camera.updateProjectionMatrix(); 128 | } 129 | 130 | cube.rotation.x += 0.01; 131 | cube.rotation.y += 0.01; 132 | cube.rotation.z += 0.01; 133 | 134 | sphere.rotation.x += 0.01; 135 | sphere.rotation.y += 0.01; 136 | sphere.rotation.y += 0.01; 137 | 138 | light.position.x = 20*Math.cos(time); 139 | light.position.y = 20*Math.sin(time); 140 | gl.render(scene, camera); 141 | requestAnimationFrame(draw); 142 | } 143 | 144 | requestAnimationFrame(draw); 145 | } 146 | 147 | // UPDATE RESIZE 148 | function resizeGLToDisplaySize(gl) { 149 | const canvas = gl.domElement; 150 | const width = canvas.clientWidth; 151 | const height = canvas.clientHeight; 152 | const needResize = canvas.width != width || canvas.height != height; 153 | if (needResize) { 154 | gl.setSize(width, height, false); 155 | } 156 | return needResize; 157 | } -------------------------------------------------------------------------------- /ch5_ex4/textures/pebbies_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch5_ex4/textures/pebbies_gray.png -------------------------------------------------------------------------------- /ch5_ex4/textures/pebbles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch5_ex4/textures/pebbles.jpg -------------------------------------------------------------------------------- /ch5_ex4/textures/pebbles_height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch5_ex4/textures/pebbles_height.png -------------------------------------------------------------------------------- /ch5_ex4/textures/pebbles_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch5_ex4/textures/pebbles_normal.png -------------------------------------------------------------------------------- /ch5_ex4/textures/sphere_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch5_ex4/textures/sphere_normal.png -------------------------------------------------------------------------------- /ch6_ex5/VRButton.js: -------------------------------------------------------------------------------- 1 | var VRButton = { 2 | createButton: function(gl, options) { 3 | if (options && options.referenceSpaceType) { 4 | gl.xr.setReferenceSpaceType(options.referenceSpaceType); 5 | } 6 | 7 | function EnterVR() { 8 | // label button 9 | button.innerHTML = 'Enter XR'; 10 | var currentSession = null; 11 | function onSessionStarted(session) { 12 | session.addEventListener('end', onSessionEnded); 13 | 14 | button.textContent = 'Exit XR'; 15 | currentSession = session; 16 | setupWebGLLayer() 17 | .then(() => { 18 | gl.xr.setSession(currentSession); 19 | }); 20 | } 21 | 22 | function onSessionEnded(/*event*/) { 23 | currentSession.removeEventListener('end', onSessionEnded); 24 | button.textContent = 'Enter XR'; 25 | currentSession = null; 26 | } 27 | 28 | function setupWebGLLayer() { 29 | var glContext = gl.getContext(); 30 | return glContext.makeXRCompatible().then(() => { 31 | currentSession.updateRenderState( {baseLayer: new XRWebGLLayer(currentSession, glContext) }); 32 | }); 33 | } 34 | 35 | button.onclick = () => { 36 | if (currentSession === null) { 37 | let sessionInit = { 38 | optionalFeatures: ["local-floor", "bounded-floor"] 39 | }; 40 | navigator.xr 41 | .requestSession('immersive-vr', sessionInit) 42 | .then(onSessionStarted); 43 | } 44 | else { 45 | currentSession.end(); 46 | } 47 | } 48 | } 49 | 50 | function NotFound() { 51 | console.log('immersive-vr mode not found'); 52 | } 53 | 54 | if (navigator.xr) { 55 | var button = document.createElement("button"); 56 | navigator.xr.isSessionSupported('immersive-vr') 57 | .then(function(supported) { 58 | if (supported) { EnterVR() } 59 | else { NotFound(); } 60 | }) 61 | button.setAttribute("id", "btn"); 62 | return button; 63 | } else { 64 | if (window.isSecureContext === false) { 65 | console.log('WebXR needs HTTPS'); 66 | } else { 67 | console.log('WebXR not available'); 68 | } 69 | return; 70 | } 71 | } 72 | } 73 | 74 | export {VRButton}; -------------------------------------------------------------------------------- /ch6_ex5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | WebXR Ch. 6 Ex. 5 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch6_ex5/index_xr.js: -------------------------------------------------------------------------------- 1 | import * as THREE from '../ch5_ex4/modules/three.module.js'; 2 | import {VRButton} from './VRButton.js'; 3 | 4 | var gl, cube, sphere, light, camera, scene, canvas, glContext; 5 | init(); 6 | animate(); 7 | 8 | function init() { 9 | // create context 10 | gl = new THREE.WebGLRenderer({antialias: true}); 11 | gl.setPixelRatio(window.devicePixelRatio); 12 | gl.setSize(window.innerWidth, window.innerHeight); 13 | gl.outputEncoding = THREE.sRGBEncoding; 14 | gl.xr.enabled = true; 15 | document.body.appendChild(gl.domElement); 16 | document.body.appendChild(VRButton.createButton(gl)); 17 | 18 | 19 | // create camera 20 | const angleOfView = 55; 21 | const aspectRatio = window.innerWidth / window.innerHeight; 22 | const nearPlane = 0.1; 23 | const farPlane = 1000; 24 | camera = new THREE.PerspectiveCamera( 25 | angleOfView, 26 | aspectRatio, 27 | nearPlane, 28 | farPlane 29 | ); 30 | camera.position.set(0, 8, 30); 31 | 32 | // create the scene 33 | scene = new THREE.Scene(); 34 | scene.background = new THREE.Color(0.3, 0.5, 0.8); 35 | const fog = new THREE.Fog("grey", 1,90); 36 | scene.fog = fog; 37 | 38 | // GEOMETRY 39 | // create the cube 40 | const cubeSize = 4; 41 | const cubeGeometry = new THREE.BoxGeometry( 42 | cubeSize, 43 | cubeSize, 44 | cubeSize 45 | ); 46 | 47 | // Create the Sphere 48 | const sphereRadius = 3; 49 | const sphereWidthSegments = 32; 50 | const sphereHeightSegments = 16; 51 | const sphereGeometry = new THREE.SphereGeometry( 52 | sphereRadius, 53 | sphereWidthSegments, 54 | sphereHeightSegments 55 | ); 56 | 57 | // Create the upright plane 58 | const planeWidth = 256; 59 | const planeHeight = 128; 60 | const planeGeometry = new THREE.PlaneGeometry( 61 | planeWidth, 62 | planeHeight 63 | ); 64 | 65 | // MATERIALS 66 | const textureLoader = new THREE.TextureLoader(); 67 | 68 | const cubeMaterial = new THREE.MeshPhongMaterial({ 69 | color: 'pink' 70 | }); 71 | 72 | const sphereNormalMap = textureLoader.load('textures/sphere_normal.png'); 73 | sphereNormalMap.wrapS = THREE.RepeatWrapping; 74 | sphereNormalMap.wrapT = THREE.RepeatWrapping; 75 | const sphereMaterial = new THREE.MeshStandardMaterial({ 76 | color: 'tan', 77 | normalMap: sphereNormalMap 78 | }); 79 | 80 | 81 | const planeTextureMap = textureLoader.load('textures/pebbles.png'); 82 | planeTextureMap.wrapS = THREE.RepeatWrapping; 83 | planeTextureMap.wrapT = THREE.RepeatWrapping; 84 | planeTextureMap.repeat.set(16, 16); 85 | //planeTextureMap.magFilter = THREE.NearestFilter; 86 | planeTextureMap.minFilter = THREE.NearestFilter; 87 | planeTextureMap.anisotropy = gl.getMaxAnisotropy(); 88 | const planeNorm = textureLoader.load('textures/pebbles_normal.png'); 89 | planeNorm.wrapS = THREE.RepeatWrapping; 90 | planeNorm.wrapT = THREE.RepeatWrapping; 91 | planeNorm.minFilter = THREE.NearestFilter; 92 | planeNorm.repeat.set(16, 16); 93 | const planeMaterial = new THREE.MeshStandardMaterial({ 94 | map: planeTextureMap, 95 | side: THREE.DoubleSide, 96 | normalMap: planeNorm 97 | }); 98 | 99 | // MESHES 100 | cube = new THREE.Mesh(cubeGeometry, cubeMaterial); 101 | cube.position.set(cubeSize + 1, cubeSize + 1, 0); 102 | scene.add(cube); 103 | 104 | sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); 105 | sphere.position.set(-sphereRadius - 1, sphereRadius + 2, 0); 106 | scene.add(sphere); 107 | 108 | const plane = new THREE.Mesh(planeGeometry, planeMaterial); 109 | plane.rotation.x = Math.PI / 2; 110 | //scene.add(plane); 111 | 112 | //LIGHTS 113 | const color = 0xffffff; 114 | const intensity = .7; 115 | light = new THREE.DirectionalLight(color, intensity); 116 | light.target = plane; 117 | light.position.set(0, 30, 30); 118 | scene.add(light); 119 | scene.add(light.target); 120 | 121 | const ambientColor = 0xffffff; 122 | const ambientIntensity = 0.2; 123 | const ambientLight = new THREE.AmbientLight(ambientColor, ambientIntensity); 124 | scene.add(ambientLight); 125 | 126 | } 127 | 128 | function animate() { 129 | // replaces requestAnimationFrame() 130 | gl.setAnimationLoop(draw); 131 | } 132 | 133 | // Renamed from render(time) 134 | function draw(time) { 135 | time *= 0.001; 136 | 137 | if (resizeDisplay) { 138 | camera.aspect = window.innerWidth / window.innerHeight; 139 | camera.updateProjectionMatrix(); 140 | } 141 | 142 | cube.rotation.x += 0.01; 143 | cube.rotation.y += 0.01; 144 | cube.rotation.z += 0.01; 145 | 146 | sphere.rotation.x += 0.01; 147 | sphere.rotation.y += 0.01; 148 | sphere.rotation.y += 0.01; 149 | 150 | light.position.x = 20*Math.cos(time); 151 | light.position.y = 20*Math.sin(time); 152 | gl.render(scene, camera); 153 | } 154 | 155 | 156 | // UPDATE RESIZE 157 | function resizeDisplay() { 158 | const canvas = gl.domElement; 159 | const width = canvas.clientWidth; 160 | const height = canvas.clientHeight; 161 | const needResize = canvas.width != width || canvas.height != height; 162 | if (needResize) { 163 | gl.setSize(width, height, false); 164 | } 165 | return needResize; 166 | } -------------------------------------------------------------------------------- /ch6_ex5/textures/pebbles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch6_ex5/textures/pebbles.png -------------------------------------------------------------------------------- /ch6_ex5/textures/pebbles_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch6_ex5/textures/pebbles_normal.png -------------------------------------------------------------------------------- /ch6_ex5/textures/sphere_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch6_ex5/textures/sphere_normal.png -------------------------------------------------------------------------------- /ch7_ex6/Part1_Floating-Cube/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebXR API: Ch.7 Ex.6 Pt.1 7 | 8 | 9 |
10 |

Immersive AR with Three.js

11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch7_ex6/Part1_Floating-Cube/index.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three/build/three.module"; 2 | // global scene values 3 | var btn, gl, glCanvas, camera, scene, renderer, cube; 4 | 5 | // global xr value 6 | var xrSession = null; 7 | 8 | loadScene(); 9 | init(); 10 | 11 | function loadScene() { 12 | // setup WebGL 13 | glCanvas = document.createElement('canvas'); 14 | gl = glCanvas.getContext('webgl', { antialias: true }); 15 | 16 | // setup Three.js scene 17 | camera = new THREE.PerspectiveCamera( 18 | 70, 19 | window.innerWidth / window.innerHeight, 20 | 0.01, 21 | 1000 22 | ); 23 | 24 | scene = new THREE.Scene(); 25 | 26 | var light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 ); 27 | light.position.set( 0.5, 1, 0.25 ); 28 | scene.add( light ); 29 | 30 | var geometry = new THREE.BoxBufferGeometry(0.2, 0.2, 0.2); 31 | var material = new THREE.MeshPhongMaterial({color: 0x89CFF0}); 32 | cube = new THREE.Mesh( geometry, material ); 33 | cube.position.y = 0.2; 34 | scene.add( cube ); 35 | 36 | // setup Three.js WebGL renderer 37 | renderer = new THREE.WebGLRenderer({ 38 | canvas: glCanvas, 39 | context: gl 40 | }); 41 | renderer.setPixelRatio( window.devicePixelRatio ); 42 | renderer.setSize( window.innerWidth, window.innerHeight ); 43 | renderer.xr.enabled = true; 44 | document.body.appendChild( renderer.domElement ); 45 | } 46 | 47 | function init() { 48 | navigator.xr.isSessionSupported('immersive-ar') 49 | .then((supported) => { 50 | if (supported) { 51 | btn = document.createElement("button"); 52 | btn.addEventListener('click', onRequestSession); 53 | btn.innerHTML = "Enter XR"; 54 | var header = document.querySelector("header"); 55 | header.appendChild(btn); 56 | } 57 | else { 58 | navigator.xr.isSessionSupported('inline') 59 | .then((supported) => { 60 | if (supported) { 61 | console.log('inline session supported') 62 | } 63 | else {console.log('inline not supported')}; 64 | }) 65 | } 66 | }) 67 | .catch((reason) => { 68 | console.log('WebXR not supported: ' + reason); 69 | }); 70 | } 71 | 72 | function onRequestSession() { 73 | console.log("requesting session"); 74 | navigator.xr.requestSession('immersive-ar', {requiredFeatures: ['viewer', 'local']}) 75 | .then(onSessionStarted) 76 | .catch((reason) => { 77 | console.log('request disabled: ' + reason); 78 | }); 79 | } 80 | 81 | function onSessionStarted(session) { 82 | console.log('starting session'); 83 | btn.removeEventListener('click', onRequestSession); 84 | btn.addEventListener('click', endXRSession); 85 | btn.innerHTML = "STOP AR"; 86 | xrSession = session; 87 | xrSession.addEventListener("end", onSessionEnd); 88 | setupWebGLLayer() 89 | .then(()=> { 90 | renderer.xr.setReferenceSpaceType('local'); 91 | renderer.xr.setSession(xrSession); 92 | animate(); 93 | }) 94 | } 95 | 96 | function setupWebGLLayer() { 97 | return gl.makeXRCompatible().then(() => { 98 | xrSession.updateRenderState( {baseLayer: new XRWebGLLayer(xrSession, gl) }); 99 | }); 100 | } 101 | 102 | function animate() { 103 | renderer.setAnimationLoop(render); 104 | } 105 | 106 | function render(time) { 107 | if (!xrSession) { 108 | renderer.clear(true, true, true); 109 | return; 110 | } else { 111 | time *= 0.001; 112 | cube.translateY(0.2 * Math.sin(time) / 100); 113 | cube.rotateY(Math.PI / 180); 114 | renderer.render(scene, camera); 115 | //renderer.render(scene, camera); 116 | } 117 | } 118 | 119 | function endXRSession() { 120 | if (xrSession) { 121 | console.log('ending session...'); 122 | xrSession.end().then(onSessionEnd); 123 | } 124 | } 125 | 126 | function onSessionEnd() { 127 | xrSession = null; 128 | console.log('session ended'); 129 | btn.innerHTML = "START AR"; 130 | btn.removeEventListener('click', endXRSession); 131 | btn.addEventListener('click', onRequestSession); 132 | } -------------------------------------------------------------------------------- /ch7_ex6/Part2_Hit-Test/hit_test.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three/build/three.module"; 2 | // global scene values 3 | var btn, gl, glCanvas, camera, scene, renderer; 4 | var controller, reticle; 5 | 6 | // global xr value 7 | var xrSession = null; 8 | var xrViewerPose; 9 | var hitTestSource = null; 10 | var hitTestSourceRequested = false; 11 | 12 | loadScene(); 13 | 14 | function loadScene() { 15 | // setup WebGL 16 | glCanvas = document.createElement('canvas'); 17 | gl = glCanvas.getContext('webgl', { antialias: true }); 18 | 19 | // setup Three.js scene 20 | camera = new THREE.PerspectiveCamera( 21 | 70, 22 | window.innerWidth / window.innerHeight, 23 | 0.01, 24 | 1000 25 | ); 26 | 27 | scene = new THREE.Scene(); 28 | // add hemisphere light 29 | var light = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 1 ); 30 | light.position.set( 0.5, 1, 0.25 ); 31 | scene.add( light ); 32 | 33 | 34 | // setup Three.js WebGL renderer 35 | renderer = new THREE.WebGLRenderer({ 36 | canvas: glCanvas, 37 | context: gl 38 | }); 39 | renderer.setPixelRatio( window.devicePixelRatio ); 40 | renderer.setSize( window.innerWidth, window.innerHeight ); 41 | renderer.xr.enabled = true; 42 | document.body.appendChild( renderer.domElement ); 43 | 44 | var geometry = new THREE.CylinderBufferGeometry(0.1, 0.1, 0.2, 32).translate(0, 0.1, 0); 45 | 46 | // controller click event listener 47 | function onSelect() { 48 | console.log("on select fired..."); 49 | var material = new THREE.MeshPhongMaterial( { color: 0xffffff * Math.random() } ); 50 | var mesh = new THREE.Mesh(geometry, material); 51 | mesh.applyMatrix4(reticle.matrix); // THIS IS A KEY FUNCTION 52 | mesh.scale.y = Math.random() * 2 + 1; // double value of random number then add 1 for height, why? 53 | scene.add(mesh); 54 | } 55 | 56 | // get controller WebXR Device API through Three.js 57 | controller = renderer.xr.getController(0); 58 | controller.addEventListener('select', onSelect); 59 | scene.add(controller); 60 | 61 | // reticle and reticle properties 62 | reticle = new THREE.Mesh( 63 | new THREE.RingBufferGeometry(0.15, 0.2, 32).rotateX(-Math.PI / 2), 64 | new THREE.MeshBasicMaterial({color: "#00FF00"}) 65 | ); 66 | 67 | reticle.matrixAutoUpdate = false; 68 | reticle.visible = false; 69 | scene.add(reticle); 70 | 71 | // begin xr query 72 | navigator.xr.isSessionSupported('immersive-ar') 73 | .then((supported) => { 74 | if (supported) { 75 | btn = document.createElement("button"); 76 | btn.addEventListener('click', onRequestSession); 77 | btn.innerHTML = "Enter XR"; 78 | var header = document.querySelector("header"); 79 | header.appendChild(btn); 80 | } 81 | else { 82 | navigator.xr.isSessionSupported('inline') 83 | .then((supported) => { 84 | if (supported) { 85 | console.log('inline session supported') 86 | } 87 | else {console.log('inline not supported')}; 88 | }) 89 | } 90 | }) 91 | .catch((reason) => { 92 | console.log('WebXR not supported: ' + reason); 93 | }); 94 | } 95 | 96 | // request immersive-ar session with hit-test 97 | function onRequestSession() { 98 | console.log("requesting session"); 99 | navigator.xr.requestSession('immersive-ar', {requiredFeatures: ['hit-test'], optionalFeatures: ['local-floor']}) 100 | .then(onSessionStarted) 101 | .catch((reason) => { 102 | console.log('request disabled: ' + reason); 103 | }); 104 | } 105 | 106 | function onSessionStarted(session) { 107 | console.log('starting session'); 108 | btn.removeEventListener('click', onRequestSession); 109 | btn.addEventListener('click', endXRSession); 110 | btn.innerHTML = "STOP AR"; 111 | xrSession = session; 112 | xrSession.addEventListener("end", endXRSession); 113 | setupWebGLLayer() 114 | .then(()=> { 115 | renderer.xr.setReferenceSpaceType('local'); 116 | renderer.xr.setSession(xrSession); 117 | animate(); 118 | }) 119 | } 120 | 121 | function setupWebGLLayer() { 122 | return gl.makeXRCompatible().then(() => { 123 | xrSession.updateRenderState( {baseLayer: new XRWebGLLayer(xrSession, gl) }); 124 | }); 125 | } 126 | 127 | function animate() { 128 | renderer.setAnimationLoop(render); 129 | } 130 | 131 | function render(time, frame) { 132 | if (frame) { 133 | var referenceSpace = renderer.xr.getReferenceSpace('local'); 134 | var session = frame.session; 135 | xrViewerPose = frame.getViewerPose(referenceSpace); 136 | if (hitTestSourceRequested === false) { 137 | session.requestReferenceSpace("viewer").then((referenceSpace) => { 138 | session.requestHitTestSource({space: referenceSpace}) 139 | .then((source) => { 140 | hitTestSource = source; 141 | }) 142 | }); 143 | 144 | session.addEventListener("end", () => { 145 | hitTestSourceRequested = false; 146 | hitTestSource = null; 147 | }); 148 | } 149 | 150 | if (hitTestSource) { 151 | var hitTestResults = frame.getHitTestResults(hitTestSource); 152 | 153 | if (hitTestResults.length > 0) { 154 | var hit = hitTestResults[0]; 155 | reticle.visible = true; 156 | reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix); 157 | } else { 158 | reticle.visible = false; 159 | } 160 | } 161 | } 162 | 163 | renderer.render(scene, camera); 164 | } 165 | 166 | function endXRSession() { 167 | if (xrSession) { 168 | xrSession.end() 169 | .then(()=> { 170 | xrSession.ended = true; 171 | onSessionEnd(); 172 | }) 173 | .catch((reason) => { 174 | console.log('session not ended because ' + reason); 175 | onSessionEnd(); 176 | }) 177 | } 178 | else {onSessionEnd();} 179 | } 180 | 181 | function onSessionEnd() { 182 | xrSession = null; 183 | console.log('session ended'); 184 | btn.innerHTML = "START AR"; 185 | btn.removeEventListener('click', endXRSession); 186 | btn.addEventListener('click', onRequestSession); 187 | window.requestAnimationFrame(render); 188 | } -------------------------------------------------------------------------------- /ch7_ex6/Part2_Hit-Test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebXR API: Ch. 7 Ex. 6 Pt. 2 7 | 10 | 11 | 12 |
13 |

WebXR Hit-Testing w/ Spatial Anchors

14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch8_Ex7_Parts_1_2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebXR API / A-Frame: Ch.8 Ex.7 Pts.1 & 2 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 35 | -------------------------------------------------------------------------------- /ch8_Ex7_Parts_1_2/textures/brick_mat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_1_2/textures/brick_mat.jpg -------------------------------------------------------------------------------- /ch8_Ex7_Parts_1_2/textures/grass-nm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_1_2/textures/grass-nm.jpg -------------------------------------------------------------------------------- /ch8_Ex7_Parts_1_2/textures/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_1_2/textures/grass.jpg -------------------------------------------------------------------------------- /ch8_Ex7_Parts_3_4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebXR API / A-Frame: Ch.8 Ex.7 Pts. 3 & 4 7 | 8 | 9 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 64 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /ch8_Ex7_Parts_3_4/textures/brick_mat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_3_4/textures/brick_mat.jpg -------------------------------------------------------------------------------- /ch8_Ex7_Parts_3_4/textures/grass-nm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_3_4/textures/grass-nm.jpg -------------------------------------------------------------------------------- /ch8_Ex7_Parts_3_4/textures/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/ar-vr-using-webxr-api/e7b459196948a4729e8b1af48faffd3477ab7292/ch8_Ex7_Parts_3_4/textures/grass.jpg -------------------------------------------------------------------------------- /ch9_ex8/assets/oculus-touch-controller-left.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'oculus-touch-controller-left.blend' 2 | # Material Count: 7 3 | 4 | newmtl body 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd external_controller01_col.png 14 | 15 | newmtl buttonHand 16 | Ns 96.078431 17 | Ka 1.000000 1.000000 1.000000 18 | Kd 0.640000 0.640000 0.640000 19 | Ks 0.500000 0.500000 0.500000 20 | Ke 0.000000 0.000000 0.000000 21 | Ni 1.000000 22 | d 1.000000 23 | illum 2 24 | map_Kd external_controller01_col.png 25 | 26 | newmtl buttonMenu 27 | Ns 96.078431 28 | Ka 1.000000 1.000000 1.000000 29 | Kd 0.640000 0.640000 0.640000 30 | Ks 0.500000 0.500000 0.500000 31 | Ke 0.000000 0.000000 0.000000 32 | Ni 1.000000 33 | d 1.000000 34 | illum 2 35 | map_Kd external_controller01_col.png 36 | 37 | newmtl buttonTrigger 38 | Ns 96.078431 39 | Ka 1.000000 1.000000 1.000000 40 | Kd 0.640000 0.640000 0.640000 41 | Ks 0.500000 0.500000 0.500000 42 | Ke 0.000000 0.000000 0.000000 43 | Ni 1.000000 44 | d 1.000000 45 | illum 2 46 | map_Kd external_controller01_col.png 47 | 48 | newmtl buttonX 49 | Ns 96.078431 50 | Ka 1.000000 1.000000 1.000000 51 | Kd 0.640000 0.640000 0.640000 52 | Ks 0.500000 0.500000 0.500000 53 | Ke 0.000000 0.000000 0.000000 54 | Ni 1.000000 55 | d 1.000000 56 | illum 2 57 | map_Kd external_controller01_col.png 58 | 59 | newmtl buttonY 60 | Ns 96.078431 61 | Ka 1.000000 1.000000 1.000000 62 | Kd 0.640000 0.640000 0.640000 63 | Ks 0.500000 0.500000 0.500000 64 | Ke 0.000000 0.000000 0.000000 65 | Ni 1.000000 66 | d 1.000000 67 | illum 2 68 | map_Kd external_controller01_col.png 69 | 70 | newmtl stick 71 | Ns 96.078431 72 | Ka 1.000000 1.000000 1.000000 73 | Kd 0.640000 0.640000 0.640000 74 | Ks 0.500000 0.500000 0.500000 75 | Ke 0.000000 0.000000 0.000000 76 | Ni 1.000000 77 | d 1.000000 78 | illum 2 79 | map_Kd external_controller01_col.png 80 | -------------------------------------------------------------------------------- /ch9_ex8/assets/oculus-touch-controller-right.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'oculus-touch-controller.right.blend' 2 | # Material Count: 7 3 | 4 | newmtl body 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd external_controller01_col.png 14 | 15 | newmtl buttonA 16 | Ns 96.078431 17 | Ka 1.000000 1.000000 1.000000 18 | Kd 0.640000 0.640000 0.640000 19 | Ks 0.500000 0.500000 0.500000 20 | Ke 0.000000 0.000000 0.000000 21 | Ni 1.000000 22 | d 1.000000 23 | illum 2 24 | map_Kd external_controller01_col.png 25 | 26 | newmtl buttonB 27 | Ns 96.078431 28 | Ka 1.000000 1.000000 1.000000 29 | Kd 0.640000 0.640000 0.640000 30 | Ks 0.500000 0.500000 0.500000 31 | Ke 0.000000 0.000000 0.000000 32 | Ni 1.000000 33 | d 1.000000 34 | illum 2 35 | map_Kd external_controller01_col.png 36 | 37 | newmtl buttonHand 38 | Ns 96.078431 39 | Ka 1.000000 1.000000 1.000000 40 | Kd 0.640000 0.640000 0.640000 41 | Ks 0.500000 0.500000 0.500000 42 | Ke 0.000000 0.000000 0.000000 43 | Ni 1.000000 44 | d 1.000000 45 | illum 2 46 | map_Kd external_controller01_col.png 47 | 48 | 49 | newmtl buttonHome 50 | Ns 96.078431 51 | Ka 1.000000 1.000000 1.000000 52 | Kd 0.640000 0.640000 0.640000 53 | Ks 0.500000 0.500000 0.500000 54 | Ke 0.000000 0.000000 0.000000 55 | Ni 1.000000 56 | d 1.000000 57 | illum 2 58 | map_Kd external_controller01_col.png 59 | 60 | newmtl buttonTrigger 61 | Ns 96.078431 62 | Ka 1.000000 1.000000 1.000000 63 | Kd 0.640000 0.640000 0.640000 64 | Ks 0.500000 0.500000 0.500000 65 | Ke 0.000000 0.000000 0.000000 66 | Ni 1.000000 67 | d 1.000000 68 | illum 2 69 | map_Kd external_controller01_col.png 70 | 71 | newmtl stick 72 | Ns 96.078431 73 | Ka 1.000000 1.000000 1.000000 74 | Kd 0.640000 0.640000 0.640000 75 | Ks 0.500000 0.500000 0.500000 76 | Ke 0.000000 0.000000 0.000000 77 | Ni 1.000000 78 | d 1.000000 79 | illum 2 80 | map_Kd external_controller01_col.png 81 | -------------------------------------------------------------------------------- /ch9_ex8/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | A-Frame: Physics, Ex. 8 -- Part 1 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /ch9_ex8/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "aframe": { 6 | "version": "1.0.4", 7 | "resolved": "https://registry.npmjs.org/aframe/-/aframe-1.0.4.tgz", 8 | "integrity": "sha512-iG/4VyRt22zUPxDsFjP4SHUXNPGIStM2hHX/iPblht6dtN8m09e7LAaFq4iQdXoT0EkZBWEVmXVBF1J7Tca3QQ==", 9 | "requires": { 10 | "custom-event-polyfill": "^1.0.6", 11 | "debug": "github:ngokevin/debug#noTimestamp", 12 | "deep-assign": "^2.0.0", 13 | "document-register-element": "github:dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90", 14 | "load-bmfont": "^1.2.3", 15 | "object-assign": "^4.0.1", 16 | "present": "0.0.6", 17 | "promise-polyfill": "^3.1.0", 18 | "super-animejs": "^3.1.0", 19 | "super-three": "^0.111.6", 20 | "three-bmfont-text": "github:dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", 21 | "webvr-polyfill": "^0.10.10" 22 | } 23 | }, 24 | "aframe-physics-system": { 25 | "version": "4.0.1", 26 | "resolved": "https://registry.npmjs.org/aframe-physics-system/-/aframe-physics-system-4.0.1.tgz", 27 | "integrity": "sha512-KzgWd9sCdxI+bbLNwHHIkXMDH9Z8G/w3l4z2cfdbM0JusQ5giHMq/ONVmLJXNm1YZyE+QSfsE+YwjCLnJyE25w==", 28 | "requires": { 29 | "ammo-debug-drawer": "github:infinitelee/ammo-debug-drawer", 30 | "cannon": "github:donmccurdy/cannon.js#v0.6.2-dev1", 31 | "three-to-ammo": "github:infinitelee/three-to-ammo", 32 | "three-to-cannon": "^1.3.0", 33 | "webworkify": "^1.4.0" 34 | } 35 | }, 36 | "ammo-debug-drawer": { 37 | "version": "github:infinitelee/ammo-debug-drawer#561fd698109e61456f34136a53dd08b45d4ad9ca", 38 | "from": "github:infinitelee/ammo-debug-drawer" 39 | }, 40 | "an-array": { 41 | "version": "1.0.0", 42 | "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz", 43 | "integrity": "sha1-wSWlu4JXd4419LT2qpx9D6nkJmU=" 44 | }, 45 | "array-shuffle": { 46 | "version": "1.0.1", 47 | "resolved": "https://registry.npmjs.org/array-shuffle/-/array-shuffle-1.0.1.tgz", 48 | "integrity": "sha1-fqSIKjVrS8pfVF4LblLq9tlxVXo=" 49 | }, 50 | "as-number": { 51 | "version": "1.0.0", 52 | "resolved": "https://registry.npmjs.org/as-number/-/as-number-1.0.0.tgz", 53 | "integrity": "sha1-rLJ+NPj52KsNqeN287iVmGD4CmY=" 54 | }, 55 | "buffer-equal": { 56 | "version": "0.0.1", 57 | "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", 58 | "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" 59 | }, 60 | "buffer-to-arraybuffer": { 61 | "version": "0.0.5", 62 | "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", 63 | "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" 64 | }, 65 | "cannon": { 66 | "version": "github:donmccurdy/cannon.js#022e8ba53fa83abf0ad8a0e4fd08623123838a17", 67 | "from": "github:donmccurdy/cannon.js#v0.6.2-dev1" 68 | }, 69 | "cardboard-vr-display": { 70 | "version": "1.0.19", 71 | "resolved": "https://registry.npmjs.org/cardboard-vr-display/-/cardboard-vr-display-1.0.19.tgz", 72 | "integrity": "sha512-+MjcnWKAkb95p68elqZLDPzoiF/dGncQilLGvPBM5ZorABp/ao3lCs7nnRcYBckmuNkg1V/5rdGDKoUaCVsHzQ==", 73 | "requires": { 74 | "gl-preserve-state": "^1.0.0", 75 | "nosleep.js": "^0.7.0", 76 | "webvr-polyfill-dpdb": "^1.0.17" 77 | } 78 | }, 79 | "custom-event-polyfill": { 80 | "version": "1.0.7", 81 | "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", 82 | "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" 83 | }, 84 | "debug": { 85 | "version": "github:ngokevin/debug#ef5f8e66d49ce8bc64c6f282c15f8b7164409e3a", 86 | "from": "github:ngokevin/debug#noTimestamp" 87 | }, 88 | "decode-uri-component": { 89 | "version": "0.2.0", 90 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 91 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 92 | }, 93 | "decompress-response": { 94 | "version": "3.3.0", 95 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 96 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 97 | "requires": { 98 | "mimic-response": "^1.0.0" 99 | } 100 | }, 101 | "deep-assign": { 102 | "version": "2.0.0", 103 | "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-2.0.0.tgz", 104 | "integrity": "sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI=", 105 | "requires": { 106 | "is-obj": "^1.0.0" 107 | } 108 | }, 109 | "document-register-element": { 110 | "version": "github:dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90", 111 | "from": "github:dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90" 112 | }, 113 | "dom-walk": { 114 | "version": "0.1.2", 115 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", 116 | "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" 117 | }, 118 | "dtype": { 119 | "version": "2.0.0", 120 | "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", 121 | "integrity": "sha1-zQUjI84GFETs0uj1dI9popvihDQ=" 122 | }, 123 | "flatten-vertex-data": { 124 | "version": "1.0.2", 125 | "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz", 126 | "integrity": "sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==", 127 | "requires": { 128 | "dtype": "^2.0.0" 129 | } 130 | }, 131 | "gl-preserve-state": { 132 | "version": "1.0.0", 133 | "resolved": "https://registry.npmjs.org/gl-preserve-state/-/gl-preserve-state-1.0.0.tgz", 134 | "integrity": "sha512-zQZ25l3haD4hvgJZ6C9+s0ebdkW9y+7U2qxvGu1uWOJh8a4RU+jURIKEQhf8elIlFpMH6CrAY2tH0mYrRjet3Q==" 135 | }, 136 | "global": { 137 | "version": "4.3.2", 138 | "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", 139 | "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", 140 | "requires": { 141 | "min-document": "^2.19.0", 142 | "process": "~0.5.1" 143 | } 144 | }, 145 | "inherits": { 146 | "version": "2.0.4", 147 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 148 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 149 | }, 150 | "is-buffer": { 151 | "version": "1.1.6", 152 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 153 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 154 | }, 155 | "is-function": { 156 | "version": "1.0.2", 157 | "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", 158 | "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" 159 | }, 160 | "is-obj": { 161 | "version": "1.0.1", 162 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", 163 | "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" 164 | }, 165 | "layout-bmfont-text": { 166 | "version": "1.3.4", 167 | "resolved": "https://registry.npmjs.org/layout-bmfont-text/-/layout-bmfont-text-1.3.4.tgz", 168 | "integrity": "sha1-8g8sVGR3T0jabOipl/vObUaUW4E=", 169 | "requires": { 170 | "as-number": "^1.0.0", 171 | "word-wrapper": "^1.0.7", 172 | "xtend": "^4.0.0" 173 | } 174 | }, 175 | "load-bmfont": { 176 | "version": "1.4.1", 177 | "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", 178 | "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", 179 | "requires": { 180 | "buffer-equal": "0.0.1", 181 | "mime": "^1.3.4", 182 | "parse-bmfont-ascii": "^1.0.3", 183 | "parse-bmfont-binary": "^1.0.5", 184 | "parse-bmfont-xml": "^1.1.4", 185 | "phin": "^2.9.1", 186 | "xhr": "^2.0.1", 187 | "xtend": "^4.0.0" 188 | } 189 | }, 190 | "map-limit": { 191 | "version": "0.0.1", 192 | "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", 193 | "integrity": "sha1-63lhAxwPDo0AG/LVb6toXViCLzg=", 194 | "requires": { 195 | "once": "~1.3.0" 196 | } 197 | }, 198 | "mime": { 199 | "version": "1.6.0", 200 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 201 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 202 | }, 203 | "mimic-response": { 204 | "version": "1.0.1", 205 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 206 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" 207 | }, 208 | "min-document": { 209 | "version": "2.19.0", 210 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", 211 | "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", 212 | "requires": { 213 | "dom-walk": "^0.1.0" 214 | } 215 | }, 216 | "minimist": { 217 | "version": "1.2.5", 218 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 219 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 220 | }, 221 | "new-array": { 222 | "version": "1.0.0", 223 | "resolved": "https://registry.npmjs.org/new-array/-/new-array-1.0.0.tgz", 224 | "integrity": "sha1-XbxjnZYerH8an7wacUbsEvKST78=" 225 | }, 226 | "nice-color-palettes": { 227 | "version": "1.0.1", 228 | "resolved": "https://registry.npmjs.org/nice-color-palettes/-/nice-color-palettes-1.0.1.tgz", 229 | "integrity": "sha1-h16gHchu+uf1leBmqLJmDnIGBT4=", 230 | "requires": { 231 | "map-limit": "0.0.1", 232 | "minimist": "^1.2.0", 233 | "new-array": "^1.0.0", 234 | "xhr-request": "^1.0.1" 235 | } 236 | }, 237 | "nosleep.js": { 238 | "version": "0.7.0", 239 | "resolved": "https://registry.npmjs.org/nosleep.js/-/nosleep.js-0.7.0.tgz", 240 | "integrity": "sha1-z9kZwlUjyg0PSmn7MwXAg62u4ok=" 241 | }, 242 | "object-assign": { 243 | "version": "4.1.1", 244 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 245 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 246 | }, 247 | "once": { 248 | "version": "1.3.3", 249 | "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", 250 | "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", 251 | "requires": { 252 | "wrappy": "1" 253 | } 254 | }, 255 | "parse-bmfont-ascii": { 256 | "version": "1.0.6", 257 | "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", 258 | "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" 259 | }, 260 | "parse-bmfont-binary": { 261 | "version": "1.0.6", 262 | "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", 263 | "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" 264 | }, 265 | "parse-bmfont-xml": { 266 | "version": "1.1.4", 267 | "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", 268 | "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", 269 | "requires": { 270 | "xml-parse-from-string": "^1.0.0", 271 | "xml2js": "^0.4.5" 272 | } 273 | }, 274 | "parse-headers": { 275 | "version": "2.0.3", 276 | "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", 277 | "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" 278 | }, 279 | "phin": { 280 | "version": "2.9.3", 281 | "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", 282 | "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" 283 | }, 284 | "present": { 285 | "version": "0.0.6", 286 | "resolved": "https://registry.npmjs.org/present/-/present-0.0.6.tgz", 287 | "integrity": "sha1-nu/3ANqp6ZhhM1Lkf3rCMk1PrwI=" 288 | }, 289 | "process": { 290 | "version": "0.5.2", 291 | "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", 292 | "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" 293 | }, 294 | "promise-polyfill": { 295 | "version": "3.1.0", 296 | "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-3.1.0.tgz", 297 | "integrity": "sha1-YpUrAdBZsRW0MnY7fvRhuA9t9H0=" 298 | }, 299 | "quad-indices": { 300 | "version": "2.0.1", 301 | "resolved": "https://registry.npmjs.org/quad-indices/-/quad-indices-2.0.1.tgz", 302 | "integrity": "sha1-ppQdiaE9Y+7WwdSlpiGgRjYXqBQ=", 303 | "requires": { 304 | "an-array": "^1.0.0", 305 | "dtype": "^2.0.0", 306 | "is-buffer": "^1.0.2" 307 | } 308 | }, 309 | "query-string": { 310 | "version": "5.1.1", 311 | "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", 312 | "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", 313 | "requires": { 314 | "decode-uri-component": "^0.2.0", 315 | "object-assign": "^4.1.0", 316 | "strict-uri-encode": "^1.0.0" 317 | } 318 | }, 319 | "sax": { 320 | "version": "1.2.4", 321 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 322 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 323 | }, 324 | "simple-concat": { 325 | "version": "1.0.1", 326 | "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", 327 | "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" 328 | }, 329 | "simple-get": { 330 | "version": "2.8.1", 331 | "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", 332 | "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", 333 | "requires": { 334 | "decompress-response": "^3.3.0", 335 | "once": "^1.3.1", 336 | "simple-concat": "^1.0.0" 337 | } 338 | }, 339 | "strict-uri-encode": { 340 | "version": "1.1.0", 341 | "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", 342 | "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" 343 | }, 344 | "super-animejs": { 345 | "version": "3.1.0", 346 | "resolved": "https://registry.npmjs.org/super-animejs/-/super-animejs-3.1.0.tgz", 347 | "integrity": "sha512-6MFAFJDRuvwkovxQZPruuyHinTa4rgj4hNLOndjcYYhZLckoXtVRY9rJPuq8p6c/tgZJrFYEAYAfJ2/hhNtUCA==" 348 | }, 349 | "super-three": { 350 | "version": "0.111.6", 351 | "resolved": "https://registry.npmjs.org/super-three/-/super-three-0.111.6.tgz", 352 | "integrity": "sha512-/OJTOBpmm7MRx8R0G5Zr9sX8EqsELy7SwATb5n0FP145QsrP134pY2W489sfkJYqZmGkpHmG1ulQ0M94icThBw==" 353 | }, 354 | "three-bmfont-text": { 355 | "version": "github:dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", 356 | "from": "github:dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", 357 | "requires": { 358 | "array-shuffle": "^1.0.1", 359 | "inherits": "^2.0.1", 360 | "layout-bmfont-text": "^1.2.0", 361 | "nice-color-palettes": "^1.0.1", 362 | "object-assign": "^4.0.1", 363 | "quad-indices": "^2.0.1", 364 | "three-buffer-vertex-data": "github:dmarcos/three-buffer-vertex-data#69378fc58daf27d3b1d930df9f233473e4a4818c" 365 | } 366 | }, 367 | "three-buffer-vertex-data": { 368 | "version": "github:dmarcos/three-buffer-vertex-data#69378fc58daf27d3b1d930df9f233473e4a4818c", 369 | "from": "github:dmarcos/three-buffer-vertex-data#69378fc58daf27d3b1d930df9f233473e4a4818c", 370 | "requires": { 371 | "flatten-vertex-data": "^1.0.0" 372 | } 373 | }, 374 | "three-to-ammo": { 375 | "version": "github:infinitelee/three-to-ammo#a15da9afc16b834f6c1906ab94e0ab3071e9ff09", 376 | "from": "github:infinitelee/three-to-ammo" 377 | }, 378 | "three-to-cannon": { 379 | "version": "1.4.1", 380 | "resolved": "https://registry.npmjs.org/three-to-cannon/-/three-to-cannon-1.4.1.tgz", 381 | "integrity": "sha512-AhaDXAqRg48wYBjMGo/Nxl0o67sW4/nGN3yIIfxMkQwL5nYLaLVnkz6aQNpn1vNNKuqHhqLFCZR7qSnSXzhhog==" 382 | }, 383 | "timed-out": { 384 | "version": "4.0.1", 385 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 386 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" 387 | }, 388 | "url-set-query": { 389 | "version": "1.0.0", 390 | "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", 391 | "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" 392 | }, 393 | "webvr-polyfill": { 394 | "version": "0.10.12", 395 | "resolved": "https://registry.npmjs.org/webvr-polyfill/-/webvr-polyfill-0.10.12.tgz", 396 | "integrity": "sha512-trDJEVUQnRIVAnmImjEQ0BlL1NfuWl8+eaEdu+bs4g59c7OtETi/5tFkgEFDRaWEYwHntXs/uFF3OXZuutNGGA==", 397 | "requires": { 398 | "cardboard-vr-display": "^1.0.19" 399 | } 400 | }, 401 | "webvr-polyfill-dpdb": { 402 | "version": "1.0.17", 403 | "resolved": "https://registry.npmjs.org/webvr-polyfill-dpdb/-/webvr-polyfill-dpdb-1.0.17.tgz", 404 | "integrity": "sha512-WOd4s0gSrb0fOlOtIpqFbwLBATax/ka7DFAB/u+C9KJBBJk1/x/FZlFynOqsNrUxMJniOdO7ViFJwVdMScMQzA==" 405 | }, 406 | "webworkify": { 407 | "version": "1.5.0", 408 | "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", 409 | "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" 410 | }, 411 | "word-wrapper": { 412 | "version": "1.0.7", 413 | "resolved": "https://registry.npmjs.org/word-wrapper/-/word-wrapper-1.0.7.tgz", 414 | "integrity": "sha1-HxSv6/Zt/fD+9V79NxhO+9CMKLY=" 415 | }, 416 | "wrappy": { 417 | "version": "1.0.2", 418 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 419 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 420 | }, 421 | "xhr": { 422 | "version": "2.5.0", 423 | "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", 424 | "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", 425 | "requires": { 426 | "global": "~4.3.0", 427 | "is-function": "^1.0.1", 428 | "parse-headers": "^2.0.0", 429 | "xtend": "^4.0.0" 430 | } 431 | }, 432 | "xhr-request": { 433 | "version": "1.1.0", 434 | "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", 435 | "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", 436 | "requires": { 437 | "buffer-to-arraybuffer": "^0.0.5", 438 | "object-assign": "^4.1.1", 439 | "query-string": "^5.0.1", 440 | "simple-get": "^2.7.0", 441 | "timed-out": "^4.0.1", 442 | "url-set-query": "^1.0.0", 443 | "xhr": "^2.0.4" 444 | } 445 | }, 446 | "xml-parse-from-string": { 447 | "version": "1.0.1", 448 | "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", 449 | "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" 450 | }, 451 | "xml2js": { 452 | "version": "0.4.23", 453 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 454 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 455 | "requires": { 456 | "sax": ">=0.6.0", 457 | "xmlbuilder": "~11.0.0" 458 | } 459 | }, 460 | "xmlbuilder": { 461 | "version": "11.0.1", 462 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 463 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 464 | }, 465 | "xtend": { 466 | "version": "4.0.2", 467 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 468 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 469 | } 470 | } 471 | } 472 | -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *AR and VR Using the WebXR API* 2 | 3 | On **page xx** [Summary of error]: 4 | 5 | Details of error here. Highlight key pieces in **bold**. 6 | 7 | *** 8 | 9 | On **page xx** [Summary of error]: 10 | 11 | Details of error here. Highlight key pieces in **bold**. 12 | 13 | *** --------------------------------------------------------------------------------