mirror of
https://github.com/troisjs/trois.git
synced 2024-11-23 20:02:32 +08:00
wip
This commit is contained in:
parent
154fd7439c
commit
d2006b1f2c
@ -7,6 +7,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue';
|
||||||
import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';
|
import { DoubleSide, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';
|
||||||
import Object3D from '../../core/Object3D.js';
|
import Object3D from '../../core/Object3D';
|
||||||
import { bindProps } from '../../tools';
|
import { bindProps } from '../../tools';
|
||||||
import LiquidEffect from './LiquidEffect.js';
|
import LiquidEffect from './LiquidEffect.js';
|
||||||
|
|
||||||
@ -17,9 +17,9 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.liquidEffect = new LiquidEffect(this.three.renderer);
|
this.liquidEffect = new LiquidEffect(this.three.renderer);
|
||||||
this.rendererComponent.onMounted(() => {
|
this.renderer.onMounted(() => {
|
||||||
this.liquidEffect.renderer = this.rendererComponent.renderer;
|
this.liquidEffect.renderer = this.renderer.renderer;
|
||||||
this.rendererComponent.onBeforeRender(this.update);
|
this.renderer.onBeforeRender(this.update);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.material = new MeshStandardMaterial({ color: this.color, side: DoubleSide, metalness: this.metalness, roughness: this.roughness,
|
this.material = new MeshStandardMaterial({ color: this.color, side: DoubleSide, metalness: this.metalness, roughness: this.roughness,
|
||||||
@ -44,7 +44,7 @@ export default defineComponent({
|
|||||||
this.initObject3D(this.mesh);
|
this.initObject3D(this.mesh);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.update);
|
this.renderer.offBeforeRender(this.update);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
update() {
|
update() {
|
||||||
|
@ -21,11 +21,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initGem();
|
this.initGem();
|
||||||
if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT);
|
if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT);
|
||||||
else this.rendererComponent.onMounted(this.updateCubeRT);
|
else this.renderer.onMounted(this.updateCubeRT);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateCubeRT);
|
this.renderer.offBeforeRender(this.updateCubeRT);
|
||||||
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
||||||
if (this.meshBack) this.removeFromParent(this.meshBack);
|
if (this.meshBack) this.removeFromParent(this.meshBack);
|
||||||
if (this.materialBack) this.materialBack.dispose();
|
if (this.materialBack) this.materialBack.dispose();
|
||||||
|
@ -17,11 +17,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initMirrorMesh();
|
this.initMirrorMesh();
|
||||||
if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT);
|
if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT);
|
||||||
else this.rendererComponent.onMounted(this.updateCubeRT);
|
else this.renderer.onMounted(this.updateCubeRT);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateCubeRT);
|
this.renderer.offBeforeRender(this.updateCubeRT);
|
||||||
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -20,11 +20,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initMirrorMesh();
|
this.initMirrorMesh();
|
||||||
if (this.autoUpdate) this.rendererComponent.onBeforeRender(this.updateCubeRT);
|
if (this.autoUpdate) this.renderer.onBeforeRender(this.updateCubeRT);
|
||||||
else this.rendererComponent.onMounted(this.updateCubeRT);
|
else this.renderer.onMounted(this.updateCubeRT);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateCubeRT);
|
this.renderer.offBeforeRender(this.updateCubeRT);
|
||||||
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
if (this.cubeCamera) this.removeFromParent(this.cubeCamera);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -5,7 +5,7 @@ export default {
|
|||||||
noSetup: { type: Boolean, default: false },
|
noSetup: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
emits: ['created'],
|
emits: ['created'],
|
||||||
inject: ['rendererComponent'],
|
inject: ['renderer'],
|
||||||
setup({ noSetup }) {
|
setup({ noSetup }) {
|
||||||
const stats = new Stats();
|
const stats = new Stats();
|
||||||
if (!noSetup) {
|
if (!noSetup) {
|
||||||
@ -16,8 +16,8 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.noSetup) {
|
if (!this.noSetup) {
|
||||||
this.rendererComponent.onBeforeRender(this.begin);
|
this.renderer.onBeforeRender(this.begin);
|
||||||
this.rendererComponent.onAfterRender(this.end);
|
this.renderer.onAfterRender(this.end);
|
||||||
}
|
}
|
||||||
this.$emit('created', { stats: this.stats });
|
this.$emit('created', { stats: this.stats });
|
||||||
},
|
},
|
||||||
@ -37,8 +37,8 @@ export default {
|
|||||||
if (this.stats && this.stats.dom) {
|
if (this.stats && this.stats.dom) {
|
||||||
this.stats.dom.parentElement.removeChild(this.stats.dom);
|
this.stats.dom.parentElement.removeChild(this.stats.dom);
|
||||||
}
|
}
|
||||||
this.rendererComponent.offBeforeRender(this.begin);
|
this.renderer.offBeforeRender(this.begin);
|
||||||
this.rendererComponent.offAfterRender(this.end);
|
this.renderer.offAfterRender(this.end);
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
return this.$slots.default ? this.$slots.default() : [];
|
return this.$slots.default ? this.$slots.default() : [];
|
||||||
|
@ -29,10 +29,10 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.rendererComponent.onBeforeRender(this.updateTime);
|
this.renderer.onBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateTime);
|
this.renderer.offBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
createGeometry() {
|
createGeometry() {
|
||||||
|
@ -30,10 +30,10 @@ export default defineComponent({
|
|||||||
watch(() => this.displacementScale, (value) => { this.material.displacementScale = value; });
|
watch(() => this.displacementScale, (value) => { this.material.displacementScale = value; });
|
||||||
|
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.rendererComponent.onBeforeRender(this.update);
|
this.renderer.onBeforeRender(this.update);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.update);
|
this.renderer.offBeforeRender(this.update);
|
||||||
this.fsQuad.dispose();
|
this.fsQuad.dispose();
|
||||||
this.dispRT.dispose();
|
this.dispRT.dispose();
|
||||||
this.dispMat.dispose();
|
this.dispMat.dispose();
|
||||||
|
@ -28,10 +28,10 @@ export default defineComponent({
|
|||||||
this.updateMaterial();
|
this.updateMaterial();
|
||||||
|
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.rendererComponent.onBeforeRender(this.updateTime);
|
this.renderer.onBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateTime);
|
this.renderer.offBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateMaterial() {
|
updateMaterial() {
|
||||||
|
@ -25,10 +25,10 @@ export default defineComponent({
|
|||||||
this.updateMaterial();
|
this.updateMaterial();
|
||||||
|
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.rendererComponent.onBeforeRender(this.updateTime);
|
this.renderer.onBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.updateTime);
|
this.renderer.offBeforeRender(this.updateTime);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateMaterial() {
|
updateMaterial() {
|
||||||
|
@ -3,7 +3,7 @@ import useCannon from './useCannon.js';
|
|||||||
// import { bindProp } from '../../tools';
|
// import { bindProp } from '../../tools';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inject: ['three', 'scene', 'rendererComponent'],
|
inject: ['three', 'scene', 'renderer'],
|
||||||
props: {
|
props: {
|
||||||
gravity: { type: Object, default: () => ({ x: 0, y: 0, z: -9.82 }) },
|
gravity: { type: Object, default: () => ({ x: 0, y: 0, z: -9.82 }) },
|
||||||
broadphase: { type: String },
|
broadphase: { type: String },
|
||||||
@ -16,10 +16,10 @@ export default defineComponent({
|
|||||||
this.cannon = useCannon({ gravity: this.gravity, broadphase: this.broadphase });
|
this.cannon = useCannon({ gravity: this.gravity, broadphase: this.broadphase });
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.rendererComponent.onBeforeRender(this.step);
|
this.renderer.onBeforeRender(this.step);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.rendererComponent.offBeforeRender(this.step);
|
this.renderer.offBeforeRender(this.step);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
step() {
|
step() {
|
||||||
|
@ -11,7 +11,7 @@ import { defineComponent } from 'vue';
|
|||||||
import { Object3D } from 'three';
|
import { Object3D } from 'three';
|
||||||
import { gsap, Power4 } from 'gsap';
|
import { gsap, Power4 } from 'gsap';
|
||||||
|
|
||||||
import Camera from '../../core/PerspectiveCamera.js';
|
import Camera from '../../core/PerspectiveCamera';
|
||||||
import Renderer from '../../core/Renderer.js';
|
import Renderer from '../../core/Renderer.js';
|
||||||
import Scene from '../../core/Scene.js';
|
import Scene from '../../core/Scene.js';
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import { defineComponent } from 'vue';
|
|||||||
import { Vector2 } from 'three';
|
import { Vector2 } from 'three';
|
||||||
import { gsap, Power4 } from 'gsap';
|
import { gsap, Power4 } from 'gsap';
|
||||||
|
|
||||||
import OrthographicCamera from '../../core/OrthographicCamera.js';
|
import OrthographicCamera from '../../core/OrthographicCamera';
|
||||||
import Renderer from '../../core/Renderer.js';
|
import Renderer from '../../core/Renderer.js';
|
||||||
import Scene from '../../core/Scene.js';
|
import Scene from '../../core/Scene.js';
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
||||||
import Camera from '../../core/PerspectiveCamera.js';
|
import Camera from '../../core/PerspectiveCamera';
|
||||||
import Renderer from '../../core/Renderer.js';
|
import Renderer from '../../core/Renderer.js';
|
||||||
import Scene from '../../core/Scene.js';
|
import Scene from '../../core/Scene.js';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue'
|
||||||
// import Object3D from '../core/Object3D.js';
|
// import Object3D from '../core/Object3D';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
// TODO: eventually extend Object3D, for now: error 'injection "scene" not found'
|
// TODO: eventually extend Object3D, for now: error 'injection "scene" not found'
|
||||||
@ -7,6 +7,6 @@ export default defineComponent({
|
|||||||
// extends: Object3D,
|
// extends: Object3D,
|
||||||
inject: ['three'],
|
inject: ['three'],
|
||||||
render() {
|
render() {
|
||||||
return this.$slots.default ? this.$slots.default() : [];
|
return this.$slots.default ? this.$slots.default() : []
|
||||||
},
|
},
|
||||||
});
|
})
|
@ -1,13 +0,0 @@
|
|||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Group } from 'three';
|
|
||||||
import Object3D from './Object3D.js';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Group',
|
|
||||||
extends: Object3D,
|
|
||||||
created() {
|
|
||||||
this.group = new Group();
|
|
||||||
this.initObject3D(this.group);
|
|
||||||
},
|
|
||||||
__hmrId: 'Group',
|
|
||||||
});
|
|
17
src/core/Group.ts
Normal file
17
src/core/Group.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { Group } from 'three'
|
||||||
|
import Object3D from './Object3D'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Group',
|
||||||
|
extends: Object3D,
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
group: new Group(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initObject3D(this.group)
|
||||||
|
},
|
||||||
|
__hmrId: 'Group',
|
||||||
|
})
|
@ -1,70 +0,0 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
|
||||||
import { bindProp } from '../tools';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Object3D',
|
|
||||||
inject: ['three', 'scene', 'rendererComponent'],
|
|
||||||
emits: ['created', 'ready'],
|
|
||||||
props: {
|
|
||||||
position: { 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 } },
|
|
||||||
lookAt: { type: Object, default: null },
|
|
||||||
autoRemove: { type: Boolean, default: true },
|
|
||||||
userData: { type: Object, default: () => ({}) },
|
|
||||||
},
|
|
||||||
// can't use setup because it will not be used in sub components
|
|
||||||
// setup() {},
|
|
||||||
unmounted() {
|
|
||||||
if (this.autoRemove) this.removeFromParent();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initObject3D(o3d) {
|
|
||||||
this.o3d = o3d;
|
|
||||||
this.o3d.userData = this.userData;
|
|
||||||
this.$emit('created', this.o3d);
|
|
||||||
|
|
||||||
bindProp(this, 'position', this.o3d);
|
|
||||||
bindProp(this, 'rotation', this.o3d);
|
|
||||||
bindProp(this, 'scale', this.o3d);
|
|
||||||
|
|
||||||
// TODO : fix lookat.x
|
|
||||||
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 });
|
|
||||||
|
|
||||||
this._parent = this.getParent();
|
|
||||||
if (this.addToParent()) this.$emit('ready', this);
|
|
||||||
else console.error('Missing parent (Scene, Group...)');
|
|
||||||
},
|
|
||||||
getParent() {
|
|
||||||
let parent = this.$parent;
|
|
||||||
while (parent) {
|
|
||||||
if (parent.add) return parent;
|
|
||||||
parent = parent.$parent;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
addToParent(o) {
|
|
||||||
const o3d = o || this.o3d;
|
|
||||||
if (this._parent) {
|
|
||||||
this._parent.add(o3d);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
removeFromParent(o) {
|
|
||||||
const o3d = o || this.o3d;
|
|
||||||
if (this._parent) {
|
|
||||||
this._parent.remove(o3d);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
add(o) { this.o3d.add(o); },
|
|
||||||
remove(o) { this.o3d.remove(o); },
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
return this.$slots.default ? this.$slots.default() : [];
|
|
||||||
},
|
|
||||||
__hmrId: 'Object3D',
|
|
||||||
});
|
|
71
src/core/Object3D.ts
Normal file
71
src/core/Object3D.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { Object3D } from 'three'
|
||||||
|
import { defineComponent, watch } from 'vue'
|
||||||
|
import { bindProp } from '../tools'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Object3D',
|
||||||
|
inject: ['three', 'scene', 'renderer'],
|
||||||
|
emits: ['created', 'ready'],
|
||||||
|
props: {
|
||||||
|
position: { 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 }) },
|
||||||
|
lookAt: { type: Object, default: null },
|
||||||
|
autoRemove: { type: Boolean, default: true },
|
||||||
|
userData: { type: Object, default: () => ({}) },
|
||||||
|
},
|
||||||
|
// can't use setup because it will not be used in sub components
|
||||||
|
// setup() {},
|
||||||
|
unmounted() {
|
||||||
|
if (this.autoRemove) this.removeFromParent()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initObject3D(o3d: Object3D) {
|
||||||
|
this.o3d = o3d
|
||||||
|
this.o3d.userData = this.userData
|
||||||
|
this.$emit('created', this.o3d)
|
||||||
|
|
||||||
|
bindProp(this, 'position', this.o3d)
|
||||||
|
bindProp(this, 'rotation', this.o3d)
|
||||||
|
bindProp(this, 'scale', this.o3d)
|
||||||
|
|
||||||
|
// TODO : fix lookat.x
|
||||||
|
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 })
|
||||||
|
|
||||||
|
this._parent = this.getParent()
|
||||||
|
if (this.addToParent()) this.$emit('ready', this)
|
||||||
|
else console.error('Missing parent (Scene, Group...)')
|
||||||
|
},
|
||||||
|
getParent() {
|
||||||
|
let parent = this.$parent
|
||||||
|
while (parent) {
|
||||||
|
if (parent.add) return parent
|
||||||
|
parent = parent.$parent
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
addToParent(o) {
|
||||||
|
const o3d = o || this.o3d
|
||||||
|
if (this._parent) {
|
||||||
|
this._parent.add(o3d)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
removeFromParent(o) {
|
||||||
|
const o3d = o || this.o3d
|
||||||
|
if (this._parent) {
|
||||||
|
this._parent.remove(o3d)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
add(o) { this.o3d.add(o); },
|
||||||
|
remove(o) { this.o3d.remove(o); },
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return this.$slots.default ? this.$slots.default() : []
|
||||||
|
},
|
||||||
|
__hmrId: 'Object3D',
|
||||||
|
})
|
@ -1,7 +1,7 @@
|
|||||||
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.js';
|
import Camera from './Camera';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Camera,
|
extends: Camera,
|
@ -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.js';
|
import Camera from './Camera';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Camera,
|
extends: Camera,
|
@ -3,7 +3,7 @@ import usePointer from './usePointer';
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Raycaster',
|
name: 'Raycaster',
|
||||||
inject: ['three', 'rendererComponent'],
|
inject: ['three', 'renderer'],
|
||||||
props: {
|
props: {
|
||||||
onPointerEnter: { type: Function, default: () => {} },
|
onPointerEnter: { type: Function, default: () => {} },
|
||||||
onPointerOver: { type: Function, default: () => {} },
|
onPointerOver: { type: Function, default: () => {} },
|
||||||
@ -13,7 +13,7 @@ export default defineComponent({
|
|||||||
intersectMode: { type: String, default: 'move' },
|
intersectMode: { type: String, default: 'move' },
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.rendererComponent.onMounted(() => {
|
this.renderer.onMounted(() => {
|
||||||
this.pointer = usePointer({
|
this.pointer = usePointer({
|
||||||
camera: this.three.camera,
|
camera: this.three.camera,
|
||||||
domElement: this.three.renderer.domElement,
|
domElement: this.three.renderer.domElement,
|
||||||
@ -27,14 +27,14 @@ export default defineComponent({
|
|||||||
this.pointer.addListeners();
|
this.pointer.addListeners();
|
||||||
|
|
||||||
if (this.intersectMode === 'frame') {
|
if (this.intersectMode === 'frame') {
|
||||||
this.rendererComponent.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.rendererComponent.offBeforeRender(this.pointer.intersect);
|
this.renderer.offBeforeRender(this.pointer.intersect);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
@ -1,105 +0,0 @@
|
|||||||
import { defineComponent, h } from 'vue';
|
|
||||||
import useThree from './useThree';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Renderer',
|
|
||||||
props: {
|
|
||||||
antialias: Boolean,
|
|
||||||
alpha: Boolean,
|
|
||||||
autoClear: { type: Boolean, default: true },
|
|
||||||
orbitCtrl: { type: [Boolean, Object], default: false },
|
|
||||||
pointer: { type: [Boolean, Object], default: false },
|
|
||||||
resize: { type: [Boolean, String], default: false },
|
|
||||||
shadow: Boolean,
|
|
||||||
width: String,
|
|
||||||
height: String,
|
|
||||||
xr: Boolean,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
three: useThree(),
|
|
||||||
raf: true,
|
|
||||||
onMountedCallbacks: [],
|
|
||||||
beforeRenderCallbacks: [],
|
|
||||||
afterRenderCallbacks: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
provide() {
|
|
||||||
return {
|
|
||||||
three: this.three,
|
|
||||||
// renderer: this.three.renderer,
|
|
||||||
rendererComponent: this,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const params = {
|
|
||||||
canvas: this.$el,
|
|
||||||
antialias: this.antialias,
|
|
||||||
alpha: this.alpha,
|
|
||||||
autoClear: this.autoClear,
|
|
||||||
orbit_ctrl: this.orbitCtrl,
|
|
||||||
pointer: this.pointer,
|
|
||||||
resize: this.resize,
|
|
||||||
width: this.width,
|
|
||||||
height: this.height,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.three.init(params)) {
|
|
||||||
this.renderer = this.three.renderer;
|
|
||||||
this.renderer.shadowMap.enabled = this.shadow;
|
|
||||||
|
|
||||||
this._render = this.three.composer ? this.three.renderC : this.three.render;
|
|
||||||
|
|
||||||
if (this.xr) {
|
|
||||||
this.renderer.xr.enabled = true;
|
|
||||||
this.renderer.setAnimationLoop(this.render);
|
|
||||||
} else {
|
|
||||||
requestAnimationFrame(this.renderLoop);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onMountedCallbacks.forEach(c => c());
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
this.beforeRenderCallbacks = [];
|
|
||||||
this.afterRenderCallbacks = [];
|
|
||||||
this.raf = false;
|
|
||||||
this.three.dispose();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onMounted(cb) {
|
|
||||||
this.onMountedCallbacks.push(cb);
|
|
||||||
},
|
|
||||||
onBeforeRender(cb) {
|
|
||||||
this.beforeRenderCallbacks.push(cb);
|
|
||||||
},
|
|
||||||
offBeforeRender(cb) {
|
|
||||||
this.beforeRenderCallbacks = this.beforeRenderCallbacks.filter(c => c !== cb);
|
|
||||||
},
|
|
||||||
onAfterRender(cb) {
|
|
||||||
this.afterRenderCallbacks.push(cb);
|
|
||||||
},
|
|
||||||
offAfterRender(cb) {
|
|
||||||
this.afterRenderCallbacks = this.afterRenderCallbacks.filter(c => c !== cb);
|
|
||||||
},
|
|
||||||
onAfterResize(cb) {
|
|
||||||
this.three.onAfterResize(cb);
|
|
||||||
},
|
|
||||||
offAfterResize(cb) {
|
|
||||||
this.three.offAfterResize(cb);
|
|
||||||
},
|
|
||||||
render(time) {
|
|
||||||
this.beforeRenderCallbacks.forEach(c => c({ time }));
|
|
||||||
this._render();
|
|
||||||
this.afterRenderCallbacks.forEach(c => c({ time }));
|
|
||||||
},
|
|
||||||
renderLoop(time) {
|
|
||||||
if (this.raf) requestAnimationFrame(this.renderLoop);
|
|
||||||
this.render(time);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
return h('canvas', {}, this.$slots.default());
|
|
||||||
},
|
|
||||||
__hmrId: 'Renderer',
|
|
||||||
});
|
|
113
src/core/Renderer.ts
Normal file
113
src/core/Renderer.ts
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import { WebGLRenderer } from 'three'
|
||||||
|
import { defineComponent, h } from 'vue'
|
||||||
|
import useThree, { ThreeConfigInterface } from './useThree'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Renderer',
|
||||||
|
props: {
|
||||||
|
antialias: Boolean,
|
||||||
|
alpha: Boolean,
|
||||||
|
autoClear: { type: Boolean, default: true },
|
||||||
|
orbitCtrl: { type: [Boolean, Object], default: false },
|
||||||
|
pointer: { type: [Boolean, Object], default: false },
|
||||||
|
resize: { type: [Boolean, String], default: false },
|
||||||
|
shadow: Boolean,
|
||||||
|
width: String,
|
||||||
|
height: String,
|
||||||
|
xr: Boolean,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const renderer: null | WebGLRenderer = null
|
||||||
|
|
||||||
|
const onMountedCallbacks: {(): void}[] = []
|
||||||
|
const beforeRenderCallbacks: {(): void}[] = []
|
||||||
|
const afterRenderCallbacks: {(): void}[] = []
|
||||||
|
|
||||||
|
return {
|
||||||
|
three: useThree(),
|
||||||
|
renderer,
|
||||||
|
raf: true,
|
||||||
|
onMountedCallbacks,
|
||||||
|
beforeRenderCallbacks,
|
||||||
|
afterRenderCallbacks,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
renderer: this,
|
||||||
|
three: this.three,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const params: ThreeConfigInterface = {
|
||||||
|
canvas: this.$el,
|
||||||
|
antialias: this.antialias,
|
||||||
|
alpha: this.alpha,
|
||||||
|
autoClear: this.autoClear,
|
||||||
|
orbitCtrl: this.orbitCtrl,
|
||||||
|
pointer: this.pointer,
|
||||||
|
resize: this.resize,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.width) params.width = parseInt(this.width)
|
||||||
|
if (this.height) params.height = parseInt(this.height)
|
||||||
|
|
||||||
|
if (this.three.init(params)) {
|
||||||
|
this.renderer = this.three.renderer
|
||||||
|
this.renderer.shadowMap.enabled = this.shadow
|
||||||
|
|
||||||
|
this._render = this.three.composer ? this.three.renderC : this.three.render
|
||||||
|
|
||||||
|
if (this.xr) {
|
||||||
|
this.renderer.xr.enabled = true
|
||||||
|
this.renderer.setAnimationLoop(this.render)
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(this.renderLoop)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.onMountedCallbacks.forEach(c => c())
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
this.beforeRenderCallbacks = []
|
||||||
|
this.afterRenderCallbacks = []
|
||||||
|
this.raf = false
|
||||||
|
this.three.dispose()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onMounted(cb: {(): void}) {
|
||||||
|
this.onMountedCallbacks.push(cb)
|
||||||
|
},
|
||||||
|
onBeforeRender(cb: {(): void}) {
|
||||||
|
this.beforeRenderCallbacks.push(cb)
|
||||||
|
},
|
||||||
|
offBeforeRender(cb: {(): void}) {
|
||||||
|
this.beforeRenderCallbacks = this.beforeRenderCallbacks.filter(c => c !== cb)
|
||||||
|
},
|
||||||
|
onAfterRender(cb: {(): void}) {
|
||||||
|
this.afterRenderCallbacks.push(cb)
|
||||||
|
},
|
||||||
|
offAfterRender(cb: {(): void}) {
|
||||||
|
this.afterRenderCallbacks = this.afterRenderCallbacks.filter(c => c !== cb)
|
||||||
|
},
|
||||||
|
onAfterResize(cb: {(): void}) {
|
||||||
|
this.three.onAfterResize(cb)
|
||||||
|
},
|
||||||
|
offAfterResize(cb: {(): void}) {
|
||||||
|
this.three.offAfterResize(cb)
|
||||||
|
},
|
||||||
|
render(time: number) {
|
||||||
|
this.beforeRenderCallbacks.forEach(c => c({ time }))
|
||||||
|
this._render()
|
||||||
|
this.afterRenderCallbacks.forEach(c => c({ time }))
|
||||||
|
},
|
||||||
|
renderLoop(time: number) {
|
||||||
|
if (this.raf) requestAnimationFrame(this.renderLoop)
|
||||||
|
this.render(time)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return h('canvas', {}, this.$slots.default ? this.$slots.default() : [])
|
||||||
|
},
|
||||||
|
__hmrId: 'Renderer',
|
||||||
|
})
|
@ -1,8 +1,8 @@
|
|||||||
export { default as Renderer } from './Renderer.js';
|
export { default as Renderer } from './Renderer';
|
||||||
export { default as OrthographicCamera } from './OrthographicCamera.js';
|
export { default as OrthographicCamera } from './OrthographicCamera';
|
||||||
export { default as PerspectiveCamera } from './PerspectiveCamera.js';
|
export { default as PerspectiveCamera } from './PerspectiveCamera';
|
||||||
export { default as Camera } from './PerspectiveCamera.js';
|
export { default as Camera } from './PerspectiveCamera';
|
||||||
export { default as Group } from './Group.js';
|
export { default as Group } from './Group';
|
||||||
export { default as Scene } from './Scene.js';
|
export { default as Scene } from './Scene';
|
||||||
export { default as Object3D } from './Object3D.js';
|
export { default as Object3D } from './Object3D';
|
||||||
export { default as Raycaster } from './Raycaster.js';
|
export { default as Raycaster } from './Raycaster';
|
||||||
|
@ -4,16 +4,16 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
|||||||
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
|
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
|
||||||
import usePointer, { IntersectObject, PointerConfigInterface, PointerInterface } from './usePointer'
|
import usePointer, { IntersectObject, PointerConfigInterface, PointerInterface } from './usePointer'
|
||||||
|
|
||||||
export interface ConfigInterface {
|
export interface ThreeConfigInterface {
|
||||||
canvas?: HTMLCanvasElement
|
canvas?: HTMLCanvasElement
|
||||||
antialias: boolean
|
antialias: boolean
|
||||||
alpha: boolean
|
alpha: boolean
|
||||||
autoClear: boolean
|
autoClear: boolean
|
||||||
orbitCtrl: boolean | Record<string, unknown>
|
orbitCtrl: boolean | Record<string, unknown>
|
||||||
pointer: boolean | PointerConfigInterface
|
pointer: boolean | PointerConfigInterface
|
||||||
resize: boolean | 'window'
|
resize: boolean | string
|
||||||
width: number
|
width?: number
|
||||||
height: number
|
height?: number
|
||||||
[index:string]: any
|
[index:string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export interface SizeInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ThreeInterface {
|
export interface ThreeInterface {
|
||||||
conf: ConfigInterface
|
conf: ThreeConfigInterface
|
||||||
renderer?: WebGLRenderer
|
renderer?: WebGLRenderer
|
||||||
camera?: Camera
|
camera?: Camera
|
||||||
cameraCtrl?: OrbitControls
|
cameraCtrl?: OrbitControls
|
||||||
@ -34,7 +34,7 @@ export interface ThreeInterface {
|
|||||||
pointer?: PointerInterface
|
pointer?: PointerInterface
|
||||||
size: SizeInterface
|
size: SizeInterface
|
||||||
composer?: EffectComposer
|
composer?: EffectComposer
|
||||||
init(config: ConfigInterface): boolean
|
init(config: ThreeConfigInterface): boolean
|
||||||
dispose(): void
|
dispose(): void
|
||||||
render(): void
|
render(): void
|
||||||
renderC(): void
|
renderC(): void
|
||||||
@ -51,7 +51,7 @@ export interface ThreeInterface {
|
|||||||
*/
|
*/
|
||||||
export default function useThree(): ThreeInterface {
|
export default function useThree(): ThreeInterface {
|
||||||
// default conf
|
// default conf
|
||||||
const conf: ConfigInterface = {
|
const conf: ThreeConfigInterface = {
|
||||||
antialias: true,
|
antialias: true,
|
||||||
alpha: false,
|
alpha: false,
|
||||||
autoClear: true,
|
autoClear: true,
|
||||||
@ -98,7 +98,7 @@ export default function useThree(): ThreeInterface {
|
|||||||
/**
|
/**
|
||||||
* init three
|
* init three
|
||||||
*/
|
*/
|
||||||
function init(params: ConfigInterface) {
|
function init(params: ThreeConfigInterface) {
|
||||||
if (params) {
|
if (params) {
|
||||||
Object.entries(params).forEach(([key, value]) => {
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
conf[key] = value
|
conf[key] = value
|
||||||
@ -122,7 +122,7 @@ export default function useThree(): ThreeInterface {
|
|||||||
onResize()
|
onResize()
|
||||||
window.addEventListener('resize', onResize)
|
window.addEventListener('resize', onResize)
|
||||||
} else {
|
} else {
|
||||||
setSize(conf.width, conf.height)
|
setSize(conf.width!, conf.height!)
|
||||||
}
|
}
|
||||||
|
|
||||||
initPointer()
|
initPointer()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D';
|
||||||
import { bindProp, setFromProp } from '../tools';
|
import { bindProp, setFromProp } from '../tools';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import { createApp } from 'vue';
|
|
||||||
import { TroisJSVuePlugin } from './plugin.js';
|
|
||||||
import App from './App.vue';
|
|
||||||
|
|
||||||
const app = createApp(App);
|
|
||||||
app.use(TroisJSVuePlugin);
|
|
||||||
app.mount('#app');
|
|
7
src/main.ts
Normal file
7
src/main.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import { TroisJSVuePlugin } from './plugin'
|
||||||
|
import App from './App.vue'
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
app.use(TroisJSVuePlugin)
|
||||||
|
app.mount('#app')
|
@ -1,6 +1,6 @@
|
|||||||
import { defineComponent, watch } from 'vue';
|
import { defineComponent, watch } from 'vue';
|
||||||
import { Mesh as TMesh } from 'three';
|
import { Mesh as TMesh } from 'three';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D';
|
||||||
import { bindProp } from '../tools';
|
import { bindProp } from '../tools';
|
||||||
|
|
||||||
export const pointerProps = {
|
export const pointerProps = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { Sprite, SpriteMaterial, TextureLoader } from 'three';
|
import { Sprite, SpriteMaterial, TextureLoader } from 'three';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Object3D,
|
extends: Object3D,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import Object3D from '../core/Object3D.js';
|
import Object3D from '../core/Object3D';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
extends: Object3D,
|
extends: Object3D,
|
||||||
|
81
src/tools.js
81
src/tools.js
@ -1,81 +0,0 @@
|
|||||||
import { toRef, watch } from 'vue';
|
|
||||||
|
|
||||||
export function setFromProp(o, prop) {
|
|
||||||
if (prop instanceof Object) {
|
|
||||||
Object.entries(prop).forEach(([key, value]) => {
|
|
||||||
o[key] = value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function bindProps(src, props, dst) {
|
|
||||||
props.forEach(prop => {
|
|
||||||
bindProp(src, prop, dst);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export function bindProp(src, srcProp, dst, dstProp) {
|
|
||||||
if (!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 });
|
|
||||||
} else {
|
|
||||||
if (ref.value) dst[dstProp] = src[srcProp];
|
|
||||||
watch(ref, (value) => { dst[dstProp] = value; });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function propsValues(props, exclude) {
|
|
||||||
const values = {};
|
|
||||||
Object.entries(props).forEach(([key, value]) => {
|
|
||||||
if (!exclude || (exclude && !exclude.includes(key))) {
|
|
||||||
values[key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return values;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function lerp(value1, value2, amount) {
|
|
||||||
amount = amount < 0 ? 0 : amount;
|
|
||||||
amount = amount > 1 ? 1 : amount;
|
|
||||||
return value1 + (value2 - value1) * amount;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function lerpv2(v1, v2, amount) {
|
|
||||||
v1.x = lerp(v1.x, v2.x, amount);
|
|
||||||
v1.y = lerp(v1.y, v2.y, amount);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function lerpv3(v1, v2, amount) {
|
|
||||||
v1.x = lerp(v1.x, v2.x, amount);
|
|
||||||
v1.y = lerp(v1.y, v2.y, amount);
|
|
||||||
v1.z = lerp(v1.z, v2.z, amount);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function limit(val, min, max) {
|
|
||||||
return val < min ? min : (val > max ? max : val);
|
|
||||||
};
|
|
||||||
|
|
||||||
// from https://github.com/pmndrs/drei/blob/master/src/useMatcapTexture.tsx
|
|
||||||
const MATCAP_ROOT = 'https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d';
|
|
||||||
|
|
||||||
export function getMatcapUrl(hash, format = 1024) {
|
|
||||||
const fileName = `${hash}${getMatcapFormatString(format)}.png`;
|
|
||||||
return `${MATCAP_ROOT}/${format}/${fileName}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getMatcapFormatString(format) {
|
|
||||||
switch (format) {
|
|
||||||
case 64:
|
|
||||||
return '-64px';
|
|
||||||
case 128:
|
|
||||||
return '-128px';
|
|
||||||
case 256:
|
|
||||||
return '-256px';
|
|
||||||
case 512:
|
|
||||||
return '-512px';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
84
src/tools.ts
Normal file
84
src/tools.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { Vector2, Vector3 } from 'three'
|
||||||
|
import { toRef, watch } from 'vue'
|
||||||
|
|
||||||
|
export function setFromProp(o: Record<string, unknown>, prop: Record<string, unknown>): void {
|
||||||
|
if (prop instanceof Object) {
|
||||||
|
Object.entries(prop).forEach(([key, value]) => {
|
||||||
|
o[key] = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bindProps(src: any, props: string[], dst: string): void {
|
||||||
|
props.forEach(prop => {
|
||||||
|
bindProp(src, prop, dst, prop)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bindProp(src: any, srcProp: string, dst: any, dstProp: string): void {
|
||||||
|
if (!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 })
|
||||||
|
} else {
|
||||||
|
if (ref.value) dst[dstProp] = src[srcProp]
|
||||||
|
watch(ref, (value) => { dst[dstProp] = value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function propsValues(props: Record<string, unknown>, exclude: string[]): Record<string, unknown> {
|
||||||
|
const values: Record<string, unknown> = {}
|
||||||
|
Object.entries(props).forEach(([key, value]) => {
|
||||||
|
if (!exclude || (exclude && !exclude.includes(key))) {
|
||||||
|
values[key] = value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lerp(value1: number, value2: number, amount: number): number {
|
||||||
|
amount = amount < 0 ? 0 : amount
|
||||||
|
amount = amount > 1 ? 1 : amount
|
||||||
|
return value1 + (value2 - value1) * amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : remove
|
||||||
|
export function lerpv2(v1: Vector2, v2: Vector2, amount: number): void {
|
||||||
|
v1.x = lerp(v1.x, v2.x, amount)
|
||||||
|
v1.y = lerp(v1.y, v2.y, amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : remove
|
||||||
|
export function lerpv3(v1: Vector3, v2: Vector3, amount: number): void {
|
||||||
|
v1.x = lerp(v1.x, v2.x, amount)
|
||||||
|
v1.y = lerp(v1.y, v2.y, amount)
|
||||||
|
v1.z = lerp(v1.z, v2.z, amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function limit(val: number, min: number, max: number): number {
|
||||||
|
return val < min ? min : (val > max ? max : val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://github.com/pmndrs/drei/blob/master/src/useMatcapTexture.tsx
|
||||||
|
const MATCAP_ROOT = 'https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d'
|
||||||
|
|
||||||
|
export function getMatcapUrl(hash: string, format = 1024): string {
|
||||||
|
const fileName = `${hash}${getMatcapFormatString(format)}.png`
|
||||||
|
return `${MATCAP_ROOT}/${format}/${fileName}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMatcapFormatString(format: number) {
|
||||||
|
switch (format) {
|
||||||
|
case 64:
|
||||||
|
return '-64px'
|
||||||
|
case 128:
|
||||||
|
return '-128px'
|
||||||
|
case 256:
|
||||||
|
return '-256px'
|
||||||
|
case 512:
|
||||||
|
return '-512px'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user