Flash/Flex学习笔记(51):3维旋转与透视变换(PerspectiveProjection)

简介: Flash/Flex学习笔记(49):3D基础 里已经介绍了3D透视的基本原理,不过如果每次都要利用象该文中那样写一堆代码,估计很多人不喜欢,事实上AS3的DisplayObject类已经内置了z坐标、rotationX、rotationY、rotationZ属性,再加上PerspectiveProjection类用于处理透视转换,基本上可以满足大多数的3D要求。

Flash/Flex学习笔记(49):3D基础 里已经介绍了3D透视的基本原理,不过如果每次都要利用象该文中那样写一堆代码,估计很多人不喜欢,事实上AS3的DisplayObject类已经内置了z坐标、rotationX、rotationY、rotationZ属性,再加上PerspectiveProjection类用于处理透视转换,基本上可以满足大多数的3D要求。

import flash.events.Event;
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.text.TextFieldAutoSize;

var isAngleChangeing = false;

var txtX:TextField,txtY:TextField,txtZ:TextField,txtPosZ:TextField,txtFieldOfView:TextField,txtInfo:TextField,txtCenter:TextField,txtFocusLength:TextField;
txtX = new TextField();
txtX.text = "rotationX:";
txtY = new TextField();
txtY.text = "rotationY:";
txtZ = new TextField();
txtZ.text = "rotationZ:";
txtPosZ = new TextField();
txtPosZ.text = "Z:";
txtFieldOfView = new TextField();
txtFieldOfView.text = "视角:";
txtCenter = new TextField();
txtCenter.text = "消失点:"
txtFocusLength = new TextField();
txtFocusLength.text = "焦距:";
txtX.y = txtY.y = txtZ.y = 5;
txtX.x = txtPosZ.x = 10;
txtPosZ.y = txtX.y + 26;
txtPosZ.x +=  40;
txtY.x = txtX.x + 180;
txtZ.x = txtY.x + 180;
txtFieldOfView.x = txtPosZ.x + 160;
txtFieldOfView.y = txtPosZ.y;
txtCenter.x = txtFieldOfView.x + 170;
txtCenter.y = txtPosZ.y;
txtInfo = new TextField();
txtInfo.text="";
txtFocusLength.x = txtX.x + 25;
txtFocusLength.y = txtPosZ.y + 25;

var imgBD:BitmapData = new ImgSample();
var img:Bitmap = new Bitmap(imgBD);
trace("img.width=",img.width,",img.height=",img.height);

var imgSprite:Sprite = new Sprite();
img.x =  -  img.width / 2;
img.y =  -  img.height / 2;
imgSprite.addChild(img);
trace("imgSprite.width=",imgSprite.width,",imgSprite.height=",imgSprite.height);

var containerSprite:Sprite = new Sprite();
containerSprite.addChild(imgSprite);
imgSprite.x = img.width / 2;
imgSprite.y = img.height / 2;

addChild(containerSprite);
trace("containerSprite.width=",containerSprite.width,",containerSprite.height=",containerSprite.height);

containerSprite.x = stage.stageWidth / 2 - containerSprite.width / 2;
containerSprite.y = stage.stageHeight / 2 - containerSprite.height / 2;
containerSprite.z = 50;

var silderX:SimpleSlider = new SimpleSlider(0,360,0);
silderX.x = txtX.x + 160;
silderX.y = txtX.y + 7;
silderX.rotation = 90;

var silderY:SimpleSlider = new SimpleSlider(0,360,0);
silderY.x = txtY.x + 160;
silderY.y = silderX.y;
silderY.rotation = 90;

var silderZ:SimpleSlider = new SimpleSlider(0,360,0);
silderZ.x = txtZ.x + 160;
silderZ.y = silderX.y;
silderZ.rotation = 90;

var silderPosZ:SimpleSlider = new SimpleSlider(-200,200,50);
silderPosZ.x = txtX.x + 160;
silderPosZ.y = silderX.y + 25;
silderPosZ.rotation = 90;

var silderFieldOfView:SimpleSlider = new SimpleSlider(0.1,179.9,90);
silderFieldOfView.x = silderPosZ.x + 180;
silderFieldOfView.y = silderPosZ.y;
silderFieldOfView.rotation = 90;

var silderCenterPos:SimpleSlider = new SimpleSlider(150,400,275);
silderCenterPos.x = silderFieldOfView.x + 180;
silderCenterPos.y = silderPosZ.y;
silderCenterPos.rotation = 90;

var silderFocusLength:SimpleSlider = new SimpleSlider(100,500,300);
silderFocusLength.x = silderPosZ.x ;
silderFocusLength.y = silderPosZ.y + 25;
silderFocusLength.rotation = 90;

addChild(txtX);
addChild(txtY);
addChild(txtZ);
addChild(txtPosZ);
addChild(txtFieldOfView);
addChild(txtInfo);
addChild(txtCenter);
addChild(txtFocusLength);
addChild(silderX);
addChild(silderY);
addChild(silderZ);
addChild(silderPosZ);
addChild(silderFieldOfView);
addChild(silderCenterPos);
addChild(silderFocusLength);

silderX.addEventListener(Event.CHANGE,silderXChangeHandler);
silderY.addEventListener(Event.CHANGE,silderYChangeHandler);
silderZ.addEventListener(Event.CHANGE,silderZChangeHandler);
silderPosZ.addEventListener(Event.CHANGE,silderPosZChangeHandler);
silderFieldOfView.addEventListener(Event.CHANGE,silderFieldOfViewChangeHandler);
silderFieldOfView.addEventListener(MouseEvent.MOUSE_UP,function(){isAngleChangeing = false});
silderCenterPos.addEventListener(Event.CHANGE,silderCenterPosChangeHandler);
silderFocusLength.addEventListener(Event.CHANGE,silderFocusLengthChangeHandler);


function showTxtInfo(s:SimpleSlider){
	txtInfo.text = s.value.toString().substr(0,5);
	txtInfo.x = mouseX + 20;
	txtInfo.y = s.y + 5;
}

function silderXChangeHandler(e:Event):void {
	imgSprite.rotationX = silderX.value;
	showTxtInfo(silderX);
}

function silderYChangeHandler(e:Event):void {
	imgSprite.rotationY = silderY.value;
	showTxtInfo(silderY);
}

function silderZChangeHandler(e:Event):void {
	imgSprite.rotationZ = silderZ.value;
	showTxtInfo(silderZ);
}

function silderPosZChangeHandler(e:Event):void {
	containerSprite.z = silderPosZ.value;
	showTxtInfo(silderPosZ);
}


function silderFieldOfViewChangeHandler(e:Event):void {
	doPerspectiveProjection();
	showTxtInfo(silderFieldOfView);
	isAngleChangeing = true;
}

function silderCenterPosChangeHandler(e:Event):void {
	doPerspectiveProjection();
	showTxtInfo(silderCenterPos);
}

function silderFocusLengthChangeHandler(e:Event):void {
	doPerspectiveProjection();
	showTxtInfo(silderFocusLength);
}

function doPerspectiveProjection():void{
	var pp:PerspectiveProjection=new PerspectiveProjection();
	pp.fieldOfView = silderFieldOfView.value;
	if (!isAngleChangeing){
		pp.focalLength  = silderFocusLength.value;	
	}
	//trace(pp.focalLength);
	pp.projectionCenter = new Point(silderCenterPos.value,silderCenterPos.value);
	containerSprite.transform.perspectiveProjection = pp;
	
}

doPerspectiveProjection();

var txtAuthor:TextField = new TextField();
txtAuthor.htmlText ="<a href='http://yjmyzz.cnblogs.com/' target='_blank'>by 菩提树下的杨过</a>";
addChild(txtAuthor);
txtAuthor.y = txtFocusLength.y;
txtAuthor.x = 425;
txtAuthor.autoSize = TextFieldAutoSize.LEFT;

稍加解释:

z坐标:即对象在z轴上的坐标,flash默认采用的是右手三维坐标,也就是说z值越大,物体越小

rotaionX,rotationY,rotationZ:即对象绕着x,y,z轴旋转的角度

PerspectiveProjection对象的三个属性:

1.focalLength 即焦距,使用效果上貌似焦距越大,物体也越大(?跟常规理解的不同),而且据官方帮助上讲:在透视转换过程中,将使用视野的角度和舞台的高宽比(舞台宽度除以舞台高度)来自动计算 focalLength

2.fieldOfView 即观察点的三维"视角"(0到180之间的值),怎么理解我还没想好,不过在使用效果上,如果当物体的z轴坐标不为0时,该值越大,物体的扭曲和形变越夸张,而且动态调整该值时focalLength值也会自动重新计算。(所以如果用代码写死了focalLength,不管如何调整fieldOfView都是看不到效果的)

3.projectionCenter:即3D透视中的消失点,当z轴坐标趋近于无限大时,物体越趋向于该点(消失)。

 

最后:上面的代码中暗藏了二个小技巧

1.为啥要先把图片放到imgSprite中,然后再将imgSprite又放到containerSprite中?

因为旋转时有一个旋转的中心点,而Flash默认这个中心就是对象的左顶点,即(0,0)位置,用二个sprite嵌套后,再配合坐标的设定,巧妙的将中心点正好移动到了图片中心,如下图:

img_628bd776ee803f797da02d49276bc6f0.png

2.如何用代码从库里取出一张图片?

img_f3c75cb09e50e5a3b67ff64fd07e980d.jpg

如上图,关键在于导入图片时要指定“类”名,这样在代码中就可以用

var imgBD:BitmapData = new ImgSample();//从库中取出一张图片
var img:Bitmap = new Bitmap(imgBD);

得到一个图片的Bigmap实例

目录
相关文章
|
3月前
|
存储 弹性计算 Linux
阿里云服务器试用与购买参考:试用与购买流程及相关规则和注意事项
阿里云服务器购买与试用全指南,阿里云每年都会推出针对新用户的免费试用活动,帮助用户低成本体验云服务的强大功能。本文将为大家解析阿里云服务器的购买与试用流程,包括注册认证、领取免费额度、选择实例配置全流程,帮助新手用户快速上手,避免操作误区。
|
7月前
|
存储 人工智能 监控
大牛直播SDK在四足机器人和无人机巡检中的创新应用方案
在工业4.0和智能化浪潮下,传统巡检方式正经历深刻变革。四足机器人与无人机凭借灵活机动性和高效巡检能力崭露头角,而大牛直播SDK则赋予其实时直播与智能互动功能。本文介绍大牛直播SDK的核心优势、在四足机器人和无人机巡检中的应用方案,以及技术实现要点和未来展望,展示智能巡检的广阔前景。
171 6
|
3月前
|
机器学习/深度学习 人工智能 算法
AI量化交易软件开发技术逻辑
AI量化交易融合人工智能与量化分析,通过算法模型深度解析市场数据,自动生成并执行交易策略,显著提升交易效率与决策精准度。其开发涵盖目标分析、数据处理、算法设计、系统构建、测试优化、合规安全及持续迭代等多个关键环节,涉及金融、编程、大数据与AI等多领域技术。掌握这些核心技术,方能打造高效智能的量化交易系统,助力投资者实现更优收益。
|
4月前
|
存储 运维 监控
确定Ceph集群中OSD组件与具体物理磁盘的关联。
总结来说,确定Ceph集群中OSD与具体物理磁盘的关联需要搜集和对比Ceph集群的配置信息、OSD元数据、物理磁盘的详细信息,以及运行时的系统日志。这对于Ceph存储集群的维护和问题诊断至关重要,也有助于进行正常的运维活动,如扩容、升级或替换硬件。通过上述步骤,管理员可以直观且高效地管理和定位Ceph集群中的存储资源。
249 15
|
3月前
|
存储 安全 测试技术
理解功能需求
本文全面解析软件开发中的功能需求,涵盖定义、分类、实例及编写与管理的最佳实践。内容适用于业务分析师、项目经理和开发人员,助力构建高质量、符合用户期望的软件产品。
193 0
|
4月前
|
搜索推荐 应用服务中间件 PHP
深入理解301重定向:优化网站结构与SEO的必备技巧
本文详细介绍了301重定向的工作原理、应用场景及实现方法。301重定向是一种HTTP状态码,表示资源已永久移动到新URL,有助于保护网站SEO价值、提升用户体验和维护网站结构。文章还提供了在Apache、Nginx服务器以及PHP、Python等编程语言中实现301重定向的具体方法,并分享了最佳实践与注意事项,帮助用户平稳过渡网站变更,确保流量与权重不流失。
208 0
|
JavaScript Java 关系型数据库
Springboot+vue的员工绩效考核管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
Springboot+vue的员工绩效考核管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
|
存储 API C++
dump系列(2)C++程序异常或内存错误,导致闪退的解决办法:分析dump文件
dump系列(2)C++程序异常或内存错误,导致闪退的解决办法:分析dump文件
2033 0