OpenGL для начинающих
11 Разное=========а. Получение текста последней ошибки OpenGL MessageBox(0, gluErrorString(glGetError), 'OpenGL error', MB_OK); б. Восстановление состояния режимаЛампа GL_LIGHT0 будет включена или выключена в зависимости от ее состояниемперед началом блока glPushAttrib(GL_LIGHT0); ... glEnable(GL_LIGH0); ... glPopAttrib(); 12 Вывод текста в OpenGL========================Код получен объединением кода Jan Horn, NeHe (уроки 13 и 14) и DRKB Работа с графикой и мультимедиа > DerectX, OpenGL > OpenGL: Каким обpазом выбиpать pазмеp шpифта.Итак, можем выводить текст как растровое изображение и как векторное (буквыэто 3D объекты). Идея такова, что для алфавита подготавливается список (см 09), а при вводе текст разбивается на буквы и потом последовательно длякаждой буквы печатаемой строки выполняется соответствующий набор команд из списка.Ниже код, который реализует как растровый, так и как векторный вывод.(необходимо лишь закоментировать указанные строки).
CharList: GLuint; // Вот этот список
gmf: array [0..255] of GLYPHMETRICSFLOAT; // массив требуется для векторного
...
{----------------------------------------------------------------}
{ Создание списка букв }
{----------------------------------------------------------------}
procedure glBuildFont;
var
Font: hFont;
begin
// Список для 256 букв алфавита
CharList := glGenLists(256);
// Создаем шрифт, подробнее см. SDK
Font := CreateFont(-28, 0, 0, 0, FW_BOLD, 0, 0, 0, RUSSIAN_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
FF_DONTCARE or DEFAULT_PITCH, 'Comic Sans MS');
// Устанавливаем шрифт для DC
SelectObject(DC, Font);
// Создаем команды списка.
// Выбираем один из двух вариантов
// Если используем wglUseFontBitmaps то - это растровое изображение
if not wglUseFontBitmaps(DC, 0, 256, CharList) then
или
// Если используем wglUseFontOutlines то - это векторное изображение
if not wglUseFontOutlines(DC, 0, 255, CharList, 0, 0.2, WGL_FONT_POLYGONS, @gmf) then
MessageBox(0, 'Font not create', 'glBuildFont', MB_OK);
// Удаляем шрифт, так как соответствующий список уже создан
DeleteObject(Font);
end;
{----------------------------------------------------------------}
{ Вывод строки на экран }
{----------------------------------------------------------------}
procedure glPrint(X, Y: Integer; text: String);
begin
// Расчитывается позиция на экране. Требуется только для растрового
// вывода. То есть при векторном выводе X и Y gLPrint игнорируются,
// поэтому перед выводом надо будет воспользоваться glTranslatef
glRasterPos2i(X, Y);
glPushAttrib(GL_LIST_BIT);
// Указыывем, что первая буква алфавита рисуется 1-ым набором команд
glListBase(1);
// Выводим текст
glCallLists(length(text), GL_UNSIGNED_BYTE, PChar(text));
glPopAttrib();
end;
...
// Где-то перед использованием вывода текста, напр. в MyOpenGL.glInit
// после создания контеста воспроизведения RC
glBuildFont;
...
// Когда работа с текстом будет уже не нужна, то очистим список
// Напр. в MyOpenGL.glKill перед освобождением RC
glDeleteLists(CharList, 256);
glColor3f(1.0, 0.0, 1.0);
// Добавляем текст на сцену
glPrint(-150, 0, 'Даст ист фантастиш');
...
var
List: GLuint;
Count: Integer;
...
// Где-то до использования создания сцены, напр. в MyOpenGL.glInit
Count := gluLoadList('1.gls', List); // моя функция загрузки скрипта из файла из MyGLU.pas
...
// Где-то в функции создания сцены, напр. в MyOpenGL.glDraw
for i := 0 to Count - 1 do
begin
glCallList(List + i); // Вызываем i-ый набор команд; нумерация с нулевого
end;
interface
uses windows, OpenGL, SysUtils;
// Функция создает список, используя команды из текстового файла
// Возвращаемое значение - число элементов созданного списка
function gluLoadList(FileName: String; var List: GLuint): Integer;
implementation
var
Param: array [1..10] of Extended;
// Получение из входной строки S подслов, которые конвертируется в Float
// и помещаются в соответствующий Param[i]. S начинает обрабатываться
// с S[Pos].
function GetParam(S: String; Pos: Integer): Integer;
var
i, j: Integer;
Value: String;
begin
for i := 1 to 10 do Param[i] := 0;
j := 1;
Value := '';
for i := Pos + 1 to Length(S) do
if (S[i] = ' ') then
begin
Param[j] := StrToFloat(Value);
if j = 10 then
begin
Result := 10;
MessageBox(0, PChar('Too many params!'), 'GetParam', MB_OK);
exit;
end
else j := j + 1;
Value := '';
end
else Value := Value + S[i];
if Value <> '' then Param[j] := StrToFloat(Value);
Result := j;
end;
function gluLoadList(FileName: String; var List: GLuint): Integer;
var
F: TextFile;
S, Command: String;
Count, CurrList, i: Integer;
Obj: GLUquadricObj;
begin
if not FileExists(FileName) then
begin
MessageBox(0, PChar('File '+FileName + ' not found'), 'glLoadList', MB_OK);
end;
AssignFile(F, FileName);
Reset(F);
readln(F, S);
Count := StrToInt(S);
CurrList := 0; // сдвиг; иначе номер набора команд.
List := glGenLists(Count);
Obj := gluNewQuadric;
// читаем из файла, если видим знакомую команду, то выполняем
while not EOF(F) do
begin
Command := '';
readln(F, S);
for i := 1 to Length(S) do
if S[i] = ' ' then break
else Command := Command + S[i];
GetParam(S, i);
Command := UpperCase(Command);
if Command = 'GLNEWLIST' then
glNewList(List + CurrList, GL_COMPILE);
if Command = 'GLENDLIST' then
begin
glEndList;
CurrList := CurrList + 1;
end;
if Command = 'GLBEGIN' then
glBegin(round(Param[1]));
if Command = 'GLEND' then
glEnd;
if Command = 'GLROTATE' then
glRotate(Param[1], Param[2], Param[3], Param[4]);
if Command = 'GLSCALE' then
glScale(Param[1], Param[2], Param[3]);
if Command = 'GLTRANSLATEF' then
glTranslatef(Param[1], Param[2], Param[3]);
if Command = 'GLVERTEX3F' then
glVertex3f(Param[1], Param[2], Param[3]);
if Command = 'GLCOLOR' then
glColor(Param[1], Param[2], Param[3], Param[4]);
if Command = 'GLLOADIDENTITY' then
glLoadIdentity;
if Command = 'GLPUSHMATRIX' then
glPushMatrix;
if Command = 'GLPOPMATRIX' then
glPopMatrix;
if Command = 'GLUSPHERE' then
gluSphere(Obj, Param[1], round(Param[2]), round(Param[3]));
if Command = 'GLUCYLINDER' then
gluCylinder(Obj, Param[1], Param[2], Param[3], round(Param[4]), round(Param[5]));
if Command = 'GLUDISK' then
gluDisk(Obj, Param[1], Param[2], round(Param[3]), round(Param[4]));
end;
glEndList;
gluDeleteQuadric(Obj);
CloseFile(F);
Result := Count;
end;
end.
Очень сильно помогло для вывода текста. Спасибо.
Отправить комментарий