Comunidad de diseño web y desarrollo en internet online

Objetos 3D animados por Actionscript 3 usando drawTriangles

En Adobe Flash CS4 se introdujo el método drawTriangles() a la clase Graphics. Este método puede tener diversas aplicaciones pero en este caso escribiré acerca del manejo y creación de figuras tridimensionales a partir de triángulos.

Content on this page requires a newer version of Adobe Flash Player.

Get Adobe Flash player


Mueve el cursor sobre el cubo para poder manipularlo.

Antes de meternos en códigos recomendaría que hayan leído y comprendido o en su defecto tener un poco de conocimientos sobre cómo funciona el método drawTriangles(), una vez de acuerdo en ello lo que haremos sera crear un documento y seleccionar el primer fotograma clave que sera donde trabajaremos.

Una vez listos, comenzaremos creando un Sprite cuyo nombre sera "cubo" y lo añadiremos al escenario:

var cubo:Sprite = new Sprite();
addChild(cubo)

Luego tenemos que buscar con que rellenarlo, así es que crearemos los tres vectores que contendrán las coordenadas de los vértices (vector points) y los aristas:

var points:Vector.<Number> = new Vector.<Number>;
var vertices:Vector.<Number> = new Vector.<Number>;
var
aristas:Vector.<int> = new Vector.<int>; 

Comenzaremos con los vértices, que para hacerlos mas fácil modificar utilizare una contante llamada "largo" con un valor a 50.

var largo:int = 50
//
points = Vector.<Number>([   
largo, -largo, largo, // P1   
largo, -largo, -largo, // P2  
-largo, -largo, -largo, // P3
 -largo, -largo, largo, // P4  
 largo, largo, largo, // P5   
largo, largo, -largo, // P6  
-largo, largo, -largo, // P7  
-largo, largo, largo // P8
])

Atención, es por esto que hubiese sido bueno que leyeras esto ya que utilizando cada uno de los puntos ya fijos en sus coordenadas que formaran los vértices (vector points) fijaremos cada uno de los triángulos que como sabemos serán 2 por cada cara dando 12 triángulos en total:

aristas = Vector.<int>([
 2,5,1, // T1: P2-P5-P1  
3
,2,1, // T2: P3-P2-P1
 5,6,7, // T3: P5-P6-P7
 7,3,0, // T4: P7-P3-P0
 1,5,4, // T5: P1-P5-P4  
2
,6,5, // T6: P2-P6-P5  
1
,4,0, // T7: P1-P4-P0  
3
,6,2, // T8: P3-P6-P2  
3
,7,6, // T9: P3-P7-P6  
5
,7,4, // T10: P5-P7-P4
 3,1,0, // T11: P3-P1-P0
 7,0,4 // T12: P7-P0-P4
])

Con esto ya tenemos toda la información necesaria para dibujar los 12 triángulos que conformaran el cubo, ahora solamente falta graficar el cubo mismo con el método drawTriangles(). Para ello crearemos un Listener que ya sea activado por MOUSE_MOVE, o ENTER_FRAME cualquiera de los dos funcionara bien, pero en este caso utilizare el segundo:

ddEventListener(Event.ENTER_FRAME, eventHandler); 
// 
function eventHandler(event:Event):void 
{ 
 switch(event.type) 
 { 
   case Event.ENTER_FRAME: 
    cubo.graphics.clear(); // Borramos la bitmap que haya dentro de "cubo" 
    cubo.graphics.beginFill(0xCA0B45,1); // Fijamos el relleno 
    cubo.graphics.lineStyle(.1,0xA30736,1); // Fijamos también el contorno 
    cubo.graphics.drawTriangles(vertices, aristas, null, TriangleCulling.NEGATIVE); // Utilizamos el método 
    cubo.graphics.endFill(); // Cerramos el relleno 
 } // switch 
}

Bueno, un cubo aburrido, pero ¿que pasa con la interactividad? Para esto utilizaremos el paquete Matrix3D y Vector3D para poder rotar el cubo en cualquiera de sus tres ejes a base de la posición del cursor:

matrix3D.appendRotation((cubo.y - mouseY)/20, Vector3D.X_AXIS); // Fijamos la rotacion en el eje X matrix3D.appendRotation((cubo.x - mouseX)/20, Vector3D.Y_AXIS); // Fijamos la rotacion en el eje Y Utils3D.projectVectors(matrix3D, points, vertices, UVData); // Añadimos la matrix al cubo  

El código resultado seria el siguiente:

var cubo:Sprite = new Sprite(); 
cubo.x = cubo.y = 100; 
addChild(cubo); 
// 
var matrix3D:Matrix3D = new Matrix3D(); 
var points:Vector.<Number> = new Vector.<Number>; 
var vertices:Vector.<Number> = new Vector.<Number>; 
var aristas:Vector.<int> = new Vector.<int>; 
var UVData:Vector.<Number> = new Vector.<Number>; 
var largo:int = 50; 
// 
points = Vector.<Number>([ 
  largo, -largo, largo, 
  largo, -largo, -largo, 
 -largo, -largo, -largo, 
 -largo, -largo, largo, 
  largo, largo, largo, 
  largo, largo, -largo, 
 -largo, largo, -largo, 
 -largo, largo, largo 
]); 
// 
aristas = Vector.<int>([ 
 2,5,1,3,2,1,5,6,7,7,3,0,1,5,4,2,6,5, 
 1,4,0,3,6,2,3,7,6,5,7,4,3,1,0,7,0,4 
]); 
// 
addEventListener(Event.ENTER_FRAME, eventHandler); 
// 
function eventHandler(event:Event):void 
{ 
 switch(event.type) 
 { 
   case Event.ENTER_FRAME: 
    matrix3D.appendRotation((cubo.y - mouseY)/20, Vector3D.X_AXIS); 
    matrix3D.appendRotation((cubo.x - mouseX)/20, Vector3D.Y_AXIS); 
    Utils3D.projectVectors(matrix3D, points, vertices, UVData); 
    // 
    cubo.graphics.clear(); 
    cubo.graphics.beginFill(0xCA0B45,1); 
    cubo.graphics.lineStyle(.1,0xA30736,1); 
    cubo.graphics.drawTriangles(vertices, aristas, null, TriangleCulling.NEGATIVE); 
    cubo.graphics.endFill(); 
 } 
} 

Finalmente, si lo enfocamos hacia su manejo en una clase externa tendremos un resultado parecido a este:

package 
{ 
 // Cargamos los paquetes necesarios... 
 import flash.events.Event; 
 import flash.geom.Matrix3D 
 import flash.geom.Vector3D; 
 import flash.geom.Utils3D; 
 import flash.display.Sprite; 
 import flash.display.TriangleCulling; 
 // 
 public class Main extends Sprite 
 { 
   // La Matrix3D dara la rotacion al cubo 
   private var matrix3D:Matrix3D; 
   // Points sera cada uno de los puntos que ayudaran a acomodar los vértices 
   private var points:Vector.<Number>; 
   // Creo que señalar que formaran estos vectores esta de mas 
   private var vertices:Vector.<Number>; 
   private var aristas:Vector.<int>; 
   // El vector "UVData" obtendra las coordenadas U,V de cada triangulo 
   private var UVData:Vector.<Number>; 
   // "largo" representa el tamaño de "cubo" antes de dibujarlo 
   private var largo:int = 50; 
   private var cubo:Sprite = new Sprite(); 
   // 
   public function Main():void 
   { 
    addChild(cubo); 
    matrix3D = new Matrix3D(); 
    UVData = new Vector.<Number>; 
    vertices = new Vector.<Number>; 
    // Funciones encargadas de fijar los vertices y aristas 
    setPoints(); 
    setLines(); 
    // Añadimos el listener que renderizara el cubo 
    addEventListener(Event.ENTER_FRAME, eventHandler); 
   } 
   // Con esta funcion se van a fijar cada uno de los vertices 
   private function setPoints():void 
   { 
    // Asignamos las posiciones de cada vertice en ejes X,Y,Z 
    points = Vector.<Number>([ 
      largo, -largo, largo, // P1 
      largo, -largo, -largo, // P2 
      -largo, -largo, -largo, // P3 
      -largo, -largo, largo, // P4 
      largo, largo, largo, // P5 
      largo, largo, -largo, // P6 
      -largo, largo, -largo, // P7 
      -largo, largo, largo // P8 
    ]); 
   } 
   // Con esta funcion se van a fijar cada uno de los aristas 
   private function setLines():void 
   { 
    // Unimos cada uno de los puntos fijados en la funcion anterior 
    aristas = Vector.<int>([ 
      2,5,1, // T1: P2-P5-P1 
      3,2,1, // T2: P3-P2-P1 
      5,6,7, // T3: P5-P6-P7 
      7,3,0, // T4: P7-P3-P0 
      1,5,4, // T5: P1-P5-P4 
      2,6,5, // T6: P2-P6-P5 
      1,4,0, // T7: P1-P4-P0 
      3,6,2, // T8: P3-P6-P2 
      3,7,6, // T9: P3-P7-P6 
      5,7,4, // T10: P5-P7-P4 
      3,1,0, // T11: P3-P1-P0 
      7,0,4 // T12: P7-P0-P4 
    ]); 
   } 
   // 
   private function eventHandler(event:Event):void 
   { 
    switch(event.type) 
    { 
      case Event.ENTER_FRAME: 
       // Fijamos las coordenadas del cubo y su rotacion 
       cubo.x = cubo.y = 100; 
       matrix3D.appendRotation((cubo.y - mouseY)/20, Vector3D.X_AXIS); 
       matrix3D.appendRotation((cubo.x - mouseX)/20, Vector3D.Y_AXIS); 
       Utils3D.projectVectors(matrix3D, points, vertices, UVData); 
       // Finalmente "unimos" los puntos para formar el cubo 
       cubo.graphics.clear(); 
       cubo.graphics.beginFill(0xCA0B45,1); 
       cubo.graphics.lineStyle(.1,0xA30736,1); 
       cubo.graphics.drawTriangles(vertices, aristas, null, TriangleCulling.POSITIVE); 
       cubo.graphics.endFill(); 
    } 
   } 
 } 
}

Una vez dominado el tema, con un poco mas de tiempo se pueden crear figuras mucho mas convincentes cuyas bases son las mismas solo que con 500 vértices mas, y 1000 triángulos:

Content on this page requires a newer version of Adobe Flash Player.

Get Adobe Flash player

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate