Tal como sugiere el título, vamos a simular un átomo con capas de electrones que orbitan un núcleo, utilizando Papervision 3D. Vámonos…
Este proyecto se creó exclusivamente con ActionScript 3.0 utilizando FlashDevelop. Si desea hacerlo de la misma manera, FlashDevelop se puede descargar aquí. (Siga las instrucciones de configuración aquí). De lo contrario, puede usar Flash CS3 o superior.
Echemos un vistazo al resultado final en el que trabajaremos:
Mueve el mouse y la cámara orbitará libremente el átomo. Coloque el átomo en una posición que le guste y haga clic con el mouse en el escenario, esto colocará el átomo en una posición fija de 'z' que le permitirá rotar la cámara en sus ejes x e y. Haz clic en el escenario de nuevo para liberar la órbita 'z' de la cámara..
Abra FlashDevelop y haga clic en Proyecto> Nuevo proyecto
Elija ActionScript 3> AS3Project. Para el nombre del Proyecto puesto en "Átomos". Para la ubicación, haga clic y navegue hasta la carpeta en la que desea guardarlo. Deje la casilla de verificación "crear directorio para el proyecto" seleccionada y haga clic en Aceptar.
Si desea utilizar Flash CS3 / CS4, cree un nuevo archivo flash y configure el ancho y el alto en 600x500. Establecer el color de fondo a negro. Dale el nombre "átomos.fla "y guárdalo donde quieras..
Para Flash, copie o arrastre las carpetas "org" y "nochump" de la descarga de origen a la carpeta donde guardó el archivoátomos.fla.
Para FlashDevelop, siga adelante y copie o arrastre Papervision3D_2.1.932.swc desde los archivos de origen (descargables anteriormente) a la carpeta lib para este proyecto. Para más información sobre PV3D, puede visitar el sitio web aquí.
En FlashDevelop, haga clic en Ver> Administrador de proyectos. Haga clic en el signo '+' a la izquierda de la carpeta lib para expandirla. Ahora haga clic con el botón derecho en Papervision3D_2.1.932.swc y seleccione Agregar a la biblioteca.
Para FlashDevelop, abra el administrador de proyectos nuevamente (consulte el paso 4), expanda la carpeta src y haga doble clic en Main.as
Debajo de las importaciones y justo encima de la definición de clase, agregue la siguiente etiqueta de metadatos para configurar las propiedades de la etapa.
[SWF (ancho = 600, altura = 500, frameRate = 30, backgroundColor = 0)]
Dentro del método init () después del comentario "punto de entrada", agregue las siguientes líneas de código.
stage.addEventListener (Event.RESIZE, createBackground); _backGround = nuevo Sprite; addChild (_backGround); createBackground (); var helium3: Helium3Atom = nuevo Helium3Atom; addChild (helio3);
A continuación, vamos a crear un fondo degradado simple. Agregue las siguientes líneas de código después del método init ():
función privada createBackground (e: Event = null): void var g: Graphics = _backGround.graphics; g.clear (); var fillType: String = GradientType.RADIAL; var colors: Array = [0x0000FF, 0x000000]; var alphas: Array = [1, 1]; var ratios: Array = [0x00, 0xFF]; var matr: Matrix = new Matrix (); matr.createGradientBox (stage.stageWidth, stage.stageHeight, 0, 0, 0); var spreadMethod: String = SpreadMethod.PAD; g.beginGradientFill (fillType, colors, alphas, ratios, matr, spreadMethod); g.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Eso es todo para la clase de documento principal, si está utilizando FlashDevelop.
Para Flash, cree una nueva clase Main.as en la misma carpeta que su proyecto. Asegúrate de que la clase Main.as esté en la misma carpeta que las carpetas atom.fla, "org" y "nochump".
Añade las siguientes líneas:
package import flash.display.GradientType; importar flash.display.Graphics; importar flash.display.SpreadMethod; importar flash.display.Sprite; import flash.events.Event; importar flash.geom.Matrix; clase pública Main extiende Sprite private var _backGround: Sprite; función pública Main (): void if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (Event.RESIZE, createBackground); _backGround = nuevo Sprite; addChild (_backGround); createBackground (); var helium3: Helium3Atom = nuevo Helium3Atom; addChild (helio3); función privada createBackground (e: Event = null): void var g: Graphics = _backGround.graphics; g.clear (); var fillType: String = GradientType.RADIAL; var colors: Array = [0x0000FF, 0x000000]; var alphas: Array = [1, 1]; var ratios: Array = [0x00, 0xFF]; var matr: Matrix = new Matrix (); matr.createGradientBox (stage.stageWidth, stage.stageHeight, 0, 0, 0); var spreadMethod: String = SpreadMethod.PAD; g.beginGradientFill (fillType, colors, alphas, ratios, matr, spreadMethod); g.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Abra Flash y asigne "Main" como clase de documento. (Echa un vistazo a esta rápida introducción a las clases de documentos si no estás seguro de lo que estamos haciendo).
Si intenta ejecutar esto ahora, recibirá un error ya que aún no hemos creado la clase Helium3Atom. Así que solo asegúrate de guardar el archivo y dejarlo por ahora.
Desde FlashDevelop, haga clic en Ver> Administrador de proyectos, haga clic con el botón derecho en la carpeta src y elija Agregar> Nueva clase.
Asigne un nombre a la clase Helium3Atom, haga clic en el botón de búsqueda de la clase base y escriba "org.papervision3d.view.BasicView". Presiona OK para completar.
(Aún en FlashDevelop) Agregue todas las importaciones necesarias dentro de los corchetes del paquete justo encima de "import org.papervision3d.view.BasicView"; y guarda el archivo.
import flash.events.Event; import flash.events.MouseEvent; importar org.papervision3d.lights.PointLight3D; importar org.papervision3d.materials.ColorMaterial; importar org.papervision3d.materials.shadematerials.GouraudMaterial; importar org.papervision3d.materials.WireframeMaterial; importar org.papervision3d.objects.DisplayObject3D; importar org.papervision3d.objects.primitives.Cylinder; importar org.papervision3d.objects.primitives.Sphere;
Para Flash, cree un nuevo archivo ActionScript, asígnele el nombre Helium3Atom y guárdelo en el mismo directorio que ha estado usando. Debería estar justo al lado del archivo atom.fla, las carpetas "org" y "nochump", y la clase Main.as. Agregue el siguiente código:
package import flash.events.Event; import flash.events.MouseEvent; importar org.papervision3d.lights.PointLight3D; importar org.papervision3d.materials.ColorMaterial; importar org.papervision3d.materials.shadematerials.GouraudMaterial; importar org.papervision3d.materials.WireframeMaterial; importar org.papervision3d.objects.DisplayObject3D; importar org.papervision3d.objects.primitives.Cylinder; importar org.papervision3d.objects.primitives.Sphere; importar org.papervision3d.view.BasicView; clase pública Helium3Atom extiende BasicView función pública Helium3Atom ()
Dentro del corchete de la clase, justo antes del método del constructor, agregue las siguientes líneas de código:
private var _do3DArray: Array; // mantendrá todas las referencias a todos los eletrones y sus anillos private var _easeOut: Number = .3; // facilitando la fuerza al mover la cámara private var _reachX: Number = .1; // la parte inferior esto se establece, cuanto más lejos esté el alcance hacia su eje x, var privado var: extensión = .1; // igual que alcanceX, pero se aplica en el eje y privado var varilla: número = .5; // utilizado junto con el - mouseY, cuanto más cerca esté el mouseY del centro del escenario, más se acercará la cámara al átomo. private var _rotX: Number = 0.5; // el valor utilizado para la rotación de la cámara en el eje x private var _rotY: Number = 0.5; // igual que _rotX, pero se aplica para el eje privado de la cámara y var _camPitch: Number = 0; // orbitando en el eje x calculado sobre la marcha dentro del método onRenderTick () private var _camYaw: Number = 0; // orbitando sobre el eje y calculado sobre la marcha dentro del método onRenderTick () private var _zDist: Number = 4; // controla la fuerza de acercar y alejar la cámara con la variable privada var _colorArray: Array = [0xCC490B, 0x26D965, 0xCC490B]; // colores para los neutrones y protones dentro del núcleo privado var _freeOrbit: Boolean = true; // cambia la órbita modo de la cámara
Añade las siguientes líneas dentro del método Constructor.
if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering ();
Las dos primeras líneas llaman al método init (). (Si la etapa aún no está disponible, agrega un escucha para cuando la instancia se agrega a la etapa y luego llama al método init ()).
El método startRendering () se llama luego. Este método es de la súper clase de BasicView, el "AbstractView". Lo que hace este método es agregar un agente de escucha ENTER_FRAME que active el método onRenderTick (). Tendremos que anular este método protegido más adelante para animar el átomo y mover la cámara..
Dentro del método init () llamado por el constructor, primero eliminamos el detector de eventos para agregar la instancia a la etapa y luego llamamos al método createAtom ()
Agregue las siguientes líneas de código debajo del método constructor ():
función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); createAtom ();
Veamos lo que está sucediendo en el método createAtom (). La _do3DArray está instanciada, necesitamos poner referencias de todos los DisplayObject3D que mantienen los anillos y los electrones en esta matriz para que podamos acceder a ellos más adelante para la animación..
A una variable local llamada "light" se le asigna una instancia de objeto PointLight3D y se coloca en el lado superior derecho de la escena.
A otra variable local llamada "átomo" se le asigna una instancia de DisplayObject3D y se agrega a la escena. Este será el DisplayObject3D padre para todos los demás elementos.
El "núcleo", también un DisplayObject3D se crea una instancia. Se gira 90 grados en su eje x para que quede frente a la cámara y luego se agrega a la instancia de "átomo" DisplayObject3D.
A la variable "esfera", también una variable local, se le asigna un objeto Esfera. Una esfera es una primitiva incorporada de PV3D. Con esta instancia en particular, asignamos "nulo" para su parámetro de material, "25" para su parámetro de radio, y "1" para ambos parámetros, parámetrosW y segmentosH.
Agregue las siguientes líneas de código después de su método init ():
función privada createAtom (): void _do3DArray = []; var light: PointLight3D = new PointLight3D; light.x = 300; light.y = 700; light.z = 0; scene.addChild (light) var atom: DisplayObject3D = new DisplayObject3D; scene.addChild (atom); núcleo de var: DisplayObject3D = nuevo DisplayObject3D; nucleus.rotationX = 90; atom.addChild (núcleo); esfera de var: Esfera = Esfera nueva (nulo, 25, 1, 1); scene.addChild (esfera);
Continúa y presiona CTRL + Enter en tu teclado. La esfera se parece más a un polígono con 5 esquinas. Esto se debe a que asignamos 1 para los segmentosW y segmentosH. Tiene un total de 5 vértices..
Después de la prueba, elimine el método addChild. La "esfera" no se agregará a la escena, en su lugar, se utilizará como guía para colocar los neutrones y protones como se verá a continuación. Agregue el siguiente código dentro del método createAtom () después de la declaración de "esfera" donde eliminó el método addChild.
para (var i: uint = 1; i < sphere.geometry.vertices.length-1; i++) var np:Sphere = new Sphere (new GouraudMaterial (light, _colorArray[i - 1], 0, 0), 23, 12, 9); np.x = sphere.geometry.vertices[i].x; np.y = sphere.geometry.vertices[i].y; np.z = sphere.geometry.vertices[i].z; nucleus.addChild (np);
Lo que hace este bucle es iterar de 1 a 4 y omite 0 y 5. Se crea una variable local convenientemente llamada "np" (neutrones y protones) durante cada bucle y se le asigna una primitiva Esfera. A cada esfera "np" se le asigna un GouraudMaterial con el objeto PointLight3D que creamos anteriormente por su luz y colorArray [i - 1] para el parámetro lightColor. Al segundo parámetro de "np" Sphere se le asigna un radio de "23" y los últimos 2 parámetros son para los segmentos W y segmentos H a los que se les asigna "12" y "9" respectivamente. Podemos permitirnos una mayor cantidad de segmentos ya que solo hay 3 esferas dentro del núcleo. El resultado es una Esfera más redondeada ...
Cada esfera "np" se agrega luego dentro del núcleo con las coordenadas basadas en el vértice de la iteración actual dentro de la esfera "esfera".
Desde aquí, iteramos dos veces para crear los electrones y sus anillos correspondientes..
Primero creamos una instancia de DisplayObject3D y lo asignamos a "do3d". Este DisplayObject3D albergará tanto el electrón como su anillo..
Luego se crea una primitiva Esfera y se asigna a "electrón". Esto hace que los electrones de color blanquecino que orbitan el núcleo. Los parámetros que asignamos para crear cada electrón son los siguientes: un Material de color con un valor de 0xEFECCA con opacidad total, el radio de la esfera con un valor de 7. Los últimos dos parámetros opcionales que omitimos con valores de 8 y 6.
Luego se crea una primitiva de cilindro para hacer los anillos. Aquí solo usamos un WireframeMaterial de color blanco, un alfa de .05, un grosor de 2, un radio de 300, una altura de 1, segmentos W de 48 para hacerlo realmente redondo y segmentos H de 1, ya que la altura también es 1. El El valor de topRadius se queda con -1, que es su valor predeterminado y configuramos tanto topFace como bottomFace en "falso" ya que no los necesitamos aquí.
El electrón se coloca en 303, de modo que el anillo está justo en el centro del electrón..
Luego establecemos la propiedad de doble cara del material del anillo en "verdadero" para hacer que el anillo muestre sus carcasas interna y externa.
Después de eso, el localRotationZ de do3d se calcula dividiendo 360 por el doble del número de anillos, multiplicando por i y agregando 45 grados al resultado. Cuando se crea el anillo por primera vez, queda plano como el fondo de una taza. Multiplicamos el número de anillos por 2 para rotar su eje "z" de 0 a 90 y agregamos 45 grados para hacer una bonita formación de "X" para los 2 anillos. Luego establecemos la rotación "y" de do3d en una posición aleatoria de un círculo completo para que todos los electrones tengan una posición diferente cuando orbitan el núcleo.
Luego se agregan los anillos y los electrones dentro de do3d, luego se agrega una referencia al _do3dArray.
Finalmente, el do3d se agrega dentro del átomo DisplayObject3D.
Agregue las siguientes líneas de código justo debajo del corchete de cierre del primer bucle:
para (i = 0; i < 2; i++) var do3d:DisplayObject3D = new DisplayObject3D; var ring:Cylinder; var electron:Sphere; electron = new Sphere (new ColorMaterial (0xEFECCA, 1), 7); ring = new Cylinder (new WireframeMaterial (0xFFFFFF, .05, 2), 300, 1, 48, 1, -1, false, false); electron.x = 303;//add half size of electron ring.material.doubleSided = true; do3d.localRotationZ = 360 / 4 * i + 45; do3d.localRotationY = 360 * Math.random (); do3d.addChild (ring); do3d.addChild (electron); _do3DArray.push (do3d); atom.addChild (do3d);
Vamos a probarlo y ver si funcionó. Si todo salió bien, deberías tener una imagen como la siguiente:
Ya casi terminamos, solo necesitamos agregar animación ahora.
Dentro del método init () (consulte el Paso 12), antes de la llamada al método "createAtom ()", agregue la siguiente línea de código:
stage.addEventListener (MouseEvent.CLICK, onStageClick);
Esto activará el cambio en el modo de órbita de la cámara. Agregue el siguiente código debajo de la llave de cierre del método init ():
función privada onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit;
Todo lo que hace es alternar _freeOrbit entre verdadero o falso.
El método onRenderTick () se activa a través de un evento.ENTER_FRAME desde la superclase de BasicView - AbstractView.
Dentro de este, super.onRenderTick (evento) Se llama a renderizar la escena..
El DisplayObject3D que contiene los anillos y los electrones dentro de _do3dArray luego se aplica una orientación de 10. La aplicación de la orientación a un DisplayObject3D es lo mismo que do3d.localRotationY + = 10; Esto es lo que hace que los anillos y los electrones orbitan el núcleo..
El xDist y el yDist simplemente calculan la distancia entre el mouseX y mouseY desde el centro del escenario.
Luego tenemos el condicional que verifica el estado actual de _freeOrbit. Si _freeOrbit es verdadero, la cámara se mueve libremente en sus 3 ejes. Mover el mouse hacia la izquierda hará que la cámara se mueva hacia su izquierda, mientras que mover el mouse hacia la derecha hará lo contrario. Lo mismo se aplica para el eje y de la cámara (moviéndose hacia arriba y hacia abajo). Cuando la cámara está más cerca del centro, se aplica un efecto de zoom.
Por otro lado, si _freeOrbit es falso, la cámara, en cambio, solo orbita libremente en sus ejes x e y tiene una posición z fija. Esto tiene el efecto de la cámara moviéndose alrededor del átomo. La ecuación es más fácil de entender si juegas con los valores de las propiedades. Se aplican 90 grados a _camPitch para que el átomo esté completamente orientado hacia el centro del escenario cuando el mouse está en el centro del escenario; si no se aplica, el átomo estará en su lado izquierdo cuando el ratón esté centrado en el escenario.
Esta es la misma razón por la que se aplican 270 grados a _camYaw; si no se agrega, el átomo estará en su lado superior cuando el mouse esté en el centro del escenario. Además, limitamos la órbita de la cámara cuando mueves el mouse hacia arriba y hacia abajo en el escenario. Si elimina los límites de _camPitch, hay un punto en el que la cámara se pone boca abajo y se corrige sola. Esto tiene un efecto indeseable. Cuando la clase se complete en el siguiente paso, intente eliminar los límites para ver qué sucede.
Agregue las siguientes líneas de código después del método createAtom ().
anular la función protegida onRenderTick (evento: Evento = nulo): void super.onRenderTick (evento); para (var i: uint = 0; i < _do3DArray.length; i++) _do3DArray[i].yaw (10); var xDist:Number = mouseX - stage.stageWidth * .5; var yDist:Number = mouseY - stage.stageHeight * .5; if (_freeOrbit) camera.x += (xDist - camera.x * _reachX) * _easeOut; camera.y += (yDist - camera.y * _reachY) * _easeOut; camera.z += (-mouseY * _zDist - camera.z) * _reachZ; else _camPitch += ((-yDist * _rotX) - _camPitch + 90) * _easeOut; _camYaw += ((xDist * _rotY) - _camYaw + 270) * _easeOut; if(_camPitch < 5) _camPitch = 5; if(_camPitch > 175) _camPitch = 175; camera.orbit (_camPitch, _camYaw);
Eso debería ser todo para la clase Helium3Atom. Tu clase debe verse exactamente como la siguiente:
package import flash.events.Event; import flash.events.MouseEvent; importar org.papervision3d.lights.PointLight3D; importar org.papervision3d.materials.ColorMaterial; importar org.papervision3d.materials.shadematerials.GouraudMaterial; importar org.papervision3d.materials.WireframeMaterial; importar org.papervision3d.objects.DisplayObject3D; importar org.papervision3d.objects.primitives.Cylinder; importar org.papervision3d.objects.primitives.Sphere; importar org.papervision3d.view.BasicView; clase pública Helium3Atom extiende BasicView private var _do3DArray: Array; private var _easeOut: Number = .3; private var _reachX: Number = .1; variable var _reachY: Número = .1; privado var _reachZ: Número = .5; var _rotX privado: Número = 0.5; var _rotY privado: Número = 0.5; var privado _camPitch: Número = 0; var _camYaw privado: Número = 0; var_zDist privado: Número = 4; private var _colorArray: Array = [0xCC490B, 0x26D965, 0xCC490B]; private var _freeOrbit: Boolean = true; función pública Helium3Atom () if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering (); función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.CLICK, onStageClick); createAtom (); función privada onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit; private function createAtom (): void _do3DArray = []; var light: PointLight3D = new PointLight3D; light.x = 300; light.y = 700; light.z = 0; scene.addChild (light) var atom: DisplayObject3D = new DisplayObject3D; scene.addChild (atom); núcleo de var: DisplayObject3D = nuevo DisplayObject3D; nucleus.rotationX = 90; atom.addChild (núcleo); var sphere: Sphere = new Sphere (null, 25, 1, 1); // guía invisible para (var i: uint = 1; i < sphere.geometry.vertices.length-1; i++) var np:Sphere = new Sphere (new GouraudMaterial (light, _colorArray[i - 1], 0, 0), 23, 12, 9); np.x = sphere.geometry.vertices[i].x; np.y = sphere.geometry.vertices[i].y; np.z = sphere.geometry.vertices[i].z; nucleus.addChild (np); for (i = 0; i < 2; i++) var do3d:DisplayObject3D = new DisplayObject3D; var ring:Cylinder; var electron:Sphere; electron = new Sphere (new ColorMaterial (0xEFECCA, 1), 7); ring = new Cylinder (new WireframeMaterial (0xFFFFFF, .05, 2), 300, 1, 48, 1, -1, false, false); electron.x = 303;//add half size of electron ring.material.doubleSided = true; do3d.localRotationZ = 360 / 4 * i + 45; do3d.localRotationY = 360 * Math.random (); do3d.addChild (ring); do3d.addChild (electron); _do3DArray.push (do3d); atom.addChild (do3d); override protected function onRenderTick (event:Event = null):void super.onRenderTick (event); for (var i:uint = 0; i < _do3DArray.length; i++) _do3DArray[i].yaw (10); var xDist:Number = mouseX - stage.stageWidth * .5; var yDist:Number = mouseY - stage.stageHeight * .5; if (_freeOrbit) camera.x += (xDist - camera.x * _reachX) * _easeOut; camera.y += (yDist - camera.y * _reachY) * _easeOut; camera.z += (-mouseY * _zDist - camera.z) * _reachZ; else _camPitch += ((-yDist * _rotX) - _camPitch + 90) * _easeOut; _camYaw += ((xDist * _rotY) - _camYaw + 270) * _easeOut; if(_camPitch < 5) _camPitch = 5; if(_camPitch > 175) _camPitch = 175; camera.orbit (_camPitch, _camYaw);
Presione CTRL + Enter y debería obtener algo como lo que ve a continuación:
Ok, ahora vamos a crear un átomo ligeramente más complejo. Cree una nueva clase (si está utilizando FlashDevelop, consulte los pasos 7 y 8). La única diferencia debe ser el nombre, debe ser "CarbonAtom". Tiene prácticamente el mismo código, con algunos cambios, así que adelante, copie todo el contenido del Helium3Atom, seleccione todo el contenido dentro del CarbonAtom y sustitúyalo por el código copiado de Helium3Atom.
Vamos a empezar a modificar las cosas desde la parte superior. Dentro de la declaración de clase donde tenemos _colorsArray, eliminamos la matriz asignada que contiene los 3 colores.
A continuación, vaya al método init (). Agregue el siguiente código antes de la llamada al método createAtom ():
randomizeColorArray ();
Vaya debajo del método onStageClick () y agregue este nuevo método:
función privada randomizeColorArray (): void _colorArray = []; var tempArray: Array = []; para (var i: uint = 0; i < 12; i++) if (i < 6) var color:uint = 0x004080; //shade of blue else color = 0xA40000; //shade of red tempArray.push (color); while (tempArray.length > 6) _colorArray.push (tempArray.splice (uint (Math.random () * tempArray.length), 1)); _colorArray = _colorArray.concat (tempArray);
Este método aleatoriza la posición de 2 colores que se almacenan en _colorArray. Esto hace que 6 partes iguales de rojo y azul se coloquen aleatoriamente dentro de _colorArray.
A continuación, ingrese al método createAtom () donde se crea una instancia del "núcleo" y elimine la asignación "nucleus.rotationX = 90".
Baje 2 líneas y cambie los parámetros de ejemplificación de la esfera por "var sphere: Sphere = new Sphere (null, 60, 4, 4);". Necesitamos una esfera más grande con más vértices para mantener los 12 protones y neutrones..
Ahora vaya al primer bucle donde se crea una instancia de la Esfera "np" y elimine los últimos 2 parámetros de 12 y 9. Esto establece los segmentosW y segmentosH a sus valores predeterminados, 8 y 6, respectivamente, y reduce el impacto en el rendimiento.
A continuación, en el segundo bucle, cambie la cantidad de bucles de 2 a 6. Vaya justo debajo de la instanciación electrónica y reemplace el siguiente código:
ring = new Cylinder (nuevo WireframeMaterial (0xFFFFFF, .05, 2), 300, 1, 48, 1, -1, false, false); electron.x = 303;
con:
if (i == 1 || i == 5) ring = new Cylinder (nuevo WireframeMaterial (0xFFFFFF, .05, 2), 450, 1, 48, 1, -1, false, false); electron.x = 453; else ring = new Cylinder (nuevo WireframeMaterial (0xFFFFFF, .05, 2), 610, 1, 48, 1, -1, false, false); electron.x = 613;
Aquí es donde se crean las dos carcasas (anillos) para el CarbonAtom.
Ahora ve abajo donde ves la asignación "ring.material.doubleSided = true" y reemplaza el código:
do3d.localRotationZ = 360/4 * i + 45;
con:
do3d.localRotationZ = 360/12 * i + 180;
Esto le da a los 6 electrones una colocación adecuada para cubrir completamente el núcleo. Eso es. Guarda el archivo antes de probar.
La clase CarbonAtom debería verse exactamente así:
package import flash.display.StageQuality; import flash.events.Event; import flash.events.MouseEvent; importar org.papervision3d.lights.PointLight3D; importar org.papervision3d.materials.ColorMaterial; importar org.papervision3d.materials.shadematerials.GouraudMaterial; importar org.papervision3d.materials.WireframeMaterial; importar org.papervision3d.objects.DisplayObject3D; importar org.papervision3d.objects.primitives.Cylinder; importar org.papervision3d.objects.primitives.Sphere; importar org.papervision3d.view.BasicView; la clase pública CarbonAtom extiende BasicView private var _do3DArray: Array; private var _easeOut: Number = .3; private var _reachX: Number = .1; variable var _reachY: Número = .1; privado var _reachZ: Número = .5; var _rotX privado: Número = 0.5; var _rotY privado: Número = 0.5; var privado _camPitch: Número = 0; var _camYaw privado: Número = 0; var_zDist privado: Número = 4; private var _colorArray: Array; private var _freeOrbit: Boolean = true; función pública CarbonAtom () if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering (); función privada init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.CLICK, onStageClick); randomizeColorArray (); createAtom (); función privada onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit; función privada randomizeColorArray (): void _colorArray = []; var tempArray: Array = []; para (var i: uint = 0; i < 12; i++) if (i < 6) var color:uint = 0x004080; else color = 0xA40000; tempArray.push (color); while (tempArray.length > 6) _colorArray.push (tempArray.splice (uint (Math.random () * tempArray.length), 1)); _colorArray = _colorArray.concat (tempArray); private function createAtom (): void _do3DArray = []; var light: PointLight3D = new PointLight3D; light.x = 300; light.y = 700; light.z = 0; scene.addChild (light) var atom: DisplayObject3D = new DisplayObject3D; scene.addChild (atom); núcleo de var: DisplayObject3D = nuevo DisplayObject3D; atom.addChild (núcleo); esfera de var: Esfera = esfera nueva (nula, 60, 4, 4); para (var i: uint = 1; i < sphere.geometry.vertices.length-1; i++) var np:Sphere = new Sphere (new GouraudMaterial (light, _colorArray[i - 1], 0, 0), 23); np.x = sphere.geometry.vertices[i].x; np.y = sphere.geometry.vertices[i].y; np.z = sphere.geometry.vertices[i].z; nucleus.addChild (np); for (i = 0; i < 6; i++) var do3d:DisplayObject3D = new DisplayObject3D; var ring:Cylinder; var electron:Sphere; electron = new Sphere (new ColorMaterial (0xEFECCA, 1), 7); if (i == 1 || i == 5) ring = new Cylinder (new WireframeMaterial (0xFFFFFF, .05, 2), 450, 1, 48, 1, -1, false, false); electron.x = 453; else ring = new Cylinder (new WireframeMaterial (0xFFFFFF, .05, 2), 610, 1, 48, 1, -1, false, false); electron.x = 613; ring.material.doubleSided = true; do3d.localRotationZ = 360 / 12 * i + 180; do3d.localRotationY = 360 * Math.random (); do3d.addChild (ring); do3d.addChild (electron); _do3DArray.push (do3d); atom.addChild (do3d); override protected function onRenderTick (event:Event = null):void super.onRenderTick (event); for (var i:uint = 0; i < _do3DArray.length; i++) _do3DArray[i].yaw (10); var xDist:Number = mouseX - stage.stageWidth * .5; var yDist:Number = mouseY - stage.stageHeight * .5; if (_freeOrbit) camera.x += (xDist - camera.x * _reachX) * _easeOut; camera.y += (yDist - camera.y * _reachY) * _easeOut; camera.z += (-mouseY * _zDist - camera.z) * _reachZ; else _camPitch += ((-yDist * _rotX) - _camPitch + 90) * _easeOut; _camYaw += ((xDist * _rotY) - _camYaw + 270) * _easeOut; if(_camPitch < 5) _camPitch = 5; if(_camPitch > 175) _camPitch = 175; camera.orbit (_camPitch, _camYaw);
Abra la clase de documento principal y reemplace el código:
var helium3: Helium3Atom = nuevo Helium3Atom; addChild (helio3);
con:
var carbon: CarbonAtom = new CarbonAtom; addChild (nuevo CarbonAtom);
Debería ver algo como la vista previa cuando prueba la película.
Papervision es una herramienta muy sencilla y poderosa. Experimente con él y obtendrá todo tipo de efectos 3D geniales que van desde simulaciones simples hasta interfaces sofisticadas..
Además, hice otra versión del átomo de carbono llamado CarbonAtom2 que también se incluye con la descarga de origen. Ese tiene un comportamiento electrónico más realista, ¡échale un vistazo! =)
Como siempre, para cualquier comentario, sugerencia o inquietud, deje una nota en la sección de comentarios. Gracias por leer!