Continuando desde la parte 1, en la que nos enfrentamos con Papervision3D, la parte 2 lleva nuestra escena un poco más lejos. En esta parte final, aprenderá cómo hacer que sus cubos giratorios salten al espectador con gafas 3D..
Sé que dice que este tutorial es sobre Papervision3D en Flash, pero en realidad se trata de engañar a tu cerebro. Haremos que tu cerebro piense que está mirando un objeto 3D real, cuando en realidad solo está viendo una imagen 2D.
Si está familiarizado con Papervision3D, podrá seguir esto mediante el uso de cualquier proyecto que tenga una escena, una cámara y una ventana. Si no, revisa la Parte 1 de este tutorial primero, ya que continuaré desde donde lo dejamos. Aquí está el tipo de cosas en las que trabajaremos:
Apunte su dedo en el aire y manténgalo en frente de su nariz.
Míralo solo con el ojo derecho abierto y luego con el izquierdo. Vea cómo parece saltar de izquierda a derecha, mientras que lo que está en el fondo apenas parece moverse.?
Su cerebro nota estas diferencias entre lo que ve cada uno de sus ojos y los utiliza para generar una simulación 3D completa del mundo que lo rodea. En tu cabeza. Instantáneamente. Muy impresionante!
Si vamos a engañar a su cerebro, tendremos que hacer que cada uno de sus ojos vea una imagen diferente. Entonces, para comenzar, agreguemos otro "ojo" (otra cámara) a la escena. Esto se utilizará para crear la imagen para su ojo derecho, mientras que la imagen de la cámara existente se enviará al ojo izquierdo.
Crear una nueva variable pública llamada camera2...
public var camera2: Camera3D;
... e inicializarlo en la función constructora Main ():
cámara = nueva Camera3D ();
Necesitaremos otra vista para tomar la salida de la cámara, así que agregue lo siguiente:
public var viewport2: Viewport3D;
viewport2 = new Viewport3D (); viewport2.autoScaleToStage = true; // esto hará que la ventana gráfica sea tan grande como el escenario addChild (viewport2);
(Estoy corriendo a través de esto, ya que lo cubrimos todo la última vez.)
Recuerda, viewport2 Estará en blanco hasta que le prestemos algo. No necesitamos crear un nuevo renderizador para esto; solo usa el existente dos veces. Entonces, en Main (), toma este código:
renderer = new BasicRenderEngine (); renderer.renderScene (escena, cámara, ventana gráfica);
... y agregue una nueva línea para representar la segunda cámara en la segunda ventana, de esta manera:
renderer = new BasicRenderEngine (); renderer.renderScene (escena, cámara, ventana gráfica); renderer.renderScene (escena, camera2, viewport2);
Haga lo mismo en su función onEnterFrame (), también:
renderer.renderScene (escena, cámara, ventana gráfica); renderer.renderScene (escena, camera2, viewport2);
Si prueba esto ahora, bueno, se verá igual que antes:
Pero eso no es una sorpresa: por un lado, las dos cámaras están exactamente en el mismo lugar!
Por defecto, las cámaras se colocan en (x = 0, y = 0, z = -1000) - puede verificar haciendo traza (camera.x, camera.y, camera.z).
Así visto desde arriba, la escena se ve así:
Visto de lado, es así:
Para imitar adecuadamente nuestros propios ojos, deberíamos colocar nuestra segunda cámara un poco a la derecha de la primera:
Intentemos moverlo 50 píxeles a la derecha y veremos qué sucede. Ponga esto en Main (), en algún lugar después de crear la segunda cámara:
camera2.x = camera.x + 50;
Ahora pruébalo y ve lo que obtienes:
Parece raro, pero claramente está funcionando! El área alrededor de los cubos es transparente en cada vista, por lo que el primero se puede ver detrás del segundo..
Será útil poder ver lo que está viendo cada cámara individualmente, así que vamos a profundizar en la analogía ocular al hacerles un "guiño" cuando hacemos clic. Primero, agregue un detector de eventos a cada ventana gráfica, para detectar los clics del mouse:
viewport.addEventListener (MouseEvent.CLICK, onClickViewport); viewport2.addEventListener (MouseEvent.CLICK, onClickViewport2);
Pon eso al final de la función Main (). No te olvides de importar MouseEvent:
import flash.events.MouseEvent;
Agregue estas nuevas funciones a su código, fuera de la función Main () pero dentro de la clase Main:
función pública onClickViewport (mouseEvt: MouseEvent): void función pública onClickViewport2 (mouseEvt: MouseEvent): void
Cuando hacemos clic en la primera ventana gráfica, necesitamos que se vuelva invisible mientras que la segunda se hace visible (y viceversa para cuando hacemos clic en la segunda ventana). Así que modifica tus manejadores de eventos de esta manera:
función pública onClickViewport (mouseEvt: MouseEvent): void viewport.visible = false; viewport2.visible = true; función pública onClickViewport2 (mouseEvt: MouseEvent): void viewport.visible = true; viewport2.visible = falso;
Pruébalo:
Tenga en cuenta que tiene que hacer clic en uno de los cubos; las áreas transparentes no disparan un CLICK MouseEvent.
Vas a necesitar un par de gafas 3D "anaglifo"; el tipo donde cada lente es de un color diferente. El par que estoy usando tiene una lente amarilla en el ojo izquierdo y una azul en el ojo derecho (llamado el sistema ColorCode3D), pero otras combinaciones de colores también son populares, como el rojo y el cian..
Puede encontrar estas gafas en eBay por unos pocos dólares: solo busque Gafas 3d
Alternativamente, incluso podrías hacer el tuyo! André publicó un comentario en la primera parte de este tutorial explicando que usa cajas de Tic-Tac de diferentes colores para hacer las suyas. Genio!
Aunque mis ejemplos se harán para gafas amarillas y azules, trataré de explicar los principios para que puedas hacer que el tuyo funcione con cualquier color que tengas. Es un poco complicado, así que por favor publique un comentario a continuación si esto se vuelve confuso!
Cada píxel en su computadora es como un grupo de tres bombillas: una roja, una verde y una azul.
Al ajustar el brillo de cada "bombilla" podemos alterar el color de ese píxel:
Las lentes de las gafas 3D evitan que la luz de algunas de esas bombillas se filtre. Por ejemplo, la lente azul en mis lentes impide que la luz roja y verde llegue a mi ojo.
Entonces, si miro esta imagen a través de mi lente azul, no podré leerla:
Ninguna luz llega a mi ojo desde el área negra porque las tres bombillas están apagadas. Y ninguna luz llega a mi ojo desde el área verde, porque solo la bombilla verde está encendida, y la lente azul filtra eso. Así que todo lo que veo es un rectángulo negro..
Ahora bien, si lo intentas tú mismo, puedes encontrar que esto no es del todo cierto. Es probable que su lente no sea 100% azul puro, por lo que dejará pasar un poco de luz verde y roja. O tal vez los colores de su monitor estén calibrados de manera diferente a los míos, por lo que el texto verde tiene una pequeña cantidad de rojo y azul. Para ser honesto, lo mismo es cierto para mí, pero no importa, siempre que el texto sea difícil leer.
Nuestro objetivo es dificultar que su ojo derecho vea la imagen de la cámara izquierda, y lo mismo ocurre con su ojo izquierdo y la cámara derecha..
La lente azul está sobre mi ojo derecho, por lo que en teoría si elimino todo el azul de la imagen de la cámara izquierda, no podré verlo con mi ojo derecho.
En este paso, entonces, hagamos que la imagen de la ventana izquierda solo emita luz roja y verde; No hay luz azul en absoluto. Podemos hacer esto usando un ColorTransform. Estos son fáciles de configurar; Primero, importa la clase:
importar flash.geom.ColorTransform;
Luego, crea una nueva variable pública para mantener una instancia de la clase:
public var leftViewportColorTransform: ColorTransform;
Ahora crea esta nueva instancia dentro de Main ():
leftViewportColorTransform = new ColorTransform ();
Finalmente, dígale a Flash que aplique este ColorTransform a la ventana de visualización de la cámara izquierda:
viewport.transform.colorTransform = leftViewportColorTransform;
(Esa última línea debe ser después de haber creado la ventana gráfica y la transformación de color. Probablemente sea más fácil ubicarlo al final de Main ()).
El SWF no se verá diferente todavía, porque ColorTransform no cambia la imagen en absoluto de forma predeterminada.
Podemos elegir qué fracción de la luz de cada bombilla queremos dejar a través cambiando la azul multiplicador, verde multiplicador y redMultiplier Propiedades de nuestro ColorTransform..
Configurando cualquiera de estos para 1 le dice a Flash que lo deje solo, mientras lo configura 0 Le dice a Flash que lo apague por completo. Y, naturalmente, 0.5 Lo hará salir la mitad de la cantidad normal., 2.0 Lo hará doblarlo, y así sucesivamente..
Así que para drenar todo el azul de la ventana izquierda, podemos hacer esto:
leftViewportColorTransform.blueMultiplier = 0;
Debe colocar eso antes de la línea que aplica la transformación a la ventana gráfica, de esta manera:
leftViewportColorTransform.blueMultiplier = 0; viewport.transform.colorTransform = leftViewportColorTransform;
Si sus lentes tienen una lente roja o verde sobre el ojo derecho, entonces debe configurar el redMultiplier o verde multiplicador a 0, en lugar del azul. Para cualquier otro color, deberá usar una mezcla de rojo, verde y azul, más sobre esto en el Paso 15.
Probar el SWF:
Es difícil distinguir la "a" del logotipo a través de la lente azul, pero no es difícil distinguir la forma de los cubos sobre ese fondo blanco!
Si cambia el fondo de su SWF, verá el problema. Debido a que el área "blanca" alrededor de los cubos no es realmente blanca, sino más bien transparente y deja que se vea el fondo blanco del SWF, no se ve afectado por el ColorTransform.
Para solucionar este problema, debemos darle a la ventana gráfica un fondo blanco sólido en el que se representarán los cubos. Eso es bastante fácil; solo vuelve a donde creaste la ventana:
viewport = new Viewport3D (); viewport.autoScaleToStage = true; // Esto hará que la ventana sea tan grande como el escenario.
... y agrega un par de líneas para dibujar un rectángulo blanco que sea tan grande como el escenario:
viewport = new Viewport3D (); viewport.autoScaleToStage = true; // esto hará que la ventana gráfica sea tan grande como el escenario viewport.graphics.beginFill (0xffffff); // 0xffffff es blanco viewport.graphics.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Prueba de nuevo:
La imagen debe ser realmente tenue, opaca y difícil de ver a través de la lente derecha, pero tan fácil como la imagen normal para ver a través de la lente izquierda.
Necesitamos hacer lo mismo para la vista correcta ahora. Entonces, crea tu nuevo ColorTransform:
public var rightViewportColorTransform: ColorTransform;
rightViewportColorTransform = new ColorTransform ();
Ahora, aplique esta nueva transformación a la ventana derecha:
viewport2.transform.colorTransform = rightViewportColorTransform;
Como mi lente izquierda es amarilla, necesito drenar todo el amarillo de esta ventana..
(Si su lente izquierda es roja, este paso es fácil; simplemente configure el redMultiplier de su nuevo ColorTransform a 0.)
Pero, ¿cómo conseguimos que el amarillo salga de rojo, verde y azul??
Si estuviéramos usando pinturas, no podríamos; El amarillo es un color primario en ese caso. Pero cuando se trata de la luz, las cosas son diferentes. Mira esto:
Imagen de Wikimedia Commons. Gracias, Mike Horvath y Jacobolus.!
Como puede ver, el rojo y el verde se mezclan para hacer el amarillo (lo que explica por qué el fondo de la ventana izquierda se volvió amarillo cuando eliminamos todo el azul). Así que para eliminar todo el amarillo de nuestra imagen, necesitamos eliminar todo el rojo y todo el verde!
Podemos hacer esto así:
rightViewportColorTransform = new ColorTransform (); rightViewportColorTransform.redMultiplier = 0; rightViewportColorTransform.greenMultiplier = 0; viewport2.transform.colorTransform = rightViewportColorTransform;
Ah, claro, también tenemos que completar el fondo de esta ventana gráfica..
Haz esto de la misma manera que antes:
viewport2 = new Viewport3D (); viewport2.autoScaleToStage = true; // esto hará que la ventana gráfica sea tan grande como el escenario viewport2.graphics.beginFill (0xffffff); // 0xffffff es blanco viewport2.graphics.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Pruébalo
La lente amarilla en mis lentes realmente deja pasar una buena cantidad de luz azul, pero aún es mucho más oscura cuando se ve a través de esa lente que cuando se ve a través de la lente azul, y eso es lo que importa.
Así que tenemos nuestras dos imágenes configuradas y transformadas en color. El problema es que en este momento solo podemos ver uno de ellos a la vez..
La forma más obvia de ver los dos a la vez es reducir el alfa (la transparencia) de la ventana gráfica en la parte frontal, de esta manera:
viewport2.alpha = 0.5;
Prueba esto:
Ah OK, no es un gran éxito. Alpha claramente no es la herramienta adecuada para el trabajo; que mas tenemos?
Flash nos da la opción de varios diferentes modos de mezcla, Métodos de mezclar dos objetos de visualización juntos. Aquí hay una lista completa de ellos, pero me centraré en el llamado añadir.
los añadir el modo de mezcla atraviesa cada píxel de las dos imágenes y agrega el brillo de cada una de las tres bombillas.
Entonces, si un píxel en particular en la primera imagen tiene la bombilla verde completamente encendida y los otros dos completamente apagados, y el mismo píxel en la segunda imagen tiene la bombilla azul completamente encendida y los otros dos completamente apagados, entonces cuando se combinan el verde y las bombillas azules estarán completamente encendidas y la bombilla roja estará completamente apagada.
Si la primera y la segunda imagen tienen la bombilla roja a la mitad y las otras dos completamente apagadas, entonces la imagen combinada tendrá la bombilla roja completamente encendida, mientras que las otras dos permanecerán apagadas.
¿Obtener la imagen? Genial, vamos a usarlo. Borre la línea que acabamos de escribir que ajustó el alfa, y reemplácela con esto:
viewport2.blendMode = "agregar";
(No necesitamos aplicar el modo de fusión a ambas vistas, solo la que está en la parte superior de la lista de visualización).
Pruébalo
Eso es más parecido!
Si lo mira a través de un ojo a la vez, debe notar que cada ojo ve una vista diferente de forma más promintente. Probablemente también podrá ver un fantasma débil de la otra ventana, pero eso no es un problema; tu cerebro puede ignorar eso.
Sin embargo, la imagen aún no se ve en 3D. Vamos a arreglar eso.
Aunque tus ojos están viendo imágenes diferentes, esto no es suficiente para engañar a tu cerebro. Tu cerebro es bastante inteligente, ya ves; Algunos incluso dirían que es el órgano más inteligente de tu cuerpo. Sabe que debe usar otras pistas para determinar si un objeto es 3D o no. Perspectiva, por ejemplo: qué tan pequeño debe verse un objeto en función de lo lejos que está.
El principal problema aquí es que nuestras dos cámaras están separadas mucho más entre sí que nuestros propios ojos. Eso no es sorprendente, ya que elegí el número 50 al azar.
La distancia real de separación que deberíamos usar dependerá de una serie de cosas, como a qué distancia está usted del monitor y qué tan grande es su pantalla, por lo que no puedo darle un número mágico para usar. Tendremos que resolverlo manualmente..
Podríamos hacer esto probando muchos números diferentes uno por uno, pero esto es tedioso y durará para siempre. Tengo una mejor idea.
Agregue esta línea a su función onEnterFrame ():
camera2.x = camera.x + (mouseX * 0.1);
Ahora cambie sus funciones onClickViewport y onClickViewport2 a lo siguiente:
función pública onClickViewport (mouseEvt: MouseEvent): void trace (camera2.x - camera.x); public function onClickViewport2 (mouseEvt: MouseEvent): void trace (camera2.x - camera.x);
Ejecute el SWF y mueva el mouse hacia la izquierda y hacia la derecha. Se verá así:
Ponte los lentes, apaga las luces y sigue moviendo el mouse hasta que encuentres el "punto dulce" donde la imagen parece volverse sólida. Haga clic con el mouse en este punto y rastreará un número. Toma nota de ello!
Una vez que haya encontrado la separación óptima, elimine la línea que acabamos de agregar a la función onEnterFrame ():
camera2.x = camera.x + (mouseX * 0.1);
Ahora encuentre la línea en Principal () donde establece la distancia entre las cámaras:
camera2.x = camera.x + 50;
... y reemplaza los 50 con cualquier número anotado. Encontré que 18 era un buen número para usar en mi configuración.
Finalmente, prueba el SWF:
Ta-da!
Bien hecho: has creado una escena 3D en Flash y has usado algunos trucos mentales para transferirla a una escena 3D dentro de tu cabeza;)
Si has entendido todo lo que pasaste, deberías poder usar la misma técnica para hacer imágenes en anaglifo 3D usando otros motores 3D.
En la primera parte mencioné que le gustaría intentar que el usuario mueva la cámara con el mouse. Ahora que ha agregado el efecto anaglifo, mover las cámaras hacia adelante y hacia atrás se verá muy impresionante.
Gracias por leer este tutorial, espero que lo hayas encontrado útil. Como siempre, si tiene alguna pregunta, por favor pregúnteles en los comentarios a continuación..