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
|
||||
},
|
||||
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() : []
|
||||
|
@ -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',
|
||||
});
|
||||
})
|
||||
|
@ -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',
|
||||
});
|
||||
})
|
||||
|
@ -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',
|
||||
});
|
||||
})
|
||||
|
@ -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',
|
||||
});
|
||||
})
|
||||
|
@ -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'
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
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 {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user