Inverting rotation in 3D, to make an object always face the camera?

前端 未结 4 908
暗喜
暗喜 2020-12-01 03:49

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 (Ac

相关标签:
4条回答
  • 2020-12-01 04:25

    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.

    0 讨论(0)
  • 2020-12-01 04:28

    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

    0 讨论(0)
  • 2020-12-01 04:33

    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;
        }
    }
    }
    
    0 讨论(0)
  • 2020-12-01 04:35

    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.

    0 讨论(0)
提交回复
热议问题