Files
zhengte.babylonjs-sdk/src/babylonjs/AppGround.ts

221 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}