Delphi - сбориник статей


Создание анимированного персонажа и вывод на экран


Специально для тех, кто не владеет навыками работы с 3D Studio Max и Character Studio, я создал модель бегающего человечка. Она находится в папке MAX, и файл называется BodyRun.max. Если у Вас вообще нет пакета 3D Studio Max, то файл GMS с сетками этого человечка находится в папке GMS и называется ManRun.gms.

Итак, запустите среду 3D Studio Max и создайте анимированного персонажа или загрузите его из файла BodyRun.max. Запустите утилиту MEGA, как это делалось в разделе Знакомство с утилитой MEGA V1.0. Установите значение поля From =0, значение поля To установите в кадр, на котором заканчивается анимация, в случае с файлом BodyRun.max это значение нужно установить в 11. Значение поля Step установите в еденицу. Выделите сетку персонажа.
Внимание: убедитесь, что Вы выделили именно сетку персонажа и только ее. Пометьте флажок Selected Only. Для анимации сетки используется скелет. Он создается и подгоняется под размеры и форму тела, затем вершины сетки связываются с костями скелета. При анимации изменяются параметры положения частей скелета, а сетка лишь следует за ними. Поэтому, всегда, когда используется этот подход, в сцене помимо сетки присутствует скелет. Вот почему необходимо выделить только сетку и пометить флажок Selected Only.

После того, как Вы выполнили все операции укзанные выше, экспортируйте объект в файл GMS. В процессе экспорта Вы должны увидеть, как последовательно перемещается ползунок расположенный внизу экрана, отсчитывая кадры анимации, и как меняются кадры в проекционных окнах 3D Studio Max. Процесс экспорта завершится, когда ползунок достигнет конечного значения.

Готовый проект лежит в папке Ch02. Откомпилируйте его и запустите на выполнение. На экране вы должны увидеть примерно то, что изображено на рисунке. Нажатием кнопки "Анимировать" можно запускать или останавливать анимацию. Если Ваш компьютер оснащен 3D ускорителем, то лучше развернуть окно на весь экран - так медленнее. Теперь разберем исходный код программы. Он дополнился новым объектом TGLMultyMesh, который создан для загрузки и последовательной отрисовки нескольких сетчатых объектов. TGLMultyMesh = class Meshes : TList; CurrentFrame : Integer; Action : Boolean; fExtent : GLFloat; Extent : Boolean; public procedure LoadFromFile( const FileName : String ); procedure Draw; constructor Create; destructor Destroy; override; published end;

Список Meshes хранит все сетки загруженные из файла. Переменная Action указывает выполняется анимация или нет, а CurrentFrame содержит номер текущего кадра анимации. procedure TGLMultyMesh.LoadFromFile; var f : TextFile; S : String; procedure ReadNextMesh; var i : Integer; Vertex : TGLVertex; Face : TGLFace; MaxVertex : GLFloat; NextMesh : TGLMesh; begin NextMesh := TGLMesh.Create; repeat ReadLn(f, S); until (S = 'numverts numfaces') or eof(f); // Читаем количество вершин и граней Readln(f,NextMesh.VertexCount,NextMesh.FacesCount); // Выделяем память для хранения сетки GetMem(NextMesh.Vertices, NextMesh.VertexCount*SizeOf(TGLVertex)); GetMem(NextMesh.Faces, NextMesh.FacesCount*SizeOf(TGLFace)); GetMem(NextMesh.FasetNormals, NextMesh.FacesCount*SizeOf(TGLVector)); ReadLn(f,S); // Пропускаем строку Mesh vertices: // Считываем вершины for i := 0 to NextMesh.VertexCount - 1 do begin Readln(f,Vertex.x,Vertex.y,Vertex.z); NextMesh.Vertices[i] := Vertex; end; ReadLn(f,S); // Пропускаем строку end vertices ReadLn(f,S); // Пропускаем строку Mesh faces: // Считываем грани for i := 0 to NextMesh.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; NextMesh.Faces[i] := Face; end; // Рассчитываем масштаб MaxVertex := 0; for i := 0 to NextMesh.VertexCount - 1 do begin MaxVertex := Max(MaxVertex,NextMesh.Vertices[i].x); MaxVertex := Max(MaxVertex,NextMesh.Vertices[i].y); MaxVertex := Max(MaxVertex,NextMesh.Vertices[i].z); end; NextMesh.fExtent := 1/MaxVertex; NextMesh.CalcNormals; Meshes.Add(NextMesh); end; begin Meshes := TList.Create; AssignFile(f,FileName); Reset(f); While not Eof(f) do begin Readln(f,S); if S = 'New object' then ReadNextMesh; end; CloseFile(f); end;

Код загрузки объекта TGLMultyMesh практически идентичен коду загрузки объекта TGLMesh. Небольшое отличие состоит в том, что объект TGLMultyMesh предполагает, что файл содержит несколько сеток. Поэтому при загрузке проиходит поиск строки "New Object", создается объект TGLMesh, который помещается в список Meshes и в него считывается информация из файла. Затем весь цикл повторяется до тех пор, пока не кончится файл. Процедуры создания, уничтожения и отрисовки объекта тоже почти не изменились: procedure TGLMultyMesh.Draw; begin if Extent then begin fExtent := TGLMesh(Meshes.Items[CurrentFrame]) .fExtent; glScalef(fExtent,fExtent,fExtent); end; // Рисование текущего кадра TGLMesh(Meshes.Items[CurrentFrame]).Draw; // Если включена анимация // увеличить значение текущего кадра if Action then begin inc(CurrentFrame); if CurrentFrame > (Meshes.Count - 1) then CurrentFrame := 0; end; end; constructor TGLMultyMesh.Create; begin Action := False; CurrentFrame := 0; end; destructor TGLMultyMesh.Destroy; Var i : Integer; begin for i := 0 to Meshes.Count - 1 do begin TGLMesh(Meshes.Items[i]).Destroy; end; Meshes.Free; end;

Немного изменился и вызов функции загрузки в модуле frmMain.pas. procedure TfrmGL.N1Click(Sender: TObject); begin if OpenDialog.Execute then begin MyMesh.Destroy; Mymesh := TGLMultyMesh.Create; MyMesh.LoadFromFile( OpenDialog.FileName ); MyMesh.Extent := true; // Проверяем сколько сеток загружено // и возможна ли анимация if MyMesh.Meshes.Count <= 1 then N2.Enabled := False else N2.Enabled := True; end; end; // Включение анимации procedure TfrmGL.N2Click(Sender: TObject); begin MyMesh.Action := not MyMesh.Action; N2.Checked := not N2.Checked; end;

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

Да, конечно, человечек убогий. Мало того, что он кривой, так еще и прихрамывает. Что делать, чтобы создавать красивых человечков с минимальным количеством граней нужно быть профессионалом 3D моделирования. Все же, мы еще попытаемся его улучшить.

Вероятно, Вы заметили, огрехи воспроизведения объектов на экране, выражающиеся в каких - то непонятных черных треугольниках в тех местах, где их не должно быть. Сам я понятия не имею, откуда они взялись. Если Вас не удовлетворяет такой вид объектов, значит, настала пора поговорить о нормалях.




Начало  Назад  Вперед