mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
commit
a583889060
@ -1,7 +1,7 @@
|
|||||||
import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';
|
import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import Object3D from '../../core/Object3D.js';
|
import Object3D from '../../core/Object3D.js';
|
||||||
import { bindProps } from '../../tools.js';
|
import { bindProps } from '../../tools';
|
||||||
import LiquidEffect from './LiquidEffect.js';
|
import LiquidEffect from './LiquidEffect.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -14,7 +14,7 @@ import Camera from '../../core/PerspectiveCamera.js';
|
|||||||
import Renderer from '../../core/Renderer.js';
|
import Renderer from '../../core/Renderer.js';
|
||||||
import Scene from '../../core/Scene.js';
|
import Scene from '../../core/Scene.js';
|
||||||
|
|
||||||
import { lerp } from '../../tools.js';
|
import { lerp } from '../../tools';
|
||||||
import AnimatedPlane from './AnimatedPlane.js';
|
import AnimatedPlane from './AnimatedPlane.js';
|
||||||
import useTextures from '../../use/useTextures';
|
import useTextures from '../../use/useTextures';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import OrthographicCamera from '../../core/OrthographicCamera.js';
|
|||||||
import Renderer from '../../core/Renderer.js';
|
import Renderer from '../../core/Renderer.js';
|
||||||
import Scene from '../../core/Scene.js';
|
import Scene from '../../core/Scene.js';
|
||||||
|
|
||||||
import { lerp, lerpv2 } from '../../tools.js';
|
import { lerp, lerpv2 } from '../../tools';
|
||||||
import ZoomBlurImage from './ZoomBlurImage.js';
|
import ZoomBlurImage from './ZoomBlurImage.js';
|
||||||
import useTextures from '../../use/useTextures.js';
|
import useTextures from '../../use/useTextures.js';
|
||||||
|
|
||||||
|
11
src/core/Camera.js
Normal file
11
src/core/Camera.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// import Object3D from '../core/Object3D.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// TODO: eventually extend Object3D, for now: error 'injection "scene" not found'
|
||||||
|
// because camera is a sibling of scene in Trois
|
||||||
|
// extends: Object3D,
|
||||||
|
inject: ['three'],
|
||||||
|
render() {
|
||||||
|
return this.$slots.default ? this.$slots.default() : [];
|
||||||
|
},
|
||||||
|
}
|
@ -1,20 +1,38 @@
|
|||||||
|
import { Vector2 } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools/index.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Object3D',
|
name: 'Object3D',
|
||||||
inject: ['three', 'scene', 'rendererComponent'],
|
inject: ['three', 'scene', 'rendererComponent'],
|
||||||
emits: ['created', 'ready'],
|
emits: ['created', 'ready', 'pointerEnter', 'pointerOver', 'pointerLeave', 'click'],
|
||||||
props: {
|
props: {
|
||||||
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
|
position: { type: Object, default: { x: 0, y: 0, z: 0 } },
|
||||||
rotation: { type: Object, default: { x: 0, y: 0, z: 0 } },
|
rotation: { type: Object, default: { x: 0, y: 0, z: 0 } },
|
||||||
scale: { type: Object, default: { x: 1, y: 1, z: 1 } },
|
scale: { type: Object, default: { x: 1, y: 1, z: 1 } },
|
||||||
lookAt: { type: Object, default: null },
|
lookAt: { type: Object, default: null },
|
||||||
|
onPointerEnter: { type: Function, default: null },
|
||||||
|
onPointerOver: { type: Function, default: null },
|
||||||
|
onPointerLeave: { type: Function, default: null },
|
||||||
|
onClick: { type: Function, default: null },
|
||||||
|
usePointerEvents: { type: Boolean, default: false },
|
||||||
|
pointerObjects: { type: [Boolean, Array], default: null }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pointerOver: null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// can't use setup because it will not be used in sub components
|
// can't use setup because it will not be used in sub components
|
||||||
// setup() {},
|
// setup() {},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
if (this._parent) this._parent.remove(this.o3d);
|
if (this._parent) this._parent.remove(this.o3d);
|
||||||
|
|
||||||
|
// teardown listeners
|
||||||
|
this.three.offBeforeRender(this.pointerHandler);
|
||||||
|
if (this.three.mouse_move_element) {
|
||||||
|
this.three.mouse_move_element.removeEventListener('mouseleave', this.renderElementLeaveHandler)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initObject3D(o3d) {
|
initObject3D(o3d) {
|
||||||
@ -29,6 +47,24 @@ export default {
|
|||||||
if (this.lookAt) this.o3d.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z);
|
if (this.lookAt) this.o3d.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z);
|
||||||
watch(() => this.lookAt, (v) => { this.o3d.lookAt(v.x, v.y, v.z); }, { deep: true });
|
watch(() => this.lookAt, (v) => { this.o3d.lookAt(v.x, v.y, v.z); }, { deep: true });
|
||||||
|
|
||||||
|
if (this.usePointerEvents
|
||||||
|
|| this.onPointerEnter
|
||||||
|
|| this.onPointerOver
|
||||||
|
|| this.onPointerLeave
|
||||||
|
|| this.onClick) {
|
||||||
|
this.three.onBeforeRender(this.pointerHandler);
|
||||||
|
}
|
||||||
|
if (this.onPointerLeave) {
|
||||||
|
// we need to wait a tick so the mouse_move_element is created
|
||||||
|
// TODO: more robust fix
|
||||||
|
this.$nextTick(() => this.three.mouse_move_element.addEventListener('mouseleave', this.renderElementLeaveHandler));
|
||||||
|
}
|
||||||
|
if (this.onClick) {
|
||||||
|
window.addEventListener('click', this.clickHandler);
|
||||||
|
// TODO: touch
|
||||||
|
}
|
||||||
|
|
||||||
|
// find first viable parent
|
||||||
let parent = this.$parent;
|
let parent = this.$parent;
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent.add) {
|
if (parent.add) {
|
||||||
@ -43,6 +79,103 @@ export default {
|
|||||||
},
|
},
|
||||||
add(o) { this.o3d.add(o); },
|
add(o) { this.o3d.add(o); },
|
||||||
remove(o) { this.o3d.remove(o); },
|
remove(o) { this.o3d.remove(o); },
|
||||||
|
pointerHandler() {
|
||||||
|
this.three.raycaster.setFromCamera(this.three.mouse, this.three.camera);
|
||||||
|
|
||||||
|
// determine what we're raycasting against
|
||||||
|
let objectsToCastAgainst = this.pointerObjects;
|
||||||
|
if (objectsToCastAgainst) {
|
||||||
|
// cast against all objects in scene if prop is `true`
|
||||||
|
if (objectsToCastAgainst === true) {
|
||||||
|
objectsToCastAgainst = this.three.scene.children;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// default: just cast against this object
|
||||||
|
objectsToCastAgainst = [this.o3d];
|
||||||
|
}
|
||||||
|
|
||||||
|
// find all intersects
|
||||||
|
const intersects = this.three.raycaster.intersectObjects(objectsToCastAgainst);
|
||||||
|
// determine if the first intersect is this object
|
||||||
|
const match = intersects.length &&
|
||||||
|
intersects[0].object.uuid === this.o3d.uuid
|
||||||
|
? intersects[0]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// if so, let's start the callback process
|
||||||
|
if (match) {
|
||||||
|
// pointer is newly over o3d
|
||||||
|
if (!this.pointerOver) {
|
||||||
|
this.pointerOver = true;
|
||||||
|
|
||||||
|
if (this.onPointerEnter) {
|
||||||
|
|
||||||
|
this.onPointerEnter({
|
||||||
|
object: this.o3d,
|
||||||
|
intersect: match
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.usePointerEvents) {
|
||||||
|
this.$emit('pointerEnter', {
|
||||||
|
object: this.o3d,
|
||||||
|
intersect: match
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pointer is still over o3d
|
||||||
|
else if (this.onPointerOver) {
|
||||||
|
this.onPointerOver({
|
||||||
|
object: this.o3d,
|
||||||
|
intersect: match
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.usePointerEvents) {
|
||||||
|
this.$emit('pointerOver', {
|
||||||
|
object: this.o3d,
|
||||||
|
intersect: match
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// pointer is not over o3d
|
||||||
|
|
||||||
|
// pointer has just left o3d
|
||||||
|
if (this.pointerOver) {
|
||||||
|
this.pointerOver = false;
|
||||||
|
if (this.onPointerLeave) {
|
||||||
|
this.onPointerLeave({ object: this.o3d });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.usePointerEvents) {
|
||||||
|
this.$emit('pointerLeave', {
|
||||||
|
object: this.o3d
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clickHandler(evt) {
|
||||||
|
if (this.pointerOver) {
|
||||||
|
// cast a ray so we can provide hit info
|
||||||
|
this.three.raycaster.setFromCamera(this.three.mouse, this.three.camera);
|
||||||
|
const [intersect] = this.three.raycaster.intersectObjects([this.o3d]);
|
||||||
|
|
||||||
|
// callbacks and events
|
||||||
|
if (this.onClick) {
|
||||||
|
this.onClick({ object: this.o3d, intersect });
|
||||||
|
}
|
||||||
|
if (this.usePointerEvents) {
|
||||||
|
this.$emit('click', { object: this.o3d, intersect });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderElementLeaveHandler() {
|
||||||
|
// since the mouse is off the renderer, we'll set its values to an unreachable number
|
||||||
|
this.three.mouse.x = this.three.mouse.y = Infinity;
|
||||||
|
// then run the normal pointer handler with these updated mouse values
|
||||||
|
this.pointerHandler();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return this.$slots.default ? this.$slots.default() : [];
|
return this.$slots.default ? this.$slots.default() : [];
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { OrthographicCamera } from 'three';
|
import { OrthographicCamera } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
import Camera from './Camera.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
extends: Camera,
|
||||||
name: 'OrthographicCamera',
|
name: 'OrthographicCamera',
|
||||||
inject: ['three'],
|
inject: ['three'],
|
||||||
props: {
|
props: {
|
||||||
@ -28,6 +30,5 @@ export default {
|
|||||||
|
|
||||||
this.three.camera = this.camera;
|
this.three.camera = this.camera;
|
||||||
},
|
},
|
||||||
render() { return []; },
|
|
||||||
__hmrId: 'OrthographicCamera',
|
__hmrId: 'OrthographicCamera',
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { PerspectiveCamera } from 'three';
|
import { PerspectiveCamera } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
import Camera from './Camera.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
extends: Camera,
|
||||||
name: 'PerspectiveCamera',
|
name: 'PerspectiveCamera',
|
||||||
inject: ['three'],
|
inject: ['three'],
|
||||||
props: {
|
props: {
|
||||||
@ -29,6 +31,5 @@ export default {
|
|||||||
|
|
||||||
this.three.camera = this.camera;
|
this.three.camera = this.camera;
|
||||||
},
|
},
|
||||||
render() { return []; },
|
|
||||||
__hmrId: 'PerspectiveCamera',
|
__hmrId: 'PerspectiveCamera',
|
||||||
};
|
};
|
||||||
|
166
src/core/Raycaster.js
Normal file
166
src/core/Raycaster.js
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import { Raycaster, Vector2 } from 'three'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Raycaster',
|
||||||
|
inject: ['three'],
|
||||||
|
props: {
|
||||||
|
onBeforeRender: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
onPointerEnter: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
onPointerLeave: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
onPointerOver: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
onClick: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
scene: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// user-provided camera. defaults to first parent camera
|
||||||
|
camera: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
intersects: {
|
||||||
|
type: Array,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const raycaster = new Raycaster();
|
||||||
|
const pointer = new Vector2();
|
||||||
|
|
||||||
|
return { pointer, raycaster }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
raycasterCamera: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// add update method
|
||||||
|
this.three.onBeforeRender(this.update);
|
||||||
|
|
||||||
|
// if we have a custom onBeforeRender method, assume
|
||||||
|
// the user is handling everything and exit setup
|
||||||
|
if (this.onBeforeRender) return;
|
||||||
|
|
||||||
|
|
||||||
|
// prep non-reactive list of intersections
|
||||||
|
this._intersects = [];
|
||||||
|
|
||||||
|
// save camera if we don't already have one
|
||||||
|
if (!this.camera) {
|
||||||
|
let parent = this.$parent;
|
||||||
|
while (parent && !this.raycasterCamera) {
|
||||||
|
this.raycasterCamera = parent.camera;
|
||||||
|
parent = parent.$parent;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.raycasterCamera = this.camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add event listeners
|
||||||
|
window.addEventListener('mousemove', this.onMouseMove);
|
||||||
|
window.addEventListener('touchmove', this.onTouchMove);
|
||||||
|
if (this.onClick) {
|
||||||
|
window.addEventListener('click', this.clickHandler);
|
||||||
|
}
|
||||||
|
// TODO: touch
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
update() {
|
||||||
|
// custom callback
|
||||||
|
if (this.onBeforeRender) {
|
||||||
|
this.onBeforeRender(this.raycaster);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save scene
|
||||||
|
const scene = this.scene || this.three.scene;
|
||||||
|
if (!scene) {
|
||||||
|
console.log('No scene detected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run standard camera-based raycaster...
|
||||||
|
this.raycaster.setFromCamera(this.pointer, this.raycasterCamera);
|
||||||
|
const intersects = this.raycaster.intersectObjects(
|
||||||
|
// ...against either our predefined objects or all objects in scene
|
||||||
|
this.intersects || scene.children
|
||||||
|
);
|
||||||
|
|
||||||
|
// capture expired intersects
|
||||||
|
if (this.onPointerLeave) {
|
||||||
|
const newObjects = intersects.map(intersect => {
|
||||||
|
return {
|
||||||
|
object: intersect.object,
|
||||||
|
instanceId: intersect.instanceId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// TODO: optimize
|
||||||
|
const expiredIntersects = this._intersects.filter(intersect => !newObjects.find(val => val.object === intersect.object && val.instanceId === intersect.instanceId));
|
||||||
|
if (expiredIntersects.length) {
|
||||||
|
this.onPointerLeave(expiredIntersects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// capture new intersects
|
||||||
|
if (this.onPointerEnter) {
|
||||||
|
const old = this._intersects.map(intersect => {
|
||||||
|
return {
|
||||||
|
object: intersect.object,
|
||||||
|
instanceId: intersect.instanceId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// TODO: optimize
|
||||||
|
const newIntersects = intersects.filter(intersect => !old.find(val => val.object === intersect.object && val.instanceId === intersect.instanceId));
|
||||||
|
if (newIntersects.length) {
|
||||||
|
this.onPointerEnter(newIntersects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// capture current intersects
|
||||||
|
if (this.onPointerOver) {
|
||||||
|
this.onPointerOver(intersects);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save internal intersect list
|
||||||
|
this._intersects = intersects;
|
||||||
|
},
|
||||||
|
onMouseMove(evt) {
|
||||||
|
const { top: canvasTop, left: canvasLeft } = this.three.mouse_move_element.getBoundingClientRect();
|
||||||
|
this.pointer.x = ((evt.x - canvasLeft) / this.three.size.width) * 2 - 1;
|
||||||
|
this.pointer.y = - ((evt.y - canvasTop) / this.three.size.height) * 2 + 1;
|
||||||
|
},
|
||||||
|
clickHandler(evt) {
|
||||||
|
// if we have any intersects, fire onclick method
|
||||||
|
if (this._intersects && this._intersects.length) {
|
||||||
|
this.onClick(this._intersects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return this.$slots.default ? this.$slots.default() : [];
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
window.removeEventListener('mousemove', this.onMouseMove);
|
||||||
|
window.removeEventListener('touchstart', this.onTouchMove);
|
||||||
|
window.removeEventListener('click', this.clickHandler);
|
||||||
|
|
||||||
|
// TODO: touch
|
||||||
|
},
|
||||||
|
__hmrId: 'Raycaster',
|
||||||
|
};
|
@ -7,10 +7,11 @@ export default {
|
|||||||
antialias: Boolean,
|
antialias: Boolean,
|
||||||
alpha: Boolean,
|
alpha: Boolean,
|
||||||
autoClear: { type: Boolean, default: true },
|
autoClear: { type: Boolean, default: true },
|
||||||
mouseMove: { type: [Boolean, String], default: false },
|
// mouseMove: { type: [Boolean, String], default: false },
|
||||||
mouseRaycast: { type: Boolean, default: false },
|
// mouseRaycast: { type: Boolean, default: false },
|
||||||
mouseOver: { type: Boolean, default: false },
|
// mouseOver: { type: Boolean, default: false },
|
||||||
click: { type: Boolean, default: false },
|
usePointer: { type: Boolean, default: true },
|
||||||
|
// click: { type: Boolean, default: false },
|
||||||
orbitCtrl: { type: [Boolean, Object], default: false },
|
orbitCtrl: { type: [Boolean, Object], default: false },
|
||||||
resize: { type: [Boolean, String], default: false },
|
resize: { type: [Boolean, String], default: false },
|
||||||
shadow: Boolean,
|
shadow: Boolean,
|
||||||
@ -38,10 +39,11 @@ export default {
|
|||||||
alpha: this.alpha,
|
alpha: this.alpha,
|
||||||
autoClear: this.autoClear,
|
autoClear: this.autoClear,
|
||||||
orbit_ctrl: this.orbitCtrl,
|
orbit_ctrl: this.orbitCtrl,
|
||||||
mouse_move: this.mouseMove,
|
// mouse_move: this.mouseMove,
|
||||||
mouse_raycast: this.mouseRaycast,
|
// mouse_raycast: this.mouseRaycast,
|
||||||
mouse_over: this.mouseOver,
|
// mouse_over: this.mouseOver,
|
||||||
click: this.click,
|
use_pointer: this.usePointer,
|
||||||
|
// click: this.click,
|
||||||
resize: this.resize,
|
resize: this.resize,
|
||||||
width: this.width,
|
width: this.width,
|
||||||
height: this.height,
|
height: this.height,
|
||||||
|
@ -5,3 +5,4 @@ export { default as Camera } from './PerspectiveCamera.js';
|
|||||||
export { default as Group } from './Group.js';
|
export { default as Group } from './Group.js';
|
||||||
export { default as Scene } from './Scene.js';
|
export { default as Scene } from './Scene.js';
|
||||||
export { default as Object3D } from './Object3D.js';
|
export { default as Object3D } from './Object3D.js';
|
||||||
|
export { default as Raycaster } from './Raycaster.js';
|
@ -19,10 +19,11 @@ export default function useThree() {
|
|||||||
alpha: false,
|
alpha: false,
|
||||||
autoClear: true,
|
autoClear: true,
|
||||||
orbit_ctrl: false,
|
orbit_ctrl: false,
|
||||||
mouse_move: false,
|
// mouse_move: false,
|
||||||
mouse_raycast: false,
|
// mouse_raycast: false,
|
||||||
mouse_over: false,
|
// mouse_over: false,
|
||||||
click: false,
|
use_pointer: true,
|
||||||
|
// click: false,
|
||||||
resize: true,
|
resize: true,
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
@ -41,7 +42,7 @@ export default function useThree() {
|
|||||||
let beforeRenderCallbacks = [];
|
let beforeRenderCallbacks = [];
|
||||||
|
|
||||||
// mouse tracking
|
// mouse tracking
|
||||||
const mouse = new Vector2();
|
const mouse = new Vector2(Infinity, Infinity);
|
||||||
const mouseV3 = new Vector3();
|
const mouseV3 = new Vector3();
|
||||||
const mousePlane = new Plane(new Vector3(0, 0, 1), 0);
|
const mousePlane = new Plane(new Vector3(0, 0, 1), 0);
|
||||||
const raycaster = new Raycaster();
|
const raycaster = new Raycaster();
|
||||||
@ -59,6 +60,7 @@ export default function useThree() {
|
|||||||
scene: null,
|
scene: null,
|
||||||
size,
|
size,
|
||||||
mouse, mouseV3,
|
mouse, mouseV3,
|
||||||
|
raycaster,
|
||||||
init,
|
init,
|
||||||
dispose,
|
dispose,
|
||||||
render,
|
render,
|
||||||
@ -109,20 +111,23 @@ export default function useThree() {
|
|||||||
setSize(conf.width | 300, conf.height | 150);
|
setSize(conf.width | 300, conf.height | 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.mouse_move = conf.mouse_move || conf.mouse_over;
|
// conf.mouse_move = conf.mouse_move || conf.mouse_over;
|
||||||
if (conf.mouse_move) {
|
if (conf.use_pointer) {
|
||||||
if (conf.mouse_move === 'body') {
|
if (conf.use_pointer === true) {
|
||||||
obj.mouse_move_element = document.body;
|
// use renderer element as mousemove by default
|
||||||
} else {
|
|
||||||
obj.mouse_move_element = obj.renderer.domElement;
|
obj.mouse_move_element = obj.renderer.domElement;
|
||||||
|
} else {
|
||||||
|
// use custom element as mousemove element
|
||||||
|
obj.mouse_move_element = conf.use_pointer;
|
||||||
}
|
}
|
||||||
obj.mouse_move_element.addEventListener('mousemove', onMousemove);
|
obj.mouse_move_element.addEventListener('mousemove', onMousemove);
|
||||||
obj.mouse_move_element.addEventListener('mouseleave', onMouseleave);
|
obj.mouse_move_element.addEventListener('mouseleave', onMouseleave);
|
||||||
|
// TODO: touch
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.click) {
|
// if (conf.click) {
|
||||||
obj.renderer.domElement.addEventListener('click', onClick);
|
// obj.renderer.domElement.addEventListener('click', onClick);
|
||||||
}
|
// }
|
||||||
|
|
||||||
afterInitCallbacks.forEach(c => c());
|
afterInitCallbacks.forEach(c => c());
|
||||||
|
|
||||||
@ -211,7 +216,8 @@ export default function useThree() {
|
|||||||
obj.mouse_move_element.removeEventListener('mousemove', onMousemove);
|
obj.mouse_move_element.removeEventListener('mousemove', onMousemove);
|
||||||
obj.mouse_move_element.removeEventListener('mouseleave', onMouseleave);
|
obj.mouse_move_element.removeEventListener('mouseleave', onMouseleave);
|
||||||
}
|
}
|
||||||
obj.renderer.domElement.removeEventListener('click', onClick);
|
// obj.renderer.domElement.removeEventListener('click', onClick);
|
||||||
|
// TODO: touch
|
||||||
if (obj.orbitCtrl) obj.orbitCtrl.dispose();
|
if (obj.orbitCtrl) obj.orbitCtrl.dispose();
|
||||||
this.renderer.dispose();
|
this.renderer.dispose();
|
||||||
}
|
}
|
||||||
@ -219,75 +225,37 @@ export default function useThree() {
|
|||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function updateMouse(e) {
|
function updateMouse(e) {
|
||||||
const rect = e.target.getBoundingClientRect();
|
const rect = obj.mouse_move_element.getBoundingClientRect();
|
||||||
mouse.x = ((e.clientX - rect.left) / size.width) * 2 - 1;
|
mouse.x = ((e.x - rect.left) / size.width) * 2 - 1;
|
||||||
mouse.y = -((e.clientY - rect.top) / size.height) * 2 + 1;
|
mouse.y = -((e.y - rect.top) / size.height) * 2 + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* click listener
|
* click listener
|
||||||
*/
|
*/
|
||||||
function onClick(e) {
|
// function onClick(e) {
|
||||||
updateMouse(e);
|
// updateMouse(e);
|
||||||
raycaster.setFromCamera(mouse, obj.camera);
|
// raycaster.setFromCamera(mouse, obj.camera);
|
||||||
const objects = raycaster.intersectObjects(intersectObjects);
|
// const objects = raycaster.intersectObjects(intersectObjects);
|
||||||
for (let i = 0; i < objects.length; i++) {
|
// for (let i = 0; i < objects.length; i++) {
|
||||||
const o = objects[i].object;
|
// const o = objects[i].object;
|
||||||
if (o.onClick) o.onClick(e);
|
// if (o.onClick) o.onClick(e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mousemove listener
|
* mousemove listener
|
||||||
*/
|
*/
|
||||||
function onMousemove(e) {
|
function onMousemove(e) {
|
||||||
updateMouse(e);
|
updateMouse(e);
|
||||||
onMousechange(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mouseleave listener
|
* mouseleave listener
|
||||||
*/
|
*/
|
||||||
function onMouseleave(e) {
|
function onMouseleave(e) {
|
||||||
// mouse.x = 0;
|
mouse.x = Infinity;
|
||||||
// mouse.y = 0;
|
mouse.y = Infinity;
|
||||||
onMousechange(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mouse change
|
|
||||||
*/
|
|
||||||
function onMousechange(e) {
|
|
||||||
if (conf.mouse_over || conf.mouse_raycast) {
|
|
||||||
raycaster.setFromCamera(mouse, obj.camera);
|
|
||||||
|
|
||||||
if (conf.mouse_raycast) {
|
|
||||||
// get mouse 3d position
|
|
||||||
obj.camera.getWorldDirection(mousePlane.normal);
|
|
||||||
mousePlane.normal.normalize();
|
|
||||||
raycaster.ray.intersectPlane(mousePlane, mouseV3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf.mouse_over) {
|
|
||||||
const onObjects = raycaster.intersectObjects(intersectObjects);
|
|
||||||
const offObjects = [...intersectObjects];
|
|
||||||
for (let i = 0; i < onObjects.length; i++) {
|
|
||||||
const o = onObjects[i].object;
|
|
||||||
if (!o.hover && o.onHover) {
|
|
||||||
o.hover = true;
|
|
||||||
o.onHover(true);
|
|
||||||
}
|
|
||||||
offObjects.splice(offObjects.indexOf(o), 1);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < offObjects.length; i++) {
|
|
||||||
const o = offObjects[i];
|
|
||||||
if (o.hover && o.onHover) {
|
|
||||||
o.hover = false;
|
|
||||||
o.onHover(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
|
|||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import EffectPass from './EffectPass.js';
|
import EffectPass from './EffectPass.js';
|
||||||
import TiltShift from '../shaders/TiltShift.js';
|
import TiltShift from '../shaders/TiltShift.js';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: EffectPass,
|
extends: EffectPass,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
|
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
|
||||||
import EffectPass from './EffectPass.js';
|
import EffectPass from './EffectPass.js';
|
||||||
import ZoomBlur from '../shaders/ZoomBlur.js';
|
import ZoomBlur from '../shaders/ZoomBlur.js';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: EffectPass,
|
extends: EffectPass,
|
||||||
|
@ -8,4 +8,4 @@ export * from './effects/index.js';
|
|||||||
|
|
||||||
// export * from './components/index.js';
|
// export * from './components/index.js';
|
||||||
|
|
||||||
export * from './tools.js';
|
export * from './tools';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D.js';
|
||||||
import { bindProp, setFromProp } from '../tools.js';
|
import { bindProp, setFromProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: Object3D,
|
extends: Object3D,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { MeshBasicMaterial } from 'three';
|
import { MeshBasicMaterial } from 'three';
|
||||||
import { bindProps, propsValues } from '../tools.js';
|
import { bindProps, propsValues } from '../tools';
|
||||||
import Material, { wireframeProps } from './Material';
|
import Material, { wireframeProps } from './Material';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { MeshLambertMaterial } from 'three';
|
import { MeshLambertMaterial } from 'three';
|
||||||
import { bindProps, propsValues } from '../tools.js';
|
import { bindProps, propsValues } from '../tools';
|
||||||
import Material, { wireframeProps } from './Material';
|
import Material, { wireframeProps } from './Material';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { MeshMatcapMaterial, TextureLoader } from 'three';
|
import { MeshMatcapMaterial, TextureLoader } from 'three';
|
||||||
// import { watch } from 'vue';
|
// import { watch } from 'vue';
|
||||||
import { propsValues, getMatcapUrl } from '../tools.js';
|
import { propsValues, getMatcapUrl } from '../tools';
|
||||||
import Material from './Material';
|
import Material from './Material';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { MeshPhongMaterial } from 'three';
|
import { MeshPhongMaterial } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProps, propsValues } from '../tools.js';
|
import { bindProps, propsValues } from '../tools';
|
||||||
import Material, { wireframeProps } from './Material';
|
import Material, { wireframeProps } from './Material';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { MeshPhysicalMaterial } from 'three';
|
import { MeshPhysicalMaterial } from 'three';
|
||||||
import { propsValues } from '../tools.js';
|
import { propsValues } from '../tools';
|
||||||
import StandardMaterial from './StandardMaterial';
|
import StandardMaterial from './StandardMaterial';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ShaderMaterial } from 'three';
|
import { ShaderMaterial } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { propsValues, defaultFragmentShader, defaultVertexShader } from '../tools.js';
|
import { propsValues, defaultFragmentShader, defaultVertexShader } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['three', 'mesh'],
|
inject: ['three', 'mesh'],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { MeshStandardMaterial } from 'three';
|
import { MeshStandardMaterial } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProp, bindProps, propsValues } from '../tools.js';
|
import { bindProp, bindProps, propsValues } from '../tools';
|
||||||
import Material, { wireframeProps } from './Material';
|
import Material, { wireframeProps } from './Material';
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, TextureLoader, UVMapping } from 'three';
|
import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, TextureLoader, UVMapping } from 'three';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['material'],
|
inject: ['material'],
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { MeshToonMaterial } from 'three';
|
import { MeshToonMaterial } from 'three';
|
||||||
import { bindProps, propsValues } from '../tools.js';
|
import { bindProps, propsValues } from '../tools';
|
||||||
import Material, { wireframeProps } from './Material';
|
import Material, { wireframeProps } from './Material';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
WebGLCubeRenderTarget,
|
WebGLCubeRenderTarget,
|
||||||
} from 'three';
|
} from 'three';
|
||||||
import Mesh from './Mesh.js';
|
import Mesh from './Mesh.js';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: Mesh,
|
extends: Mesh,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { InstancedMesh } from 'three';
|
import { InstancedMesh } from 'three';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D.js';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: Object3D,
|
extends: Object3D,
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
WebGLCubeRenderTarget,
|
WebGLCubeRenderTarget,
|
||||||
} from 'three';
|
} from 'three';
|
||||||
import Mesh from './Mesh.js';
|
import Mesh from './Mesh.js';
|
||||||
import { bindProp } from '../tools.js';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: Mesh,
|
extends: Mesh,
|
||||||
|
@ -7,6 +7,7 @@ export const TroisJSVuePlugin = {
|
|||||||
'Camera',
|
'Camera',
|
||||||
'OrthographicCamera',
|
'OrthographicCamera',
|
||||||
'PerspectiveCamera',
|
'PerspectiveCamera',
|
||||||
|
'Raycaster',
|
||||||
'Renderer',
|
'Renderer',
|
||||||
'Scene',
|
'Scene',
|
||||||
'Group',
|
'Group',
|
||||||
|
Loading…
Reference in New Issue
Block a user