Ю.М. Баяковский, А.В. Игнатенко - Начальный курс OpenGL (DOC) (1124366), страница 17
Текст из файла (страница 17)
{
unsigned numb = buf[3]; numb = (numb « 8) | buf[2]; numb = (numb « 8) | buf[l]; numb = (numb « 8) | buf[0]; return numb;
}
int ReadFileHeader (FILE* f, int* bitmap_pos)
{
unsigned char header [BMP_SIZE_FRJEHEADER] ;
s i z e _ t numb = 0;
int offset = 0;
if (fseek(f, 0, SEEK_SET)) return 0;
numb = fread (header , BMP_SIZE_FILEHEADER, 1, f);
Б. 3. Загрузка BMP файла
181
if (numb ! = 1) return 0;
if (header[0] != 'B' || header[l] != 'M') return 0;
offset = uInt32Number (header + 10);
numb = fread(header, 4, 1, f); if (numb ! = 1) return 0;
if (uInt32Number(header) != 40) return 0;
*bitmap_pos = offset ; return 1;
}
// загрузка BMP—файла
int LoadBMP(const char* file , IMAGE* out_img)
{
FILE* f;
int bitmap_pos;
unsigned char buf[40];
s i z e _ t numb ;
int x_res ;
int y_res ;
int n_bits ;
int compression ;
int size_image ;
int n_used_colors ;
// открываем файл
f = fopen(file , "rb");
182 Приложение Б. Демонстрационные программы
if (!f) return 0;
if (out_img = NULL) return 0;
// читаем заголовок
if (! ReadFileHeader (f , &bitmap_pos))
{
fclose(f ); return 0;
}
if (fseek(f, BMP_SIZE_FILEHEADER, SEEK_SET))
{
fclose(f ); return 0;
}
numb = fread(buf, 40, 1, f); if (numb ! = 1)
{
fclose(f ); return 0;
}
x_res = (int )uInt32Number (buf + 4); y_res = (int )uInt32Number (buf + 8);
n_bits = (int) uIntl6Number ( buf + 14)
compression = (int) uInt32Number ( buf + 16)
size_image = (int) uInt32Number ( buf + 20)
n_used_colors = (int )uInt32Number (buf + 32)
// читаем только полноцветные файлы if (n_bits = BMP_COLOR_BLTS_24)
Б. 3. Загрузка BMP файла
183
{ _
int rgb_size ; unsigned char* rgb ; int y;
unsigned char* line; int rest_4 ;
if (bitmap_pos ! =
BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER)
{
fclose(f ); return 0;
}
if (fseek(f, bitmap_pos , SEEK_SET))
{
fclose(f ); return 0;
}
rgb_size = 3 * x_res; rest_4 = rgb_size % 4; if (rest_4 > 0)
rgb_size += 4 — rest_4;
out_img—>width = x_res ; out_img—>height = y_res;
out_img—>data =
(unsigned char *) malloc (x_res * y_res * 3);
if (out_img->data = NULL) return 0;
rgb = (unsigned char *) malloc ( rgb_size ) ;
// заполняем данные из файла
184
Приложение Б. Демонстрационные программы
for (у = 0; у < y_res; y++)
{
s i z e _ t numb = 0; int x = 0;
numb = fread(rgb, rgb_size i f (numb ! = 1)
{
fclose ( f ); free (rgb ); return 0;
}
numb = 0;
line = out_img—>data + x_
for (x = 0; x < x_res; x+-
{
line [2] = rgb [numb++]; line[l] = rgb [numb++]; line[0]= rgb[numb++]; line += 3; } }
fclose(f ); free(rgb );
} else
return 0;
return 1;
}
typedef unsigned typedef unsigned typedef unsigned
char BYTE; short WORD; int DWORD;
typedef struct tagBITMAPFILEHEADER
Б. 3. Загрузка BMP файла
185
{ WORD | bfType; |
DWORD | bfSize; |
WORD | bfReservedl; |
WORD | bfReserved2; |
DWORD | bfOffBits ; |
} BETMAPFILEHEADER; | |
typedef | struct tagBITMAPINFOHEADER { |
DWORD | biSize ; |
long | biWidth; |
long | biHeight ; |
WORD | biPlanes; |
WORD | biBitCount ; |
DWORD | biCompression ; |
DWORD | biSizelmage ; |
long | biXPelsPerMeter ; |
long | biYPelsPerMeter ; |
DWORD | biClrUsed; |
DWORD | biClrlmportant ; |
} BETMAPrNFOHEADER;
static void IntTo2Bytes (int val , BYTE buf[2])
{
buf [0] = (BYTE) val;
buf[l] = (BYTE) (val » 8); }
static void IntTo4Bytes (int val, BYTE buf [4])
{
buf [0] = (BYTE) val;
buf[l] = (BYTE) (val » 8);
buf [2] = (BYTE) (val » 16);
buf[3] = (BYTE)(val » 24);
}
186
Приложение Б. Демонстрационные программы
Б.4. Пример 3: Текстурирование и анимация
Результатом выполнения этой программы является построение тетраэдра с вращающимися вокруг него кольцами, на которые нанесена текстура.
При компиляции программы в Microsoft Visual СИ—Ь файл «texture.bmp» надо поместить в каталог проекта или указать полный путь к нему. Если путь не указан, то при запуске исполняемого файла из операционной системы файл с текстурой должен находиться в том же каталоге. Для загрузки изображения текстуры программа использует функцию LoadBMP, приведенную в предыдущем пункте.
Программа Б.5. Пример текстурирования и анимации.
^include <stdlib.h> T^include <math . h> #include <GL\glut.h> T^include "loadbmp.h"
#define TETR_LIST 1
GLfloat light_col[] = {1,1,1};
float mat_diffl [] = {0.8 ,0.8 ,0.8};
float mat_difi2[] = {0.0 ,0.0 ,0.9};
float mat_amb[]= {0.2,0.2,0.2};
float mat_spec [] = {0.6 ,0.6 ,0.6} ;
float shininess =0.7 * 128, CurAng=0, RingRad = l,
RingH eight =0.1; GLUquadricObj* QuadrObj ; GLuint Texld ; GLfloat TetrVertex [4][3] , TetrNormal [4] [3] ;
// Вычисление, нормали к плоскости, // задаваемой точками а ,Ь , с
void get norm (float a [3] , float b [3] , float c[3], float *n)
Б.4- Пример 3: Текстурирование и анимация
187
{
float mult=0;
n[0] = (b[l]-a[l])*(c[2]-a[2])-(b[2]-a[2]) *
(с[1]-а[1]); n[l] = (c[0]-a[0])*(b[2]-a[2])-(b[0]-a[0]) *
(с[2]-а[2]); n[2] = (b[0]-a[0])*(c[l]-a[l])-(c[0]-a[0]) *
(b[l]-a[l]); // Определение нужного направления нормали: // от точки (0,0,0) for (i=0;i <3;i++) mult+=a [ i ] *n [ i ] ; if (mult<0) for (j=0;j<3;j++) n[j]=-n[j ]; }
// Вычисление координат вершин тетраэдра void InitVertexTetr ()
{
float alpha = 0; int i ;
TetrVertex[0][0]=0;
TetrVertex[0][l] = 1.3;
TetrVertex [0] [2] =0;
// Вычисление координат основания тетраэдра
for (i=l;i<4;i++)
{
TetrVertex [i][0] = 0.94* cos (alpha);
TetrVertex[i][l] = 0;
Tetr Vertex [i][2] = 0.94* sin (alpha);
alpha+ = 120.0*3.14/180.0; } }
// Вычисление нормалей сторон тетраэдра void InitNormsTetr ()
{
getnorm ( TetrVertex [0] , TetrVertex [ 1] ,
188
Приложение Б. Демонстрационные программы
TetrVertex [2] , TetrNormal [0]) ; getnorm ( TetrVertex [0] , TetrVertex [2] ,
TetrVertex [3] , TetrNormal [ 1 ]) ; getnorm (TetrVertex [0] , TetrVertex [3] ,
TetrVertex [1] , TetrNormal [2]) ; getnorm ( TetrVertex [ 1] , TetrVertex [2] ,
TetrVertex [3] , TetrNormal [3]) ;
// Создание списка построения тетраэдра void MakeTetrList ()
{ _
int i ;
gINewList (TETR _LIST,GL_COMPILE) ;
// Задание сторон тетраэдра
g 1В e g i n (GL_TRIANGLES);
for (i=l;i <4;i++)
{
glNormal3fv (TetrNormal [i -1]); glVertex3fv (TetrVertex [0]) ; glVertex3fv( TetrVertex [i ]) ; if (i! = 3)
glVertex3fv( TetrVertex [ i +1]); else
glVertex3fv( TetrVertex [1]) ;
}
glNormal3fv( TetrNormal [3]) ; glVertex3fv( TetrVertex [1]) ; glVertex3fv (TetrVertex [2]) ; glVertex3fv (TetrVertex [3]) ; glEnd(); glEndList () ; }
void DrawRing()
{
// Построение цилиндра (кольца), расположенного
Б.4- Пример 3: Текстурирование и анимация 189
// параллельно оси z // Второй и третий параметры задают // радиусы оснований, четвертый высоту, // последние два—число разбиений вокруг и // вдоль оси z. При этом дальнее основание // цилиндра находится в плоскости z=Q gluCylinder (QuadrObj , RingRad , RingRad , RingHeight ,30 ,2); }
void Texturelnit ()
{
char st rFile [] = " texture .bmp" ; IMAGE img;
// Выравнивание в * .bmp no байту glPixelStorei (GLJJNPACK_ ALIGNMENT, 1); // Создание идентификатора для текстуры glGenTextures (1 ,&TexId ); // Загрузка изображения в память if (!LoadBMP(strFile , &img)) return ; ;
// Начало описания свойств текстуры
glBindTexture (GL_TEXTURE_2D, Texld ) ;
// Создание уровней детализации и инициализация
// текстуры
gluBuild2DMipmaps(GL_TEXTURE_2D,3 ,
img. width, img. height,
GL_RGB, GL_UNSIGNED_BYTE, img . d at a );
// Разрешение наложения этой текстуры на
// quadric—объекты
gluQuadricTexture (QuadrObj , GLJTRUE);
// Задание, параметров текстуры
// Повтор изображения по параметрическим
190
Приложение Б. Демонстрационные программы
// осям s и t
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_REPEAT);
// He использовать интерполяцию при выборе точки
// на текстуре
glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_MN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D,
GL_TEXTURE_MAG_FIJTER1 GL_NEAREST);
// Совмещать текстуру и материал объекта glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODlIATE); }
void Init(void)
{
InitVertexTetr () ;
InitNormsTetr () ;
MakeTetrList () ;
// Определение свойств материала glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
mat_amb) ; glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
mat_spec) ; glMaterialf (GL_FRONT, GL_SHININESS,
shininess);
// Определение свойств освещения glLightfv(GL_LIGHTO, GL_DIFFUSE, light_col); glEnable (GL_LIGIfflNG); glEnable (GL_LIGHT0);
Б.4- Пример 3: Текстурирование и анимация
191
// Проводить удаление невидимых линий и // поверхностей glEnable (GL_DEPTH_TEST); // Проводить нормирование нормалей glEnable (GL_NORMALEZE) ;
// Материалы объектов отличаются только цветом // диффузного отражения glEnable (GL_COLOR_MATERIAL); glColorMaterial (GL_FRONT_AND_BACK, GL_DIFFUSE);
// Создания указателя на quadric—объект // для построения колец QuadrObj=gliiNewQiiadric ();
// Определение свойств текстуры Texturelnit ();
// Задание перспективной проекции glMatrixMode (GL_PROJECTION); gluPerspective (89.0 , 1.0, 0.5, 100.0); // Далее, будет проводиться только // преобразование объектов сцены glMatrixMode (GL_MODELVIEW); }
void DrawFigures (void)
{
// Включение режима нанесения текстуры
glEnable (GL_TEXTURE_2D) ;
// Задаем цвет диффузного отражения для колец
glColor3fv(mat_difil);
// Чтобы не. проводить перемножение с предыдущей
// матрицей загружаем единичную матрицу
glLoadldentity () ;
// Определяем точку наблюдения
192
Приложение Б. Демонстрационные программы
gluLookAt (0.0 , 0.0, 2.5,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0); // Сохраняем видовую матрицу, так как дальше // будет проводиться поворот колец glPushMatrix () ;
// Производим несколько поворотов на новый угол // (это быстрее, чем умножать предыдущую видовую // матрицу на матрицу поворота с фиксированным // углом поворота) glRotatef (-CurAng, l, 1, 0); glRotatef (CurAng, 1, 0, 0); // Для рисования колец каждое из них надо // преобразовать отдельно, поэтому сначала // сохраняем видовую матрицу, затем восстанавливаем glPushMatrix () ;
glTranslatef (0 ,0, - RingHeight /2); DrawRing () ; glPopMatrix () ; glPushMatrix () ;
glTranslatef (0 , RingHeight/2 ,0); glRotatef (90,1,0,0); DrawRing () ; glPopMatrix () ; glPushMatrix () ;
glTranslatef (-RingHeight/2 ,0 ,0); glRotatef (90,0,1,0); DrawRing () ;
glPopMatrix () ;
// Восстанавливаем матрицу для поворотов тераэдра
glPopMatrix () ;
// Выключаем режим наложения текстуры
glDisable (GL_TEXTURE_2D);
// Проводим повороты glRotatef (CurAng, l, 0, 0);