Java → Processing → Processing 3D → Uvod u 3D Processing – Kamera i kreiranje sopstvenih 3D objekata


Uvod u 3D Processing – Kamera i kreiranje sopstvenih 3D objekata

Lekcija 2 od 4

U prethodnoj lekciji upoznali smo osnovne mogućnosti 3D grafike u Processing-u. Naučili smo kako da uključimo P3D renderer, crtamo osnovne trodimenzionalne objekte i primenjujemo transformacije poput pomeranja i rotacije.

U ovoj lekciji napravićemo korak dalje. Naučićemo kako da postavimo kameru u 3D prostoru, kako da menjamo njen položaj i kako da kreiramo prve sopstvene 3D objekte korišćenjem temena (vertex()) i funkcije beginShape().

U ovoj lekciji naučićete:
  • kako radi funkcija camera(),
  • kako se podešava pogled na 3D scenu,
  • osnove funkcije perspective(),
  • kako funkcioniše osvetljenje scene,
  • kako se kreiraju sopstveni 3D objekti pomoću funkcija beginShape() i vertex().

Kamera u 3D prostoru – funkcija camera()

Do sada smo scenu posmatrali iz podrazumevanog položaja kamere. Processing omogućava da sami odredimo položaj kamere pomoću funkcije camera(). Na taj način možemo da posmatramo scenu iz različitih uglova, približavamo se objektima ili se udaljavamo od njih.

Šta ćemo naučiti u ovom primeru?
  • kako se postavlja kamera u 3D prostoru,
  • kako se menja njen položaj,
  • kako različiti položaji kamere utiču na prikaz scene.

Primer – pomeranje kamere

U sledećem programu kamera se može pomerati pomoću tastature. Na taj način posmatramo istu kocku iz različitih uglova.


// Koordinate kamere
float kameraX = -10;
float kameraY = -10;
float kameraZ = 150;

// Stranica kocke
float stranica = 50;

// Ugao rotacije
float ugao = 0;

// Da li je uključena rotacija?
boolean rotacija = false;

void setup(){

    // Uključivanje 3D renderera.
    size(500,500,P3D);

}

void draw(){

    // Crna pozadina.
    background(0);

    // Pomeranje koordinatnog sistema u centar prozora.
    translate(width/2,height/2);

    // Uključivanje podrazumevanog osvetljenja.
    lights();

    // Postavljanje kamere.
    camera(
        kameraX, kameraY, kameraZ,
        0, 0, 0,
        0, -1, 0
    );

    // Boja kocke.
    fill(100,255,200);

    // Rotacija kocke.
    if(rotacija){

        rotateY(ugao);

        ugao += 0.05;

    }

    // Crtanje kocke.
    box(stranica);

}

void keyPressed(){

    // Udaljavanje kamere.
    if(keyCode==UP){
        kameraZ += 10;
    }

    // Približavanje kamere.
    if(keyCode==DOWN){
        kameraZ -= 10;
    }

    // Pomeranje ulevo.
    if(keyCode==LEFT){
        kameraX += 10;
    }

    // Pomeranje udesno.
    if(keyCode==RIGHT){
        kameraX -= 10;
    }

    // Pomeranje nagore.
    if(key=='q'){
        kameraY += 10;
    }

    // Pomeranje nadole.
    if(key=='w'){
        kameraY -= 10;
    }

    // Uključivanje ili isključivanje rotacije.
    if(key=='r'){
        rotacija = !rotacija;
    }

}

U ovom primeru menjamo samo prve tri vrednosti funkcije camera(). One predstavljaju položaj kamere u prostoru. Kocka ostaje na istom mestu, ali se menja ugao iz kog je posmatramo.

Važno!

Pritiskom na tastere ne pomera se kocka, već kamera. Objekat ostaje na istom mestu, dok se menja položaj posmatrača.

Eksperiment
  • Udaljite kameru od objekta.
  • Približite kameru tako da kocka ispuni skoro ceo ekran.
  • Menjajte samo koordinatu kameraY i posmatrajte scenu odozgo i odozdo.
  • Pritiskom na taster R uključite i isključite rotaciju.

Perspektiva u 3D prostoru – funkcija perspective()

Kada posmatramo objekte u stvarnom svetu, oni koji su bliži izgledaju veći, dok udaljeni objekti izgledaju manji. Ovakav način prikaza naziva se perspektiva.

Processing podrazumevano koristi perspektivni prikaz, ali ga možemo prilagoditi pomoću funkcije perspective(). Njome određujemo vidno polje kamere i opseg rastojanja u kojem će objekti biti vidljivi.

Najčešći oblik funkcije:

perspective(fov, aspect, near, far);
  • fov – ugao vidnog polja (Field of View)
  • aspect – odnos širine i visine prozora
  • near – najmanje rastojanje koje kamera vidi
  • far – najveće rastojanje koje kamera vidi

Primer


// Podešavanje perspektive.
perspective(
    PI/3,
    (float)width/height,
    1,
    1000
);

U većini jednostavnijih programa nije potrebno ručno pozivati ovu funkciju, jer Processing automatski podešava odgovarajuću perspektivu. Međutim, kod složenijih 3D scena njeno pravilno podešavanje može značajno uticati na izgled prikaza.

Eksperiment
  • Povećajte ugao fov i posmatrajte kako se menja prikaz.
  • Smanjite vrednost parametra far i pogledajte koji objekti nestaju.

Osvetljenje scene

Za razliku od 2D grafike, u trodimenzionalnim scenama osvetljenje ima veoma važnu ulogu. Bez izvora svetlosti objekti mogu izgledati ravno ili se uopšte neće pravilno prikazati.

Processing nudi više različitih tipova osvetljenja. Najčešće korišćene funkcije su:

  • lights()
  • pointLight()
  • directionalLight()

Podrazumevano osvetljenje – lights()

Najjednostavniji način osvetljavanja scene jeste poziv funkcije lights(). Ona uključuje podrazumevano osvetljenje i u većini jednostavnih primera sasvim je dovoljna.


void draw(){

    background(220);

    lights();

    translate(width/2,height/2);

    box(120);

}
Napomena

Ako izostavite funkciju lights(), 3D objekti mogu izgledati ravno i izgubiće utisak dubine.

Tačkasti izvor svetlosti – pointLight()

Funkcija pointLight() predstavlja izvor svetlosti koji se nalazi u jednoj tački prostora. Svetlost se odatle širi u svim pravcima, slično sijalici.


// Bela svetlost postavljena u prostoru.
pointLight(
    255,255,255,
    -150,-100,200
);

Prva tri parametra predstavljaju RGB boju svetlosti, dok druga tri predstavljaju položaj izvora svetlosti u 3D prostoru.


Usmereno svetlo – directionalLight()

Za razliku od tačkastog izvora, funkcija directionalLight() predstavlja svetlost koja dolazi iz određenog pravca, kao što Sunce osvetljava Zemlju.


// Belo usmereno svetlo.
directionalLight(
    255,255,255,
    -1,1,-1
);

Ovde poslednja tri parametra ne predstavljaju položaj izvora svetlosti, već njen smer prostiranja.

Važno!

Kod funkcije pointLight() određujemo položaj izvora svetlosti, dok kod funkcije directionalLight() određujemo samo smer iz kojeg svetlost dolazi.

Tačkasti izvor svetlosti

pointLight()

Svetlost se širi iz jedne tačke u svim pravcima.

Usmereno svetlo

directionalLight()

Svetlost dolazi iz jednog smera.

Poređenje različitih tipova osvetljenja

Poređenje

Različiti tipovi osvetljenja daju potpuno drugačiji izgled objektima.


Sada kada znamo kako funkcionišu kamera, perspektiva i osvetljenje, spremni smo da napravimo prvi sopstveni 3D objekat. U sledećem primeru videćemo kako se pomoću funkcija beginShape(), vertex() i endShape() može konstruisati piramida od pojedinačnih temena.


Kreiranje sopstvenih 3D objekata

Do sada smo koristili gotove 3D objekte kao što su box(), sphere() i cylinder() (ako ga sami implementiramo). Međutim, Processing omogućava da kreiramo potpuno nove oblike definisanjem njihovih temena.

Za to se koriste funkcije beginShape(), vertex() i endShape(). Između naredbi beginShape() i endShape() navodimo temena objekta pomoću funkcije vertex(x, y, z). Processing zatim od tih temena formira linije ili površine.

Najvažnije funkcije
  • beginShape() – početak definisanja objekta.
  • vertex(x,y,z) – dodavanje jednog temena.
  • endShape() – završetak definisanja objekta.
  • endShape(CLOSE) – zatvara poslednju ivicu objekta.

Primer – piramida sa rotacijom

U sledećem primeru kreiramo jednostavnu četvorostranu piramidu. Njena osnova nalazi se u XOY ravni, dok je vrh pomeren u pozitivnom smeru Z ose. Nakon toga piramida se rotira kako bismo mogli da je posmatramo iz svih uglova.


// Ugao rotacije piramide.
float ugao = 0;

void setup(){

    // Uključivanje 3D renderera.
    size(700,600,P3D);

}

void draw(){

    // Pozadina.
    background(220);

    // Uključivanje osvetljenja.
    lights();

    // Koordinatni sistem pomeramo u centar prozora.
    translate(width/2,height/2);

    // Rotacija tako da piramida stoji uspravno.
    rotateX(PI/2);

    // Rotacija oko svoje ose.
    rotateZ(PI/6 + ugao);

    // Boja površine.
    fill(240);

    // Boja ivica.
    stroke(80);

    // Početak definisanja objekta.
    beginShape(TRIANGLE_STRIP);

    // Prva stranica.
    vertex(-100,-100,-100);
    vertex( 100,-100,-100);
    vertex(   0,   0, 100);

    // Druga stranica.
    vertex( 100,-100,-100);
    vertex( 100, 100,-100);
    vertex(   0,   0, 100);

    // Treća stranica.
    vertex(100,100,-100);
    vertex(-100,100,-100);
    vertex(0,0,100);

    // Četvrta stranica.
    vertex(-100,100,-100);
    vertex(-100,-100,-100);
    vertex(0,0,100);

    // Zatvaranje objekta.
    endShape(CLOSE);

    // Promena ugla rotacije.
    ugao += 0.02;

}

Svaki poziv funkcije vertex() definiše jedno teme objekta. Processing povezuje susedna temena i formira trouglaste stranice piramide.

Važno!

Redosled kojim navodite temena veoma je važan. Ako promenite njihov raspored, stranice mogu biti izvrnute ili se mogu presecati, pa objekat neće izgledati kako očekujete.

Interaktivna animacija – rotirajuća piramida

Ova animacija prikazuje piramidu koja se rotira oko svoje ose. Možeš je koristiti da vizuelno razumeš vertex() i 3D transformacije.


Probaj:
  • Promeni brzinu rotacije u Pyramid.js
  • Promeni boju piramide
  • Dodaj osvetljenje (lights)

Piramida kreirana pomoću vertex funkcije

Kreiranje piramide

Piramida je napravljena definisanjem temena pomoću funkcije vertex().

Temena i ivice piramide

Temena i ivice

Objekat nastaje povezivanjem temena u odgovarajućem redosledu.

Rotirajuća piramida

Rotacija piramide

Animacija omogućava da objekat posmatramo iz različitih uglova.


Eksperiment
  • Promenite visinu vrha piramide.
  • Povećajte ili smanjite dimenzije osnove.
  • Promenite brzinu rotacije.
  • Dodajte ose koordinatnog sistema pomoću funkcije line().
  • Pokušajte da napravite petostranu ili šestostranu piramidu.

Šta smo naučili?

  • Kako se postavlja kamera pomoću funkcije camera().
  • Kako se podešava perspektiva pomoću funkcije perspective().
  • Razliku između funkcija lights(), pointLight() i directionalLight().
  • Kako se kreiraju sopstveni 3D objekti pomoću funkcija beginShape(), vertex() i endShape().

Sledeća lekcija

U narednoj lekciji primenićemo sve naučene tehnike na praktičnom projektu – napravićemo jednostavnu simulaciju Sunčevog sistema u kojoj će se planete okretati oko Sunca, a mesec oko svoje planete. Tako ćemo upoznati hijerarhijske transformacije, koje predstavljaju jedan od najvažnijih koncepata 3D grafike.