OpenGL - Прости обекти

OpenGL предoставя финкции за изрисуване само на прости обекти - линии, триъгълници, полигони, които могат да бъдат свързани в някоя по-сложна фигура. Разбира се библиотеките GLAUX и GLUT правят лесно създаването на често използвани фигури като сфера, куб и различни многоъгълници. Библиотеката GLU дори представя функции, с които можете да създадете иначе доста сложни обекти - цилиндър, диск, криви, релеф. Аз ще започна от началото, а как се работи с фунцкиите от високо ниво на библиотеката GLU ще научите в друга тема.

За да създадете проста фигура трябва да дефинирате нейните точки ( т.е. нейните върхове ). За всеки един връх може да се определи цвят, полупрозрачност и нормала ( вектор, който се използва за определянето на динамичната светлина, която попада върху съответната повърхност ). Определянето на върховете на даден обект трябва да стои между функциите glBegin( GLenum Mode ) и glEnd( ). Те показват началото и края на дадено изрисуване. За всеки връх се използва текущия цвят, който може да се промени при повторно извикване на определена функция но с различни аргументи. Определянето на координатите на точка става с функцията :

glVertex{234}f[v]( x, y, z, (w) ) - както виждате тази функция може да приема от два до четири аргумента, а също и масив от стойности. Ако искате просто да определите някаква точка в 3D пространството извикайте :
glVertex3f( x, y, z ) - aргумента w e равен на 1 ( ако не определен ) и на него се делят x , y и z. Той не ви е особенно нужен, така че можете спокойно да минете и без него.

Определянето на цвят в RGBA режим става с функцията:

glColor{34}f[v]( R, G, B, (A) ) - цвета се изгражда в зависимост от наситеноста на червения, синия и зеления цвят, която се определя в проценти. Ако искате наполовина наситено червено трябва да извикате фунцкията със следните параметри :

glColor3f( 0.5 , 0.0 , 0.0 );

Четвъртият аргумент, който не е задължителен е прозрачността. Тя обаче трябва да се включи предварително с други функции. Ще прочетете за полупрозрачността в друга тема, а засега ако имате четвърти аргумент, определяйте му стойност 1.0 , която показва че няма полупрозрачност.

При Color-Index режим функцията за определяне на цвят е :

glIndex( index ) - като число от 0 - 255 определя различен цвят.

Можете да определите различен цвят за всеки връх и така вашата фигура ще прелива в зависимост от цвета на нейните върхове. С функцията glShadeModel( GLenum mode ) може да определите начина на определяне на цвета. Тя може да приеме една от константите:

GL_SMOOTH - за преливащ цвят, което е по-подразбиране.
GL_FLAT - за едноцветни фигури, независимо от цвета на върховете.

Преди да изрисувате някакъв обект трябва да подадете като аргумент на функцията glBegin( GLenum mode ) една от следните константи:

GL_POINTS - остават отделни точки.
GL_LINES - точките се свързват две по две в отделни линии. Ако броя на точките е нечетен, последната точка остава несвързана.
GL_LINE_STRIP - всяка точка се свързва със следващата.
GL_LINE_LOOP - всяка точка се свързва със следващата, като последната се свързва с първата.
GL_TRIANGLES - точките се свързват в отделни триъгълници. Ако останат една или две точки те не се свързват.
GL_TRIANGLE_STRIP - точките се свързват в серия от триъгълници. Първо се свързват точки 1, 2 и 3, след това 3, 2 и 4, следват 3, 4 и 5, след това 4,5 и 6 и т.н.
GL_TRIANGLE_FAN - точките се свързват в отново в серия от триъгълници, но начина на свързване е различен. Първо 1, 2 и 3 после 1, 3 и 4 след това 1, 4 и 5 и т.н.
Така се получава някакво подобие на диск защото всички триъгълници имат една допирна точка.
GL_QUADS - точките се свързват в отделни четириъгълници. Ако броя на точките не е кратен на 4, последните остават несвързани.
GL_QUAD_STRIP - точките се свързват в серия от четириъгълници, като първо се свързват точки 1, 2, 4 и 3 следват 3, 4, 6 и 5, след това 5, 6, 8 и 7 и т.н.
GL_POLYGON - точките се свързват в полигон, който трябва да е задължително изпъкнал, иначе са възможни аномалии.

Следната картинка би трябвало да ви доизясни нещата :


А това са функции от високо ниво, които създават наготово някои по-сложни обекти :

glRectf( x1, x2, y1, y2 ) - тази функция изгражда правоъгълник. Съответно ( x1, y1 ) сa координатите на горния ляв ъгъл, а ( x2, y2 ) на долния десен ъгъл.

Следващите функции са част от помощната библиотека GLUT :

glutSolidCube ( GLdouble width ) - изрисува куб, в зависимост от неговата страна.
glutSolidSphere( GLdouble radius, GLint slices, GLint stacks ) - приема радиуса на сферата, но и подразделенията съответно около оста z ( меридиани ) и по оста z ( паралели ) т.е. ако подадете за последните два аргумента числото 20, вашата сфера ще бъде по-ръбата от сфера с 50 подразделения около и по z координатата, но и по-лека за графичния ускорител.
glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks ) - изрисува конус, като приема радиуса на основата, височината и съответните подразделения за които вече стана дума.
glutSolidTorus( GLdouble innerRadius,GLdouble outerRadius,GLint nsides, GLint rings ) - изрисува торус, като приема външния и вътрешния радиус и съответните подразделения.
glutSolidTeapot( GLdouble size ) - изрисува чайник, като неговата големина е се генерира в зависимост от подадения аргумент.

Следващите функции не приемат аргумент. По подразбиране техния радиус е равен на корен квадратен от 3. Разбира се вие можете да промените размерите им с функцията glScale( ).

glutSolidDodecahedron( void ) - изрисува дванадесетостенник.
glutSolidIcosahedron( void ) - изрисува двадесетостенник.
glutSolidOctahedron( void ) - изрисува осмостенник.
glutSolidTetrahedron( void ) - изрисува четиристенник.

Ако искате да изрисувате някой от тези обекти, обаче изобразен само с линии по неговите краища, трябва да използвате същите функции, но вместо Solid е нужно да сложите Wire в името на функцията. Например:
glutWireCube( GLdouble width ).

В GLUAX се съдържат същите функции, само че вместо с glut започват с aux. Разликата се състои в това че повечето от тях приемат различен брой аргументи и безспорно някои от обектите създадени с GLUT могат да бъдат много по-детайлни от същите създадени с GLAUX. И макар че е по-удачно да използвате библиотеката GLUT, ще ви представя за всеки случай съответните функции в GLAUX:

auxSolidCube ( GLdouble width ) - изрисува куб, като приема за аргумент неговата страна.
auxSolidBox( GLdouble width, GLdouble height, GLdouble depth ) - изрисува "кутия", като приема за аргументи, нейната ширина, височина и дебелина.
auxSolidCone( GLdouble radius, GLdouble height ) - изрисува конус, като приема за аргументи неговия радиус и височина.
auxSolidCylinder( GLdouble radius, GLdouble height ) - изрисува цилиндър, като приема за аргументи неговия радиус и височина.
auxSolidSphere( GLdouble radius ) - изрисува сфера, като приема за аргумент нейния радиус.
auxSolidTorus( GLdouble innerRadius, GLdouble outerRadius ) - изрисува фигура, чиято форма най-точно наподобява "геврек" . Функцията приема съответно външния и вътрешния радиус.
auxSolidTeapot( GLdouble size ) - изрисува чайник, като неговата големина е се генерира в зависимост от подадения аргумент.
auxSolidDodecahedron( GLdouble radius ) - изрисува дванадесетостенник.
auxSolidIcosahedron( GLdouble radius ) - изрисува двадесетостенник.
auxSolidOctahedron( GLdouble radius ) - изрисува осмостенник.
auxSolidTetrahedron( GLdouble radius ) - изрисува четиристенник.


Както при GLUT и тук можете да определите "линеарно" изрисуване с Wire вместо Solid.

Функции от библиотеките GLAUX и GLUT не само създават обект, но и определят неговите нормални вектори, нужни за правилното функциониране на динамичната светлина, която пък наистина ще накара триизмерните обекти да изглеждат триизмерно. Ако сте останали разочаровани от това, че сферата ви прилича на обикновен кръг, ще видите скоро какви чудеса прави динамичната светлина.

Ето oще една функция от OpenGL, която може да ви бъде полезна :

glPolygonMode( face , mode ) - тя се отнася за всички видове фигури и определя как да бъдат изрисувани. Първия аргумент може да бъде една от константите GL_FRONT, GL_BACK , GL_FRONT_AND_BACK - съответно за предна страна, задна или и за двете страни. Втория аргумент може да бъде GL_FILL - за плътни фигури, което е и по подразбиране, GL_POINT - изобразяват се само върховете или GL_LINE - изобразяват се само линиите на обектите.

Вероятно няма да сте много доволни от това как изглеждат триизмерните обекти, особенно сферите, които приличат на 2D кръгове, което се дължи на пълното отсъствие на динамичната светлина. Но за сметка на това следващата тема ще е изцяло за видовете светлина.

Автор: Иван Георгиев Иванов