Мобильная версия сайта | |||||||||
[Главная] | [Новости] | [Статьи] |
[Проекты] |
[Ссылки] |
[Автор] |
||||
[Архив новостей] | |||||||||
[Форум] | на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы | ||||||||
Здравствуйте! Вы попали на информационно-образовательный сайт посвященный информатике, информационным технологиям и компьютерным играм. Подробнее о целях и задачах сайта в разделе Главная. [English version of this page here...] | |||||||||
[Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi] | |||||||||
[Разработка компьютерной игры] [Пример игры Donuts3D] [Delphi DirectX] | |||||||||
Основы 3D-программирования DirectX8.1 в Delphi 6-7: теоретические и практические основы создания игр. | |||||||||
Анимация | |||||||||
10.01.2008 Эти заметки написаны с целью лучшего уяснения работы с шейдерами, а также для внедрения использования анимации в имеющийся код. |
|||||||||
[Все уроки] | |||||||||
За основу взят пример SkinnedMesh. | |||||||||
Итак, внутри DrawFrames происходит следующее: Result:= m_pd3dDevice.SetTransform(D3DTS_WORLD, pframeCur.matCombined); по матрице matCombined устанавливается Мировая трансформация; Result:= DrawMeshContainer(pmcMesh); //строится анимированный меш Result:= DrawFrames(pframeChild, cTriangles);//осуществляется рекурсивный вызов данной процедуры для дочерних кадров |
|||||||||
главная работа происходит внутри DrawMeshContainer(pmcMesh); поступивший сюда меш (pmcMesh) проходит следующие стадии обработки: if (m_method <> pmcMesh.m_Method) then GenerateMesh(pmcMesh); //изменился метод анимации - нужно сгенерировать новый меш Далее осуществляется построение в зависимости от выбранного метода анимации: if (m_method = D3DNONINDEXED) then Получаем указатель на массив комбинаций костей скелета влияющих на вершины модели. Группы вершин связанных с данными комбинациями костей (в простейшем случае это всего лишь 1 кость) имеют Атрибуты Идентификации (AttribId) По этим атрибутам происходит определение числа фаз межкадрового сглаживания - numBlend, из массива Комбинаций костей считываются матрицы трансформации по их идентификатору - matid:= pBoneComb[ipattr].BoneId[i]; //ipattr - это номер атрибута, i - номер фазы сглаживания //из массива Комбинаций Костей по номерам считываются матрицы и устанавливаются в качестве Мировой матрицы трансформации. Перетекание между фазами анимации осуществляется за счет перемножения матриц m_pd3dDevice.SetTransform(D3DTS_WORLDMATRIX(i),
pmcMesh.m_pBoneMatrix[matid]^); |
|||||||||
Далее происходит установка количества фаз межкадрового сглаживания, устанавливается материал, текстура и происходит фактическая отрисовка подмножества граней меша с данным номером атрибута Если графическое устройство не может производить все фазы межкадрового сглаживания на аппаратном уровне (HW - Hardware Vertex Processing), то далее оставшаясь часть модели отрисовывается на программном уровне. В коде это отражается лишь установкой соответствующего флага и появлением новой группы атрибутов (iAttrSplit) |
|||||||||
Анимация при помощи других методов осуществляется подобным же образом с особенностями реализации для конкретного ее вида (см исходный код). | |||||||||
Ответ на первый вопрос: 1) Каким образом внедрить в код примера другие модели (например, земную поверхность)? | |||||||||
Если создать отдельный класс, например TAnimatedModel, реализующий возможности заложенные в примере SkinnedMesh, то просто создав отдельный объект и загрузив в него нужную модель можно внедрить в код использование других моделей. Но вот в чём загвоздка: в примере SkinnedMesh даже написанном на C++ из DX SDK содержится следующая ошибка - при попытке загрузить модель через пункт меню Open приложения возникает ошибка. Поэтому прежде чем двигаться дальше нужно найти причину и устранить эту ошибку!!! |
|||||||||
Заметки
по устранению: При загрузке модели приложением ошибка не возникает. Как проходит загрузка во время старта приложения? В методе создания (Create) приложения: SomeModel := TAnimatedModel.Create; В методе инициализации (InitDeviceObjects): SomeModel.m_szPath
:= 'Media\Models\nanozone1.x'; |
|||||||||
В методе RestoreDeviceObjects методы SomeModel не вызываются. | |||||||||
В методе Invalidate - SomeModel.InvalidateDeviceObjects; |
|||||||||
В методе DeleteDeviceObjects - SomeModel.Free; |
|||||||||
В методах Render и FrameMove соответстующие методы SomeModel При выборе пункта меню Open приложения SkinnedMesh осуществляется следующая цепочка команд (см. метод MsgProc): {...} lstrcpy(m_szPath,
ofn.lpstrFile); |
|||||||||
Ошибка происходит внутри: SomeModel.InitDeviceObjects > LoadMeshHierarchy в строках кода //
Enumerate top level objects. if
FAILED(Result) then Exit; на втором проходе цикла |
|||||||||
код ошибки: -2005529767 Просмотр расшифровки кода ошибки утилитой DXErr из DX SDK дает следующую расшифровку кода ошибки: D3DXERR_INVALIDDATA | |||||||||
В режиме отладки проследим за поведением приложения при 1) начальном старте 2) при выборе пункта меню Open |
|||||||||
1) начальный старт - SomeModel.InitDeviceObjects > LoadMeshHierarchy |
|||||||||
![]() |
|||||||||
Для полной загрузки модели nanoco_go.x требуется всего 3 прохода цикла внутри которого установлена контрольная точка (см. рисунок) без учета рекурсивных вызовов происходящих внутри процедуры LoadFrames | |||||||||
2) при выборе пункта меню Open На втором проходе цикла возникает указанная выше ошибка |
|||||||||
Достичь выявления сути ошибки можно сравнением внутренней работы, происходящей внутри LoadFrames при 1) начальном старте приложения и при 2) выборе пункта меню Open | |||||||||
Сначала установим на каком рекурсивном вызове происходит ошибка при условии 2 внутри LoadFrames | |||||||||
Ошибка возникает на 2 рекурсивном вызове. Теперь нужно установить на каком проходе возникает ошибка внутри данного рекурсивного вызова. Внутри данного рекурсивного вызова ошибка возникает в строке if
SUCCEEDED(Result) then
pxofobjChild:= nil; |
|||||||||
на 2-ом проходе, другими словами это можно записать схемой (в скобках указан номер прохода, на котором происходит ошибка при условии 2 - второй столбец таблицы) | |||||||||
1) начальный старт приложения LoadMeshHierarchy > LoadFrames (3) |
2) загрузка выбором пункта меню Open LoadMeshHierarchy > LoadFrames (2) > LoadFrames (2) > LoadFrames (2) > LoadMesh ошибка происходит в строке Result:=
D3DXCreateTextureFromFile(m_pDevice, szPath, pmcMesh.pTextures[iMaterial]); |
||||||||
При начальном старте приложения строка кода DXUtil_FindMediaFile(szPath, pMaterials[iMaterial].pTextureFilename); производит определение пути к файлу с текстурой, а строка Result:= D3DXCreateTextureFromFile(m_pDevice, szPath, pmcMesh.pTextures[iMaterial]); осуществляет загрузку текстуры например: pMaterials[iMaterial].pTextureFilename = 'Media/Textures/nanoco.jpg' strFullPath (внутри DXUtil_FindMediaFile) = полный путь к файлу При загрузке через Open строка кода DXUtil_FindMediaFile(szPath, pMaterials[iMaterial].pTextureFilename); производит определение пути к файлу с текстурой, но внутри данной процедуры происходит ошибка из-за построения некорректного пути. Эта ошибка присуща не только примеру SkinnedMesh, но и другим примерам из DX SDK написанным на C++: enchancedmesh, optimizedmesh, progressivemesh и проявляется в отсутствии текстуры на модели открытой через пункт меню Open. |
|||||||||
Разработчики DirectX в DX SDK 9 на обновленном примере SkinnedMesh проблему обошли за счёт удаления пункта меню Open. | |||||||||
Но вернемся к нашему примеру. Если в примере SkinnedMesh внутри процедуры LoadMesh пару строк заменить на {**
Result:= }D3DXCreateTextureFromFile(m_pDevice, szPath, pmcMesh.pTextures[iMaterial]); То открытие моделей можно будеть осуществлять, только с потерей вида текстуры на модели (т.е будет наблюдаться такое же поведение как в примерах enchancedmesh, optimizedmesh, progressivemesh). |
|||||||||
В приложениях для просмотра мешей mview (MeshView) из DX SDK 8 и DXViewer из DX SDK 9 все модели загружаются без текстур. Это говорит о том, что в данном случае имеет место какая-то фундаментальная проблема которая в примерах из DX SDK никак не решается, а просто обходится стороной. Возможно это связано с особенностями COM-приложений и характером связей между файлом модели и файлами текстур. Поэтому и нам придется похоже смириться с этим и радоваться тому, что текстуры хотя бы загружаются при начальном старте приложения. |
|||||||||
Я попытался разрешить проблему своими силами добавив в коде приложения SkinnedMesh следующий код ограниченный строками //** означающими, что код отладочный и его в реальном приложении следует удалить или закомментировать: //** begin procedure
RemakeDelimeter(var AStr: array of Char); А внутри метода LoadMesh внёс следующие изменения: if
(pMaterials[iMaterial].pTextureFilename <> nil) then
if OpenMenuItemSel then begin
FreeMem(tempStr);
|
|||||||||
Таким образом: - Я пробовал загружать текстуру без использования процедуры DXUtil_FindMediaFile; - Определять путь к текстуре через другие методы; - Менять разделители в пути к текстуре с '\' на '/' и наоборот; Но это не помогло решить проблему. |
|||||||||
Поэтому остается смириться с этой проблемой убрав весь отладочный код и оставив только строки {**
Result:= }D3DXCreateTextureFromFile(m_pDevice, szPath, pmcMesh.pTextures[iMaterial]); А также учитывать факт потери текстур моделями при их загрузке не во время начального старта приложения, а повторно до его закрытия. Нормальное появление текстур на моделях возможно только при рестарте приложения! |
|||||||||
21.01.2008 Однако в этом случае возникает вопрос: Как же происходит повторная загрузка моделей в играх? Ведь ни одна игра не может загружать все модели для всех уровней разом. В разных уровнях требуются разные модели, а значит неминуемы повторные загрузки. И это надо осуществить без рестарта приложения! Решение найдено!!! Если внутри файла модели указан не относительный, а абсолютный путь к текстуре в данной системе, то проблема отпадает и указанные выше ограничения и изменения в коде снимаются!!! |
|||||||||
Таким образом, решением может быть коррекция путей к текстурам в файлах моделей на каждой конкретной системе. Это должно происходить во время инсталляции игры или самим игровым приложением до выполнения загрузки моделей. | |||||||||
22.01.2008 - решение проблемы оказалось тривиально простым, даже не потребуется написания ни единой строки кода!!! Если
модель имеет следующий путь Media\Models\SomeModel.x При этом все описанные проблемы снимаются!!! и никаких изменений в коде делать не нужно!!! |
|||||||||
24.01.2008 Эксперименты показали еще одну особенность. Это касается кода приложений использующих DirectX 8.1. Если
модель расположена по пути - А
текстура - То
если внутри модели указан путь к текстуре как То
при старте приложения текстура выводится, Если
путь записан как то
при старте приложения текстура не В приложениях DirectX 9 этого не наблюдается. Путь всегда должен быть записан как ../Textures/nx4_2.bmp |
|||||||||
31.01.2008 Необходима
переделка пути только при первом Проблема
была решена следующим образом: была
объявлена глобальная переменная Внутри метода загрузки моделей - // Find the path to the texture and create that texture
if FirstStart then begin // текстового файла списка используемых текстур
StrCopy(strMediaPath, PChar(TexturesList[i])); и в конце данного метода -
if FirstStart then begin Идея
решения проблемы состоит в том, что в папке с моделями исходная
модель - spacebox.x Если
модель имеет следующий путь Media\Models\SomeModel.x Номера
строк внутри файла списка текстур соответствуют индексам Как
нужно записывать пути к текстурам для анимированных или Т.о.
внутри модели путь к текстуре должен быть относительный - появление
текстуры при первой загрузке (при старте приложения) |
|||||||||
[далее - решение поставленных выше вопросов -] 1) Каким образом внедрить в код примера другие модели (например, земную поверхность)? 2) Как использовать в коде примера камеру ? 3) И наконец, как перемещать и вращать анимированную модель в 3D-сцене, например чтобы анимированный персонаж перемещался по земной поверхности ? |
|||||||||
[Назад] [Все уроки] | |||||||||
Обновления
и новости о развитии Delphi DirectX проекта http://www.megainformaticsite.pochta.ru http://www.megainformatic.boom.ru http://www.megainformatic.narod.ru
|
|||||||||
по всем вопросам пишите на megainformatic@mail.ru или оставьте сообщение на форуме |
|||||||||
Обмен ссылками | |||||||||
|
|||||||||
(с) МЕГА ИНФОРМАТИК 2006-2009 | |||||||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |