///
///
///
declare var Stats; // Stats.jsのため
module demo {
// Away3Dライブラリを読み込み
import View3D = away.containers.View3D;
import TextureMaterial = away.materials.TextureMaterial;
import ColorMaterial = away.materials.ColorMaterial;
import SphereGeometry = away.primitives.SphereGeometry;
import PlaneGeometry = away.primitives.PlaneGeometry;
import Geometry = away.base.Geometry;
import Mesh = away.entities.Mesh;
import DirectionalLight = away.lights.DirectionalLight;
import PointLight = away.lights.PointLight;
import RequestAnimationFrame = away.utils.RequestAnimationFrame;
import StaticLightPicker = away.materials.StaticLightPicker;
import HTMLImageElementTexture = away.textures.HTMLImageElementTexture;
import HoverController = away.controllers.HoverController;
import Sprite3D = away.entities.Sprite3D;
import ParticleAnimationSet = away.animators.ParticleAnimationSet;
import ParticleAnimator = away.animators.ParticleAnimator;
import ParticleBillboardNode = away.animators.ParticleBillboardNode;
import ParticleInitialColorNode = away.animators.ParticleInitialColorNode;
import ParticlePositionNode = away.animators.ParticlePositionNode;
import ParticleProperties = away.animators.ParticleProperties;
import ParticlePropertiesMode = away.animators.ParticlePropertiesMode;
import ParticleVelocityNode = away.animators.ParticleVelocityNode;
import ParticleColorNode = away.animators.ParticleColorNode;
import ParticleFollowNode = away.animators.ParticleFollowNode;
import ParticleScaleNode = away.animators.ParticleScaleNode;
import ParticleGeometry = away.base.ParticleGeometry;
import ParticleGeometryHelper = away.tools.ParticleGeometryHelper;
import ParticleGeometryTransform = away.tools.ParticleGeometryTransform;
import Vector3D = away.geom.Vector3D;
import ColorTransform = away.geom.ColorTransform;
import Object3D = away.base.Object3D;
import PerspectiveLens = away.cameras.PerspectiveLens;
import ObjectContainer3D = away.containers.ObjectContainer3D;
import BlendMode = away.display.BlendMode;
import Cast = away.utils.Cast;
import WireframePlane = away.primitives.WireframePlane;
import AssetLibrary = away.library.AssetLibrary;
import Texture2DBase = away.textures.Texture2DBase;
import LoaderEvent = away.events.LoaderEvent;
import URLRequest = away.net.URLRequest;
import FogMethod = away.materials.FogMethod;
import TextureMultiPassMaterial = away.materials.TextureMultiPassMaterial;
var ROUND:number = 100;
var NUM_FIRES:number = 25;
var GROUND_Y:number = -300;
var LENS_FRARE_Z:number = 750;
var RESOURCE_LIST:string[] = [
"imgs/blue.png",
"imgs/floor_diffuse.jpg",
"imgs/floor_normal.jpg",
"imgs/floor_specular.jpg",
"imgs/lens_frare.png",
"imgs/lens_frare_active.png",
];
export class Main extends away.containers.View3D {
private _loadedCount = 0;
private cameraController:HoverController;
private fireAnimationSet:ParticleAnimationSet
private fireObjects:FireVO[] = [];
private collisions:ObjectContainer3D[];
private lastMouseX:number;
private lastMouseY:number;
private lastPanAngle:number;
private lastTiltAngle:number;
private isMouseDown:boolean;
private lightDirectional:DirectionalLight;
private lightPicker:StaticLightPicker;
private particleFollowNode:ParticleFollowNode;
private particleGeometry:ParticleGeometry;
private particleMaterial:TextureMaterial;
private particleScaleNode:ParticleScaleNode;
private planeMaterial:TextureMultiPassMaterial;
private particleSpriteMaterial:TextureMaterial;
private particleActSpriteMaterial:TextureMaterial;
private stats:any;
constructor() {
super();
var touchManager = new utils.TouchManager();
touchManager.enableTouch();
touchManager.addListener(document.body);
this.onResize();
this.render();
// Import Assets
AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, this.onResourceCompelte, this);
for (var i = 0; i < RESOURCE_LIST.length; i++) {
AssetLibrary.load(new URLRequest(RESOURCE_LIST[i]));
}
}
onResourceCompelte(event:LoaderEvent) {
this._loadedCount++;
if (this._loadedCount < RESOURCE_LIST.length)
return;
this.init();
}
init() {
( this.camera.lens).fieldOfView = 70;
( this.camera.lens).far = 20000;
//setup controller to be used on the camera
this.cameraController = new HoverController(this.camera);
this.cameraController.minTiltAngle = -6;
this.cameraController.maxTiltAngle = 30;
this.cameraController.panAngle = 45;
this.cameraController.tiltAngle = 5;
this.cameraController.steps = 20;
this.reset();
this.initLights();
this.initMaterials();
this.initParticles();
this.initObjects();
this.initListeners();
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(60);
this.stats = new Stats();
document.body.appendChild(this.stats.domElement);
}
/**
* Initialise the listeners
*/
private initListeners() {
// アニメーションさせるためにループイベントを指定します
var raf = new RequestAnimationFrame(this.enterFrameHandler, this);
raf.start();
document.onmousedown = (event) => this.onMouseDown(event);
document.onmouseup = (event) => this.onMouseUp(event);
document.onmousemove = (event) => this.onMouseMove(event);
window.onresize = (event) => this.onResize();
}
/**
* Initialise the lights
*/
private initLights() {
this.lightDirectional = new DirectionalLight(0, -1, 0.1);
this.lightDirectional.castsShadows = false;
this.lightDirectional.color = 0x993300;
this.lightDirectional.diffuse = 1;
this.lightDirectional.ambient = .0;
this.lightDirectional.specular = 0.25;
this.lightDirectional.ambientColor = 0x0;
this.scene.addChild(this.lightDirectional);
this.lightPicker = new StaticLightPicker([this.lightDirectional]);
}
/**
* Initialise the materials
*/
private initMaterials() {
var fog:FogMethod = new FogMethod(1000, 4500, 0x0);
this.planeMaterial = new TextureMultiPassMaterial( AssetLibrary.getAsset(RESOURCE_LIST[1]));
this.planeMaterial.specularMap = AssetLibrary.getAsset(RESOURCE_LIST[3]);
this.planeMaterial.normalMap = AssetLibrary.getAsset(RESOURCE_LIST[2]);
this.planeMaterial.lightPicker = this.lightPicker;
this.planeMaterial.repeat = true;
this.planeMaterial.smooth = false;
this.planeMaterial.mipmap = false;
this.planeMaterial.specular = 15;
this.planeMaterial.addMethod(fog);
this.particleMaterial = new TextureMaterial( AssetLibrary.getAsset(RESOURCE_LIST[0]));
this.particleMaterial.blendMode = BlendMode.ADD;
this.particleMaterial.smooth = false;
this.particleMaterial.mipmap = false;
this.particleMaterial.alphaBlending = false;
this.particleSpriteMaterial = new TextureMaterial( AssetLibrary.getAsset(RESOURCE_LIST[4]));
this.particleSpriteMaterial.blendMode = BlendMode.ADD;
this.particleActSpriteMaterial = new TextureMaterial( AssetLibrary.getAsset(RESOURCE_LIST[5]));
this.particleActSpriteMaterial.blendMode = BlendMode.ADD;
}
private fireSprite:Sprite3D[];
private fireActSprite:Sprite3D[];
/**
* Initialise the particles
*/
private initParticles() {
//create the particle animation set
this.fireAnimationSet = new ParticleAnimationSet(true, true);
//add some animations which can control the particles:
//the global animations can be set directly, because they influence all the particles with the same factor
this.fireAnimationSet.addAnimation(new ParticleBillboardNode());
this.fireAnimationSet.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.LOCAL_STATIC));
this.fireAnimationSet.addAnimation(this.particleScaleNode = new ParticleScaleNode(ParticlePropertiesMode.GLOBAL, false, false, 2, 0.5));
this.fireAnimationSet.addAnimation(this.particleFollowNode = new ParticleFollowNode(true, false));
// ParticleAccelerationNode はバグのため利用していない
this.fireAnimationSet.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL, true, true, false, false, new ColorTransform(0, 0, 0, 1, 0xFF, 0x66, 0x22), new ColorTransform(0, 0, 0, 1, 0x99)));
//no need to set the local animations here, because they influence all the particle with different factors.
this.fireAnimationSet.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.LOCAL_STATIC));
//set the initParticleFunc. It will be invoked for the local static property initialization of every particle
this.fireAnimationSet.initParticleFunc = (prop) => this.initParticleFunc(prop);
//create the original particle geometry
var particle:Geometry = new PlaneGeometry(50, 50, 1, 1, false);
//combine them into a list
var geometrySet:Geometry[] = [];
for (var i:number = 0; i < 50; i++)
geometrySet.push(particle);
this.particleGeometry = ParticleGeometryHelper.generateGeometry(geometrySet);
}
/**
* Initialise the scene objects
*/
private initObjects() {
// create the terrain mesh
var plane:Mesh = new Mesh(new PlaneGeometry(6000, 6000), this.planeMaterial);
plane.geometry.scaleUV(8, 8);
plane.y = GROUND_Y;
this.scene.addChild(plane);
// reate fire object meshes from geomtry and material, and apply particle animators to each
for (var i:number = 0; i < NUM_FIRES; i++) {
var particleMesh:Mesh = new Mesh(this.particleGeometry, this.particleMaterial);
var animator:ParticleAnimator = new ParticleAnimator(this.fireAnimationSet);
particleMesh.animator = animator;
animator.start();
this.particleFollowNode.getAnimationState(animator).followTarget = this.collisions[i];
//create a fire object and add it to the fire object vector
var fireObject:FireVO = new FireVO(particleMesh, animator);
this.fireObjects.push(fireObject);
this.scene.addChild(particleMesh);
this.createFireLight(fireObject);
}
var particleMain:Mesh = new Mesh(this.particleGeometry, this.particleMaterial);
particleMain.y = GROUND_Y;
var animatorMain:ParticleAnimator = new ParticleAnimator(this.fireAnimationSet);
this.particleScaleNode.getAnimationState(animatorMain).maxScale = 15;
particleMain.animator = animatorMain;
animatorMain.start();
this.scene.addChild(particleMain);
this.fireSprite = [];
this.fireActSprite = [];
for (var i = 0; i < NUM_FIRES; i++) {
var obj = new away.entities.Sprite3D(this.particleSpriteMaterial, 512 * 2, 512 * 2);
obj.position = this.resetPosition();
this.scene.addChild(obj);
this.fireSprite[i] = obj;
var obj = new away.entities.Sprite3D(this.particleActSpriteMaterial, 512 * 3, 512 * 3);
obj.position = this.resetPosition();
this.scene.addChild(obj);
this.fireActSprite[i] = obj;
}
}
/**
* Returns an array of active lights in the scene
*/
private getAllLights() {
var lights = [];
lights.push(this.lightDirectional);
for (var i = 0; i < this.fireObjects.length; i++) {
var fireVO:FireVO = this.fireObjects[i];
if (fireVO.light)
lights.push(fireVO.light);
}
return lights;
}
/**
* Timer event handler
*/
private createFireLight(fireObject:FireVO) {
//start the animator
// fireObject.animator.start();
//create the lightsource
var light:PointLight = new PointLight();
light.color = 0xFF6622;
light.diffuse = 0;
light.specular = 0;
light.position = fireObject.mesh.position;
//add the lightsource to the fire object
fireObject.light = light;
//update the lightpicker
this.lightPicker.lights = this.getAllLights();
}
/**
* Initialiser function for particle properties
*/
private initParticleFunc(prop:ParticleProperties) {
prop.startTime = Math.random() * 2;
prop.duration = Math.random() * 0.6 + 0.1;
var r:number = 600;
prop[ParticleVelocityNode.VELOCITY_VECTOR3D] = new Vector3D(
r * (Math.random() - 0.5),
r * (Math.random() - 0.5) + 1000,
r * (Math.random() - 0.5));
r = 10;
prop[ParticlePositionNode.POSITION_VECTOR3D] = new Vector3D(
r * (Math.random() - 0.5),
r * (Math.random() - 0.5),
r * (Math.random() - 0.5));
}
private enterFrameHandler(e:Event) {
this.stats.begin();
//animate lights
var fireVO:FireVO;
for (var i:number = 0; i < this.fireObjects.length; i++) {
fireVO = this.fireObjects[i];
//update flame light
var light:PointLight = fireVO.light;
if (fireVO.strength < 1)
fireVO.strength += 0.1;
if (light == null)
continue;
light.fallOff = 1080 + Math.random() * 20;
light.radius = 1;
light.diffuse = light.specular = fireVO.strength + Math.random() * .2;
light.position = this.collisions[i].position;
// 火の粉
this.fireSprite[i].position = this.collisions[i].position;
this.fireActSprite[i].position = this.collisions[i].position;
this.fireActSprite[i].visible = this.camera.project(this.fireActSprite[i].position).z < LENS_FRARE_Z && this.fireActSprite[i].y > 200; // 原点より手間に来たら
}
this.particleSpriteMaterial.alpha = Math.random() * 0.1 + 0.9;
this.particleActSpriteMaterial.alpha = Math.random() * 0.2 + 0.8;
this.render();
this.stats.end();
}
private reset() {
if (this.collisions == null) {
this.collisions = [];
for (var i = 0; i < NUM_FIRES; i++) {
// create cylinders
var skin:ObjectContainer3D = new ObjectContainer3D();
//skin.addChild(new away.primitives.WireframeSphere()); // For Debug
skin.position = this.resetPosition();
this.scene.addChild(skin);
this.collisions.push(skin);
var delay:number = 6000 * Math.random();
// 火の粉
new createjs.Timeline([
// 拡散
createjs.Tween.get(skin)
.wait(delay)
.to({
x: 5000 * (Math.random() - 0.5),
z: 5000 * (Math.random() - 0.5)
}, 6000, createjs.Ease.sineOut)
.set({x: 0, y: GROUND_Y, z: 0}),
// 高さ
createjs.Tween.get(skin)
.wait(delay)
.to({
y: 500 + 500 * Math.random()
}, 2000, createjs.Ease.cubicOut)
.to({
y: GROUND_Y
}, 4000, createjs.Ease.bounceOut)
], null, {loop: true}).gotoAndPlay(0);
}
}
for (i = 0; i < this.collisions.length; i++) {
// create cylinders
var body = this.collisions[i];
body.position = this.resetPosition();
}
}
private resetPosition():Vector3D {
return new Vector3D(ROUND * (Math.random() - 0.5), GROUND_Y, ROUND * (Math.random() - 0.5))
}
/** マウスを押したとき */
private onMouseDown(event) {
this.lastPanAngle = this.cameraController.panAngle;
this.lastTiltAngle = this.cameraController.tiltAngle;
this.lastMouseX = event.clientX;
this.lastMouseY = event.clientY;
this.isMouseDown = true;
}
/** マウスを離したとき */
private onMouseUp(event) {
this.isMouseDown = false;
}
/** マウスを動かした時 */
private onMouseMove(event) {
if (this.isMouseDown) {
this.cameraController.panAngle = 0.4 * (event.clientX - this.lastMouseX) + this.lastPanAngle;
this.cameraController.tiltAngle = 0.4 * (event.clientY - this.lastMouseY) + this.lastTiltAngle;
}
}
private onResize() {
this.width = window.innerWidth;
this.height = window.innerHeight;
}
}
/**
* Data class for the fire objects
*/
class FireVO {
constructor(mesh:Mesh, animator:ParticleAnimator) {
this.mesh = mesh;
this.animator = animator;
}
animator:ParticleAnimator;
light:PointLight;
mesh:Mesh;
strength:number = 0;
}
}
window.onload = ()=> {
new demo.Main();
}