From 8adb685c56a018f4dd818ef551b7d9955777aee6 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Mon, 19 Apr 2021 19:37:11 +0200 Subject: [PATCH] wip: core --- src/core/Camera.ts | 6 +----- src/core/Raycaster.ts | 38 ++++++++++++++++++++++++++++---------- src/core/Renderer.ts | 32 ++++++++++++++++++++++++++------ src/core/Scene.ts | 10 ++++++---- 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/core/Camera.ts b/src/core/Camera.ts index 2a5c6a8..b24bfc3 100644 --- a/src/core/Camera.ts +++ b/src/core/Camera.ts @@ -1,11 +1,7 @@ -import { Camera } from 'three' import { defineComponent, inject } from 'vue' +import { ThreeInterface } from './useThree' // import Object3D from './Object3D' -interface ThreeInterface { - camera?: Camera -} - export default defineComponent({ // TODO: eventually extend Object3D // extends: Object3D, diff --git a/src/core/Raycaster.ts b/src/core/Raycaster.ts index baacc96..464038e 100644 --- a/src/core/Raycaster.ts +++ b/src/core/Raycaster.ts @@ -1,26 +1,40 @@ import { Object3D } from 'three' -import { defineComponent } from 'vue' -import usePointer, { PointerIntersectCallbackType } from './usePointer' +import { defineComponent, inject, PropType } from 'vue' +import usePointer, { IntersectObject, PointerInterface, PointerIntersectCallbackType } from './usePointer' +import { RendererInterface } from './Renderer' +import { ThreeInterface } from './useThree' // eslint-disable-next-line @typescript-eslint/no-empty-function const emptyCallBack: PointerIntersectCallbackType = () => {} +interface RaycasterSetupInterface { + renderer: RendererInterface + three: ThreeInterface + pointer?: PointerInterface +} + export default defineComponent({ name: 'Raycaster', - inject: ['three', 'renderer'], props: { - onPointerEnter: { type: Function, default: emptyCallBack }, - onPointerOver: { type: Function, default: emptyCallBack }, - onPointerMove: { type: Function, default: emptyCallBack }, - onPointerLeave: { type: Function, default: emptyCallBack }, - onClick: { type: Function, default: emptyCallBack }, + onPointerEnter: { type: Function as PropType, default: emptyCallBack }, + onPointerOver: { type: Function as PropType, default: emptyCallBack }, + onPointerMove: { type: Function as PropType, default: emptyCallBack }, + onPointerLeave: { type: Function as PropType, default: emptyCallBack }, + onClick: { type: Function as PropType, default: emptyCallBack }, intersectMode: { type: String, default: 'move' }, }, + setup(): RaycasterSetupInterface { + const renderer = inject('renderer') as RendererInterface + const three = inject('three') as ThreeInterface + return { renderer, three } + }, mounted() { this.renderer.onMounted(() => { + if (!this.three.camera) return + this.pointer = usePointer({ camera: this.three.camera, - domElement: this.three.renderer.domElement, + domElement: this.renderer.canvas, intersectObjects: this.getIntersectObjects(), onIntersectEnter: ( this.onPointerEnter), onIntersectOver: ( this.onPointerOver), @@ -43,7 +57,11 @@ export default defineComponent({ }, methods: { getIntersectObjects() { - return this.three.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type)) + if (this.three.scene) { + const children = this.three.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type)) + return children as IntersectObject[] + } + return [] }, }, render() { diff --git a/src/core/Renderer.ts b/src/core/Renderer.ts index b13759d..4893226 100644 --- a/src/core/Renderer.ts +++ b/src/core/Renderer.ts @@ -1,8 +1,8 @@ import { WebGLRenderer } from 'three' import { defineComponent } from 'vue' -import useThree, { ThreeConfigInterface, ThreeInterface } from './useThree' +import useThree, { SizeInterface, ThreeConfigInterface, ThreeInterface } from './useThree' -type CallbackType = (e: T) => void +type CallbackType = (e?: T) => void interface EventInterface { renderer: T @@ -12,19 +12,31 @@ interface RenderEventInterface extends EventInterface { time: number } -export interface RendererInterface { +interface RendererSetupInterface { canvas: HTMLCanvasElement three: ThreeInterface renderer: WebGLRenderer + size: SizeInterface renderFn(): void raf: boolean onMountedCallbacks: CallbackType>[] beforeRenderCallbacks: CallbackType>[] afterRenderCallbacks: CallbackType>[] + // pointerPosition?: Vector2 + // pointerPositionN?: Vector2 + // pointerPositionV3?: Vector3 } -type MountedCallbackType = CallbackType> -type RenderCallbackType = CallbackType> +export interface RendererInterface extends RendererSetupInterface { + onMounted(cb: CallbackType>): void + onBeforeRender(cb: CallbackType>): void + offBeforeRender(cb: CallbackType>): void + onAfterRender(cb: CallbackType>): void + offAfterRender(cb: CallbackType>): void +} + +// type MountedCallbackType = CallbackType> +// type RenderCallbackType = CallbackType> export default defineComponent({ name: 'Renderer', @@ -42,7 +54,7 @@ export default defineComponent({ onReady: Function, // onFrame: Function, }, - setup(props): RendererInterface { + setup(props): RendererSetupInterface { const canvas = document.createElement('canvas') const config: ThreeConfigInterface = { canvas, @@ -69,6 +81,7 @@ export default defineComponent({ canvas, three, renderer: three.renderer, + size: three.size, renderFn, raf: true, onMountedCallbacks, @@ -88,6 +101,13 @@ export default defineComponent({ if (this.three.init()) { this.onReady?.(this) + + // if (this.three.pointer) { + // this.pointerPosition = this.three.pointer.position + // this.pointerPositionN = this.three.pointer.positionN + // this.pointerPositionV3 = this.three.pointer.positionV3 + // } + this.renderer.shadowMap.enabled = this.shadow this.renderFn = this.three.composer ? this.three.renderC : this.three.render diff --git a/src/core/Scene.ts b/src/core/Scene.ts index ecbc487..6f71a97 100644 --- a/src/core/Scene.ts +++ b/src/core/Scene.ts @@ -1,20 +1,22 @@ -import { defineComponent, watch } from 'vue' +import { defineComponent, inject, watch } from 'vue' import { Scene, Color, Object3D } from 'three' +import { ThreeInterface } from './useThree' export default defineComponent({ name: 'Scene', - inject: ['three'], + // inject: ['three'], props: { - id: String, + // id: String, background: [String, Number], }, setup(props) { + const three = inject('three') as ThreeInterface const scene = new Scene() if (props.background) { scene.background = new Color(props.background) } watch(() => props.background, (value) => { if (scene.background instanceof Color && value) scene.background.set(value) }) - return { scene } + return { three, scene } }, provide() { return {