1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00
This commit is contained in:
Kevin Levron 2021-04-16 03:19:50 +02:00
parent d2006b1f2c
commit de98dd8d11
9 changed files with 129 additions and 99 deletions

View File

@ -61,8 +61,8 @@ export default defineComponent({
}
return false
},
add(o) { this.o3d.add(o); },
remove(o) { this.o3d.remove(o); },
add(o: Object3D) { this.o3d.add(o) },
remove(o: Object3D) { this.o3d.remove(o) },
},
render() {
return this.$slots.default ? this.$slots.default() : []

View File

@ -1,12 +1,11 @@
import { defineComponent, watch } from 'vue';
import { OrthographicCamera } from 'three';
import { bindProp } from '../tools';
import Camera from './Camera';
import { defineComponent, watch } from 'vue'
import { OrthographicCamera } from 'three'
import { bindProp } from '../tools'
import Camera from './Camera'
export default defineComponent({
extends: Camera,
name: 'OrthographicCamera',
inject: ['three'],
props: {
left: { type: Number, default: -1 },
right: { type: Number, default: 1 },
@ -15,20 +14,25 @@ export default defineComponent({
near: { type: Number, default: 0.1 },
far: { type: Number, default: 2000 },
zoom: { type: Number, default: 1 },
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
position: { type: Object, default: () => ({ x: 0, y: 0, z: 0 }) },
},
setup(props) {
const camera = new OrthographicCamera(props.left, props.right, props.top, props.bottom, props.near, props.far)
return {
camera,
}
},
created() {
this.camera = new OrthographicCamera(this.left, this.right, this.top, this.bottom, this.near, this.far);
bindProp(this, 'position', this.camera);
['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'].forEach(p => {
watch(() => this[p], () => {
this.camera[p] = this[p];
this.camera.updateProjectionMatrix();
});
});
this.camera.updateProjectionMatrix()
})
})
this.three.camera = this.camera;
this.three.camera = this.camera
},
__hmrId: 'OrthographicCamera',
});
})

View File

@ -1,7 +1,7 @@
import { defineComponent, watch } from 'vue';
import { PerspectiveCamera } from 'three';
import { bindProp } from '../tools';
import Camera from './Camera';
import { defineComponent, watch } from 'vue'
import { PerspectiveCamera } from 'three'
import { bindProp } from '../tools'
import Camera from './Camera'
export default defineComponent({
extends: Camera,
@ -12,24 +12,30 @@ export default defineComponent({
far: { type: Number, default: 2000 },
fov: { type: Number, default: 50 },
near: { type: Number, default: 0.1 },
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
position: { type: Object, default: () => ({ x: 0, y: 0, z: 0 }) },
lookAt: { type: Object, default: null },
},
setup(props) {
return {
camera: new PerspectiveCamera(props.fov, props.aspect, props.near, props.far),
}
},
created() {
this.camera = new PerspectiveCamera(this.fov, this.aspect, this.near, this.far);
bindProp(this, 'position', this.camera);
bindProp(this, 'position', this.camera)
if (this.lookAt) this.camera.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z);
watch(() => this.lookAt, (v) => { this.camera.lookAt(v.x, v.y, v.z); }, { deep: true });
// TODO : fix lookAt x
if (this.lookAt) this.camera.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z)
watch(() => this.lookAt, (v) => { this.camera.lookAt(v.x, v.y, v.z) }, { deep: true })
['aspect', 'far', 'fov', 'near'].forEach(p => {
const watchProps = ['aspect', 'far', 'fov', 'near']
watchProps.forEach(p => {
watch(() => this[p], () => {
this.camera[p] = this[p];
this.camera.updateProjectionMatrix();
});
});
this.camera[p] = this[p]
this.camera.updateProjectionMatrix()
})
})
this.three.camera = this.camera;
this.three.camera = this.camera
},
__hmrId: 'PerspectiveCamera',
});
})

View File

@ -1,15 +1,19 @@
import { defineComponent } from 'vue';
import usePointer from './usePointer';
import { Object3D } from 'three'
import { defineComponent } from 'vue'
import usePointer, { PointerIntersectCallbackType } from './usePointer'
// eslint-disable-next-line @typescript-eslint/no-empty-function
const emptyCallBack: PointerIntersectCallbackType = () => {}
export default defineComponent({
name: 'Raycaster',
inject: ['three', 'renderer'],
props: {
onPointerEnter: { type: Function, default: () => {} },
onPointerOver: { type: Function, default: () => {} },
onPointerMove: { type: Function, default: () => {} },
onPointerLeave: { type: Function, default: () => {} },
onClick: { type: Function, default: () => {} },
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 },
intersectMode: { type: String, default: 'move' },
},
mounted() {
@ -18,32 +22,32 @@ export default defineComponent({
camera: this.three.camera,
domElement: this.three.renderer.domElement,
intersectObjects: this.getIntersectObjects(),
onIntersectEnter: this.onPointerEnter,
onIntersectOver: this.onPointerOver,
onIntersectMove: this.onPointerMove,
onIntersectLeave: this.onPointerLeave,
onIntersectClick: this.onClick,
});
this.pointer.addListeners();
onIntersectEnter: (<PointerIntersectCallbackType> this.onPointerEnter),
onIntersectOver: (<PointerIntersectCallbackType> this.onPointerOver),
onIntersectMove: (<PointerIntersectCallbackType> this.onPointerMove),
onIntersectLeave: (<PointerIntersectCallbackType> this.onPointerLeave),
onIntersectClick: (<PointerIntersectCallbackType> this.onClick),
})
this.pointer.addListeners()
if (this.intersectMode === 'frame') {
this.renderer.onBeforeRender(this.pointer.intersect);
this.renderer.onBeforeRender(this.pointer.intersect)
}
});
})
},
unmounted() {
if (this.pointer) {
this.pointer.removeListeners();
this.renderer.offBeforeRender(this.pointer.intersect);
this.pointer.removeListeners()
this.renderer.offBeforeRender(this.pointer.intersect)
}
},
methods: {
getIntersectObjects() {
return this.three.scene.children.filter(e => e.type === 'Mesh');
return this.three.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type))
},
},
render() {
return [];
return []
},
__hmrId: 'Raycaster',
});
})

View File

@ -1,5 +1,5 @@
import { defineComponent, watch } from 'vue';
import { Scene, Color } from 'three';
import { defineComponent, watch } from 'vue'
import { Scene, Color, Object3D } from 'three'
export default defineComponent({
name: 'Scene',
@ -9,27 +9,29 @@ export default defineComponent({
background: [String, Number],
},
setup(props) {
const scene = new Scene();
if (props.background) scene.background = new Color(props.background);
watch(() => props.background, (value) => { scene.background.set(value); });
return { scene };
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 }
},
provide() {
return {
scene: this.scene,
};
}
},
mounted() {
if (!this.three.scene) {
this.three.scene = this.scene;
this.three.scene = this.scene
}
},
methods: {
add(o) { this.scene.add(o); },
remove(o) { this.scene.remove(o); },
add(o: Object3D) { this.scene.add(o) },
remove(o: Object3D) { this.scene.remove(o) },
},
render() {
return this.$slots.default ? this.$slots.default() : [];
return this.$slots.default ? this.$slots.default() : []
},
__hmrId: 'Scene',
});
})

View File

@ -1,8 +1,8 @@
export { default as Renderer } from './Renderer';
export { default as OrthographicCamera } from './OrthographicCamera';
export { default as PerspectiveCamera } from './PerspectiveCamera';
export { default as Camera } from './PerspectiveCamera';
export { default as Group } from './Group';
export { default as Scene } from './Scene';
export { default as Object3D } from './Object3D';
export { default as Raycaster } from './Raycaster';
export { default as Renderer } from './Renderer'
export { default as OrthographicCamera } from './OrthographicCamera'
export { default as PerspectiveCamera } from './PerspectiveCamera'
export { default as Camera } from './PerspectiveCamera'
export { default as Group } from './Group'
export { default as Scene } from './Scene'
export { default as Object3D } from './Object3D'
export { default as Raycaster } from './Raycaster'

View File

@ -16,6 +16,8 @@ export interface PointerIntersectEventInterface {
intersect?: Intersection
}
export type PointerIntersectCallbackType = (e: PointerIntersectEventInterface) => void
export type IntersectObject = Mesh | InstancedMesh
export interface PointerConfigInterface {
@ -31,11 +33,11 @@ export interface PointerConfigInterface {
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
onIntersectEnter: PointerIntersectCallbackType
onIntersectOver: PointerIntersectCallbackType
onIntersectMove: PointerIntersectCallbackType
onIntersectLeave: PointerIntersectCallbackType
onIntersectClick: PointerIntersectCallbackType
}
export interface PointerInterface {

View File

@ -1,29 +1,41 @@
import { Plane, Raycaster, Vector3 } from 'three';
import { Camera, Intersection, Plane, Raycaster, Vector2, Vector3 } from 'three';
import { IntersectObject } from './usePointer'
export default function useRaycaster(options) {
export interface RaycasterInterface {
position: Vector3
updatePosition(coords: Vector2): void
intersect(coords: Vector2, objects: IntersectObject[]): Intersection[],
}
export interface RaycasterConfigInterface {
camera: Camera
resetPosition?: Vector3
}
export default function useRaycaster(options: RaycasterConfigInterface): RaycasterInterface {
const {
camera,
resetPosition = new Vector3(0, 0, 0),
} = options;
} = options
const raycaster = new Raycaster();
const position = resetPosition.clone();
const plane = new Plane(new Vector3(0, 0, 1), 0);
const raycaster = new Raycaster()
const position = resetPosition.clone()
const plane = new Plane(new Vector3(0, 0, 1), 0)
const updatePosition = (coords) => {
raycaster.setFromCamera(coords, camera);
camera.getWorldDirection(plane.normal);
raycaster.ray.intersectPlane(plane, position);
};
const updatePosition = (coords: Vector2) => {
raycaster.setFromCamera(coords, camera)
camera.getWorldDirection(plane.normal)
raycaster.ray.intersectPlane(plane, position)
}
const intersect = (coords, objects) => {
raycaster.setFromCamera(coords, camera);
return raycaster.intersectObjects(objects);
};
const intersect = (coords: Vector2, objects: IntersectObject[]) => {
raycaster.setFromCamera(coords, camera)
return raycaster.intersectObjects(objects)
}
return {
position,
updatePosition,
intersect,
};
};
}
}

View File

@ -15,15 +15,15 @@ export function bindProps(src: any, props: string[], dst: string): void {
})
}
export function bindProp(src: any, srcProp: string, dst: any, dstProp: string): void {
if (!dstProp) dstProp = srcProp
export function bindProp(src: any, srcProp: string, dst: any, dstProp?: string): void {
const _dstProp = dstProp || srcProp
const ref = toRef(src, srcProp)
if (ref.value instanceof Object) {
setFromProp(dst[dstProp], ref.value)
watch(ref, (value) => { setFromProp(dst[dstProp], value) }, { deep: true })
setFromProp(dst[_dstProp], ref.value)
watch(ref, (value) => { setFromProp(dst[_dstProp], value) }, { deep: true })
} else {
if (ref.value) dst[dstProp] = src[srcProp]
watch(ref, (value) => { dst[dstProp] = value })
if (ref.value) dst[_dstProp] = src[srcProp]
watch(ref, (value) => { dst[_dstProp] = value })
}
}