/******** fspp - Flash Spherical Panorama Player (c) 2008 Atanas Minev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Official site: http://pan0.net/fspp ChangeLog: --------------------------------------------------------------------------------------- dd.mm.yy version description --------------------------------------------------------------------------------------- 09.06.08 0.02 added commandline parameters: tesselation - tesselation of the pano sphere - default = 30, more is smoother, but slower PA - initial pitch angle - default = 0 degrees, points to horizon minPA - min pitch angle - default = -90 degrees, camera points to nadir maxPA - max pitch angle - default = 90 degrees, camera points to zenith zoom - initial zoom - default = 1.5 minZoom - min camera zoom - default = 1 maxZoom - max camera zoom - default = 5 allowFullScreen - allow fullscreen mode - default = true --------------------------------------------------------------------------------------- 06.06.08 0.01 initial revision ********/ package { import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display.Stage; import flash.display.StageDisplayState; import flash.geom.Point; import flash.ui.Keyboard; import flash.events.Event; import flash.events.MouseEvent; import flash.events.KeyboardEvent; import flash.events.ContextMenuEvent; import org.papervision3d.events.FileLoadEvent; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.cameras.FreeCamera3D; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.core.geom.renderables.Triangle3D; import org.papervision3d.materials.BitmapFileMaterial; import org.papervision3d.view.BasicView; public class fspp extends BasicView { // parameters private var panoSrc: String = "pano.jpg"; private var tesselation: Number = 30; private var PA: Number = 0; private var minPA: Number = -90; private var maxPA: Number = 90; private var zoom: Number = 1.5; private var minZoom: Number = 1; private var maxZoom: Number = 5; private var allowFullScreen: Boolean = true; private var panoSphere: Sphere; private var material: BitmapFileMaterial; private var needsFastFrameRender: Boolean = false; private var needsSmoothFrameRender: Boolean = true; private var startPoint: Point; private var rotationXStart: Number = 0; private var rotationYStart: Number = 0; private var rotationXTarget: Number = 0; private var rotationYTarget: Number = 0; public function fspp() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; super(stage.stageWidth, stage.stageHeight, true, true, FreeCamera3D.TYPE); processParameters(); init(); startRendering(); } private function processParameters(): void { if (loaderInfo.parameters.panoSrc) panoSrc= loaderInfo.parameters.panoSrc; if (loaderInfo.parameters.tesselation) tesselation= loaderInfo.parameters.tesselation; if (loaderInfo.parameters.PA) PA= loaderInfo.parameters.PA; if (loaderInfo.parameters.minPA) minPA= loaderInfo.parameters.minPA; if (loaderInfo.parameters.maxPA) maxPA= loaderInfo.parameters.maxPA; if (loaderInfo.parameters.zoom) zoom= loaderInfo.parameters.zoom; if (loaderInfo.parameters.minZoom) minZoom= loaderInfo.parameters.minZoom; if (loaderInfo.parameters.maxZoom) maxZoom= loaderInfo.parameters.maxZoom; if (loaderInfo.parameters.allowFullScreen) allowFullScreen= loaderInfo.parameters.allowFullScreen; } private function init(): void { material = new BitmapFileMaterial(panoSrc); material.opposite = true; material.interactive = true; material.addEventListener(FileLoadEvent.LOAD_COMPLETE, onLoadComplete); panoSphere= new Sphere(material, 30000, tesselation, tesselation); scene.addChild(panoSphere); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownEvent); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpEvent); stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent); stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownEvent); camera.x = camera.y = camera.z = 0; camera.focus = 300; camera.zoom = zoom; } override protected function onRenderTick(event: Event = null): void { if (needsFastFrameRender) { calcCameraRotation(); super.onRenderTick(event); } if (needsSmoothFrameRender) { material.smooth = true; super.onRenderTick(event); material.smooth = false; needsSmoothFrameRender = false; } } private function calcCameraRotation(): void { camera.rotationY += (rotationYTarget - camera.rotationY) / 3; camera.rotationX += (rotationXTarget - camera.rotationX) / 3; if (camera.rotationX < minPA) camera.rotationX = minPA; if (camera.rotationX > maxPA) camera.rotationX = maxPA; } private function onMouseDownEvent(e: MouseEvent): void { stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveEvent); startPoint = new Point(mouseX, mouseY); rotationYStart = camera.rotationY; rotationXStart = camera.rotationX; needsFastFrameRender = true; } private function onMouseMoveEvent(e: MouseEvent): void{ rotationYTarget = rotationYStart - (startPoint.x - mouseX) / 2; rotationXTarget = rotationXStart + (startPoint.y - mouseY) / 2; needsFastFrameRender = true; } private function onMouseUpEvent(e: MouseEvent): void{ stage.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMoveEvent); needsFastFrameRender = false; needsSmoothFrameRender = true; } private function onMouseWheelEvent(e: MouseEvent): void { camera.zoom += e.delta / 10; if (camera.zoom < minZoom) camera.zoom = minZoom; if (camera.zoom > maxZoom) camera.zoom = maxZoom; needsSmoothFrameRender = true; } private function onLoadComplete(event: FileLoadEvent): void { needsSmoothFrameRender = true; } private function onKeyDownEvent(event: KeyboardEvent): void { switch (event.keyCode) { case Keyboard.LEFT: rotationYTarget -= 2; calcCameraRotation(); needsSmoothFrameRender = true; break; case Keyboard.RIGHT: rotationYTarget += 2; calcCameraRotation(); needsSmoothFrameRender = true; break; case Keyboard.UP: rotationXTarget += 2; calcCameraRotation(); needsSmoothFrameRender = true; break; case Keyboard.DOWN: rotationXTarget -= 2; calcCameraRotation(); needsSmoothFrameRender = true; break; case Keyboard.PAGE_UP: camera.zoom += 0.5; if (camera.zoom > maxZoom) camera.zoom = maxZoom; needsSmoothFrameRender = true; break; case Keyboard.PAGE_DOWN: camera.zoom -= 0.5; if (camera.zoom < minZoom) camera.zoom = minZoom; needsSmoothFrameRender = true; break; case Keyboard.HOME: if ((stage.displayState == StageDisplayState.NORMAL) && allowFullScreen) { stage.displayState = StageDisplayState.FULL_SCREEN; needsSmoothFrameRender = true; } break; } } private function goFullScreen(event:ContextMenuEvent): void { stage.displayState = StageDisplayState.FULL_SCREEN; } } }