1
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { Scene, Mesh, MeshBuilder, StandardMaterial, Color3, Vector3 } from '@babylonjs/core';
|
||||
import { Scene, Mesh, MeshBuilder, StandardMaterial, Color3, Vector3, ActionManager, ExecuteCodeAction } from '@babylonjs/core';
|
||||
|
||||
/**
|
||||
* 墙面配置 - 定义一个垂直面的起始和结束坐标
|
||||
@ -9,6 +9,7 @@ export interface WallConfig {
|
||||
endPoint: Vector3; // 结束点坐标(右下角)
|
||||
height: number; // 墙面高度
|
||||
divisions: number; // 分割数(将这个面分成几块)
|
||||
offset?: number; // 偏移量(正数向外,负数向内,默认0)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,6 +41,7 @@ export class AppPlacementWall {
|
||||
private scene: Scene;
|
||||
private placementZones: PlacementZoneInfo[] = [];
|
||||
private borderLines: Mesh[] = [];
|
||||
private onZoneClickCallback?: (zoneInfo: PlacementZoneInfo) => void;
|
||||
|
||||
constructor(scene: Scene) {
|
||||
this.scene = scene;
|
||||
@ -83,7 +85,7 @@ export class AppPlacementWall {
|
||||
material: StandardMaterial,
|
||||
thickness: number
|
||||
): PlacementZoneInfo[] {
|
||||
const { name, startPoint, endPoint, height, divisions } = wall;
|
||||
const { name, startPoint, endPoint, height, divisions, offset = 0 } = wall;
|
||||
|
||||
// 计算墙面的方向向量和长度
|
||||
const direction = endPoint.subtract(startPoint);
|
||||
@ -96,15 +98,18 @@ export class AppPlacementWall {
|
||||
// 计算墙面的法线方向(垂直于墙面,指向外侧)
|
||||
const normal = new Vector3(-normalizedDir.z, 0, normalizedDir.x);
|
||||
|
||||
// 应用偏移量(沿着法线方向)
|
||||
const offsetVector = normal.scale(offset);
|
||||
|
||||
const zones: PlacementZoneInfo[] = [];
|
||||
|
||||
for (let i = 0; i < divisions; i++) {
|
||||
// 计算当前块的中心位置
|
||||
const offset = blockWidth * (i + 0.5);
|
||||
const centerX = startPoint.x + normalizedDir.x * offset;
|
||||
const offset_i = blockWidth * (i + 0.5);
|
||||
const centerX = startPoint.x + normalizedDir.x * offset_i;
|
||||
const centerY = startPoint.y + height / 2;
|
||||
const centerZ = startPoint.z + normalizedDir.z * offset;
|
||||
const center = new Vector3(centerX, centerY, centerZ);
|
||||
const centerZ = startPoint.z + normalizedDir.z * offset_i;
|
||||
const center = new Vector3(centerX, centerY, centerZ).add(offsetVector);
|
||||
|
||||
// 创建放置区域平面
|
||||
const plane = MeshBuilder.CreatePlane(
|
||||
@ -127,6 +132,28 @@ export class AppPlacementWall {
|
||||
// 启用拾取
|
||||
plane.isPickable = true;
|
||||
|
||||
// 添加点击事件
|
||||
plane.actionManager = new ActionManager(this.scene);
|
||||
plane.actionManager.registerAction(
|
||||
new ExecuteCodeAction(
|
||||
ActionManager.OnPickTrigger,
|
||||
() => {
|
||||
const zoneInfo: PlacementZoneInfo = {
|
||||
mesh: plane,
|
||||
wallName: name,
|
||||
index: i,
|
||||
center: center.clone(),
|
||||
width: blockWidth,
|
||||
height: height,
|
||||
normal: normal.clone()
|
||||
};
|
||||
if (this.onZoneClickCallback) {
|
||||
this.onZoneClickCallback(zoneInfo);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// 为每个块创建边框
|
||||
this.createBlockBorder(name, i, center, blockWidth, height, normalizedDir, normal);
|
||||
|
||||
@ -204,13 +231,21 @@ export class AppPlacementWall {
|
||||
* 创建墙面边框
|
||||
*/
|
||||
private createWallBorder(wall: WallConfig, color: string): void {
|
||||
const { name, startPoint, endPoint, height } = wall;
|
||||
const { name, startPoint, endPoint, height, offset = 0 } = wall;
|
||||
|
||||
// 计算四个角点
|
||||
const bottomLeft = startPoint.clone();
|
||||
const bottomRight = endPoint.clone();
|
||||
const topLeft = new Vector3(startPoint.x, startPoint.y + height, startPoint.z);
|
||||
const topRight = new Vector3(endPoint.x, endPoint.y + height, endPoint.z);
|
||||
// 计算法线方向
|
||||
const direction = endPoint.subtract(startPoint);
|
||||
const normalizedDir = direction.normalize();
|
||||
const normal = new Vector3(-normalizedDir.z, 0, normalizedDir.x);
|
||||
|
||||
// 应用偏移量
|
||||
const offsetVector = normal.scale(offset);
|
||||
|
||||
// 计算四个角点(应用偏移)
|
||||
const bottomLeft = startPoint.clone().add(offsetVector);
|
||||
const bottomRight = endPoint.clone().add(offsetVector);
|
||||
const topLeft = new Vector3(startPoint.x, startPoint.y + height, startPoint.z).add(offsetVector);
|
||||
const topRight = new Vector3(endPoint.x, endPoint.y + height, endPoint.z).add(offsetVector);
|
||||
|
||||
// 创建四条边
|
||||
const edges = [
|
||||
@ -240,7 +275,8 @@ export class AppPlacementWall {
|
||||
private createMaterial(color: string, alpha: number): StandardMaterial {
|
||||
const material = new StandardMaterial('placementMaterial', this.scene);
|
||||
const rgb = this.hexToRgb(color);
|
||||
material.diffuseColor = new Color3(rgb.r, rgb.g, rgb.b);
|
||||
material.emissiveColor = new Color3(rgb.r, rgb.g, rgb.b);
|
||||
material.disableLighting = true;
|
||||
material.alpha = alpha;
|
||||
material.backFaceCulling = false;
|
||||
return material;
|
||||
@ -283,6 +319,13 @@ export class AppPlacementWall {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置点击回调
|
||||
*/
|
||||
setOnZoneClick(callback: (zoneInfo: PlacementZoneInfo) => void): void {
|
||||
this.onZoneClickCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示所有放置区域
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user