mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
meshes
This commit is contained in:
parent
c82430eb39
commit
7cab6b5a79
@ -1,69 +0,0 @@
|
||||
import { defineComponent, watch } from 'vue';
|
||||
import { DoubleSide, MeshBasicMaterial, PlaneGeometry, TextureLoader } from 'three';
|
||||
import Mesh from './Mesh.js';
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['loaded'],
|
||||
extends: Mesh,
|
||||
props: {
|
||||
src: String,
|
||||
width: Number,
|
||||
height: Number,
|
||||
keepSize: Boolean,
|
||||
},
|
||||
created() {
|
||||
this.createGeometry();
|
||||
this.createMaterial();
|
||||
this.initMesh();
|
||||
|
||||
watch(() => this.src, this.refreshTexture);
|
||||
|
||||
['width', 'height'].forEach(p => {
|
||||
watch(() => this[p], this.resize);
|
||||
});
|
||||
|
||||
if (this.keepSize) this.three.onAfterResize(this.resize);
|
||||
},
|
||||
methods: {
|
||||
createGeometry() {
|
||||
this.geometry = new PlaneGeometry(1, 1, 1, 1);
|
||||
},
|
||||
createMaterial() {
|
||||
this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() });
|
||||
},
|
||||
loadTexture() {
|
||||
return new TextureLoader().load(this.src, this.onLoaded);
|
||||
},
|
||||
refreshTexture() {
|
||||
if (this.texture) this.texture.dispose();
|
||||
this.material.map = this.loadTexture();
|
||||
this.material.needsUpdate = true;
|
||||
},
|
||||
onLoaded(texture) {
|
||||
this.texture = texture;
|
||||
this.resize();
|
||||
this.$emit('loaded');
|
||||
},
|
||||
resize() {
|
||||
if (!this.texture) return;
|
||||
const screen = this.three.size;
|
||||
const iW = this.texture.image.width;
|
||||
const iH = this.texture.image.height;
|
||||
const iRatio = iW / iH;
|
||||
let w, h;
|
||||
if (this.width && this.height) {
|
||||
w = this.width * screen.wWidth / screen.width;
|
||||
h = this.height * screen.wHeight / screen.height;
|
||||
} else if (this.width) {
|
||||
w = this.width * screen.wWidth / screen.width;
|
||||
h = w / iRatio;
|
||||
} else if (this.height) {
|
||||
h = this.height * screen.wHeight / screen.height;
|
||||
w = h * iRatio;
|
||||
}
|
||||
this.mesh.scale.x = w;
|
||||
this.mesh.scale.y = h;
|
||||
},
|
||||
},
|
||||
__hmrId: 'Image',
|
||||
});
|
80
src/meshes/Image.ts
Normal file
80
src/meshes/Image.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { DoubleSide, MeshBasicMaterial, PlaneGeometry, Texture, TextureLoader } from 'three'
|
||||
import Mesh, { MeshSetupInterface } from './Mesh'
|
||||
import { object3DSetup } from '../core/Object3D'
|
||||
|
||||
interface ImageInterface extends MeshSetupInterface {
|
||||
material?: MeshBasicMaterial
|
||||
texture?: Texture
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['loaded'],
|
||||
extends: Mesh,
|
||||
props: {
|
||||
src: { type: String, required: true },
|
||||
width: Number,
|
||||
height: Number,
|
||||
keepSize: Boolean,
|
||||
},
|
||||
setup(): ImageInterface {
|
||||
return object3DSetup()
|
||||
},
|
||||
created() {
|
||||
this.geometry = new PlaneGeometry(1, 1, 1, 1)
|
||||
this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() })
|
||||
|
||||
watch(() => this.src, this.refreshTexture);
|
||||
|
||||
['width', 'height'].forEach(p => {
|
||||
// @ts-ignore
|
||||
watch(() => this[p], this.resize)
|
||||
})
|
||||
|
||||
this.resize()
|
||||
if (this.keepSize) this.renderer.onResize(this.resize)
|
||||
},
|
||||
methods: {
|
||||
loadTexture() {
|
||||
return new TextureLoader().load(this.src, this.onLoaded)
|
||||
},
|
||||
refreshTexture() {
|
||||
this.texture?.dispose()
|
||||
if (this.material) {
|
||||
this.material.map = this.loadTexture()
|
||||
this.material.needsUpdate = true
|
||||
}
|
||||
},
|
||||
onLoaded(texture: Texture) {
|
||||
this.texture = texture
|
||||
this.resize()
|
||||
this.$emit('loaded', texture)
|
||||
},
|
||||
resize() {
|
||||
if (!this.texture) return
|
||||
const screen = this.renderer.size
|
||||
const iW = this.texture.image.width
|
||||
const iH = this.texture.image.height
|
||||
const iRatio = iW / iH
|
||||
let w = 1, h = 1
|
||||
if (this.width && this.height) {
|
||||
w = this.width * screen.wWidth / screen.width
|
||||
h = this.height * screen.wHeight / screen.height
|
||||
} else if (this.width) {
|
||||
w = this.width * screen.wWidth / screen.width
|
||||
h = w / iRatio
|
||||
} else if (this.height) {
|
||||
h = this.height * screen.wHeight / screen.height
|
||||
w = h * iRatio
|
||||
} else {
|
||||
if (iRatio > 1) w = h * iRatio
|
||||
else h = w / iRatio
|
||||
}
|
||||
if (this.mesh) {
|
||||
this.mesh.scale.x = w
|
||||
this.mesh.scale.y = h
|
||||
}
|
||||
},
|
||||
},
|
||||
__hmrId: 'Image',
|
||||
})
|
@ -1,8 +1,7 @@
|
||||
import { ComponentPropsOptions, defineComponent, inject, watch } from 'vue'
|
||||
import { ComponentPropsOptions, defineComponent, watch } from 'vue'
|
||||
import { BufferGeometry, Material, Mesh as TMesh } from 'three'
|
||||
import Object3D from '../core/Object3D'
|
||||
import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
|
||||
import { bindProp } from '../tools'
|
||||
import { ThreeInterface } from '../core/useThree'
|
||||
|
||||
export const pointerProps = {
|
||||
onPointerEnter: Function,
|
||||
@ -14,23 +13,18 @@ export const pointerProps = {
|
||||
onClick: Function,
|
||||
}
|
||||
|
||||
interface MeshSetupInterface {
|
||||
three?: ThreeInterface
|
||||
export interface MeshSetupInterface extends Object3DSetupInterface {
|
||||
mesh?: TMesh
|
||||
geometry?: BufferGeometry
|
||||
material?: Material
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export interface MeshInterface {
|
||||
export interface MeshInterface extends MeshSetupInterface {
|
||||
setGeometry(g: BufferGeometry): void
|
||||
setMaterial(m: Material): void
|
||||
}
|
||||
|
||||
export function defaultSetup(): MeshSetupInterface {
|
||||
const three = inject('three') as ThreeInterface
|
||||
return { three }
|
||||
}
|
||||
|
||||
const Mesh = defineComponent({
|
||||
name: 'Mesh',
|
||||
extends: Object3D,
|
||||
@ -39,10 +33,8 @@ const Mesh = defineComponent({
|
||||
receiveShadow: Boolean,
|
||||
...pointerProps,
|
||||
},
|
||||
setup() {
|
||||
return defaultSetup()
|
||||
},
|
||||
created() {
|
||||
setup(): MeshSetupInterface {
|
||||
return object3DSetup()
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@ -114,8 +106,8 @@ export function meshComponent(name, props, createGeometry) {
|
||||
name,
|
||||
extends: Mesh,
|
||||
props,
|
||||
setup() {
|
||||
return defaultSetup()
|
||||
setup(): MeshSetupInterface {
|
||||
return object3DSetup()
|
||||
},
|
||||
created() {
|
||||
this.createGeometry()
|
||||
|
@ -1,54 +0,0 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { Sprite, SpriteMaterial, TextureLoader } from 'three';
|
||||
import Object3D from '../core/Object3D';
|
||||
|
||||
export default defineComponent({
|
||||
extends: Object3D,
|
||||
emits: ['loaded'],
|
||||
props: {
|
||||
src: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
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;
|
||||
this.initObject3D(this.sprite);
|
||||
},
|
||||
unmounted() {
|
||||
this.texture.dispose();
|
||||
this.material.dispose();
|
||||
},
|
||||
methods: {
|
||||
onLoaded() {
|
||||
this.loading = false;
|
||||
this.updateUV();
|
||||
this.$emit('loaded');
|
||||
},
|
||||
updateUV() {
|
||||
this.iWidth = this.texture.image.width;
|
||||
this.iHeight = this.texture.image.height;
|
||||
this.iRatio = this.iWidth / this.iHeight;
|
||||
|
||||
let x = 0.5, y = 0.5;
|
||||
if (this.iRatio > 1) {
|
||||
y = 0.5 / this.iRatio;
|
||||
} else {
|
||||
x = 0.5 / this.iRatio;
|
||||
}
|
||||
|
||||
const positions = this.geometry.attributes.position.array;
|
||||
positions[0] = -x; positions[1] = -y;
|
||||
positions[5] = x; positions[6] = -y;
|
||||
positions[10] = x; positions[11] = y;
|
||||
positions[15] = -x; positions[16] = y;
|
||||
this.geometry.attributes.position.needsUpdate = true;
|
||||
},
|
||||
},
|
||||
__hmrId: 'Sprite',
|
||||
});
|
58
src/meshes/Sprite.ts
Normal file
58
src/meshes/Sprite.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { Sprite, SpriteMaterial, Texture, TextureLoader } from 'three'
|
||||
import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
|
||||
|
||||
interface SpriteSetupInterface extends Object3DSetupInterface {
|
||||
texture?: Texture
|
||||
material?: SpriteMaterial
|
||||
sprite?: Sprite
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
extends: Object3D,
|
||||
emits: ['loaded'],
|
||||
props: {
|
||||
src: { type: String, required: true },
|
||||
},
|
||||
setup(): SpriteSetupInterface {
|
||||
return object3DSetup()
|
||||
},
|
||||
created() {
|
||||
this.texture = new TextureLoader().load(this.src, this.onLoaded)
|
||||
this.material = new SpriteMaterial({ map: this.texture })
|
||||
this.sprite = new Sprite(this.material)
|
||||
this.initObject3D(this.sprite)
|
||||
},
|
||||
unmounted() {
|
||||
this.texture?.dispose()
|
||||
this.material?.dispose()
|
||||
},
|
||||
methods: {
|
||||
onLoaded() {
|
||||
this.updateUV()
|
||||
this.$emit('loaded')
|
||||
},
|
||||
updateUV() {
|
||||
if (!this.texture || !this.sprite) return
|
||||
|
||||
const iWidth = this.texture.image.width
|
||||
const iHeight = this.texture.image.height
|
||||
const iRatio = iWidth / iHeight
|
||||
|
||||
let x = 0.5, y = 0.5
|
||||
if (iRatio > 1) {
|
||||
x = 0.5 * iRatio
|
||||
} else {
|
||||
y = 0.5 / iRatio
|
||||
}
|
||||
|
||||
const positions = this.sprite.geometry.attributes.position.array as Array<number>
|
||||
positions[0] = -x; positions[1] = -y
|
||||
positions[5] = x; positions[6] = -y
|
||||
positions[10] = x; positions[11] = y
|
||||
positions[15] = -x; positions[16] = y
|
||||
this.sprite.geometry.attributes.position.needsUpdate = true
|
||||
},
|
||||
},
|
||||
__hmrId: 'Sprite',
|
||||
})
|
Loading…
Reference in New Issue
Block a user