Om aan te sluiten bij onze Papervision3D Essentials-weggeefactie, bevat de zelfstudie van vandaag ook een PV3D-thema.
Deze tweedelige tutorial laat je zien hoe je aan de slag kunt met de Papervision3D-engine, en hoe je je creatie uit het scherm kunt laten springen met een anaglyph-effect in combinatie met 3D-bril.
Heb je een 3D-bril rondslingeren? Hier in het VK heeft Channel 4 een speciale 3D-week - zeven dagen tv-programma's uitgezonden in 3D - dus veel mensen hier doen het. Laten we ze gebruiken.
Deze tweeledige zelfstudie laat je zien hoe je aan de slag kunt met de Papervision3D-engine en hoe je je creatie uit het scherm kunt laten springen..
In dit eerste deel leer je de basisprincipes van PV3D, en eindig je met zoiets als dit:
... en in het tweede deel leert u meer over het anaglyph-effect voor een 3D-bril en past u het toe op wat u zo hebt gemaakt:
Als u Flash gebruikt, maakt u een nieuw ActionScript 3.0 Flash-bestand. Stel de grootte van het podium in op wat je maar wilt - ik blijf bij de standaard 550 bij 400 pixels.
Maak een nieuw ActionScript-bestand terwijl u bezig bent en sla het op als Main.as in dezelfde map als uw FLA. We gaan dit AS-bestand gebruiken als de FLA's documentklasse, dus klik op een lege ruimte in uw FLA-bestand en voer in Hoofd in het vak "Documentklasse" van het venster Eigenschappen.
(Maak een nieuw AS3-project als u de Flash IDE niet gebruikt.)
Ga naar de downloadpagina van Papervision. Er zijn veel verschillende versies en een paar verschillende soorten bestanden (zip, swc, mxp). Pak gewoon het nieuwste .zip-bestand (zou moeten zeggen Uitgelicht ernaast). Degene die ik gebruik, wordt gebeld Papervision3D 2.1.920.zip (voor gebruik met het boek "Papervision3D Essentials").
Pak het zipbestand dat u zojuist hebt gedownload uit en plaats het overal op uw harde schijf. Ik hou ervan om alle verschillende engines die ik gebruik in dezelfde map te bewaren, maar het is aan jou.
Flash moet weten waar je Papervision hebt geëxtraheerd voordat het het kan gebruiken. We gebruiken een classpath hiervoor: klik Bewerken> Voorkeuren, kiezen ActionScript, dan klikken ActionScript 3.0-instellingen ... .
Klik in het vak dat verschijnt op het kleine "draadkruis" -pictogram, zoek de map waarin u Papervision hebt uitgepakt en klik op OK. Klik op OK in de andere vakken totdat u weer bij de FLA komt.
Als u de Flash IDE niet gebruikt, moet u dit op een andere manier instellen. In FlashDevelop moet u bijvoorbeeld klikken Hulpmiddelen> Wereldwijde klassenpaden.
In Papervision moeten al je 3D-objecten in een tafereel. Het lijkt op het werkgebied in standaard ActionScript. Dus voordat we iets doen, moeten we een Scene3D object dat al het andere bevat.
Schakel over naar uw Main.as-bestand. Laten we snel de basiscode toevoegen die nodig is voor elke documentklasse:
pakket import flash.display.MovieClip; public class Main breidt MovieClip uit public function Main ()
Het Scene3D-object is binnen org.papervision3d.scenes.Scene3D, dus we moeten het doen importeren dat, maak dan een nieuw openbare var om de scène vast te houden en ten slotte het eigenlijke scèneobject te maken: (lijnen 4, 8 en 12)
pakket import flash.display.MovieClip; import org.papervision3d.scenes.Scene3D; public class Main breidt MovieClip uit public var scene: Scene3D; openbare functie Main () scene = new Scene3D ();
Om te beginnen, laten we gewoon een grote gewone kubus maken die in onze scène zit.
We volgen dezelfde soort stappen als hierboven om het te maken en voegen het vervolgens toe aan onze scène: (regels 5, 10, 15, 16)
pakket import flash.display.MovieClip; import org.papervision3d.scenes.Scene3D; import org.papervision3d.objects.primitives.Cube; public class Main breidt MovieClip uit public var scene: Scene3D; openbare var-kubus: Cube; openbare functie Main () scene = new Scene3D (); cube = nieuwe Cube (); scene.addChild (kubus);
Merk op dat we "addChild ()" gebruiken om de kubus aan de scène toe te voegen, precies zoals we doen wanneer een MovieClip aan het werkgebied wordt toegevoegd.
De bovenstaande code geeft een foutmelding als u het probeert uit te voeren. Dat komt omdat we de kubus niet hebben verteld hoe de oppervlakken van het gezicht er uit moeten zien.
Papervision gebruikt materialen om te beschrijven hoe een oppervlak eruit ziet. We kunnen een heel eenvoudig, eenkleurig materiaal maken met een ColorMaterial:
var grayMaterial: ColorMaterial = nieuw ColorMaterial (0xCCCCCC);
De "0xCCCCCC" geeft de kleur grijs weer; neem gewoon de kleurcode van elke kleur en vervang de # met 0x:
Omdat een kubus zes vlakken heeft, moeten we er zes geven. Om dit te doen, plaatsen we alle zes in een lijst:
var materialsList: MaterialsList = new MaterialsList (); materialsList.addMaterial (grayMaterial, "front"); materialsList.addMaterial (grayMaterial, "back"); materialsList.addMaterial (grayMaterial, "left"); materialsList.addMaterial (grayMaterial, "right"); materialsList.addMaterial (grayMaterial, "top"); materialsList.addMaterial (grayMaterial, "bottom");
... en geef die lijst door aan de kubus wanneer we deze maken:
cube = nieuwe Cube (materialsList);
Dus je hele code zou er als volgt uit moeten zien: (vergeet niet het importeren statements!)
pakket import flash.display.MovieClip; import org.papervision3d.scenes.Scene3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.utils.MaterialsList; public class Main breidt MovieClip uit public var scene: Scene3D; openbare var-kubus: Cube; public function Main () var grayMaterial: ColorMaterial = new ColorMaterial (0xCCCCCC); var materialsList: MaterialsList = new MaterialsList (); materialsList.addMaterial (grayMaterial, "front"); materialsList.addMaterial (grayMaterial, "back"); materialsList.addMaterial (grayMaterial, "left"); materialsList.addMaterial (grayMaterial, "right"); materialsList.addMaterial (grayMaterial, "top"); materialsList.addMaterial (grayMaterial, "bottom"); scène = nieuwe Scene3D (); cube = nieuwe Cube (materialsList); scene.addChild (kubus);
We hebben dus geen fouten, maar om iets te zien, moeten we een toevoegen camera naar de scène. We zullen alles zien via de "lens" van de camera.
Het toevoegen van een camera is net zo eenvoudig als het toevoegen van een kubus - eigenlijk eenvoudiger, omdat we het niet aan het scenario hoeven toe te voegen ():
import org.papervision3d.cameras.Camera3D;
openbare var camera: Camera3D;
scène = nieuwe Scene3D (); cube = nieuwe Cube (materialsList); scene.addChild (kubus); camera = nieuwe Camera3D (); // dit is de nieuwe regel in Main ()
Nu staat er een camera op de scène, maar deze is niet aangesloten op een uitgang, dus we kunnen de kubus nog steeds niet zien!
Standaard wordt de kubus rechts in het midden van de scène geplaatst (bij x = 0, y = 0, z = 0) en wordt de camera 1000 eenheden erachter geplaatst (bij x = 0, y = 0, z = -1000).
Hoe kunnen we het beeld krijgen dat de camera ziet in het Flash Player-venster?
Het antwoord is, we gebruiken een uitkijk postje. Dit is een type DisplayObject, zoals een MovieClip, dus we kunnen dit aan het stadium toevoegen (ch) (). Maar we kunnen ook Papervision maken geven (d.w.z. teken) de weergave van de camera naar dit kijkvenster - het is een beetje alsof een kunstenaar tekent wat hij door een cameralens kan zien, en vervolgens zijn tekening kan nemen en deze op een tv-toestel kan plakken. Behalve sneller.
We moeten dus een viewport en een renderer maken:
import org.papervision3d.view.Viewport3D; import org.papervision3d.render.BasicRenderEngine;
openbare var viewport: Viewport3D; public var renderer: BasicRenderEngine;
// zet dit aan het einde van Main () viewport = new Viewport3D (); viewport.autoScaleToStage = true; // dit maakt de viewport zo groot als de stage addChild (viewport); renderer = nieuwe BasicRenderEngine ();
Nu hoeven we alleen maar de renderer de daadwerkelijke weergave te laten doen. Hiervoor moet het de scène, de camera en de viewport weten:
renderer.renderScene (scène, camera, viewport);
Eindelijk! We kunnen eindelijk de SWF testen. Tromgeroffel aub…
Ongelooflijk! Verbijsterend! OK prima, het is eigenlijk best kreupel. Hoe kunnen we zelfs zeggen dat het een kubus is? Het ziet eruit als een vierkant.
Als we de kubus draaien, kunnen we zien of het een kubus is of niet.
Omdat de kubus drie dimensies heeft, is het woord "roteren" een beetje verwarrend - welke richting bedoelen we? We moeten aangeven of we rond de x-as, y-as of z-as roteren.
De Kubus object heeft drie eigenschappen die we kunnen gebruiken om dit te definiëren, genaamd (niet verrassend) rotationX, rotationY en rotationZ. Laten we er een paar veranderen:
scène = nieuwe Scene3D (); cube = nieuwe Cube (materialsList); cube.rotationX = 25; // verander rotatie cube.rotationY = 40; // change rotation scene.addChild (cube); camera = nieuwe Camera3D ();
Het is beter, maar omdat alle vlakken exact dezelfde kleur hebben, vloeien ze gewoon in elkaar over. Laten we dat oplossen.
In plaats van grijs, ga ik de zijkanten schilderen met het ActiveTuts + -logo.
Als u de Flash IDE gebruikt, maakt u een nieuwe filmclip en tekent of plakt u de afbeelding die u wilt gebruiken. Ik heb het logo opgenomen in mijn FLA-bibliotheek in de zip.
Klik met de rechtermuisknop op uw filmclip en selecteer Eigenschappen. Vink "export voor ActionScript" aan en geef het een klassenaam. Hierdoor krijg je er toegang toe met behulp van code. (Als u de Flash IDE niet gebruikt, bevat de zip ook een SWC met een MovieClip genaamd ActiveTutsLogo die u kunt gebruiken.U kunt ook een nieuwe MovieClip-code maken en uw afbeelding eraan toevoegen.Ik ga niet naar ga hier echter dieper op in.)
Inplaats van een ColorMaterial we gaan een gebruiken MovieMaterial, en in plaats van een kleur op te geven, geven we een filmclip op. Dus vervang dit:
var grayMaterial: ColorMaterial = nieuw ColorMaterial (0xCCCCCC); var materialsList: MaterialsList = new MaterialsList (); materialsList.addMaterial (grayMaterial, "front"); materialsList.addMaterial (grayMaterial, "back"); materialsList.addMaterial (grayMaterial, "left"); materialsList.addMaterial (grayMaterial, "right"); materialsList.addMaterial (grayMaterial, "top"); materialsList.addMaterial (grayMaterial, "bottom");
… hiermee:
var logoMaterial: MovieMaterial = nieuw MovieMaterial (nieuwe ActiveTutsLogo ()); // vervang hierboven "ActiveTutsLogo" met de klassenaam van uw filmclip var materialsList: MaterialsList = new MaterialsList (); materialsList.addMaterial (logoMaterial, "front"); materialsList.addMaterial (logoMaterial, "back"); materialsList.addMaterial (logoMaterial, "left"); materialsList.addMaterial (logoMaterial, "right"); materialsList.addMaterial (logoMaterial, "top"); materialsList.addMaterial (logoMaterial, "bottom");
Je moet ook het MovieMaterial importeren:
import org.papervision3d.materials.MovieMaterial;
Test het opnieuw:
Nou, het werkt, maar het ziet er een beetje gedeukt uit.
De "gedeukte" look is omdat Papervision standaard is ingesteld om dingen snel te tekenen in plaats van nauwkeurig. Ik wil ervoor zorgen dat deze tutorial op langzamere computers wordt uitgevoerd, dus ik laat het hierbij, maar hier is hoe u het kunt verbeteren:
Wanneer u de kubus maakt, kunt u parameters doorgeven om te definiëren hoeveel segmenten elk gezicht is opgesplitst in. Hoe meer segmenten u kiest, hoe nauwkeuriger de kubus eruitziet, maar hoe langzamer deze wordt weergegeven.
Ik heb geconstateerd dat 10 een groot aantal segmenten is om in elke richting te gebruiken. Hier ziet u hoe de code er uitziet:
kubus = nieuwe kubus (materiaallijst, 500, 500, 500, 10, 10, 10);
De vijfde, zesde en zevende parameter bepalen het aantal segmenten dat in elke richting wordt gebruikt. Om ze in te stellen, moeten we echter alle parameters specificeren voor de vijfde ook.
We specificeren de eerste parameter al - dat is de materiaallijst. De tweede, derde en vierde parameter bepalen de breedte, diepte en hoogte van de kubus. Deze zijn standaard ingesteld op 500, dus ik heb ze hier hetzelfde gehouden.
Als u de bovenstaande coderegel gebruikt, ziet uw kubus er als volgt uit:
Veel netter!
We kunnen een gewone MovieClip ronddraaien door het te vergroten omwenteling eigenschap elk frame - en natuurlijk kunnen we hetzelfde doen met de kubus en de rotatieX / Y / Z-waarden.
Maak een ENTER_FRAME-gebeurtenislistener, die elk frame zal uitvoeren:
import flash.events.Event;
// onder aan Main () addEventListener (Event.ENTER_FRAME, onEnterFrame);
// als een nieuwe functie // in de hoofdklasse maar buiten de functie Main () openbare functie onEnterFrame (evt: Event): void cube.rotationX = cube.rotationX + 5; cube.rotationY = cube.rotationY + 5;
Hierdoor zal de kubus elk frame een beetje meer draaien. Dus als je de SWF nu uitprobeert ... blijft de kubus volledig stil. huh?
Denk eens terug aan de schilder. We kijken nog steeds naar zijn oude foto - we hebben hem nodig om ons een nieuw beeld te geven, anders zullen we geen wijzigingen zien!
Dus, wijzig de functie onEnterFrame ():
public function onEnterFrame (evt: Event): void cube.rotationX = cube.rotationX + 5; cube.rotationY = cube.rotationY + 5; renderer.renderScene (scène, camera, viewport);
Bekijk het nu:
Eén kubus is geweldig, maar zoals Roman je al liet zien hoe dat te doen met Away3D, laten we het een beetje verder brengen.
Laten we er nog een paar toevoegen, om een horizontale rij kubussen te vormen. We kunnen een eenvoudig gebruiken voor lus om dat te doen; vervang gewoon deze code:
cube = nieuwe Cube (materialsList); cube.rotationX = 25; // verander rotatie cube.rotationY = 40; // change rotation scene.addChild (cube);
… hiermee:
for (var i: int = -1; i <= 1; i++ ) cube = new Cube( materialsList ); cube.x = i * 350; cube.rotationX = 25; cube.rotationY = 40; scene.addChild( cube );
Merk op dat ik de x-positie van elke kubus maak afhankelijk van hoe ver we door de lus zijn. Als u dit uitvoert, krijgt u het volgende:
Oeps, de kubussen staan te dicht bij elkaar. We kunnen ze verkleinen om dit te omzeilen; verander gewoon de schaal eigendom van elke kubus:
for (var i: int = -1; i <= 1; i++ ) cube = new Cube( materialsList ); cube.x = i * 350; cube.scale = 0.40; //make the cubes 40% of original size cube.rotationX = 25; cube.rotationY = 40; scene.addChild( cube );
Dus dat lost het kruispuntprobleem op, maar slechts één van onze kubussen draait. Hoe kan dat?
Het is omdat het kubus variabele heeft altijd alleen betrekking op de laatste cube gemaakt - en onze functie onEnterFrame () verandert alleen de rotaties van die ene kubus.
Dus om dit op te lossen, hebben we een array nodig. Net zoals onze materialenlijst verschillende materialen heeft opgeslagen, slaat onze array meerdere kubussen op.
public var cubeArray: Array;
cubeArray = new Array (); // maak de nieuwe Array voor (var i: int = -1; i <= 1; i++ ) cube = new Cube( materialsList ); cube.x = i * 350; cube.scale = 0.40; cube.rotationX = 25; cube.rotationY = 40; scene.addChild( cube ); cubeArray.push( cube ); //add the new cube to the array
("Push" betekent gewoon "toevoegen aan het einde van de lijst".)
Nu elke kubus zich in de array bevindt, kunnen we elk frame door de array herhalen en elk frame roteren:
public function onEnterFrame (evt: Event): void for each (cube in cubeArray) cube.rotationX = cube.rotationX + 5; cube.rotationY = cube.rotationY + 5; renderer.renderScene (scène, camera, kijkvenster);
De "voor elke" lus maakt de kubus variabelen verwijzen beurtelings naar elke kubus, één voor één, in plaats van alleen naar de laatste kubus die is gemaakt zoals eerder. Dit is het resultaat:
Succes!
We hebben een rij kubussen gemaakt, dus een vierkant wordt niet moeilijk. In plaats van slechts drie kubussen te maken, maken we er drie lijnen van drie kubussen.
Om dit te doen, kunnen we een loop-in-a-lus gebruiken, zoals zo:
for (var i: int = -1; i <= 1; i++ ) for ( var j:int = -1; j <= 1; j++ ) //loop inside a loop cube = new Cube( materialsList ); cube.x = i * 350; cube.y = j * 350; //don't forget to change j! cube.scale = 0.40; cube.rotationX = 25; cube.rotationY = 40; scene.addChild( cube ); cubeArray.push( cube ); //don't forget this closing bracket either
Test het uit:
Leuk. En merk op dat we de code in onEnterFrame () helemaal niet hoefden te veranderen; de lus die elk frame uitvoert, roteert gewoon elke kubus in de array - en we duwen nog steeds elke afzonderlijke kubus naar de array.
Nou, het zou teleurstellend zijn om op een plein te stoppen, toch? Dit is tenslotte een 3D-zelfstudie.
Ik verwacht dat je zelf kunt uitzoeken hoe je deze stap moet doen. Maar voor het geval dat u wilt vergelijken:
for (var i: int = -1; i <= 1; i++ ) for ( var j:int = -1; j <= 1; j++ ) for ( var k:int = 0; k <= 2; k++ ) cube = new Cube( materialsList ); cube.x = i * 350; cube.y = j * 350; cube.z = k * 350; cube.scale = 0.40; cube.rotationX = 25; cube.rotationY = 40; scene.addChild( cube ); cubeArray.push( cube );
Ik ben hier een beetje stiekem geweest. Ik heb k gestart op 0 in plaats van op -1, omdat anders de voorste laag kubussen te dicht bij de camera zou zijn. Je kunt natuurlijk de nummers gebruiken die je leuk vindt.
Hé, heb je gemerkt dat het "gedeukte" effect in feite is verdwenen nu we kleinere blokjes gebruiken?
Geweldig!
Dit is alleen maar krassen op het oppervlak van wat je kunt doen met Papervision3D. Voordat we naar een 3D-bril gaan, zijn hier een paar dingen waarmee je kunt experimenteren:
In het tweede deel leert u hoe u uw scène met een 3D-bril kunt laten werken. Dus als je een paar hebt, gooi ze dan niet weg!
In de tussentijd, bedankt voor het lezen van het eerste deel. Ik hoop dat je het nuttig hebt gevonden. Als je vragen hebt of als er iets verwarrends is, plaats dan een reactie hieronder.