使用 3d Cameras

http://www.adobe.com/cn/devnet/flashplayer/articles/3d-cameras.html

介绍

这篇教程是对使用3d cameras的介绍,一个3d cameras 可以让开发者创建一个在3d场景中漫游的应用。在本教程中描述了编写一个以第一视角在3d场景中漫游的简单程序。

 

使用3d cameras

为了更好的解理3d cameras,设想你在拍一部电影。你必须建立一个场景并且需要一个camera。为了得到连接的镜头,你需要带着cameras在场景中漫步,从不同的角度和观察点拍下场景中的物体。

这与使用3d cameras是相同的拍摄过程。你需要一个虚拟的相机漫步于虚拟的场景中。

在观看世界时有两种流行的拍摄方法,一种是通过一个角色的眼睛(也就是第一视角),一种是把摄像机定在一个位置保持所有物体可见(也就是第三视角)

对3d cameras的基本作用:可以用于漫游于3d场景中并且在一个具体的视角渲染出连续的画面。

 

理解世界空间和观察空间

需要实现这种行为:你将渲染位于3d cameras观察点看到的所有3d世界中的物体,并不仅仅是世界坐标系的观察点,或其它观察点。

一般来过,一个3d场景包含一系列的3d模型,模型是由一系列的结点和三角形相对于它们自己的坐标系定义的。定义模型的空间叫做模型空间。

把模型放在3d场景中后,你可以用世界坐标转换矩阵对它他的结点进行转换。每一个物体有它们自己的坐标矩阵来说明他们的位置和方向。

这个新的参照系统被称作世界空间或全局空间,一个简单的方式去控制他就是通过变换矩阵关联每个物体。

为了实现3d cameras的行为,你必须按照以下步骤,你要参照世界坐标系统而不3d cameras自身的。

对待3d cameras的一个很好的方式就是把看成一个真实的3d物体,像其它3d物体一样,你使用世界坐标变换矩阵把3d cameras放在你期望的位置和期望的朝向。这个世界坐标转换矩阵把camera的方向期望的沿z轴角度转到实际的在世界中的位置。

 

图1展示了世界坐标系 (x, y, z) view视口坐标系 camera(x', y', z')间的关系

图1 世界坐标系与视口坐标系关系

 

 

 

 

现在你可能好奇一旦你增加一个3D cameras 到方程式中,之前教程(Working with Stage3D and perspective projection)说的投影变换矩阵,会发生什么。它的工作方式是这样的,你仍可以应用你最后的投影变换,因此,如果你要在3D cameras 的视点去渲染你的3d场景,你之前要应用3D cameras 的视口坐标变换,之后才能用投影变换。

因此,全部应用在3d场景里的3d模型的转换像这样。

model space -> world space

world space -> view space

view space -> projection space

 

3D camera 转换

在这部分你将学到如何加速世界坐标到视口坐标的转换

/camera的世界转换矩阵,把camera从世界原点的位置和它看上去的角度变换到3d实际的位置和角度。

设想你如同使用一个矩阵的属性一样使用转换。

protected var cameraWorldTransform:Matrix3D = new Matrix3D();

 

你可以通过改变矩阵来设置相机的位置。

cameraWorldTransform.appendRotation(20, Vector3D.Y_AXIS);

cameraWorldTransform.appendTranslation(2, 3, 5);

 

最后,为了把物体转换成他们从观察点看到的那样,你需要对camera的世界坐标矩阵反转。

viewTransform = cameraWorldTransform.clone()

viewTransform.invert();

 

之后,当你渲染每个物体时,仅仅是将viewTransform前乘每一个物体的worldTransform

 

建立一个 3D camera的应用程序

在这个小节,你将以创建一个简单的有漫游3d场景的3D camera程序。我会以 Working with Stage3D and perspective projection.中的教学代码开始。

 

一个camera键盘控制器

恰当处理 3D camera控制的过程并不像看起来的那么简单。一个好的 3D camera应该显得很自然。一个 3D camera不应该挡住用户的路。它应该感觉非常自然而忘了他的存在。

有太多的方法实现 3D camera控制器代码。控制一个 3D camera,可以如同严格控制相机每一步一样简单,通过限制用户按键时固定通过场景物体的数量。或者控制一个 3D camera,它可以附加一个风吹的物理系统并包括物体碰撞检测系统。

例子中解释了如何建一个简单的 3D camera 控制器,它可以使用恒定的加速度和一些减速来控制基于键盘交互的 3D camera。首先,你要先写一些代码还转换和旋转camera当用户按键时。以定义恒定的camera加速度开始,然后计算camera的周期来设置位置和角度。

 

 

 

 

 

protected const MAX_FORWARD_VELOCITY:Number = 0.05;

protected const MAX_ROTATION_VELOCITY:Number = 0.5;

protected const LINEAR_ACCELERATION:Number = 0.0005;

protected const ROTATION_ACCELERATION:Number = 0.01;

protected const DAMPING:Number = 1.09;

...

stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownEventHandler );

stage.addEventListener( KeyboardEvent.KEY_UP, keyUpEventHandler );

...

protected function keyDownEventHandler(e:KeyboardEvent):void

{

    switch (e.keyCode)

    {

        case 37: // left arrow

            cameraRotationAcceleration = -ROTATION_ACCELERATION;

            break

        case 38: // up arrow

            cameraLinearAcceleration = LINEAR_ACCELERATION;

            break

        case 39: // right arrow

            cameraRotationAcceleration = ROTATION_ACCELERATION;

            break;

        case 40: // down arrow

            cameraLinearAcceleration = -LINEAR_ACCELERATION;

            break;

    }

}

 

protected function keyUpEventHandler(e:KeyboardEvent):void

{

    switch (e.keyCode)

    {

        case 37: // left arrow

        case 39: // right arrow

            cameraRotationAcceleration = 0;

            break

        case 38: // up arrow

        case 40: // down arrow

            cameraLinearAcceleration = 0;

            break

    }            

}

 

 

基于键盘的输入,上面的两个键盘事件处理函数简单的设置了线性和角度的加速度。这些加速度一会在updateViewMatrix函数里用来计算计算位置和旋转角度。

在这个例子中,用户按左和右方向来旋转camera 3D camera的向上的轴一直指向上方,也就是说,camera将垂直的放在那指向前方。然后旋转camera会使它绕y轴转。updateViewMatrix 函数会以当前点作为注册点应用之个旋转角度。

 

当用户按向上和向下箭头时,可以把camera向前和向后移。现在这个camera在应用世界转换坐标矩阵之前会一直指向z,因此,在camera自身的坐标系中,整体向前的向量是(001)。因此camera向前周期的矢量仍在它本身的坐标系中,像这样(0, 0, forwardVelocity)

 updateViewMatrix函数计算它的位置,简单的通过将这个向前的周期矢量转换到世界坐标系中。

protected function updateViewMatrix():void

{

    cameraLinearVelocity.z = calculateUpdatedVelocity(cameraLinearVelocity.z, cameraLinearAcceleration, MAX_FORWARD_VELOCITY);

    cameraRotationVelocity = calculateUpdatedVelocity(cameraRotationVelocity, cameraRotationAcceleration, MAX_ROTATION_VELOCITY);

                

    cameraWorldTransform.appendRotation(cameraRotationVelocity, Vector3D.Y_AXIS, cameraWorldTransform.position);            

    cameraWorldTransform.position = cameraWorldTransform.transformVector(cameraLinearVelocity);            

    

    viewTransform.copyFrom(cameraWorldTransform);

    viewTransform.invert();

}

 

由于viewTransform作为cameraWorldTransform的逆函数,所以updateViewMatrix 函数也是3D camera魔法发生的地方,

 

下面的calculateUpdatedVelocity 函数简单的计算出以现在加速度开始更新的周期。

protected function calculateUpdatedVelocity(curVelocity:Number, curAcceleration:Number, maxVelocity:Number):Number

{

    var newVelocity:Number;

    

    if (curAcceleration != 0)

    {

        newVelocity = curVelocity + curAcceleration;

        if (newVelocity > maxVelocity)

        {

            newVelocity = maxVelocity;

        }

        else if (newVelocity < -maxVelocity)

        {

            newVelocity = - maxVelocity;

        }

    }

    else

    {

        newVelocity = curVelocity / DAMPING;

    }

    return newVelocity;

}

 

 

 

 

camera渲染

在开始控制之后,处理渲染的过程非常简单。在每一进行渲染之前,你将调用updateViewMatrix 

 

然后像这样

protected function onRender(e:Event):void

{

    ...

    updateViewMatrix();

 

    var m:Matrix3D = new Matrix3D();

    m.appendRotation(getTimer()/30, Vector3D.Y_AXIS);

    m.appendRotation(getTimer()/10, Vector3D.X_AXIS);

    m.appendTranslation(0, 0, 2);

    m.append(viewTransform);

    m.append(projectionTransform);

 

    context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);

    ...

}

全部原代码看原文章

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值