Visualiza modelos de 3DS con Away3D 4.0 Beta
() translation by (you can also view the original English article)
En este tutorial aprenderemos cómo cargar y mostrar un archivo de modelo 3DS en Flash, usando Away3D 4.0 beta y la aceleración de hardware GPU de Stage3D.
Vista previa del resultado final
Echemos un vistazo al resultado final hacia el que estaremos trabajando:
Introducción
Para usar este tutorial necesitarás tener un modelo en 3D (exportado como un archivo .3ds) y su textura (como un archivo de imagen).
He creado un modelo en 3D simple de una tetera en Autodesk 3DS Max, y lo exporté a un archivo llamado Teapot.3DS junto con su archivo de textura separado, teapot.jpg. Puedes encontrar ambos archivos en la descarga de la fuente.
Necesitarás descargar un paquete SWC de Away3D 4.0.0 beta (también puedes encontrar este SWC en los archivos fuente).
Y debes saber que la versión de Away3D 4.0.0 beta usa las nuevas herramientas de Stage3D de Adobe Flash, lo que significa que puede usar la GPU para la aceleración de gráficos 3D.
Vamos a construir este ejemplo usando AS3 puro, compilado en FlashDevelop (puedes leer más sobre esto aquí). FlashDevelop es un IDE de AS3 gratuito, aunque solamente para Windows. Si prefieres usar otro IDE aún podrás seguir este tutorial.
Paso 1: Crea un nuevo proyecto
Si aún no lo tienes, asegúrate de descargar e instalar FlashDevelop. Ábrelo y crea un nuevo proyecto de AS3.



FlashDevelop creará una plantilla de proyecto AS3 vacía para tí. Usaremos la clase Main para todo nuestro código.
Paso 2: Opciones del compilador
Ve al menú Project (Proyecto), elige Properties (Propiedades) y cambia algunas opciones:
- Asigna el valor Flash Player 11.1 como plataforma destino.
- Cambia el tamaño del SWF a 550x400px.
- Configura el color de fondo para que sea negro.
- Cambia el valor de FPS a 40.



Si queremos ejecutar este tutorial desde el código HTML incrustado, tenemos que incluir el parámetro wmode=direct
en los parámetros del objeto Flash en el archivo HTML. Se verá de esta forma:
1 |
<object width="550" height="400" data="3DViewer.swf" type="application/x-shockwave-flash" wmode="direct"> |
2 |
<param name="src" value="3DViewer.swf" /> |
3 |
<param name="wmode" value="direct" /> |
4 |
</object>
|
En este tutorial vamos a cargar el archivo 3DS desde el almacenamiento local (en vez de hacerlo desde un servidor web), así que debemos cambiar algunas configuraciones en la pestaña Compiler Options (Opciones del Compilador). Asigna el valor False (Falso) a Use Network Services (Usar Servicios de Red).
Paso 3: Agrega la biblioteca Away3D
Obtén away3d-core-fp11_4_0_0_beta.swc
de los archivos fuente o descárgalo desde el sitio de Away3D.
Copia ese archivo al directorio lib de tu proyecto.
En FlashDevelop, haz clic con el botón derecho en el archivo SWC y elige Add to Library
(Añadir a la biblioteca).
Paso 4: Imports
Ahora vamos a comenzar a codificar con nuestro archivo Main.as
. Para empezar, tenemos que importar los archivos de biblioteca necesarios para que el programa configure el motor Away3D y los componentes Flash. Son bastantes, así que vamos a deshacernos de esa tarea:
1 |
// 3DS Model Viewer Tutorial
|
2 |
// by Vu Hoang Minh - www.3dgameflash.com
|
3 |
// Created for active.tutsplus.com
|
4 |
|
5 |
package
|
6 |
{
|
7 |
//Away3D classes
|
8 |
import away3d.cameras.lenses.PerspectiveLens; |
9 |
import away3d.containers.ObjectContainer3D; |
10 |
import away3d.containers.View3D; |
11 |
import away3d.entities.Mesh; |
12 |
import away3d.events.LoaderEvent; |
13 |
import away3d.loaders.Loader3D; |
14 |
import away3d.loaders.parsers.Max3DSParser; |
15 |
import away3d.materials.TextureMaterial; |
16 |
import away3d.textures.BitmapTexture; |
17 |
|
18 |
//General Flash classes for display and interaction
|
19 |
import flash.display.Bitmap; |
20 |
import flash.display.MovieClip; |
21 |
import flash.display.Shape; |
22 |
import flash.display.Sprite; |
23 |
import flash.events.Event; |
24 |
import flash.events.MouseEvent; |
25 |
import flash.geom.Vector3D; |
26 |
import flash.text.TextField; |
27 |
|
28 |
//Classes for loading the 3DS file from the hard drive
|
29 |
import flash.display.SimpleButton; |
30 |
import flash.events.IOErrorEvent; |
31 |
import flash.net.FileFilter; |
32 |
import flash.net.FileReference; |
33 |
import flash.net.URLRequest; |
34 |
import flash.system.Security; |
Paso 5: Inicializar el programa
Vamos a comenzar. Declararemos las variables que vamos a necesitar, a inicializar el motor 3D y a configurar el botón "Browse" ("Buscar") así como el campo de texto de salida de la depuración.
1 |
public class Main extends Sprite |
2 |
{
|
3 |
private var file:FileReference; |
4 |
private var view3d:View3D; |
5 |
private var loader:Loader3D; |
6 |
private var labelDebug:TextField; |
7 |
private var object3d:Mesh; |
8 |
|
9 |
public function Main():void |
10 |
{
|
11 |
//boilerplate loading code
|
12 |
if (stage) |
13 |
init(); |
14 |
else
|
15 |
addEventListener(Event.ADDED_TO_STAGE, init); |
16 |
}
|
17 |
|
18 |
private function init(e:Event = null):void |
19 |
{
|
20 |
//allow us to load a local file
|
21 |
Security.allowDomain("*"); |
22 |
|
23 |
removeEventListener(Event.ADDED_TO_STAGE, init); |
24 |
|
25 |
//init 3D engine
|
26 |
view3d = new View3D(); |
27 |
view3d.camera.lens = new PerspectiveLens(); |
28 |
view3d.camera.z = 100; |
29 |
addChild(view3d); |
30 |
|
31 |
//3D loader
|
32 |
initLoader(); |
33 |
|
34 |
//Button to open file browser
|
35 |
var mcBrowse:MovieClip = new MovieClip(); |
36 |
mcBrowse.graphics.beginFill(0xeeeeee); |
37 |
mcBrowse.graphics.drawRoundRect(1, 2, 100, 25, 7, 7); |
38 |
mcBrowse.graphics.endFill(); |
39 |
var labelBrowse:TextField = new TextField(); |
40 |
labelBrowse.text = "Browse"; |
41 |
mcBrowse.addChild(labelBrowse); |
42 |
mcBrowse.mouseChildren = false; |
43 |
mcBrowse.buttonMode = true; |
44 |
labelBrowse.x = 25; |
45 |
mcBrowse.addEventListener(MouseEvent.CLICK, onClick_mcBrowse); |
46 |
addChild(mcBrowse); |
47 |
|
48 |
//debug output
|
49 |
labelDebug = new TextField(); |
50 |
labelDebug.text = "..."; |
51 |
labelDebug.textColor = 0xff0000; |
52 |
labelDebug.selectable = false; |
53 |
labelDebug.y = mcBrowse.height / 2; |
54 |
labelDebug.width = 600; |
55 |
addChild(labelDebug); |
56 |
|
57 |
//file
|
58 |
file = new FileReference(); |
59 |
}
|
En las líneas 25-29 inicializamos los componentes de gráficos de Away3D. Creamos un nuevo View3D (un contenedor que almacena la cámara y los objetos), configuramos su lente y su cámara y lo agregamos a la lista de visualización.
Después de eso creamos un botón Browse (Buscar): dibujamos su fondo, agregamos su etiqueta, lo configuramos y lo agregamos a la lista de visualización.
Para facilitar el seguimiento del estado de carga de 3DS creamos una etiqueta de depuración, que es un campo de texto simple.
Finalmente, inicializamos una instancia de FileReference
para gestionar la búsqueda del archivo 3DS.
Paso 6: Inicializar el cargador de 3D
La siguiente tarea importante que debemos llevar a cabo es crear un cargador para modelos en 3D.
1 |
private function initLoader():void |
2 |
{
|
3 |
//clear all
|
4 |
removeEventListener(Event.ENTER_FRAME, onEnterFrame); |
5 |
while (view3d.scene.numChildren > 0) |
6 |
{
|
7 |
view3d.scene.removeChild(view3d.scene.getChildAt(0)); |
8 |
}
|
9 |
|
10 |
//init new 3D loader
|
11 |
Loader3D.enableParser(Max3DSParser); |
12 |
loader = new Loader3D(); |
13 |
loader.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onComplete_loader); |
14 |
loader.addEventListener(LoaderEvent.LOAD_ERROR, onError_loader); |
15 |
view3d.scene.addChild(loader); |
16 |
|
17 |
//config camera
|
18 |
view3d.camera.lookAt(loader.position); |
19 |
}
|
Esta función tiene tres secciones:
- Primero limpiamos todo, en caso de que nuestro programa haya sido ejecutado anteriormente.
- Después de eso, inicializamos una nueva instancia de
Loader3D
y le agregamos funciones de escucha que se activarán cuando se lance un Error al cargar un archivo 3D por completo. Para hacerlo visible, lo añadimos a la escena deView3D
. - Para asegurarnos de que verdaderamente podamos ver el objeto una vez que haya sido cargado, le indicamos a la cámara que apunte hacia él.
Paso 7: Gestionar todos los eventos
A continuación vamos a añadir todas las funciones manejadoras de eventos, todas las cuales tienen qué ver con la carga del archivo de 3DS.
1 |
private function onClick_mcBrowse(e:MouseEvent):void |
2 |
{
|
3 |
file.browse([new FileFilter("3DS", "*.3ds")]); |
4 |
file.addEventListener(Event.SELECT, onFileSelected); |
5 |
file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); |
6 |
file.addEventListener(IOErrorEvent.IO_ERROR, onIOError); |
7 |
}
|
8 |
|
9 |
private function onSecurityError(e:Event):void |
10 |
{
|
11 |
labelDebug.text += ".Security Error!"; |
12 |
}
|
13 |
|
14 |
private function onIOError(e:IOErrorEvent):void |
15 |
{
|
16 |
labelDebug.text += ".File not found Error!"; |
17 |
}
|
18 |
|
19 |
private function onFileSelected(e:Event):void |
20 |
{
|
21 |
labelDebug.text = "File :" + file.name; |
22 |
file.removeEventListener(Event.SELECT, onFileSelected); |
23 |
file.addEventListener(Event.COMPLETE, onFileLoaded); |
24 |
file.load(); |
25 |
}
|
26 |
|
27 |
private function onFileLoaded(e:Event):void |
28 |
{
|
29 |
file.removeEventListener(Event.COMPLETE, onFileLoaded); |
30 |
initLoader(); |
31 |
loader.loadData(e.target.data); |
32 |
}
|
33 |
|
34 |
private function onError_loader(e:LoaderEvent):void |
35 |
{
|
36 |
trace("Error loading File..."); |
37 |
labelDebug.text += " .Loading Error"; |
38 |
}
|
39 |
|
40 |
private function onComplete_loader(e:LoaderEvent):void |
41 |
{
|
42 |
trace("3D File loaded"); |
43 |
labelDebug.text += " .Complete.Rendering..."; |
44 |
loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, onComplete_loader); |
45 |
loader.removeEventListener(LoaderEvent.LOAD_ERROR, onError_loader); |
46 |
object3d = Mesh(loader.getChildAt(0)); |
47 |
view3d.scene.addChild(object3d); |
48 |
loader.dispose(); |
49 |
loader = null; |
50 |
|
51 |
addEventListener(Event.ENTER_FRAME, onEnterFrame); |
52 |
}
|
Cuando el usuario haga clic en el botón Browse (Buscar), mostramos el File Browse Dialog, o cuadro de diálogo de búsqueda de archivos, que usa un FileFilter
para restringir los archivos mostrados y que sean solamente aquellos que tengan una extensión .3ds
. Agregamos varios manejadores de eventos a este cuadro de diálogo para poder identificar si un archivo ha sido detectado o si ocurre un error.
Después de que un archivo haya sido seleccionado, lo cargamos en la instancia de FileReference
que inicializamos anteriormente. Una vez que haya cargado, invocamos a la función initLoader()
que definimos en el paso anterior y que carga nuestro modelo en 3D.
En este punto hay dos estados posibles que podemos detectar:
- Uno es el estado de "error", que implica que nuestro programa no puede cargar el archivo del modelo en 3D (tal vez la ruta es incorrecta, o el archivo de mapa de texturas es el equivocado...).
- El otro es el evento "loaded successfully" ("cargado exitosamente", durante el que enviamos el archivo cargado a un
Mesh
y lo añadimos a la escena delView3D
.
Para liberar nuestra memoria y reutilizarla más adelante, debemos deshacernos de nuestro cargador.
Al final del código anterior (asumiendo que el archivo fue cargado) agregamos un evento ENTER_FRAME
, que usaremos para renderizar el objeto. Ahora escribiremos ese manejador.
Paso 8: Iniciar el ciclo de renderizado
Ahora que todo ha sido inicializado, estamos listos para renderizarlo todo. Con cada cuadro, haremos que el objeto en 3D se mueva (gire) e invocaremos a la función render()
de View3D
para actualizar la vista.
1 |
private function onEnterFrame(e:Event):void |
2 |
{
|
3 |
object3d.yaw(1); //yaw by one unit |
4 |
view3d.render(); |
5 |
}
|
Paso 9: ¡Compila y ejecuta!
¡Casi listo! compila tu SWF con F5 y observa tu resultado final. Muy interesante, ¿verdad?.
No puedes hacer más que simplemente girar el objeto. Intenta invocando object3d.moveFoward(10)
u object3d.pitch(1)
. Incluso podrías hacer esto en respuesta al movimiento del ratón o a la pulsación de una tecla.
Solamente como referencia, y para asegurarte de que hayas usado los nombres de archivos y ubicaciones correctas para todo, ésta es la manera en la que debería verse tu proyecto de FlashDevelop:

Conclusión
Hemos terminado nuestro primer tutorial de 3D básico sobre la función de aceleración 3D más reciente de Adobe. De manera cálida, animo a todos los lectores que se pongan en contacto conmigo a través de los comentarios, o a través de mi sitio web, en cualquier momento. Gracias por leer. Hasta la próxima. ¡Buena suerte y QUE TE DIVIERTAS!.