From 6c5afa39b9084b3c9624f90576a894ca2b016773 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Wed, 14 Apr 2021 22:08:16 +0200 Subject: [PATCH 01/65] add typescript conf --- package.json | 7 +++++-- tsconfig.json | 11 +++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tsconfig.json diff --git a/package.json b/package.json index c63b380..c87dfff 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,13 @@ "version": "0.2.3", "scripts": { "dev": "vite", - "build": "vite build", + "build": "vue-tsc --noEmit && vite build", "rollup": "rollup -c" }, "devDependencies": { "@rollup/plugin-buble": "^0.21.3", "@rollup/plugin-replace": "^2.3.3", + "@types/three": "^0.127.1", "@vitejs/plugin-vue": "^1.2.1", "@vue/compiler-sfc": "^3.0.11", "cannon": "^0.6.2", @@ -25,8 +26,10 @@ "rollup-plugin-vue": "^6.0.0-beta.11", "stats.js": "0.17.0", "three": "^0.127", + "typescript": "^4.1.3", "vite": "^2.1.5", - "vue": "^3.0.11" + "vue": "^3.0.11", + "vue-tsc": "^0.0.15" }, "main": "build/trois.js", "module": "build/trois.module.js", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b1ffd42 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + // this enables stricter inference for data properties on `this` + "strict": true, + "jsx": "preserve", + "moduleResolution": "node", + }, + "include": ["src"] +} From 6bbb80710db63ca27d409de15f9636f9e77df50f Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Thu, 15 Apr 2021 17:50:41 +0200 Subject: [PATCH 02/65] update typescript/eslint conf --- .eslintrc.js | 29 +++++++++++++++++++++-------- package.json | 11 +++++++---- tsconfig.json | 4 ++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 93240c8..849d004 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,22 +1,28 @@ -/* eslint-disable quote-props */ module.exports = { + root: true, env: { browser: true, es2020: true, + node: true, }, extends: [ 'plugin:vue/essential', + '@vue/standard', + '@vue/typescript/recommended', 'standard', ], + parser: 'vue-eslint-parser', parserOptions: { - ecmaVersion: 12, - sourceType: 'module', + parser: '@typescript-eslint/parser', }, - plugins: [ - 'vue', - ], + // parserOptions: { + // ecmaVersion: 2020, + // }, rules: { - 'semi': [2, 'always'], + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + + 'semi': ['error', 'never'], 'space-before-function-paren': 'off', 'one-var': 'off', 'quotes': 'off', @@ -36,5 +42,12 @@ module.exports = { 'object-property-newline': 'off', 'eqeqeq': 'warn', 'no-multiple-empty-lines': 'off', + + '@typescript-eslint/ban-ts-comment': 'warn', + // '@typescript-eslint/ban-ts-comment': ['warn', { + // 'ts-ignore': 'allow-with-description', + // }], + // 'vue/valid-template-root': 'off', + 'vue/no-multiple-template-root': 'off', }, -}; +} diff --git a/package.json b/package.json index c87dfff..3a8181e 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,19 @@ "@rollup/plugin-buble": "^0.21.3", "@rollup/plugin-replace": "^2.3.3", "@types/three": "^0.127.1", + "@typescript-eslint/eslint-plugin": "^4.22.0", + "@typescript-eslint/parser": "^4.22.0", "@vitejs/plugin-vue": "^1.2.1", "@vue/compiler-sfc": "^3.0.11", + "@vue/eslint-config-standard": "^5.1.2", + "@vue/eslint-config-typescript": "^7.0.0", "cannon": "^0.6.2", "eslint": "^7.7.0", - "eslint-config-airbnb-base": "^14.2.0", - "eslint-config-standard": "^14.1.1", "eslint-plugin-import": "^2.22.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", - "eslint-plugin-vue": "^6.2.2", + "eslint-plugin-vue": "^7.9.0", "gsap": "^3.5.1", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-vue": "^6.0.0-beta.11", @@ -29,7 +31,8 @@ "typescript": "^4.1.3", "vite": "^2.1.5", "vue": "^3.0.11", - "vue-tsc": "^0.0.15" + "vue-eslint-parser": "^7.6.0", + "vue-tsc": "^0.0.24" }, "main": "build/trois.js", "module": "build/trois.module.js", diff --git a/tsconfig.json b/tsconfig.json index b1ffd42..6165f54 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,8 @@ "module": "esnext", // this enables stricter inference for data properties on `this` "strict": true, - "jsx": "preserve", "moduleResolution": "node", }, - "include": ["src"] + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": [ "node_modules" ] } From 154fd7439c01be152ad38ccfb04c1fd8aaec9d02 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Fri, 16 Apr 2021 00:54:11 +0200 Subject: [PATCH 03/65] wip --- src/core/usePointer.js | 175 ----------------------- src/core/usePointer.ts | 225 +++++++++++++++++++++++++++++ src/core/useThree.js | 264 ---------------------------------- src/core/useThree.ts | 311 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 536 insertions(+), 439 deletions(-) delete mode 100644 src/core/usePointer.js create mode 100644 src/core/usePointer.ts delete mode 100644 src/core/useThree.js create mode 100644 src/core/useThree.ts diff --git a/src/core/usePointer.js b/src/core/usePointer.js deleted file mode 100644 index a8f8751..0000000 --- a/src/core/usePointer.js +++ /dev/null @@ -1,175 +0,0 @@ -import { InstancedMesh, Vector2, Vector3 } from 'three'; -import useRaycaster from './useRaycaster'; - -export default function usePointer(options) { - const { - camera, - domElement, - intersectObjects, - touch = true, - resetOnEnd = false, - resetPosition = new Vector2(0, 0), - resetPositionV3 = new Vector3(0, 0, 0), - onEnter = () => {}, - onMove = () => {}, - onLeave = () => {}, - onIntersectEnter = () => {}, - onIntersectOver = () => {}, - onIntersectMove = () => {}, - onIntersectLeave = () => {}, - onIntersectClick = () => {}, - } = options; - - const position = resetPosition.clone(); - const positionN = new Vector2(0, 0); - - const raycaster = useRaycaster({ camera }); - const positionV3 = raycaster.position; - - const obj = { - position, - positionN, - positionV3, - intersectObjects, - listeners: false, - addListeners, - removeListeners, - intersect, - }; - - return obj; - - function reset() { - position.copy(resetPosition); - positionV3.copy(resetPositionV3); - }; - - function updatePosition(event) { - let x, y; - if (event.touches && event.touches.length > 0) { - x = event.touches[0].clientX; - y = event.touches[0].clientY; - } else { - x = event.clientX; - y = event.clientY; - } - - const rect = domElement.getBoundingClientRect(); - position.x = x - rect.left; - position.y = y - rect.top; - positionN.x = (position.x / rect.width) * 2 - 1; - positionN.y = -(position.y / rect.height) * 2 + 1; - raycaster.updatePosition(positionN); - }; - - function intersect() { - if (intersectObjects.length) { - const intersects = raycaster.intersect(positionN, intersectObjects); - const offObjects = [...intersectObjects]; - const iMeshes = []; - - intersects.forEach(intersect => { - const { object } = intersect; - const { component } = object; - - // only once for InstancedMesh - if (object instanceof InstancedMesh) { - if (iMeshes.indexOf(object) !== -1) return; - iMeshes.push(object); - } - - if (!object.over) { - object.over = true; - const overEvent = { type: 'pointerover', over: true, component, intersect }; - const enterEvent = { ...overEvent, type: 'pointerenter' }; - onIntersectOver(overEvent); - onIntersectEnter(enterEvent); - if (component.onPointerOver) component.onPointerOver(overEvent); - if (component.onPointerEnter) component.onPointerEnter(enterEvent); - } - - const moveEvent = { type: 'pointermove', component, intersect }; - onIntersectMove(moveEvent); - if (component.onPointerMove) component.onPointerMove(moveEvent); - - offObjects.splice(offObjects.indexOf(object), 1); - }); - - offObjects.forEach(object => { - const { component } = object; - if (object.over) { - object.over = false; - const overEvent = { type: 'pointerover', over: false, component }; - const leaveEvent = { ...overEvent, type: 'pointerleave' }; - onIntersectOver(overEvent); - onIntersectLeave(leaveEvent); - if (component.onPointerOver) component.onPointerOver(overEvent); - if (component.onPointerLeave) component.onPointerLeave(leaveEvent); - } - }); - } - }; - - function pointerEnter(event) { - updatePosition(event); - onEnter({ type: 'pointerenter', position, positionN, positionV3 }); - }; - - function pointerMove(event) { - updatePosition(event); - onMove({ type: 'pointermove', position, positionN, positionV3 }); - intersect(); - }; - - function pointerClick(event) { - updatePosition(event); - if (intersectObjects.length) { - const intersects = raycaster.intersect(positionN, intersectObjects); - const iMeshes = []; - intersects.forEach(intersect => { - const { object } = intersect; - const { component } = object; - - // only once for InstancedMesh - if (object instanceof InstancedMesh) { - if (iMeshes.indexOf(object) !== -1) return; - iMeshes.push(object); - } - - const event = { type: 'click', component, intersect }; - onIntersectClick(event); - if (component.onClick) component.onClick(event); - }); - } - }; - - function pointerLeave() { - if (resetOnEnd) reset(); - onLeave({ type: 'pointerleave' }); - }; - - function addListeners() { - domElement.addEventListener('mouseenter', pointerEnter); - domElement.addEventListener('mousemove', pointerMove); - domElement.addEventListener('mouseleave', pointerLeave); - domElement.addEventListener('click', pointerClick); - if (touch) { - domElement.addEventListener('touchstart', pointerEnter); - domElement.addEventListener('touchmove', pointerMove); - domElement.addEventListener('touchend', pointerLeave); - } - obj.listeners = true; - }; - - function removeListeners() { - domElement.removeEventListener('mouseenter', pointerEnter); - domElement.removeEventListener('mousemove', pointerMove); - domElement.removeEventListener('mouseleave', pointerLeave); - domElement.removeEventListener('click', pointerClick); - - domElement.removeEventListener('touchstart', pointerEnter); - domElement.removeEventListener('touchmove', pointerMove); - domElement.removeEventListener('touchend', pointerLeave); - obj.listeners = false; - }; -}; diff --git a/src/core/usePointer.ts b/src/core/usePointer.ts new file mode 100644 index 0000000..85eb9ff --- /dev/null +++ b/src/core/usePointer.ts @@ -0,0 +1,225 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ +import { Camera, InstancedMesh, Intersection, Mesh, Vector2, Vector3 } from 'three' +import useRaycaster from './useRaycaster' + +export interface PointerEventInterface { + type: 'pointerenter' | 'pointermove' | 'pointerleave' | 'click' + position?: Vector2 + positionN?: Vector2 + positionV3?: Vector3 +} + +export interface PointerIntersectEventInterface { + type: 'pointerenter' | 'pointerover' | 'pointermove' | 'pointerleave' | 'click' + component: any + over?: boolean + intersect?: Intersection +} + +export type IntersectObject = Mesh | InstancedMesh + +export interface PointerConfigInterface { + camera: Camera + domElement: HTMLCanvasElement + intersectObjects: IntersectObject[] + intersectMode?: 'frame' + touch?: boolean + resetOnEnd?: boolean + resetPosition?: Vector2 + resetPositionV3?: Vector3 + onEnter?(e: PointerEventInterface): void + onMove?(e: PointerEventInterface): void + onLeave?(e: PointerEventInterface): void + onClick?(e: PointerEventInterface): void + onIntersectEnter?(e: PointerIntersectEventInterface): void + onIntersectOver?(e: PointerIntersectEventInterface): void + onIntersectMove?(e: PointerIntersectEventInterface): void + onIntersectLeave?(e: PointerIntersectEventInterface): void + onIntersectClick?(e: PointerIntersectEventInterface): void +} + +export interface PointerInterface { + position: Vector2 + positionN: Vector2 + positionV3: Vector3 + intersectObjects: IntersectObject[] + listeners: boolean + addListeners(cb: void): void + removeListeners(cb: void): void + intersect(): void +} + +export default function usePointer(options: PointerConfigInterface): PointerInterface { + const { + camera, + domElement, + intersectObjects, + touch = true, + resetOnEnd = false, + resetPosition = new Vector2(0, 0), + resetPositionV3 = new Vector3(0, 0, 0), + onEnter = () => {}, + onMove = () => {}, + onLeave = () => {}, + onClick = () => {}, + onIntersectEnter = () => {}, + onIntersectOver = () => {}, + onIntersectMove = () => {}, + onIntersectLeave = () => {}, + onIntersectClick = () => {}, + } = options + + const position = resetPosition.clone() + const positionN = new Vector2(0, 0) + + const raycaster = useRaycaster({ camera }) + const positionV3 = raycaster.position + + const obj: PointerInterface = { + position, + positionN, + positionV3, + intersectObjects, + listeners: false, + addListeners, + removeListeners, + intersect, + } + + return obj + + function reset() { + position.copy(resetPosition) + positionV3.copy(resetPositionV3) + } + + function updatePosition(event: TouchEvent | MouseEvent) { + let x, y + if (event instanceof TouchEvent && event.touches && event.touches.length > 0) { + x = (event).touches[0].clientX + y = (event).touches[0].clientY + } else { + x = (event).clientX + y = (event).clientY + } + + const rect = domElement.getBoundingClientRect() + position.x = x - rect.left + position.y = y - rect.top + positionN.x = (position.x / rect.width) * 2 - 1 + positionN.y = -(position.y / rect.height) * 2 + 1 + raycaster.updatePosition(positionN) + } + + function intersect() { + if (intersectObjects.length) { + const intersects = raycaster.intersect(positionN, intersectObjects) + const offObjects: IntersectObject[] = [...intersectObjects] + const iMeshes: InstancedMesh[] = [] + + intersects.forEach(intersect => { + const { object } = intersect + const { component } = object.userData + + // only once for InstancedMesh + if (object instanceof InstancedMesh) { + if (iMeshes.indexOf(object) !== -1) return + iMeshes.push(object) + } + + if (!object.userData.over) { + object.userData.over = true + const overEvent: PointerIntersectEventInterface = { type: 'pointerover', over: true, component, intersect } + const enterEvent: PointerIntersectEventInterface = { ...overEvent, type: 'pointerenter' } + onIntersectOver(overEvent) + onIntersectEnter(enterEvent) + component.onPointerOver?.(overEvent) + component.onPointerEnter?.(enterEvent) + } + + const moveEvent: PointerIntersectEventInterface = { type: 'pointermove', component, intersect } + onIntersectMove(moveEvent) + component.onPointerMove?.(moveEvent) + + offObjects.splice(offObjects.indexOf((object)), 1) + }) + + offObjects.forEach(object => { + const { component } = object.userData + if (object.userData.over) { + object.userData.over = false + const overEvent: PointerIntersectEventInterface = { type: 'pointerover', over: false, component } + const leaveEvent: PointerIntersectEventInterface = { ...overEvent, type: 'pointerleave' } + onIntersectOver(overEvent) + onIntersectLeave(leaveEvent) + component.onPointerOver?.(overEvent) + component.onPointerLeave?.(leaveEvent) + } + }) + } + } + + function pointerEnter(event: TouchEvent | MouseEvent) { + updatePosition(event) + onEnter({ type: 'pointerenter', position, positionN, positionV3 }) + } + + function pointerMove(event: TouchEvent | MouseEvent) { + updatePosition(event) + onMove({ type: 'pointermove', position, positionN, positionV3 }) + intersect() + } + + function pointerClick(event: TouchEvent | MouseEvent) { + updatePosition(event) + if (intersectObjects.length) { + const intersects = raycaster.intersect(positionN, intersectObjects) + const iMeshes: InstancedMesh[] = [] + intersects.forEach(intersect => { + const { object } = intersect + const { component } = object.userData + + // only once for InstancedMesh + if (object instanceof InstancedMesh) { + if (iMeshes.indexOf(object) !== -1) return + iMeshes.push(object) + } + + const event: PointerIntersectEventInterface = { type: 'click', component, intersect } + onIntersectClick(event) + component.onClick?.(event) + }) + } + onClick({ type: 'click', position, positionN, positionV3 }) + } + + function pointerLeave() { + if (resetOnEnd) reset() + onLeave({ type: 'pointerleave' }) + } + + function addListeners() { + domElement.addEventListener('mouseenter', pointerEnter) + domElement.addEventListener('mousemove', pointerMove) + domElement.addEventListener('mouseleave', pointerLeave) + domElement.addEventListener('click', pointerClick) + if (touch) { + domElement.addEventListener('touchstart', pointerEnter) + domElement.addEventListener('touchmove', pointerMove) + domElement.addEventListener('touchend', pointerLeave) + } + obj.listeners = true + } + + function removeListeners() { + domElement.removeEventListener('mouseenter', pointerEnter) + domElement.removeEventListener('mousemove', pointerMove) + domElement.removeEventListener('mouseleave', pointerLeave) + domElement.removeEventListener('click', pointerClick) + + domElement.removeEventListener('touchstart', pointerEnter) + domElement.removeEventListener('touchmove', pointerMove) + domElement.removeEventListener('touchend', pointerLeave) + obj.listeners = false + } +} diff --git a/src/core/useThree.js b/src/core/useThree.js deleted file mode 100644 index 6295902..0000000 --- a/src/core/useThree.js +++ /dev/null @@ -1,264 +0,0 @@ -import { WebGLRenderer } from 'three'; -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; -import usePointer from './usePointer'; - -/** - * Three.js helper - */ -export default function useThree() { - // default conf - const conf = { - canvas: null, - antialias: true, - alpha: false, - autoClear: true, - orbit_ctrl: false, - pointer: false, - resize: false, - width: 300, - height: 150, - }; - - // size - const size = { - width: 1, height: 1, - wWidth: 1, wHeight: 1, - ratio: 1, - }; - - // handlers - const afterInitCallbacks = []; - let afterResizeCallbacks = []; - let beforeRenderCallbacks = []; - - const intersectObjects = []; - - // returned object - const obj = { - conf, - renderer: null, - camera: null, - cameraCtrl: null, - scene: null, - pointer: null, - size, - init, - dispose, - render, - renderC, - setSize, - onAfterInit, - onAfterResize, offAfterResize, - // onBeforeRender, offBeforeRender, - addIntersectObject, removeIntersectObject, - }; - - /** - * init three - */ - function init(params) { - if (params) { - Object.entries(params).forEach(([key, value]) => { - conf[key] = value; - }); - } - - if (!obj.scene) { - console.error('Missing Scene'); - return; - } - - if (!obj.camera) { - console.error('Missing Camera'); - return; - } - - obj.renderer = new WebGLRenderer({ canvas: conf.canvas, antialias: conf.antialias, alpha: conf.alpha }); - obj.renderer.autoClear = conf.autoClear; - - if (conf.resize) { - onResize(); - window.addEventListener('resize', onResize); - } else { - setSize(conf.width, conf.height); - } - - initPointer(); - - if (conf.orbit_ctrl) { - obj.orbitCtrl = new OrbitControls(obj.camera, obj.renderer.domElement); - if (conf.orbit_ctrl instanceof Object) { - Object.entries(conf.orbit_ctrl).forEach(([key, value]) => { - obj.orbitCtrl[key] = value; - }); - } - } - - afterInitCallbacks.forEach(c => c()); - - return true; - }; - - function initPointer() { - let pointerConf = { - camera: obj.camera, - domElement: obj.renderer.domElement, - intersectObjects, - }; - - if (conf.pointer && conf.pointer instanceof Object) { - pointerConf = { ...pointerConf, ...conf.pointer }; - } - - obj.pointer = usePointer(pointerConf); - if (conf.pointer || intersectObjects.length) { - obj.pointer.addListeners(); - if (conf.pointer.intersectMode === 'frame') { - onBeforeRender(() => { - obj.pointer.intersect(); - }); - } - } - } - - /** - * add after init callback - */ - function onAfterInit(callback) { - afterInitCallbacks.push(callback); - } - - /** - * add after resize callback - */ - function onAfterResize(callback) { - afterResizeCallbacks.push(callback); - } - - /** - * remove after resize callback - */ - function offAfterResize(callback) { - afterResizeCallbacks = afterResizeCallbacks.filter(c => c !== callback); - } - - /** - * add before render callback - */ - function onBeforeRender(callback) { - beforeRenderCallbacks.push(callback); - } - - /** - * remove before render callback - */ - function offBeforeRender(callback) { - beforeRenderCallbacks = beforeRenderCallbacks.filter(c => c !== callback); - } - - /** - * default render - */ - function render() { - if (obj.orbitCtrl) obj.orbitCtrl.update(); - beforeRenderCallbacks.forEach(c => c()); - obj.renderer.render(obj.scene, obj.camera); - } - - /** - * composer render - */ - function renderC() { - if (obj.orbitCtrl) obj.orbitCtrl.update(); - beforeRenderCallbacks.forEach(c => c()); - obj.composer.render(); - } - - /** - * add intersect object - */ - function addIntersectObject(o) { - if (intersectObjects.indexOf(o) === -1) { - intersectObjects.push(o); - } - // add listeners if needed - if (obj.pointer && !obj.pointer.listeners) { - obj.pointer.addListeners(); - } - } - - /** - * remove intersect object - */ - function removeIntersectObject(o) { - const i = intersectObjects.indexOf(o); - if (i !== -1) { - intersectObjects.splice(i, 1); - } - // remove listeners if needed - if (obj.pointer && !conf.pointer && intersectObjects.length === 0) { - obj.pointer.removeListeners(); - } - } - - /** - * remove listeners and dispose - */ - function dispose() { - beforeRenderCallbacks = []; - window.removeEventListener('resize', onResize); - if (obj.pointer) obj.pointer.removeListeners(); - if (obj.orbitCtrl) obj.orbitCtrl.dispose(); - if (obj.renderer) obj.renderer.dispose(); - } - - /** - * resize listener - */ - function onResize() { - if (conf.resize === 'window') { - setSize(window.innerWidth, window.innerHeight); - } else { - const elt = obj.renderer.domElement.parentNode; - setSize(elt.clientWidth, elt.clientHeight); - } - afterResizeCallbacks.forEach(c => c()); - } - - /** - * update renderer size and camera - */ - function setSize(width, height) { - size.width = width; - size.height = height; - size.ratio = width / height; - - obj.renderer.setSize(width, height, false); - obj.camera.aspect = size.ratio; - obj.camera.updateProjectionMatrix(); - - if (obj.composer) { - obj.composer.setSize(width, height); - } - - if (obj.camera.type === 'OrthographicCamera') { - size.wWidth = obj.camera.right - obj.camera.left; - size.wHeight = obj.camera.top - obj.camera.bottom; - } else { - const wsize = getCameraSize(); - size.wWidth = wsize[0]; size.wHeight = wsize[1]; - } - } - - /** - * calculate camera visible area size - */ - function getCameraSize() { - const vFOV = (obj.camera.fov * Math.PI) / 180; - const h = 2 * Math.tan(vFOV / 2) * Math.abs(obj.camera.position.z); - const w = h * obj.camera.aspect; - return [w, h]; - } - - return obj; -} diff --git a/src/core/useThree.ts b/src/core/useThree.ts new file mode 100644 index 0000000..dc0c22c --- /dev/null +++ b/src/core/useThree.ts @@ -0,0 +1,311 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { Camera, OrthographicCamera, PerspectiveCamera, Scene, WebGLRenderer } from 'three' +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' +import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js' +import usePointer, { IntersectObject, PointerConfigInterface, PointerInterface } from './usePointer' + +export interface ConfigInterface { + canvas?: HTMLCanvasElement + antialias: boolean + alpha: boolean + autoClear: boolean + orbitCtrl: boolean | Record + pointer: boolean | PointerConfigInterface + resize: boolean | 'window' + width: number + height: number + [index:string]: any +} + +export interface SizeInterface { + width: number + height: number + wWidth: number + wHeight: number + ratio: number +} + +export interface ThreeInterface { + conf: ConfigInterface + renderer?: WebGLRenderer + camera?: Camera + cameraCtrl?: OrbitControls + scene?: Scene + pointer?: PointerInterface + size: SizeInterface + composer?: EffectComposer + init(config: ConfigInterface): boolean + dispose(): void + render(): void + renderC(): void + setSize(width: number, height: number): void + onAfterInit(callback: {(): void}): void + onAfterResize(callback: {(): void}): void + offAfterResize(callback: {(): void}): void + addIntersectObject(o: IntersectObject): void + removeIntersectObject(o: IntersectObject): void +} + +/** + * Three.js helper + */ +export default function useThree(): ThreeInterface { + // default conf + const conf: ConfigInterface = { + antialias: true, + alpha: false, + autoClear: true, + orbitCtrl: false, + pointer: false, + resize: false, + width: 300, + height: 150, + } + + // size + const size: SizeInterface = { + width: 1, height: 1, + wWidth: 1, wHeight: 1, + ratio: 1, + } + + // handlers + // const afterInitCallbacks: void[] = [] + // let afterResizeCallbacks: void[] = [] + // let beforeRenderCallbacks: void[] = [] + const afterInitCallbacks: {(): void;}[] = [] + let afterResizeCallbacks: {(): void;}[] = [] + let beforeRenderCallbacks: {(): void;}[] = [] + + const intersectObjects: IntersectObject[] = [] + + // returned object + const obj: ThreeInterface = { + conf, + size, + init, + dispose, + render, + renderC, + setSize, + onAfterInit, + onAfterResize, offAfterResize, + addIntersectObject, removeIntersectObject, + } + + return obj + + /** + * init three + */ + function init(params: ConfigInterface) { + if (params) { + Object.entries(params).forEach(([key, value]) => { + conf[key] = value + }) + } + + if (!obj.scene) { + console.error('Missing Scene') + return false + } + + if (!obj.camera) { + console.error('Missing Camera') + return false + } + + obj.renderer = new WebGLRenderer({ canvas: conf.canvas, antialias: conf.antialias, alpha: conf.alpha }) + obj.renderer.autoClear = conf.autoClear + + if (conf.resize) { + onResize() + window.addEventListener('resize', onResize) + } else { + setSize(conf.width, conf.height) + } + + initPointer() + + if (conf.orbitCtrl) { + obj.cameraCtrl = new OrbitControls(obj.camera, obj.renderer.domElement) + if (conf.orbitCtrl instanceof Object) { + Object.entries(conf.orbitCtrl).forEach(([key, value]) => { + // @ts-ignore + obj.cameraCtrl[key] = value + }) + } + } + + afterInitCallbacks.forEach(c => c()) + + return true + } + + function initPointer() { + let pointerConf: PointerConfigInterface = { + camera: obj.camera!, + domElement: obj.renderer!.domElement, + intersectObjects, + } + + if (conf.pointer && conf.pointer instanceof Object) { + pointerConf = { ...pointerConf, ...conf.pointer } + } + + const pointer = obj.pointer = usePointer(pointerConf) + if (conf.pointer || intersectObjects.length) { + pointer.addListeners() + if (pointerConf.intersectMode === 'frame') { + onBeforeRender(pointer.intersect) + } + } + } + + /** + * add after init callback + */ + function onAfterInit(callback: {(): void}) { + afterInitCallbacks.push(callback) + } + + /** + * add after resize callback + */ + function onAfterResize(callback: {(): void}) { + afterResizeCallbacks.push(callback) + } + + /** + * remove after resize callback + */ + function offAfterResize(callback: {(): void}) { + afterResizeCallbacks = afterResizeCallbacks.filter(c => c !== callback) + } + + /** + * add before render callback + */ + function onBeforeRender(callback: {(): void}) { + beforeRenderCallbacks.push(callback) + } + + /** + * remove before render callback + */ + // function offBeforeRender(callback: void) { + // beforeRenderCallbacks = beforeRenderCallbacks.filter(c => c !== callback) + // } + + /** + * default render + */ + function render() { + if (obj.cameraCtrl) obj.cameraCtrl.update() + beforeRenderCallbacks.forEach(c => c()) + obj.renderer!.render(obj.scene!, obj.camera!) + } + + /** + * composer render + */ + function renderC() { + if (obj.cameraCtrl) obj.cameraCtrl.update() + beforeRenderCallbacks.forEach(c => c()) + obj.composer!.render() + } + + /** + * add intersect object + */ + function addIntersectObject(o: IntersectObject) { + if (intersectObjects.indexOf(o) === -1) { + intersectObjects.push(o) + } + // add listeners if needed + if (obj.pointer && !obj.pointer.listeners) { + obj.pointer.addListeners() + } + } + + /** + * remove intersect object + */ + function removeIntersectObject(o: IntersectObject) { + const i = intersectObjects.indexOf(o) + if (i !== -1) { + intersectObjects.splice(i, 1) + } + // remove listeners if needed + if (obj.pointer && !conf.pointer && intersectObjects.length === 0) { + obj.pointer.removeListeners() + } + } + + /** + * remove listeners and dispose + */ + function dispose() { + beforeRenderCallbacks = [] + window.removeEventListener('resize', onResize) + if (obj.pointer) obj.pointer.removeListeners() + if (obj.cameraCtrl) obj.cameraCtrl.dispose() + if (obj.renderer) obj.renderer.dispose() + } + + /** + * resize listener + */ + function onResize() { + if (conf.resize === 'window') { + setSize(window.innerWidth, window.innerHeight) + } else { + const elt = obj.renderer!.domElement.parentNode as Element + if (elt) setSize(elt.clientWidth, elt.clientHeight) + } + afterResizeCallbacks.forEach(c => c()) + } + + /** + * update renderer size and camera + */ + function setSize(width: number, height: number) { + size.width = width + size.height = height + size.ratio = width / height + + obj.renderer!.setSize(width, height, false) + + // already done in EffectComposer + // if (obj.composer) { + // obj.composer.setSize(width, height) + // } + + const camera = (obj.camera!) + if (camera.type === 'PerspectiveCamera') { + const pCamera = (camera) + pCamera.aspect = size.ratio + pCamera.updateProjectionMatrix() + } + + if (camera.type === 'OrthographicCamera') { + const oCamera = (camera) + size.wWidth = oCamera.right - oCamera.left + size.wHeight = oCamera.top - oCamera.bottom + } else { + const wsize = getCameraSize() + size.wWidth = wsize[0]; size.wHeight = wsize[1] + } + } + + /** + * calculate camera visible area size + */ + function getCameraSize() { + const camera = (obj.camera!) + const vFOV = (camera.fov * Math.PI) / 180 + const h = 2 * Math.tan(vFOV / 2) * Math.abs(camera.position.z) + const w = h * camera.aspect + return [w, h] + } +} From d2006b1f2c7202fb7f94e723133b478dfdc441d8 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Fri, 16 Apr 2021 01:56:52 +0200 Subject: [PATCH 04/65] wip --- index.html | 2 +- src/components/liquid/LiquidPlane.js | 10 +- src/components/meshes/Gem.js | 6 +- src/components/meshes/MirrorMesh.js | 6 +- src/components/meshes/RefractionMesh.js | 6 +- src/components/misc/Stats.js | 10 +- src/components/noisy/NoisyImage.js | 4 +- src/components/noisy/NoisyPlane.js | 4 +- src/components/noisy/NoisySphere.js | 4 +- src/components/noisy/NoisyText.js | 4 +- src/components/physics/CannonWorld.js | 6 +- src/components/sliders/Slider1.vue | 2 +- src/components/sliders/Slider2.vue | 2 +- src/components/viewers/GLTFViewer.vue | 2 +- src/core/{Camera.js => Camera.ts} | 8 +- src/core/Group.js | 13 -- src/core/Group.ts | 17 +++ src/core/Object3D.js | 70 ----------- src/core/Object3D.ts | 71 +++++++++++ ...graphicCamera.js => OrthographicCamera.ts} | 2 +- ...spectiveCamera.js => PerspectiveCamera.ts} | 2 +- src/core/{Raycaster.js => Raycaster.ts} | 8 +- src/core/Renderer.js | 105 ---------------- src/core/Renderer.ts | 113 ++++++++++++++++++ src/core/{Scene.js => Scene.ts} | 0 src/core/index.js | 16 +-- src/core/{useRaycaster.js => useRaycaster.ts} | 0 src/core/useThree.ts | 18 +-- src/lights/Light.js | 2 +- src/main.js | 7 -- src/main.ts | 7 ++ src/meshes/Mesh.js | 2 +- src/meshes/Sprite.js | 2 +- src/models/Model.js | 2 +- src/{plugin.js => plugin.ts} | 0 src/tools.js | 81 ------------- src/tools.ts | 84 +++++++++++++ 37 files changed, 357 insertions(+), 341 deletions(-) rename src/core/{Camera.js => Camera.ts} (60%) delete mode 100644 src/core/Group.js create mode 100644 src/core/Group.ts delete mode 100644 src/core/Object3D.js create mode 100644 src/core/Object3D.ts rename src/core/{OrthographicCamera.js => OrthographicCamera.ts} (96%) rename src/core/{PerspectiveCamera.js => PerspectiveCamera.ts} (97%) rename src/core/{Raycaster.js => Raycaster.ts} (84%) delete mode 100644 src/core/Renderer.js create mode 100644 src/core/Renderer.ts rename src/core/{Scene.js => Scene.ts} (100%) rename src/core/{useRaycaster.js => useRaycaster.ts} (100%) delete mode 100644 src/main.js create mode 100644 src/main.ts rename src/{plugin.js => plugin.ts} (100%) delete mode 100644 src/tools.js create mode 100644 src/tools.ts diff --git a/index.html b/index.html index 883edf9..0626100 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,6 @@
- + diff --git a/src/components/liquid/LiquidPlane.js b/src/components/liquid/LiquidPlane.js index 9a7d455..eb1a916 100644 --- a/src/components/liquid/LiquidPlane.js +++ b/src/components/liquid/LiquidPlane.js @@ -1,6 +1,6 @@ import { defineComponent, watch } from 'vue'; import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three'; -import Object3D from '../../core/Object3D.js'; +import Object3D from '../../core/Object3D'; import { bindProps } from '../../tools'; import LiquidEffect from './LiquidEffect.js'; @@ -17,9 +17,9 @@ export default defineComponent({ }, mounted() { this.liquidEffect = new LiquidEffect(this.three.renderer); - this.rendererComponent.onMounted(() => { - this.liquidEffect.renderer = this.rendererComponent.renderer; - this.rendererComponent.onBeforeRender(this.update); + this.renderer.onMounted(() => { + this.liquidEffect.renderer = this.renderer.renderer; + this.renderer.onBeforeRender(this.update); }); this.material = new MeshStandardMaterial({ color: this.color, side: DoubleSide, metalness: this.metalness, roughness: this.roughness, @@ -44,7 +44,7 @@ export default defineComponent({ this.initObject3D(this.mesh); }, unmounted() { - this.rendererComponent.offBeforeRender(this.update); + this.renderer.offBeforeRender(this.update); }, methods: { update() { diff --git a/src/components/meshes/Gem.js b/src/components/meshes/Gem.js index 1e05486..cb26e92 100644 --- a/src/components/meshes/Gem.js +++ b/src/components/meshes/Gem.js @@ -21,11 +21,11 @@ export default defineComponent({ }, mounted() { this.initGem(); - if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT); - else this.rendererComponent.onMounted(this.updateCubeRT); + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); + else this.renderer.onMounted(this.updateCubeRT); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateCubeRT); + this.renderer.offBeforeRender(this.updateCubeRT); if (this.cubeCamera) this.removeFromParent(this.cubeCamera); if (this.meshBack) this.removeFromParent(this.meshBack); if (this.materialBack) this.materialBack.dispose(); diff --git a/src/components/meshes/MirrorMesh.js b/src/components/meshes/MirrorMesh.js index bef5dd6..c81980d 100644 --- a/src/components/meshes/MirrorMesh.js +++ b/src/components/meshes/MirrorMesh.js @@ -17,11 +17,11 @@ export default defineComponent({ }, mounted() { this.initMirrorMesh(); - if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT); - else this.rendererComponent.onMounted(this.updateCubeRT); + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); + else this.renderer.onMounted(this.updateCubeRT); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateCubeRT); + this.renderer.offBeforeRender(this.updateCubeRT); if (this.cubeCamera) this.removeFromParent(this.cubeCamera); }, methods: { diff --git a/src/components/meshes/RefractionMesh.js b/src/components/meshes/RefractionMesh.js index 891633c..41fad69 100644 --- a/src/components/meshes/RefractionMesh.js +++ b/src/components/meshes/RefractionMesh.js @@ -20,11 +20,11 @@ export default defineComponent({ }, mounted() { this.initMirrorMesh(); - if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT); - else this.rendererComponent.onMounted(this.updateCubeRT); + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); + else this.renderer.onMounted(this.updateCubeRT); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateCubeRT); + this.renderer.offBeforeRender(this.updateCubeRT); if (this.cubeCamera) this.removeFromParent(this.cubeCamera); }, methods: { diff --git a/src/components/misc/Stats.js b/src/components/misc/Stats.js index 5ef9d95..d2b4dc2 100644 --- a/src/components/misc/Stats.js +++ b/src/components/misc/Stats.js @@ -5,7 +5,7 @@ export default { noSetup: { type: Boolean, default: false }, }, emits: ['created'], - inject: ['rendererComponent'], + inject: ['renderer'], setup({ noSetup }) { const stats = new Stats(); if (!noSetup) { @@ -16,8 +16,8 @@ export default { }, mounted() { if (!this.noSetup) { - this.rendererComponent.onBeforeRender(this.begin); - this.rendererComponent.onAfterRender(this.end); + this.renderer.onBeforeRender(this.begin); + this.renderer.onAfterRender(this.end); } this.$emit('created', { stats: this.stats }); }, @@ -37,8 +37,8 @@ export default { if (this.stats && this.stats.dom) { this.stats.dom.parentElement.removeChild(this.stats.dom); } - this.rendererComponent.offBeforeRender(this.begin); - this.rendererComponent.offAfterRender(this.end); + this.renderer.offBeforeRender(this.begin); + this.renderer.offAfterRender(this.end); }, render() { return this.$slots.default ? this.$slots.default() : []; diff --git a/src/components/noisy/NoisyImage.js b/src/components/noisy/NoisyImage.js index aed547a..3bd2f53 100644 --- a/src/components/noisy/NoisyImage.js +++ b/src/components/noisy/NoisyImage.js @@ -29,10 +29,10 @@ export default defineComponent({ }, mounted() { this.startTime = Date.now(); - this.rendererComponent.onBeforeRender(this.updateTime); + this.renderer.onBeforeRender(this.updateTime); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateTime); + this.renderer.offBeforeRender(this.updateTime); }, methods: { createGeometry() { diff --git a/src/components/noisy/NoisyPlane.js b/src/components/noisy/NoisyPlane.js index e08a7cb..51083cc 100644 --- a/src/components/noisy/NoisyPlane.js +++ b/src/components/noisy/NoisyPlane.js @@ -30,10 +30,10 @@ export default defineComponent({ watch(() => this.displacementScale, (value) => { this.material.displacementScale = value; }); this.startTime = Date.now(); - this.rendererComponent.onBeforeRender(this.update); + this.renderer.onBeforeRender(this.update); }, unmounted() { - this.rendererComponent.offBeforeRender(this.update); + this.renderer.offBeforeRender(this.update); this.fsQuad.dispose(); this.dispRT.dispose(); this.dispMat.dispose(); diff --git a/src/components/noisy/NoisySphere.js b/src/components/noisy/NoisySphere.js index 870b2bb..23e2e4c 100644 --- a/src/components/noisy/NoisySphere.js +++ b/src/components/noisy/NoisySphere.js @@ -28,10 +28,10 @@ export default defineComponent({ this.updateMaterial(); this.startTime = Date.now(); - this.rendererComponent.onBeforeRender(this.updateTime); + this.renderer.onBeforeRender(this.updateTime); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateTime); + this.renderer.offBeforeRender(this.updateTime); }, methods: { updateMaterial() { diff --git a/src/components/noisy/NoisyText.js b/src/components/noisy/NoisyText.js index 0454aaf..3909c52 100644 --- a/src/components/noisy/NoisyText.js +++ b/src/components/noisy/NoisyText.js @@ -25,10 +25,10 @@ export default defineComponent({ this.updateMaterial(); this.startTime = Date.now(); - this.rendererComponent.onBeforeRender(this.updateTime); + this.renderer.onBeforeRender(this.updateTime); }, unmounted() { - this.rendererComponent.offBeforeRender(this.updateTime); + this.renderer.offBeforeRender(this.updateTime); }, methods: { updateMaterial() { diff --git a/src/components/physics/CannonWorld.js b/src/components/physics/CannonWorld.js index efb3eae..3d38726 100644 --- a/src/components/physics/CannonWorld.js +++ b/src/components/physics/CannonWorld.js @@ -3,7 +3,7 @@ import useCannon from './useCannon.js'; // import { bindProp } from '../../tools'; export default defineComponent({ - inject: ['three', 'scene', 'rendererComponent'], + inject: ['three', 'scene', 'renderer'], props: { gravity: { type: Object, default: () => ({ x: 0, y: 0, z: -9.82 }) }, broadphase: { type: String }, @@ -16,10 +16,10 @@ export default defineComponent({ this.cannon = useCannon({ gravity: this.gravity, broadphase: this.broadphase }); }, mounted() { - this.rendererComponent.onBeforeRender(this.step); + this.renderer.onBeforeRender(this.step); }, unmounted() { - this.rendererComponent.offBeforeRender(this.step); + this.renderer.offBeforeRender(this.step); }, methods: { step() { diff --git a/src/components/sliders/Slider1.vue b/src/components/sliders/Slider1.vue index d176bb9..bc91cae 100644 --- a/src/components/sliders/Slider1.vue +++ b/src/components/sliders/Slider1.vue @@ -11,7 +11,7 @@ import { defineComponent } from 'vue'; import { Object3D } from 'three'; import { gsap, Power4 } from 'gsap'; -import Camera from '../../core/PerspectiveCamera.js'; +import Camera from '../../core/PerspectiveCamera'; import Renderer from '../../core/Renderer.js'; import Scene from '../../core/Scene.js'; diff --git a/src/components/sliders/Slider2.vue b/src/components/sliders/Slider2.vue index d8a4008..859d383 100644 --- a/src/components/sliders/Slider2.vue +++ b/src/components/sliders/Slider2.vue @@ -10,7 +10,7 @@ import { defineComponent } from 'vue'; import { Vector2 } from 'three'; import { gsap, Power4 } from 'gsap'; -import OrthographicCamera from '../../core/OrthographicCamera.js'; +import OrthographicCamera from '../../core/OrthographicCamera'; import Renderer from '../../core/Renderer.js'; import Scene from '../../core/Scene.js'; diff --git a/src/components/viewers/GLTFViewer.vue b/src/components/viewers/GLTFViewer.vue index a3028b3..439521c 100644 --- a/src/components/viewers/GLTFViewer.vue +++ b/src/components/viewers/GLTFViewer.vue @@ -10,7 +10,7 @@ From 6f64c8b8591d3009cb553be16c6880a300bb9374 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Thu, 22 Apr 2021 00:32:46 +0200 Subject: [PATCH 49/65] various fixes --- src/components/meshes/Gem.js | 2 +- src/components/meshes/MirrorMesh.js | 2 +- src/components/meshes/RefractionMesh.js | 2 +- src/components/noisy/NoisyImage.js | 64 ++++++++++++------------- src/components/noisy/NoisyPlane.js | 2 +- src/components/noisy/NoisySphere.js | 2 +- src/components/noisy/NoisyText.js | 2 +- src/components/sliders/Slider1.vue | 4 +- src/components/sliders/Slider2.vue | 8 ++-- src/core/OrthographicCamera.ts | 2 +- src/effects/TiltShiftPass.ts | 42 +++++++++------- src/geometries/TubeGeometry.ts | 6 +-- src/meshes/Image.ts | 7 ++- src/meshes/Mesh.ts | 3 +- 14 files changed, 80 insertions(+), 68 deletions(-) diff --git a/src/components/meshes/Gem.js b/src/components/meshes/Gem.js index d1c1322..c6098a3 100644 --- a/src/components/meshes/Gem.js +++ b/src/components/meshes/Gem.js @@ -8,7 +8,7 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -import Mesh from '../../meshes/Mesh.js'; +import Mesh from '../../meshes/Mesh'; import { bindProp } from '../../tools'; export default defineComponent({ diff --git a/src/components/meshes/MirrorMesh.js b/src/components/meshes/MirrorMesh.js index e62b862..ac72a17 100644 --- a/src/components/meshes/MirrorMesh.js +++ b/src/components/meshes/MirrorMesh.js @@ -5,7 +5,7 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -import Mesh from '../../meshes/Mesh.js'; +import Mesh from '../../meshes/Mesh'; export default defineComponent({ extends: Mesh, diff --git a/src/components/meshes/RefractionMesh.js b/src/components/meshes/RefractionMesh.js index 3e942a9..81232fe 100644 --- a/src/components/meshes/RefractionMesh.js +++ b/src/components/meshes/RefractionMesh.js @@ -6,7 +6,7 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -import Mesh from '../../meshes/Mesh.js'; +import Mesh from '../../meshes/Mesh'; import { bindProp } from '../../tools'; export default defineComponent({ diff --git a/src/components/noisy/NoisyImage.js b/src/components/noisy/NoisyImage.js index 3bd2f53..dad2151 100644 --- a/src/components/noisy/NoisyImage.js +++ b/src/components/noisy/NoisyImage.js @@ -1,7 +1,7 @@ -import { defineComponent, watch } from 'vue'; -import { DoubleSide, MeshBasicMaterial, PlaneGeometry } from 'three'; -import Image from '../../meshes/Image.js'; -import snoise2 from '../../glsl/snoise2.glsl.js'; +import { defineComponent, watch } from 'vue' +import { DoubleSide, MeshBasicMaterial, PlaneGeometry } from 'three' +import Image from '../../meshes/Image' +import snoise2 from '../../glsl/snoise2.glsl.js' export default defineComponent({ extends: Image, @@ -15,43 +15,41 @@ export default defineComponent({ }, setup(props) { // uniforms - const uTime = { value: 0 }; - const uNoiseCoef = { value: props.noiseCoef }; - watch(() => props.noiseCoef, (value) => { uNoiseCoef.value = value; }); - const uZCoef = { value: props.zCoef }; - watch(() => props.zCoef, (value) => { uZCoef.value = value; }); - const uDispCoef = { value: props.dispCoef }; - watch(() => props.dispCoef, (value) => { uDispCoef.value = value; }); + const uTime = { value: 0 } + const uNoiseCoef = { value: props.noiseCoef } + watch(() => props.noiseCoef, (value) => { uNoiseCoef.value = value }) + const uZCoef = { value: props.zCoef } + watch(() => props.zCoef, (value) => { uZCoef.value = value }) + const uDispCoef = { value: props.dispCoef } + watch(() => props.dispCoef, (value) => { uDispCoef.value = value }) return { uTime, uNoiseCoef, uZCoef, uDispCoef, - }; + } }, - mounted() { - this.startTime = Date.now(); - this.renderer.onBeforeRender(this.updateTime); + created() { + this.tweakMaterial() + + this.startTime = Date.now() + this.renderer.onBeforeRender(this.updateTime) }, unmounted() { - this.renderer.offBeforeRender(this.updateTime); + this.renderer.offBeforeRender(this.updateTime) }, methods: { - createGeometry() { - this.geometry = new PlaneGeometry(1, 1, this.widthSegments, this.heightSegments); - }, - createMaterial() { - this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() }); + tweakMaterial() { this.material.onBeforeCompile = (shader) => { - shader.uniforms.uTime = this.uTime; - shader.uniforms.uNoiseCoef = this.uNoiseCoef; - shader.uniforms.uZCoef = this.uZCoef; - shader.uniforms.uDispCoef = this.uDispCoef; + shader.uniforms.uTime = this.uTime + shader.uniforms.uNoiseCoef = this.uNoiseCoef + shader.uniforms.uZCoef = this.uZCoef + shader.uniforms.uDispCoef = this.uDispCoef shader.vertexShader = ` uniform float uTime; uniform float uNoiseCoef; uniform float uZCoef; varying float vNoise; ${snoise2} - ` + shader.vertexShader; + ` + shader.vertexShader shader.vertexShader = shader.vertexShader.replace( '#include ', @@ -62,12 +60,12 @@ export default defineComponent({ vec3 transformed = vec3(position); transformed.z += vNoise * uZCoef; ` - ); + ) shader.fragmentShader = ` uniform float uDispCoef; varying float vNoise; - ` + shader.fragmentShader; + ` + shader.fragmentShader shader.fragmentShader = shader.fragmentShader.replace( '#include ', @@ -77,13 +75,13 @@ export default defineComponent({ texelColor.r = dispTexel.r; diffuseColor = texelColor; ` - ); - this.materialShader = shader; - }; + ) + this.materialShader = shader + } }, updateTime() { - this.uTime.value = (Date.now() - this.startTime) * this.timeCoef; + this.uTime.value = (Date.now() - this.startTime) * this.timeCoef }, }, __hmrId: 'NoisyImage', -}); +}) diff --git a/src/components/noisy/NoisyPlane.js b/src/components/noisy/NoisyPlane.js index 6b8010a..719e748 100644 --- a/src/components/noisy/NoisyPlane.js +++ b/src/components/noisy/NoisyPlane.js @@ -1,7 +1,7 @@ import { defineComponent, watch } from 'vue'; import { ObjectSpaceNormalMap, ShaderMaterial, Vector2, WebGLRenderTarget } from 'three'; import { Pass } from 'three/examples/jsm/postprocessing/Pass.js'; -import Plane from '../../meshes/Plane.js'; +import Plane from '../../meshes/Plane'; import snoise3 from '../../glsl/snoise3.glsl.js'; export default defineComponent({ diff --git a/src/components/noisy/NoisySphere.js b/src/components/noisy/NoisySphere.js index 23e2e4c..5bb47dd 100644 --- a/src/components/noisy/NoisySphere.js +++ b/src/components/noisy/NoisySphere.js @@ -1,5 +1,5 @@ import { defineComponent, watch } from 'vue'; -import Sphere from '../../meshes/Sphere.js'; +import Sphere from '../../meshes/Sphere'; import snoise4 from '../../glsl/snoise4.glsl.js'; export default defineComponent({ diff --git a/src/components/noisy/NoisyText.js b/src/components/noisy/NoisyText.js index 3909c52..c8966fa 100644 --- a/src/components/noisy/NoisyText.js +++ b/src/components/noisy/NoisyText.js @@ -1,5 +1,5 @@ import { defineComponent, watch } from 'vue'; -import Text from '../../meshes/Text.js'; +import Text from '../../meshes/Text'; import snoise2 from '../../glsl/snoise2.glsl.js'; export default defineComponent({ diff --git a/src/components/sliders/Slider1.vue b/src/components/sliders/Slider1.vue index f9be477..c998c40 100644 --- a/src/components/sliders/Slider1.vue +++ b/src/components/sliders/Slider1.vue @@ -12,8 +12,8 @@ import { Object3D } from 'three'; import { gsap, Power4 } from 'gsap'; import Camera from '../../core/PerspectiveCamera'; -import Renderer from '../../core/Renderer.js'; -import Scene from '../../core/Scene.js'; +import Renderer from '../../core/Renderer'; +import Scene from '../../core/Scene'; import { lerp } from '../../tools'; import AnimatedPlane from './AnimatedPlane.js'; diff --git a/src/components/sliders/Slider2.vue b/src/components/sliders/Slider2.vue index 44d3936..1838d5b 100644 --- a/src/components/sliders/Slider2.vue +++ b/src/components/sliders/Slider2.vue @@ -11,12 +11,12 @@ import { Vector2 } from 'three'; import { gsap, Power4 } from 'gsap'; import OrthographicCamera from '../../core/OrthographicCamera'; -import Renderer from '../../core/Renderer.js'; -import Scene from '../../core/Scene.js'; +import Renderer from '../../core/Renderer'; +import Scene from '../../core/Scene'; import { lerp, lerpv2 } from '../../tools'; import ZoomBlurImage from './ZoomBlurImage.js'; -import useTextures from '../../use/useTextures.js'; +import useTextures from '../../use/useTextures'; export default defineComponent({ components: { OrthographicCamera, Renderer, Scene }, @@ -86,7 +86,7 @@ export default defineComponent({ scene.add(this.image2.mesh); }, animate() { - const { positionN } = this.renderer.pointer; + const { positionN } = this.renderer.three.pointer; this.center.copy(positionN).divideScalar(2).addScalar(0.5); lerpv2(this.image1.uCenter.value, this.center, 0.1); lerpv2(this.image2.uCenter.value, this.center, 0.1); diff --git a/src/core/OrthographicCamera.ts b/src/core/OrthographicCamera.ts index d9d4044..3c6bc83 100644 --- a/src/core/OrthographicCamera.ts +++ b/src/core/OrthographicCamera.ts @@ -19,7 +19,7 @@ export default defineComponent({ setup(props) { const camera = new OrthographicCamera(props.left, props.right, props.top, props.bottom, props.near, props.far) - bindProp(this, 'position', camera) + bindProp(props, 'position', camera) const watchProps = ['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'] watchProps.forEach(p => { diff --git a/src/effects/TiltShiftPass.ts b/src/effects/TiltShiftPass.ts index 38fe6cf..e2fd033 100644 --- a/src/effects/TiltShiftPass.ts +++ b/src/effects/TiltShiftPass.ts @@ -1,6 +1,5 @@ import { defineComponent, watch } from 'vue' -import { ShaderMaterial, Vector2 } from 'three' -import { Pass } from 'three/examples/jsm/postprocessing/Pass' +import { Vector2 } from 'three' import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js' import EffectPass from './EffectPass' import TiltShift from '../shaders/TiltShift' @@ -14,27 +13,35 @@ const props = { } interface TiltShiftPassSetupInterface { - uniforms: {[name: string]: { value: any }} - pass1?: Pass - pass2?: Pass + uniforms1: {[name: string]: { value: any }} + uniforms2: {[name: string]: { value: any }} + pass1?: ShaderPass + pass2?: ShaderPass } export default defineComponent({ extends: EffectPass, props, setup(): TiltShiftPassSetupInterface { - const uniforms = {} - return { uniforms } + return { uniforms1: {}, uniforms2: {} } }, created() { - const shaderMat = new ShaderMaterial(TiltShift) - this.uniforms = shaderMat.uniforms + this.pass1 = new ShaderPass(TiltShift) + this.pass2 = new ShaderPass(TiltShift) - this.pass1 = new ShaderPass(shaderMat) - this.pass2 = new ShaderPass(shaderMat) + const uniforms1 = this.uniforms1 = this.pass1.uniforms + const uniforms2 = this.uniforms2 = this.pass2.uniforms + + // shared uniforms + uniforms2.blurRadius = uniforms1.blurRadius + uniforms2.gradientRadius = uniforms1.gradientRadius + uniforms2.start = uniforms1.start + uniforms2.end = uniforms1.end + uniforms2.texSize = uniforms1.texSize + + bindProp(this, 'blurRadius', uniforms1.blurRadius, 'value') + bindProp(this, 'gradientRadius', uniforms1.gradientRadius, 'value') - bindProp(this, 'blurRadius', this.uniforms.blurRadius, 'value') - bindProp(this, 'gradientRadius', this.uniforms.gradientRadius, 'value') this.updateFocusLine(); ['start', 'end'].forEach(p => { @@ -43,7 +50,7 @@ export default defineComponent({ }) this.pass1.setSize = (width: number, height: number) => { - this.uniforms.texSize.value.set(width, height) + uniforms1.texSize.value.set(width, height) } this.initEffectPass(this.pass1) @@ -54,10 +61,11 @@ export default defineComponent({ }, methods: { updateFocusLine() { - this.uniforms.start.value.copy(this.start) - this.uniforms.end.value.copy(this.end) + this.uniforms1.start.value.copy(this.start) + this.uniforms1.end.value.copy(this.end) const dv = new Vector2().copy(this.end as Vector2).sub(this.start as Vector2).normalize() - this.uniforms.delta.value.copy(dv) + this.uniforms1.delta.value.copy(dv) + this.uniforms2.delta.value.set(-dv.y, dv.x) }, }, __hmrId: 'TiltShiftPass', diff --git a/src/geometries/TubeGeometry.ts b/src/geometries/TubeGeometry.ts index 5dada15..237d5f6 100644 --- a/src/geometries/TubeGeometry.ts +++ b/src/geometries/TubeGeometry.ts @@ -50,7 +50,7 @@ export function updateTubeGeometryPoints(tube: TubeGeometry, points: Vector3[]): const nAttribute = tube.getAttribute('normal') const normal = new Vector3() - let P = new Vector3() + const P = new Vector3() for (let i = 0; i < tubularSegments; i++) { updateSegment(i) @@ -61,7 +61,7 @@ export function updateTubeGeometryPoints(tube: TubeGeometry, points: Vector3[]): tube.attributes.normal.needsUpdate = true function updateSegment(i: number) { - P = curve.getPointAt(i / tubularSegments, P) + curve.getPointAt(i / tubularSegments, P) const N = frames.normals[i] const B = frames.binormals[i] for (let j = 0; j <= radialSegments; j++) { @@ -72,7 +72,7 @@ export function updateTubeGeometryPoints(tube: TubeGeometry, points: Vector3[]): normal.y = (cos * N.y + sin * B.y) normal.z = (cos * N.z + sin * B.z) normal.normalize() - const index = (i * (radialSegments + 1) + j) * 3 + const index = (i * (radialSegments + 1) + j) nAttribute.setXYZ(index, normal.x, normal.y, normal.z) pAttribute.setXYZ(index, P.x + radius * normal.x, P.y + radius * normal.y, P.z + radius * normal.z) } diff --git a/src/meshes/Image.ts b/src/meshes/Image.ts index ca920ca..f1a04eb 100644 --- a/src/meshes/Image.ts +++ b/src/meshes/Image.ts @@ -15,13 +15,15 @@ export default defineComponent({ src: { type: String, required: true }, width: Number, height: Number, + widthSegments: { type: Number, default: 1 }, + heightSegments: { type: Number, default: 1 }, keepSize: Boolean, }, setup(): ImageSetupInterface { return object3DSetup() }, created() { - this.geometry = new PlaneGeometry(1, 1, 1, 1) + this.geometry = new PlaneGeometry(1, 1, this.widthSegments, this.heightSegments) this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() }) watch(() => this.src, this.refreshTexture); @@ -34,6 +36,9 @@ export default defineComponent({ this.resize() if (this.keepSize) this.renderer.onResize(this.resize) }, + unmounted() { + this.renderer.offResize(this.resize) + }, methods: { loadTexture() { return new TextureLoader().load(this.src, this.onLoaded) diff --git a/src/meshes/Mesh.ts b/src/meshes/Mesh.ts index 6472475..44b441e 100644 --- a/src/meshes/Mesh.ts +++ b/src/meshes/Mesh.ts @@ -93,8 +93,9 @@ const Mesh = defineComponent({ if (this.mesh) { this.renderer.three?.removeIntersectObject(this.mesh) } - // for predefined mesh (geometry is not unmounted) + // for predefined mesh (geometry/material are not unmounted) if (this.geometry) this.geometry.dispose() + if (this.material) this.material.dispose() }, __hmrId: 'Mesh', }) From d15b90e4b2ed7a2b3945b5d4e92f88e7d80fe141 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Thu, 22 Apr 2021 00:46:52 +0200 Subject: [PATCH 50/65] cs --- src/components/liquid/LiquidEffect.js | 1 - src/components/liquid/LiquidPlane.js | 49 +++---- src/components/meshes/Gem.js | 82 +++++------ src/components/meshes/MirrorMesh.js | 34 ++--- src/components/meshes/RefractionMesh.js | 40 +++--- src/components/misc/Stats.js | 30 ++-- src/components/misc/VRButton.vue | 40 +++--- src/components/noisy/NoisyImage.js | 1 - src/components/noisy/NoisyPlane.js | 82 +++++------ src/components/noisy/NoisySphere.js | 46 +++--- src/components/noisy/NoisyText.js | 46 +++--- src/components/physics/CannonWorld.js | 50 +++---- src/components/physics/useCannon.js | 184 ++++++++++++------------ src/components/sliders/AnimatedPlane.js | 148 +++++++++---------- src/components/sliders/Slider1.vue | 144 +++++++++---------- src/components/sliders/Slider2.vue | 146 +++++++++---------- src/components/sliders/ZoomBlurImage.js | 44 +++--- 17 files changed, 583 insertions(+), 584 deletions(-) diff --git a/src/components/liquid/LiquidEffect.js b/src/components/liquid/LiquidEffect.js index 7aa52a8..512b74e 100644 --- a/src/components/liquid/LiquidEffect.js +++ b/src/components/liquid/LiquidEffect.js @@ -8,7 +8,6 @@ import { ShaderMaterial, Uniform, Vector2, - WebGLRenderer, WebGLRenderTarget, } from 'three' diff --git a/src/components/liquid/LiquidPlane.js b/src/components/liquid/LiquidPlane.js index ae26a2b..e65eead 100644 --- a/src/components/liquid/LiquidPlane.js +++ b/src/components/liquid/LiquidPlane.js @@ -1,8 +1,8 @@ -import { defineComponent, watch } from 'vue'; -import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three'; -import Object3D from '../../core/Object3D'; -import { bindProps } from '../../tools'; -import LiquidEffect from './LiquidEffect.js'; +import { defineComponent, watch } from 'vue' +import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three' +import Object3D from '../../core/Object3D' +import { bindProps } from '../../tools' +import LiquidEffect from './LiquidEffect.js' export default defineComponent({ extends: Object3D, @@ -16,39 +16,40 @@ export default defineComponent({ roughness: { type: Number, default: 0.25 }, }, mounted() { - this.liquidEffect = new LiquidEffect(this.renderer.renderer); + this.liquidEffect = new LiquidEffect(this.renderer.renderer) this.renderer.onMounted(() => { - this.liquidEffect.renderer = this.renderer.renderer; - this.renderer.onBeforeRender(this.update); - }); + this.liquidEffect.renderer = this.renderer.renderer + this.renderer.onBeforeRender(this.update) + }) - this.material = new MeshStandardMaterial({ color: this.color, side: DoubleSide, metalness: this.metalness, roughness: this.roughness, + this.material = new MeshStandardMaterial({ + color: this.color, side: DoubleSide, metalness: this.metalness, roughness: this.roughness, onBeforeCompile: shader => { - shader.uniforms.hmap = { value: this.liquidEffect.hMap.texture }; - shader.vertexShader = "uniform sampler2D hmap;\n" + shader.vertexShader; - const token = '#include '; + shader.uniforms.hmap = { value: this.liquidEffect.hMap.texture } + shader.vertexShader = "uniform sampler2D hmap;\n" + shader.vertexShader + const token = '#include ' const customTransform = ` vec3 transformed = vec3(position); vec4 info = texture2D(hmap, uv); vNormal = vec3(info.b, sqrt(1.0 - dot(info.ba, info.ba)), info.a).xzy; transformed.z = 20. * info.r; - `; - shader.vertexShader = shader.vertexShader.replace(token, customTransform); + ` + shader.vertexShader = shader.vertexShader.replace(token, customTransform) }, - }); - bindProps(this, ['metalness', 'roughness'], this.material); - watch(() => this.color, (value) => this.material.color.set(value)); + }) + bindProps(this, ['metalness', 'roughness'], this.material) + watch(() => this.color, (value) => this.material.color.set(value)) - this.geometry = new PlaneGeometry(this.width, this.height, this.widthSegments, this.heightSegments); - this.mesh = new Mesh(this.geometry, this.material); - this.initObject3D(this.mesh); + this.geometry = new PlaneGeometry(this.width, this.height, this.widthSegments, this.heightSegments) + this.mesh = new Mesh(this.geometry, this.material) + this.initObject3D(this.mesh) }, unmounted() { - this.renderer.offBeforeRender(this.update); + this.renderer.offBeforeRender(this.update) }, methods: { update() { - this.liquidEffect.update(); + this.liquidEffect.update() }, }, -}); +}) diff --git a/src/components/meshes/Gem.js b/src/components/meshes/Gem.js index c6098a3..d7efed7 100644 --- a/src/components/meshes/Gem.js +++ b/src/components/meshes/Gem.js @@ -1,4 +1,4 @@ -import { defineComponent } from 'vue'; +import { defineComponent } from 'vue' import { BackSide, CubeCamera, @@ -7,9 +7,9 @@ import { Mesh as TMesh, RGBFormat, WebGLCubeRenderTarget, -} from 'three'; -import Mesh from '../../meshes/Mesh'; -import { bindProp } from '../../tools'; +} from 'three' +import Mesh from '../../meshes/Mesh' +import { bindProp } from '../../tools' export default defineComponent({ extends: Mesh, @@ -20,54 +20,54 @@ export default defineComponent({ autoUpdate: Boolean, }, mounted() { - this.initGem(); - if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); - else this.renderer.onMounted(this.updateCubeRT); + this.initGem() + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT) + else this.renderer.onMounted(this.updateCubeRT) }, unmounted() { - this.renderer.offBeforeRender(this.updateCubeRT); - if (this.cubeCamera) this.removeFromParent(this.cubeCamera); - if (this.meshBack) this.removeFromParent(this.meshBack); - if (this.materialBack) this.materialBack.dispose(); + this.renderer.offBeforeRender(this.updateCubeRT) + if (this.cubeCamera) this.removeFromParent(this.cubeCamera) + if (this.meshBack) this.removeFromParent(this.meshBack) + if (this.materialBack) this.materialBack.dispose() }, methods: { initGem() { - const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); - this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - bindProp(this, 'position', this.cubeCamera); - this.addToParent(this.cubeCamera); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }) + this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT) + bindProp(this, 'position', this.cubeCamera) + this.addToParent(this.cubeCamera) - this.material.side = FrontSide; - this.material.envMap = cubeRT.texture; - this.material.envMapIntensity = 10; - this.material.metalness = 0; - this.material.roughness = 0; - this.material.opacity = 0.75; - this.material.transparent = true; - this.material.premultipliedAlpha = true; - this.material.needsUpdate = true; + this.material.side = FrontSide + this.material.envMap = cubeRT.texture + this.material.envMapIntensity = 10 + this.material.metalness = 0 + this.material.roughness = 0 + this.material.opacity = 0.75 + this.material.transparent = true + this.material.premultipliedAlpha = true + this.material.needsUpdate = true - this.materialBack = this.material.clone(); - this.materialBack.side = BackSide; - this.materialBack.envMapIntensity = 5; - this.materialBack.metalness = 1; - this.materialBack.roughness = 0; - this.materialBack.opacity = 0.5; + this.materialBack = this.material.clone() + this.materialBack.side = BackSide + this.materialBack.envMapIntensity = 5 + this.materialBack.metalness = 1 + this.materialBack.roughness = 0 + this.materialBack.opacity = 0.5 - this.meshBack = new TMesh(this.geometry, this.materialBack); + this.meshBack = new TMesh(this.geometry, this.materialBack) - bindProp(this, 'position', this.meshBack); - bindProp(this, 'rotation', this.meshBack); - bindProp(this, 'scale', this.meshBack); - this.addToParent(this.meshBack); + bindProp(this, 'position', this.meshBack) + bindProp(this, 'rotation', this.meshBack) + bindProp(this, 'scale', this.meshBack) + this.addToParent(this.meshBack) }, updateCubeRT() { - this.mesh.visible = false; - this.meshBack.visible = false; - this.cubeCamera.update(this.renderer.renderer, this.scene); - this.mesh.visible = true; - this.meshBack.visible = true; + this.mesh.visible = false + this.meshBack.visible = false + this.cubeCamera.update(this.renderer.renderer, this.scene) + this.mesh.visible = true + this.meshBack.visible = true }, }, __hmrId: 'Gem', -}); +}) diff --git a/src/components/meshes/MirrorMesh.js b/src/components/meshes/MirrorMesh.js index ac72a17..203d422 100644 --- a/src/components/meshes/MirrorMesh.js +++ b/src/components/meshes/MirrorMesh.js @@ -1,11 +1,11 @@ -import { defineComponent } from 'vue'; +import { defineComponent } from 'vue' import { CubeCamera, LinearMipmapLinearFilter, RGBFormat, WebGLCubeRenderTarget, -} from 'three'; -import Mesh from '../../meshes/Mesh'; +} from 'three' +import Mesh from '../../meshes/Mesh' export default defineComponent({ extends: Mesh, @@ -16,28 +16,28 @@ export default defineComponent({ autoUpdate: Boolean, }, mounted() { - this.initMirrorMesh(); - if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); - else this.renderer.onMounted(this.updateCubeRT); + this.initMirrorMesh() + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT) + else this.renderer.onMounted(this.updateCubeRT) }, unmounted() { - this.renderer.offBeforeRender(this.updateCubeRT); - if (this.cubeCamera) this.removeFromParent(this.cubeCamera); + this.renderer.offBeforeRender(this.updateCubeRT) + if (this.cubeCamera) this.removeFromParent(this.cubeCamera) }, methods: { initMirrorMesh() { - const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); - this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - this.addToParent(this.cubeCamera); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }) + this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT) + this.addToParent(this.cubeCamera) - this.material.envMap = cubeRT.texture; - this.material.needsUpdate = true; + this.material.envMap = cubeRT.texture + this.material.needsUpdate = true }, updateCubeRT() { - this.mesh.visible = false; - this.cubeCamera.update(this.renderer.renderer, this.scene); - this.mesh.visible = true; + this.mesh.visible = false + this.cubeCamera.update(this.renderer.renderer, this.scene) + this.mesh.visible = true }, }, __hmrId: 'MirrorMesh', -}); +}) diff --git a/src/components/meshes/RefractionMesh.js b/src/components/meshes/RefractionMesh.js index 81232fe..ad4df31 100644 --- a/src/components/meshes/RefractionMesh.js +++ b/src/components/meshes/RefractionMesh.js @@ -1,13 +1,13 @@ -import { defineComponent } from 'vue'; +import { defineComponent } from 'vue' import { CubeCamera, CubeRefractionMapping, LinearMipmapLinearFilter, RGBFormat, WebGLCubeRenderTarget, -} from 'three'; -import Mesh from '../../meshes/Mesh'; -import { bindProp } from '../../tools'; +} from 'three' +import Mesh from '../../meshes/Mesh' +import { bindProp } from '../../tools' export default defineComponent({ extends: Mesh, @@ -19,30 +19,30 @@ export default defineComponent({ autoUpdate: Boolean, }, mounted() { - this.initMirrorMesh(); - if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT); - else this.renderer.onMounted(this.updateCubeRT); + this.initMirrorMesh() + if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT) + else this.renderer.onMounted(this.updateCubeRT) }, unmounted() { - this.renderer.offBeforeRender(this.updateCubeRT); - if (this.cubeCamera) this.removeFromParent(this.cubeCamera); + this.renderer.offBeforeRender(this.updateCubeRT) + if (this.cubeCamera) this.removeFromParent(this.cubeCamera) }, methods: { initMirrorMesh() { - const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); - this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - bindProp(this, 'position', this.cubeCamera); - this.addToParent(this.cubeCamera); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }) + this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT) + bindProp(this, 'position', this.cubeCamera) + this.addToParent(this.cubeCamera) - this.material.envMap = cubeRT.texture; - this.material.refractionRatio = this.refractionRatio; - this.material.needsUpdate = true; + this.material.envMap = cubeRT.texture + this.material.refractionRatio = this.refractionRatio + this.material.needsUpdate = true }, updateCubeRT() { - this.mesh.visible = false; - this.cubeCamera.update(this.renderer.renderer, this.scene); - this.mesh.visible = true; + this.mesh.visible = false + this.cubeCamera.update(this.renderer.renderer, this.scene) + this.mesh.visible = true }, }, __hmrId: 'RefractionMesh', -}); +}) diff --git a/src/components/misc/Stats.js b/src/components/misc/Stats.js index d2b4dc2..774aad8 100644 --- a/src/components/misc/Stats.js +++ b/src/components/misc/Stats.js @@ -1,4 +1,4 @@ -import Stats from 'stats.js'; +import Stats from 'stats.js' export default { props: { @@ -7,40 +7,40 @@ export default { emits: ['created'], inject: ['renderer'], setup({ noSetup }) { - const stats = new Stats(); + const stats = new Stats() if (!noSetup) { - stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom - document.body.appendChild(stats.dom); + stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom + document.body.appendChild(stats.dom) } - return { stats }; + return { stats } }, mounted() { if (!this.noSetup) { - this.renderer.onBeforeRender(this.begin); - this.renderer.onAfterRender(this.end); + this.renderer.onBeforeRender(this.begin) + this.renderer.onAfterRender(this.end) } - this.$emit('created', { stats: this.stats }); + this.$emit('created', { stats: this.stats }) }, methods: { begin() { if (this.stats) { - this.stats.begin(); + this.stats.begin() } }, end() { if (this.stats) { - this.stats.end(); + this.stats.end() } }, }, unmounted() { if (this.stats && this.stats.dom) { - this.stats.dom.parentElement.removeChild(this.stats.dom); + this.stats.dom.parentElement.removeChild(this.stats.dom) } - this.renderer.offBeforeRender(this.begin); - this.renderer.offAfterRender(this.end); + this.renderer.offBeforeRender(this.begin) + this.renderer.offAfterRender(this.end) }, render() { - return this.$slots.default ? this.$slots.default() : []; + return this.$slots.default ? this.$slots.default() : [] }, -}; +} diff --git a/src/components/misc/VRButton.vue b/src/components/misc/VRButton.vue index 33fbb2e..b04efd7 100644 --- a/src/components/misc/VRButton.vue +++ b/src/components/misc/VRButton.vue @@ -14,57 +14,57 @@ export default { error: '', xrSupport: false, currentSession: null, - }; + } }, computed: { message() { if (this.xrSupport) { - return this.currentSession ? this.exitMessage : this.enterMessage; + return this.currentSession ? this.exitMessage : this.enterMessage } else if (this.error) { - return this.error; + return this.error } - return ''; + return '' }, }, created() { if ('xr' in navigator) { navigator.xr.isSessionSupported('immersive-vr').then((supported) => { - this.xrSupport = supported; - }); + this.xrSupport = supported + }) } else { if (window.isSecureContext === false) { - this.error = 'WEBXR NEEDS HTTPS'; + this.error = 'WEBXR NEEDS HTTPS' } else { - this.error = 'WEBXR NOT AVAILABLE'; + this.error = 'WEBXR NOT AVAILABLE' } } }, methods: { init(renderer) { - this.renderer = renderer; + this.renderer = renderer }, onClick() { - if (!this.xrSupport) return; - if (!this.renderer) return; + if (!this.xrSupport) return + if (!this.renderer) return if (this.currentSession) { - this.currentSession.end(); + this.currentSession.end() } else { - const sessionInit = { optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking'] }; - navigator.xr.requestSession('immersive-vr', sessionInit).then(this.onSessionStarted); + const sessionInit = { optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking'] } + navigator.xr.requestSession('immersive-vr', sessionInit).then(this.onSessionStarted) } }, async onSessionStarted(session) { - session.addEventListener('end', this.onSessionEnded); - await this.renderer.xr.setSession(session); - this.currentSession = session; + session.addEventListener('end', this.onSessionEnded) + await this.renderer.xr.setSession(session) + this.currentSession = session }, onSessionEnded() { - this.currentSession.removeEventListener('end', this.onSessionEnded); - this.currentSession = null; + this.currentSession.removeEventListener('end', this.onSessionEnded) + this.currentSession = null }, }, -}; +}