123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- /******/ (function(modules) { // webpackBootstrap
- /******/ // The module cache
- /******/ var installedModules = {};
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/ // Check if module is in cache
- /******/ if(installedModules[moduleId])
- /******/ return installedModules[moduleId].exports;
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = installedModules[moduleId] = {
- /******/ exports: {},
- /******/ id: moduleId,
- /******/ loaded: false
- /******/ };
- /******/ // Execute the module function
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
- /******/ // Flag the module as loaded
- /******/ module.loaded = true;
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/ // expose the modules object (__webpack_modules__)
- /******/ __webpack_require__.m = modules;
- /******/ // expose the module cache
- /******/ __webpack_require__.c = installedModules;
- /******/ // __webpack_public_path__
- /******/ __webpack_require__.p = "";
- /******/ // Load entry module and return exports
- /******/ return __webpack_require__(0);
- /******/ })
- /************************************************************************/
- /******/ ([
- /* 0 */
- /***/ (function(module, exports, __webpack_require__) {
- /* global THREE, AFRAME, Element */
- var cylinderTexture = __webpack_require__(1);
- var parabolicCurve = __webpack_require__(2);
- var RayCurve = __webpack_require__(3);
- if (typeof AFRAME === 'undefined') {
- throw new Error('Component attempted to register before AFRAME was available.');
- }
- if (!Element.prototype.matches) {
- Element.prototype.matches =
- Element.prototype.matchesSelector ||
- Element.prototype.mozMatchesSelector ||
- Element.prototype.msMatchesSelector ||
- Element.prototype.oMatchesSelector ||
- Element.prototype.webkitMatchesSelector ||
- function (s) {
- var matches = (this.document || this.ownerDocument).querySelectorAll(s);
- var i = matches.length;
- while (--i >= 0 && matches.item(i) !== this) { /* no-op */ }
- return i > -1;
- };
- }
- AFRAME.registerComponent('teleport-controls', {
- schema: {
- type: {default: 'parabolic', oneOf: ['parabolic', 'line']},
- button: {default: 'trackpad', oneOf: ['trackpad', 'trigger', 'grip', 'menu']},
- startEvents: {type: 'array'},
- endEvents: {type: 'array'},
- collisionEntities: {default: ''},
- hitEntity: {type: 'selector'},
- cameraRig: {type: 'selector'},
- teleportOrigin: {type: 'selector'},
- hitCylinderColor: {type: 'color', default: '#99ff99'},
- hitCylinderRadius: {default: 0.25, min: 0},
- hitCylinderHeight: {default: 0.3, min: 0},
- interval: {default: 0},
- maxLength: {default: 10, min: 0, if: {type: ['line']}},
- curveNumberPoints: {default: 30, min: 2, if: {type: ['parabolic']}},
- curveLineWidth: {default: 0.025},
- curveHitColor: {type: 'color', default: '#99ff99'},
- curveMissColor: {type: 'color', default: '#ff0000'},
- curveShootingSpeed: {default: 5, min: 0, if: {type: ['parabolic']}},
- defaultPlaneSize: { default: 100 },
- landingNormal: {type: 'vec3', default: '0 1 0'},
- landingMaxAngle: {default: '45', min: 0, max: 360},
- drawIncrementally: {default: false},
- incrementalDrawMs: {default: 700},
- missOpacity: {default: 1.0},
- hitOpacity: {default: 1.0}
- },
- init: function () {
- var data = this.data;
- var el = this.el;
- var teleportEntity;
- var i;
- this.active = false;
- this.obj = el.object3D;
- this.hitPoint = new THREE.Vector3();
- this.rigWorldPosition = new THREE.Vector3();
- this.newRigWorldPosition = new THREE.Vector3();
- this.teleportEventDetail = {
- oldPosition: this.rigWorldPosition,
- newPosition: this.newRigWorldPosition,
- hitPoint: this.hitPoint
- };
- this.hit = false;
- this.prevCheckTime = undefined;
- this.prevHitHeight = 0;
- this.referenceNormal = new THREE.Vector3();
- this.curveMissColor = new THREE.Color();
- this.curveHitColor = new THREE.Color();
- this.raycaster = new THREE.Raycaster();
- this.defaultPlane = createDefaultPlane(this.data.defaultPlaneSize);
- this.defaultCollisionMeshes = [this.defaultPlane];
- teleportEntity = this.teleportEntity = document.createElement('a-entity');
- teleportEntity.classList.add('teleportRay');
- teleportEntity.setAttribute('visible', false);
- el.sceneEl.appendChild(this.teleportEntity);
- this.onButtonDown = this.onButtonDown.bind(this);
- this.onButtonUp = this.onButtonUp.bind(this);
- if (this.data.startEvents.length && this.data.endEvents.length) {
- for (i = 0; i < this.data.startEvents.length; i++) {
- el.addEventListener(this.data.startEvents[i], this.onButtonDown);
- }
- for (i = 0; i < this.data.endEvents.length; i++) {
- el.addEventListener(this.data.endEvents[i], this.onButtonUp);
- }
- } else {
- el.addEventListener(data.button + 'down', this.onButtonDown);
- el.addEventListener(data.button + 'up', this.onButtonUp);
- }
- this.queryCollisionEntities();
- },
- update: function (oldData) {
- var data = this.data;
- var diff = AFRAME.utils.diff(data, oldData);
- // Update normal.
- this.referenceNormal.copy(data.landingNormal);
- // Update colors.
- this.curveMissColor.set(data.curveMissColor);
- this.curveHitColor.set(data.curveHitColor);
- // Create or update line mesh.
- if (!this.line ||
- 'curveLineWidth' in diff || 'curveNumberPoints' in diff || 'type' in diff) {
- this.line = createLine(data);
- this.line.material.opacity = this.data.hitOpacity;
- this.line.material.transparent = this.data.hitOpacity < 1;
- this.numActivePoints = data.curveNumberPoints;
- this.teleportEntity.setObject3D('mesh', this.line.mesh);
- }
- // Create or update hit entity.
- if (data.hitEntity) {
- this.hitEntity = data.hitEntity;
- } else if (!this.hitEntity || 'hitCylinderColor' in diff || 'hitCylinderHeight' in diff ||
- 'hitCylinderRadius' in diff) {
- // Remove previous entity, create new entity (could be more performant).
- if (this.hitEntity) { this.hitEntity.parentNode.removeChild(this.hitEntity); }
- this.hitEntity = createHitEntity(data);
- this.el.sceneEl.appendChild(this.hitEntity);
- }
- this.hitEntity.setAttribute('visible', false);
- if ('collisionEntities' in diff) { this.queryCollisionEntities(); }
- },
- remove: function () {
- var el = this.el;
- var hitEntity = this.hitEntity;
- var teleportEntity = this.teleportEntity;
- if (hitEntity) { hitEntity.parentNode.removeChild(hitEntity); }
- if (teleportEntity) { teleportEntity.parentNode.removeChild(teleportEntity); }
- el.sceneEl.removeEventListener('child-attached', this.childAttachHandler);
- el.sceneEl.removeEventListener('child-detached', this.childDetachHandler);
- },
- tick: (function () {
- var p0 = new THREE.Vector3();
- var v0 = new THREE.Vector3();
- var g = -9.8;
- var a = new THREE.Vector3(0, g, 0);
- var next = new THREE.Vector3();
- var last = new THREE.Vector3();
- var quaternion = new THREE.Quaternion();
- var translation = new THREE.Vector3();
- var scale = new THREE.Vector3();
- var shootAngle = new THREE.Vector3();
- var lastNext = new THREE.Vector3();
- var auxDirection = new THREE.Vector3();
- var timeSinceDrawStart = 0;
- return function (time, delta) {
- if (!this.active) { return; }
- if (this.data.drawIncrementally && this.redrawLine){
- this.redrawLine = false;
- timeSinceDrawStart = 0;
- }
- timeSinceDrawStart += delta;
- this.numActivePoints = this.data.curveNumberPoints*timeSinceDrawStart/this.data.incrementalDrawMs;
- if (this.numActivePoints > this.data.curveNumberPoints){
- this.numActivePoints = this.data.curveNumberPoints;
- }
- // Only check for intersection if interval time has passed.
- if (this.prevCheckTime && (time - this.prevCheckTime < this.data.interval)) { return; }
- // Update check time.
- this.prevCheckTime = time;
- var matrixWorld = this.obj.matrixWorld;
- matrixWorld.decompose(translation, quaternion, scale);
- var direction = shootAngle.set(0, 0, -1)
- .applyQuaternion(quaternion).normalize();
- this.line.setDirection(auxDirection.copy(direction));
- this.obj.getWorldPosition(p0);
- last.copy(p0);
- // Set default status as non-hit
- this.teleportEntity.setAttribute('visible', true);
- this.line.material.color.set(this.curveMissColor);
- this.line.material.opacity = this.data.missOpacity;
- this.line.material.transparent = this.data.missOpacity < 1;
- this.hitEntity.setAttribute('visible', false);
- this.hit = false;
- if (this.data.type === 'parabolic') {
- v0.copy(direction).multiplyScalar(this.data.curveShootingSpeed);
- this.lastDrawnIndex = 0;
- const numPoints = this.data.drawIncrementally ? this.numActivePoints : this.line.numPoints;
- for (var i = 0; i < numPoints+1; i++) {
- var t;
- if (i == Math.floor(numPoints+1)){
- t = numPoints / (this.line.numPoints - 1);
- }
- else {
- t = i / (this.line.numPoints - 1);
- }
- parabolicCurve(p0, v0, a, t, next);
- // Update the raycaster with the length of the current segment last->next
- var dirLastNext = lastNext.copy(next).sub(last).normalize();
- this.raycaster.far = dirLastNext.length();
- this.raycaster.set(last, dirLastNext);
- this.lastDrawnPoint = next;
- this.lastDrawnIndex = i;
- if (this.checkMeshCollisions(i, next)) { break; }
- last.copy(next);
- }
- for (var j = this.lastDrawnIndex+1; j < this.line.numPoints; j++) {
- this.line.setPoint(j, this.lastDrawnPoint);
- }
- } else if (this.data.type === 'line') {
- next.copy(last).add(auxDirection.copy(direction).multiplyScalar(this.data.maxLength));
- this.raycaster.far = this.data.maxLength;
- this.raycaster.set(p0, direction);
- this.line.setPoint(0, p0);
- this.checkMeshCollisions(1, next);
- }
- };
- })(),
- /**
- * Run `querySelectorAll` for `collisionEntities` and maintain it with `child-attached`
- * and `child-detached` events.
- */
- queryCollisionEntities: function () {
- var collisionEntities;
- var data = this.data;
- var el = this.el;
- if (!data.collisionEntities) {
- this.collisionEntities = [];
- return;
- }
- collisionEntities = [].slice.call(el.sceneEl.querySelectorAll(data.collisionEntities));
- this.collisionEntities = collisionEntities;
- // Update entity list on attach.
- this.childAttachHandler = function childAttachHandler (evt) {
- if (!evt.detail.el.matches(data.collisionEntities)) { return; }
- collisionEntities.push(evt.detail.el);
- };
- el.sceneEl.addEventListener('child-attached', this.childAttachHandler);
- // Update entity list on detach.
- this.childDetachHandler = function childDetachHandler (evt) {
- var index;
- if (!evt.detail.el.matches(data.collisionEntities)) { return; }
- index = collisionEntities.indexOf(evt.detail.el);
- if (index === -1) { return; }
- collisionEntities.splice(index, 1);
- };
- el.sceneEl.addEventListener('child-detached', this.childDetachHandler);
- },
- onButtonDown: function () {
- this.active = true;
- this.redrawLine = true;
- },
- /**
- * Jump!
- */
- onButtonUp: (function () {
- const teleportOriginWorldPosition = new THREE.Vector3();
- const newRigLocalPosition = new THREE.Vector3();
- const newHandPosition = [new THREE.Vector3(), new THREE.Vector3()]; // Left and right
- const handPosition = new THREE.Vector3();
- return function (evt) {
- if (!this.active) { return; }
- // Hide the hit point and the curve
- this.active = false;
- this.hitEntity.setAttribute('visible', false);
- this.teleportEntity.setAttribute('visible', false);
- if (!this.hit) {
- // Button released but not hit point
- return;
- }
- const rig = this.data.cameraRig || this.el.sceneEl.camera.el;
- rig.object3D.getWorldPosition(this.rigWorldPosition);
- this.newRigWorldPosition.copy(this.hitPoint);
- // If a teleportOrigin exists, offset the rig such that the teleportOrigin is above the hitPoint
- const teleportOrigin = this.data.teleportOrigin;
- if (teleportOrigin) {
- teleportOrigin.object3D.getWorldPosition(teleportOriginWorldPosition);
- this.newRigWorldPosition.sub(teleportOriginWorldPosition).add(this.rigWorldPosition);
- }
- // Always keep the rig at the same offset off the ground after teleporting
- this.newRigWorldPosition.y = this.rigWorldPosition.y + this.hitPoint.y - this.prevHitHeight;
- this.prevHitHeight = this.hitPoint.y;
- // Finally update the rigs position
- newRigLocalPosition.copy(this.newRigWorldPosition);
- if (rig.object3D.parent) {
- rig.object3D.parent.worldToLocal(newRigLocalPosition);
- }
- rig.setAttribute('position', newRigLocalPosition);
- // If a rig was not explicitly declared, look for hands and mvoe them proportionally as well
- if (!this.data.cameraRig) {
- var hands = document.querySelectorAll('a-entity[tracked-controls]');
- for (var i = 0; i < hands.length; i++) {
- hands[i].object3D.getWorldPosition(handPosition);
- // diff = rigWorldPosition - handPosition
- // newPos = newRigWorldPosition - diff
- newHandPosition[i].copy(this.newRigWorldPosition).sub(this.rigWorldPosition).add(handPosition);
- hands[i].setAttribute('position', newHandPosition[i]);
- }
- }
- this.el.emit('teleported', this.teleportEventDetail);
- };
- })(),
- /**
- * Check for raycaster intersection.
- *
- * @param {number} Line fragment point index.
- * @param {number} Next line fragment point index.
- * @returns {boolean} true if there's an intersection.
- */
- checkMeshCollisions: function (i, next) {
- // @todo We should add a property to define if the collisionEntity is dynamic or static
- // If static we should do the map just once, otherwise we're recreating the array in every
- // loop when aiming.
- var meshes;
- if (!this.data.collisionEntities) {
- meshes = this.defaultCollisionMeshes;
- } else {
- meshes = this.collisionEntities.map(function (entity) {
- return entity.getObject3D('mesh');
- }).filter(function (n) { return n; });
- meshes = meshes.length ? meshes : this.defaultCollisionMeshes;
- }
- var intersects = this.raycaster.intersectObjects(meshes, true);
- if (intersects.length > 0 && !this.hit &&
- this.isValidNormalsAngle(intersects[0].face.normal)) {
- var point = intersects[0].point;
- this.line.material.color.set(this.curveHitColor);
- this.line.material.opacity = this.data.hitOpacity;
- this.line.material.transparent= this.data.hitOpacity < 1;
- this.hitEntity.setAttribute('position', point);
- this.hitEntity.setAttribute('visible', true);
- this.hit = true;
- this.hitPoint.copy(intersects[0].point);
- // If hit, just fill the rest of the points with the hit point and break the loop
- for (var j = i; j < this.line.numPoints; j++) {
- this.line.setPoint(j, this.hitPoint);
- }
- return true;
- } else {
- this.line.setPoint(i, next);
- return false;
- }
- },
- isValidNormalsAngle: function (collisionNormal) {
- var angleNormals = this.referenceNormal.angleTo(collisionNormal);
- return (THREE.Math.RAD2DEG * angleNormals <= this.data.landingMaxAngle);
- },
- });
- function createLine (data) {
- var numPoints = data.type === 'line' ? 2 : data.curveNumberPoints;
- return new RayCurve(numPoints, data.curveLineWidth);
- }
- /**
- * Create mesh to represent the area of intersection.
- * Default to a combination of torus and cylinder.
- */
- function createHitEntity (data) {
- var cylinder;
- var hitEntity;
- var torus;
- // Parent.
- hitEntity = document.createElement('a-entity');
- hitEntity.className = 'hitEntity';
- // Torus.
- torus = document.createElement('a-entity');
- torus.setAttribute('geometry', {
- primitive: 'torus',
- radius: data.hitCylinderRadius,
- radiusTubular: 0.01
- });
- torus.setAttribute('rotation', {x: 90, y: 0, z: 0});
- torus.setAttribute('material', {
- shader: 'flat',
- color: data.hitCylinderColor,
- side: 'double',
- depthTest: false
- });
- hitEntity.appendChild(torus);
- // Cylinder.
- cylinder = document.createElement('a-entity');
- cylinder.setAttribute('position', {x: 0, y: data.hitCylinderHeight / 2, z: 0});
- cylinder.setAttribute('geometry', {
- primitive: 'cylinder',
- segmentsHeight: 1,
- radius: data.hitCylinderRadius,
- height: data.hitCylinderHeight,
- openEnded: true
- });
- cylinder.setAttribute('material', {
- shader: 'flat',
- color: data.hitCylinderColor,
- side: 'double',
- src: cylinderTexture,
- transparent: true,
- depthTest: false
- });
- hitEntity.appendChild(cylinder);
- return hitEntity;
- }
- function createDefaultPlane (size) {
- var geometry;
- var material;
- geometry = new THREE.PlaneBufferGeometry(100, 100);
- geometry.rotateX(-Math.PI / 2);
- material = new THREE.MeshBasicMaterial({color: 0xffff00});
- return new THREE.Mesh(geometry, material);
- }
- /***/ }),
- /* 1 */
- /***/ (function(module, exports) {
- module.exports = 'url(data:image/png;base64,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)';
- /***/ }),
- /* 2 */
- /***/ (function(module, exports) {
- /* global THREE */
- // Parabolic motion equation, y = p0 + v0*t + 1/2at^2
- function parabolicCurveScalar (p0, v0, a, t) {
- return p0 + v0 * t + 0.5 * a * t * t;
- }
- // Parabolic motion equation applied to 3 dimensions
- function parabolicCurve (p0, v0, a, t, out) {
- out.x = parabolicCurveScalar(p0.x, v0.x, a.x, t);
- out.y = parabolicCurveScalar(p0.y, v0.y, a.y, t);
- out.z = parabolicCurveScalar(p0.z, v0.z, a.z, t);
- return out;
- }
- module.exports = parabolicCurve;
- /***/ }),
- /* 3 */
- /***/ (function(module, exports) {
- /* global THREE */
- var RayCurve = function (numPoints, width) {
- this.geometry = new THREE.BufferGeometry();
- this.vertices = new Float32Array(numPoints * 3 * 2);
- this.uvs = new Float32Array(numPoints * 2 * 2);
- this.width = width;
- this.geometry.setAttribute('position', new THREE.BufferAttribute(this.vertices, 3).setUsage(THREE.DynamicDrawUsage));
- this.material = new THREE.MeshBasicMaterial({
- side: THREE.DoubleSide,
- color: 0xff0000
- });
- this.mesh = new THREE.Mesh(this.geometry, this.material);
- THREE.BufferGeometryUtils.toTrianglesDrawMode(this.mesh.geometry, THREE.TriangleStripDrawMode);
- //this.mesh.drawMode = THREE.TriangleStripDrawMode;
- this.mesh.frustumCulled = false;
- this.mesh.vertices = this.vertices;
- this.direction = new THREE.Vector3();
- this.numPoints = numPoints;
- };
- RayCurve.prototype = {
- setDirection: function (direction) {
- var UP = new THREE.Vector3(0, 1, 0);
- this.direction
- .copy(direction)
- .cross(UP)
- .normalize()
- .multiplyScalar(this.width / 2);
- },
- setWidth: function (width) {
- this.width = width;
- },
- setPoint: (function () {
- var posA = new THREE.Vector3();
- var posB = new THREE.Vector3();
- return function (i, point) {
- posA.copy(point).add(this.direction);
- posB.copy(point).sub(this.direction);
- var idx = 2 * 3 * i;
- this.vertices[idx++] = posA.x;
- this.vertices[idx++] = posA.y;
- this.vertices[idx++] = posA.z;
- this.vertices[idx++] = posB.x;
- this.vertices[idx++] = posB.y;
- this.vertices[idx++] = posB.z;
- this.geometry.attributes.position.needsUpdate = true;
- };
- })()
- };
- module.exports = RayCurve;
- /***/ })
- /******/ ]);
|