@ -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 = start Point. clone ( ) ;
const bottomRight = endPoint . clon e( ) ;
const topLeft = new Vector3 ( startPoint . x , startPoint . y + height , startPoint . z ) ;
const topRight = new Vector3 ( endPoint . x , endPoint . y + height , endPoint . z ) ;
// 计算法线方向
const direction = end Point. subtract ( startPoint ) ;
const normalizedDir = direction . normaliz e( ) ;
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 . diffus eColor = new Color3 ( rgb . r , rgb . g , rgb . b ) ;
material . emissiv eColor = 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 ;
}
/**
* 显示所有放置区域
*/