egret-docs-master/Engine3D/Effect/Grass/README.md

175 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

2024-06-19 13:32:32 +08:00
* 草动画(GrassMesh)
* 用来模拟实现风吹草动的效果;
* 加入受角色对草产生的挤压效果;
* 结合Egret3D的地形数据可以通过Unity4导出场景中的草模型
* GrassMethod由GrassMesh自动生成不建议您在外部创建这个对象。
----------
module egret3d {
export class Class_GrassMesh extends Class_View3D {
protected view1: View3D;
protected cameraCrl: LookAtController;
private _grass: GrassMesh;
private _lightFromBall: Mesh;
private _lightVector: Vector3D;
constructor() {
super();
this._egret3DCanvas.addEventListener(Event3D.ENTER_FRAME, this.update, this);
this.view1 = new View3D(0, 0, window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio);
this.view1.backColor = 0xff000000;
this._egret3DCanvas.addView3D(this.view1);
var bgImg: HTMLImageElement = <HTMLImageElement>document.getElementById("bg");
var tex: ImageTexture = new ImageTexture(bgImg);
this.cameraCrl = new LookAtController(this.view1.camera3D, new Object3D());
this.cameraCrl.distance = 600;
this.cameraCrl.rotationX = 60;
this._lightFromBall = new Mesh(new SphereGeometry(20));
this.view1.addChild3D(this._lightFromBall);
this.initGrass();
}
private parseDistribution(image:ImageData): Vector3D[] {
var width: number = image.width;
var height: number = image.height;
var color: number;
var offset: number;
var ratio: number = 1 / 16;
var positions: Vector3D[] = [];
for (var i: number = 0; i < width; i++) {
for (var j: number = 0; j < height; j++) {
offset = i * width + j;
offset *= 4;
color = image.data[offset] * ratio;
color = Math.round(color);
if (color > 0) {
this.getPosition(i, j, color, positions);
}
}
}
return positions;
}
private getPosition(i: number, j: number, count: number, positions: Vector3D[]): void {
var pos: Vector3D;
for (var i: number = 0; i < count; i++) {
//随机一个值
pos = new Vector3D(i, 0, j);
positions.push(pos);
}
}
private initGrass(): void {
var positions: Vector3D[] = this.createPositions();
var mat: TextureMaterial = new TextureMaterial();
mat.ambientColor = 0xffffff;
mat.blendMode = BlendMode.NORMAL;
mat.cutAlpha = 0.4;
var data: GrassData = new GrassData();
data.minWidth = 30;
data.maxWidth = 70;
data.minHeight = 30;
data.maxHeight = 70;
data.noiseSpread = 1;
data.billboard = false;
data.healthyColor = "0x00ff00";
data.dryColor = "0xff8000";
this._grass = new GrassMesh(positions, mat, data);
this._grass.y = 20;
this.view1.addChild3D(this._grass);
var loadtex: URLLoader = new URLLoader("resource/scene/plant/leaf.png");
loadtex.addEventListener(LoaderEvent3D.LOADER_COMPLETE, this.onLoadTexture, this);
loadtex["mat"] = mat;
}
private createPositions(): Vector3D[] {
var plane: PlaneValueShape = new PlaneValueShape();
plane.width = 1000;
plane.height = 1000;
var positions: Vector3D[] = plane.calculate(1000);
return positions;
}
protected onLoadTexture(e: LoaderEvent3D) {
e.loader["mat"].diffuseTexture = e.loader.data;
}
private anlge: number = 0;
private dirLight: DirectLight;
private position: Vector3D = new Vector3D();
public update(e: Event3D) {
this.cameraCrl.update();
this.anlge += 0.01;
this.position.setTo(Math.sin(this.anlge) * 300, 10, Math.cos(this.anlge) * 300);
this._lightFromBall.position = this.position;
if (this._grass) {
this._grass.method.updateSqueezeData(this.position, true, 60, 1);
}
}
}
}
示例展示为草动画受小球的挤压影响效果
![](grassAnim.gif)
----------
* Unity中导出草的步骤
* 创建地形对象
![](grass1.png)
* 使Terrain处于选中状态点击草的图标获得当前为刷草模式
![](grass2.png)
* 点击Edit Details进入草动画详细编辑模式
![](grass3.png)
* 点击Add Grass Texture获得新建一组草的动画
![](grass4.png)
* 在弹开的编辑草详细内容界面中编辑贴图调整各个属性完成后点击Add按钮草动画详细信息确认成功
![](grass5.png)
* 于场景中地形区域,按住鼠标不放松,然后滑动鼠标,开始执行刷草
![](grass6.png)
* 编辑完毕后使用Egret3D提供的场景导出插件导出当前场景。
![](grass7.png)
* 最后用Egret3D的UnitLoader加载这个场景查看草的动画。