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实例

posted @ 2010-11-22 17:49  模西的哥哥  阅读(429)  评论(0编辑  收藏  举报