In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

[Alternativa3D 7.5] test

Get Adobe Flash player
by tencho 23 Oct 2012
  • Related works: 4
  • Talk

    makc3d at 04 Oct 2010 17:48
    1076 faces 9...14 /60 fps. boy, does my hardware suck :)
    makc3d at 04 Oct 2010 17:50
    ah, wait, BSPContainer, rrrright...
    tencho at 04 Oct 2010 20:15
    9fps!? Object3D's blendMode and BSP sorting are working so slow...
    makc3d at 05 Oct 2010 03:19
    you could get way better fps with mixed sorting, because there will be less polys (bsp thing cuts stuff making it more polys than you'd think)
    tencho at 05 Oct 2010 05:38
    i think blendMode is the cause.(i added checkboxes) light:off+reflection:off+bsp:on 60/60fps
    makc3d at 05 Oct 2010 15:41
    I dont get here more than 25...30 with all boxes off. "reflection" alone doesnt take much fps either, but it gets down to 7...15 fps with "volume light" alone.
    katopz at 05 Oct 2010 21:03
    why BSP still calculate when camera not dirty? is that expected behavior?
    bradsedito at 06 Oct 2010 10:05
    Everything working beautifully on my end. Awesome job.
    makc3d at 06 Oct 2010 15:30
    @katopz, yes, and this is in fact optimization for scenes where camera is almost never dirty (such as in tanki game)
    tencho at 07 Oct 2010 18:45
    @makc3d i'm late. thanks for your report. @bradsedito thanks!
    focus at 18 Feb 2011 23:38
    Volume light cuts fps from 60 to approx 30 for me.
    heterfire at 04 Sep 2011 14:41
    Hello, I use my own model, you can not achieve the effect, I guess it is model of the problem, DAE file you can give me look it? Can send me a 3dMax file, my mail heterfire@gmail.com, thank you!

    Tags

    Embed
/**
 * Copyright tencho ( http://wonderfl.net/user/tencho )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eZbi
 */

/**
 * Alternativa3D7.5の練習
 * Colladaモデルを読み込んでカメラを動かしているだけです
 * カメラの位置によってはエラーが出てしまうみたいで時々固まります。。
 */
package  {
	import alternativ7.engine3d.containers.BSPContainer;
	import alternativ7.engine3d.controllers.SimpleObjectController;
	import alternativ7.engine3d.core.Camera3D;
	import alternativ7.engine3d.core.Object3D;
	import alternativ7.engine3d.core.Sorting;
	import alternativ7.engine3d.core.View;
	import alternativ7.engine3d.loaders.events.LoaderErrorEvent;
	import alternativ7.engine3d.loaders.events.LoaderProgressEvent;
	import alternativ7.engine3d.loaders.MaterialLoader;
	import alternativ7.engine3d.loaders.ParserCollada;
	import alternativ7.engine3d.materials.FillMaterial;
	import alternativ7.engine3d.materials.TextureMaterial;
	import alternativ7.engine3d.objects.Mesh;
	import com.bit101.components.CheckBox;
	import com.bit101.components.Label;
	import com.bit101.components.Style;
	import com.bit101.components.VBox;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.ColorTransform;
	import flash.geom.Vector3D;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.Security;
	import flash.utils.Dictionary;
	import net.hires.debug.Stats;
	import org.libspark.betweenas3.BetweenAS3;
	import org.libspark.betweenas3.easing.Quad;
	import org.libspark.betweenas3.tweens.ITween;
	import org.libspark.betweenas3.tweens.ITweenGroup;
	public class Alternativa3DTest extends Sprite {
		private var _autoCamera:Object3D = new Object3D();
		private var _userCamera:Object3D = new Object3D();
		private var _cameraMode:int = 0;
		private var _camera:Camera3D;
		private var _controller:SimpleObjectController;
		private var _scene:BSPContainer;
		private var _dragger:GlobeDragger;
		
		private var _stats:Stats;
		private var _bg:Sprite;
		private var _header:Sprite;
		private var _info:Label;
		private var _loadingTxt:Label;
		private var _wireMaterial:FillMaterial = new FillMaterial(0, 0, 0, 0xffffff);
		private var _rawTextures:Dictionary = new Dictionary();
		
		private var _loader:URLLoader;
		private var _parser:ParserCollada;
		private var _mloader:MaterialLoader;
		private var _isInitError:Boolean = false;
		
		private const PATH_POLICY:String = "http://shelter.s377.xrea.com/crossdomain.xml";
		private const PATH_DIR:String = "http://shelter.s377.xrea.com/assets/wonderfl/alt3dtest/";
		private const PATH_DAE:String = "model_wdfl.DAE";
		
		/**
		 * コンストラクタ
		 */
		public function Alternativa3DTest() {
			stage.frameRate = 60;
			stage.quality = StageQuality.LOW;
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.addEventListener(Event.RESIZE, onResize);
			
			_camera = new Camera3D();
			_camera.view = new View(465, 465);
			_camera.view.alpha = 0;
			_controller = new SimpleObjectController(stage, _camera, 1);
						
			_scene = new BSPContainer();
			_scene.addChild(_camera);
			
			//マウスドラッグで動かすカメラ用
			_dragger = new GlobeDragger(this, 45, 2, 320);
			_dragger.enabled = false;
			_dragger.wheelEnabled = false;
			_dragger.angleSpeed = _dragger.rotationSpeed = 0.75;
			_dragger.setAngleLimit( -7, 90);
			_dragger.setDistanceLimit(10, 420);
			
			var v:Vector3D = _dragger.position;
			_userCamera.x = v.x;
			_userCamera.y = v.z;
			_userCamera.z = v.y;
			
			//画面に配置するもの色々
			_bg = Painter.createColorRect(465, 465, 0x000000);
			_header = new Sprite();
			_header.addChild(Painter.createColorRect(465, 40, 0, 0.5));
			Style.LABEL_TEXT = 0x000000;
			new SwitchButton(_header, 10, 10, ["CAMERA : AUTO", "CAMERA : DRAG"], onSwitchCamera);
			new SwitchButton(_header, 120, 10, ["WIREFRAME : OFF", "WIREFRAME : ON"], onSwitchMaterial);
			Style.LABEL_TEXT = 0xFFFFFF;
			_info = new Label(_header, 230, 10, "");
			_loadingTxt = new Label(null, 10, 10, "LOADING COLLADA MODEL ...");
			_stats = new Stats( { bg:0x222222 } );
			Style.BACKGROUND = 0x444444;
			var vox:VBox = new VBox(_header);
			vox.x = 8;
			vox.y = 50;
			vox.spacing = 12;
			for (var i:int = 0; i < 3; i++) {
				var chk:CheckBox = new CheckBox(vox, 0, 0, ["VOLUME LIGHT", "REFLECTION", "BSP SORTING"][i], onClickCheckBox);
				chk.tag = i;
				chk.selected = true;
			}
			addChild(_bg);
			addChild(_loadingTxt);
			addChild(_camera.view);
			addChild(_header);
			addChild(_stats);
			
			_header.visible = false;
			
			onResize(null);
			startLoad();
		}
		private function onClickCheckBox(e:MouseEvent):void{
			var rb:CheckBox = e.currentTarget as CheckBox;
			switch(rb.tag) {
				case 0:
					_scene.getChildByName("volumelight").visible = rb.selected;
					break;
				case 1:
					_scene.getChildByName("floor").blendMode = (rb.selected)? BlendMode.ADD : BlendMode.NORMAL;
					break;
				case 2:
					setBSPEnabled(rb.selected);
					break;
			}
		}
		/**
		 * BSPソートとZソートを切り替える
		 * @param	enabled
		 */
		private function setBSPEnabled(enabled:Boolean):void{
			for (var i:int = 0; i < _scene.numChildren; i++) {
				var m:Mesh = _scene.getChildAt(i) as Mesh;
				if (!m) continue;
				if (["floor", "sunlight", "containerbox", "truss", "poles"].indexOf(m.name) != -1) {
					m.sorting = (enabled)? Sorting.DYNAMIC_BSP : Sorting.AVERAGE_Z;
				}
			}
		}
		/**
		 * カメラモード切り替え
		 */
		private function onSwitchCamera(e:MouseEvent, mode:int):void {
			_cameraMode = mode;
			_dragger.enabled = (_cameraMode == 1);
			onTick(null);
		}
		/**
		 * マテリアル張り替え
		 */
		private function onSwitchMaterial(e:MouseEvent, mode:int):void {
			for (var i:int = 0; i < _scene.numChildren; i++) {
				var o:Object3D = _scene.getChildAt(i);
				if (o is Mesh) {
					var m:Mesh = o as Mesh;
					m.setMaterialToAllFaces(mode? _wireMaterial : _rawTextures[m]);
				}
			}
			_camera.render();
		}
		/**
		 * 画面リサイズ時
		 */
		private function onResize(e:Event):void {
			var sw:Number = stage.stageWidth;
			var sh:Number = stage.stageHeight;
			_bg.width = sw;
			_bg.height = sh;
			_stats.y = sh - 100;
			_camera.view.width = sw;
			_camera.view.height = sh;
			_camera.render();
			_header.getChildAt(0).width = sw;
		}
		/**
		 * Collada読み込み開始
		 */
		private function startLoad():void {
			Security.loadPolicyFile(PATH_POLICY);
			_loader = new URLLoader();
			_loader.addEventListener(Event.COMPLETE, onLoadCollada);
			_loader.addEventListener(IOErrorEvent.IO_ERROR, onErrorAsset);
			_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onErrorAsset);
			_loader.load(new URLRequest(PATH_DIR + PATH_DAE));
		}
		private function onErrorAsset(e:ErrorEvent):void {
			_loadingTxt.text = e.text;
			_loadingTxt.transform.colorTransform = new ColorTransform(0, 0, 0, 1, 0xFF, 0, 0);
			_isInitError = true;
		}		
		/**
		 * Colladaモデル読み込み完了時
		 * @param	e
		 */
		private function onLoadCollada(e:Event):void {
			//Colladaファイルをパース
			_parser = new ParserCollada();
			_parser.parse(new XML(_loader.data), PATH_DIR);
			
			//テクスチャ読み込み
			_mloader = new MaterialLoader();
			_mloader.addEventListener(LoaderErrorEvent.LOADER_ERROR, onErrorAsset);
			_mloader.addEventListener(LoaderProgressEvent.LOADER_PROGRESS, onProgressMaterial);
			_mloader.addEventListener(Event.COMPLETE, onCompleteMaterial);
			_mloader.load(_parser.textureMaterials, new LoaderContext(true));
		}
		private function onProgressMaterial(e:LoaderProgressEvent):void {
			if (_isInitError) return;
			var per:Number = e.totalProgress;
			_loadingTxt.text = "LOADING COLLADA MODEL ... " + int(per * 100) + "%";
		}
		/**
		 * テクスチャ読み込み完了時
		 * @param	e
		 */
		private function onCompleteMaterial(e:Event):void {
			//マテリアルの読み込みに失敗していたら処理停止
			if (_isInitError) return;
			addEventListener(Event.ENTER_FRAME, onTick);
			//黒画面からのフェードイン
			BetweenAS3.to(_camera.view, { alpha:1 }, 2, Quad.easeIn).play();
			_header.visible = true;
			_loadingTxt.visible = false;
			
			//全テクスチャのリピートをOFFにする
			for each(var tm:TextureMaterial in _parser.textureMaterials) tm.repeat = false;
			
			//天井からの光の筋
			_parser.getObjectByName("volumelight").blendMode = BlendMode.OVERLAY;
			//床
			_parser.getObjectByName("floor").blendMode = BlendMode.ADD;
			
			var totalFaceNum:int = 0;
			var cameras:Vector.<Object3D> = new Vector.<Object3D>();
			
			for each(var o:Object3D in _parser.objects) {
				if (!o.name) continue;
				_scene.addChild(o);
				if (o is Mesh) {
					var m:Mesh = o as Mesh;
					_rawTextures[m] = m.geometry.orderedFaces[0].material;
					totalFaceNum += m.geometry.orderedFaces.length;
				} else if (o.name.indexOf("Camera") != -1) {
					//カメラリストに追加
					cameras.push(o);
				}
			}
			setBSPEnabled(true);
			_info.text = "TOTAL FACES: " + totalFaceNum;
			//カメラリストを名前順にソート
			cameras.sort(function(a:Object3D, b:Object3D):int { return int(a.name > b.name) - int(a.name < b.name) } );
			
			//自動カメラの動きをBetweenAS3で設定する
			var list:Array = [];
			var leng:int = cameras.length;
			for (var i:int = 0; i < leng; i++) {
				var cf:Object3D = cameras[i];
				var ct:Object3D = cameras[(i + 1) % leng];
				var it:ITween = BetweenAS3.tween(
					_autoCamera,
					{ x:ct.x, y:ct.y, z:ct.z, rotationX:ct.rotationX, rotationY:ct.rotationY, rotationZ:ct.rotationZ },
					{ x:cf.x, y:cf.y, z:cf.z, 
						rotationX:Angle.toNearRadian(cf.rotationX, ct.rotationX),
						rotationY:Angle.toNearRadian(cf.rotationY, ct.rotationY),
						rotationZ:Angle.toNearRadian(cf.rotationZ, ct.rotationZ)
					},
					2.5,
					Quad.easeInOut
				);
				it = BetweenAS3.delay(it, 0.5, 0);
				list.push(it);
			}
			if (leng) {
				var itg:ITweenGroup = BetweenAS3.serialTweens(list);
				itg.stopOnComplete = false;
				itg.play();
			}
			
			onResize(null);
		}
		/**
		 * 毎フレーム処理
		 * @param	e
		 */
		private function onTick(e:Event):void {
			if (_cameraMode == 0) {
				//自動カメラモード
				_controller.setObjectPosXYZ(_autoCamera.x, _autoCamera.y, _autoCamera.z);
				_controller.lookAtXYZ(0, 0, 0);
				_camera.rotationX = _autoCamera.rotationX;
				_camera.rotationY = _autoCamera.rotationY;
				_camera.rotationZ = _autoCamera.rotationZ;
			} else {
				//ドラッグカメラモード
				var v:Vector3D = _dragger.position;
				_userCamera.x += (v.x - _userCamera.x) * 0.3;
				_userCamera.y += (v.z - _userCamera.y) * 0.3;
				_userCamera.z += (v.y - _userCamera.z) * 0.3;
				_controller.setObjectPosXYZ(_userCamera.x, _userCamera.y, _userCamera.z + 80);
				_controller.lookAtXYZ(0, 0, 80);
			}
			_camera.render();
		}
	}
}
import com.bit101.components.PushButton;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Vector3D;
class Angle {
	static public const PI2:Number = Math.PI * 2;
	/**
	 * baseのラジアン度をnearに一番近くなるよう再設定(+Math.PI*2/-Math.PI*2)する
	 */
	static public function toNearRadian(base:Number, near:Number):Number {
		var rad:Number = base - near;
		rad = (rad % PI2 + PI2) % PI2;
		if (rad > Math.PI) rad -= PI2;
		return rad + near;
	}
}
/**
 * シーンをマウスでぐるぐる
 */
class GlobeDragger extends EventDispatcher {
	public var zoomSpeed:Number = 1.2;
	public var rotationSpeed:Number = 1;
	public var angleSpeed:Number = 1;
	public var distanceMin:Number = NaN;
	public var distanceMax:Number = NaN;
	public var rotationMin:Number = NaN;
	public var rotationMax:Number = NaN;
	public var angleMin:Number = NaN;
	public var angleMax:Number = NaN;
	public var wheelEnabled:Boolean = false;
	
	private var _distance:Number;
	private var _rotation:Number;
	private var _angle:Number;
	private var _enabled:Boolean = true;
	private var _eventObj:InteractiveObject;
	private var _saveRotation:Number;
	private var _saveAngle:Number;
	private var _saveMousePos:Point;
	private var _position:Vector3D = new Vector3D();
	
	public var onMoveCamera:Function;
	
	public function get position():Vector3D { return _position; }
	public function get enabled():Boolean { return _enabled; }
	public function set enabled(value:Boolean):void {
		onMsUp();
		_enabled = value;
	}
	
	/**
	 * @param	obj	マウスイベントを登録する場所
	 * @param	rotation	初期の横方向角度
	 * @param	angle	初期の縦方向角度
	 * @param	distance	初期の中心点からの距離
	 */
	public function GlobeDragger(obj:InteractiveObject, rotation:Number = 0, angle:Number = 30, distance:Number = 1000) {
		_distance = distance;
		_angle = angle;
		_rotation = rotation;
		_eventObj = obj;
		_eventObj.addEventListener(MouseEvent.MOUSE_DOWN, onMsDown);
		_eventObj.stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMsWheel);
	}
	private function dispose():void {
		_eventObj.removeEventListener(MouseEvent.MOUSE_DOWN, onMsDown);
		_eventObj.stage.removeEventListener(MouseEvent.MOUSE_UP, onMsUp);
		_eventObj.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMsWheel);
		_eventObj.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
	}
	private function onMsWheel(e:MouseEvent):void {
		if (!_enabled || !wheelEnabled) return;
		var vec:int = (e.delta < 0)? -1 : 1;
		_distance *= Math.pow(zoomSpeed, -vec);
		_distance = checkLimit(_distance, distanceMin, distanceMax);
		updatePosition();
	}
	public function dispatch():void {
		dispatchEvent(new Event(Event.CHANGE));
		if (onMoveCamera != null) onMoveCamera.apply(null, [_position]);
	}
	public function setDistanceLimit(min:Number, max:Number):void {
		distanceMin = min;
		distanceMax = max;
	}
	public function setAngleLimit(min:Number, max:Number):void {
		angleMin = min;
		angleMax = max;
	}
	public function setRotationLimit(min:Number, max:Number):void {
		rotationMin = min;
		rotationMax = max;
	}
	private function onMsDown(e:MouseEvent):void {
		if (!_enabled) return;
		_eventObj.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
		_eventObj.stage.addEventListener(MouseEvent.MOUSE_UP, onMsUp);
		_saveRotation = _rotation;
		_saveAngle = _angle;
		_saveMousePos = new Point(_eventObj.mouseX, _eventObj.mouseY);
	}
	private function onMsMove(e:MouseEvent):void {
		if (!_enabled) return;
		var dragOffset:Point = new Point(_eventObj.mouseX, _eventObj.mouseY).subtract(_saveMousePos);
		_rotation = _saveRotation - dragOffset.x * rotationSpeed;
		_rotation = checkLimit(_rotation, rotationMin, rotationMax);
		_angle = Math.max(-89, Math.min(89, _saveAngle + dragOffset.y * angleSpeed));
		_angle = checkLimit(_angle, angleMin, angleMax);
		updatePosition();
	}
	private function checkLimit(num:Number, min:Number, max:Number):Number {
		if (!isNaN(min) && num < min) num = min;
		if (!isNaN(max) && num > max) num = max;
		return num;
	}
	private function onMsUp(...rest):void {
		_eventObj.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMsMove);
		_eventObj.stage.removeEventListener(MouseEvent.MOUSE_UP, onMsUp);
		updatePosition();
	}
	private function updatePosition():void {
		var per:Number = Math.cos(Math.PI / 180 * _angle);
		var px:Number = Math.cos(Math.PI / 180 * _rotation) * _distance * per;
		var py:Number = Math.sin(Math.PI / 180 * _angle) * _distance;
		var pz:Number = Math.sin(Math.PI / 180 * _rotation) * _distance * per;
		_position = new Vector3D(px, py, pz)
		dispatch();
	}
}
/**
 * クリックでラベルが切り替わるボタン
 */
class SwitchButton extends PushButton {
	private var _mode:int = 0;
	private var _labels:Array = [];
	private var _switchFunc:Function;
	public function get mode():int { return _mode; }
	public function SwitchButton(parent:DisplayObjectContainer = null, x:Number = 0, y:Number = 0, labels:Array = null, clickFunc:Function = null) {
		_switchFunc = clickFunc;
		_labels = (labels == null)? [""] : labels.concat();
		if (_labels.length == 0) _labels = [""];
		super(parent, x, y, _labels[0], onClick);
	}
	public function setMode(mode:int):void {
		_mode = mode;
		label = _labels[mode];
	}
	private function onClick(e:MouseEvent):void {
		setMode(++_mode % _labels.length);
		//引数の数が足りない場合は処理を振り分ける
		if (_switchFunc != null) {
			try {
				_switchFunc.apply(null, [e, _mode]);
			} catch (error:Error) {
				try {
					_switchFunc.apply(null, [e]);
				} catch (error:Error) {
					_switchFunc.apply(null, []);
				}
			}
		}
	}
}
class Painter {
	/**
	 * べた塗りスプライト生成
	 */
	static public function createColorRect(width:Number, height:Number, color:uint = 0x000000, alpha:Number = 1, x:Number = 0, y:Number = 0):Sprite {
		var sp:Sprite = new Sprite();
		sp.graphics.beginFill(color, alpha);
		sp.graphics.drawRect(0, 0, width, height);
		sp.graphics.endFill();
		sp.x = x;
		sp.y = y;
		return sp;
	}
}