- •Лекция 1 Основные понятия OpenGl
- •1.2 Однородные координаты и матрицы
- •1.3 Поворот точки вокруг прямой заданной точкой а(a,b,c) и направляющим вектором e(l,m,n), , на угол φ.
- •1.4 Система координат
- •1.5 Вершины
- •Лекция 2 Освещение объектов
- •2.1Основные понятия
- •2.2 Задание цвета объекта
- •2.3.1 Свойства диффузного отражения
- •2.3.2 Свойства зеркального отражения
- •Лекция 3
- •3.1 Контекст воспроизведения
- •2.3 Освещение объектов
- •3.2 Стандартные функции библиотеки OpenGl
- •3.3 Функции библиотеки glu
- •3.4 Рекомендации по созданию графических приложений
- •Лекция 4
- •Свойства материалов
- •Установка источников света
- •Модель освещения
- •Смешение цветов
- •4.5 Задание теста глубины
- •Лекция 5 Наложение текстуры на объект
- •Задание параметров текстуры
- •Задание параметров текстуры
- •Взаимодействие текстуры с объектом
- •Привязка координат текстуры к объекту
- •Подготовка текстуры из bmp файла, для случая, когда размеры файла известны
- •Пример инициализации двухмерной текстуры
- •Лекция 6. Буфер трафарета
- •6.1 Тест трафарета
- •6.2 Логические операции с графическими объектами
- •6.2.1 Описание метода вычитания графических объектов
- •Лекция 7. Сплайновые поверхности
- •7.1 Кривые Безье
- •7.2 Отображение кривых Безье в OpenGl
- •7.3 Отображение поверхностей Безье в OpenGl
- •Лекция 8. Выбор графических объектов на экране
- •8.1 Идея метода
- •Лекция 9. Экспорт трехмерных изображений из 3d Studio max
- •9.1 Формат файла gms
- •9.2 Импортирование изображений объектов в программу
- •9.3 Загрузка файла формата gms в Delphi
- •Лекция 10 Вспомогательные функции
- •10.1.Работа с таймером
- •10.2 Обработка нажатия клавиши
- •10.3 Вывод текста на экран
- •Литература
9.2 Импортирование изображений объектов в программу
осуществляется с.о.
Включить в проект модуль “Mesh”
В глобальных переменных описать объект, в который из файла будет считано изображение. Например: MyMesh : TGLMultyMesh; // Многосеточный объект
В FormCreate добавить строки
MyMesh := TGLMultyMesh.Create;
MyMesh.LoadFromFile( 'имя_файла.gms' ); // загрузка объекта
MyMesh.Extent := True; // Масштабировать
MyMesh.fSmooth := True; // Установить в фасеты
В FormPaint добавить строки отображения объекта
MyMesh.Draw; // Рисуем объект из 3dmax
В случае необходимости ввести масштаб
glScalef (mx, my, mz);
9.3 Загрузка файла формата gms в Delphi
Пример кода программы выполняющего загрузку данных из файла и отображение объектов в окне показан ниже:
Type // Объявление типов данных
PGLVertex = ^TGLVertex; // Указатель на вершину
TGLVertex = record
x,y,z : GLFloat; // Вершина, как три значения с плавающей точкой
end;
PGLVector = ^TGLVector; // Указатель на вектор
TGLVector = array[0..2] of GLFloat; // Вектор, как массив из трех элементов с плавающей точкой
PGLFace = ^TGLFace; // Указатель на грань
TGLFace = array[0..2] of GLInt; // Грань, как массив из трех целочисленных значений
PGLVertexArray = ^TGLVertexArray; // Указатель на массив вершин
TGLVertexArray = array[Word] of TGLVertex; // Массив вершин
PGLFacesArray = ^TGLFacesArray; // Указатель на массив граней
TGLFacesArray = array[word] of TGLFace; // Массив граней
Здесь требуется небольшое пояснение. Грань объявлена, как массив из трех целочисленных чисел. Дело в том, что граней почти всегда больше чем вершин. Поэтому все вершины запоминаются в отдельном массиве, а грань - это три индекса в этом массиве, указывающие на вершины принадлежащие грани. Одна вершина может принадлежать нескольким граням.
Теперь рассмотрим описание объекта сетка:
TGLMesh = class
Vertices : PGLVertexArray; // Массив вершин объекта - сетка
Faces : PGLFacesArray; // Массив граней
FasetNormals : PGLVertexArray; // Массив фасетных нормалей
VertexCount : Integer; // Количество вершин
FacesCount : Integer; // Количество граней
fExtent : GLFloat; // Коэффициент масштабирования
Extent : GLBoolean; // Флаг масштабирования
public
procedure LoadFromFile( const FileName : String ); // Загрузка
procedure CalcNormals; // Расчет нормалей
procedure Draw; // Отрисовка
destructor Destroy; override; // Уничтожение с очисткой массивов
end;
Здесь пояснений практически не требуется. Можно лишь отметить, что Extent служит для того, чтобы объект загнать в размеры в пределах (-1, 1). об этом совсем не хочется.
procedure TGLMesh.LoadFromFile; // Загрузка файла
var
f : TextFile;
S : String;
i : Integer;
Vertex : TGLVertex;
Face : TGLFace;
MaxVertex : GLFloat;
begin
AssignFile(f,FileName);
Reset(f);
// Пропускаем строки, пока не попадется 'numverts numfaces'
repeat
ReadLn(f, S);
until (S = 'numverts numfaces') or eof(f);
// Читаем количество вершин и граней
Readln(f,VertexCount,FacesCount);
// Выделяем память для хранения сетки
GetMem(Vertices,VertexCount*SizeOf(TGLVertex));
GetMem(Faces,FacesCount*SizeOf(TGLFace));
GetMem(FasetNormals,FacesCount*SizeOf(TGLVector));
ReadLn(f, S); // Пропускаем строку "Mesh vertices"
// Считываем вершины
for i := 0 to VertexCount - 1 do begin
Readln(f,Vertex.x,Vertex.y,Vertex.z);
Vertices[i] := Vertex;
end;
ReadLn(f, S); // Пропускаем строку "end vertices"
ReadLn(f, S); // Пропускаем строку "Mesh faces"
// Считываем грани
for i := 0 to FacesCount - 1 do begin
Readln(f,Face[0],Face[1],Face[2]);
Face[0] := Face[0] - 1;
Face[1] := Face[1] - 1;
Face[2] := Face[2] - 1;
Faces[i] := Face;
end;
CloseFile(f);
// Рассчитываем масштаб
MaxVertex := 0;
for i := 0 to VertexCount - 1 do begin
MaxVertex := Max(MaxVertex,Vertices[i].x);
MaxVertex := Max(MaxVertex,Vertices[i].y);
MaxVertex := Max(MaxVertex,Vertices[i].z);
end;
fExtent := 1/MaxVertex;
CalcNormals;
end;
Здесь могут быть непонятны следующие моменты: В блоке считывания граней вычитается единица из каждого индекса вершины, считанного из файла. Делается это потому, что в программе индексы нумеруются, начиная с нуля, а в файле GMS - начиная с единицы. Процедура CalcNormals служит для расчета нормалей.
procedure TGLMesh.Draw;
var
i : Integer;
Face : TGLFace;
begin
if Extent then glScalef(fExtent,fExtent,fExtent);
for i := 0 to FacesCount - 1 do begin
glBegin(GL_TRIANGLES);
Face := Faces[i];
glNormal3fv(@FasetNormals[i]);
glVertex3fv(@Vertices[Face[0]]);
glVertex3fv(@Vertices[Face[1]]);
glVertex3fv(@Vertices[Face[2]]);
glEnd;
end;
end;
Здесь все понятно. Сначала, если установлен флаг масштабирования, устанавливается масштаб одинаковый по всем осям, затем в цикле рисуются треугольники. Перед началом рисования треугольника объявляется нормаль к нему. В качестве параметров передаются не конкретные значения, а указатели на них.
destructor TGLMesh.Destroy;
begin
FreeMem(Vertices,VertexCount*SizeOf(TGLVertex));
FreeMem(Faces,FacesCount*SizeOf(TGLFace));
FreeMem(FasetNormals,FacesCount*SizeOf(TGLVector));
end;
Здесь тоже все понятно, просто освобождается память, занятая объектом. Вызовы процедур загрузки и отрисовки выполняется известным способом.
