1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00
This commit is contained in:
Kevin Levron 2021-03-06 23:14:22 +01:00
parent 7e0dd5b2ea
commit 2b441f7cd7
44 changed files with 184 additions and 304 deletions

View File

@ -1,47 +1,11 @@
import { Group } from 'three'; import { Group } from 'three';
import { bindProp } from '../tools.js'; import Object3D from './Object3D.js';
export default { export default {
inject: { extends: Object3D,
three: 'three',
scene: 'scene',
group: { default: null },
},
props: {
position: Object,
rotation: Object,
scale: Object,
},
provide() {
return {
group: this.group,
};
},
created() { 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(); this.group = new Group();
bindProp(this, 'position', this.group.position); this.initObject3D(this.group);
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() : [];
}, },
__hmrId: 'Group', __hmrId: 'Group',
}; };

41
src/core/Object3D.js Normal file
View File

@ -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() : [];
},
};

View File

@ -26,7 +26,6 @@ export default {
}); });
}); });
// this.camera.updateProjectionMatrix();
this.three.camera = this.camera; this.three.camera = this.camera;
}, },
render() { render() {

View File

@ -28,9 +28,6 @@ export default {
remove(o) { this.scene.remove(o); }, remove(o) { this.scene.remove(o); },
}, },
render() { render() {
if (this.$slots.default) { return this.$slots.default ? this.$slots.default() : [];
return this.$slots.default();
}
return [];
}, },
}; };

View File

@ -1,4 +1,4 @@
import { BoxBufferGeometry } from 'three'; import { BoxGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -18,7 +18,7 @@ export default {
if (this.size) { if (this.size) {
w = this.size; h = this.size; d = 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { CircleBufferGeometry } from 'three'; import { CircleGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -11,7 +11,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { ConeBufferGeometry } from 'three'; import { ConeGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -14,7 +14,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { CylinderBufferGeometry } from 'three'; import { CylinderGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -15,7 +15,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { DodecahedronBufferGeometry } from 'three'; import { DodecahedronGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -9,7 +9,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { createGeometry() {
this.geometry = new DodecahedronBufferGeometry(this.radius, this.detail); this.geometry = new DodecahedronGeometry(this.radius, this.detail);
}, },
}, },
}; };

View File

@ -1,7 +1,6 @@
import { watch } from 'vue'; import { watch } from 'vue';
export default { export default {
emits: ['ready'],
inject: ['mesh'], inject: ['mesh'],
props: { props: {
rotateX: Number, rotateX: Number,
@ -12,26 +11,20 @@ export default {
if (!this.mesh) { if (!this.mesh) {
console.error('Missing parent Mesh'); console.error('Missing parent Mesh');
} }
this.watchProps = []; this.watchProps = [];
Object.entries(this.$props).forEach(e => this.watchProps.push(e[0])); Object.entries(this.$props).forEach(e => this.watchProps.push(e[0]));
},
beforeMount() {
this.createGeometry(); this.createGeometry();
this.rotateGeometry(); this.rotateGeometry();
this.mesh.setGeometry(this.geometry); this.mesh.setGeometry(this.geometry);
},
mounted() {
this.addWatchers(); this.addWatchers();
}, },
unmounted() { unmounted() {
this.geometry.dispose(); this.geometry.dispose();
}, },
methods: { 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() { addWatchers() {
this.watchProps.forEach(prop => { this.watchProps.forEach(prop => {
watch(() => this[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() { refreshGeometry() {
const oldGeo = this.geometry; const oldGeo = this.geometry;
this.createGeometry(); this.createGeometry();
@ -47,7 +45,5 @@ export default {
oldGeo.dispose(); oldGeo.dispose();
}, },
}, },
render() { render() { return []; },
return [];
},
}; };

View File

@ -1,4 +1,4 @@
import { IcosahedronBufferGeometry } from 'three'; import { IcosahedronGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -9,7 +9,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { createGeometry() {
this.geometry = new IcosahedronBufferGeometry(this.radius, this.detail); this.geometry = new IcosahedronGeometry(this.radius, this.detail);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { LatheBufferGeometry } from 'three'; import { LatheGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -11,7 +11,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { OctahedronBufferGeometry } from 'three'; import { OctahedronGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -9,7 +9,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { createGeometry() {
this.geometry = new OctahedronBufferGeometry(this.radius, this.detail); this.geometry = new OctahedronGeometry(this.radius, this.detail);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { PolyhedronBufferGeometry } from 'three'; import { PolyhedronGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -11,7 +11,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { RingBufferGeometry } from 'three'; import { RingGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -13,7 +13,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { SphereBufferGeometry } from 'three'; import { SphereGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -10,7 +10,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { createGeometry() {
this.geometry = new SphereBufferGeometry(this.radius, this.widthSegments, this.heightSegments); this.geometry = new SphereGeometry(this.radius, this.widthSegments, this.heightSegments);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { TetrahedronBufferGeometry } from 'three'; import { TetrahedronGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -9,7 +9,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { createGeometry() {
this.geometry = new TetrahedronBufferGeometry(this.radius, this.detail); this.geometry = new TetrahedronGeometry(this.radius, this.detail);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { TorusBufferGeometry } from 'three'; import { TorusGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -12,7 +12,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { TorusKnotBufferGeometry } from 'three'; import { TorusKnotGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -13,7 +13,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import { Curve, TubeBufferGeometry } from 'three'; import { Curve, TubeGeometry } from 'three';
import Geometry from './Geometry.js'; import Geometry from './Geometry.js';
export default { export default {
@ -12,7 +12,7 @@ export default {
}, },
methods: { methods: {
createGeometry() { 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);
}, },
}, },
}; };

View File

@ -5,6 +5,7 @@ export default {
extends: Light, extends: Light,
created() { created() {
this.light = new AmbientLight(this.color, this.intensity); this.light = new AmbientLight(this.color, this.intensity);
this.initLight();
}, },
__hmrId: 'AmbientLight', __hmrId: 'AmbientLight',
}; };

View File

@ -8,6 +8,7 @@ export default {
}, },
created() { created() {
this.light = new DirectionalLight(this.color, this.intensity); this.light = new DirectionalLight(this.color, this.intensity);
this.initLight();
}, },
__hmrId: 'DirectionalLight', __hmrId: 'DirectionalLight',
}; };

View File

@ -1,62 +1,47 @@
import { Color } from 'three'; import { Color } from 'three';
import { watch } from 'vue'; import { watch } from 'vue';
import { setFromProp } from '../tools.js'; import { bindProp, setFromProp } from '../tools.js';
import { bindProp } from '../tools.js';
export default { export default {
inject: {
scene: 'scene',
group: { default: null },
},
props: { props: {
color: { color: { type: String, default: '#ffffff' },
type: String, intensity: { type: Number, default: 1 },
default: '#ffffff', castShadow: { type: Boolean, default: false },
}, shadowMapSize: { type: Object, default: { x: 512, y: 512 } },
intensity: {
type: Number,
default: 1,
},
castShadow: {
type: Boolean,
default: false,
},
shadowMapSize: Object,
position: Object, position: Object,
}, },
// 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() {},
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() { unmounted() {
this.parent.remove(this.light); this.$parent.remove(this.light);
if (this.light.target) this.parent.remove(this.light.target); 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() { render() {
return []; return [];

View File

@ -15,6 +15,7 @@ export default {
}, },
created() { created() {
this.light = new PointLight(this.color, this.intensity, this.distance, this.decay); this.light = new PointLight(this.color, this.intensity, this.distance, this.decay);
this.initLight();
}, },
__hmrId: 'PointLight', __hmrId: 'PointLight',
}; };

View File

@ -5,22 +5,10 @@ import Light from './Light.js';
export default { export default {
extends: Light, extends: Light,
props: { props: {
angle: { angle: { type: Number, default: Math.PI / 3 },
type: Number, decay: { type: Number, default: 1 },
default: Math.PI / 3, distance: { type: Number, default: 0 },
}, penumbra: { type: Number, default: 0 },
decay: {
type: Number,
default: 1,
},
distance: {
type: Number,
default: 0,
},
penumbra: {
type: Number,
default: 0,
},
target: Object, target: Object,
}, },
created() { created() {
@ -30,6 +18,7 @@ export default {
this.light[p] = this[p]; this.light[p] = this[p];
}); });
}); });
this.initLight();
}, },
__hmrId: 'SpotLight', __hmrId: 'SpotLight',
}; };

View File

@ -6,7 +6,7 @@ export default {
extends: Material, extends: Material,
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshBasicMaterial(propsValues(this.$props, ['id'])); this.material = new MeshBasicMaterial(propsValues(this.$props));
}, },
}, },
__hmrId: 'BasicMaterial', __hmrId: 'BasicMaterial',

View File

@ -6,7 +6,7 @@ export default {
extends: Material, extends: Material,
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshLambertMaterial(propsValues(this.$props, ['id'])); this.material = new MeshLambertMaterial(propsValues(this.$props));
}, },
}, },
__hmrId: 'LambertMaterial', __hmrId: 'LambertMaterial',

View File

@ -1,4 +1,4 @@
import Texture from '../core/Texture'; import Texture from './Texture.js';
export default { export default {
extends: Texture, extends: Texture,

View File

@ -12,7 +12,7 @@ export default {
methods: { methods: {
createMaterial() { createMaterial() {
const src = this.name ? getMatcapUrl(this.name) : this.src; 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); opts.matcap = new TextureLoader().load(src);
this.material = new MeshMatcapMaterial(opts); this.material = new MeshMatcapMaterial(opts);
}, },

View File

@ -4,7 +4,6 @@ import { FrontSide } from 'three';
export default { export default {
inject: ['three', 'mesh'], inject: ['three', 'mesh'],
props: { props: {
id: String,
color: { type: [String, Number], default: '#ffffff' }, color: { type: [String, Number], default: '#ffffff' },
depthTest: { type: Boolean, default: true }, depthTest: { type: Boolean, default: true },
depthWrite: { type: Boolean, default: true }, depthWrite: { type: Boolean, default: true },
@ -20,18 +19,15 @@ export default {
material: this, material: this,
}; };
}, },
beforeMount() { created() {
this.createMaterial(); this.createMaterial();
if (this.id) this.three.materials[this.id] = this.material;
this.mesh.setMaterial(this.material); this.mesh.setMaterial(this.material);
},
mounted() {
this._addWatchers(); this._addWatchers();
if (this.addWatchers) this.addWatchers(); if (this.addWatchers) this.addWatchers();
}, },
unmounted() { unmounted() {
this.material.dispose(); this.material.dispose();
if (this.id) delete this.three.materials[this.id];
}, },
methods: { methods: {
setProp(key, value, needsUpdate = false) { setProp(key, value, needsUpdate = false) {
@ -55,10 +51,7 @@ export default {
}, },
}, },
render() { render() {
if (this.$slots.default) { return this.$slots.default ? this.$slots.default() : [];
return this.$slots.default();
}
return [];
}, },
__hmrId: 'Material', __hmrId: 'Material',
}; };

View File

@ -14,7 +14,7 @@ export default {
}, },
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshPhongMaterial(propsValues(this.$props, ['id'])); this.material = new MeshPhongMaterial(propsValues(this.$props));
}, },
addWatchers() { addWatchers() {
['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular'].forEach(p => { ['emissive', 'emissiveIntensity', 'reflectivity', 'shininess', 'specular'].forEach(p => {

View File

@ -6,7 +6,7 @@ export default {
extends: StandardMaterial, extends: StandardMaterial,
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshPhysicalMaterial(propsValues(this.$props, ['id'])); this.material = new MeshPhysicalMaterial(propsValues(this.$props));
}, },
}, },
__hmrId: 'PhysicalMaterial', __hmrId: 'PhysicalMaterial',

View File

@ -1,22 +1,17 @@
export default { export default {
inject: ['three', 'mesh'], inject: ['three', 'mesh'],
props: { props: {
id: String,
uniforms: Object, uniforms: Object,
vertexShader: String, vertexShader: String,
fragmentShader: String, fragmentShader: String,
}, },
beforeMount() { created() {
this.createMaterial(); this.createMaterial();
if (this.id) this.three.materials[this.id] = this.material;
this.mesh.setMaterial(this.material); this.mesh.setMaterial(this.material);
},
mounted() {
if (this.addWatchers) this.addWatchers(); if (this.addWatchers) this.addWatchers();
}, },
unmounted() { unmounted() {
this.material.dispose(); this.material.dispose();
if (this.id) delete this.three.materials[this.id];
}, },
render() { render() {
return []; return [];

View File

@ -25,7 +25,7 @@ export default {
props, props,
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshStandardMaterial(propsValues(this.$props, ['id', 'normalScale'])); this.material = new MeshStandardMaterial(propsValues(this.$props, ['normalScale']));
}, },
addWatchers() { addWatchers() {
// todo : use setProp ? // todo : use setProp ?

View File

@ -27,7 +27,7 @@ export default {
if (key === 'color') _key = 'diffuse'; if (key === 'color') _key = 'diffuse';
_value = new Color(value); _value = new Color(value);
} }
if (!['id', 'transparent', 'vertexColors'].includes(key)) { if (!['transparent', 'vertexColors'].includes(key)) {
uniforms[_key].value = _value; uniforms[_key].value = _value;
} }
}); });

View File

@ -32,7 +32,5 @@ export default {
this.$emit('loaded'); this.$emit('loaded');
}, },
}, },
render() { render() { return []; },
return [];
},
}; };

View File

@ -6,7 +6,7 @@ export default {
extends: Material, extends: Material,
methods: { methods: {
createMaterial() { createMaterial() {
this.material = new MeshToonMaterial(propsValues(this.$props, ['id'])); this.material = new MeshToonMaterial(propsValues(this.$props));
}, },
}, },
__hmrId: 'ToonMaterial', __hmrId: 'ToonMaterial',

View File

@ -7,8 +7,7 @@ import {
RGBFormat, RGBFormat,
WebGLCubeRenderTarget, WebGLCubeRenderTarget,
} from 'three'; } from 'three';
// import { watch } from 'vue'; import Mesh from './Mesh.js';
import Mesh from '../meshes/Mesh.js';
import { bindProp } from '../tools.js'; import { bindProp } from '../tools.js';
export default { export default {
@ -26,15 +25,17 @@ export default {
}, },
unmounted() { unmounted() {
this.three.offBeforeRender(this.updateCubeRT); 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(); if (this.materialBack) this.materialBack.dispose();
}, },
methods: { methods: {
initGem() { initGem() {
this.initMesh();
const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter });
this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT);
bindProp(this, 'position', this.cubeCamera.position); bindProp(this, 'position', this.cubeCamera.position);
this.parent.add(this.cubeCamera); this.$parent.add(this.cubeCamera);
this.material.side = FrontSide; this.material.side = FrontSide;
this.material.envMap = cubeRT.texture; this.material.envMap = cubeRT.texture;
@ -58,7 +59,7 @@ export default {
bindProp(this, 'position', this.meshBack.position); bindProp(this, 'position', this.meshBack.position);
bindProp(this, 'rotation', this.meshBack.rotation); bindProp(this, 'rotation', this.meshBack.rotation);
bindProp(this, 'scale', this.meshBack.scale); bindProp(this, 'scale', this.meshBack.scale);
this.parent.add(this.meshBack); this.$parent.add(this.meshBack);
}, },
updateCubeRT() { updateCubeRT() {
this.mesh.visible = false; this.mesh.visible = false;

View File

@ -1,61 +1,28 @@
import { InstancedMesh } from 'three'; import { InstancedMesh } from 'three';
import { watch } from 'vue'; import Object3D from '../core/Object3D.js';
import { bindProp } from '../tools.js';
export default { export default {
inject: { extends: Object3D,
three: 'three',
scene: 'scene',
group: { default: null },
},
props: { props: {
materialId: String,
count: Number, count: Number,
position: Object,
castShadow: Boolean,
receiveShadow: Boolean,
}, },
provide() { provide() {
return { return {
mesh: this, mesh: this,
}; };
}, },
created() {
this.parent = this.group ? this.group : this.scene;
},
beforeMount() { beforeMount() {
if (!this.$slots.default) { if (!this.$slots.default) {
console.error('Missing Geometry'); console.error('Missing Geometry');
} }
}, },
mounted() { created() {
this.initMesh(); this.initMesh();
}, },
unmounted() {
this.parent.remove(this.mesh);
},
methods: { methods: {
initMesh() { initMesh() {
if (!this.material && this.materialId) {
this.material = this.three.materials[this.materialId];
}
this.mesh = new InstancedMesh(this.geometry, this.material, this.count); this.mesh = new InstancedMesh(this.geometry, this.material, this.count);
this.initObject3D(this.mesh);
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);
}, },
setGeometry(geometry) { setGeometry(geometry) {
this.geometry = geometry; this.geometry = geometry;
@ -66,8 +33,5 @@ export default {
if (this.mesh) this.mesh.material = material; if (this.mesh) this.mesh.material = material;
}, },
}, },
render() {
return this.$slots.default();
},
__hmrId: 'InstancedMesh', __hmrId: 'InstancedMesh',
}; };

View File

@ -1,51 +1,24 @@
import { Mesh } from 'three'; import { Mesh } from 'three';
import { watch } from 'vue'; import Object3D from '../core/Object3D.js';
import { bindProp } from '../tools.js';
export default { export default {
inject: { extends: Object3D,
three: 'three',
scene: 'scene',
rendererComponent: 'rendererComponent',
group: { default: null },
},
emits: ['ready'],
props: { props: {
materialId: String,
position: Object,
rotation: Object,
scale: Object,
castShadow: Boolean,
receiveShadow: Boolean,
onHover: Function, onHover: Function,
onClick: Function, onClick: Function,
}, },
// 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() {},
created() {
this.parent = this.group ? this.group : this.scene;
},
provide() { provide() {
return { return {
mesh: this, mesh: this,
}; };
}, },
mounted() { mounted() {
if (this.geometry && !this.mesh) this.initMesh(); if (!this.mesh && !this.loading) 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();
}, },
methods: { methods: {
initMesh() { initMesh() {
if (!this.material && this.materialId) {
this.material = this.three.materials[this.materialId];
}
this.mesh = new Mesh(this.geometry, this.material); this.mesh = new Mesh(this.geometry, this.material);
if (this.onHover) { if (this.onHover) {
@ -58,23 +31,7 @@ export default {
this.three.addIntersectObject(this.mesh); this.three.addIntersectObject(this.mesh);
} }
this.bindProps(); this.initObject3D(this.mesh);
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];
});
}, },
setGeometry(geometry) { setGeometry(geometry) {
this.geometry = geometry; this.geometry = geometry;
@ -91,11 +48,13 @@ export default {
oldGeo.dispose(); oldGeo.dispose();
}, },
}, },
render() { unmounted() {
if (this.$slots.default) { if (this.mesh) {
return this.$slots.default(); 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', __hmrId: 'Mesh',
}; };

View File

@ -4,9 +4,7 @@ import {
RGBFormat, RGBFormat,
WebGLCubeRenderTarget, WebGLCubeRenderTarget,
} from 'three'; } from 'three';
// import { watch } from 'vue';
import Mesh from './Mesh.js'; import Mesh from './Mesh.js';
import { bindProp } from '../tools.js';
export default { export default {
extends: Mesh, extends: Mesh,
@ -23,13 +21,15 @@ export default {
}, },
unmounted() { unmounted() {
this.three.offBeforeRender(this.updateCubeRT); this.three.offBeforeRender(this.updateCubeRT);
if (this.cubeCamera) this.parent.remove(this.cubeCamera); if (this.cubeCamera) this.$parent.remove(this.cubeCamera);
}, },
methods: { methods: {
initMirrorMesh() { initMirrorMesh() {
this.initMesh();
const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter });
this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); 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.envMap = cubeRT.texture;
this.material.needsUpdate = true; this.material.needsUpdate = true;

View File

@ -5,7 +5,6 @@ import {
RGBFormat, RGBFormat,
WebGLCubeRenderTarget, WebGLCubeRenderTarget,
} from 'three'; } from 'three';
// import { watch } from 'vue';
import Mesh from './Mesh.js'; import Mesh from './Mesh.js';
import { bindProp } from '../tools.js'; import { bindProp } from '../tools.js';
@ -25,14 +24,16 @@ export default {
}, },
unmounted() { unmounted() {
this.three.offBeforeRender(this.updateCubeRT); this.three.offBeforeRender(this.updateCubeRT);
if (this.cubeCamera) this.parent.remove(this.cubeCamera); if (this.cubeCamera) this.$parent.remove(this.cubeCamera);
}, },
methods: { methods: {
initMirrorMesh() { initMirrorMesh() {
this.initMesh();
const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter });
this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT);
bindProp(this, 'position', this.cubeCamera.position); bindProp(this, 'position', this.cubeCamera.position);
this.parent.add(this.cubeCamera); this.$parent.add(this.cubeCamera);
this.material.envMap = cubeRT.texture; this.material.envMap = cubeRT.texture;
this.material.refractionRatio = this.refractionRatio; this.material.refractionRatio = this.refractionRatio;

View File

@ -1,39 +1,31 @@
import { Sprite, SpriteMaterial, TextureLoader } from 'three'; import { Sprite, SpriteMaterial, TextureLoader } from 'three';
import { bindProp } from '../tools.js'; import Object3D from '../core/Object3D.js';
export default { export default {
emits: ['ready', 'loaded'], extends: Object3D,
inject: { emits: ['loaded'],
three: 'three',
scene: 'scene',
group: { default: null },
},
props: { props: {
src: String, src: String,
position: Object, },
scale: Object, data() {
return {
loading: true,
};
}, },
created() { created() {
this.parent = this.group ? this.group : this.scene;
},
mounted() {
this.texture = new TextureLoader().load(this.src, this.onLoaded); this.texture = new TextureLoader().load(this.src, this.onLoaded);
this.material = new SpriteMaterial({ map: this.texture }); this.material = new SpriteMaterial({ map: this.texture });
this.sprite = new Sprite(this.material); this.sprite = new Sprite(this.material);
this.geometry = this.sprite.geometry; this.geometry = this.sprite.geometry;
bindProp(this, 'position', this.sprite.position); this.initObject3D(this.sprite);
bindProp(this, 'scale', this.sprite.scale);
this.parent.add(this.sprite);
this.$emit('ready');
}, },
unmounted() { unmounted() {
this.texture.dispose(); this.texture.dispose();
this.material.dispose(); this.material.dispose();
this.parent.remove(this.sprite);
}, },
methods: { methods: {
onLoaded() { onLoaded() {
this.loading = false;
this.updateUV(); this.updateUV();
this.$emit('loaded'); this.$emit('loaded');
}, },
@ -57,8 +49,5 @@ export default {
this.geometry.attributes.position.needsUpdate = true; this.geometry.attributes.position.needsUpdate = true;
}, },
}, },
render() {
return [];
},
__hmrId: 'Sprite', __hmrId: 'Sprite',
}; };

View File

@ -8,6 +8,11 @@ export default {
props: { props: {
...TextProps, ...TextProps,
}, },
data() {
return {
loading: true,
};
},
created() { created() {
// add watchers // add watchers
const watchProps = [ const watchProps = [
@ -23,6 +28,7 @@ export default {
const loader = new FontLoader(); const loader = new FontLoader();
loader.load(this.fontSrc, (font) => { loader.load(this.fontSrc, (font) => {
this.loading = false;
this.font = font; this.font = font;
this.createGeometry(); this.createGeometry();
this.initMesh(); this.initMesh();