Crea un atomo rotante in Papervision3D

Proprio come suggerisce il titolo, simuleremo un Atomo con gusci di elettroni in orbita attorno a un nucleo, usando Papervision 3D. Muoviamoci…

Questo progetto è stato creato esclusivamente con ActionScript 3.0 con FlashDevelop. Se vuoi farlo allo stesso modo, FlashDevelop può essere scaricato qui. (Seguire le istruzioni di configurazione qui.) In caso contrario, è possibile utilizzare Flash CS3 o versioni successive.


Anteprima del risultato finale

Diamo un'occhiata al risultato finale su cui lavoreremo:

Muovi il mouse e la telecamera orbita attorno all'atomo liberamente. Prendi l'Atom in una posizione che ti piace e fai clic con il mouse sul palco, questo metterà l'Atom su una posizione fissa a "z" permettendoti di ruotare la telecamera sui suoi assi xe y. Fai di nuovo clic sul palco per rilasciare l'orbita 'z' della telecamera.


Passaggio 1: crea un nuovo progetto

Apri FlashDevelop e fai clic su Progetto> Nuovo progetto


Passaggio 2: configurazione

Scegli ActionScript 3> AS3Project. Per il nome del progetto messo in "Atomi". Per la posizione, fare clic e accedere alla cartella in cui si desidera salvarla. Lasciare selezionata la casella di controllo "Crea directory per progetto" e fare clic su OK.

Se si desidera utilizzare Flash CS3 / CS4, creare un nuovo file flash e impostare la larghezza e l'altezza su 600x500. Imposta il colore di sfondo sul nero. Chiamalo "atoms.fla" e salvalo ovunque desideri.


Passaggio 3: Installazione di Papervision 3D

Per Flash, copia o trascina le cartelle "org" e "nochump" dal download sorgente nella cartella in cui hai salvato il file atoms.fla.

Per FlashDevelop, andare avanti e copiare o trascinare Papervision3D_2.1.932.swc dai file di origine (scaricabile sopra) nella cartella lib per questo progetto. Per ulteriori informazioni su PV3D, è possibile visitare il sito Web qui.


Passaggio 4: assegnare la libreria esterna

In FlashDevelop, fai clic su Visualizza> Project Manager. Fare clic sul segno '+' a sinistra della cartella lib per espanderlo. Ora fai clic con il pulsante destro su Papervision3D_2.1.932.swc e seleziona Aggiungi alla libreria.


Passaggio 6: la classe del documento

Per FlashDevelop, riaprire il project manager (fare riferimento al punto 4), espandere la cartella src e fare doppio clic su Main.as
Sotto le importazioni e subito sopra la definizione della classe, aggiungere il seguente tag metadata per impostare le proprietà dello stage.

 [SWF (larghezza = 600, altezza = 500, frameRate = 30, backgroundColor = 0)]

All'interno del metodo init () dopo il commento "entry point", aggiungere le seguenti righe di codice.

 stage.addEventListener (Event.RESIZE, createBackground); _backGround = new Sprite; addChild (_backGround); createBackground (); var helium3: Helium3Atom = new Helium3Atom; addChild (elio3);

Quindi, creiamo uno sfondo sfumato semplice. Aggiungi le seguenti righe di codice dopo il metodo init ():

 funzione privata 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 ratio: 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); 

Questo è tutto per la classe principale del documento, se stai usando FlashDevelop.

Per Flash, crea una nuova classe Main.as nella stessa cartella del tuo progetto. Assicurati che la classe Main.as si trovi nella stessa cartella delle cartelle atoms.fla, "org" e "nochump".

Aggiungi le seguenti linee:

 package import flash.display.GradientType; import flash.display.Graphics; import flash.display.SpreadMethod; import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix; public class Main estende Sprite private var _backGround: Sprite; funzione pubblica Main (): void if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init);  funzione privata init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (Event.RESIZE, createBackground); _backGround = new Sprite; addChild (_backGround); createBackground (); var helium3: Helium3Atom = new Helium3Atom; addChild (elio3);  private function 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 ratio: 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); 

Apri Flash e assegna "Main" come classe Document. (Guarda questa breve introduzione alle classi di documenti se non sei sicuro di quello che stiamo facendo).

Se provi a eseguire questa operazione ora, riceverai un errore poiché non abbiamo ancora creato la classe Helium3Atom. Quindi assicurati di salvare il file e lasciarlo per ora.


Passaggio 7: creare la classe Helium3Atom

Da FlashDevelop, fare clic su Visualizza> Gestione progetti, fare clic con il tasto destro sulla cartella src e selezionare Aggiungi> Nuova classe.


Passaggio 8: impostazione della classe

Assegna un nome alla classe Helium3Atom, fai clic sul pulsante Sfoglia per la classe base e inserisci "org.papervision3d.view.BasicView". Premi OK per completare.


Passaggio 9: importazione delle classi richieste

(Ancora in FlashDevelop) Aggiungi tutte le importazioni necessarie all'interno delle parentesi del pacchetto proprio sopra "import org.papervision3d.view.BasicView;" e salva il file.

 import flash.events.Event; import flash.events.MouseEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.GouraudMaterial; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cylinder; import org.papervision3d.objects.primitives.Sphere;

Per Flash, crea un nuovo file ActionScript, chiamalo Helium3Atom e salvalo nella stessa directory che hai utilizzato. Dovrebbe trovarsi accanto al file atoms.fla, alle cartelle "org" e "nochump" e alla classe Main.as. Aggiungi il seguente codice:

 package import flash.events.Event; import flash.events.MouseEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.GouraudMaterial; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cylinder; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; public class Helium3Atom estende BasicView public function Helium3Atom () 

Passaggio 10: Variabili di istanza

All'interno della parentesi di classe, subito prima del metodo del costruttore, aggiungi le seguenti righe di codice:

 private var _do3DArray: Array; // manterrà tutti i riferimenti a tutti gli eletrons e ai loro anelli private var _easeOut: Number = .3; // forza di snellimento quando si sposta la telecamera private var _reachX: Number = .1; // lower questo è impostato, maggiore è la portata verso il suo asse x private var _reachY: Number = .1; // uguale a reachX, ma si applica sull'asse y private var _reachZ: Number = .5; // usato in congiunzione con il - mouseY, più vicino è il mouseY al centro del palco, più la telecamera si avvicina all'atomo. private var _rotX: Number = 0.5; // il valore utilizzato per la rotazione della telecamera sull'asse x var var _rotY: Number = 0.5; // uguale a _rotX, ma si applica per l'asse y della telecamera private var _camPitch: Number = 0; // orbitante sull'asse x calcolato al volo all'interno del metodo onRenderTick () private var _camYaw: Number = 0; // orbitante sull'asse y calcolato al volo all'interno del metodo onRenderTick () private var _zDist: Number = 4; // controlla la forza dello zoom della telecamera in entrata e in uscita private var _colorArray: Array = [0xCC490B, 0x26D965, 0xCC490B]; // colori per i neutroni e i protoni all'interno del nucleo private var _freeOrbit: Boolean = true; // cambia l'orbita modalità della fotocamera

Step 11: The Constructor

Aggiungi le seguenti righe all'interno del metodo Constructor.

 if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering ();

Le prime due linee chiamano il metodo init (). (Se lo stage non è ancora disponibile, aggiunge un listener per quando l'istanza viene aggiunta allo stage e quindi chiama il metodo init ().)

Il metodo startRendering () viene quindi chiamato in seguito. Questo metodo proviene dalla super-classe di BasicView, la "AbstractView". Ciò che questo metodo fa è aggiungere un listener ENTER_FRAME che attiva il metodo onRenderTick (). Avremo bisogno di sovrascrivere questo metodo protetto in seguito per animare l'atomo e spostare la fotocamera.


Passaggio 12: inizializzazione dell'istanza

All'interno del metodo init () chiamato dal costruttore, prima rimuoviamo il listener di eventi per aggiungere l'istanza allo stage e poi chiama il metodo createAtom ()

Aggiungi le seguenti linee di codice sotto il metodo constructor ():

 funzione privata init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); createAtom (); 

Step 13: Atom Elements (prima metà)

Vediamo cosa succede nel metodo createAtom (). Il _do3DArray è istanziato, dobbiamo mettere i riferimenti di tutto il DisplayObject3D che contengono gli anelli e gli elettroni in questo array in modo che possiamo accedervi in ​​seguito per l'animazione.

Una variabile locale denominata "light" viene assegnata a un'istanza di oggetto PointLight3D e posizionata sul lato in alto a destra della scena.

Un'altra variabile locale denominata "atom" viene assegnata a un'istanza DisplayObject3D e viene aggiunta alla scena. Questo sarà il DisplayObject3D genitore per tutti gli altri elementi.

Il "nucleo", anche un DisplayObject3D viene quindi istanziato. Viene ruotato di 90 gradi sul suo asse x per farlo rivolgere verso la telecamera e quindi aggiunto all'istanza DisplayObject3D "atom".

La variabile "sfera", anche una variabile locale, viene quindi assegnata a un oggetto Sfera. A Sphere è una primitiva incorporata di PV3D. Con questa particolare istanza, assegniamo "null" per il suo parametro materiale, "25" per il suo parametro raggio, e "1" per entrambi i parametri segmentiW e segmentiH.

Aggiungi le seguenti righe di codice dopo il loro metodo init ():

 funzione privata 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 (atomo); nucleo di var: DisplayObject3D = new DisplayObject3D; nucleus.rotationX = 90; atom.addChild (nucleo); var sphere: Sphere = new Sphere (null, 25, 1, 1); scene.addChild (sfera); 

Step 14: Controllo della sfera

Vai avanti e premi CTRL + Invio sulla tua tastiera. La sfera sembra più un poligono con 5 angoli. Questo perché abbiamo assegnato 1 per entrambi i segmenti W e i segmentiH. Ha un totale di 5 vertici.

Dopo il test, rimuovere il metodo addChild. La "sfera" non verrà aggiunta alla scena, ma sarà usata come guida per posizionare i neutroni e i protoni come vedrai dopo. Aggiungi il codice qui sotto all'interno del metodo createAtom () dopo la dichiarazione "sfera" in cui hai rimosso il metodo addChild.

 per (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); 

Ciò che fa questo ciclo è iterare da 1 a 4 e saltare 0 e 5. Una variabile locale chiamata convenientemente "np" (neutroni e protoni) viene creata durante ogni ciclo e assegnata a una primitiva Sphere. A ciascuna sfera "np" viene assegnato un materiale Gouraud con l'oggetto PointLight3D che abbiamo creato in precedenza per la sua luce e colorArray [i-1] per il parametro lightColor. Il secondo parametro "np" Sphere viene assegnato con un raggio di "23" e gli ultimi 2 parametri sono per i segmenti W e segmentiH a cui sono assegnati rispettivamente "12" e "9". Possiamo permetterci quantità maggiori di segmenti poiché ci sono solo 3 sfere all'interno del nucleo. Il risultato è una sfera più arrotondata ...

Ogni Sfera "np" viene poi aggiunta all'interno del nucleo con le coordinate basate sul vertice dell'iterazione corrente all'interno della sfera "sfera".


Step 15: Atom Elements (seconda metà)

Da qui, iteriamo due volte per creare gli elettroni e i loro anelli corrispondenti.

Prima istanziamo un DisplayObject3D e lo assegniamo a "do3d". Questo DisplayObject3D ospiterà sia l'elettrone che il suo anello.

Una primitiva Sphere viene quindi creata e assegnata a "electron". Questo rende gli elettroni colorati di colore biancastro che orbitano attorno al nucleo. I parametri che abbiamo assegnato per creare ogni elettrone sono i seguenti: un ColorMaterial con un valore di 0xEFECCA con opacità completa, il raggio della sfera con un valore di 7. Gli ultimi due parametri facoltativi che abbiamo omesso sono stati impostati con valori di 8 e 6.

Viene quindi creata una primitiva Cilindro per creare gli anelli. Qui usiamo solo un WireframeMaterial di colore bianco, un alfa di .05, uno spessore di 2, un raggio di 300, altezza di 1, segmentiW di 48 per renderlo veramente rotondo e segmentiH di 1 poiché l'altezza è anche 1. Il il valore topRadius viene lasciato con -1, che è il suo valore predefinito e impostiamo sia topFace che bottomFace su "false" "poiché non ne abbiamo bisogno qui.

L'elettrone viene quindi posizionato su 303 in modo che l'anello si trovi esattamente al centro dell'elettrone.

Quindi impostiamo la proprietà doubleSided del materiale dell'anello su "true" per far sì che l'anello mostri sia il suo guscio interno che quello esterno.

Successivamente, la localRotationZ del do3d viene quindi calcolata dividendo 360 del doppio del numero di squilli, moltiplicando per i e aggiungendo 45 gradi al risultato. Quando l'anello viene creato per la prima volta, è disteso come il fondo di una tazza. Moltiplichiamo il numero di anelli per 2 per ruotare il suo asse "z" da 0 a 90 e aggiungiamo 45 gradi per formare una bella "X" formazione per i 2 anelli. Quindi impostiamo la rotazione "y" di do3d su una posizione casuale di un cerchio completo in modo che gli elettroni abbiano tutti una posizione diversa quando orbitano attorno al nucleo.

Gli anelli e gli elettroni vengono quindi aggiunti all'interno di do3d, quindi viene aggiunto un riferimento nel _do3dArray.

Infine, il do3d viene aggiunto all'interno dell'atomo DisplayObject3D.

Aggiungi le seguenti righe di codice immediatamente sotto la parentesi di chiusura del primo ciclo:

 per (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); 

Step 16: Controllo dei nostri progressi

Proviamoci e vediamo se ha funzionato. Se tutto è andato bene, dovresti avere un'immagine come di seguito:

Abbiamo quasi finito, dobbiamo solo aggiungere animazione ora.


Passaggio 17: Modalità Orbita della fotocamera

All'interno del metodo init () (fare riferimento al punto 12), prima della chiamata al metodo "createAtom ()", aggiungere la seguente riga di codice:

 stage.addEventListener (MouseEvent.CLICK, onStageClick);

Questo attiverà il cambiamento nella modalità di orbita della fotocamera. Aggiungi il seguente codice sotto la parentesi di chiusura del metodo init ():

 funzione privata onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit; 

Tutto ciò che viene fatto è alternare _freeOrbit tra vero o falso.


Step 18: Orbitare l'atomo

Il metodo onRenderTick () viene attivato tramite Event.ENTER_FRAME dalla superclasse di BasicView - AbstractView.

Dentro questo, super.onRenderTick (evento) è chiamato per rendere la scena.

Il DisplayObject3D che contiene gli anelli e gli elettroni all'interno di _do3dArray viene quindi applicato a un imbardata di 10. L'applicazione di imbardata a un DisplayObject3D è la stessa di do3d.localRotationY + = 10 ;. Questo è ciò che rende gli anelli e gli elettroni in orbita attorno al nucleo.

XDist e yDist calcolano semplicemente quanto lontano mouseX e mouseY sono dal centro dello stage.

Quindi abbiamo il condizionale che controlla lo stato corrente di _freeOrbit. Se _freeOrbit è vero, la telecamera si muove liberamente sui suoi 3 assi. Spostando il mouse a sinistra, la fotocamera si solleverà verso sinistra, mentre spostando il mouse a destra farà l'opposto. Lo stesso vale per l'asse y della videocamera (spostandosi su e giù). Quando la fotocamera è più vicina al centro, viene applicato un effetto di zoom.

D'altra parte, se _freeOrbit è falso, la telecamera, invece, orbita solo liberamente sui suoi assi xey e ha una posizione z fissa. Questo ha l'effetto della fotocamera che si muove attorno all'atomo. L'equazione è più facile da capire se giochi con i valori delle proprietà. 90 gradi viene applicato a _camPitch in modo che l'atomo sia completamente rivolto verso il centro del palco quando il mouse si trova nel mezzo del palco; se non applicato, l'atomo sarà sul lato sinistro quando il mouse è centrato sul palco.

Questa è la stessa ragione per cui 270 ° viene applicato a _camYaw; se non viene aggiunto, l'atomo sarà sul lato superiore quando il mouse si trova nel mezzo del palco. Inoltre, limitiamo l'orbita della fotocamera quando muovete il mouse su e giù sul palco. Se rimuovi i limiti di _camPitch, c'è un punto in cui la videocamera si capovolge e si correggerà da sola. Questo ha un effetto indesiderato. Una volta completata la lezione nel passaggio successivo, prova a rimuovere i limiti per vedere cosa succede.

Aggiungi le seguenti righe di codice dopo il metodo createAtom ().

 sovrascrivi la funzione protetta onRenderTick (event: Event = null): void super.onRenderTick (event); per (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); 

Passaggio 19: test della classe completata

Questo dovrebbe essere tutto per la classe Helium3Atom. La tua classe dovrebbe apparire esattamente come la seguente:

 package import flash.events.Event; import flash.events.MouseEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.GouraudMaterial; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cylinder; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; public class Helium3Atom estende BasicView private var _do3DArray: Array; private var _easeOut: Number = .3; private var _reachX: Number = .1; private var _reachY: Number = .1; private var _reachZ: Number = .5; private var _rotX: Number = 0.5; private var _rotY: Number = 0.5; private var _camPitch: Number = 0; private var _camYaw: Number = 0; private var _zDist: Number = 4; private var _colorArray: Array = [0xCC490B, 0x26D965, 0xCC490B]; private var _freeOrbit: Boolean = true; funzione pubblica Helium3Atom () if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering ();  funzione privata init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.CLICK, onStageClick); createAtom ();  funzione privata onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit;  funzione privata 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 (atomo); nucleo di var: DisplayObject3D = new DisplayObject3D; nucleus.rotationX = 90; atom.addChild (nucleo); var sphere: Sphere = new Sphere (null, 25, 1, 1); // guida invisibile per (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); 

Premi CTRL + Invio e dovresti ottenere qualcosa di simile a quello che vedi qui sotto:


Step 20: The Carbon Atom

Ok, creiamo ora un atomo un po 'più complesso. Creare una nuova classe (se si utilizza FlashDevelop, fare riferimento ai passaggi 7 e 8). L'unica differenza dovrebbe essere il nome, dovrebbe essere "CarbonAtom". Ha praticamente lo stesso codice, con poche modifiche quindi vai avanti e copia tutto il contenuto di Helium3Atom, seleziona tutto il contenuto all'interno di CarbonAtom e sostituiscilo con il codice copiato da Helium3Atom.

Iniziamo a modificare le cose dall'alto. All'interno della dichiarazione della classe in cui è presente _colorsArray, rimuovere l'array assegnato che contiene i 3 colori.

Quindi, vai al metodo init (). Aggiungi il codice qui sotto prima della chiamata al metodo createAtom ():

 randomizeColorArray ();

Vai sotto il metodo onStageClick () e aggiungi questo nuovo metodo:

 private function randomizeColorArray (): void _colorArray = []; var tempArray: Array = []; per (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); 

Questo metodo randomizza la posizione di 2 colori che sono memorizzati in _colorArray. Ciò rende 6 parti uguali di rosso e blu posizionate casualmente all'interno di _colorArray.

Quindi, vai nel metodo createAtom () proprio dove "nucleo" è istanziato e rimuovi l'assegnazione "nucleus.rotationX = 90".

Scendi 2 righe e modifica i parametri di istanziazione delle sfere in "var sphere: Sphere = new Sphere (null, 60, 4, 4);". Abbiamo bisogno di una sfera più grande con più vertici per contenere tutti e 12 i protoni e i neutroni.

Ora vai all'interno del primo ciclo in cui la "np" Sphere viene istanziata e rimuovi gli ultimi 2 parametri di 12 e 9. In questo modo i segmenti W e i segmenti H sono impostati sui loro valori predefiniti, rispettivamente 8 e 6, e riducono l'impatto sulle prestazioni.

Successivamente, nel secondo ciclo, modifica la quantità di cicli da 2 a 6. Vai subito sotto l'istanza dell'elettrone e sostituisci il seguente codice:

 ring = new Cylinder (new WireframeMaterial (0xFFFFFF, .05, 2), 300, 1, 48, 1, -1, false, false); electron.x = 303;

con:

 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; 

È qui che vengono creati i due gusci (anelli) per CarbonAtom.

Ora vai sotto dove vedi l'assegnazione "ring.material.doubleSided = true" e sostituisci il codice:

 do3d.localRotationZ = 360/4 * i + 45;

con:

 do3d.localRotationZ = 360/12 * i + 180;

Questo dà il posizionamento corretto di 6 elettroni per coprire completamente il nucleo. Questo è tutto. Salva il file prima di testare.


Passo 21: test del CarbonAtom

La classe CarbonAtom dovrebbe apparire esattamente come questa:

 package import flash.display.StageQuality; import flash.events.Event; import flash.events.MouseEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.GouraudMaterial; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cylinder; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; la classe pubblica CarbonAtom estende BasicView private var _do3DArray: Array; private var _easeOut: Number = .3; private var _reachX: Number = .1; private var _reachY: Number = .1; private var _reachZ: Number = .5; private var _rotX: Number = 0.5; private var _rotY: Number = 0.5; private var _camPitch: Number = 0; private var _camYaw: Number = 0; private var _zDist: Number = 4; private var _colorArray: Array; private var _freeOrbit: Boolean = true; funzione pubblica CarbonAtom () if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init); startRendering ();  funzione privata init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.CLICK, onStageClick); randomizeColorArray (); createAtom ();  funzione privata onStageClick (e: MouseEvent): void _freeOrbit =! _freeOrbit;  private function randomizeColorArray (): void _colorArray = []; var tempArray: Array = []; per (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);  funzione privata 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 (atomo); nucleo di var: DisplayObject3D = new DisplayObject3D; atom.addChild (nucleo); var sphere: Sphere = new Sphere (null, 60, 4, 4); per (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); 

Aprire la classe del documento principale e sostituire il codice:

 var helium3: Helium3Atom = new Helium3Atom; addChild (elio3);

con:

 var carbon: CarbonAtom = new CarbonAtom; addChild (nuovo CarbonAtom);

Dovresti vedere qualcosa di simile all'anteprima quando testi il ​​film.


Conclusione

Papervision è uno strumento molto semplice e potente. Sperimentalo e troverai tutti i tipi di fantastici effetti 3D che vanno dalle semplici simulazioni alle interfacce sofisticate.

Inoltre, ho realizzato un'altra versione dell'atomo di carbonio CarbonAtom2, anch'essa inclusa nel download del codice sorgente. Quello ha un comportamento più realistico degli elettroni, dai un'occhiata! =)

Come sempre, per eventuali commenti, suggerimenti o dubbi, si prega di lasciare una nota nella sezione commenti. Grazie per aver letto!