OpenGL v C++ Builderu (3.díl) - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Soutěž

Sponzorem soutěže je:

IDIF

 

Kde se koná výstava fotografií Luďka Vojtěchovského?

V dnešní soutěži hrajeme o:



C/C++

OpenGL v C++ Builderu (3.díl)

open gl

3. září 2001, 00.00 | V dnešním díle seriálu o OpenGL, se naučíme používat světel a povíme si také něco o knihovně GLU.

Vítejte opět v dalším pokračování seriálu o OpenGL. Pomalu nám končí prázdniny a mi všichni se vracíme zpět do práce nebo do školy, zkrátka je čas zasednout k C++ Builderu a dělat programy v OpenGL. Tentokráte se budeme zabývat světly a krátce se seznámíme s knihovnou glu.

Světlo

Již umíme narýsovat libovolné těleso pomocí okrajových bodů (neboli vertexů), umíme i takové těleso obarvit libovolnou barvou a teď si k tomu přidáme osvětlení libovolné barvy a libovolné intenzity. Začneme jak jinak než velmi jednoduše. Uděláme desku, nad ní zavěsíme kouli a budeme jí pohybovat nahoru a dolu, celou scénu osvětlíme, též pohyblivým světlem viz obrázek.

Takže pěkně popořádku. Na rotaci si připravíme čítače:

GLfloat	xrot; // rotace kolem X
GLfloat	yrot; // rotace kolem Y
GLfloat xspeed; // rychlost rotace X
GLfloat yspeed; // rychlost rotace Y

Dále definujeme objekt tzv. Quadratics: GLUquadricObj *quadratic; Používáme jej při rýsování složitějších geometrických útvarů, jako například koule, kterou chceme vytvořit. Na co jej budeme potřebovat se dozvíte dále. Teď již přichází čas na definici světla, kterou provedeme pomocí tří polí:

GLfloat LightAmbient[]= { 0.1f, 0.8f, 0.1f, 1.0f };
GLfloat LightDiffuse[]= { 0.2f, 1.0f, 0.1f, 0.5f }; GLfloat LightPosition[]= {-1.5f, -1.0f, -5.0f, 1.0f };

Vlastnosti světla definujeme za pomocí polí, výstižně nazvaných LightAmbiet, LightDiffuse a LightPossition, jejíž význam si ihned vysvětlíme.
Používáme dva druhy světla. LightAmbiet znamená okolní světlo. Toto světlo určíme pomocí čtyř parametrů R,G,B, určuje barvu světla a ALFA (intenzitu). Druhým druhem světla je světelný zdroj LightDiffuse. Toto světlo definujeme stejným způsobem (RGBA). A do třetice musíme světlo umístit do prostoru, o to se postará pole LightPosition. První tři parametry umístí světlo do prostoru podle souřadnic x, y, z a čtvrtý parametr ovlivňuje mohutnost světla (rozptyl). Využití posledního parametru ukazují následující obrázky:

Aby světlo bylo vidět na scéně, je potřeba nejprve aktivovat používaní světel, a definovat nové světlo GL_LIGHT1.

// světlo GL_LIGHT1 bude sestaven z okolního světla
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
// GL_LIGHT1 bude mít světelný zdroj
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
// nastavení pozice v prostoru pro GL_LIGHT1
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
// aktivujeme světlo GL_LIGHT1 do scény
glEnable(GL_LIGHT1);
// aktivujeme používání světel glEnable(GL_LIGHTING);

Zajímavé je podívat se na to, jaký vliv mají na světlo jednotlivé definice (vlastnosti světla), použití Ambiet a Diffuse. Na následujícím obrázku vidíte nejprve použití okolního světla a světelného zdroje zároveň, na druhém obrázku je použit pouze světelný zdroj a na třetím obrázku vidíme pouze světlo okolí.

V programu jsme rozpohybovali světlo tak, aby se s koulí pohybovalo nahoru a dolu. Při každém průchodu funkcí DrawScene, přepočítáme vhodně souřadnice světla x a y podle následujícího kódu:

LightPosition[1] += 5*prirustek;
LightPosition[0] += 5*prirustek; 
citac += prirustek;
if (citac > 1 || citac < -1)
  prirustek *= -1;                                  
// změna pohybu, když jsme nahoře pojedeme dolů a naopak

Nebudu vás již déle napínat, vyzkoušejte si zdrojový kód v akci. Program bez rotací máte k dispozici zde.

OpenGL Utility Library - předdefinované objekty

Pokud jste pozorně pročetli kód u přiloženého programu, narazili jste jistě na část kódu, kterou jsem nevysvětlil. Ihned to napravím, a proto .... nepřestávejte číst :))).

Již jsme si říkali, jakým způsobem narýsujeme libovolný geometrický tvar. A když zavzpomínáte, kolik kódu jsme museli napsat, aby jsme stvořili obyčejnou krychli: 6stěn poskládaných ze čtverců. Jak tedy naprogramovat kouli, abychom se u toho nezbláznili a ušetřili množství řádků. Knihovna OpanGL nám nenabízí přímou možnost, jak vložit do scény složitější objekt, jako například kouli, válec, jehlan atd. , ale nic není ztaceno, obrátíme se tedy s výhodou na OpenGL Utility Library (GLU). Tuto knihovnu považujeme za nadstavbu OpenGL.

V GLU najdeme k narýsování několik předdefinovaných objektů: gluCylinder,gluDisk, gluPartialDisk, gluSphere. A tím přeskočíme k dalšímu prográmku, který jsem si pro vás dnes připravil. Vylepšíme předcházející program tak, že rotující kouli bude možné nahradit, válcem, jehlanem, diskem. Toho docílíme stiskem kláves 1,2,3,4,5 a 6. O narýsování jednotlivých těles se postará následující kód:

switch(object)
{
case 0:
  // vlastní funkce pro narýsování krychle
  glDrawCube();       
  break;
case 1:
  glTranslatef(0.0f,0.0f,-1.5f);  
// válec s radiusem 0.5 s výškou 2 gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32); break; case 2: glRotatef(90, 0.1f,0.0f,0.0f); // Disk (CD) radius vnitřní = 0.5, radius vnější = 2 gluDisk(quadratic,0.5f,1.5f,32,32); break; case 3: // Koule radius = 1 , segmenty= 16 a 16 gluSphere(quadratic,1.3f,32,32); break; case 4: glTranslatef(0.0f,0.0f,-1.5f);
// jehlan, spodní radius = 5 , výška = 2 gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32); break; };

Provkládání složitějších objektíků do scény je vhodné použít objekt Quadratics, který jsme si popsali na začátku článku. Do něj budeme vkládat jednotlivé geometrické tělesa. Na objekt Quadratics se odkazujeme pointerem quadratic. Popišme si parametry jednotlivých těles:

void gluCylinder( GLUquadricObj *qobj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks );
Těleso Cylinder je popsáno radiusem při základně, radiusem na vršku tělesa (u jehlanu je vrchní rádius nulový a u válce jsou oba stejné), height udává výšku tělesa, slices a stack naopak stanovují "počet subčástí kolem osy z", protože Cylinder je orientován podél osy z. No a lidsky řečeno slices a stack určí bohatost drátěného modelu, nebo abych to přesně vyjádřil počet částí (drátů) v ose. Nejlepší je si to vyzkoušet na vlastní kůži.

Pomocí funkce gluClinder zvládneme velké množství geometrických objektů. Podívejte se na několik typů:

gluCylinder(quadratic,1.0f,1.0f,3.0f,4,1); // kvádr
gluCylinder(quadratic,1.0f,1.0f,3.0f,20,1); // válec
gluCylinder(quadratic,1.0f,1.0f,3.0f,20,20); // válec s větším počtem drátů na výšku
gluCylinder(quadratic,1.5f,0.0f,3.0f,20,1); // jehlan

Analogicky použijeme i další objekty:

void gluSphere( GLUquadricObj *qobj, GLdouble radius, GLint slices, GLint stacks );

Koule, je definována poloměrem (radius) a počtem částí v osách.

void gluDisk( GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops );

Disk je popsán vnitřním a vnějším radiusem, počtem částí (drátů), loops udává také počet částí (počítáno od středu).

Jak již jsem říkal nejlépe pochopíte význam parametrů, které udávají počet častí (drátů), když vše vyzkoušíte sami, ale před tím musíte styl objektu Quadratics nastavit na:

gluQuadricDrawStyle(quadratic, GLU_LINE);

Tímto řádkem docílíte, že se tělesa budou vykreslovat jen jako drátěné modely, možné hodnoty GLU_FILL, GLU_LINE,GLU_SILHOUETTE a GLU_POINT.

Na závěr musíme ještě obsloužit klávesnici, aby jsme mohli měnit zobrazované objekty na scéně. K tomu nám slouží pole keys[256].

Výsledek se nachází zde.

No a to je pro tentokrát až nad hlavu. Příště se můžete těšit na další díl o mapování textůr a blendingu.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: