房间几何体
import * as THREE from "three";
export class Room {
constructor(
public name: string,
public roomPrefix: string,
public textureUrl: string,
public scene: THREE.Scene = new THREE.Scene(),
public position: THREE.Vector3 = new THREE.Vector3(0, 0, 0),
public euler: THREE.Euler = new THREE.Euler(0, 0, 0),
) {
// 创建立方体
const geometry = new THREE.BoxGeometry(10, 10, 10);
geometry.scale(1, 1, -1);
const arr = [
`${roomPrefix}_r`,
`${roomPrefix}_l`,
`${roomPrefix}_u`,
`${roomPrefix}_d`,
`${roomPrefix}_f`,
`${roomPrefix}_b`,
];
const boxMaterials: THREE.MeshBasicMaterial[] = [];
arr.forEach((item) => {
const texture = new THREE.TextureLoader().load(
textureUrl + item + ".jpg"
);
boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));
})
const box = new THREE.Mesh(geometry, boxMaterials);
box.position.copy(position);
box.rotation.copy(euler);
scene.add(box);
}
}
位置Sprite
import * as THREE from "three";
export class PositionSprite {
sprite: THREE.Sprite;
callbacks: any[];
constructor(
text: string,
position: THREE.Vector3,
scene: THREE.Scene,
camera: THREE.Camera
) {
this.callbacks = [];
// 定义canvas
const canvas = document.createElement("canvas");
canvas.width = 1024;
canvas.height = 1024;
const context = canvas.getContext("2d")!;
context.fillStyle = "rgba(100,100,100,.7)";
context.fillRect(0, 256, canvas.width, canvas.height / 2);
context.textAlign = "center";
context.textBaseline = "middle";
context.font = "bold 200px Arial";
context.fillStyle = "white";
context.fillText(text, canvas.width / 2, canvas.height / 2);
const texture = new THREE.CanvasTexture(canvas);
const material = new THREE.SpriteMaterial({
map: texture,
transparent: true,
})
const sprite = new THREE.Sprite(material);
sprite.position.copy(position);
this.sprite = sprite;
scene.add(sprite);
let pointer = new THREE.Vector2();
let raycaster = new THREE.Raycaster();
window.addEventListener('click', (event: MouseEvent) => {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObject(sprite);
if (intersects.length > 0) {
// 触发回调
this.callbacks.forEach((callback) => {
callback();
})
}
})
}
onClick(callback: () => void) {
this.callbacks.push(callback);
}
}
信息提示Sprite
import * as THREE from "three";
export class TooltipSprite {
sprite: THREE.Sprite;
constructor(
public url: string,
public position: THREE.Vector3,
public scene: THREE.Scene,
public camera: THREE.Camera,
public userData: Record<string, any> = {}
) {
const tooltipTexture = new THREE.TextureLoader().load(url);
const tooltipMaterial = new THREE.SpriteMaterial({
map: tooltipTexture,
transparent: true,
});
const tooltipSprite = new THREE.Sprite(tooltipMaterial);
tooltipSprite.position.copy(position);
tooltipSprite.scale.set(0.2, 0.2, 0.2);
tooltipSprite.userData = userData;
this.sprite = tooltipSprite;
scene.add(tooltipSprite);
}
}