Программирование графики с использованием Direct3D

       

Функции меню File в классе FacePickWin


Приложение FacePick позволяет загружать и сохранять сетки с помощью меню File. Для этих целей в класс FacePickWin включены функции OnFileOpen() и OnFileSave(). Функция OnFileOpen() выглядит следующим образом:

void FacePickWin::OnFileOpen() { static char BASED_CODE filter[] = "X Files (*.x)|*.x|All Files (*.*)|*.*||"; CFileDialog opendialog(TRUE, 0, 0, OFN_FILEMUSTEXIST, filter, this); if (opendialog.DoModal() == IDOK) { CWaitCursor cur; CString filename = opendialog.GetPathName();

LPDIRECT3DRMMESHBUILDER builder; d3drm->CreateMeshBuilder(&builder); HRESULT r = builder->Load((void*)(LPCTSTR)filename, NULL, D3DRMLOAD_FROMFILE, NULL, NULL); if (r != D3DRM_OK) { CString msg; msg.Format("Failed to load file\n'%s'", filename); AfxMessageBox(msg); return; }

meshframe->DeleteVisual(meshbuilder); meshbuilder->Release(); meshbuilder = builder; meshframe->AddVisual(meshbuilder); meshscale = ScaleMesh(meshbuilder, D3DVALUE(25)); } }

Функция использует класс MFC CFileDialog. Обратите внимание, что в качестве аргумента конструктора класса используется строка filter. Эта строка информирует диалоговое окно о том, какие типы файлов могут быть загружены.

Для вывода диалогового окна используется функция DoModal(). Если будет возвращена константа IDOK, имя файла извлекается из класса диалогового окна с помощью функции GetPathName(). Обратите внимание, что мы не проверяем, существует ли данный файл. Это сделано потому, что при конструировании объекта диалогового окна мы указали константу OFN_FILEMUSTEXIST. Данная константа указывает классу диалогового окна, что в случае ручного ввода имени файла должен быть проверен факт существования данного файла. В результате диалоговое окно просто не позволит ввести имя несуществующего файла (эта проверка не гарантирует правильности содержимого файла, она гарантирует только его существование).

Затем функция пытается загрузить новую сетку. Если попытка завершается неудачно, выводится окно с сообщением об ошибке и функция завершает работу.
Эта ошибка не вызовет проблем в работе приложения, просто и дальше будет отображаться существующая в сцене сетка.

Если новая сетка успешно загружена, существующая сетка удаляется из сцены функцией DeleteVisual() интерфейса Direct3DRMFrame, и указатель meshbuilder освобождается. Затем к сцене добавляется новый конструктор сеток с помощью функции AddVisual().

На последнем этапе вызывается функция ScaleMesh(). Мы видели, как эта функция используется в других демонстрационных программах, но в данном случае есть несколько отличий. Вспомните, что функция ScaleMesh() масштабирует сетку до желаемого размера. В данном случае мы масштабируем любую загруженную сетку до размера в 25 единиц. Это замечательно работало в других приложениях, и работает здесь, но если после масштабирования сетка будет записана на диск, ее размеры изменятся. Поэтому перед тем как записывать сетку на диск, ей необходимо вернуть первоначальные размеры. Функция ScaleMesh() возвращает значение, являющееся коэффициентом, использованным для масштабирования оригинальной сетки. Сохранение этого значения позволит нам вернуть сетке оригинальный размер. Мы увидим, как это делается, когда будем обсуждать код функции OnFileSave().

Функция OnFileSave() определена следующим образом:

void FacePickWin::OnFileSave() { static char BASED_CODE filter[] = "X Files (*.x)|*.x||"; CFileDialog opendialog(FALSE, ".x", "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter); if (opendialog.DoModal() == IDOK) { CWaitCursor cur; CString filename = opendialog.GetPathName(); D3DVALUE restorescale = D3DVALUE(1)/meshscale; meshbuilder->Scale(restorescale, restorescale, restorescale); meshbuilder->Save(filename, D3DRMXOF_BINARY, D3DRMXOFSAVE_ALL); meshbuilder->Scale(meshscale, meshscale, meshscale); } }

Функция OnFileSave() также использует класс CFileDialog, но в вызове конструктора класса диалогового окна указан другой набор констант. Константа OFN_HIDEREADONLY указывает, что в диалоговом окне не надо отображать флажок Open as Read Only.


Наличие константы OFN_OVERWRITEPROMPT приведет к тому, что в случае перезаписи существующего файла программа попросит подтвердить необходимость выполнения данного действия.

Для вывода диалогового окна используется функция DoModal(). Если функция возвращает константу IDOK, текущая сетка записывается на диск. Класс CWaitCursor используется для отображения во время выполнения записи указателя мыши в форме песочных часов. Для получения имени сохраняемого или перезаписываемого файла применяется функция GetPathName(). Затем сетке возвращается ее оригинальный размер. Значение restorescale вычисляется таким образом, чтобы обратить операцию масштабирования, которой сетка подверглась при загрузке. Затем используется функция Scale() интерфейса Direct3DRMMeshBuilder чтобы масштабировать сетку согласно полученному коэффициенту restorescale. Для сохранения сетки вызывается функция Save(). Затем сетке возвращается ее предыдущий размер. Если не сделать этого, то после сохранения отображаемая сетка может стать огромной или микроскопической.


Содержание раздела