import sandy.core.group.Group; import sandy.core.group.TransformGroup; import sandy.core.transform.Transform3D; import sandy.primitive.Plane3D; import sandy.skin.TextureSkin; import sandy.view.Camera3D; import sandy.view.ClipScreen; import sandy.view.IScreen; import sandy.core.World3D; import sandy.util.*; import flash.display.BitmapData; /** * @mtasc -main CubicPano -swf CubicPano.swf -header 300:300:120:FFFFFF -version 8 -wimp */ class CubicPano { // the MovieClip in which CubicPano does its stuff private var _scope:MovieClip; // the six bitmaps that will constitute the cubic view private var _textures:Object; private var _planeNames:Object; private var _mcLoader:MovieClipLoader; private var _faceWidth:Number; private var _texturesLoaded:Number; private var _world:World3D; private var _tf:TextField; private var _fps:Number; private var _ms:Number; private var _loadingTF:TextField; private var _yaw:Number; private var _pitch:Number; private var _fov:Number; private var _planeGroups:Object; private var _frameSize:Number; private var _numPlanes:Number; public static function main():Void { var p:CubicPano = new CubicPano(_level0); } public function CubicPano(scope:MovieClip) { this._numPlanes = 6; this._scope = scope; this._world = World3D.getInstance(); this._fps = 0; _faceWidth = 300; this._frameSize = 300; makeLoadingTF(); this._planeNames = ["straight_ahead", "left", "behind", "right", "down", "up"]; this._textures = new Object(); this._texturesLoaded = 0; this._planeGroups = new Object(); this._mcLoader = new MovieClipLoader(); this._mcLoader.addListener(this); for (var i:Number = 0; i < _numPlanes; i++) { this.loadClip(_planeNames[i]); } } private function makeLoadingTF():Void { this._loadingTF = _scope.createTextField( "_loadingTF", _scope.getNextHighestDepth(), Stage.width/2 - 50, Stage.height/2 - 10, 100, 20); var tFormat = new TextFormat(); tFormat.color = 0x000000; tFormat.align = "center"; tFormat.font = "_sans"; _loadingTF.setNewTextFormat(tFormat); _loadingTF.text = "Loading images..." } private function killLoadingTF():Void { this._loadingTF._visible = false; this._loadingTF.removeTextField(); } private function __createFPS():Void { _tf = _scope.createTextField ("fps", _scope.getNextHighestDepth(), 5, 10, 40, 20); _tf.border = true; _tf.borderColor = 0xFFFFFF; } private function loadClip(planeName:String) { var pathName:String = planeName + ".jpg"; // this MC will never appear on screen: var loaderMC:MovieClip = _scope.createEmptyMovieClip(planeName, _scope.getNextHighestDepth()); _mcLoader.loadClip(pathName, loaderMC); } // note that this method removes the MC once it has extracted the bmp private function convertToBmp(target:MovieClip):BitmapData { var image:BitmapData = new BitmapData(target._width, target._height, false, 0); image.draw(target); target.removeMovieClip(); return image; } // this method is invoked when the mcLoader has loaded the clip public function onLoadInit(target:MovieClip):Void { this._textures[target._name] = convertToBmp(target); if (++this._texturesLoaded == _numPlanes) // when all six textures have been loaded { start(); } } public function start():Void { killLoadingTF(); _yaw = _pitch = 0; //this._faceWidth = this._textures[this._planeNames[0]].width; var branchGroup:Group = makePlanes(); // We have built all the objects; now we can display them var screen:IScreen = new ClipScreen(_scope.createEmptyMovieClip("screen", _scope.getNextHighestDepth()), _frameSize, _frameSize); __createFPS(); var cam:Camera3D = new Camera3D(200, screen); //cam.setPosition( 0, 0, -500 ); _fov = fov(300); _world.addCamera(cam); _world.setRootGroup( branchGroup ); _ms = getTimer(); _world.addEventListener(World3D.onRenderEVENT, this, interactions); _world.render(); } private function makePlanes():Group { var g:Group = new Group(); // var rotations:Object = makeRotations(); var translations:Object = makeTranslations(); // var t:Transform3D, r:Transform3D, r2:Transform3D; for (var i:Number = 0; i < _numPlanes; i++) { var tggr:TransformGroup = new TransformGroup(); tggr.setTransform( TransformUtil.rotX( 90 ) ); var planeName:String = _planeNames[i]; var tgr:TransformGroup = new TransformGroup(); var tgt:TransformGroup = new TransformGroup(); // t = Transform3D(translations[planeName]); r = Transform3D(rotations[planeName]); // tgr.setTransform( r ); tgt.setTransform( t ); // var plane:Plane3D = makePlane(planeName); // tggr.addChild(plane); tgr.addChild( tggr ); tgt.addChild( tgr ); g.addChild( tgt ); } return g; } private function makeRotations():Object { var rotations:Object = { straight_ahead: TransformUtil.rotY(0), right: TransformUtil.rotY(90), left: TransformUtil.rotY(-90), behind: TransformUtil.rotY(180), up: TransformUtil.rotX(90), down: TransformUtil.rotX(-90) }; return rotations; } private function makeTranslations():Object { var dist:Number = this._faceWidth/2; var translations:Object = { straight_ahead: TransformUtil.translateZ(-dist), right: TransformUtil.translateX(dist), left: TransformUtil.translateX(-dist), behind: TransformUtil.translateZ(dist), up: TransformUtil.translateY(-dist), down: TransformUtil.translateY(dist) }; return translations; } private function makePlane(planeName:String):Plane3D { var plane:Plane3D = new Plane3D(this._faceWidth, // height this._faceWidth, // width 4, // quality 'tri');// mode plane.enableBackFaceCulling = false; var planeSkin:TextureSkin = new TextureSkin( this._textures[planeName] ); plane.setSkin(planeSkin); plane.setBackSkin( planeSkin ); return plane; } private function interactions():Void { var newMS:Number = getTimer(); if (newMS - 1000 > _ms) { _ms = newMS; _tf.text = _fps + " fps"; _fps = 0; } else { _fps++; } var cam:Camera3D = _world.getCamera(); if (Key.isDown(Key.RIGHT)) { cam.rotateY(5); // yaw _yaw += 5; } if (Key.isDown(Key.LEFT)) { cam.rotateY(-5); // yaw _yaw -= 5; } if (Key.isDown(Key.UP)) { cam.tilt(5); // pitch (not really but OK since we don't roll) _pitch += 5; } if (Key.isDown(Key.DOWN)) { cam.tilt(-5); // pitch (not really but OK since we don't roll) _pitch -= 5; } if (Key.isDown(Key.SHIFT)) { _fov -= 10; cam.setFocal(foc(_fov)); // zoom trace(_fov); } if (Key.isDown(Key.CONTROL)) { _fov += 10; cam.setFocal(foc(_fov)); // zoom trace(_fov); } if (_yaw > 180) _yaw -= 360; else if (_yaw < -180) _yaw += 360; } private function fov(foc:Number):Number // fov in degrees { return 360 * Math.atan(_frameSize/(2 * foc)) / Math.PI; } private function foc(fov:Number):Number // fov in degrees { return _frameSize / (2 * Math.tan(Math.PI * fov/360)); } }