react-xrplayer
Version:
An excellent xr player for react
237 lines (178 loc) • 8.27 kB
JavaScript
;
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var THREE = _interopRequireWildcard(require("three"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var StereoEffect = function StereoEffect(renderer) {
var _this = this;
_classCallCheck(this, StereoEffect);
_defineProperty(this, "setEyeSeparation", function (eyeSep) {
_this.stereoCamera.eyeSep = eyeSep;
});
_defineProperty(this, "setSize", function (width, height) {
_this.renderer.setSize(width, height);
});
_defineProperty(this, "render", function (scene, camera) {
scene.updateMatrixWorld();
var size = _this.size;
if (camera.parent === null) camera.updateMatrixWorld();
_this.stereoCamera.update(camera);
_this.renderer.getSize(_this.size);
if (_this.renderer.autoClear) _this.renderer.clear();
_this.renderer.setScissorTest(true);
_this.renderer.setScissor(0, 0, size.width / 2, size.height);
_this.renderer.setViewport(0, 0, size.width / 2, size.height);
_this.renderer.render(scene, _this.stereoCamera.cameraL);
_this.renderer.setScissor(size.width / 2, 0, size.width / 2, size.height);
_this.renderer.setViewport(size.width / 2, 0, size.width / 2, size.height);
_this.renderer.render(scene, _this.stereoCamera.cameraR);
_this.renderer.setScissorTest(false);
});
this.renderer = renderer;
this.stereoCamera = new THREE.StereoCamera();
this.stereoCamera.aspect = 0.5;
this.size = new THREE.Vector2();
};
var VRHelper = function VRHelper(renderer, _camera) {
var _this2 = this;
_classCallCheck(this, VRHelper);
_defineProperty(this, "setSize", function (width, height) {
_this2.effect && _this2.effect.setSize(width, height);
});
_defineProperty(this, "initCursor", function () {
var cursorColors = new Uint8Array([64, 64, 64, 64, // dark gray
255, 255, 255, 255 // white
]);
_this2.cursorTexture = _this2.makeDataTexture(cursorColors, 2, 1);
var cursorGeometry = new THREE.TorusBufferGeometry(1, 0.1, 4, 64);
var cursorMaterial = new THREE.MeshBasicMaterial({
color: 'white',
map: _this2.cursorTexture,
transparent: true,
depthTest: false,
blending: THREE.CustomBlending,
blendSrc: THREE.OneMinusDstColorFactor,
blendDst: THREE.OneMinusSrcColorFactor
});
var cursor = new THREE.Mesh(cursorGeometry, cursorMaterial);
_this2.camera.add(cursor);
cursor.position.z = -500;
var scale = 25;
cursor.scale.set(scale, scale, scale);
_this2.cursor = cursor;
cursor.visible = false;
});
_defineProperty(this, "makeDataTexture", function (data, width, height) {
var texture = new THREE.DataTexture(data, width, height, THREE.RGBAFormat);
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
texture.needsUpdate = true;
return texture;
});
_defineProperty(this, "initCone", function () {
var coneGeometry = new THREE.ConeGeometry(0.8, 1.2, 3, 1);
var coneMaterial = new THREE.MeshBasicMaterial({
color: 'white',
transparent: true,
depthTest: false,
wireframe: true
});
var cone = new THREE.Mesh(coneGeometry, coneMaterial);
_this2.cone = cone;
cone.position.z = -500;
var scale = 25;
cone.scale.set(scale, scale, scale);
cone.rotation.x = Math.PI / 2;
_this2.camera.add(cone);
cone.visible = false;
});
_defineProperty(this, "pick", function (normalizedPosition, camera, time, objects) {
if (!!!objects || _this2.vrStatus === false) {
_this2.pickedObject = undefined;
return undefined;
}
var elapsedTime = time - _this2.lastTime;
_this2.lastTime = time;
var lastPickedObject = _this2.pickedObject; // restore the color if there is a picked object
if (_this2.pickedObject) {
_this2.pickedObject = undefined;
} // cast a ray through the frustum
_this2.raycaster.setFromCamera(normalizedPosition, camera); // get the list of objects the ray intersected
var intersectedObjects = _this2.raycaster.intersectObjects(objects);
if (intersectedObjects.length) {
// pick the first object. It's the closest one
_this2.pickedObject = intersectedObjects[0].object;
} // show or hide cursor
_this2.cursor.visible = !!_this2.pickedObject;
var selected = false; // if we're looking at the same object as before
// increment time select timer
if (_this2.pickedObject && lastPickedObject === _this2.pickedObject) {
_this2.selectTimer += elapsedTime;
if (_this2.selectTimer >= _this2.selectDuration) {
_this2.selectTimer = 0;
selected = true;
}
} else {
_this2.selectTimer = 0;
} // set cursor material to show the timer state
var fromStart = 0;
var fromEnd = _this2.selectDuration;
var toStart = -0.5;
var toEnd = 0.5;
_this2.cursorTexture.offset.x = THREE.MathUtils.mapLinear(_this2.selectTimer, fromStart, fromEnd, toStart, toEnd);
return selected ? _this2.pickedObject : undefined;
});
_defineProperty(this, "setObjectInteractionHandler", function (callback) {
_this2.onObjectInteractionHandler = callback;
});
_defineProperty(this, "updateInteractionObjects", function (objs, time) {
_this2.objects = objs;
_this2.time = time;
});
_defineProperty(this, "render", function (scene, camera) {
if (_this2.vrStatus) {
_this2.effect.render(scene, camera);
var pickedObject = _this2.pick({
x: 0,
y: 0
}, camera, _this2.time, Array.from(_this2.objects));
if (!!pickedObject) {
_this2.onObjectInteractionHandler && _this2.onObjectInteractionHandler(pickedObject);
}
}
});
_defineProperty(this, "enable", function () {
_this2.vrStatus = true;
_this2.cursor.visible = true;
_this2.cone.visible = true;
});
_defineProperty(this, "disable", function () {
_this2.vrStatus = false;
_this2.cursor.visible = false;
_this2.cone.visible = false;
});
this.renderer = renderer;
this.camera = _camera;
this.effect = new StereoEffect(renderer);
this.vrStatus = false;
this.cursor = null;
this.cone = null;
this.raycaster = new THREE.Raycaster();
this.pickedObject = null;
this.initCursor();
this.initCone();
this.selectTimer = 0;
this.selectDuration = 2;
this.lastTime = 0;
this.objects = []; // 可交互object
this.time = 0; // 热点触发计时器
this.onObjectInteractionHandler = null;
};
var _default = VRHelper;
exports.default = _default;