En introduksjon til SceneKit Fundamentals

Hva du skal skape

I denne opplæringen lærer du hvordan du lager en grunnleggende 3D-scene i SceneKit uten kompleksiteten til OpenGL. Dette inkluderer grunnleggende geometri, kameraer, lys, materialer og skygger.

Introduksjon

SceneKit-rammen ble først lansert av Apple sammen med OS X 10.8 Mountain Lion og ble senere gjort tilgjengelig på iOS med utgivelsen av iOS 8. Formålet med dette rammeprogrammet er å tillate utviklere å enkelt integrere 3D-grafikk i spill og applikasjoner uten kompleksiteten av grafikk-APIer, for eksempel OpenGL og Metal.

SceneKit lar deg bare gi en beskrivelse av eiendelene du vil ha i din scene, med selve rammen som håndterer alle OpenGL-gjengivelsenskoder for deg. I denne første opplæringen vil jeg lære deg noen av grunnleggende for å jobbe med 3D-eiendeler og grunnleggende i SceneKit-rammen.

Denne opplæringen krever at du kjører på Xcode 6 eller høyere. Selv om det ikke er nødvendig, anbefaler jeg at du bruker en fysisk enhet som kjører iOS 8 for å teste din SceneKit-kode på. Du kan bruke iOS-simulatoren, men ytelsen er ikke bra hvis scenen din blir mer kompleks. Vær oppmerksom på at testing på en fysisk iOS-enhet krever at du har en registrert iOS-utviklerkonto.

1. Grunnlag

Det første du trenger å vite om SceneKit er at eiendeler, representert av noder, er arrangert i et hierarkisk tre som kalles en scene graf. Hvis du er kjent med iOS-utviklingen, fungerer dette treet som en vanlig se hierarkieti UIKit. Hver scene du lager, har en enkelt rotnode som du legger til påfølgende nodene, og som også gir grunnlag for 3D-koordinatsystemet for den scenen.

Når du legger til en node på en scene, er posisjonen angitt av et sett med tre tall, en tre-komponentvektor representert av SCNVector3 struktur i koden din. Hver av disse tre komponentene definerer nodens posisjon på x-, y- og z-aksene som vist i bildet nedenfor.

Image Credit: Apple SceneKit Framework Reference

Din scenes rotknuteposisjon er definert som (0, 0, 0). I bildet ovenfor er dette stedet hvor de tre aksene skjærer. Det medfølgende kameraet i bildet representerer standardretningen et kamera peker på når det legges til din scene.

Nå som du vet noen av grunnleggende om hvordan objekter er representert av SceneKit, er du klar til å begynne å skrive noen kode.

2. Prosjektoppsett

Åpne Xcode og opprett en ny iOS-applikasjon basert på Enkeltvisningsprogram mal. Mens du enkelt kan lage et program fra Spill mal ved hjelp av SceneKit, for denne opplæringen skal jeg vise deg hvordan du begynner å jobbe med SceneKit fra bunnen av.

Skriv inn en Produktnavn, sett Språk til Fort, og enheter til Universell. Klikk neste å fortsette.

Etter å ha opprettet prosjektet, naviger til ViewController.swift og legg til følgende importoppgave øverst for å importere SceneKit-rammeverket:

importere SceneKit

Deretter legger du til følgende implementering av viewDidLoad metode i ViewController klasse:

overstyr func viewDidLoad () super.viewDidLoad () la sceneView = SCNView (ramme: self.view.frame) self.view.addSubview (sceneView)

I viewDidLoad Metode, vi lager en SCNView objekt, passerer i rammen av visningskontrollørens visning. Vi tildeler SCNView forekommer til en konstant, sceneView, og legg det til som et undervisning av visningskontrollens visning.

De SCNView klassen er en underklasse av UIView og gir et uttak for ditt SceneKit-innhold. Bortsett fra å ha funksjonaliteten til en vanlig visning, an SCNView har også flere egenskaper og metoder knyttet til SceneKit-innholdet.

For å kontrollere at alt fungerer som det skal, bygg og kjør appen din. Du vil se at du bare har en blank, hvit visning.

3. Sceneoppsett

For å gjengi innhold i en SCNView, du må først opprette en SCNScene og tilordne den til visningen. I denne scenen må du legge til en kamera og minst ett lys. For dette eksempelet skal du også legge til en kube for SceneKit å gjengi. Legg til følgende kode i viewDidLoad metode:

overstyr func viewDidLoad () super.viewDidLoad () la sceneView = SCNView (ramme: self.view.frame) self.view.addSubview (sceneView) la scene = SCNScene () sceneView.scene = scene la kamera = SCNCamera cameraNode = SCNNode () cameraNode.camera = kamera kameraNode.position = SCNVector3 (x: 0.0, y: 0.0, z: 3.0) la lys = SCNLight () light.type = SCNLightTypeOmni la lightNode = SCNNode () lightNode.light = light lightNode.position = SCNVector3 (x: 1,5, y: 1,5, z: 1,5) la cubeGeometry = SCNBox (bredde: 1,0, høyde: 1,0, lengde: 1,0, chamferRadius: 0,0) la cubeNode = SCNNode (geometri: cubeGeometry) scene. rootNode.addChildNode (lightNode) scene.rootNode.addChildNode (cameraNode) scene.rootNode.addChildNode (cubeNode)

La oss gå gjennom viewDidLoad metode trinn for trinn:

  • Du oppretter først scenen for visningen din ved å påkalle i det metode. Med mindre du laster inn en forberedt scene fra en ekstern fil, er dette initialisereren du alltid vil bruke.
  • Deretter oppretter du en SCNCamera objekt og en SCNNode eksempel for kameraet. Du tilordner deretter SCNCamera protestere mot kamera tilhører cameraNode og flytt denne noden langs z-aksen for å se kuben du vil lage litt senere.
  • I neste trinn oppretter du en SCNLight objekt og a SCNNode oppkalt lightNode. De SCNLight forekomst er tildelt til lys egenskapen til lysnoden. De type eiendom av SCNLight er satt til SCNLightTypeOmni. Denne lystypen fordeler lys jevnt i alle retninger fra et punkt i 3D-plass. Du kan tenke på denne lys typen som en vanlig lyspære.
  • Til slutt lager du en terning ved å bruke SCNBox klasse, noe som gjør bredden, høyden og lengden av samme størrelse. De SCNBox klassen er en underklasse av SCNGeometry og er en av de primitive figurene du kan lage. Andre former inkluderer sfærer, pyramider og toruser. Du lager også en node som passerer i terningen for geometri parameter.
  • For å sette opp scenen, legger du til de tre noder (kamera, lys og terning) til scenens scenediagram. Ekstra oppsett er ikke nødvendig som en SCNScene objekt oppdager automatisk når en knute inneholder et kamera eller lysobjekt, som gjør scenen tilsvarende.

Bygg og kjør appen din, og du vil se at du nå har en svart terning som lyser opp av lyset ditt fra øverste høyre hjørne.

Dessverre ser kuben ikke tredimensjonal ut i øyeblikket. Dette skyldes at kameraet er plassert rett foran den. Hva du skal gjøre nå, er å endre posisjonen til kameraet slik at det gir et bedre bilde av kuben.

For å holde kameraet spiss direkte på terningen, vil du også legge til en SCNLookAtConstraint til kameraet. Start med å oppdatere posisjonen til kameraet som vist nedenfor.

cameraNode.position = SCNVector3 (x: -3.0, y: 3.0, z: 3.0)

Deretter legger du til følgende kodestykke i ViewDidLoad-metoden, etter at du har installert noden for terningen:

la begrensning = SCNLookAtConstraint (mål: cubeNode) constraint.gimbalLockEnabled = true cameraNode.constraints = [begrensning]

Posisjonsendringen beveger kameraet til venstre og oppover. Ved å legge til en begrensning, med terningen som mål og gimbalLockEnabled satt til ekte, Du sikrer at kameraet forblir parallelt med horisonten og visningsporten, enhetens skjerm i dette tilfellet. Dette gjøres ved å deaktivere rotasjon langs rulleaksen, idet aksen peker fra kameraet til begrensningens mål.

Bygg og kjør appen din på nytt, og du vil se kuben i alle sine 3D-ære.

4. Materialer og skygger

Det er på tide å legge til mer realisme på scenen med materialer og skygger. Du kommer først til å trenge et annet objekt for å kaste en skygge på. Bruk følgende kodestykke for å lage et plan, et flatt rektangel, og plasser det under kuben. Ikke glem å legge til den nye noden som en barnekode til scenens rotknutepunkt.

overstyr func viewDidLoad () ... la cubeGeometry = SCNBox (bredde: 1.0, høyde: 1.0, lengde: 1.0, chamferRadius: 0.0) la cubeNode = SCNNode (geometri: cubeGeometry) la planeGeometry = SCNPlane (bredde: 50,0, høyde: 50,0) la planetNode = SCNNode (geometri: planetGeometry) planetNode.eulerAngles = SCNVector3 (x: GLKMathDegreesToRadians (-90), y: 0, z: 0) planetNode.position = SCNVector3 (x: 0, y: -0,5, z: 0) ... scene.rootNode.addChildNode (lightNode) scene.rootNode.addChildNode (cameraNode) scene.rootNode.addChildNode (cubeNode) scene.rootNode.addChildNode (planeNode)

Ved å endre flyknutens Tait-Bryan rotasjoner eiendom, roterer du flyet bakover 90 grader langs x-aksen. Vi må gjøre dette, fordi flyene er opprettet vertikalt som standard. I SceneKit beregnes rotasjonsvinkler i radianer i stedet for grader, men disse verdiene kan enkelt konverteres ved hjelp av GLKMathDegreesToRadians (_ :) og GLKMathsRadiansToDegrees (_ :) funksjoner. GLK står for GLKit, Apples OpenGL-rammeverk.

Deretter legger du til et materiale på terningen og flyet. For dette eksempelet skal du gi terningen og flyet en solid farge, rød og grønn henholdsvis. Legg til følgende linjer i viewDidLoad metode for å lage disse materialene.

overstyr func viewDidLoad () ... planNode.position = SCNVector3 (x: 0, y: -0,5, z: 0) la redMaterial = SCNMaterial () redMaterial.diffuse.contents = UIColor.redColor () cubeGeometry.materials = [redMaterial] la greenMaterial = SCNMaterial () greenMaterial.diffuse.contents = UIColor.greenColor () planeGeometry.materials = [greenMaterial] la begrensning = SCNLookAtConstraint (mål: cubeNode) ...

For hver SCNMaterial objekt, tilordner du dets diffuse innhold a UIColor verdi. Den diffuse egenskapen til et materiale bestemmer hvordan det vises når det er direkte lys. Legg merke til at verdien som er tildelt, ikke må være a UIColor gjenstand. Det er mange andre akseptable objekttyper som kan tilordnes denne egenskapen, for eksempel UIImageCALayer, og til og med en SpriteKit tekstur (SKTexture).

Bygg og kjør appen din igjen for ikke bare å se flyet for første gang, men også materialene du opprettet.

Nå er det på tide å legge til noen skygger på scenen din. Av de fire lysene som er tilgjengelige i SceneKit, kan bare spotlys skape skygger. For dette eksempelet skal du omdanne ditt eksisterende omni-lys til et spotlys, rettet mot kassen. Legg til følgende kode i viewDidLoad metode:

overstyr func viewDidLoad () ... la lys = SCNLight () light.type = SCNLightTypeSpot light.spotInnerAngle = 30.0 light.spotOuterAngle = 80.0 light.castsShadow = sant la lightNode = SCNNode () lightNode.light = light lightNode.position = SCNVector3 x: 1,5, y: 1,5, z: 1,5) ... la begrensning = SCNLookAtConstraint (mål: cubeNode) constraint.gimbalLockEnabled = true cameraNode.constraints = [begrensning] lightNode.constraints = [begrensning] ...

For å lage spotlyset, setter du først lysets type til SCNLightTypeSpot. Du angir deretter spotlysets indre og ytre vinkel i grader. Standardverdiene er 0 og 45 henholdsvis. Den indre vinkelen bestemmer hvor mye område lyset dekker i direkte lys mens ytre vinkel bestemmer hvor mye område er delvis opplyst. Forskjellen mellom disse vinklene blir klar når du ser den resulterende scenen. Du forklarer da eksplisitt lyset for å kaste skygger og også legge til det samme SCNLookAtConstraint som du opprettet for kameraet ditt tidligere.

Bygg og kjør appen din for å se den resulterende scenen. Den indre vinkelen du spesifiserte i koden din, vises hvor flyet er en solid grønn, rett under kuben. Ytre vinkelen er vist ved lysets gradient som fades til svart når den beveger seg bort fra lysets mål.

Du ser at du nå har kuben som støtter en skygge riktig. Spotlyset lyser imidlertid bare en del av flyet. Dette skyldes at det ikke er omgivende lys i scenen din. 

Et omgivende lys er en lyskilde som belyser alt med en like lysfordeling. Fordi et omgivelseslys lyser opp hele scenen, spiller ingen rolle det, og du kan legge det til en node du vil ha, til og med samme node som kameraet ditt. Bruk følgende kodestykke for å lage et omgivende lys for scenen din.

overstyr func viewDidLoad () ... la kamera = SCNCamera () la kameraNode = SCNNode () kameraNode.camera = kamera kameraNode.position = SCNVector3 (x: -3,0, y: 3,0, z: 3,0) la ambientLight = SCNLight () ambientLight .type = SCNLightTypeAmbient ambientLight.color = UIColor (rød: 0.2, grønn: 0.2, blå: 0.2, alfa: 1.0) cameraNode.light = ambientLight ...

Kodestykket oppretter en SCNLight, akkurat som du gjorde før. Hovedforskjellen er lysets type eiendom, som er satt til SCNLightTypeAmbient. Du stiller også fargen til mørkegrå, slik at den ikke overstyrer scenen din. Standardfarge for lys er ren hvit (RGB-verdi på 1, 1, 1) og med denne fargen på et omgivende lys får hele scenen til å bli fullt opplyst som vist på skjermbildet under.

Bygg og kjør appen din en gang for å se det endelige resultatet.

Konklusjon

Hvis du har gjort det til slutten av denne opplæringen, bør du nå være komfortabel med følgende emner:

  • 3D-koordinatsystemet og scenediagrammet som brukes av SceneKit
  • sette opp en SCNView med en SCNScene
  • legger til kameraer, lys og noder til en scene
  • tilordne materialer til geometrier
  • arbeider med lys for å belyse en scene og kaste skygger

I neste veiledning i denne serien lærer du om noen mer avanserte konsepter i SceneKit-rammen, inkludert animasjon, brukerinteraksjon, partikkelsystemer og simulerende fysikk.