Flash制作3D类动画的教程
脚本之家
继续上次的学习,接下来要试试摄像机的移动了。
这里需要涉及几个概念,摄像机的坐标(x, y, z)和视觉角度(LookAt)
摄像机的位置可以使用(x, y, z)来定位;
视觉角度可以定义如何通过窗口来看场景。
lookAt(p_nX:Number, p_nY:Number, p_nZ:Number)
如:lookAt(0,0,0);//可以理解为通过摄像机的位置看场景。
摄像机的移动方式比较有意思,如果直接修改x、y、z坐标,视觉效果会与现实看到的情况相同;
而tilt、pan则是与场景平行移动;
roll是以z轴移动,通过摄像机视野看上去是摄像机的旋转效果。
额外说一下 Line3D 是在场景中绘制了线段,这里用做参考线,代码不难理解我就不过多解释了。
代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.ui.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.net.URLRequest;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;
import sandy.core.data.*;
/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.x = 100;
camera.y = 100;
camera.z = -300;
camera.lookAt(0,0,0);
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
}
var box = new Box("box", 100, 100, 100);
var Plane:Plane3D;
public function createScene() {
var g:Group = new Group();
//在场景画一个坐标定位点
Plane = new Plane3D("Texture", 300, 300);
var myXLine:Line3D = new Line3D( "x-coord", new Point3D( -20, 0, 0), new Point3D( 20, 0, 0 ));
var myYLine:Line3D = new Line3D( "y-coord", new Point3D(0, -20, 0), new Point3D( 0, 20, 0 ));
var myZLine:Line3D = new Line3D( "z-coord", new Point3D(0, 0, -20), new Point3D( 0, 0, 20 ));
g.addChild(myXLine);
g.addChild(myYLine);
g.addChild(myZLine);
g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
public function keyPressed(_evt:KeyboardEvent):void {
switch(_evt.keyCode) {
case Keyboard.UP:
camera.tilt += 2;
//camera.y -= 2;
break;
case Keyboard.DOWN:
camera.tilt -= 2;
//camera.y += 2;
break;
case Keyboard.RIGHT:
camera.pan -= 2;
//camera.x += 2;
break;
case Keyboard.LEFT:
camera.pan += 2;
//camera.x -= 2;
break;
case Keyboard.CONTROL:
camera.roll += 2;
break;
case Keyboard.PAGE_DOWN:
camera.z -= 5;
break;
case Keyboard.PAGE_UP:
camera.z += 5;
break;
}
}
}
}
效果:
还有场景自适应的问题,需要说明一下。
摄像机的镜头可视角度使用 fov(vertical field of view angle)来定义。
换算公式:
var fl:Numer = (viewport.height / 2) / Math.tan (camera.fov / 2 * (Math.PI / 180));
代码:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.ui.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;
import sandy.core.data.*;
/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.x = 100;
camera.y = 100;
camera.z = -300;
camera.lookAt(0,0,0);
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
stage.addEventListener (Event.RESIZE, onResize);
}
var box = new Box("box", 100, 100, 100);
var Plane:Plane3D;
public function createScene() {
var g:Group = new Group();
//在场景画一个坐标定位点
Plane = new Plane3D("Texture", 300, 300);
var myXLine:Line3D = new Line3D( "x-coord", new Point3D( -20, 0, 0), new Point3D( 20, 0, 0 ));
var myYLine:Line3D = new Line3D( "y-coord", new Point3D(0, -20, 0), new Point3D( 0, 20, 0 ));
var myZLine:Line3D = new Line3D( "z-coord", new Point3D(0, 0, -20), new Point3D( 0, 0, 20 ));
g.addChild(myXLine);
g.addChild(myYLine);
g.addChild(myZLine);
g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
function onResize (e:Event):void{
// 获取场景宽高
var w:Number = stage.stageWidth;
var h:Number = stage.stageHeight;
// 设置视野宽高
scene.camera.viewport.width = w;
scene.camera.viewport.height = h;
// 获取物体box与摄像机间的距离
var d:Number = box.getPosition ("camera").getNorm ();
// 保持摄像机观看比例
scene.camera.fov = 2 * Math.atan2 (h / 2, d) * (180 / Math.PI);
// 执行渲染
scene.render();
}
}
}
效果: