diff --git a/src/core/Group.js b/src/core/Group.js index 42c6bc5..9b2ca7f 100644 --- a/src/core/Group.js +++ b/src/core/Group.js @@ -1,47 +1,11 @@ import { Group } from 'three'; -import { bindProp } from '../tools.js'; +import Object3D from './Object3D.js'; export default { - inject: { - three: 'three', - scene: 'scene', - group: { default: null }, - }, - props: { - position: Object, - rotation: Object, - scale: Object, - }, - provide() { - return { - group: this.group, - }; - }, + extends: Object3D, created() { - if (!this.$parent) { - console.error('Missing parent'); - } else if (!this.$parent.add || !this.$parent.remove) { - - } - - this.parent = this.group ? this.group : this.scene; - this.group = new Group(); - bindProp(this, 'position', this.group.position); - bindProp(this, 'rotation', this.group.rotation); - bindProp(this, 'scale', this.group.scale); - - this.parent.add(this.group); - }, - unmounted() { - if (this.$parent) this.$parent.remove(this.group); - }, - methods: { - add(o) { this.group.add(o); }, - remove(o) { this.group.remove(o); }, - }, - render() { - return this.$slots.default ? this.$slots.default() : []; + this.initObject3D(this.group); }, __hmrId: 'Group', }; diff --git a/src/core/Object3D.js b/src/core/Object3D.js new file mode 100644 index 0000000..b5cc213 --- /dev/null +++ b/src/core/Object3D.js @@ -0,0 +1,41 @@ +import { watch } from 'vue'; +import { bindProp } from '../tools.js'; + +export default { + inject: ['three', 'scene', 'rendererComponent'], + props: { + position: Object, + rotation: Object, + scale: Object, + castShadow: Boolean, + receiveShadow: Boolean, + loading: Boolean, + }, + // can't use setup because it will not be used in sub components + // setup() {}, + created() {}, + unmounted() { + if (this.$parent.remove) this.$parent.remove(this.o3d); + }, + methods: { + initObject3D(o3d) { + this.o3d = o3d; + + bindProp(this, 'position', this.o3d.position); + bindProp(this, 'rotation', this.o3d.rotation); + bindProp(this, 'scale', this.o3d.scale); + + ['castShadow', 'receiveShadow'].forEach(p => { + this.o3d[p] = this[p]; + watch(() => this[p], () => { this.o3d[p] = this[p]; }); + }); + + if (this.$parent.add) this.$parent.add(this.o3d); + }, + add(o) { this.o3d.add(o); }, + remove(o) { this.o3d.remove(o); }, + }, + render() { + return this.$slots.default ? this.$slots.default() : []; + }, +}; diff --git a/src/core/PerspectiveCamera.js b/src/core/PerspectiveCamera.js index be0f8f7..e77272c 100644 --- a/src/core/PerspectiveCamera.js +++ b/src/core/PerspectiveCamera.js @@ -26,7 +26,6 @@ export default { }); }); - // this.camera.updateProjectionMatrix(); this.three.camera = this.camera; }, render() { diff --git a/src/core/Scene.js b/src/core/Scene.js index ac41f4d..5562c28 100644 --- a/src/core/Scene.js +++ b/src/core/Scene.js @@ -28,9 +28,6 @@ export default { remove(o) { this.scene.remove(o); }, }, render() { - if (this.$slots.default) { - return this.$slots.default(); - } - return []; + return this.$slots.default ? this.$slots.default() : []; }, }; diff --git a/src/geometries/BoxGeometry.js b/src/geometries/BoxGeometry.js index 8aa8e9f..d0b9a75 100644 --- a/src/geometries/BoxGeometry.js +++ b/src/geometries/BoxGeometry.js @@ -1,4 +1,4 @@ -import { BoxBufferGeometry } from 'three'; +import { BoxGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -18,7 +18,7 @@ export default { if (this.size) { w = this.size; h = this.size; d = this.size; } - this.geometry = new BoxBufferGeometry(w, h, d, this.widthSegments, this.heightSegments, this.depthSegments); + this.geometry = new BoxGeometry(w, h, d, this.widthSegments, this.heightSegments, this.depthSegments); }, }, }; diff --git a/src/geometries/CircleGeometry.js b/src/geometries/CircleGeometry.js index edcf48a..784772a 100644 --- a/src/geometries/CircleGeometry.js +++ b/src/geometries/CircleGeometry.js @@ -1,4 +1,4 @@ -import { CircleBufferGeometry } from 'three'; +import { CircleGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -11,7 +11,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new CircleBufferGeometry(this.radius, this.segments, this.thetaStart, this.thetaLength); + this.geometry = new CircleGeometry(this.radius, this.segments, this.thetaStart, this.thetaLength); }, }, }; diff --git a/src/geometries/ConeGeometry.js b/src/geometries/ConeGeometry.js index 6e7da22..a4e451d 100644 --- a/src/geometries/ConeGeometry.js +++ b/src/geometries/ConeGeometry.js @@ -1,4 +1,4 @@ -import { ConeBufferGeometry } from 'three'; +import { ConeGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -14,7 +14,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new ConeBufferGeometry(this.radius, this.height, this.radialSegments, this.heightSegments, this.openEnded, this.thetaStart, this.thetaLength); + this.geometry = new ConeGeometry(this.radius, this.height, this.radialSegments, this.heightSegments, this.openEnded, this.thetaStart, this.thetaLength); }, }, }; diff --git a/src/geometries/CylinderGeometry.js b/src/geometries/CylinderGeometry.js index d8a7cf6..3be02c2 100644 --- a/src/geometries/CylinderGeometry.js +++ b/src/geometries/CylinderGeometry.js @@ -1,4 +1,4 @@ -import { CylinderBufferGeometry } from 'three'; +import { CylinderGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -15,7 +15,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new CylinderBufferGeometry(this.radiusTop, this.radiusBottom, this.height, this.radialSegments, this.heightSegments, this.openEnded, this.thetaStart, this.thetaLength); + this.geometry = new CylinderGeometry(this.radiusTop, this.radiusBottom, this.height, this.radialSegments, this.heightSegments, this.openEnded, this.thetaStart, this.thetaLength); }, }, }; diff --git a/src/geometries/DodecahedronGeometry.js b/src/geometries/DodecahedronGeometry.js index 00b2bb6..9343550 100644 --- a/src/geometries/DodecahedronGeometry.js +++ b/src/geometries/DodecahedronGeometry.js @@ -1,4 +1,4 @@ -import { DodecahedronBufferGeometry } from 'three'; +import { DodecahedronGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -9,7 +9,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new DodecahedronBufferGeometry(this.radius, this.detail); + this.geometry = new DodecahedronGeometry(this.radius, this.detail); }, }, }; diff --git a/src/geometries/Geometry.js b/src/geometries/Geometry.js index 39fdb20..055fb91 100644 --- a/src/geometries/Geometry.js +++ b/src/geometries/Geometry.js @@ -1,7 +1,6 @@ import { watch } from 'vue'; export default { - emits: ['ready'], inject: ['mesh'], props: { rotateX: Number, @@ -12,26 +11,20 @@ export default { if (!this.mesh) { console.error('Missing parent Mesh'); } + this.watchProps = []; Object.entries(this.$props).forEach(e => this.watchProps.push(e[0])); - }, - beforeMount() { + this.createGeometry(); this.rotateGeometry(); this.mesh.setGeometry(this.geometry); - }, - mounted() { + this.addWatchers(); }, unmounted() { this.geometry.dispose(); }, methods: { - rotateGeometry() { - if (this.rotateX) this.geometry.rotateX(this.rotateX); - if (this.rotateY) this.geometry.rotateY(this.rotateY); - if (this.rotateZ) this.geometry.rotateZ(this.rotateZ); - }, addWatchers() { this.watchProps.forEach(prop => { watch(() => this[prop], () => { @@ -39,6 +32,11 @@ export default { }); }); }, + rotateGeometry() { + if (this.rotateX) this.geometry.rotateX(this.rotateX); + if (this.rotateY) this.geometry.rotateY(this.rotateY); + if (this.rotateZ) this.geometry.rotateZ(this.rotateZ); + }, refreshGeometry() { const oldGeo = this.geometry; this.createGeometry(); @@ -47,7 +45,5 @@ export default { oldGeo.dispose(); }, }, - render() { - return []; - }, + render() { return []; }, }; diff --git a/src/geometries/IcosahedronGeometry.js b/src/geometries/IcosahedronGeometry.js index 4595356..d273eae 100644 --- a/src/geometries/IcosahedronGeometry.js +++ b/src/geometries/IcosahedronGeometry.js @@ -1,4 +1,4 @@ -import { IcosahedronBufferGeometry } from 'three'; +import { IcosahedronGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -9,7 +9,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new IcosahedronBufferGeometry(this.radius, this.detail); + this.geometry = new IcosahedronGeometry(this.radius, this.detail); }, }, }; diff --git a/src/geometries/LatheGeometry.js b/src/geometries/LatheGeometry.js index e52285d..def13d3 100644 --- a/src/geometries/LatheGeometry.js +++ b/src/geometries/LatheGeometry.js @@ -1,4 +1,4 @@ -import { LatheBufferGeometry } from 'three'; +import { LatheGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -11,7 +11,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new LatheBufferGeometry(this.points, this.segments, this.phiStart, this.phiLength); + this.geometry = new LatheGeometry(this.points, this.segments, this.phiStart, this.phiLength); }, }, }; diff --git a/src/geometries/OctahedronGeometry.js b/src/geometries/OctahedronGeometry.js index 3901efd..edf6413 100644 --- a/src/geometries/OctahedronGeometry.js +++ b/src/geometries/OctahedronGeometry.js @@ -1,4 +1,4 @@ -import { OctahedronBufferGeometry } from 'three'; +import { OctahedronGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -9,7 +9,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new OctahedronBufferGeometry(this.radius, this.detail); + this.geometry = new OctahedronGeometry(this.radius, this.detail); }, }, }; diff --git a/src/geometries/PolyhedronGeometry.js b/src/geometries/PolyhedronGeometry.js index d34ef25..8ecb1a5 100644 --- a/src/geometries/PolyhedronGeometry.js +++ b/src/geometries/PolyhedronGeometry.js @@ -1,4 +1,4 @@ -import { PolyhedronBufferGeometry } from 'three'; +import { PolyhedronGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -11,7 +11,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new PolyhedronBufferGeometry(this.vertices, this.indices, this.radius, this.detail); + this.geometry = new PolyhedronGeometry(this.vertices, this.indices, this.radius, this.detail); }, }, }; diff --git a/src/geometries/RingGeometry.js b/src/geometries/RingGeometry.js index 02cbcb7..40d52bb 100644 --- a/src/geometries/RingGeometry.js +++ b/src/geometries/RingGeometry.js @@ -1,4 +1,4 @@ -import { RingBufferGeometry } from 'three'; +import { RingGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -13,7 +13,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new RingBufferGeometry(this.innerRadius, this.outerRadius, this.thetaSegments, this.phiSegments, this.thetaStart, this.thetaLength); + this.geometry = new RingGeometry(this.innerRadius, this.outerRadius, this.thetaSegments, this.phiSegments, this.thetaStart, this.thetaLength); }, }, }; diff --git a/src/geometries/SphereGeometry.js b/src/geometries/SphereGeometry.js index eb1df04..1a15bad 100644 --- a/src/geometries/SphereGeometry.js +++ b/src/geometries/SphereGeometry.js @@ -1,4 +1,4 @@ -import { SphereBufferGeometry } from 'three'; +import { SphereGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -10,7 +10,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new SphereBufferGeometry(this.radius, this.widthSegments, this.heightSegments); + this.geometry = new SphereGeometry(this.radius, this.widthSegments, this.heightSegments); }, }, }; diff --git a/src/geometries/TetrahedronGeometry.js b/src/geometries/TetrahedronGeometry.js index 7f6b968..2705b45 100644 --- a/src/geometries/TetrahedronGeometry.js +++ b/src/geometries/TetrahedronGeometry.js @@ -1,4 +1,4 @@ -import { TetrahedronBufferGeometry } from 'three'; +import { TetrahedronGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -9,7 +9,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new TetrahedronBufferGeometry(this.radius, this.detail); + this.geometry = new TetrahedronGeometry(this.radius, this.detail); }, }, }; diff --git a/src/geometries/TorusGeometry.js b/src/geometries/TorusGeometry.js index 82be289..c1e6da3 100644 --- a/src/geometries/TorusGeometry.js +++ b/src/geometries/TorusGeometry.js @@ -1,4 +1,4 @@ -import { TorusBufferGeometry } from 'three'; +import { TorusGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -12,7 +12,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new TorusBufferGeometry(this.radius, this.tube, this.radialSegments, this.tubularSegments, this.arc); + this.geometry = new TorusGeometry(this.radius, this.tube, this.radialSegments, this.tubularSegments, this.arc); }, }, }; diff --git a/src/geometries/TorusKnotGeometry.js b/src/geometries/TorusKnotGeometry.js index 0c33ca2..0b04d64 100644 --- a/src/geometries/TorusKnotGeometry.js +++ b/src/geometries/TorusKnotGeometry.js @@ -1,4 +1,4 @@ -import { TorusKnotBufferGeometry } from 'three'; +import { TorusKnotGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -13,7 +13,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new TorusKnotBufferGeometry(this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q); + this.geometry = new TorusKnotGeometry(this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q); }, }, }; diff --git a/src/geometries/TubeGeometry.js b/src/geometries/TubeGeometry.js index 944c2c3..bab9c9b 100644 --- a/src/geometries/TubeGeometry.js +++ b/src/geometries/TubeGeometry.js @@ -1,4 +1,4 @@ -import { Curve, TubeBufferGeometry } from 'three'; +import { Curve, TubeGeometry } from 'three'; import Geometry from './Geometry.js'; export default { @@ -12,7 +12,7 @@ export default { }, methods: { createGeometry() { - this.geometry = new TubeBufferGeometry(this.path, this.tubularSegments, this.radius, this.radiusSegments, this.closed); + this.geometry = new TubeGeometry(this.path, this.tubularSegments, this.radius, this.radiusSegments, this.closed); }, }, }; diff --git a/src/lights/AmbientLight.js b/src/lights/AmbientLight.js index 982fa42..b424633 100644 --- a/src/lights/AmbientLight.js +++ b/src/lights/AmbientLight.js @@ -5,6 +5,7 @@ export default { extends: Light, created() { this.light = new AmbientLight(this.color, this.intensity); + this.initLight(); }, __hmrId: 'AmbientLight', }; diff --git a/src/lights/DirectionalLight.js b/src/lights/DirectionalLight.js index afe807f..13a1f99 100644 --- a/src/lights/DirectionalLight.js +++ b/src/lights/DirectionalLight.js @@ -8,6 +8,7 @@ export default { }, created() { this.light = new DirectionalLight(this.color, this.intensity); + this.initLight(); }, __hmrId: 'DirectionalLight', }; diff --git a/src/lights/Light.js b/src/lights/Light.js index 60374e0..7d86dd7 100644 --- a/src/lights/Light.js +++ b/src/lights/Light.js @@ -1,62 +1,47 @@ import { Color } from 'three'; import { watch } from 'vue'; -import { setFromProp } from '../tools.js'; -import { bindProp } from '../tools.js'; +import { bindProp, setFromProp } from '../tools.js'; export default { - inject: { - scene: 'scene', - group: { default: null }, - }, props: { - color: { - type: String, - default: '#ffffff', - }, - intensity: { - type: Number, - default: 1, - }, - castShadow: { - type: Boolean, - default: false, - }, - shadowMapSize: Object, + color: { type: String, default: '#ffffff' }, + intensity: { type: Number, default: 1 }, + castShadow: { type: Boolean, default: false }, + shadowMapSize: { type: Object, default: { x: 512, y: 512 } }, position: Object, }, // can't use setup because it will not be used in sub components // setup() {}, - created() { - this.parent = this.group ? this.group : this.scene; - }, - mounted() { - bindProp(this, 'position', this.light.position); - - if (this.light.target) { - bindProp(this, 'target', this.light.target.position); - } - - if (this.light.shadow) { - this.light.castShadow = this.castShadow; - setFromProp(this.light.shadow.mapSize, this.shadowMapSize); - } - - ['color', 'intensity', 'castShadow'].forEach(p => { - watch(() => this[p], () => { - if (p === 'color') { - this.light.color = new Color(this.color); - } else { - this.light[p] = this[p]; - } - }); - }); - - this.parent.add(this.light); - if (this.light.target) this.parent.add(this.light.target); - }, unmounted() { - this.parent.remove(this.light); - if (this.light.target) this.parent.remove(this.light.target); + this.$parent.remove(this.light); + if (this.light.target) this.$parent.remove(this.light.target); + }, + methods: { + initLight() { + bindProp(this, 'position', this.light.position); + + if (this.light.target) { + bindProp(this, 'target', this.light.target.position); + } + + if (this.light.shadow) { + this.light.castShadow = this.castShadow; + setFromProp(this.light.shadow.mapSize, this.shadowMapSize); + } + + ['color', 'intensity', 'castShadow'].forEach(p => { + watch(() => this[p], () => { + if (p === 'color') { + this.light.color = new Color(this.color); + } else { + this.light[p] = this[p]; + } + }); + }); + + this.$parent.add(this.light); + if (this.light.target) this.$parent.add(this.light.target); + }, }, render() { return []; diff --git a/src/lights/PointLight.js b/src/lights/PointLight.js index e00e98f..a22893c 100644 --- a/src/lights/PointLight.js +++ b/src/lights/PointLight.js @@ -15,6 +15,7 @@ export default { }, created() { this.light = new PointLight(this.color, this.intensity, this.distance, this.decay); + this.initLight(); }, __hmrId: 'PointLight', }; diff --git a/src/lights/SpotLight.js b/src/lights/SpotLight.js index 61f2b0a..0d23a13 100644 --- a/src/lights/SpotLight.js +++ b/src/lights/SpotLight.js @@ -5,22 +5,10 @@ import Light from './Light.js'; export default { extends: Light, props: { - angle: { - type: Number, - default: Math.PI / 3, - }, - decay: { - type: Number, - default: 1, - }, - distance: { - type: Number, - default: 0, - }, - penumbra: { - type: Number, - default: 0, - }, + angle: { type: Number, default: Math.PI / 3 }, + decay: { type: Number, default: 1 }, + distance: { type: Number, default: 0 }, + penumbra: { type: Number, default: 0 }, target: Object, }, created() { @@ -30,6 +18,7 @@ export default { this.light[p] = this[p]; }); }); + this.initLight(); }, __hmrId: 'SpotLight', }; diff --git a/src/materials/BasicMaterial.js b/src/materials/BasicMaterial.js index 5008ea1..900cc08 100644 --- a/src/materials/BasicMaterial.js +++ b/src/materials/BasicMaterial.js @@ -6,7 +6,7 @@ export default { extends: Material, methods: { createMaterial() { - this.material = new MeshBasicMaterial(propsValues(this.$props, ['id'])); + this.material = new MeshBasicMaterial(propsValues(this.$props)); }, }, __hmrId: 'BasicMaterial', diff --git a/src/materials/LambertMaterial.js b/src/materials/LambertMaterial.js index 8680fac..bb83ee2 100644 --- a/src/materials/LambertMaterial.js +++ b/src/materials/LambertMaterial.js @@ -6,7 +6,7 @@ export default { extends: Material, methods: { createMaterial() { - this.material = new MeshLambertMaterial(propsValues(this.$props, ['id'])); + this.material = new MeshLambertMaterial(propsValues(this.$props)); }, }, __hmrId: 'LambertMaterial', diff --git a/src/materials/Map.js b/src/materials/Map.js index 6d878f3..b176226 100644 --- a/src/materials/Map.js +++ b/src/materials/Map.js @@ -1,4 +1,4 @@ -import Texture from '../core/Texture'; +import Texture from './Texture.js'; export default { extends: Texture, diff --git a/src/materials/MatcapMaterial.js b/src/materials/MatcapMaterial.js index 7565338..5d5c384 100644 --- a/src/materials/MatcapMaterial.js +++ b/src/materials/MatcapMaterial.js @@ -12,7 +12,7 @@ export default { methods: { createMaterial() { const src = this.name ? getMatcapUrl(this.name) : this.src; - const opts = propsValues(this.$props, ['id', 'src', 'name']); + const opts = propsValues(this.$props, ['src', 'name']); opts.matcap = new TextureLoader().load(src); this.material = new MeshMatcapMaterial(opts); }, diff --git a/src/materials/Material.js b/src/materials/Material.js index 7b54ed5..1ded368 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -4,7 +4,6 @@ import { FrontSide } from 'three'; export default { inject: ['three', 'mesh'], props: { - id: String, color: { type: [String, Number], default: '#ffffff' }, depthTest: { type: Boolean, default: true }, depthWrite: { type: Boolean, default: true }, @@ -20,18 +19,15 @@ export default { material: this, }; }, - beforeMount() { + created() { this.createMaterial(); - if (this.id) this.three.materials[this.id] = this.material; this.mesh.setMaterial(this.material); - }, - mounted() { + this._addWatchers(); if (this.addWatchers) this.addWatchers(); }, unmounted() { this.material.dispose(); - if (this.id) delete this.three.materials[this.id]; }, methods: { setProp(key, value, needsUpdate = false) { @@ -55,10 +51,7 @@ export default { }, }, render() { - if (this.$slots.default) { - return this.$slots.default(); - } - return []; + return this.$slots.default ? this.$slots.default() : []; }, __hmrId: 'Material', }; diff --git a/src/materials/PhongMaterial.js b/src/materials/PhongMaterial.js index b2c8204..e7c4a1a 100644 --- a/src/materials/PhongMaterial.js +++ b/src/materials/PhongMaterial.js @@ -14,7 +14,7 @@ export default { }, methods: { createMaterial() { - this.material = new MeshPhongMaterial(propsValues(this.$props, ['id'])); + this.material = new MeshPhongMaterial(propsValues(this.$props)); }, addWatchers() { ['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular'].forEach(p => { diff --git a/src/materials/PhysicalMaterial.js b/src/materials/PhysicalMaterial.js index 394df8c..95ba19e 100644 --- a/src/materials/PhysicalMaterial.js +++ b/src/materials/PhysicalMaterial.js @@ -6,7 +6,7 @@ export default { extends: StandardMaterial, methods: { createMaterial() { - this.material = new MeshPhysicalMaterial(propsValues(this.$props, ['id'])); + this.material = new MeshPhysicalMaterial(propsValues(this.$props)); }, }, __hmrId: 'PhysicalMaterial', diff --git a/src/materials/ShaderMaterial.js b/src/materials/ShaderMaterial.js index b2e6da2..43f4bc6 100644 --- a/src/materials/ShaderMaterial.js +++ b/src/materials/ShaderMaterial.js @@ -1,22 +1,17 @@ export default { inject: ['three', 'mesh'], props: { - id: String, uniforms: Object, vertexShader: String, fragmentShader: String, }, - beforeMount() { + created() { this.createMaterial(); - if (this.id) this.three.materials[this.id] = this.material; this.mesh.setMaterial(this.material); - }, - mounted() { if (this.addWatchers) this.addWatchers(); }, unmounted() { this.material.dispose(); - if (this.id) delete this.three.materials[this.id]; }, render() { return []; diff --git a/src/materials/StandardMaterial.js b/src/materials/StandardMaterial.js index d0d7b51..3f42f15 100644 --- a/src/materials/StandardMaterial.js +++ b/src/materials/StandardMaterial.js @@ -25,7 +25,7 @@ export default { props, methods: { createMaterial() { - this.material = new MeshStandardMaterial(propsValues(this.$props, ['id', 'normalScale'])); + this.material = new MeshStandardMaterial(propsValues(this.$props, ['normalScale'])); }, addWatchers() { // todo : use setProp ? diff --git a/src/materials/SubSurfaceMaterial.js b/src/materials/SubSurfaceMaterial.js index d0039ea..efac4d2 100644 --- a/src/materials/SubSurfaceMaterial.js +++ b/src/materials/SubSurfaceMaterial.js @@ -27,7 +27,7 @@ export default { if (key === 'color') _key = 'diffuse'; _value = new Color(value); } - if (!['id', 'transparent', 'vertexColors'].includes(key)) { + if (!['transparent', 'vertexColors'].includes(key)) { uniforms[_key].value = _value; } }); diff --git a/src/materials/Texture.js b/src/materials/Texture.js index 7c77070..e83e552 100644 --- a/src/materials/Texture.js +++ b/src/materials/Texture.js @@ -32,7 +32,5 @@ export default { this.$emit('loaded'); }, }, - render() { - return []; - }, + render() { return []; }, }; diff --git a/src/materials/ToonMaterial.js b/src/materials/ToonMaterial.js index cadce9f..8cc12ce 100644 --- a/src/materials/ToonMaterial.js +++ b/src/materials/ToonMaterial.js @@ -6,7 +6,7 @@ export default { extends: Material, methods: { createMaterial() { - this.material = new MeshToonMaterial(propsValues(this.$props, ['id'])); + this.material = new MeshToonMaterial(propsValues(this.$props)); }, }, __hmrId: 'ToonMaterial', diff --git a/src/meshes/Gem.js b/src/meshes/Gem.js index e2a89e8..347e389 100644 --- a/src/meshes/Gem.js +++ b/src/meshes/Gem.js @@ -7,8 +7,7 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -// import { watch } from 'vue'; -import Mesh from '../meshes/Mesh.js'; +import Mesh from './Mesh.js'; import { bindProp } from '../tools.js'; export default { @@ -26,15 +25,17 @@ export default { }, unmounted() { this.three.offBeforeRender(this.updateCubeRT); - if (this.meshBack) this.parent.remove(this.meshBack); + if (this.meshBack) this.$parent.remove(this.meshBack); if (this.materialBack) this.materialBack.dispose(); }, methods: { initGem() { + this.initMesh(); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); bindProp(this, 'position', this.cubeCamera.position); - this.parent.add(this.cubeCamera); + this.$parent.add(this.cubeCamera); this.material.side = FrontSide; this.material.envMap = cubeRT.texture; @@ -58,7 +59,7 @@ export default { bindProp(this, 'position', this.meshBack.position); bindProp(this, 'rotation', this.meshBack.rotation); bindProp(this, 'scale', this.meshBack.scale); - this.parent.add(this.meshBack); + this.$parent.add(this.meshBack); }, updateCubeRT() { this.mesh.visible = false; diff --git a/src/meshes/InstancedMesh.js b/src/meshes/InstancedMesh.js index a333ac2..a75de03 100644 --- a/src/meshes/InstancedMesh.js +++ b/src/meshes/InstancedMesh.js @@ -1,61 +1,28 @@ import { InstancedMesh } from 'three'; -import { watch } from 'vue'; -import { bindProp } from '../tools.js'; +import Object3D from '../core/Object3D.js'; export default { - inject: { - three: 'three', - scene: 'scene', - group: { default: null }, - }, + extends: Object3D, props: { - materialId: String, count: Number, - position: Object, - castShadow: Boolean, - receiveShadow: Boolean, }, provide() { return { mesh: this, }; }, - created() { - this.parent = this.group ? this.group : this.scene; - }, beforeMount() { if (!this.$slots.default) { console.error('Missing Geometry'); } }, - mounted() { + created() { this.initMesh(); }, - unmounted() { - this.parent.remove(this.mesh); - }, methods: { initMesh() { - if (!this.material && this.materialId) { - this.material = this.three.materials[this.materialId]; - } - this.mesh = new InstancedMesh(this.geometry, this.material, this.count); - - bindProp(this, 'position', this.mesh.position); - bindProp(this, 'rotation', this.mesh.rotation); - bindProp(this, 'scale', this.mesh.scale); - - ['castShadow', 'receiveShadow'].forEach(p => { - this.mesh[p] = this[p]; - watch(() => this[p], () => { this.mesh[p] = this[p]; }); - }); - - // watch(() => this.materialId, () => { - // this.mesh.material = this.three.materials[this.materialId]; - // }); - - this.parent.add(this.mesh); + this.initObject3D(this.mesh); }, setGeometry(geometry) { this.geometry = geometry; @@ -66,8 +33,5 @@ export default { if (this.mesh) this.mesh.material = material; }, }, - render() { - return this.$slots.default(); - }, __hmrId: 'InstancedMesh', }; diff --git a/src/meshes/Mesh.js b/src/meshes/Mesh.js index 5c4ce5d..4833622 100644 --- a/src/meshes/Mesh.js +++ b/src/meshes/Mesh.js @@ -1,51 +1,24 @@ import { Mesh } from 'three'; -import { watch } from 'vue'; -import { bindProp } from '../tools.js'; +import Object3D from '../core/Object3D.js'; export default { - inject: { - three: 'three', - scene: 'scene', - rendererComponent: 'rendererComponent', - group: { default: null }, - }, - emits: ['ready'], + extends: Object3D, props: { - materialId: String, - position: Object, - rotation: Object, - scale: Object, - castShadow: Boolean, - receiveShadow: Boolean, onHover: Function, onClick: Function, }, // can't use setup because it will not be used in sub components // setup() {}, - created() { - this.parent = this.group ? this.group : this.scene; - }, provide() { return { mesh: this, }; }, mounted() { - if (this.geometry && !this.mesh) this.initMesh(); - }, - unmounted() { - if (this.mesh) { - this.three.removeIntersectObject(this.mesh); - this.parent.remove(this.mesh); - } - if (this.geometry) this.geometry.dispose(); - if (this.material && !this.materialId) this.material.dispose(); + if (!this.mesh && !this.loading) this.initMesh(); }, methods: { initMesh() { - if (!this.material && this.materialId) { - this.material = this.three.materials[this.materialId]; - } this.mesh = new Mesh(this.geometry, this.material); if (this.onHover) { @@ -58,23 +31,7 @@ export default { this.three.addIntersectObject(this.mesh); } - this.bindProps(); - this.parent.add(this.mesh); - this.$emit('ready'); - }, - bindProps() { - bindProp(this, 'position', this.mesh.position); - bindProp(this, 'rotation', this.mesh.rotation); - bindProp(this, 'scale', this.mesh.scale); - - ['castShadow', 'receiveShadow'].forEach(p => { - this.mesh[p] = this[p]; - watch(() => this[p], () => { this.mesh[p] = this[p]; }); - }); - - watch(() => this.materialId, () => { - this.mesh.material = this.three.materials[this.materialId]; - }); + this.initObject3D(this.mesh); }, setGeometry(geometry) { this.geometry = geometry; @@ -91,11 +48,13 @@ export default { oldGeo.dispose(); }, }, - render() { - if (this.$slots.default) { - return this.$slots.default(); + unmounted() { + if (this.mesh) { + this.three.removeIntersectObject(this.mesh); } - return []; + // for predefined mesh (geometry and material are not unmounted) + if (this.geometry) this.geometry.dispose(); + if (this.material) this.material.dispose(); }, __hmrId: 'Mesh', }; diff --git a/src/meshes/MirrorMesh.js b/src/meshes/MirrorMesh.js index 41ff95d..3d43863 100644 --- a/src/meshes/MirrorMesh.js +++ b/src/meshes/MirrorMesh.js @@ -4,9 +4,7 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -// import { watch } from 'vue'; import Mesh from './Mesh.js'; -import { bindProp } from '../tools.js'; export default { extends: Mesh, @@ -23,13 +21,15 @@ export default { }, unmounted() { this.three.offBeforeRender(this.updateCubeRT); - if (this.cubeCamera) this.parent.remove(this.cubeCamera); + if (this.cubeCamera) this.$parent.remove(this.cubeCamera); }, methods: { initMirrorMesh() { + this.initMesh(); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - this.parent.add(this.cubeCamera); + this.$parent.add(this.cubeCamera); this.material.envMap = cubeRT.texture; this.material.needsUpdate = true; diff --git a/src/meshes/RefractionMesh.js b/src/meshes/RefractionMesh.js index b015043..78e3f64 100644 --- a/src/meshes/RefractionMesh.js +++ b/src/meshes/RefractionMesh.js @@ -5,7 +5,6 @@ import { RGBFormat, WebGLCubeRenderTarget, } from 'three'; -// import { watch } from 'vue'; import Mesh from './Mesh.js'; import { bindProp } from '../tools.js'; @@ -25,14 +24,16 @@ export default { }, unmounted() { this.three.offBeforeRender(this.updateCubeRT); - if (this.cubeCamera) this.parent.remove(this.cubeCamera); + if (this.cubeCamera) this.$parent.remove(this.cubeCamera); }, methods: { initMirrorMesh() { + this.initMesh(); + const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); bindProp(this, 'position', this.cubeCamera.position); - this.parent.add(this.cubeCamera); + this.$parent.add(this.cubeCamera); this.material.envMap = cubeRT.texture; this.material.refractionRatio = this.refractionRatio; diff --git a/src/meshes/Sprite.js b/src/meshes/Sprite.js index e956ec8..3093902 100644 --- a/src/meshes/Sprite.js +++ b/src/meshes/Sprite.js @@ -1,39 +1,31 @@ import { Sprite, SpriteMaterial, TextureLoader } from 'three'; -import { bindProp } from '../tools.js'; +import Object3D from '../core/Object3D.js'; export default { - emits: ['ready', 'loaded'], - inject: { - three: 'three', - scene: 'scene', - group: { default: null }, - }, + extends: Object3D, + emits: ['loaded'], props: { src: String, - position: Object, - scale: Object, + }, + data() { + return { + loading: true, + }; }, created() { - this.parent = this.group ? this.group : this.scene; - }, - mounted() { this.texture = new TextureLoader().load(this.src, this.onLoaded); this.material = new SpriteMaterial({ map: this.texture }); this.sprite = new Sprite(this.material); this.geometry = this.sprite.geometry; - bindProp(this, 'position', this.sprite.position); - bindProp(this, 'scale', this.sprite.scale); - - this.parent.add(this.sprite); - this.$emit('ready'); + this.initObject3D(this.sprite); }, unmounted() { this.texture.dispose(); this.material.dispose(); - this.parent.remove(this.sprite); }, methods: { onLoaded() { + this.loading = false; this.updateUV(); this.$emit('loaded'); }, @@ -57,8 +49,5 @@ export default { this.geometry.attributes.position.needsUpdate = true; }, }, - render() { - return []; - }, __hmrId: 'Sprite', }; diff --git a/src/meshes/Text.js b/src/meshes/Text.js index 7448744..ca9e4d9 100644 --- a/src/meshes/Text.js +++ b/src/meshes/Text.js @@ -8,6 +8,11 @@ export default { props: { ...TextProps, }, + data() { + return { + loading: true, + }; + }, created() { // add watchers const watchProps = [ @@ -23,6 +28,7 @@ export default { const loader = new FontLoader(); loader.load(this.fontSrc, (font) => { + this.loading = false; this.font = font; this.createGeometry(); this.initMesh();