175 lines
5.4 KiB
Markdown
175 lines
5.4 KiB
Markdown
|
|
|||
|
* 草动画(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加载这个场景,查看草的动画。
|