Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
комп графика Лекции.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
200 Кб
Скачать
☆

9.2 Импортирование изображений объектов в программу

осуществляется с.о.

  1. Включить в проект модуль “Mesh”

  2. В глобальных переменных описать объект, в который из файла будет считано изображение. Например: MyMesh : TGLMultyMesh; // Многосеточный объект

  3. В FormCreate добавить строки

  • MyMesh := TGLMultyMesh.Create;

  • MyMesh.LoadFromFile( 'имя_файла.gms' ); // загрузка объекта

  • MyMesh.Extent := True; // Масштабировать

  • MyMesh.fSmooth := True; // Установить в фасеты

  1. В FormPaint добавить строки отображения объекта

MyMesh.Draw; // Рисуем объект из 3dmax

  1. В случае необходимости ввести масштаб

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;

Здесь тоже все понятно, просто освобождается память, занятая объектом. Вызовы процедур загрузки и отрисовки выполняется известным способом.