În acest tutorial, veți învăța cum să creați o scenă 3D de bază în SceneKit fără complexitatea OpenGL. Aceasta include geometria de bază, camerele, lumina, materialele și umbrele.
Cadrul SceneKit a fost lansat pentru prima dată de către Apple alături de OS X 10.8 Mountain Lion și a fost ulterior pus la dispoziție pe iOS cu lansarea iOS 8. Scopul acestui cadru este de a permite dezvoltatorilor să integreze cu ușurință grafica 3D în jocuri și aplicații fără complexitatea grafică API, cum ar fi OpenGL și Metal.
SceneKit vă permite să furnizați pur și simplu o descriere a activelor pe care le doriți în scenă, cu cadrul însuși manipulând tot codul de redare OpenGL pentru dvs. În acest prim tutorial, vă voi învăța câteva dintre fundamentele de lucru cu active 3D și elementele de bază ale cadrului SceneKit.
Acest tutorial cere să rulați la Xcode 6 sau o versiune superioară. În timp ce nu este necesar, vă recomandăm să utilizați un dispozitiv fizic care rulează iOS 8 pentru a vă testa codul SceneKit. Puteți folosi simulatorul iOS, dar performanța nu este excelentă dacă scena dvs. devine mai complexă. Rețineți că testarea pe un dispozitiv fizic iOS necesită un cont de dezvoltator iOS înregistrat.
Primul lucru pe care trebuie să știți despre SceneKit este că activele, reprezentate de noduri, sunt aranjate într-un arbore ierarhic numit graficul scenei. Dacă sunteți familiarizat cu dezvoltarea iOS, acest arbore funcționează mult ca un obișnuit vizualiza ierarhiaîn UIKit. Fiecare scenă pe care o creați are un singur nod rădăcină în care adăugați noduri ulterioare și care oferă, de asemenea, o bază pentru sistemul de coordonate 3D al acelei scene.
Când adăugați un nod la o scenă, poziția sa este specificată de un set de trei numere, un vector cu trei componente reprezentat de SCNVector3
structură în codul dvs. Fiecare dintre aceste trei componente definește poziția nodului pe axele x, y și z, după cum se arată în imaginea de mai jos.
Poziția nodului tău rădăcină este definită ca (0, 0, 0). În imaginea de mai sus, aceasta este poziția în care se intersectează cele trei axe. Camera inclusă în imagine reprezintă direcția implicită pe care un aparat de fotografiat o aduce în scenă.
Acum că știți câteva dintre elementele de bază despre modul în care obiectele sunt reprezentate de SceneKit, sunteți gata să începeți să scrieți un cod.
Deschideți Xcode și creați un nou Aplicația iOS bazat pe Vizualizare individuală șablon. În timp ce puteți crea cu ușurință o aplicație de la Joc șablon folosind SceneKit, pentru acest tutorial vă voi arăta cum să începeți să lucrați cu SceneKit de la zero.
Introduceți a numele produsului, a stabilit Limba la Rapid, și Dispozitive la universal. Clic Următor → a continua.
După crearea proiectului, navigați la ViewController.swift și adăugați următoarea declarație de import în partea de sus pentru a importa cadrul SceneKit:
import SceneKit
Apoi, adăugați următoarea implementare a viewDidLoad
metodă în ViewController
clasă:
override func vizualizareDidLoad () super.viewDidLoad () permite sceneView = SCNView (cadru: self.view.frame) self.view.addSubview (sceneView)
În viewDidLoad
metoda, vom crea o SCNView
obiect, trecând în cadrul vizualizării controlerului de vizualizare. Noi atribuim SCNView
exemplu la o constantă, sceneView
, și adăugați-o ca o subiectivă a vizualizării controlerului de vizualizare.
SCNView
clasa este o subclasă de UIView
și oferă o priză pentru conținutul dvs. SceneKit. Pe lângă faptul că are funcționalitatea unei viziuni obișnuite, o SCNView
are de asemenea mai multe proprietăți și metode referitoare la conținutul SceneKit.
Pentru a verifica dacă totul funcționează corect, construiți și executați aplicația. Veți vedea că aveți doar o vizualizare alb albă.
Pentru a reda conținut într-un SCNView
, trebuie mai întâi să creați un SCNScene
și alocați-l opiniei. În această scenă, trebuie să adăugați a camera foto și cel puțin o lumină. Pentru acest exemplu, veți adăuga, de asemenea, un cub pentru SceneKit pentru a face. Adăugați următorul cod la viewDidLoad
metodă:
override funcția viewDidLoad () super.viewDidLoad () let sceneView = SCNView (cadru: self.view.frame) auto.view.addSubview (sceneView) let scene = SCNScene () sceneView.scene = scena let camera = SCNCamera cameraNode = camera SCNNode () cameraNode.camera = cameraName.position = SCNVector3 (x: 0.0, y: 0.0, z: 3.0) (n = 1, lm: 1.5, z: 1.5) permite cubeGeometry = SCNBox (lățime: 1,0, înălțimea: 1,0, lungimea: 1,0, chamferRadius: 0,0). rootNode.addChildNode (lightNode) scena.rootNode.addChildNode (cameraNode) scene.rootNode.addChildNode (cubeNode)
Să trecem prin viewDidLoad
metoda pas cu pas:
init
metodă. Dacă nu încărcați o scenă pregătită dintr-un fișier extern, acesta este inițializatorul pe care îl veți folosi întotdeauna.SCNCamera
obiect și an SCNNode
exemplu pentru camera foto. Apoi, atribuiți SCNCamera
obiecte față de aparat foto
proprietatea cameraNode
și mutați acest nod de-a lungul axei z pentru a vedea cubul pe care îl veți crea un pic mai târziu.SCNLight
obiect și a SCNNode
numit lightNode
. SCNLight
este atribuită instanței ușoară
proprietatea nodului luminos. tip
proprietate a SCNLight
este setat sa SCNLightTypeOmni
. Acest tip de lumină distribuie lumină în mod egal în toate direcțiile dintr-un punct din spațiul 3D. Vă puteți gândi la acest tip de lumină ca la un bec obișnuit.SCNBox
clasa, făcând lățimea, înălțimea și lungimea cu aceeași dimensiune. SCNBox
clasa este o subclasă de SCNGeometry
și este una dintre formele primitive pe care le puteți crea. Alte forme includ sfere, piramide și torusi. De asemenea, creați un nod care trece în cub pentru geometrie
parametru.SCNScene
Obiectul detectează automat când un nod conține o cameră sau un obiect luminoas, făcând scena în consecință.Construiți și rulați aplicația dvs. și veți vedea că aveți acum un cub negru care este iluminat de lumina dvs. din colțul din dreapta sus.
Din păcate, cubul nu arată în acest moment tridimensional. Acest lucru se datorează faptului că aparatul foto este poziționat direct în fața acestuia. Ceea ce aveți de gând să faceți acum este să schimbați poziția aparatului foto astfel încât acesta să aibă o vedere mai bună asupra cubului.
Pentru a păstra aparatul foto îndreptat direct spre cub, cu toate acestea, veți adăuga, de asemenea, un SCNLookAtConstraint
la camera foto. Începeți prin actualizarea poziției camerei, după cum se arată mai jos.
cameraNode.position = SCNVector3 (x: -3.0, y: 3.0, z: 3.0)
Apoi, adăugați următorul fragment de cod în metoda viewDidLoad, după instanțializarea nodului pentru cub:
constraint = SCNLookAtConstraint (țintă: cubeNode) constraint.gimbalLockEnabled = true cameraNode.constraints = [constraint]
Schimbarea poziției mută camera la stânga și în sus. Prin adăugarea unei constrângeri, cu cubul ca țintă și gimbalLockEnabled
setat la Adevărat
, vă asigurați că în acest caz camera va rămâne paralelă cu orizontul și cu fereastra de vizualizare, ecranul dispozitivului dvs. Aceasta se face prin dezactivarea rotației de-a lungul axei rolei, axa care indică de la aparatul de fotografiat la ținta constrângerii.
Construiți și rulați aplicația din nou și veți vedea cubul în toată gloria 3D.
Este timpul să adăugați mai multă realism scena cu materiale și umbre. În primul rând veți avea nevoie de un alt obiect pentru a arunca o umbră. Utilizați următorul fragment de cod pentru a crea un plan, un dreptunghi plat și poziționați-l sub cub. Nu uitați să adăugați noul nod ca nod copil la nodul rădăcină al scenei.
override functie viewDidLoad () ... lasa cubeGeometry = SCNBox (lățime: 1.0, înălțime: 1.0, lungime: 1.0, chamferRadius: 0.0) permite cubeNode = SCNNode (geometrie: cubeGeometrie) (x: 0, y: -0.5, z: 0) planNode.position = SCNNode (geometrie: planeGeometrie) planeNode.eulerAngles = SCNVector3 (x: GLKMathDegreesToRadians ... scene.rootNode.addChildNode (lightNode) scene.rootNode.addChildNode (cameraNode) scene.rootNode.addChildNode (cubeNode) scene.rootNode.addChildNode (planeNode)
Prin schimbarea nodului plan Unghiurile lui Euler
proprietate, rotiți planul înapoi cu 90 de grade de-a lungul axei x. Trebuie să facem acest lucru, deoarece avioanele sunt create vertical în mod implicit. În SceneKit, unghiurile de rotație sunt calculate mai degrabă în radiani decât în grade, dar aceste valori pot fi ușor convertite utilizând GLKMathDegreesToRadians (_ :)
și GLKMathsRadiansToDegrees (_ :)
funcții. GLK reprezintă GLKit, cadrul OpenGL al Apple.
Apoi, adăugați un material la cub și avion. Pentru acest exemplu, veți da cubului și avionului o culoare solidă, respectiv roșu și verde. Adăugați următoarele linii la viewDidLoad
pentru a crea aceste materiale.
override functie viewDidLoad () ... planeNode.position = SCNVector3 (x: 0, y: -0.5, z: 0) redMaterial = SCNMaterial () redMaterial.diffuse.contents = UIColor.redColor () cubeGeometry.materials = [redMaterial] permiteți greenMaterial = SCNMaterial () greenMaterial.diffuse.contents = UIColor.greenColor () planeGeometry.materials = [greenMaterial] permite constraint = SCNLookAtConstraint (target: cubeNode) ...
Pentru fiecare SCNMaterial
obiect, îi atribuiți conținuturile sale difuze a UIColor
valoare. Proprietatea difuză a unui material determină cum apare atunci când se află în lumină directă. Rețineți că valoarea atribuită nu trebuie să fie a UIColor
obiect. Există multe alte tipuri de obiecte acceptabile pentru a le atribui acestei proprietăți, cum ar fi UIImage
, CALayer
, și chiar și o textură SpriteKit (SKTexture
).
Construiți și rulați din nou aplicația dvs. pentru a nu vedea doar avionul pentru prima dată, ci și materialele pe care le-ați creat.
Acum este timpul să adăugați niște umbre la scenă. Dintre cele patru tipuri de lumină disponibile în SceneKit, numai luminile spot pot crea umbre. Pentru acest exemplu, veți transforma lumina omni existente într-o lumină spot, orientată spre cub. Adăugați următorul cod la viewDidLoad
metodă:
override functie viewDidLoad () ... permite lumina = SCNLight () light.type = SCNLightTypeSpot lumina.spotInnerAngle = 30.0 light.spotOuterAngle = 80.0 light.castsShadow = true da lightNode = SCNNode () lightNode.light = lumina luminiiNode.position = SCNVector3 x: 1.5, y: 1.5, z: 1.5) ... constraint = constraint = constraint = constraint = constraint = constraint = constraint constraint.gmpalLockEnabled = true cameraNode.constraints =
Pentru a crea lumina spot, setați mai întâi tipul luminii SCNLightTypeSpot
. Apoi specificați unghiurile interioare și exterioare ale luminilor spot în grade. Valorile implicite sunt 0 și 45 respectiv. Unghiul interior determină suprafața pe care lumina o acoperă în lumină directă, în timp ce unghiul exterior determină cât spațiu este parțial luminat. Diferența dintre aceste unghiuri va deveni clară odată ce veți vedea scena rezultată. Apoi, spuneți în mod explicit lumina să arunce umbre și, de asemenea, adăugați la fel SCNLookAtConstraint
pe care l-ați creat mai devreme pentru camera dvs. foto.
Construiți și rulați aplicația pentru a vedea scena rezultată. Unghiul interior specificat în codul dvs. este afișat în cazul în care planul este un verde solid, direct sub cub. Unghiul exterior este arătat de gradientul de lumină care se estompează la negru pe măsură ce se îndepărtează de ținta luminii.
Veți vedea că acum ați luat cubul dvs. aruncând o umbră corect. Lumina spotului, totuși, luminează doar o parte a avionului. Acest lucru se datorează faptului că nu există lumină ambientală în scenă.
O lumină ambientală este o sursă de lumină care luminează totul cu o distribuție egală a luminii. Deoarece o lumină ambientală luminează întreaga scenă, poziția sa nu contează și o puteți adăuga la orice nod pe care îl doriți, chiar la același nod ca și camera dvs. foto. Utilizați următorul fragment de cod pentru a crea o lumină ambientală pentru scenă.
override functie viewDidLoad () ... permite camera = SCNCamera () lasa cameraNode = SCNNode () cameraNode.camera = CameraName.position = SCNVector3 (x: -3.0, y: 3.0, z: 3.0) .type = SCNLightTypeAmbient ambientLight.color = UICcolor (roșu: 0,2, verde: 0,2, albastru: 0,2, alfa: 1,0) cameraNode.light = ambientLight ...
Fragmentul de cod creează un SCNLight
, la fel cum ați făcut înainte. Diferența principală este cea a luminii tip
proprietate, care este setat la SCNLightTypeAmbient
. De asemenea, setați culoarea la un gri închis, astfel încât să nu depășească scena. Culoarea implicită pentru o lumină este albă pură (valoarea RGB de 1, 1, 1) și având această culoare pe o lumină ambientală determină ca întreaga scenă să fie complet iluminată așa cum se arată în imaginea de mai jos.
Construiți și rulați aplicația ultima oară pentru a vedea rezultatul final.
Dacă ați reușit până la sfârșitul acestui tutorial, acum ar trebui să vă simțiți confortabil cu următoarele subiecte:
SCNView
cu un SCNScene
În următorul tutorial al acestei serii, veți afla despre câteva concepte mai avansate ale cadrului SceneKit, inclusiv animația, interacțiunea cu utilizatorul, sistemele de particule și simularea fizicii.