zoukankan      html  css  js  c++  java
  • Flash/Flex学习笔记(51):3维旋转与透视变换(PerspectiveProjection)

    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嵌套后,再配合坐标的设定,巧妙的将中心点正好移动到了图片中心,如下图:

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

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

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

    得到一个图片的Bigmap实例

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    揭示同步块索引(下):总结
    关于.NET技术体系的思维导图
    嵌入式Linux中摄像头使用简要整理
    Tslib和Qt 4.8.4与在开发板上的移植
    图像处理经典图片Lena背后的故事
    Linux 下编译安装OpenCV
    Linux 下编译、安装、配置 QT
    Qt Creator的配置和开发初步测试
    OpenCV的第一个小程序:读取图像并显示
    转:智能手机Flash/DRAM选择、配置与价格大全
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1740377.html
Copyright © 2011-2022 走看看