[ < ]

[ > ]

 

[ << ]

[ Up ]

[ >> ]

 

 

 

 

[Top]

[Contents]

[Index]

[ ? ]

4.3.1.3 Egy “világ” létrehozása

Most már van egy rendkívűl érdekfeszítő alkalmazásunk ami megnyit egy fekete ablakot és az ESC bilentyűre vár a kilépéshez. Feltételezhetjük, hogy ez az az alkalmazás, maire mindig is vágytál? Nem? Oké, akkor készítsünk némi 3D dolgot!

Adjunk hozzá egy textúra kezelőt, egy szobát (technikailag szektornak nevezzük), és némi fényt. Elsőként adj egy pointert a fő szektorunkra és egy CreateRoom() függvényt a 'Simple' osztály fejállományában:

 

...
struct iSector;
...
class Simple
{
private:
  ...
  iSector* room;
  float rotX, rotY;
  ...
  void CreateRoom ();
  ...

Most add hozzá ezt a kódrészletet (textúra kezelő, szoba, fények) a 'simple.cpp'-hez:

 

bool Simple::Application ()
{
  ...
  // First disable the lighting cache. Our app is simple enough
  // not to need this.
  engine->SetLightingCacheMode (0);
  ...
  // These are used store the current orientation of the camera.
  rotY = rotX = 0;
  ...
  CreateRoom ()
  ...
}
...
void Simple::CreateRoom ()
{
  // Load the texture from the standard library.  This is located in
  // CS/data/standard.zip and mounted as /lib/std using the Virtual
  // File System (VFS) plugin.
  if (!loader->LoadTexture ("stone", "/lib/std/stone4.gif"))
    ReportError("Error loading 'stone4' texture!");

  iMaterialWrapper* tm =
    engine->GetMaterialList ()->FindByName ("stone");

  room = engine->CreateSector ("room");
  csRef<iMeshWrapper> walls (
    engine->CreateSectorWallsMesh (room, "walls"));
  csRef<iThingState> thing_state (
    SCF_QUERY_INTERFACE (walls->GetMeshObject (), iThingState));
  iThingFactoryState* walls_state = thing_state->GetFactory ();
  walls_state->AddInsideBox (
    csVector3 (-5, 0, -5), csVector3 (5, 20, 5));
  walls_state->SetPolygonMaterial (CS_POLYRANGE_LAST, tm);
  walls_state->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3);

  csRef<iLight> light;
  iLightList* ll = room->GetLights ();

  light = engine->CreateLight (0, csVector3 (-3, 5, 0), 10,
        csColor (1, 0, 0));
  ll->Add (light);

  light = engine->CreateLight (0, csVector3 (3, 5,  0), 10,
        csColor (0, 0, 1));
  ll->Add (light);

  light = engine->CreateLight (0, csVector3 (0, 5, -3), 10,
        csColor (0, 1, 0));
  ll->Add (light);

  engine->Prepare ();
}

A további kód elsőként betölt egy textúrát a LoadTexture() függvénnyel. Az első paraméter a textúta engine által ismert neve, a második a VFS rendszerbeli fájlneve. Virtual File System (VFS)). Megjegyezzük, hogy ha nincs meg neked a 'stone4.gif' textúra, mást is használhatsz helyette. Az egyetlen feltétel, hogy a méretének a kettő hatványaival kell megegyeznie (pl. 64*64). A Crysal Space automatikusan átméretezi, ha nem felel meg ennek a feltételnek, de ez rontja a minőséget. A fügvény egy 'iTextureWrapper' tipussal tér vissza, amit most nem használunk. Ehelyett az 'iMaterialTexture' -t fogjuk használni, mai automatikusan létrejön a LoadTexture() meghívásával.

Ezután a CreateSector() meghívásával létrehzzunik a szobánkat. Ez a szoba kezdetben üres lesz. A szobát a Crystal Space-ben az 'iSector' reprezentálja, ami alapjában véve egy olyan tároló, ami geometriai objektumokat képes eltárolni. Az objektumok a Crystal Space-ben mesh objektumokként vannak jelen, (lásd a Mesh Object Plug-In System című részt) . Különféle mesh tipusok létenek a Crystal Space-ben. Minden más objektum tipus más módon jelenítimeg a geometriát. Ebben a tutoriálban csak a 'thing' (dolog) mesh objektum tipust fojuk használni. Ez a mesh objektum tipus nagyon jól hazánlható épületek belső falainak megjelenítésére.

Most meg fogjuk alkotni a sozbánk hat falát. Elsőként létrehozzuk a thing mesh objektumunkat. Mivel ez egy nagyon szokványos eset, létezik egy ezt elkészítő tagfüggvény az engine-en ( CreateSectorWallsMesh() ) ami létrehoz egy thingmesh objektumot és egy adott szektorba teszi. Az egyetlen dolog, amit ezután meg kell tenni az, hogy poligonokat adjunkhozzá a meshez. Ennek véghezvitelére először lekérjük az 'iThingState' interfészt a thing mesh objektumról. Az SCF_QUERY_INTERFACE() makrót használjuk, ami az SCF része (lásd Shared Class Facility (SCF)). Ez látni fogja, hogy a mesh objektum (amit a mesh burkoló burkol be), jelen pillanatban az 'iThingState' -et implementálja (erről az esetről van most szó), és visszatér egy 'iThingState” tipusú pointerrel. Minden mesh objektum megvalósít vaamilyen állapotinterfészt, amit amesh objektum felálítására használunk. Megjegyezzük, hogy minden mesh obektum, amit lekérsz az SCF_QUERY_INTERFACE() makró használatával, elérhető lesz egészen addig, amíg szükséged van rá ( a DecRef() ) Továbbá ebben a példában egy csRef<> -hez rendeljük, ami elintézi helyettünk a DecRef() meghívását. Hat rendezett poligon fog nekünk létrehozni, amik belülről láthatóak. (megjegyzzük, hogy a Crystal Space-ben akkor látható, ha a vertexek az óramutató járásával megegyezően orientálódnak).A visszatérés során kapott thing állapotból most már letudjuk kérni a gyár állapotát ('iThingFactoryState'), amit poligonok létrehozására használhatunk. Számos függvény létezik egyéni poligonok létrehozására, ha akarod, de ebben az esetbngy egyszerű függvényt használunk egy doboz létrehozására, ami csak belülről látható. Ez fogja nekünk a falakat szolgáltatni. Ezt az AddInsideBox() fogja megtenni. Az objektum térben adjuk meg az AddInsideBox() függvénynek a doboz koordinátáit ( nem a kamera térrel vagy a világ térrel).

A SetPolygonMaterial() függvény fogja beállítani a poligonok anyagát. Az első paraméter a távolság. A CS_POLYGON_LAST makrót használjuk annak a jelzésére, hogy minket az utolsóként létrehozott poligon anyaga érdekel (azok a polignok amiket az AddInsideBox() hozott létre).

A textúrát a SetPolygonTextureMapping()használatával húzzuk fel. Ebbe a tutoriálban a lehető leegyszerűbb, de működő megoldást fogjuk választani. Ebben az egyedi esetben tehát vesszük minden, a dobozt alkotó poligon első két vertexét és ezt használjuk a textúra u tengelyének. A v tengely az u tengely merőlegeseként lesz kiszámolva. A harmadik paraméter azt jelzi, hogy a textúrát úgy méretezzük, hogy egy textúra csempe 3*3 világ koordináta egység méretű lesz.

Végül létrehozuk némi fényt a szobánkban, hogy hogy láthassuk a falakat. Az 'iLight' interfész reprezentálja a fényt. Eben az esetben statikus fényeket haszánlunk, mivel neakrjuk semmozgatni, sem az intenzitását változtatni. Három ilyen fényt alkotunk és a szobához adjuk az AddLight() segítségével. Megjegyezzük, hogy a fények listáját az 'iLightList' interfészt egvalósító osztály tárolja egy adott szektoron blül. A listát a iSector::GetLights() meghívásával érhetjük el.

A fények létrehozásánál használunk néhány paramétert. Elsőször is nevet adunk aénynek. Ez nem túl gyakran használats ezért 0-ra állítjuk. A másdik paraméter a fény hele a világban. Ezuátn a sugár következik. A fény nem hat az olyan poligonokra, amik kívűl esek a középponttal és a sugárral meghatározott gömbön. A következőparaméter fény színe RGB formában, ahol az <1,1,1> jelenti az abszolút fehéret és a <0,0,0 > az abzzolút feketét. Az utolsó paraméterrel adjuk meg, hogy akarjuk-e, hogy a fényünk pszeudo-dinamikus lgyen-e. A pszeudodinaimkus fény nem mozoghat, de képes változtatni az intenzitását. Van némi teljesítménybeli ára a használatának, ezért nem alapértelemezett.

A Prepare() meghívásával előkészítjük az engine-t a jelenet renderelésére. Előkészít minden textúrát és létrehoz minden fénytérképet (lightmap) ami szükséges. Csak ezután tudod megkezdeni a világ renderelését, mivel a fénytérképek átkonvetálódnak a válaszott 3D renderernek megfelelőbb formára.

Oké, létrehoztuk a szobánkat és helyesen előkészítettük azt. Ha lefordítod és futtatod az alkalmazást, egy fekete képernyőt fogsz látni. Miért? Mert nem készítetünk kamerát, amivel ránézhetnénk a szobára.


[ < ]

[ > ]

 

[ << ]

[ Up ]

[ >> ]

This document was generated using texi2html 1.76.