diff --git a/.gitignore b/.gitignore index b97935f..e86354a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules *.vscode .DS_Store +.idea diff --git a/README.md b/README.md index a828647..7195d02 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,38 @@ The plugin was developed for [Tzina: A Symphony of Longing](https://tzina.space) ![DepthKit.js screencapture](https://raw.githubusercontent.com/juniorxsound/DepthKit.js/master/assets/gh/wire.gif) -Include ```depthkit.js``` or ```depthkit.min.js``` after loading ```three.js``` in your project. - -Alternatively, if you use Node.js you can install the package with npm using ```npm install depthkit``` [npm package](https://www.npmjs.com/package/depthkit) +# Install + +## Install via NPM + +`npm i dephtkit` and then `import { DepthKit } from 'depthkit'` +See [npm package](https://www.npmjs.com/package/depthkit). + +## Install from CDN - es module (es6) + +```html + + + + + +``` ### Creating a character ```JavaScript @@ -45,18 +74,13 @@ Calling ```new DepthKit()``` returns a three.js Object3D which has all the regul [Mouse hover example](https://juniorxsound.github.io/Depthkit.js/examples/raycast.html) -[Simple webVR example](https://juniorxsound.github.io/Depthkit.js/examples/webvr_simple.html) - -[Raycasting webVR example](https://juniorxsound.github.io/Depthkit.js/examples/webvr_raycast.html) +[Raycasting webVR example](https://juniorxsound.github.io/Depthkit.js/examples/webxr_raycast.html) ## How to contribute: 1. Fork/Clone/Download -1. Install all dependcies using ```npm install``` -1. Use the following node commands: - -```npm run start``` uses ```concurrently``` to start an ```http-server``` and to run ```watchify``` and bundle on every change to ```build/depthkit.js``` - -```npm run build``` to bundle and minify to ```build/depthkit.min.js``` +1. Install all dependencies using `npm install` +1. Start http server : `npm run start` +1. Open http://localhost:8080/examples/simple.html ## Thanks Originally written by [@mrdoob](https://github.com/mrdoob) and [@obviousjim](https://github.com/obviousjim) ported and modified by [@juniorxsound](https://github.com/juniorxsound) and [@avnerus](https://github.com/Avnerus). Special thank you to [Shirin Anlen](https://github.com/ShirinStar) and all the Tzina crew, [@ZEEEVE](https://github.com/zivschneider), [@jhclaura](https://github.com/jhclaura) diff --git a/build/depthkit.js b/build/depthkit.js deleted file mode 100644 index 107c9ee..0000000 --- a/build/depthkit.js +++ /dev/null @@ -1,379 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0 && arguments[0] !== undefined ? arguments[0] : 'mesh'; - - var _props = arguments[1]; - - var _this = this; - - var _movie = arguments[2]; - var _poster = arguments[3]; - - _classCallCheck(this, DepthKit); - - //Load the shaders - var rgbdFrag = glsl(["#define GLSLIFY 1\nuniform sampler2D map;\nuniform float opacity;\n\nuniform float uvdy;\nuniform float uvdx;\n\nvarying float visibility;\nvarying vec2 vUv;\nvarying vec3 vNormal;\nvarying vec3 vPos;\n\nvoid main() {\n\n if ( visibility < 0.9 ) discard;\n\n vec4 color = texture2D(map, vUv);\n color.w = opacity;\n\n gl_FragColor = color;\n \n}"]); - var rgbdVert = glsl(["#define GLSLIFY 1\nuniform float mindepth;\nuniform float maxdepth;\n\nuniform float width;\nuniform float height;\n\nuniform bool isPoints;\nuniform float pointSize;\n\nuniform float time;\n\nuniform vec2 focalLength;\nuniform vec2 principalPoint;\nuniform vec2 imageDimensions;\nuniform vec4 crop;\nuniform vec2 meshDensity;\nuniform mat4 extrinsics;\n\nvarying vec3 vNormal;\nvarying vec3 vPos;\n\nuniform sampler2D map;\n\nvarying float visibility;\nvarying vec2 vUv;\n\nconst float _DepthSaturationThreshhold = 0.5; //a given pixel whose saturation is less than half will be culled (old default was .5)\nconst float _DepthBrightnessThreshold = 0.5; //a given pixel whose brightness is less than half will be culled (old default was .9)\nconst float _Epsilon = .03;\n\nvec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + _Epsilon)), d / (q.x + _Epsilon), q.x);\n}\n\nfloat depthForPoint(vec2 texturePoint)\n{\n vec4 depthsample = texture2D(map, texturePoint);\n vec3 depthsamplehsv = rgb2hsv(depthsample.rgb);\n return depthsamplehsv.g > _DepthSaturationThreshhold && depthsamplehsv.b > _DepthBrightnessThreshold ? depthsamplehsv.r : 0.0;\n}\n\nvoid main() {\n vec4 texSize = vec4(1.0 / width, 1.0 / height, width, height);\n\n vec2 centerpix = texSize.xy * .5;\n vec2 textureStep = 1.0 / meshDensity;\n vec2 basetex = floor(position.xy * textureStep * texSize.zw) * texSize.xy;\n vec2 imageCoordinates = crop.xy + (basetex * crop.zw);\n basetex.y = 1.0 - basetex.y;\n\n vec2 depthTexCoord = basetex * vec2(1.0, 0.5) + centerpix;\n vec2 colorTexCoord = basetex * vec2(1.0, 0.5) + vec2(0.0, 0.5) + centerpix;\n\n vUv = colorTexCoord;\n vPos = (modelMatrix * vec4(position, 1.0 )).xyz;\n vNormal = normalMatrix * normal;\n\n //check neighbors\n //texture coords come in as [0.0 - 1.0] for this whole plane\n float depth = depthForPoint(depthTexCoord);\n\n float neighborDepths[8];\n neighborDepths[0] = depthForPoint(depthTexCoord + vec2(0.0, textureStep.y));\n neighborDepths[1] = depthForPoint(depthTexCoord + vec2(textureStep.x, 0.0));\n neighborDepths[2] = depthForPoint(depthTexCoord + vec2(0.0, -textureStep.y));\n neighborDepths[3] = depthForPoint(depthTexCoord + vec2(-textureStep.x, 0.0));\n neighborDepths[4] = depthForPoint(depthTexCoord + vec2(-textureStep.x, -textureStep.y));\n neighborDepths[5] = depthForPoint(depthTexCoord + vec2(textureStep.x, textureStep.y));\n neighborDepths[6] = depthForPoint(depthTexCoord + vec2(textureStep.x, -textureStep.y));\n neighborDepths[7] = depthForPoint(depthTexCoord + vec2(-textureStep.x, textureStep.y));\n\n visibility = 1.0;\n int numDudNeighbors = 0;\n //search neighbor verts in order to see if we are near an edge\n //if so, clamp to the surface closest to us\n if (depth < _Epsilon || (1.0 - depth) < _Epsilon)\n {\n // float depthDif = 1.0;\n float nearestDepth = 1.0;\n for (int i = 0; i < 8; i++)\n {\n float depthNeighbor = neighborDepths[i];\n if (depthNeighbor >= _Epsilon && (1.0 - depthNeighbor) > _Epsilon)\n {\n // float thisDif = abs(nearestDepth - depthNeighbor);\n if (depthNeighbor < nearestDepth)\n {\n // depthDif = thisDif;\n nearestDepth = depthNeighbor;\n }\n }\n else\n {\n numDudNeighbors++;\n }\n }\n\n depth = nearestDepth;\n visibility = 0.8;\n\n // blob filter\n if (numDudNeighbors > 6)\n {\n visibility = 0.0;\n }\n }\n\n // internal edge filter\n float maxDisparity = 0.0;\n for (int i = 0; i < 8; i++)\n {\n float depthNeighbor = neighborDepths[i];\n if (depthNeighbor >= _Epsilon && (1.0 - depthNeighbor) > _Epsilon)\n {\n maxDisparity = max(maxDisparity, abs(depth - depthNeighbor));\n }\n }\n visibility *= 1.0 - maxDisparity;\n\n float z = depth * (maxdepth - mindepth) + mindepth;\n vec4 worldPos = extrinsics * vec4((imageCoordinates * imageDimensions - principalPoint) * z / focalLength, z, 1.0);\n worldPos.w = 1.0;\n\n gl_Position = projectionMatrix * modelViewMatrix * worldPos;\n}"]); - - //Crate video element - this.video = document.createElement('video'); - - //Set the crossOrigin and props - this.video.id = 'depthkit-video'; - this.video.crossOrigin = 'anonymous'; - this.video.setAttribute('crossorigin', 'anonymous'); - this.video.setAttribute('webkit-playsinline', 'webkit-playsinline'); - this.video.setAttribute('playsinline', 'playsinline'); - this.video.src = _movie; - this.video.poster = _poster; - - //Don't autostart don't loop - this.video.autoplay = true; - this.video.loop = false; - this.video.muted = true; - this.video.load(); - - //Create a video texture to be passed to the shader - this.videoTexture = new THREE.VideoTexture(this.video); - this.videoTexture.minFilter = THREE.NearestFilter; - this.videoTexture.magFilter = THREE.LinearFilter; - this.videoTexture.format = THREE.RGBAFormat; - this.videoTexture.generateMipmaps = false; - - //Manages loading of assets internally - this.manager = new THREE.LoadingManager(); - - //JSON props once loaded - this.props; - - //Geomtery - if (!DepthKit.geo) { - DepthKit.buildGeomtery(); - } - - //Material - this.material = new THREE.ShaderMaterial({ - uniforms: { - "map": { - type: "t", - value: this.videoTexture - }, - "time": { - type: "f", - value: 0.0 - }, - "mindepth": { - type: "f", - value: 0.0 - }, - "maxdepth": { - type: "f", - value: 0.0 - }, - "meshDensity": { - value: new THREE.Vector2(VERTS_WIDE, VERTS_TALL) - }, - "focalLength": { - value: new THREE.Vector2(1, 1) - }, - "principalPoint": { - value: new THREE.Vector2(1, 1) - }, - "imageDimensions": { - value: new THREE.Vector2(512, 828) - }, - "extrinsics": { - value: new THREE.Matrix4() - }, - "crop": { - value: new THREE.Vector4(0, 0, 1, 1) - }, - "width": { - type: "f", - value: 0 - }, - "height": { - type: "f", - value: 0 - }, - "opacity": { - type: "f", - value: 1.0 - }, - "isPoints": { - type: "b", - value: false - }, - "pointSize": { - type: "f", - value: 3.0 - } - }, - vertexShader: rgbdVert, - fragmentShader: rgbdFrag, - transparent: true - }); - - //Make the shader material double sided - this.material.side = THREE.DoubleSide; - - //Switch a few things based on selected rendering type and create the mesh - switch (_type) { - case 'wire': - this.material.wireframe = true; - this.mesh = new THREE.Mesh(DepthKit.geo, this.material); - break; - - case 'points': - this.material.uniforms.isPoints.value = true; - this.mesh = new THREE.Points(DepthKit.geo, this.material); - break; - - default: - this.mesh = new THREE.Mesh(DepthKit.geo, this.material); - break; - } - - //Make sure to read the config file as json (i.e JSON.parse) - this.jsonLoader = new THREE.FileLoader(this.manager); - this.jsonLoader.setResponseType('json'); - this.jsonLoader.load(_props, - // Function when json is loaded - function (data) { - _this.props = data; - // console.log(this.props); - - //Update the shader based on the properties from the JSON - _this.material.uniforms.width.value = _this.props.textureWidth; - _this.material.uniforms.height.value = _this.props.textureHeight; - _this.material.uniforms.mindepth.value = _this.props.nearClip; - _this.material.uniforms.maxdepth.value = _this.props.farClip; - _this.material.uniforms.focalLength.value = _this.props.depthFocalLength; - _this.material.uniforms.principalPoint.value = _this.props.depthPrincipalPoint; - _this.material.uniforms.imageDimensions.value = _this.props.depthImageSize; - _this.material.uniforms.crop.value = _this.props.crop; - - var ex = _this.props.extrinsics; - _this.material.uniforms.extrinsics.value.set(ex["e00"], ex["e10"], ex["e20"], ex["e30"], ex["e01"], ex["e11"], ex["e21"], ex["e31"], ex["e02"], ex["e12"], ex["e22"], ex["e32"], ex["e03"], ex["e13"], ex["e23"], ex["e33"]); - - //Create the collider - var boxGeo = new THREE.BoxGeometry(_this.props.boundsSize.x, _this.props.boundsSize.y, _this.props.boundsSize.z); - var boxMat = new THREE.MeshBasicMaterial({ - color: 0xffff00, - wireframe: true - }); - - _this.collider = new THREE.Mesh(boxGeo, boxMat); - - // this.collider.visible = false; - _this.mesh.add(_this.collider); - - //Temporary collider positioning fix - // TODO: fix that with this.props.boundsCenter - _this.collider.position.set(650, -200, -1900); - }); - - //Make sure we don't hide the character - this helps the objects in webVR - this.mesh.frustumCulled = false; - - //Apend the object to the Three Object3D that way it's accsesable from the instance - this.mesh.depthkit = this; - this.mesh.name = 'depthkit'; - - //Return the object3D so it could be added to the scene - return this.mesh; - } - - _createClass(DepthKit, [{ - key: 'setPointSize', - - - /* - * Render related methods - */ - value: function setPointSize(size) { - if (this.material.uniforms.isPoints.value) { - this.material.uniforms.pointSize.value = size; - } else { - console.warn('Can not set point size because the current character is not set to render points'); - } - } - }, { - key: 'setOpacity', - value: function setOpacity(opacity) { - this.material.uniforms.opacity.value = opacity; - } - }, { - key: 'setLineWidth', - value: function setLineWidth(width) { - if (this.material.wireframe) { - this.material.wireframeLinewidth = width; - } else { - console.warn('Can not set the line width because the current character is not set to render wireframe'); - } - } - - /* - * Video Player methods - */ - - }, { - key: 'play', - value: function play() { - if (!this.video.isPlaying) { - this.video.play(); - } else { - console.warn('Can not play because the character is already playing'); - } - } - }, { - key: 'stop', - value: function stop() { - this.video.currentTime = 0.0; - this.video.pause(); - } - }, { - key: 'pause', - value: function pause() { - this.video.pause(); - } - }, { - key: 'setLoop', - value: function setLoop(isLooping) { - this.video.loop = isLooping; - } - }, { - key: 'setVolume', - value: function setVolume(volume) { - this.video.volume = volume; - } - }, { - key: 'update', - value: function update(time) { - this.material.uniforms.time.value = time; - } - }, { - key: 'toggleColliderVisiblity', - value: function toggleColliderVisiblity() { - this.mesh.collider.visible = !this.mesh.collider.visible; - } - }, { - key: 'dispose', - value: function dispose() { - //Remove the mesh from the scene - try { - this.mesh.parent.remove(this.mesh); - } catch (e) { - console.warn(e); - } finally { - this.mesh.traverse(function (child) { - if (child.geometry !== undefined) { - child.geometry.dispose(); - child.material.dispose(); - } - }); - } - } - }], [{ - key: 'buildGeomtery', - value: function buildGeomtery() { - var geometry = new THREE.BufferGeometry(); - var verts = []; - var faces = []; - - for (var y = 0; y < VERTS_TALL; y++) { - for (var x = 0; x < VERTS_WIDE; x++) { - verts.push(x, y, 0); - } - } - for (var _y = 0; _y < VERTS_TALL - 1; _y++) { - for (var _x2 = 0; _x2 < VERTS_WIDE - 1; _x2++) { - faces.push(_x2 + _y * VERTS_WIDE, _x2 + (_y + 1) * VERTS_WIDE, _x2 + 1 + _y * VERTS_WIDE, _x2 + 1 + _y * VERTS_WIDE, _x2 + (_y + 1) * VERTS_WIDE, _x2 + 1 + (_y + 1) * VERTS_WIDE); - } - } - - // set the attributes of the geometry - geometry.setAttribute('position', new THREE.Float32BufferAttribute(verts, 3)); - geometry.setIndex(new THREE.Uint16BufferAttribute(faces, 1)); - - DepthKit.geo = geometry; - } - }]); - - return DepthKit; -}(); - -exports.default = DepthKit; - -},{"glslify":1}],3:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DepthKit = undefined; - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; //DepthKit.js class - - -var _depthkit = require('./depthkit'); - -var _depthkit2 = _interopRequireDefault(_depthkit); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -//Make it global -if (typeof window !== 'undefined' && _typeof(window.THREE) === 'object') { - window.DepthKit = _depthkit2.default; -} else { - console.warn('[DepthKit.js] It seems like THREE is not included in your code, try including it before DepthKit.js'); -} - -exports.DepthKit = _depthkit2.default; - -},{"./depthkit":2}]},{},[3]); diff --git a/build/depthkit.min.js b/build/depthkit.min.js deleted file mode 100644 index 52372a5..0000000 --- a/build/depthkit.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0&&arguments[0]!==undefined?arguments[0]:"mesh";var _props=arguments[1];var _this=this;var _movie=arguments[2];var _poster=arguments[3];_classCallCheck(this,DepthKit);var rgbdFrag=glsl(["#define GLSLIFY 1\nuniform sampler2D map;\nuniform float opacity;\n\nuniform float uvdy;\nuniform float uvdx;\n\nvarying float visibility;\nvarying vec2 vUv;\nvarying vec3 vNormal;\nvarying vec3 vPos;\n\nvoid main() {\n\n if ( visibility < 0.9 ) discard;\n\n vec4 color = texture2D(map, vUv);\n color.w = opacity;\n\n gl_FragColor = color;\n \n}"]);var rgbdVert=glsl(["#define GLSLIFY 1\nuniform float mindepth;\nuniform float maxdepth;\n\nuniform float width;\nuniform float height;\n\nuniform bool isPoints;\nuniform float pointSize;\n\nuniform float time;\n\nuniform vec2 focalLength;\nuniform vec2 principalPoint;\nuniform vec2 imageDimensions;\nuniform vec4 crop;\nuniform vec2 meshDensity;\nuniform mat4 extrinsics;\n\nvarying vec3 vNormal;\nvarying vec3 vPos;\n\nuniform sampler2D map;\n\nvarying float visibility;\nvarying vec2 vUv;\n\nconst float _DepthSaturationThreshhold = 0.5; //a given pixel whose saturation is less than half will be culled (old default was .5)\nconst float _DepthBrightnessThreshold = 0.5; //a given pixel whose brightness is less than half will be culled (old default was .9)\nconst float _Epsilon = .03;\n\nvec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + _Epsilon)), d / (q.x + _Epsilon), q.x);\n}\n\nfloat depthForPoint(vec2 texturePoint)\n{\n vec4 depthsample = texture2D(map, texturePoint);\n vec3 depthsamplehsv = rgb2hsv(depthsample.rgb);\n return depthsamplehsv.g > _DepthSaturationThreshhold && depthsamplehsv.b > _DepthBrightnessThreshold ? depthsamplehsv.r : 0.0;\n}\n\nvoid main() {\n vec4 texSize = vec4(1.0 / width, 1.0 / height, width, height);\n\n vec2 centerpix = texSize.xy * .5;\n vec2 textureStep = 1.0 / meshDensity;\n vec2 basetex = floor(position.xy * textureStep * texSize.zw) * texSize.xy;\n vec2 imageCoordinates = crop.xy + (basetex * crop.zw);\n basetex.y = 1.0 - basetex.y;\n\n vec2 depthTexCoord = basetex * vec2(1.0, 0.5) + centerpix;\n vec2 colorTexCoord = basetex * vec2(1.0, 0.5) + vec2(0.0, 0.5) + centerpix;\n\n vUv = colorTexCoord;\n vPos = (modelMatrix * vec4(position, 1.0 )).xyz;\n vNormal = normalMatrix * normal;\n\n //check neighbors\n //texture coords come in as [0.0 - 1.0] for this whole plane\n float depth = depthForPoint(depthTexCoord);\n\n float neighborDepths[8];\n neighborDepths[0] = depthForPoint(depthTexCoord + vec2(0.0, textureStep.y));\n neighborDepths[1] = depthForPoint(depthTexCoord + vec2(textureStep.x, 0.0));\n neighborDepths[2] = depthForPoint(depthTexCoord + vec2(0.0, -textureStep.y));\n neighborDepths[3] = depthForPoint(depthTexCoord + vec2(-textureStep.x, 0.0));\n neighborDepths[4] = depthForPoint(depthTexCoord + vec2(-textureStep.x, -textureStep.y));\n neighborDepths[5] = depthForPoint(depthTexCoord + vec2(textureStep.x, textureStep.y));\n neighborDepths[6] = depthForPoint(depthTexCoord + vec2(textureStep.x, -textureStep.y));\n neighborDepths[7] = depthForPoint(depthTexCoord + vec2(-textureStep.x, textureStep.y));\n\n visibility = 1.0;\n int numDudNeighbors = 0;\n //search neighbor verts in order to see if we are near an edge\n //if so, clamp to the surface closest to us\n if (depth < _Epsilon || (1.0 - depth) < _Epsilon)\n {\n // float depthDif = 1.0;\n float nearestDepth = 1.0;\n for (int i = 0; i < 8; i++)\n {\n float depthNeighbor = neighborDepths[i];\n if (depthNeighbor >= _Epsilon && (1.0 - depthNeighbor) > _Epsilon)\n {\n // float thisDif = abs(nearestDepth - depthNeighbor);\n if (depthNeighbor < nearestDepth)\n {\n // depthDif = thisDif;\n nearestDepth = depthNeighbor;\n }\n }\n else\n {\n numDudNeighbors++;\n }\n }\n\n depth = nearestDepth;\n visibility = 0.8;\n\n // blob filter\n if (numDudNeighbors > 6)\n {\n visibility = 0.0;\n }\n }\n\n // internal edge filter\n float maxDisparity = 0.0;\n for (int i = 0; i < 8; i++)\n {\n float depthNeighbor = neighborDepths[i];\n if (depthNeighbor >= _Epsilon && (1.0 - depthNeighbor) > _Epsilon)\n {\n maxDisparity = max(maxDisparity, abs(depth - depthNeighbor));\n }\n }\n visibility *= 1.0 - maxDisparity;\n\n float z = depth * (maxdepth - mindepth) + mindepth;\n vec4 worldPos = extrinsics * vec4((imageCoordinates * imageDimensions - principalPoint) * z / focalLength, z, 1.0);\n worldPos.w = 1.0;\n\n gl_Position = projectionMatrix * modelViewMatrix * worldPos;\n}"]);this.video=document.createElement("video");this.video.id="depthkit-video";this.video.crossOrigin="anonymous";this.video.setAttribute("crossorigin","anonymous");this.video.setAttribute("webkit-playsinline","webkit-playsinline");this.video.setAttribute("playsinline","playsinline");this.video.src=_movie;this.video.poster=_poster;this.video.autoplay=true;this.video.loop=false;this.video.muted=true;this.video.load();this.videoTexture=new THREE.VideoTexture(this.video);this.videoTexture.minFilter=THREE.NearestFilter;this.videoTexture.magFilter=THREE.LinearFilter;this.videoTexture.format=THREE.RGBAFormat;this.videoTexture.generateMipmaps=false;this.manager=new THREE.LoadingManager;this.props;if(!DepthKit.geo){DepthKit.buildGeomtery()}this.material=new THREE.ShaderMaterial({uniforms:{map:{type:"t",value:this.videoTexture},time:{type:"f",value:0},mindepth:{type:"f",value:0},maxdepth:{type:"f",value:0},meshDensity:{value:new THREE.Vector2(VERTS_WIDE,VERTS_TALL)},focalLength:{value:new THREE.Vector2(1,1)},principalPoint:{value:new THREE.Vector2(1,1)},imageDimensions:{value:new THREE.Vector2(512,828)},extrinsics:{value:new THREE.Matrix4},crop:{value:new THREE.Vector4(0,0,1,1)},width:{type:"f",value:0},height:{type:"f",value:0},opacity:{type:"f",value:1},isPoints:{type:"b",value:false},pointSize:{type:"f",value:3}},vertexShader:rgbdVert,fragmentShader:rgbdFrag,transparent:true});this.material.side=THREE.DoubleSide;switch(_type){case"wire":this.material.wireframe=true;this.mesh=new THREE.Mesh(DepthKit.geo,this.material);break;case"points":this.material.uniforms.isPoints.value=true;this.mesh=new THREE.Points(DepthKit.geo,this.material);break;default:this.mesh=new THREE.Mesh(DepthKit.geo,this.material);break}this.jsonLoader=new THREE.FileLoader(this.manager);this.jsonLoader.setResponseType("json");this.jsonLoader.load(_props,function(data){_this.props=data;_this.material.uniforms.width.value=_this.props.textureWidth;_this.material.uniforms.height.value=_this.props.textureHeight;_this.material.uniforms.mindepth.value=_this.props.nearClip;_this.material.uniforms.maxdepth.value=_this.props.farClip;_this.material.uniforms.focalLength.value=_this.props.depthFocalLength;_this.material.uniforms.principalPoint.value=_this.props.depthPrincipalPoint;_this.material.uniforms.imageDimensions.value=_this.props.depthImageSize;_this.material.uniforms.crop.value=_this.props.crop;var ex=_this.props.extrinsics;_this.material.uniforms.extrinsics.value.set(ex["e00"],ex["e10"],ex["e20"],ex["e30"],ex["e01"],ex["e11"],ex["e21"],ex["e31"],ex["e02"],ex["e12"],ex["e22"],ex["e32"],ex["e03"],ex["e13"],ex["e23"],ex["e33"]);var boxGeo=new THREE.BoxGeometry(_this.props.boundsSize.x,_this.props.boundsSize.y,_this.props.boundsSize.z);var boxMat=new THREE.MeshBasicMaterial({color:16776960,wireframe:true});_this.collider=new THREE.Mesh(boxGeo,boxMat);_this.mesh.add(_this.collider);_this.collider.position.set(650,-200,-1900)});this.mesh.frustumCulled=false;this.mesh.depthkit=this;this.mesh.name="depthkit";return this.mesh}_createClass(DepthKit,[{key:"setPointSize",value:function setPointSize(size){if(this.material.uniforms.isPoints.value){this.material.uniforms.pointSize.value=size}else{console.warn("Can not set point size because the current character is not set to render points")}}},{key:"setOpacity",value:function setOpacity(opacity){this.material.uniforms.opacity.value=opacity}},{key:"setLineWidth",value:function setLineWidth(width){if(this.material.wireframe){this.material.wireframeLinewidth=width}else{console.warn("Can not set the line width because the current character is not set to render wireframe")}}},{key:"play",value:function play(){if(!this.video.isPlaying){this.video.play()}else{console.warn("Can not play because the character is already playing")}}},{key:"stop",value:function stop(){this.video.currentTime=0;this.video.pause()}},{key:"pause",value:function pause(){this.video.pause()}},{key:"setLoop",value:function setLoop(isLooping){this.video.loop=isLooping}},{key:"setVolume",value:function setVolume(volume){this.video.volume=volume}},{key:"update",value:function update(time){this.material.uniforms.time.value=time}},{key:"toggleColliderVisiblity",value:function toggleColliderVisiblity(){this.mesh.collider.visible=!this.mesh.collider.visible}},{key:"dispose",value:function dispose(){try{this.mesh.parent.remove(this.mesh)}catch(e){console.warn(e)}finally{this.mesh.traverse(function(child){if(child.geometry!==undefined){child.geometry.dispose();child.material.dispose()}})}}}],[{key:"buildGeomtery",value:function buildGeomtery(){var geometry=new THREE.BufferGeometry;var verts=[];var faces=[];for(var y=0;y EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - - if ( zoomChanged || - lastPosition.distanceToSquared( scope.object.position ) > EPS || - 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { - - scope.dispatchEvent( changeEvent ); - - lastPosition.copy( scope.object.position ); - lastQuaternion.copy( scope.object.quaternion ); - zoomChanged = false; - - return true; - - } - - return false; - - }; - - }(); - - this.dispose = function () { - - scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); - scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); - scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); - - scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); - scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); - scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); - - document.removeEventListener( 'mousemove', onMouseMove, false ); - document.removeEventListener( 'mouseup', onMouseUp, false ); - - window.removeEventListener( 'keydown', onKeyDown, false ); - - //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? - - }; - - // - // internals - // - - var scope = this; - - var changeEvent = { type: 'change' }; - var startEvent = { type: 'start' }; - var endEvent = { type: 'end' }; - - var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 }; - - var state = STATE.NONE; - - var EPS = 0.000001; - - // current position in spherical coordinates - var spherical = new THREE.Spherical(); - var sphericalDelta = new THREE.Spherical(); - - var scale = 1; - var panOffset = new THREE.Vector3(); - var zoomChanged = false; - - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - - var panStart = new THREE.Vector2(); - var panEnd = new THREE.Vector2(); - var panDelta = new THREE.Vector2(); - - var dollyStart = new THREE.Vector2(); - var dollyEnd = new THREE.Vector2(); - var dollyDelta = new THREE.Vector2(); - - function getAutoRotationAngle() { - - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - - } - - function getZoomScale() { - - return Math.pow( 0.95, scope.zoomSpeed ); - - } - - function rotateLeft( angle ) { - - sphericalDelta.theta -= angle; - - } - - function rotateUp( angle ) { - - sphericalDelta.phi -= angle; - - } - - var panLeft = function () { - - var v = new THREE.Vector3(); - - return function panLeft( distance, objectMatrix ) { - - v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix - v.multiplyScalar( - distance ); - - panOffset.add( v ); - - }; - - }(); - - var panUp = function () { - - var v = new THREE.Vector3(); - - return function panUp( distance, objectMatrix ) { - - v.setFromMatrixColumn( objectMatrix, 1 ); // get Y column of objectMatrix - v.multiplyScalar( distance ); - - panOffset.add( v ); - - }; - - }(); - - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - - var offset = new THREE.Vector3(); - - return function pan( deltaX, deltaY ) { - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - if ( scope.object instanceof THREE.PerspectiveCamera ) { - - // perspective - var position = scope.object.position; - offset.copy( position ).sub( scope.target ); - var targetDistance = offset.length(); - - // half of the fov is center to top of screen - targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); - - // we actually don't use screenWidth, since perspective camera is fixed to screen height - panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); - panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); - - } else if ( scope.object instanceof THREE.OrthographicCamera ) { - - // orthographic - panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); - panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); - - } else { - - // camera neither orthographic nor perspective - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); - scope.enablePan = false; - - } - - }; - - }(); - - function dollyIn( dollyScale ) { - - if ( scope.object instanceof THREE.PerspectiveCamera ) { - - scale /= dollyScale; - - } else if ( scope.object instanceof THREE.OrthographicCamera ) { - - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - - } else { - - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; - - } - - } - - function dollyOut( dollyScale ) { - - if ( scope.object instanceof THREE.PerspectiveCamera ) { - - scale *= dollyScale; - - } else if ( scope.object instanceof THREE.OrthographicCamera ) { - - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - - } else { - - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; - - } - - } - - // - // event callbacks - update the object state - // - - function handleMouseDownRotate( event ) { - - //console.log( 'handleMouseDownRotate' ); - - rotateStart.set( event.clientX, event.clientY ); - - } - - function handleMouseDownDolly( event ) { - - //console.log( 'handleMouseDownDolly' ); - - dollyStart.set( event.clientX, event.clientY ); - - } - - function handleMouseDownPan( event ) { - - //console.log( 'handleMouseDownPan' ); - - panStart.set( event.clientX, event.clientY ); - - } - - function handleMouseMoveRotate( event ) { - - //console.log( 'handleMouseMoveRotate' ); - - rotateEnd.set( event.clientX, event.clientY ); - rotateDelta.subVectors( rotateEnd, rotateStart ); - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - // rotating across whole screen goes 360 degrees around - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); - - // rotating up and down along whole screen attempts to go 360, but limited to 180 - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); - - rotateStart.copy( rotateEnd ); - - scope.update(); - - } - - function handleMouseMoveDolly( event ) { - - //console.log( 'handleMouseMoveDolly' ); - - dollyEnd.set( event.clientX, event.clientY ); - - dollyDelta.subVectors( dollyEnd, dollyStart ); - - if ( dollyDelta.y > 0 ) { - - dollyIn( getZoomScale() ); - - } else if ( dollyDelta.y < 0 ) { - - dollyOut( getZoomScale() ); - - } - - dollyStart.copy( dollyEnd ); - - scope.update(); - - } - - function handleMouseMovePan( event ) { - - //console.log( 'handleMouseMovePan' ); - - panEnd.set( event.clientX, event.clientY ); - - panDelta.subVectors( panEnd, panStart ); - - pan( panDelta.x, panDelta.y ); - - panStart.copy( panEnd ); - - scope.update(); - - } - - function handleMouseUp( event ) { - - // console.log( 'handleMouseUp' ); - - } - - function handleMouseWheel( event ) { - - // console.log( 'handleMouseWheel' ); - - if ( event.deltaY < 0 ) { - - dollyOut( getZoomScale() ); - - } else if ( event.deltaY > 0 ) { - - dollyIn( getZoomScale() ); - - } - - scope.update(); - - } - - function handleKeyDown( event ) { - - //console.log( 'handleKeyDown' ); - - switch ( event.keyCode ) { - - case scope.keys.UP: - pan( 0, scope.keyPanSpeed ); - scope.update(); - break; - - case scope.keys.BOTTOM: - pan( 0, - scope.keyPanSpeed ); - scope.update(); - break; - - case scope.keys.LEFT: - pan( scope.keyPanSpeed, 0 ); - scope.update(); - break; - - case scope.keys.RIGHT: - pan( - scope.keyPanSpeed, 0 ); - scope.update(); - break; - - } - - } - - function handleTouchStartRotate( event ) { - - //console.log( 'handleTouchStartRotate' ); - - rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - - } - - function handleTouchStartDolly( event ) { - - //console.log( 'handleTouchStartDolly' ); - - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; - - var distance = Math.sqrt( dx * dx + dy * dy ); - - dollyStart.set( 0, distance ); - - } - - function handleTouchStartPan( event ) { - - //console.log( 'handleTouchStartPan' ); - - panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - - } - - function handleTouchMoveRotate( event ) { - - //console.log( 'handleTouchMoveRotate' ); - - rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - rotateDelta.subVectors( rotateEnd, rotateStart ); - - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - - // rotating across whole screen goes 360 degrees around - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); - - // rotating up and down along whole screen attempts to go 360, but limited to 180 - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); - - rotateStart.copy( rotateEnd ); - - scope.update(); - - } - - function handleTouchMoveDolly( event ) { - - //console.log( 'handleTouchMoveDolly' ); - - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; - - var distance = Math.sqrt( dx * dx + dy * dy ); - - dollyEnd.set( 0, distance ); - - dollyDelta.subVectors( dollyEnd, dollyStart ); - - if ( dollyDelta.y > 0 ) { - - dollyOut( getZoomScale() ); - - } else if ( dollyDelta.y < 0 ) { - - dollyIn( getZoomScale() ); - - } - - dollyStart.copy( dollyEnd ); - - scope.update(); - - } - - function handleTouchMovePan( event ) { - - //console.log( 'handleTouchMovePan' ); - - panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - - panDelta.subVectors( panEnd, panStart ); - - pan( panDelta.x, panDelta.y ); - - panStart.copy( panEnd ); - - scope.update(); - - } - - function handleTouchEnd( event ) { - - //console.log( 'handleTouchEnd' ); - - } - - // - // event handlers - FSM: listen for events and reset state - // - - function onMouseDown( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - switch ( event.button ) { - - case scope.mouseButtons.ORBIT: - - if ( scope.enableRotate === false ) return; - - handleMouseDownRotate( event ); - - state = STATE.ROTATE; - - break; - - case scope.mouseButtons.ZOOM: - - if ( scope.enableZoom === false ) return; - - handleMouseDownDolly( event ); - - state = STATE.DOLLY; - - break; - - case scope.mouseButtons.PAN: - - if ( scope.enablePan === false ) return; - - handleMouseDownPan( event ); - - state = STATE.PAN; - - break; - - } - - if ( state !== STATE.NONE ) { - - document.addEventListener( 'mousemove', onMouseMove, false ); - document.addEventListener( 'mouseup', onMouseUp, false ); - - scope.dispatchEvent( startEvent ); - - } - - } - - function onMouseMove( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - switch ( state ) { - - case STATE.ROTATE: - - if ( scope.enableRotate === false ) return; - - handleMouseMoveRotate( event ); - - break; - - case STATE.DOLLY: - - if ( scope.enableZoom === false ) return; - - handleMouseMoveDolly( event ); - - break; - - case STATE.PAN: - - if ( scope.enablePan === false ) return; - - handleMouseMovePan( event ); - - break; - - } - - } - - function onMouseUp( event ) { - - if ( scope.enabled === false ) return; - - handleMouseUp( event ); - - document.removeEventListener( 'mousemove', onMouseMove, false ); - document.removeEventListener( 'mouseup', onMouseUp, false ); - - scope.dispatchEvent( endEvent ); - - state = STATE.NONE; - - } - - function onMouseWheel( event ) { - - if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; - - event.preventDefault(); - event.stopPropagation(); - - handleMouseWheel( event ); - - scope.dispatchEvent( startEvent ); // not sure why these are here... - scope.dispatchEvent( endEvent ); - - } - - function onKeyDown( event ) { - - if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; - - handleKeyDown( event ); - - } - - function onTouchStart( event ) { - - if ( scope.enabled === false ) return; - - switch ( event.touches.length ) { - - case 1: // one-fingered touch: rotate - - if ( scope.enableRotate === false ) return; - - handleTouchStartRotate( event ); - - state = STATE.TOUCH_ROTATE; - - break; - - case 2: // two-fingered touch: dolly - - if ( scope.enableZoom === false ) return; - - handleTouchStartDolly( event ); - - state = STATE.TOUCH_DOLLY; - - break; - - case 3: // three-fingered touch: pan - - if ( scope.enablePan === false ) return; - - handleTouchStartPan( event ); - - state = STATE.TOUCH_PAN; - - break; - - default: - - state = STATE.NONE; - - } - - if ( state !== STATE.NONE ) { - - scope.dispatchEvent( startEvent ); - - } - - } - - function onTouchMove( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - event.stopPropagation(); - - switch ( event.touches.length ) { - - case 1: // one-fingered touch: rotate - - if ( scope.enableRotate === false ) return; - if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?... - - handleTouchMoveRotate( event ); - - break; - - case 2: // two-fingered touch: dolly - - if ( scope.enableZoom === false ) return; - if ( state !== STATE.TOUCH_DOLLY ) return; // is this needed?... - - handleTouchMoveDolly( event ); - - break; - - case 3: // three-fingered touch: pan - - if ( scope.enablePan === false ) return; - if ( state !== STATE.TOUCH_PAN ) return; // is this needed?... - - handleTouchMovePan( event ); - - break; - - default: - - state = STATE.NONE; - - } - - } - - function onTouchEnd( event ) { - - if ( scope.enabled === false ) return; - - handleTouchEnd( event ); - - scope.dispatchEvent( endEvent ); - - state = STATE.NONE; - - } - - function onContextMenu( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - } - - // - - scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); - - scope.domElement.addEventListener( 'mousedown', onMouseDown, false ); - scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); - - scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); - scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); - scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); - - window.addEventListener( 'keydown', onKeyDown, false ); - - // force an update at start - - this.update(); - - }; - - THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); - THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; - - Object.defineProperties( THREE.OrbitControls.prototype, { - - center: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .center has been renamed to .target' ); - return this.target; - - } - - }, - - // backward compatibility - - noZoom: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); - return ! this.enableZoom; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); - this.enableZoom = ! value; - - } - - }, - - noRotate: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); - return ! this.enableRotate; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); - this.enableRotate = ! value; - - } - - }, - - noPan: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); - return ! this.enablePan; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); - this.enablePan = ! value; - - } - - }, - - noKeys: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); - return ! this.enableKeys; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); - this.enableKeys = ! value; - - } - - }, - - staticMoving: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); - return ! this.enableDamping; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); - this.enableDamping = ! value; - - } - - }, - - dynamicDampingFactor: { - - get: function () { - - console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); - return this.dampingFactor; - - }, - - set: function ( value ) { - - console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); - this.dampingFactor = value; - - } - - } - - } ); \ No newline at end of file diff --git a/examples/lib/VRButton.js b/examples/lib/VRButton.js deleted file mode 100644 index 3477298..0000000 --- a/examples/lib/VRButton.js +++ /dev/null @@ -1,199 +0,0 @@ -class VRButton { - - static createButton( renderer ) { - - const button = document.createElement( 'button' ); - - function showEnterVR( /*device*/ ) { - - let currentSession = null; - - async function onSessionStarted( session ) { - - session.addEventListener( 'end', onSessionEnded ); - - await renderer.xr.setSession( session ); - button.textContent = 'EXIT VR'; - - currentSession = session; - - } - - function onSessionEnded( /*event*/ ) { - - currentSession.removeEventListener( 'end', onSessionEnded ); - - button.textContent = 'ENTER VR'; - - currentSession = null; - - } - - // - - button.style.display = ''; - - button.style.cursor = 'pointer'; - button.style.left = 'calc(50% - 50px)'; - button.style.width = '100px'; - - button.textContent = 'ENTER VR'; - - button.onmouseenter = function () { - - button.style.opacity = '1.0'; - - }; - - button.onmouseleave = function () { - - button.style.opacity = '0.5'; - - }; - - button.onclick = function () { - - if ( currentSession === null ) { - - // WebXR's requestReferenceSpace only works if the corresponding feature - // was requested at session creation time. For simplicity, just ask for - // the interesting ones as optional features, but be aware that the - // requestReferenceSpace call will fail if it turns out to be unavailable. - // ('local' is always available for immersive sessions and doesn't need to - // be requested separately.) - - const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking', 'layers' ] }; - navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted ); - - } else { - - currentSession.end(); - - } - - }; - - } - - function disableButton() { - - button.style.display = ''; - - button.style.cursor = 'auto'; - button.style.left = 'calc(50% - 75px)'; - button.style.width = '150px'; - - button.onmouseenter = null; - button.onmouseleave = null; - - button.onclick = null; - - } - - function showWebXRNotFound() { - - disableButton(); - - button.textContent = 'VR NOT SUPPORTED'; - - } - - function showVRNotAllowed( exception ) { - - disableButton(); - - console.warn( 'Exception when trying to call xr.isSessionSupported', exception ); - - button.textContent = 'VR NOT ALLOWED'; - - } - - function stylizeElement( element ) { - - element.style.position = 'absolute'; - element.style.bottom = '20px'; - element.style.padding = '12px 6px'; - element.style.border = '1px solid #fff'; - element.style.borderRadius = '4px'; - element.style.background = 'rgba(0,0,0,0.1)'; - element.style.color = '#fff'; - element.style.font = 'normal 13px sans-serif'; - element.style.textAlign = 'center'; - element.style.opacity = '0.5'; - element.style.outline = 'none'; - element.style.zIndex = '999'; - - } - - if ( 'xr' in navigator ) { - - button.id = 'VRButton'; - button.style.display = 'none'; - - stylizeElement( button ); - - navigator.xr.isSessionSupported( 'immersive-vr' ).then( function ( supported ) { - - supported ? showEnterVR() : showWebXRNotFound(); - - if ( supported && VRButton.xrSessionIsGranted ) { - - button.click(); - - } - - } ).catch( showVRNotAllowed ); - - return button; - - } else { - - const message = document.createElement( 'a' ); - - if ( window.isSecureContext === false ) { - - message.href = document.location.href.replace( /^http:/, 'https:' ); - message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message - - } else { - - message.href = 'https://immersiveweb.dev/'; - message.innerHTML = 'WEBXR NOT AVAILABLE'; - - } - - message.style.left = 'calc(50% - 90px)'; - message.style.width = '180px'; - message.style.textDecoration = 'none'; - - stylizeElement( message ); - - return message; - - } - - } - - static xrSessionIsGranted = false; - - static registerSessionGrantedListener() { - - if ( 'xr' in navigator ) { - - // WebXRViewer (based on Firefox) has a bug where addEventListener - // throws a silent exception and aborts execution entirely. - if ( /WebXRViewer\//i.test( navigator.userAgent ) ) return; - - navigator.xr.addEventListener( 'sessiongranted', () => { - - VRButton.xrSessionIsGranted = true; - - } ); - - } - - } - -} - -VRButton.registerSessionGrantedListener(); \ No newline at end of file diff --git a/examples/raycast.html b/examples/raycast.html index 96c48bb..cfed353 100644 --- a/examples/raycast.html +++ b/examples/raycast.html @@ -32,18 +32,27 @@ - - - - - - -
DepthKit.js - Collision example using Three.js
Written by juniorxsound
- + + + - - - - -
DepthKit.js - Simple example using Three.js
Written by juniorxsound

Click page to start playback
- + + + - - - - -
DepthKit.js - Simple webVR example using Three.js
Written by juniorxsound
- + + +