2011-03-29 124 views
5

我有很多在三维空间排列的精灵,他们的父容器有旋转应用。 我如何反转精灵3D旋转,他们总是面对相机(Actionscript 3)?在3D中反转旋转,使对象始终面向相机?

继承人的代码进行测试:

package{ 
import flash.display.Sprite; 
import flash.events.Event; 
public class test extends Sprite{ 

var canvas:Sprite = new Sprite(); 
var sprites:Array = [] 

public function test(){ 
    addChild(canvas) 
    for (var i:int=0;i<20;i++){ 
     var sp:Sprite = new Sprite(); 
     canvas.addChild(sp); 
     sp.graphics.beginFill(0xFF0000); 
     sp.graphics.drawCircle(0,0,4); 
     sp.x = Math.random()*400-200; 
     sp.y = Math.random()*400-200; 
     sp.z = Math.random()*400-200; 
     sprites.push(sp); 
    } 
    addEventListener(Event.ENTER_FRAME,function():void{ 
     canvas.rotationX++; 
     canvas.rotationY = canvas.rotationY+Math.random()*2; 
     canvas.rotationZ++; 
     for (var i:int=0;i<20;i++){ 
      //this is not working... 
      sprites[i].rotationX = -canvas.rotationX 
      sprites[i].rotationY = -canvas.rotationY 
      sprites[i].rotationZ = -canvas.rotationZ 
     } 
    }) 
} 
} 
} 

我猜我必须做一些与魔法精灵的rotation3D矩阵... 我试图执行这个脚本:http://ughzoid.wordpress.com/2011/02/03/papervision3d-sprite3d/,但曾经如此成功
感谢您的帮助。

回答

17

最简单的方法是“清算”的变换矩阵的旋转部分。典型的同质转型看起来是这样的

| xx xy xz xw | 
| yx yy yz yw | 
| zx zy zz zw | 
| wx wy wz ww | 

与WX = WY = WZ = 0,WW = 1。如果你仔细看,你会看到,实际上这个矩阵是由一个3x3的子矩阵定义的旋转,3子向量的翻译和均匀排0 0 0 1

| R  T | 
| (0,0,0) 1 | 

对于要保留翻译,但摆脱了旋转,即R = I的情况下,一些广告牌/精灵规模应用,身份需要被缩放。

这给出以下recipie:

d = SQRT(xx²+yx²+zx²)

| d 0 0 T.x | 
| 0 d 0 T.y | 
| 0 0 d T.z | 
| 0 0 0 1 | 

加载这个矩阵可以绘制相机对准精灵。

+0

好的,问题是:你如何得到任何特定对象的“全局”矩阵,如你所描述的那样操纵它,然后将它设置回这个精灵? AFAIK,你不能设置一个“全局”转换矩阵到一个对象,只有一个“本地”的! “pointAt”Matrix3D方法能解决这个问题吗? – 2012-10-02 19:28:22

+0

@BillKotsias:您有责任跟踪场景中物体的变换矩阵。你通常有某种转换层次:'view·t_1·t_2·t_3 ...'。这是你的“全局”转换矩阵。现在,如果你想在这个转换链中画一些物体,但是使它面对相机,你可以采用这种复合矩阵并按照我所描述的方式进行改变。实际上,这只是将视图中的对象转换为视图中的正确位置,而不会将其从“相机”中移开。 – datenwolf 2012-10-02 19:34:59

+0

我完全不理解这一点。它只会缩放物体并将其移动一段距离,但它不会“定向”平面,使其面向相机(它面向相机,因为平面的法线与一条线平行从相机的原点到飞机的中心)。 – user18490 2015-01-17 13:55:25

1

道歉提前为这是一个建议,而不是一个解决方案:

如果你的目的是模拟3D球旋转,你的最简单的途径是放弃了2.5D API,只需使用简单的缩放和正弦/余弦计算定位。

一个有趣的地方开始:http://www.reflektions.com/miniml/template_permalink.asp?id=329

+0

我认为它更容易使用随Flashplayer 10(displayobjects的.z属性)一起提供的3D API - 这允许在3D空间中轻松定位。如果我在1-2天内没有找到解决方案,请用sin/cos计算模拟旋转,或者绝对使用zedbox – sydd 2011-03-29 20:18:21

+0

。这两种方法有不同的'外观',因为当使用'z'或任何特定于轴的旋转时,displayObjects被转换为位图。检查Matrix3D.invert()方法。 – NickHubben 2011-03-29 21:02:31

1

我已经使用维基百科,矩阵和黑魔法解决它。我选择实现自定义旋转而不是反转所有对象的旋转。如果任何人有兴趣 继承人的代码:

package{ 
import flash.display.Sprite; 
import flash.events.Event; 

public class test extends Sprite{ 

private var canvas:Sprite = new Sprite(); 
private var sprites:Array = [] 
private var rotx:Number=0,roty:Number=0,rotz:Number=0; 
private var mm:Matrix3 = new Matrix3(); 
public function test(){ 
    addChild(canvas); 
    canvas.x = canvas.y = 230 
    for (var i:int=0;i<30;i++){ 
     var sp:Sprite = new Sprite(); 
     canvas.addChild(sp); 
     sp.graphics.beginFill(0xFF0000); 
     sp.graphics.drawCircle(0,0,2); 
     sp.x = Math.random()*200-100; 
     sp.y = Math.random()*200-100; 
     sp.z = Math.random()*200-100; 
     sprites.push(sp); 
     rotx=0.06; //from top to bottom 
     //roty=0.1; //from right to left 
     rotz=0.1; //clockwise 
     mm.make3DTransformMatrix(rotx,roty,rotz); 
    } 
    addEventListener(Event.ENTER_FRAME,function():void{ 
     for (var i:int=0;i<sprites.length;i++){ 
      var s:Sprite = sprites[i]; 
      mm.rotateByAngles(s); 
     } 
    }) 
} 
} 
} 

和matrix3类:要做到这一点

public class Matrix3{ 

    private var da:Vector.<Number>; // rows 

    public function make3DTransformMatrix(rotx:Number,roty:Number,rotz:Number):void{ 
     var cosx:Number = Math.cos(rotx); 
     var cosy:Number = Math.cos(roty); 
     var cosz:Number = Math.cos(rotz); 
     var sinx:Number = Math.sin(rotx); 
     var siny:Number = Math.sin(roty); 
     var sinz:Number = Math.sin(rotz); 
     da = new <Number>[ 
      cosy*cosz, -cosx*sinz+sinx*siny*cosz, sinx*sinz+cosx*siny*cosz, 
      cosy*sinz, cosx*cosz+sinx*siny*sinz , -sinx*cosz+cosx*siny*sinz, 
      -siny ,   sinx*cosy  ,  cosx*cosy   ]; 
    } 

    public function rotateByAngles(d:DisplayObject):void{ 
     var dx:Number,dy:Number,dz:Number; 
     dx = da[0]*d.x+da[1]*d.y+da[2]*d.z; 
     dy = da[3]*d.x+da[4]*d.y+da[5]*d.z; 
     dz = da[6]*d.x+da[7]*d.y+da[8]*d.z; 
     d.x = dx; 
     d.y = dy; 
     d.z = dz; 
    } 
} 
}