[转]使用CS4的新增类实现全景图效果

[url]http://uh.9ria.com/space-12147-do-blog-id-5759.html[/url]

全景图原理其实很简单,就是将做好的球面贴图贴在一个圆的内部,然后将摄像机放在圆的中间观看,由于视差而产生的现象。因此,只要使用3D引擎的话,制作一个全景系统是很简单的(创建球体,贴上贴图,然后放置摄像机到原点就可以)

但是仅仅是一个全景显示就去搬pv3D这样一个大家伙过来有些小题大做。FLASH3D其实都是将位图打碎成三角形,然后对每个三角形做矩阵变换,并通过绘制三角形到元件的方式实现的。明白这一点就可以自己做。CS4之后提供了原生的3D转换和批量绘制三角形的drawTriangles方法以及许多关于3D矢量的数学公式,大大简化了这个过程(但drawTriangles的使用方法确实难以掌握)

[url]http://code.google.com/p/ghostcat/source/browse/trunk/ghostcatfp10/src/ghostcat/display/g3d/GBitmapSphere.as[/url]

这个类实际上是一个绘制球体的类,传入位图贴图,半径,面数之后,修改其matrix3d属性并执行render方法后,就会绘制出一个3D的球体。我们要制作全景效果,只要将它的culling属性设为显示内部TriangleCulling.NEGATIVE,然后将圆的半径设置得足够大,看起来就像是在球体内部了。

值得一提的是,这样制作的全景系统将只有1.8K。而且因为省掉了排序等等多余的操作,效率会有一定提高。

之后会再说说全景中热点的实现方法。



package ghostcat.display.g3d
{
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.TriangleCulling;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;

/**
* 位图贴图球体
*
* @author flashyiyi
*
*/
public class GBitmapSphere extends Sprite
{
/**
* 贴图
*/
public var material:BitmapData;

private var vertsVec:Vector.<Vector.<Vector3D>>;

/**
* 转换矩阵
*/
public var matrix3D:Matrix3D;
/**
* 半径
*/
public var radius:Number;

/**
* 显示内部/外部
*/
public var culling:String;

/**
* 贴图平滑
*/
public var smooth:Boolean;

private var nMesh:Number;
private var vertices:Vector.<Number>;
private var indices:Vector.<int>;
private var uvtData:Vector.<Number>;

public function GBitmapSphere(material:BitmapData,radius:Number = 100, nMesh:int = 30)
{
this.material = material;
this.radius = radius;
this.nMesh = nMesh;
this.matrix3D = new Matrix3D();
this.culling = TriangleCulling.POSITIVE;

setVertsVec();
render();
}

/**
* 创建多边形
*
*/
protected function setVertsVec():void
{
var i:int;
var j:int;
var istep:Number;
var jstep:Number;

istep=2*Math.PI/nMesh;
jstep=Math.PI/nMesh;

this.vertsVec=new Vector.<Vector.<Vector3D>>();

for(i=0;i<=nMesh;i++)
{
var vector:Vector.<Vector3D> = new Vector.<Vector3D>();
for(j=0;j<=nMesh;j++)
{
vector[j]=new Vector3D(radius*Math.sin(istep*i)*Math.sin(jstep*j),-radius*Math.cos(jstep*j),-radius*Math.cos(istep*i)*Math.sin(jstep*j));
}

vertsVec[i] = vector;
}

indices = new Vector.<int>();
uvtData = new Vector.<Number>();

var curVertsNum:int=0;
for(i=0;i<nMesh;i++)
{
for(j=0;j<nMesh;j++)
{
indices.push(curVertsNum,curVertsNum+1,curVertsNum+3,curVertsNum+1,curVertsNum+2,curVertsNum+3);
uvtData.push(i/nMesh,j/nMesh,(i+1)/nMesh,j/nMesh,(i+1)/nMesh,(j+1)/nMesh,i/nMesh,(j+1)/nMesh);
curVertsNum += 4;
}
}
}

/**
* 旋转矩阵并渲染
* @param rotx
* @param roty
* @param rotz
*
*/
public function rotate(rotx:Number,roty:Number,rotz:Number):void
{
matrix3D.appendRotation(rotx,Vector3D.X_AXIS);
matrix3D.appendRotation(roty,Vector3D.Y_AXIS);
matrix3D.appendRotation(rotz,Vector3D.Z_AXIS);
}

/**
* 重置旋转
*
*/
public function reset():void
{
matrix3D = new Matrix3D();
}

/**
* 根据矩阵渲染图像
*
*/
public function render():void
{
vertices = new Vector.<Number>();
for(var i:int = 0;i<nMesh;i++)
{
for(var j:int = 0;j<nMesh;j++)
{
var curv0:Vector3D = matrix3D.deltaTransformVector(vertsVec[i][j]);
var curv1:Vector3D = matrix3D.deltaTransformVector(vertsVec[i+1][j]);
var curv2:Vector3D = matrix3D.deltaTransformVector(vertsVec[i+1][j+1]);
var curv3:Vector3D = matrix3D.deltaTransformVector(vertsVec[i][j+1]);

vertices.push(curv0.x,curv0.y,curv1.x,curv1.y,curv2.x,curv2.y,curv3.x,curv3.y);
}
}

graphics.clear();

if (material)
graphics.beginBitmapFill(material,null,false,smooth);

graphics.drawTriangles(vertices,indices,uvtData,culling);
graphics.endFill();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值