Intro
Creating a CS4 Panorama has a unique twist – literally! You actually don’t rotate the primitive but you animate its texture, using the code snippet below:
public function step(moveU:Number, moveV:Number=0.0):void {
for (var i=0; i<uvtData.length; i+=2) {
uvtData[i++] -= moveU;
uvtData[i] += moveV;
// each loop i increases by 3 because skiping over the t-coordinate
}
}
The uvtData is easily animated just by skipping through correct U or V values of the uvtData vector and adding a small increment. Click on the image below to see the web demo.
As in the previous Super Prim post, Petri Leskinen’s great work on Pixelero http://pixelero.wordpress.com/ was key to this creation. He demonstrates an animated tube which with a little work I was able to turn into this panorama.
YouTube: Coming Soon!
Discussion
The encapsulated code very closely resembles the OOP regimentation of Papervision3D. The CS4PanoPrim wrapper class instantiates the SpherePano primitive. And the SpherePano constructor function has 5 input parameters: material, width, height, hSegments, and wSegments, as shown below:
spherePano = new SpherePano(bmp, 500.0, 500.0, 32, 32);
The SpherePanoPrim is set up very much like the Super Prim (previous post) with the addition of a new mask function, which gives you the ability to trim the look of your pano.
private function addMyMask():void {
// mask crops that to a rectangle
myMask = new Sprite();
myMask.graphics.lineStyle(0.0,0×00,1.0);
myMask.graphics.beginFill(0×00,1.0);
myMask.graphics.drawRect(-w/2,-h/2,w,h);
myMask.graphics.endFill();
addChild(myMask);
this.mask = myMask;
}
The mask is just a simple sprite that uses the “this.mask” method to mask your pano.
If you want to learn how to make spherical pano images check out the following YouTube links by Amanda Verrette (one of my graphic designers):
Part 1: http://www.youtube.com/watch?v=wfkLQ93Uey0
Part 2: http://www.youtube.com/watch?v=hhjuSIzLXCE
Part 3: http://www.youtube.com/watch?v=AKpVboahayg
Parts 4, 5, 6, 7, and 8 are still in production.
There’s still more work to do on this before release, but it’s great starter code. And harnesses the OOP structure of Papervision3D. To view both classes discussed above click the more link below:
Wrapper Class – CS4PanoPrim
package {
import flash.events.*
import flash.display.*;
import flash.geom.*;
import SpherePanoPrim;
public class CS4PanoPrim extends Sprite {
[Embed(source='bridgePano.jpg')]
public var MyPhoto:Class;
private var tunnel:Tunnel;
private var spherePano:SpherePano;
private var diffY:Number=0;
private var diffX:Number=0;
public function CS4PanoPrim() {
var bmp:BitmapData = (new MyPhoto()).bitmapData;
spherePano = new SpherePano(bmp, 500.0, 500.0, 32, 32);
spherePano.x = stage.stageWidth/2;
spherePano.y = stage.stageHeight/2;
addChild(spherePano);
stage.addEventListener(flash.events.MouseEvent.MOUSE_MOVE, frameThrottle);
stage.addEventListener(Event.ENTER_FRAME, iterateMovement);
}
private function frameThrottle(e:MouseEvent):void{
diffX = ( stage.stageWidth/2 – mouseX);
diffY = (stage.stageHeight/2 – mouseY);
}
private function iterateMovement(event:Event):void {
// move with mouse
if( Math.abs(diffX)<spherePano.w/2 ){
spherePano.step(diffX/50000, -diffY/20000);
spherePano.animLoop();
}
}
}
}
SpherePanoPrim
package {
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.GraphicsPathCommand;
import flash.display.TriangleCulling;
import flash.geom.Vector3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Matrix3D;
import flash.geom.Utils3D;
public class SpherePanoPrim extends Sprite {
private var ix:Number;
private var iy:Number;
private var paraVec:Vector3D;
public var n:int ;
public var m:int ;
public var w:Number;
public var h:Number;
//Elliptical Parameters
private var radx:Number=1;
private var rady:Number=1;
private var radz:Number=1;
public var bitmapData:BitmapData = new BitmapData(1,1,true,0xFFFFFFFF);
private var myMask:Sprite;
private var radius:Number;
private var vertices:Vector.<Number>;
private var verts:Vector.<Number> = new Vector.<Number>;
private var indices:Vector.<int>;
private var uvtData:Vector.<Number>;
private var coords3D:Vector.<Number>;
private var projectedVerts:Vector.<Number>= new Vector.<Number>;
private var bendedVerts:Vector.<Number>;
private var projectionMatrix:Matrix3D;
private static const doublePi:Number = 2.0*Math.PI;
public function SpherePanoPrim(bmp:BitmapData, _w:Number = 800, _h:Number = 600,
_n:int =32, _m:int=32) {
bitmapData = bmp;
this.w = _w;
this.h = _h;
this.n = _n;
this.m = _m;
var perspective:PerspectiveProjection= new PerspectiveProjection();
perspective.fieldOfView = 75.0; // camera angle, in degrees
projectionMatrix = perspective.toMatrix3D();
projectionMatrix.prependTranslation(0,0,0);
init();
}
private function init():void {
indices = new Vector.<int>();
uvtData = new Vector.<Number>();
for (var i:int = 0 ; i!=n; i++) {
ix= i/(n-1)*Math.PI*2.0;
for (var j:int =0 ; j!=m; j++) {
iy= (j/(m-1)-0.5)*Math.PI;
//Sphere
paraVec = new Vector3D(
Math.cos(iy)*Math.cos(ix), Math.sin(iy), Math.cos(iy)*Math.sin(ix));
//Collect vetices in the verts Vector array
verts.push(radx*paraVec.x,rady*paraVec.y,radz*paraVec.z);
//Subtract 1 to flip image
uvtData.push(1-i/(n-1),1-j/(m-1), 0);
projectedVerts.push(0.0,0.0);
}
}
var ii:int =0;
for (i=0 ; i!=n-1; i++) {
for (j=0 ; j!=m-1; j++) {
indices.push(ii,ii+m+1,ii+1);
indices.push(ii+m,ii+m+1,ii++);
}
ii++;
}
animLoop();
addMyMask();
}
//image moves
public function step(moveU:Number, moveV:Number=0.0):void {
for (var i=0; i<uvtData.length; i+=2) {
uvtData[i++] -= moveU;
uvtData[i] += moveV;
// each loop i increases by 3 because skiping over the t-coordinate
}
}
public function animLoop():void {
// projection to 2D
Utils3D.projectVectors(projectionMatrix, verts,
projectedVerts, uvtData);
// drawing …
with (this.graphics) {
clear();
beginBitmapFill(this.bitmapData ,
null, // no matrix
true, // = repeat, important for ‘moving’ the bitmap
true); // = smooth
drawTriangles(projectedVerts,
indices,
uvtData,
TriangleCulling.NEGATIVE);
endFill();
}
}
//My Mask
private function addMyMask():void {
// mask crops that to a rectangle
myMask = new Sprite();
myMask.graphics.lineStyle(0.0,0×00,1.0);
myMask.graphics.beginFill(0×00,1.0);
myMask.graphics.drawRect(-w/2,-h/2,w,h);
myMask.graphics.endFill();
addChild(myMask);
this.mask = myMask;
}
}
}

January 26, 2009 at 4:38 pm |
vertical shift doesnt really make sense, does it
January 30, 2009 at 5:15 pm |
[...] > Flash CS4 Spherical Panorama (animating uvtData) « Professional Papervision3D Book [...]
February 16, 2009 at 2:47 pm |
[...] Flash CS4 Spherical Panorama (animating uvtData) http://professionalpapervision.wordpress.com/2009/01/24/flash-cs4-spherical-panorama-animating-uvtda... [...]
April 14, 2009 at 12:01 pm |
Please provide the SpherePano Class as well or give a link. I am having problems with your example download.
Thanks a lot