在 3D 中反转旋转,使物体始终面向相机?

发布于 2024-10-27 09:51:31 字数 1294 浏览 1 评论 0原文

我有很多排列在 3D 空间中的精灵,并且它们的父容器应用了旋转。 我如何反转精灵 3D 旋转,使其始终面向相机(Actionscript 3)?

这是一个测试它的代码:

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
        }
    })
}
}
}

我猜我必须对精灵的旋转3D矩阵做一些魔法...... 我尝试实现此脚本: http://ughzoid.wordpress.com/2011/02/ 03/papervision3d-sprite3d/,但是非常成功
感谢您的帮助。

i have lots of sprites arranged in 3D space, and their parent container has rotations applied.
How do i reverse the sprites 3D rotation, that they always face the camera (Actionscript 3)?

heres a code to test it:

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
        }
    })
}
}
}

I am guessing i have to do some magic with the rotation3D matrices of the sprites...
I've tried to implement this script: http://ughzoid.wordpress.com/2011/02/03/papervision3d-sprite3d/ , but had so success
Thanks for help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

撩起发的微风 2024-11-03 09:51:31

最简单的方法是“清除”变换矩阵的旋转部分。典型的齐次变换看起来像这样

| 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。如果应用了某些缩放,则身份也需要缩放。

这给出了以下公式:

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

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

加载此矩阵允许您绘制相机对齐的精灵。

The easiest way to do this is "clearing" the rotational part of the transform matrix. Your typical homogenous transformation looks like this

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

with wx = wy = wz = 0, ww = 1. If you take a closer look you'll see that in fact this matrix is composed of a 3x3 submatrix defining the rotation, a 3 subvector for the translation and a homogenous row 0 0 0 1

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

For a billboard/sprite you want to keep the translation, but get rid of the rotation, i.e. R = I. In case some scaleing was applied the identity needs to be scaled as well.

This gives the following 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 |

Loading this matrix allows you to draw camera aligned sprites.

南街九尾狐 2024-11-03 09:51:31

我已经使用维基百科、矩阵和黑魔法解决了这个问题。我选择实现自定义旋转,而不是反转所有对象的旋转。
如果有人感兴趣的话,这里是代码:

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;
    }
}
}

I've solved it using Wikipedia, matrices and black magic. I choose to implement custom rotation instead of inverting the rotation of all objects.
Heres the code if anyones interested:

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);
        }
    })
}
}
}

and the matrix3 class:

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;
    }
}
}
月棠 2024-11-03 09:51:31

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

如果您的目的是模拟 3D 球形旋转,那么最简单的方法是放弃 2.5D API,而仅使用简单的缩放和正弦/余弦计算来进行定位。

一个有趣的起点:http://www.reflektions.com/miniml/template_permalink .asp?id=329

Apologies in advance for this being a suggestion, not a solution:

If your intent is simulate 3D spherical rotations, your easiest route would be to forego the 2.5D API and just use simple scaling and sin/cos calculations for the positioning.

A fun place to start: http://www.reflektions.com/miniml/template_permalink.asp?id=329

青春如此纠结 2024-11-03 09:51:31

,右侧的相机设置为面向四边形(左侧),因此它们的法线完全相反。当相机旋转时,为了使四边形仍然具有相反的法线,必须将四边形沿相反方向旋转与相机相同的角度。因此,我只需通过围绕 y 轴按 -camera.Yaw 旋转四边形即可产生正确的效果。

enter image description here

As you can see in the picture above, the camera on the right is set to face the quad (on the left), so that their normals are exactly opposite. When the camera is rotated, for the quad to still have an opposite normal, the quad would have to be rotated in the opposite direction the same angle as the camera. So, I was able to produce the right effect simply by rotating the quad by -camera.Yawaround the y-axis.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文