import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder'; import { Mesh } from '@babylonjs/core/Meshes/mesh'; import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial'; import { GridMaterial } from '@babylonjs/materials/grid/gridMaterial'; import { Texture } from '@babylonjs/core/Materials/Textures/texture'; import { Color3 } from '@babylonjs/core/Maths/math.color'; import { Vector3 } from '@babylonjs/core/Maths/math.vector'; import { Monobehiver } from '../base/Monobehiver'; /** * 地面网格配置接口 */ export interface GroundConfig { /** 地面宽度 */ width?: number; /** 地面深度 */ height?: number; /** 网格细分数 */ subdivisions?: number; /** 贴图URL */ textureUrl?: string; /** 贴图平铺次数 (uScale, vScale) */ textureScale?: { u: number; v: number }; /** 地面颜色 (当没有贴图时使用) */ color?: Color3; /** 是否接收阴影 */ receiveShadows?: boolean; /** 地面位置 */ position?: Vector3; /** 是否显示网格 */ showGrid?: boolean; /** 网格线颜色 */ gridColor?: Color3; /** 网格大小 */ gridRatio?: number; } /** * 地面网格管理类 - 负责创建和管理地面网格 */ export class AppGround extends Monobehiver { ground: Mesh | null; material: PBRMaterial | null; gridGround: Mesh | null; gridMaterial: GridMaterial | null; private config: GroundConfig; constructor(mainApp: any, config: GroundConfig = {}) { super(mainApp); this.ground = null; this.material = null; this.gridGround = null; this.gridMaterial = null; this.config = { width: 100, height: 100, subdivisions: 10, receiveShadows: true, position: new Vector3(0, 0, 0), textureScale: { u: 10, v: 10 }, color: new Color3(0.5, 0.5, 0.5), textureUrl: "https://cdn.files.zguiy.com/zt/ground1.jpg", // 默认贴图 showGrid: true, // 默认显示网格 gridColor: new Color3(1,1,1), gridRatio: 1.0, ...config }; } /** 初始化地面网格 */ Awake(): void { this.createGround(); this.createMaterial(); if (this.config.showGrid) { this.createGridGround(); } } /** 创建地面网格 */ private createGround(): void { if (!this.mainApp.appScene.object) { console.error('场景未初始化'); return; } this.ground = MeshBuilder.CreateGround( 'ground', { width: this.config.width, height: this.config.height, subdivisions: this.config.subdivisions }, this.mainApp.appScene.object ); if (this.config.position) { this.ground.position = this.config.position; } if (this.config.receiveShadows) { this.ground.receiveShadows = true; } } /** 创建材质 */ private createMaterial(): void { if (!this.ground || !this.mainApp.appScene.object) return; this.material = new PBRMaterial('groundMaterial', this.mainApp.appScene.object); // 如果有贴图URL,加载贴图 if (this.config.textureUrl) { const texture = new Texture( this.config.textureUrl, this.mainApp.appScene.object ); // 设置贴图平铺 if (this.config.textureScale) { texture.uScale = this.config.textureScale.u; texture.vScale = this.config.textureScale.v; } this.material.albedoTexture = texture; } else { // 没有贴图时使用纯色 this.material.albedoColor = this.config.color || new Color3(1,1,1); } // PBR 材质属性设置 this.material.metallic = 0.0; // 非金属 this.material.roughness = 1.0; // 粗糙表面 this.ground.material = this.material; } /** 创建网格地面 */ private createGridGround(): void { if (!this.mainApp.appScene.object) return; // 创建网格地面,位置稍微高一点避免z-fighting this.gridGround = MeshBuilder.CreateGround( 'gridGround', { width: this.config.width, height: this.config.height, subdivisions: this.config.subdivisions }, this.mainApp.appScene.object ); // 设置位置,稍微高于贴图地面 const gridPosition = this.config.position ? this.config.position.clone() : new Vector3(0, 0, 0); gridPosition.y += 0.01; // 抬高0.01单位避免z-fighting this.gridGround.position = gridPosition; // 创建网格材质 this.gridMaterial = new GridMaterial('gridMaterial', this.mainApp.appScene.object); this.gridMaterial.mainColor = this.config.gridColor || new Color3(0.3, 0.3, 0.3); this.gridMaterial.lineColor = this.config.gridColor || new Color3(0.3, 0.3, 0.3); this.gridMaterial.gridRatio = this.config.gridRatio || 1.0; this.gridMaterial.opacity = 0.8; this.gridMaterial.backFaceCulling = false; this.gridGround.material = this.gridMaterial; } /** 更新贴图 */ setTexture(textureUrl: string, uScale: number = 10, vScale: number = 10): void { if (!this.material || !this.mainApp.appScene.object) return; const texture = new Texture(textureUrl, this.mainApp.appScene.object); texture.uScale = uScale; texture.vScale = vScale; this.material.albedoTexture = texture; } /** 更新地面颜色 */ setColor(color: Color3): void { if (!this.material) return; this.material.albedoColor = color; } /** 显示/隐藏地面 */ setVisible(visible: boolean): void { if (this.ground) { this.ground.isVisible = visible; } if (this.gridGround) { this.gridGround.isVisible = visible; } } /** 显示/隐藏网格 */ setGridVisible(visible: boolean): void { if (this.gridGround) { this.gridGround.isVisible = visible; } } /** 销毁地面 */ dispose(): void { if (this.ground) { this.ground.dispose(); this.ground = null; } if (this.material) { this.material.dispose(); this.material = null; } if (this.gridGround) { this.gridGround.dispose(); this.gridGround = null; } if (this.gridMaterial) { this.gridMaterial.dispose(); this.gridMaterial = null; } } }