2011-03-29 15 views
5

tengo muchos sprites dispuestos en espacio 3D, y su contenedor principal tiene rotaciones aplicadas. ¿Cómo invierto la rotación 3D de los sprites, que siempre miran hacia la cámara (Actionscript 3)?¿Invertir la rotación en 3D para hacer que un objeto siempre mire hacia la cámara?

aquí hay un código para probarlo:

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

que supongo que tengo que hacer un poco de magia con las matrices rotation3D de los sprites ... he tratado de poner en práctica este script: http://ughzoid.wordpress.com/2011/02/03/papervision3d-sprite3d/, pero tuvo tanto éxito
Gracias por ayuda.

Respuesta

17

La manera más sencilla de hacerlo es "claro" la parte de rotación de la matriz de transformación. Su transformación homogénea típica se parece a esto

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

con wx = wy = wz = 0, ww = 1. Si se echa un vistazo más de cerca se verá que, de hecho, esta matriz se compone de una submatriz 3x3 definir el rotación, un subvector 3 para la traducción y una hilera homogénea 0 0 0 1

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

para una cartelera/sprite que desea mantener la traducción, pero deshacerse de la rotación, es decir, R = I. En caso de que algunos se aplicó la escala, la identidad también se debe escalar.

Esto da la siguiente 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 esta matriz le permite dibujar sprites alineado de la cámara.

+0

OK, la pregunta es: ¿cómo se obtiene la matriz "global" para cualquier objeto en particular, manipularlo como se describe, y luego volver a establecerlo en este sprite? ¡AFAIK, no puedes establecer una matriz de transformación "global" para un objeto, solo una "local"! ¿Podría el método "pointAt" Matrix3D resolver este problema? –

+0

@BillKotsias: es su responsabilidad rastrear las matrices de transformación de los objetos en su escena. Por lo general, tiene algún tipo de jerarquía de transformación: 'view · t_1 · t_2 · t_3 ...'. Esta es su matriz de transformación "global". Ahora bien, si desea dibujar algún objeto en esta cadena de transformación, pero hacerlo frente a la cámara, tome esa matriz compuesta y cámbiela de la manera que describí. Efectivamente, esto solo traduce el objeto en el lugar correcto de la vista sin alejarlo de la "cámara". – datenwolf

+0

No entiendo esto en absoluto. Solo escalaría el objeto y lo alejaría de la cámara, pero no "orientaría" el plano de modo que esté orientado hacia las cámaras (está orientado hacia la cámara ya que en la normalidad del plano es paralelo a la línea) desde el origen de la cámara al centro del avión). – user18490

1

Disculpas por adelantado para que esto sea una sugerencia, no una solución:

Si su intención es simular 3D rotaciones esféricas, la ruta más fácil sería renunciar a la API 2.5D y simplemente utilizar el escalamiento simple y sen/cos cálculos para el posicionamiento.

Un lugar divertido para empezar: http://www.reflektions.com/miniml/template_permalink.asp?id=329

+0

Creo que es más fácil usar la API 3D que viene con Flashplayer 10 (propiedad .z de displayobjects): esto permite un fácil posicionamiento en el espacio tridimensional. Si no encuentro una solución en 1-2 días, simulo la rotación con los cálculos de sin/cos, o use zedbox – sydd

+0

Absolutamente. Los dos métodos tienen diferentes 'apariencia' ya que los objetos de pantalla se convierten a mapas de bits cuando se usa 'z' o cualquiera de las rotaciones específicas del eje. Mira el método Matrix3D.invert(). – NickHubben

1

He resuelto que el uso de Wikipedia, matrices y la magia negro. Elijo implementar una rotación personalizada en lugar de invertir la rotación de todos los objetos. Heres el código si anyones interesados:

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

y las clases 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; 
    } 
} 
} 
Cuestiones relacionadas