mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
wip
This commit is contained in:
parent
d2006b1f2c
commit
de98dd8d11
@ -61,8 +61,8 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
add(o) { this.o3d.add(o); },
|
add(o: Object3D) { this.o3d.add(o) },
|
||||||
remove(o) { this.o3d.remove(o); },
|
remove(o: Object3D) { this.o3d.remove(o) },
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return this.$slots.default ? this.$slots.default() : []
|
return this.$slots.default ? this.$slots.default() : []
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue'
|
||||||
import { OrthographicCamera } from 'three';
|
import { OrthographicCamera } from 'three'
|
||||||
import { bindProp } from '../tools';
|
import { bindProp } from '../tools'
|
||||||
import Camera from './Camera';
|
import Camera from './Camera'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Camera,
|
extends: Camera,
|
||||||
name: 'OrthographicCamera',
|
name: 'OrthographicCamera',
|
||||||
inject: ['three'],
|
|
||||||
props: {
|
props: {
|
||||||
left: { type: Number, default: -1 },
|
left: { type: Number, default: -1 },
|
||||||
right: { type: Number, default: 1 },
|
right: { type: Number, default: 1 },
|
||||||
@ -15,20 +14,25 @@ export default defineComponent({
|
|||||||
near: { type: Number, default: 0.1 },
|
near: { type: Number, default: 0.1 },
|
||||||
far: { type: Number, default: 2000 },
|
far: { type: Number, default: 2000 },
|
||||||
zoom: { type: Number, default: 1 },
|
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() {
|
created() {
|
||||||
this.camera = new OrthographicCamera(this.left, this.right, this.top, this.bottom, this.near, this.far);
|
|
||||||
bindProp(this, 'position', this.camera);
|
bindProp(this, 'position', this.camera);
|
||||||
|
|
||||||
['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'].forEach(p => {
|
['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'].forEach(p => {
|
||||||
watch(() => this[p], () => {
|
watch(() => this[p], () => {
|
||||||
this.camera[p] = 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',
|
__hmrId: 'OrthographicCamera',
|
||||||
});
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue'
|
||||||
import { PerspectiveCamera } from 'three';
|
import { PerspectiveCamera } from 'three'
|
||||||
import { bindProp } from '../tools';
|
import { bindProp } from '../tools'
|
||||||
import Camera from './Camera';
|
import Camera from './Camera'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Camera,
|
extends: Camera,
|
||||||
@ -12,24 +12,30 @@ export default defineComponent({
|
|||||||
far: { type: Number, default: 2000 },
|
far: { type: Number, default: 2000 },
|
||||||
fov: { type: Number, default: 50 },
|
fov: { type: Number, default: 50 },
|
||||||
near: { type: Number, default: 0.1 },
|
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 },
|
lookAt: { type: Object, default: null },
|
||||||
},
|
},
|
||||||
|
setup(props) {
|
||||||
|
return {
|
||||||
|
camera: new PerspectiveCamera(props.fov, props.aspect, props.near, props.far),
|
||||||
|
}
|
||||||
|
},
|
||||||
created() {
|
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);
|
// TODO : fix lookAt x
|
||||||
watch(() => this.lookAt, (v) => { this.camera.lookAt(v.x, v.y, v.z); }, { deep: true });
|
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], () => {
|
watch(() => this[p], () => {
|
||||||
this.camera[p] = this[p];
|
this.camera[p] = this[p]
|
||||||
this.camera.updateProjectionMatrix();
|
this.camera.updateProjectionMatrix()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
this.three.camera = this.camera;
|
this.three.camera = this.camera
|
||||||
},
|
},
|
||||||
__hmrId: 'PerspectiveCamera',
|
__hmrId: 'PerspectiveCamera',
|
||||||
});
|
})
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { Object3D } from 'three'
|
||||||
import usePointer from './usePointer';
|
import { defineComponent } from 'vue'
|
||||||
|
import usePointer, { PointerIntersectCallbackType } from './usePointer'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
const emptyCallBack: PointerIntersectCallbackType = () => {}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Raycaster',
|
name: 'Raycaster',
|
||||||
inject: ['three', 'renderer'],
|
inject: ['three', 'renderer'],
|
||||||
props: {
|
props: {
|
||||||
onPointerEnter: { type: Function, default: () => {} },
|
onPointerEnter: { type: Function, default: emptyCallBack },
|
||||||
onPointerOver: { type: Function, default: () => {} },
|
onPointerOver: { type: Function, default: emptyCallBack },
|
||||||
onPointerMove: { type: Function, default: () => {} },
|
onPointerMove: { type: Function, default: emptyCallBack },
|
||||||
onPointerLeave: { type: Function, default: () => {} },
|
onPointerLeave: { type: Function, default: emptyCallBack },
|
||||||
onClick: { type: Function, default: () => {} },
|
onClick: { type: Function, default: emptyCallBack },
|
||||||
intersectMode: { type: String, default: 'move' },
|
intersectMode: { type: String, default: 'move' },
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -18,32 +22,32 @@ export default defineComponent({
|
|||||||
camera: this.three.camera,
|
camera: this.three.camera,
|
||||||
domElement: this.three.renderer.domElement,
|
domElement: this.three.renderer.domElement,
|
||||||
intersectObjects: this.getIntersectObjects(),
|
intersectObjects: this.getIntersectObjects(),
|
||||||
onIntersectEnter: this.onPointerEnter,
|
onIntersectEnter: (<PointerIntersectCallbackType> this.onPointerEnter),
|
||||||
onIntersectOver: this.onPointerOver,
|
onIntersectOver: (<PointerIntersectCallbackType> this.onPointerOver),
|
||||||
onIntersectMove: this.onPointerMove,
|
onIntersectMove: (<PointerIntersectCallbackType> this.onPointerMove),
|
||||||
onIntersectLeave: this.onPointerLeave,
|
onIntersectLeave: (<PointerIntersectCallbackType> this.onPointerLeave),
|
||||||
onIntersectClick: this.onClick,
|
onIntersectClick: (<PointerIntersectCallbackType> this.onClick),
|
||||||
});
|
})
|
||||||
this.pointer.addListeners();
|
this.pointer.addListeners()
|
||||||
|
|
||||||
if (this.intersectMode === 'frame') {
|
if (this.intersectMode === 'frame') {
|
||||||
this.renderer.onBeforeRender(this.pointer.intersect);
|
this.renderer.onBeforeRender(this.pointer.intersect)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
if (this.pointer) {
|
if (this.pointer) {
|
||||||
this.pointer.removeListeners();
|
this.pointer.removeListeners()
|
||||||
this.renderer.offBeforeRender(this.pointer.intersect);
|
this.renderer.offBeforeRender(this.pointer.intersect)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getIntersectObjects() {
|
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() {
|
render() {
|
||||||
return [];
|
return []
|
||||||
},
|
},
|
||||||
__hmrId: 'Raycaster',
|
__hmrId: 'Raycaster',
|
||||||
});
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue'
|
||||||
import { Scene, Color } from 'three';
|
import { Scene, Color, Object3D } from 'three'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Scene',
|
name: 'Scene',
|
||||||
@ -9,27 +9,29 @@ export default defineComponent({
|
|||||||
background: [String, Number],
|
background: [String, Number],
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const scene = new Scene();
|
const scene = new Scene()
|
||||||
if (props.background) scene.background = new Color(props.background);
|
if (props.background) {
|
||||||
watch(() => props.background, (value) => { scene.background.set(value); });
|
scene.background = new Color(props.background)
|
||||||
return { scene };
|
}
|
||||||
|
watch(() => props.background, (value) => { if (scene.background instanceof Color && value) scene.background.set(value) })
|
||||||
|
return { scene }
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
scene: this.scene,
|
scene: this.scene,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.three.scene) {
|
if (!this.three.scene) {
|
||||||
this.three.scene = this.scene;
|
this.three.scene = this.scene
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
add(o) { this.scene.add(o); },
|
add(o: Object3D) { this.scene.add(o) },
|
||||||
remove(o) { this.scene.remove(o); },
|
remove(o: Object3D) { this.scene.remove(o) },
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return this.$slots.default ? this.$slots.default() : [];
|
return this.$slots.default ? this.$slots.default() : []
|
||||||
},
|
},
|
||||||
__hmrId: 'Scene',
|
__hmrId: 'Scene',
|
||||||
});
|
})
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
export { default as Renderer } from './Renderer';
|
export { default as Renderer } from './Renderer'
|
||||||
export { default as OrthographicCamera } from './OrthographicCamera';
|
export { default as OrthographicCamera } from './OrthographicCamera'
|
||||||
export { default as PerspectiveCamera } from './PerspectiveCamera';
|
export { default as PerspectiveCamera } from './PerspectiveCamera'
|
||||||
export { default as Camera } from './PerspectiveCamera';
|
export { default as Camera } from './PerspectiveCamera'
|
||||||
export { default as Group } from './Group';
|
export { default as Group } from './Group'
|
||||||
export { default as Scene } from './Scene';
|
export { default as Scene } from './Scene'
|
||||||
export { default as Object3D } from './Object3D';
|
export { default as Object3D } from './Object3D'
|
||||||
export { default as Raycaster } from './Raycaster';
|
export { default as Raycaster } from './Raycaster'
|
||||||
|
@ -16,6 +16,8 @@ export interface PointerIntersectEventInterface {
|
|||||||
intersect?: Intersection
|
intersect?: Intersection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PointerIntersectCallbackType = (e: PointerIntersectEventInterface) => void
|
||||||
|
|
||||||
export type IntersectObject = Mesh | InstancedMesh
|
export type IntersectObject = Mesh | InstancedMesh
|
||||||
|
|
||||||
export interface PointerConfigInterface {
|
export interface PointerConfigInterface {
|
||||||
@ -31,11 +33,11 @@ export interface PointerConfigInterface {
|
|||||||
onMove?(e: PointerEventInterface): void
|
onMove?(e: PointerEventInterface): void
|
||||||
onLeave?(e: PointerEventInterface): void
|
onLeave?(e: PointerEventInterface): void
|
||||||
onClick?(e: PointerEventInterface): void
|
onClick?(e: PointerEventInterface): void
|
||||||
onIntersectEnter?(e: PointerIntersectEventInterface): void
|
onIntersectEnter: PointerIntersectCallbackType
|
||||||
onIntersectOver?(e: PointerIntersectEventInterface): void
|
onIntersectOver: PointerIntersectCallbackType
|
||||||
onIntersectMove?(e: PointerIntersectEventInterface): void
|
onIntersectMove: PointerIntersectCallbackType
|
||||||
onIntersectLeave?(e: PointerIntersectEventInterface): void
|
onIntersectLeave: PointerIntersectCallbackType
|
||||||
onIntersectClick?(e: PointerIntersectEventInterface): void
|
onIntersectClick: PointerIntersectCallbackType
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PointerInterface {
|
export interface PointerInterface {
|
||||||
|
@ -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 {
|
const {
|
||||||
camera,
|
camera,
|
||||||
resetPosition = new Vector3(0, 0, 0),
|
resetPosition = new Vector3(0, 0, 0),
|
||||||
} = options;
|
} = options
|
||||||
|
|
||||||
const raycaster = new Raycaster();
|
const raycaster = new Raycaster()
|
||||||
const position = resetPosition.clone();
|
const position = resetPosition.clone()
|
||||||
const plane = new Plane(new Vector3(0, 0, 1), 0);
|
const plane = new Plane(new Vector3(0, 0, 1), 0)
|
||||||
|
|
||||||
const updatePosition = (coords) => {
|
const updatePosition = (coords: Vector2) => {
|
||||||
raycaster.setFromCamera(coords, camera);
|
raycaster.setFromCamera(coords, camera)
|
||||||
camera.getWorldDirection(plane.normal);
|
camera.getWorldDirection(plane.normal)
|
||||||
raycaster.ray.intersectPlane(plane, position);
|
raycaster.ray.intersectPlane(plane, position)
|
||||||
};
|
}
|
||||||
|
|
||||||
const intersect = (coords, objects) => {
|
const intersect = (coords: Vector2, objects: IntersectObject[]) => {
|
||||||
raycaster.setFromCamera(coords, camera);
|
raycaster.setFromCamera(coords, camera)
|
||||||
return raycaster.intersectObjects(objects);
|
return raycaster.intersectObjects(objects)
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
position,
|
position,
|
||||||
updatePosition,
|
updatePosition,
|
||||||
intersect,
|
intersect,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
12
src/tools.ts
12
src/tools.ts
@ -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 {
|
export function bindProp(src: any, srcProp: string, dst: any, dstProp?: string): void {
|
||||||
if (!dstProp) dstProp = srcProp
|
const _dstProp = dstProp || srcProp
|
||||||
const ref = toRef(src, srcProp)
|
const ref = toRef(src, srcProp)
|
||||||
if (ref.value instanceof Object) {
|
if (ref.value instanceof Object) {
|
||||||
setFromProp(dst[dstProp], ref.value)
|
setFromProp(dst[_dstProp], ref.value)
|
||||||
watch(ref, (value) => { setFromProp(dst[dstProp], value) }, { deep: true })
|
watch(ref, (value) => { setFromProp(dst[_dstProp], value) }, { deep: true })
|
||||||
} else {
|
} else {
|
||||||
if (ref.value) dst[dstProp] = src[srcProp]
|
if (ref.value) dst[_dstProp] = src[srcProp]
|
||||||
watch(ref, (value) => { dst[dstProp] = value })
|
watch(ref, (value) => { dst[_dstProp] = value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user