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

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

    001
    import flash.events.Event;

    002
    import flash.display.Sprite;

    003
    import flash.text.TextField;

    004
    import flash.events.MouseEvent;

    005
    import flash.text.TextFieldAutoSize;

    006

    007
    var isAngleChangeing = false;

    008

    009
    var txtX:TextField,txtY:TextField,txtZ:TextField,txtPosZ:TextField,txtFieldOfView:TextField,txtInfo:TextField,txtCenter:TextField,txtFocusLength:TextField;

    010
    txtX = new TextField();

    011
    txtX.text = "rotationX:";

    012
    txtY = new TextField();

    013
    txtY.text = "rotationY:";

    014
    txtZ = new TextField();

    015
    txtZ.text = "rotationZ:";

    016
    txtPosZ = new TextField();

    017
    txtPosZ.text = "Z:";

    018
    txtFieldOfView = new TextField();

    019
    txtFieldOfView.text = "视角:";

    020
    txtCenter = new TextField();

    021
    txtCenter.text = "消失点:"

    022
    txtFocusLength = new TextField();

    023
    txtFocusLength.text = "焦距:";

    024
    txtX.y = txtY.y = txtZ.y = 5;

    025
    txtX.x = txtPosZ.x = 10;

    026
    txtPosZ.y = txtX.y + 26;

    027
    txtPosZ.x +=  40;

    028
    txtY.x = txtX.x + 180;

    029
    txtZ.x = txtY.x + 180;

    030
    txtFieldOfView.x = txtPosZ.x + 160;

    031
    txtFieldOfView.y = txtPosZ.y;

    032
    txtCenter.x = txtFieldOfView.x + 170;

    033
    txtCenter.y = txtPosZ.y;

    034
    txtInfo = new TextField();

    035
    txtInfo.text="";

    036
    txtFocusLength.x = txtX.x + 25;

    037
    txtFocusLength.y = txtPosZ.y + 25;

    038

    039
    var imgBD:BitmapData = new ImgSample();

    040
    var img:Bitmap = new Bitmap(imgBD);

    041
    trace("img.width=",img.width,",img.height=",img.height);

    042

    043
    var imgSprite:Sprite = new Sprite();

    044
    img.x =  -  img.width / 2;

    045
    img.y =  -  img.height / 2;

    046
    imgSprite.addChild(img);

    047
    trace("imgSprite.width=",imgSprite.width,",imgSprite.height=",imgSprite.height);

    048

    049
    var containerSprite:Sprite = new Sprite();

    050
    containerSprite.addChild(imgSprite);

    051
    imgSprite.x = img.width / 2;

    052
    imgSprite.y = img.height / 2;

    053

    054
    addChild(containerSprite);

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

    056

    057
    containerSprite.x = stage.stageWidth / 2 - containerSprite.width / 2;

    058
    containerSprite.y = stage.stageHeight / 2 - containerSprite.height / 2;

    059
    containerSprite.z = 50;

    060

    061
    var silderX:SimpleSlider = new SimpleSlider(0,360,0);

    062
    silderX.x = txtX.x + 160;

    063
    silderX.y = txtX.y + 7;

    064
    silderX.rotation = 90;

    065

    066
    var silderY:SimpleSlider = new SimpleSlider(0,360,0);

    067
    silderY.x = txtY.x + 160;

    068
    silderY.y = silderX.y;

    069
    silderY.rotation = 90;

    070

    071
    var silderZ:SimpleSlider = new SimpleSlider(0,360,0);

    072
    silderZ.x = txtZ.x + 160;

    073
    silderZ.y = silderX.y;

    074
    silderZ.rotation = 90;

    075

    076
    var silderPosZ:SimpleSlider = new SimpleSlider(-200,200,50);

    077
    silderPosZ.x = txtX.x + 160;

    078
    silderPosZ.y = silderX.y + 25;

    079
    silderPosZ.rotation = 90;

    080

    081
    var silderFieldOfView:SimpleSlider = new SimpleSlider(0.1,179.9,90);

    082
    silderFieldOfView.x = silderPosZ.x + 180;

    083
    silderFieldOfView.y = silderPosZ.y;

    084
    silderFieldOfView.rotation = 90;

    085

    086
    var silderCenterPos:SimpleSlider = new SimpleSlider(150,400,275);

    087
    silderCenterPos.x = silderFieldOfView.x + 180;

    088
    silderCenterPos.y = silderPosZ.y;

    089
    silderCenterPos.rotation = 90;

    090

    091
    var silderFocusLength:SimpleSlider = new SimpleSlider(100,500,300);

    092
    silderFocusLength.x = silderPosZ.x ;

    093
    silderFocusLength.y = silderPosZ.y + 25;

    094
    silderFocusLength.rotation = 90;

    095

    096
    addChild(txtX);

    097
    addChild(txtY);

    098
    addChild(txtZ);

    099
    addChild(txtPosZ);

    100
    addChild(txtFieldOfView);

    101
    addChild(txtInfo);

    102
    addChild(txtCenter);

    103
    addChild(txtFocusLength);

    104
    addChild(silderX);

    105
    addChild(silderY);

    106
    addChild(silderZ);

    107
    addChild(silderPosZ);

    108
    addChild(silderFieldOfView);

    109
    addChild(silderCenterPos);

    110
    addChild(silderFocusLength);

    111

    112
    silderX.addEventListener(Event.CHANGE,silderXChangeHandler);

    113
    silderY.addEventListener(Event.CHANGE,silderYChangeHandler);

    114
    silderZ.addEventListener(Event.CHANGE,silderZChangeHandler);

    115
    silderPosZ.addEventListener(Event.CHANGE,silderPosZChangeHandler);

    116
    silderFieldOfView.addEventListener(Event.CHANGE,silderFieldOfViewChangeHandler);

    117
    silderFieldOfView.addEventListener(MouseEvent.MOUSE_UP,function(){isAngleChangeing = false});

    118
    silderCenterPos.addEventListener(Event.CHANGE,silderCenterPosChangeHandler);

    119
    silderFocusLength.addEventListener(Event.CHANGE,silderFocusLengthChangeHandler);

    120

    121

    122
    function showTxtInfo(s:SimpleSlider){

    123
    txtInfo.text = s.value.toString().substr(0,5);

    124
    txtInfo.x = mouseX + 20;

    125
    txtInfo.y = s.y + 5;

    126
    }

    127

    128
    function silderXChangeHandler(e:Event):void {

    129
    imgSprite.rotationX = silderX.value;

    130
    showTxtInfo(silderX);

    131
    }

    132

    133
    function silderYChangeHandler(e:Event):void {

    134
    imgSprite.rotationY = silderY.value;

    135
    showTxtInfo(silderY);

    136
    }

    137

    138
    function silderZChangeHandler(e:Event):void {

    139
    imgSprite.rotationZ = silderZ.value;

    140
    showTxtInfo(silderZ);

    141
    }

    142

    143
    function silderPosZChangeHandler(e:Event):void {

    144
    containerSprite.z = silderPosZ.value;

    145
    showTxtInfo(silderPosZ);

    146
    }

    147

    148

    149
    function silderFieldOfViewChangeHandler(e:Event):void {

    150
    doPerspectiveProjection();

    151
    showTxtInfo(silderFieldOfView);

    152
    isAngleChangeing = true;

    153
    }

    154

    155
    function silderCenterPosChangeHandler(e:Event):void {

    156
    doPerspectiveProjection();

    157
    showTxtInfo(silderCenterPos);

    158
    }

    159

    160
    function silderFocusLengthChangeHandler(e:Event):void {

    161
    doPerspectiveProjection();

    162
    showTxtInfo(silderFocusLength);

    163
    }

    164

    165
    function doPerspectiveProjection():void{

    166
    var pp:PerspectiveProjection=new PerspectiveProjection();

    167
    pp.fieldOfView = silderFieldOfView.value;

    168
    if (!isAngleChangeing){

    169
    pp.focalLength  = silderFocusLength.value;  

    170
    }

    171
    //trace(pp.focalLength);

    172
    pp.projectionCenter = new Point(silderCenterPos.value,silderCenterPos.value);

    173
    containerSprite.transform.perspectiveProjection = pp;

    174

    175
    }

    176

    177
    doPerspectiveProjection();

    178

    179
    var txtAuthor:TextField = new TextField();

    180
    txtAuthor.htmlText ="<a href='http://yjmyzz.cnblogs.com/' target='_blank'>by 菩提树下的杨过</a>";

    181
    addChild(txtAuthor);

    182
    txtAuthor.y = txtFocusLength.y;

    183
    txtAuthor.x = 425;

    184
    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.如何用代码从库里取出一张图片?

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

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

    2
    var img:Bitmap = new Bitmap(imgBD);

    得到一个图片的Bigmap实例

  • 相关阅读:
    ViewState与Session [转]
    HTML5和HTML4的主要区别 [转]
    委托 与 Lambda
    ArcGIS 基础4-删除数据
    ArcGIS 基础3-新建数据
    ArcGIS 基础2-编辑数据
    ArcGIS 基础1-打开地图文档并浏览
    成都地铁线路图
    矢量数据库合并工具
    ArcGIS Pro试用下载步骤
  • 原文地址:https://www.cnblogs.com/happysky97/p/1884609.html
Copyright © 2011-2022 走看看