OpenGL в Delphi

       

Предлагаю вам дорисовать звезды




Должен сразу извиниться перед астрономами за множество допущенных в этой модели ошибок, с позиций современной науки она совершенно безграмотная, и использовать ее для уроков астрономии нельзя
В процедуру подготовки образа текстуры передается имя файла растра, создание образа текстуры включено в код процедуры

procedure TfrmGL.Preparelmage(bmap: string);
// тип для динамического массива, код подходит для всех версий Delphi
type
PPixelArray = ^TPixelArray;
TPixelArray = array [0..0] of Byte;
var
Bitmap : TBitmap;
Data : PPixelArray; // образ текстуры, размер заранее не оговариваем
BMInfo : TBitmapInfo; // заголовок файла
ImageSize : Integer;// вспомогательные переменные
Temp : Byte; // для перестановки цветов
MemDC : HOC; // вспомогательный идентификатор
begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile (bmap); // считываем образ из файла
with BMinfо.bmiHeader do begin
FillChar (BMInfo, SizeOf(BMInfo), 0); // считываем заголовок
biSize := sizeof (TBitmapInfoHeader);
biBitCount := 24;
biWidth := Bitmap.Width;
biHeight := Bitmap.Height;
ImageSize := biWidth * biHeight;
biPlanes := 1;
biCompression := BI_RGB;
MemDC := CreateCompatibleDC (0);
GetMem (Data, ImageSize * 3); // создаем динамический массив
try
GetDIBits (MemDC, Bitmap.Handle, 0, biHeight, Data, // считываем
BMInfo, DIB_RGB_COLORS); // в DIB-формат растр
// битового массива
For I := 0 to ImageSize - 1 do begin // переставляем цвета
Temp := Data [I * 3]; Data [I * 3] := Data [1*3+2];
Data [1*3+2] := Temp,
end;
glTexImage2d(GLJTEXTURE_2D, 0, 3, biWidth, // создаем образ
biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
finally
FreeMem (Data); // освобождаем память DeleteDC (MemDC);
Bitmap.Free;
end;
end;
end;

Это универсальная процедура и годится для любых форматов. В ней осуществляется сравнительно много действий, и вызывается она два раза - для подготовки рисования и планеты, и спутника Используются дисплейные списки:

Quadric := gluNewQuadric;
gluQuadricTexture (Quadric, TRUE);
// обычные параметры текстуры
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN__FILTER, GL_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// включать режим текстуры для оптимизации надо было бы в кадре
glEnable(GL_TEXTURE_2D);
// список для Земли
glNewList (Earth, GL_COMPILE);
Preparelmage ('..\earth.bmp'); // подготавливаем образ
gluSphere (Quadric, 1 0, 24, 24); glEndList; // список для Луны
glNewList (Moon, GL_COMPILE);
Preparelmage ('..\moon.bmp'); // образ другой
glPushMatrix; // будет перемещение
glTranslatef (1.3, 1.3, 0.3);
gluSphere (Quadric, 0.2, 24, 24);
glPopMatrix; // возвращаемся на место
glEndList;
// после описания списков quadnc-объекты больше не нужны
gluDeleteQuadric (Quadric);

Это очень важно, поэтому хочу еще раз повторить дисплейные списки в таких случаях являются крайне эффективным решением, иначе бы нам приходилось подготавливать и переключать образы текстуры многократно, для каждого кадра.
При описании списка мы обращаемся к процедуре чтения файла Preparelmage Здесь мог бы быть и более обширный код, но в дисплейный список компилируется только одна единственная строка, строка с подготовкой текстуры При вызове списка все промежуточные строки не вызываются, файл не считывается и, в принципе, вы можете ею даже удалить, т. к. он больше не используется.
По сценарию Земля вращается вокруг своей оси, а Луна вращается в противоположную Земле сторону:

glPushMatrix;
glRotatef (-10, 0.0, 1.0, 0.0);
glRotatef (Angle, 0.0, 0.0, 1.0); // поворот Земли вокруг своей оси
glCallList(Earth); glPopMatrix;
// для Луны необходимо добавить вращение вокруг своей оси
glPushMatrix;
glRotatef (-Angle, 0.0, 0.0, 1.0); // угол вращения противоположный
glCallList(Moon); glPopMatrix;

Переходим к следующему примеру, проекту из подкаталога Ex89, в котором показывается работа с полупрозрачной текстурой
(Рисунок 4.62).



Содержание раздела