Bitmap透视变换PerspectiveTransform
Bitmap变换PerspectiveTransform
package com.vincent.utils{
import flash.display.*;
import flash.geom.*;
import flash.events.*;
public class PerspectiveTransform extends Sprite {
private var photo:Sprite;
private var tempMc:Sprite;
private var bitmapSource:BitmapData;
var showLine = true;
var inBitmapWidth;
var inBitmapHeight;
var bitmapWidth;
var bitmapHeight;
//鼠标按下时bitmap的变换距阵
var bitmapMtrx = new Matrix();
var subBitmapMtix = new Matrix();
//舞台宽度变量申明
var StWidth = 550;
var StHeight = 400;
var ox;
var oy;
//焦距
var focus = 80;
//摄影机角度变量
var angU = 0;
var angV = 0;
//细分段数
var subdiv = 5;
var subdivPic;
var subdivVy = new Array();
var subdivVx = new Array();
var subdivVz = new Array();
var subdivX = new Array();
var subdivY = new Array();
var subdivEnable = new Array();
var mtrx = new Array();
var mtrx2 = new Array();
//细分bitmap在map内部的X和Y
var subdivMapX = new Array();
var subdivMapY = new Array();
var subdivWidth;
var subdivHeight;
var mtrxSx;
var mtrxSy;
var mtrxSxy;
var mtrxSyx;
var subdivV;
var mtrxA;
var mtrxB;
var mtrxC;
var mtrxD;
var mtrx2A;
var mtrx2B;
var mtrx2C;
var mtrx2D;
var cos_angU = Math.cos(angU);
var sin_angU = Math.sin(angU);
var cos_angV = Math.cos(angV);
var sin_angV = Math.sin(angV);
var dx;
var dy;
public function PerspectiveTransform(sour:Bitmap) {
this.bitmapSource=sour.bitmapData;
inBitmapWidth = 1/bitmapSource.width;
inBitmapHeight = 1/bitmapSource.height;
bitmapWidth = bitmapSource.width;
bitmapHeight = bitmapSource.height;
ox = StWidth/2;
oy = StHeight/2;
subdivPic = subdiv*(subdiv-1);
subdivWidth = bitmapSource.width/(subdiv-1);
subdivHeight = bitmapSource.height/(subdiv-1);
mtrxSx = subdivWidth/bitmapWidth;
mtrxSy = subdivHeight/bitmapHeight;
mtrxSxy = subdivWidth/bitmapHeight;
mtrxSyx = subdivHeight/bitmapWidth;
subdivV = subdiv-1;
photo=new Sprite();
tempMc=new Sprite();
drawRec(photo,0,0,0xff0000,1);
addChild(photo);
drawRec(tempMc,600,600,0xffcc00,.02);
addChild(tempMc);
init();
}
private function init():void {
for (var i = 0; i<subdiv; i++) {
for (var j = 0; j<subdiv; j++) {
subdivMapX.push(j*subdivWidth);
subdivMapY.push(i*subdivHeight);
}
}
//
for (var h = 0; h<subdivPic; h++) {
mtrx.push(new flash.geom.Matrix());
mtrx2.push(new flash.geom.Matrix());
subdivVy.push(new Array(subdivPic));
subdivVx.push(new Array(subdivPic));
subdivVz.push(new Array(subdivPic));
subdivX.push(new Array(subdivPic));
subdivY.push(new Array(subdivPic));
subdivEnable.push(new Array(subdivPic));
}
for (var m = 0; m<subdiv-1; ++m) {
for (var n = 0; n<subdiv-1; ++n) {
var subID = n+m*subdiv;
var mtrxTx = subdivMapX[subdiv*m+n];
var mtrxTy = subdivMapY[subdiv*m+n];
mtrx[subID].tx = mtrxTx;
mtrx[subID].ty = mtrxTy;
mtrx[subID].a = mtrxSx;
mtrx[subID].b = 0;
mtrx[subID].c = mtrxSxy;
mtrx[subID].d = mtrxSy;
mtrx[subID].invert();
mtrx2[subID].tx = mtrxTx;
mtrx2[subID].ty = mtrxTy;
mtrx2[subID].a = mtrxSx;
mtrx2[subID].b = mtrxSyx;
mtrx2[subID].c = 0;
mtrx2[subID].d = mtrxSy;
mtrx2[subID].invert();
}
}
mtrxA = mtrx[0].a;
mtrxB = mtrx[0].b;
mtrxC = mtrx[0].c;
mtrxD = mtrx[0].d;
mtrx2A = mtrx2[0].a;
mtrx2B = mtrx2[0].b;
mtrx2C = mtrx2[0].c;
mtrx2D = mtrx2[0].d;
photo.graphics.clear();
tempMc.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDownHandler);
tempMc.addEventListener(MouseEvent.MOUSE_UP,onMouseUpHandler);
fun6(0,1,0,0,0,0,-1,0,0,-1);
render();
}
private function onMouseDownHandler(evt:MouseEvent):void {
tempMc.addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
dx = mouseX;
dy = mouseY;
}
private function onMouseUpHandler(evt:MouseEvent):void {
tempMc.removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
photo.graphics.clear();
render();
}
private function onEnterFrameHandler(evt:Event):void {
var xWidth = mouseX-dx;
var yWidth = mouseY-dy;
if (xWidth != 0 || yWidth != 0) {
photo.graphics.clear();
angU = angU-xWidth*0.001;
angV = angV-yWidth*0.001;
cos_angU = Math.cos(angU);
sin_angU = Math.sin(angU);
cos_angV = Math.cos(angV);
sin_angV = Math.sin(angV);
render();
}
}
// 初始每个bitmap细分结点在正则化3D视见体空间中的空间位置
private function fun6(bitmapNo, new19, new20, new21, new22, new25, new23, new26, new24, new27) {
var new15 = subdiv-1 >> 1;
for (var i = 0; i<subdiv; i++) {
for (var j = 0; j<subdiv; j++) {
var subID = j+i*subdiv;
subdivVy[bitmapNo][subID] = new19*new15+new22*(j-new15)+new25*(i-new15);
subdivVx[bitmapNo][subID] = new20*new15+new23*(j-new15)+new26*(i-new15);
subdivVz[bitmapNo][subID] = new21*new15+new24*(j-new15)+new27*(i-new15);
//trace(subdivVy[bitmapNo][subID]+"/"+subdivVx[bitmapNo][subID]+"/"+subdivVz[bitmapNo][subID]);
}
}
}
private function render() {
for (var i = 0; i<6; i++) {
fun7(i);
for (var j = 0; j<subdivV; ++j) {
for (var k = 0; k<subdivV; k++) {
var pointA = k+j*subdiv;
var pointC = k+(j+1)*subdiv;
var pointB = pointA+1;
var pointD = pointC+1;
var _loc2 = subdivEnable[i][pointA]+subdivEnable[i][pointD]+subdivEnable[i][pointB];
var _loc3 = subdivEnable[i][pointA]+subdivEnable[i][pointD]+subdivEnable[i][pointC];
//如果细分表面顶点有1个在屏幕内则渲染该面片
if (_loc2>0) {
//细分表面拉伸距阵计算
subBitmapMtix.a = mtrxA;
subBitmapMtix.b = mtrxB;
subBitmapMtix.c = mtrxC;
subBitmapMtix.d = mtrxD;
subBitmapMtix.tx = mtrx[pointA].tx;
subBitmapMtix.ty = mtrx[pointA].ty;
renderBitmap(i,subdivX[i][pointA],subdivY[i][pointA],subdivX[i][pointB],subdivY[i][pointB],subdivX[i][pointD],subdivY[i][pointD],subBitmapMtix);
}
//如果细分表面顶点有1个在屏幕内则渲染该面片
if (_loc3>0) {
//细分表面拉伸距阵计算
subBitmapMtix.a = mtrx2A;
subBitmapMtix.b = mtrx2B;
subBitmapMtix.c = mtrx2C;
subBitmapMtix.d = mtrx2D;
subBitmapMtix.tx = mtrx2[pointA].tx;
subBitmapMtix.ty = mtrx2[pointA].ty;
renderBitmap(i,subdivX[i][pointA],subdivY[i][pointA],subdivX[i][pointD],subdivY[i][pointD],subdivX[i][pointC],subdivY[i][pointC],subBitmapMtix);
}
}
}
}
}
private function fun7(bitmapNo) {
for (var i = 0; i<subdivPic; i++) {
//此为核心部分:细分贴图顶点在camera坐标空间中的坐标系变换运算 _loc5为z值,_loc5与_loc6的两个方程是对空间向量距阵计算的简化
var _loc6 = cos_angU*subdivVy[bitmapNo][i]+sin_angU*subdivVx[bitmapNo][i];
var _loc5 = cos_angV*_loc6+sin_angV*subdivVz[bitmapNo][i];
//如果顶点在视角前方则进行投影计算
if (_loc5>=0.1) {
var _loc7 = focus/_loc5;
//计算投影的x,y
subdivX[bitmapNo][i] = (sin_angU*subdivVy[bitmapNo][i]-cos_angU*subdivVx[bitmapNo][i])*_loc7+ox;
subdivY[bitmapNo][i] = (sin_angV*_loc6-cos_angV*subdivVz[bitmapNo][i])*_loc7+oy;
if (subdivX[bitmapNo][i]>0 && subdivX[bitmapNo][i]<StWidth && subdivY[bitmapNo][i]>0 && subdivY[bitmapNo][i]<StHeight) {
subdivEnable[bitmapNo][i] = 1;
} else {
subdivEnable[bitmapNo][i] = 0;
}
}
}
}
private function renderBitmap(bitmapNo, point1X, point1Y, point2X, point2Y, point3X, point3Y, subBitmapMtix) {
//细分表面贴图距阵计算
this.bitmapMtrx.a = (point2X-point1X)*inBitmapWidth;
this.bitmapMtrx.b = (point2Y-point1Y)*inBitmapWidth;
this.bitmapMtrx.c = (point3X-point1X)*inBitmapHeight;
this.bitmapMtrx.d = (point3Y-point1Y)*inBitmapHeight;
this.bitmapMtrx.tx = point1X;
this.bitmapMtrx.ty = point1Y;
subBitmapMtix.concat(this.bitmapMtrx);
//贴图渲染
this.photo.graphics.beginBitmapFill(bitmapSource,subBitmapMtix,false,false);
if (showLine == true) {
this.photo.graphics.lineStyle(1,0x000000,100);
}
this.photo.graphics.moveTo(point1X,point1Y);
this.photo.graphics.lineTo(point2X,point2Y);
this.photo.graphics.lineTo(point3X,point3Y);
this.photo.graphics.endFill();
}
private function drawRec(_con:Sprite,_w,_h,color,num):Sprite {
_con.graphics.beginFill(color,num);
_con.graphics.drawRect(0,0,_w,_h);
_con.graphics.endFill();
return _con;
}
}
}
补充:flash教程,As3.0