3D Flickr Image Sphere
/**
* Copyright amyneon ( http://wonderfl.net/user/amyneon )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xOZP
*/
// forked from sakef's simple 3D 06 (not using PV3D)
package
{
import com.bit101.components.Label;
import net.hires.debug.Stats;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.system.Security;
[SWF(width="465", height="465", backgroundColor="0xffffff")]
public class simple3d_06 extends Sprite
{
// Plane???·??·??????
private static const SIZE:Number = 90;
private static const RADIUS:int = 300;
private static const CENTER_X:int=465 >> 1;
private static const CENTER_Y:int=465 >> 1;
private static const CAMERA_RADIUS:int=600;
private static const FOCUS:Number=400;
// ????????????
private static const KEYWORD:String = "sea";
// ?????????·????????
private const CENTER:MyVector3D=new MyVector3D();
private const UP:MyVector3D=new MyVector3D(0, 1, 0);
// ????
private var camera:MyVector3D;
private var isMouseDown:Boolean;
private var oldX:Number;
private var oldY:Number;
private var targetRot:Number;
private var targetPitch:Number;
private var rot:Number;
private var pitch:Number;
// ?????Plane??
private var container:Array;
private var n_planes:int;
// ???
private var img_array:Array;
private var count:int;
private var label:Label;
// ???????
public function simple3d_06()
{
// ??????·????????
stage.scaleMode=StageScaleMode.SHOW_ALL;
stage.align=StageAlign.TOP;
stage.quality=StageQuality.HIGH;
stage.frameRate=30;
mouseChildren=false;
mouseEnabled=false;
// Stats??
//addChild(new Stats());
// ??????
img_array = [];
container = [];
oldX=oldY=rot=pitch=n_planes=count=0;
targetPitch=90;
targetRot=180;
isMouseDown=false;
camera=new MyVector3D(0, 0, FOCUS);
// Plane???????
var radian:Number = Math.PI/180;
var H:int=(RADIUS * Math.PI) / SIZE;
var theta1:Number;
var theta2:Number=90;
for(var i:int=0; i < H; i++)
{
theta1=0;
var pn:int=Math.floor((2 * RADIUS * Math.PI * Math.cos(theta2 * radian)) / SIZE);
for(var j:int=0; j < pn; j++)
{
var plane:MyPlane = new MyPlane(SIZE, n_planes);
plane.rotationX=-theta2;
plane.rotationY=theta1;
plane.x=RADIUS * Math.cos(theta2 * radian) * Math.sin(theta1 * radian);
plane.y=RADIUS * Math.sin(theta2 * radian);
plane.z=RADIUS * Math.cos(theta2 * radian) * Math.cos(theta1 * radian);
theta1+=360 / pn;
container[n_planes] = plane;
n_planes ++;
}
theta2-=180 / H;
}
// ?????????????
label = new Label(this, CENTER_X-80, CENTER_Y-50);
label.scaleX = label.scaleY = 2;
label.text="Loading images from flickr.\n" + count.toString() + "\t/ " + n_planes.toString();
// ?????????????
Security.loadPolicyFile("http://api.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm1.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm2.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm3.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm4.static.flickr.com/crossdomain.xml");
// Flickr????????
var api_loader:URLLoader=new URLLoader;
api_loader.addEventListener(Event.COMPLETE, onCompleteAccessAPI);
api_loader.load(new URLRequest("http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=25c5f4bc0087edf4d6efdc567daf0a64&tags="+KEYWORD + "&per_page=" + n_planes));
}
// FlickrAPI??????????????????
private function onCompleteAccessAPI(e:Event):void
{
var api_loader:URLLoader=e.target as URLLoader;
api_loader.removeEventListener(Event.COMPLETE, onCompleteAccessAPI);
// XML????????URL???·???
var xml:XML=XML(api_loader.data);
if (xml.@stat == "ok")
{
for each(var photo:XML in xml.photos.photo)
{
var url:String="http://farm" + photo.@farm + ".static.flickr.com/" + photo.@server + "/" + photo.@id + "_" + photo.@secret + ".jpg";
var img_loader:Loader=new Loader();
img_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompletePhotoLoad);
img_loader.load(new URLRequest(url), new LoaderContext(true));
}
}
}
// ??????????????????
private function onCompletePhotoLoad(e:Event):void
{
var img_loader:Loader=(e.target as LoaderInfo).loader;
img_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompletePhotoLoad);
// ??????????
img_array[count]=(img_loader.content as Bitmap).bitmapData;
count ++;
label.text="Loading images from flickr.\n" + count.toString() + "\t/ " + n_planes.toString();
// ??????????????????????
if(count == n_planes)
{
label.visible = false;
addEventListener(Event.ENTER_FRAME, onFrame);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
// ???????
private function onFrame(e:Event):void
{
// ??????
if (isMouseDown)
{
targetRot+=(mouseX - oldX) * 0.2;
targetPitch+=(mouseY - oldY) * 0.2;
targetPitch=(targetPitch > -90) ? (targetPitch) : (-90);
targetPitch=(targetPitch < 90) ? (targetPitch) : (90);
oldX=mouseX;
oldY=mouseY;
}
rot+=(targetRot - rot) * 0.1;
pitch+=(targetPitch - pitch) * 0.1;
pitch=(pitch > -90) ? (pitch) : (-90);
pitch=(pitch < 90) ? (pitch) : (90);
camera.x=CAMERA_RADIUS * Math.sin(rot * Math.PI / 180);
camera.y=CAMERA_RADIUS * Math.sin(pitch * Math.PI / 180);
camera.z=CAMERA_RADIUS * Math.cos(rot * Math.PI / 180);
// ??????????
var Mview:MyMatrix3D=getViewingTransformMatrix(camera);
// ??????
for(var i:int = 0 ; i<n_planes ; i++) (container[i] as MyPlane).render(Mview);
// ???
container.sortOn("sortNumber", Array.NUMERIC | Array.DESCENDING);
// ??
graphics.clear();
for(i=0 ; i<n_planes ; i++)
{
var plane:MyPlane = container[i] as MyPlane;
plane.draw(graphics, CENTER_X, CENTER_Y, FOCUS, img_array[plane.imgNumber] as BitmapData);
}
}
// ??????????
private function onMouseDown(e:MouseEvent):void
{
isMouseDown=true;
oldX=mouseX;
oldY=mouseY;
}
// ??????????
private function onMouseUp(e:MouseEvent):void
{
isMouseDown=false;
}
// ??????????????????????
private function getViewingTransformMatrix(camera:MyVector3D):MyMatrix3D
{
// Center - Eye ???????????
var n:MyVector3D=CENTER.subtract(camera);
n.normalize();
// up×n??? (??)
var u:MyVector3D=UP.crossProduct(n);
u.normalize();
// n×u??? (??)
var v:MyVector3D=n.crossProduct(u);
v.normalize();
// d???
var dx:Number=-camera.innerProduct(u);
var dy:Number=-camera.innerProduct(v);
var dz:Number=-camera.innerProduct(n);
// ??????????
var Mview:MyMatrix3D=new MyMatrix3D(u.x, u.y, u.z, dx, v.x, v.y, v.z, dy, n.x, n.y, n.z, dz, 0, 0, 0, 1);
return Mview;
}
}
}
/*
Plane???
*/
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.geom.Matrix;
import flash.geom.Point;
final class MyPlane
{
// ????????
private const CENTER:MyVector3D = new MyVector3D();
// ???????????????????
private var eye_Coord_points:Array;
// ?????
public var x:Number;
public var y:Number;
public var z:Number;
public var rotationX:Number;
public var rotationY:Number;
public var rotationZ:Number;
public var size:Number
// ??????·???????
public var sortNumber:Number;
public var imgNumber:int;
// ???????
public function MyPlane(size:Number, imgNumber:int)
{
x = y = z = rotationX = rotationY = rotationZ = 0;
eye_Coord_points=[];
this.size = size;
this.imgNumber = imgNumber;
}
// ?????
public function render(Mview:MyMatrix3D):void
{
// ????????
var s:Number = size >> 1;
var original_points:Array=[new MyVector3D(-s, s), new MyVector3D(s, s), new MyVector3D(-s, -s), new MyVector3D(s, -s)];
// ??????????
var Mmodel:MyMatrix3D=new MyMatrix3D;
Mmodel=Mmodel.productParallelTransformMatrix(x, y, z);
Mmodel=Mmodel.productRotationZMatrix(rotationZ);
Mmodel=Mmodel.productRotationYMatrix(rotationY);
Mmodel=Mmodel.productRotationXMatrix(rotationX);
// ??????????
var Mmodelview:MyMatrix3D=Mview.productMatrix(Mmodel);
// ?????????????
sortNumber=0;
eye_Coord_points=[];
for(var i:int=0; i < 4; i++)
{
var p:MyVector3D=Mmodelview.productVector(original_points[i]as MyVector3D);
eye_Coord_points[i]=p;
sortNumber+=p.z;
}
}
// ??
public function draw(graphics:Graphics, centerX:Number, centerY:Number, focus:Number, bmpd:BitmapData):void
{
// 3D?2D???
var points:Array=[];
for(var i:int=0; i < 4; i++)
{
var p:MyVector3D=eye_Coord_points[i]as MyVector3D;
var scale:Number=focus / CENTER.distance(p);
var screenX:Number=p.x * scale + centerX;
var screenY:Number=-p.y * scale + centerY;
points[i]=new Point(screenX, screenY);
}
// ??
// ????????????:http://www.d-project.com/flex/009_FreeTransform/
var a0:Point=new Point();
var a1:Point=new Point(bmpd.width, 0);
var a2:Point=new Point(0, bmpd.height);
var a3:Point=new Point(bmpd.width, bmpd.height);
var b0:Point=points[0]as Point;
var b1:Point=points[1]as Point;
var b2:Point=points[2]as Point;
var b3:Point=points[3]as Point;
var mtx:Matrix = createMatrix(a0,a1,a2,b0,b1,b2);
graphics.beginBitmapFill(bmpd, mtx);
graphics.moveTo(b0.x, b0.y);
graphics.lineTo(b1.x, b1.y);
graphics.lineTo(b2.x, b2.y);
graphics.endFill();
mtx = createMatrix(a3,a1,a2,b3,b1,b2);
graphics.beginBitmapFill(bmpd, mtx);
graphics.moveTo(b3.x, b3.y);
graphics.lineTo(b1.x, b1.y);
graphics.lineTo(b2.x, b2.y);
graphics.endFill();
}
// ?????????????
// ??????????????????:http://www.d-project.com/flex/009_FreeTransform/
private function createMatrix(a0:Point, a1:Point, a2:Point, point0:Point, point1:Point, point2:Point):Matrix
{
var ma:Matrix=new Matrix(a1.x - a0.x, a1.y - a0.y, a2.x - a0.x, a2.y - a0.y);
var mb:Matrix=new Matrix(point1.x - point0.x, point1.y - point0.y, point2.x - point0.x, point2.y - point0.y);
ma.invert();
var m:Matrix=new Matrix();
m.translate(-a0.x, -a0.y);
m.concat(ma);
m.concat(mb);
m.translate(point0.x, point0.y);
return m;
}
}
/*
????????
*/
final class MyMatrix3D
{
// ?????
public var v11:Number, v12:Number, v13:Number, v14:Number;
public var v21:Number, v22:Number, v23:Number, v24:Number;
public var v31:Number, v32:Number, v33:Number, v34:Number;
public var v41:Number, v42:Number, v43:Number, v44:Number;
// ???????
private static const RADIAN:Number=Math.PI / 180;
// ???????
public function MyMatrix3D(v11:Number=1, v12:Number=0, v13:Number=0, v14:Number=0,
v21:Number=0, v22:Number=1, v23:Number=0, v24:Number=0,
v31:Number=0, v32:Number=0, v33:Number=1, v34:Number=0,
v41:Number=0, v42:Number=0, v43:Number=0, v44:Number=1)
{
this.v11=v11; this.v12=v12; this.v13=v13; this.v14=v14;
this.v21=v21; this.v22=v22; this.v23=v23; this.v24=v24;
this.v31=v31; this.v32=v32; this.v33=v33; this.v34=v34;
this.v41=v41; this.v42=v42; this.v43=v43; this.v44=v44;
}
// ????? (???A????B????A*B)
public function productMatrix(m:MyMatrix3D):MyMatrix3D
{
var newMat:MyMatrix3D=new MyMatrix3D();
newMat.v11=v11 * m.v11 + v12 * m.v21 + v13 * m.v31 + v14 * m.v41;
newMat.v12=v11 * m.v12 + v12 * m.v22 + v13 * m.v32 + v14 * m.v42;
newMat.v13=v11 * m.v13 + v12 * m.v23 + v13 * m.v33 + v14 * m.v43;
newMat.v14=v11 * m.v14 + v12 * m.v24 + v13 * m.v34 + v14 * m.v44;
newMat.v21=v21 * m.v11 + v22 * m.v21 + v23 * m.v31 + v24 * m.v41;
newMat.v22=v21 * m.v12 + v22 * m.v22 + v23 * m.v32 + v24 * m.v42;
newMat.v23=v21 * m.v13 + v22 * m.v23 + v23 * m.v33 + v24 * m.v43;
newMat.v24=v21 * m.v14 + v22 * m.v24 + v23 * m.v34 + v24 * m.v44;
newMat.v31=v31 * m.v11 + v32 * m.v21 + v33 * m.v31 + v34 * m.v41;
newMat.v32=v31 * m.v12 + v32 * m.v22 + v33 * m.v32 + v34 * m.v42;
newMat.v33=v31 * m.v13 + v32 * m.v23 + v33 * m.v33 + v34 * m.v43;
newMat.v34=v31 * m.v14 + v32 * m.v24 + v33 * m.v34 + v34 * m.v44;
newMat.v41=v41 * m.v11 + v42 * m.v21 + v43 * m.v31 + v44 * m.v41;
newMat.v42=v41 * m.v12 + v42 * m.v22 + v43 * m.v32 + v44 * m.v42;
newMat.v43=v41 * m.v13 + v42 * m.v23 + v43 * m.v33 + v44 * m.v43;
newMat.v44=v41 * m.v14 + v42 * m.v24 + v43 * m.v34 + v44 * m.v44;
return newMat;
}
// ???????
public function productVector(v:MyVector3D):MyVector3D
{
var newVec:MyVector3D=new MyVector3D();
newVec.x=v11 * v.x + v12 * v.y + v13 * v.z + v14;
newVec.y=v21 * v.x + v22 * v.y + v23 * v.z + v24;
newVec.z=v31 * v.x + v32 * v.y + v33 * v.z + v34;
return newVec;
}
// x???????????
public function productRotationXMatrix(rotationX:Number):MyMatrix3D
{
var sin:Number=Math.sin(rotationX * RADIAN);
var cos:Number=Math.cos(rotationX * RADIAN);
var mat:MyMatrix3D=new MyMatrix3D(1, 0, 0, 0, 0, cos, -sin, 0, 0, sin, cos);
return productMatrix(mat);
}
// y???????????
public function productRotationYMatrix(rotationY:Number):MyMatrix3D
{
var sin:Number=Math.sin(rotationY * RADIAN);
var cos:Number=Math.cos(rotationY * RADIAN);
var mat:MyMatrix3D=new MyMatrix3D(cos, 0, sin, 0, 0, 1, 0, 0, -sin, 0, cos);
return productMatrix(mat);
}
// z???????????
public function productRotationZMatrix(rotationZ:Number):MyMatrix3D
{
var sin:Number=Math.sin(rotationZ * RADIAN);
var cos:Number=Math.cos(rotationZ * RADIAN);
var mat:MyMatrix3D=new MyMatrix3D(cos, -sin, 0, 0, sin, cos);
return productMatrix(mat);
}
// ?????????????
public function productParallelTransformMatrix(x:Number, y:Number, z:Number):MyMatrix3D
{
var mat:MyMatrix3D=new MyMatrix3D(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z);
return productMatrix(mat);
}
}
/*
??????????
*/
final class MyVector3D
{
// x?y?z?????????
public var x:Number;
public var y:Number;
public var z:Number;
public var w:Number;
// ???????
public function MyVector3D(x:Number=0, y:Number=0, z:Number=0)
{
this.x=x;
this.y=y;
this.z=z;
this.w=1;
}
// ??
public function distance(v:MyVector3D):Number
{
return Math.sqrt((v.x - x) * (v.x - x) + (v.y - y) * (v.y - y) + (v.z - z) * (v.z - z));
}
// ?
public function subtract(v:MyVector3D):MyVector3D
{
var newVec:MyVector3D=new MyVector3D();
newVec.x=x - v.x;
newVec.y=y - v.y;
newVec.z=z - v.z;
return newVec;
}
// ???
public function normalize():void
{
var len:Number=Math.sqrt(x * x + y * y + z * z);
x/=len;
y/=len;
z/=len;
}
// ??
public function innerProduct(v:MyVector3D):Number
{
return (x * v.x + y * v.y + z * v.z);
}
// ??(????) (???A????B?????A×B???)
public function crossProduct(v:MyVector3D):MyVector3D
{
var newVec:MyVector3D=new MyVector3D();
newVec.x=y * v.z - z * v.y;
newVec.y=z * v.x - x * v.z;
newVec.z=x * v.y - y * v.x;
return newVec;
}
}