Flash AS3的3D —— Papervision3D组件

点击在新窗口中浏览此图片
  今天网上乱逛,发现个好东东,flash的3d组件,不过还不是用as3.0的,我对3.0还不怎么熟呢,暂贴上来,以后灵活自如后再去研究。


先看看这个几个网址的东西:

http://www.papervision3d.org/

http://www.noventaynueve.com/2007/

http://www.rhythmoflines.co.uk/

http://carlosulloa.com/

点击在新窗口中浏览此图片

点击在新窗口中浏览此图片

Papervision3D Component v1.5 下载地址:http://code.google.com/p/papervision3d/downloads/detail?name=PV3DComponents_v1.5.1.mxp&can=2&q=

以前还研究全景视图呢,现在看来,直接用这个就可以解决了,而且速度肯定更快!

官方博客:http://blog.papervision3d.org/


-------------------------------------------------------------

相关原理:
flash 360度3D虚拟实境(cubicVR)源代码及其实现原理
  flash的3D虚拟实境最早源自于德国的flash图形学大牛andre.michelle在其labsite:lab.andre-michelle.com上发表了一篇关于虚拟实境的文章,并提供了一个实例(NaN sourcecode).为了深入虚拟实境,在接下来的2个月里我陆续找到一些cubicVR的源文件并尝试破译了一些源码,我同时尝试开发了一个简单的flash3D引擎以及图片3D拉伸算法,所有这些的思想均来自于andre-michelle在其日志中提到的一些idea.现在在这篇文章中所用的实例依然是我对andre早期版本的整理,虽然目前我开发的新版本有更好的结构以及执行效率,但此版本的编程思想更通俗易懂。我想利用这个假期时间开发出flash球型虚拟实境,使它变得更真实。

  在flash里部署3D虚拟实境无疑是一个革命性进步,我们再也不用去安装java虚拟机和QTVR了,事实上,在基于flash的可编程矢量图形界面基础上开发出来的虚拟现实可以通过创新的用户界面以达到完美的用户体验。city8.com既采用这种技术来部署他们的全景体验城市地图。

demo:鼠标拖拽以转换camera视角

原理:
1.1点透视与投影
  通过1点透视来产生远小近大的变化以产生空间感,在cubicVR中,设想观察者camera在一个正六面体中央,通过一点透视来计算每个面的在空间投影中的位置,以产生透视效果。
  demo:没有导入透视方程的情况:

2.细分贴图
  flash的matrix类只支持2D图形变换:切变、缩放、平面位移。位图无法实现3D变换,这与openGL不同,openGL只需要在定义多边型顶点和贴图法线,位图就会自动贴到一个面片上,而且整个贴图过程完全由GPU完成。而在flash中必须使用细分贴图的方法来欺骗人们的眼睛,既:将一张图片细分为n张小的三角面片,再将小三角面片进行平面切变,正因为如此,flash3D一旦涉及贴图必然导致大量占用cpu运算资源。
细分贴图的demo:http://godson.blueidea.com/archives/2006/3708.shtml

3.消隐算法
  如果没有消隐算法,那么观察者只能看到离屏幕最近的面,而不能看到整个3D空间,理论上消隐算法有3个步骤:1在一个六面体中,面法线与视锥体夹角大于180度则应设为不可见,2在同一个像素上,只显示与camera最近的多边形(Zbuffer算法),3投影在屏幕以外的多边型不可见,但这三种算法非常占用cpu资源,andrew设计了一种更简单的算法:1多边形的中心与camera重合,在camera坐标系中Z值
源代码:

--------------------------------渲染部分------------------------------------

//读入位图数据,将其存放在数组中
var bitmapAry = new Array();
var bitmapSource = flash.display.BitmapData.loadBitmap("data2");
for (i=0; ivar face = new flash.display.BitmapData(bitmapSource.width, bitmapSource.width, false);
face.copyPixels(bitmapSource, new flash.geom.Rectangle(0, bitmapSource.width*i, bitmapSource.width, bitmapSource.width*(i+1)), new flash.geom.Point(0, 0));
bitmapAry.push(face);
}
var showLine = true;
var inBitmapWidth = 1/bitmapAry[0].width;
var inBitmapHeight = 1/bitmapAry[0].height;
var bitmapWidth = bitmapAry[0].width;
var bitmapHeight = bitmapAry[0].height;
//鼠标按下时bitmap的变换距阵
this.bitmapMtrx = new flash.geom.Matrix();
var subBitmapMtix = new flash.geom.Matrix();
//舞台宽度变量申明
StWidth = Stage.width;
StHeight = Stage.height;
ox = StWidth/2;
oy = StHeight/2;
//焦距
focus = 300;
//摄影机角度变量
angU = 0;
angV = 0;
//细分段数
subdiv = 9;
subdivPic = subdiv*subdiv;
//
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 = bitmapAry[0].width/(subdiv-1);
var subdivHeight = bitmapAry[0].height/(subdiv-1);
for (var i = 0; ifor (var j = 0; j  var subID = j+i*subdiv;
  subdivMapX.push(j*subdivWidth);
  subdivMapY.push(i*subdivHeight);
}
}
//
for (var i = 0; imtrx.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));
}
// end of for
var mtrxSx = subdivWidth/bitmapWidth;
var mtrxSy = subdivHeight/bitmapHeight;
var mtrxSxy = subdivWidth/bitmapHeight;
var mtrxSyx = subdivHeight/bitmapWidth;
for (var i = 0; ifor (var j = 0; j  var subID = j+i*subdiv;
  var mtrxTx = subdivMapX[subdiv*i+j];
  var mtrxTy = subdivMapY[subdiv*i+j];
  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;
// 初始每个bitmap细分结点在正则化3D视见体空间中的空间位置
function fun6(bitmapNo, new19, new20, new21, new22, new25, new23, new26, new24, new27) {
new15 = subdiv-1 >> 1;
for (var i = 0; i  for (var j = 0; 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);
fun6(1, 0, -1, 0, -1, 0, 0, 0, 0, -1);
fun6(2, -1, 0, 0, 0, 0, 1, 0, 0, -1);
fun6(3, 0, 1, 0, 1, 0, 0, 0, 0, -1);
fun6(4, 0, 0, 1, 0, 1, -1, 0, 0, 0);
fun6(5, 0, 0, -1, 0, -1, -1, 0, 0, 0);
// 求每个subdiv的在屏幕坐标系的x和y将每个subdiv可见量存储于subdivEnable中
function fun7(bitmapNo) {
for (var i = 0; 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 and subdivX[bitmapNo][i]0 and subdivY[bitmapNo][i]    subdivEnable[bitmapNo][i] = 1;
   } else {
    subdivEnable[bitmapNo][i] = 0;
   }
  }
}
}
//
subdivV = subdiv-1;
function render() {
for (var i = 0; i  fun7(i);
  for (var j = 0; j   for (var k = 0; 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);
    }
   }
  }
}
}
//
renderBitmap = function (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.beginBitmapFill(bitmapAry[bitmapNo], subBitmapMtix, false, false);
if (showLine == true) {
  this.photo.lineStyle(1, 0x000000, 100);
}
this.photo.moveTo(point1X, point1Y);
this.photo.lineTo(point2X, point2Y);
this.photo.lineTo(point3X, point3Y);
this.photo.endFill();
};
//初始渲染
photo.clear();
cos_angU = Math.cos(angU);
sin_angU = Math.sin(angU);
cos_angV = Math.cos(angV);
sin_angV = Math.sin(angV);
render();
--------------------------------------鼠标控制部分---------------------------------

var myMouseListener = new Object();
var myKeyListener = new Object();
this.createEmptyMovieClip("photo", this.getNextHighestDepth());
this.createEmptyMovieClip("win", this.getNextHighestDepth());
lable.swapDepths(photo);
win.lineStyle(2, 0x000000, 100);
win.moveTo(0, 0);
win.lineTo(Stage.width, 0);
win.lineTo(Stage.width, Stage.height);
win.lineTo(0, Stage.height);
win.lineTo(0, 0);
myMouseListener.onMouseDown = function() {
onEnterFrame = function () {
  var xWidth = _xmouse-dx;
  var yWidth = _ymouse-dy;
  if (xWidth != 0 || yWidth != 0) {
   photo.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();
  }
};
dx = _xmouse;
dy = _ymouse;
};
myMouseListener.onMouseUp = function() {
onEnterFrame = undefined;
photo.clear();
render();
};
myMouseListener.onMouseWheel = function(wheelMove) {
i = 0;
focus = focus+wheelMove*20;
if (focus  focus = 180;
}
photo.clear();
render();
};
Mouse.addListener(myMouseListener);
Tags - flash , as3.0 , 3d , papervision3d

转载于:https://www.cnblogs.com/pelephone/articles/flash-3d-pv3d.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值