正文  图形图像 > Canvas/Bitmap >

Bitmap透视变换 js开发教程

import flash.geom.*;var photo:Sprite=new Sprite();addChild(photo);//Img为继承于BitmapData的图片类...


import flash.geom.*;
var photo:Sprite=new Sprite();
addChild(photo);
//Img为继承于BitmapData的图片类
var bitmapSource = new Img(400,300);
var showLine = true;
var inBitmapWidth = 1/bitmapSource.width;
var inBitmapHeight = 1/bitmapSource.height;
var bitmapWidth = bitmapSource.width;
var bitmapHeight = bitmapSource.height;
//鼠标按下时bitmap的变换距阵
var bitmapMtrx = new Matrix();
var subBitmapMtix = new Matrix();
//舞台宽度变量申明
var StWidth = 550;
var StHeight = 400;
var ōx = StWidth/2;
var ōy = StHeight/2;
//焦距
var focus = 80;
//摄影机角度变量
var angU = 0;
var angV = 0;
//细分段数
var subdiv = 5;
var subdivPic = subdiv*(subdiv-1);
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 = bitmapSource.width/(subdiv-1);
var subdivHeight = bitmapSource.height/(subdiv-1);
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));
}
var mtrxSx = subdivWidth/bitmapWidth;
var mtrxSy = subdivHeight/bitmapHeight;
var mtrxSxy = subdivWidth/bitmapHeight;
var mtrxSyx = subdivHeight/bitmapWidth;
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();
 }
}
var mtrxA = mtrx[0].a;
var mtrxB = mtrx[0].b;
var mtrxC = mtrx[0].c;
var mtrxD = mtrx[0].d;
var mtrx2A = mtrx2[0].a;
var mtrx2B = mtrx2[0].b;
var mtrx2C = mtrx2[0].c;
var mtrx2D = mtrx2[0].d;
// 初始每个bitmap细分结点在正则化3D视见体空间中的空间位置
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]);
  }
 }
}
fun6(0,1,0,0,0,0,-1,0,0,-1);
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;
   }
  }
 }
}
var subdivV = subdiv-1;
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);
    }
   }
  }
 }
}
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();
}//初始渲染
photo.graphics.clear();
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;
stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUpHandler);
function onMouseDownHandler(evt:MouseEvent):void {
 stage.addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
 dx = mouseX;
 dy = mouseY;
}
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();
 }
}
function onMouseUpHandler(evt:MouseEvent):void {
 stage.removeEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
 photo.graphics.clear();
 render();
}
render();