IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

9. diel - XNA tvorba v 3D - Kamera

Vitajte desiatykrát. Dnes sa opäť vydáme do priestoru s tromi rozmermi. Zatiaľ sme si vytvorili len komponenty vykresľovanie cez SpriteBatch, preto aby bolo možné ono jedno D pridať bude potrebné trochu viac než len to. Budeme potrebovať kameru, kde si uložíme naše známe matice (konkrétne View a Projection) a ďalšie potrebné veci. Je to veľa práce tak sa do toho pustíme, nech to máme hotovo.

Kamera

Ako som už naznačil v úvode, budeme v kamere ukladať nám známe dve matice a tiež polohu kamery. Nami vytvorená základná kamera bude pomerne hlúpa. Dokonca bude abstraktné, takže z nej nepôjde vytvoriť inštancie. Zároveň ale bude obsahovať všetko spoločné pre ďalšie kamery, ktoré už budú použiteľné. V pôvodnom enginu od Seana sú kamery komponenty a zároveň sú uložené v nejakom service kontainery. Zdá sa mi to veľmi zložité a preto sa opäť vydávam cestou jednoduchosti. Kameru si uložíme do premennej v hernom okne. Ale to až za chvíľu, najprv si ju musíme vytvoriť. Pridáme si teda novú zložku kamery, alebo si ju napokon pomenujte ako uznáte za vhodné. Do nej pridáme súbor s triedou Kamera. Upravíme rovnako ako tradične menný priestor a tiež urobíme triedu verejnú a abstraktné. Pre kolegu sokola radšej rekapituláciu:

public abstract class Kamera{

}

Potrebovať budeme určite obe matice View a Projection, tak si ich do triedy pripravíme:

private Matrix fView;
private Matrix fProjection;

public Matrix View{
  get{
    return fView;
  }
  set{
    fView = value;
  }
}

public Matrix Projection{
  get{
    return fProjection;
  }
  set{
    fProjection = value;
  }
}

Spoločná pre všetky budúce kamery bude tiež ich pozície v priestore. Vytvorme si teda na to tiež premennú:

private Vector3 fPozice;
public Vector3 Pozice{
  get{
    return fPozice;
  }
  set{
    fPozice = value;
  }
}

Ďalej sa bude hodiť určenie toho ako ďaleko kamera vidí, teda definícia far plain. Ak si spomínate na obrázok kamery, tak je to práve zadná plocha, všetko čo sa nachádza za ňou nebude vykreslené. Near plain si zakladať nebudeme, pretože bude vždy 1. Nech vás nikoho nenapadne dávať tam inú hodnotu.

private float fFarPlane;

public float FarPlane{
  get {
    return fFarPlane;
  }
  set{
    fFarPlane = value;
  }
}

Vytvoríme si tiež konštruktor a v ňom nastavíme far plane na 1000. Táto hodnota ale záleží na konkrétnom použití. Nie je ale dobré voliť ju príliš veľkú. Ako parameter odovzdáme herné okno, ku ktorému kamera patrí, a uložíme si ho:

protected GameScreen Parent;

public Kamera(GameScreen okno){
  Parent = okno;
  FarPlane = 1000f;
}

Potreba bude tiež virtuálny metóda Update, cez ktorú budeme meniť pozíciu kamery a v nej prepočítavať matica pre vykresľovanie:

public virtual void Update(){

}

Jednu maticu nie je potrebné počítať stále dookola, pretože sa nemení. Matica View to nie je, pohľad sa mení, ale matica Projection je stále rovnaká. Môžeme si ju vytvoriť v konstruktoru:

Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, Parent.Engine.GraphicsDevice.Viewport.AspectRatio, 1f, FarPlane);

Metóda je stále rovnaká ako sme ju používali predtým, takže ju prejdeme bez komentára. Ešte by bolo vhodné maticu znova vygenerovať keď zmeníme FarPlane, pridáme teda rovnaký riadok aj do setter tejto premennej:

set{
  fFarPlane = value;
  Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, Parent.Engine.GraphicsDevice.Viewport.AspectRatio, 1f, fFarPlane);
}

Z tejto triedy je to všetko, viac všeobecného a spoločného pre všetky kamery asi nenájdeme, ak áno, tak si to sem pridáme. Premiestnime náš záujem do triedy GameScreen, kde si pridáme premennú na kameru:

public Kamera Kamera{
  get;
  set;
}

A do miestnej metódy Update zavoláme Update u kamery, ak ju máme nastavenú:

if (Kamera != null) Kamera.Update();

Hotovo :-) Kamery rovnako ako komponenty pridáme v metóde Load a máme postarané. Dobré je ešte zriadiť si u komponenty špeciálnu metódu Draw, kde budeme v parametroch rovno odovzdávať naše dve matice a pozíciu kamery. Presunieme sa teda do triedy s komponentom a túto metódu pridáme:

public virtual void Draw(Matrix View, Matrix Projection, Vector3 CameraPosition){

}

a v druhej metóde ju zavoláme:

public virtual void Draw(){
  if (Parent.Kamera != null){
    Draw(Parent.Kamera.View, Parent.Kamera.Projection, Parent.Kamera.Pozice);
  }
}

Výborne. Teraz je všetko potrebné hotovo. Máme kameru, sme na tretí rozmer dobre vybavení a alebo nie? Naozaj nie. Kameru máme, ale je nepoužiteľná bude potrebné si urobiť jej kamarátku, ktorú už použiť možno. Aj keď to nebude žiadne terno, ale pre začiatok to stačí. Kamier bolo vymyslené veľa. Za všetkými sa ale skrýva väčšie prípadne menšie vektorová matematika. Najľahšie je kamera, ktorú sme už používali pri vykresľovaní v prvých dieloch seriálu, anglicky ju nájdete pod názvom target camera. Názov vypovedá za všetko. Kamera má svoj cieľ, na ktorý zo svojej pozície hľadí. Free camera alebo tiež FPS kamera sa hýbe tým smerom, kam sa pozerá. Ďalšia je chase camera, teda kamera ktorá má priradený nejaký objekt za ktorým v určenej vzdialenosti lieta. Toto už je matematicky zložitejšia aj na pochopenie toho ako to vlastne funguje. Občas sa hodí aj moja obľúbená arc ball camera. To je kamera, ktorá sa pohybuje v určitej vzdialenosti okolo daného bodu. Hýbe sa teda po pomyselnej guľu. Ako sa tohto docielilo sa ma nepýtajte. Neviem to, hlavne že mi to funguje. Ako taká kamera vyzerá v akcii môžete vidieť na nasledujúcom videu:

Target pevná kamera

Zatiaľ nám bude stačiť pre naše skromné účely statická target camera. Budeme jej potrebné hovoriť pevná kamera. Názov triedy ponechám anglicky, je to vhodné pre prípadné hľadanie zdrojov a informácií. Do zložky na kamery si teda pridáme súbor sa triedou TargetKamera. Ako obvykle urobíme verejnú, upravíme menný priestor a zariadime že bude dediť z triedy Kamera:

public class TargetKamera: Kamera

Potreba bude onen cieľ, kam sa kamera pozerá, takže si ho vytvorme:

private Vector3 fTarget;

public Vector3 Target{
  get{
    return fTarget;
  }

  set{
    fTarget = value;
  }
}

Pridáme konštruktor:

public TargetKamera(GameScreen okno, Vector3 pozice, Vector3 target):base(okno){
  Pozice = pozice;
  Target = target;
}

Teraz zostáva už len prepísať metódu Update, kde budeme generovať maticu View a to nasledovne. Pre vytvorenie matice View použijeme rovnakú metódu ako sme používali predtým:

public override void Update(){
  this.View = Matrix.CreateLookAt(Pozice, Target, Vector3.Up);
}

A je hotovo. V budúcom dieli si preložíme model do komponentov a skrze engine si ho vykreslíme. Čo si ostatne môžete skúsiť urobiť aj sami. Opäť čakám na Vaše komentáre dole pod článkom.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 223x (1.67 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
XNA tvorba v 3D - Sprit a Text
Všetky články v sekcii
Základy 3D grafiky a tvorba enginu
Preskočiť článok
(neodporúčame)
XNA tvorba v 3D - Model druhýkrát
Článok pre vás napísal vodacek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Vodáček dělá že umí C#, naplno se již pět let angažuje v projektu ŽvB. Nyní studuje na FEI Upa informatiku, ikdyž si připadá spíš na ekonomice. Není mu také cizí PHP a SQL. Naopak cizí mu je Java a Python.
Aktivity