Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики




НазваниеОбразования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики
страница3/4
Дата24.09.2012
Размер0.62 Mb.
ТипДипломная работа
1   2   3   4

2. Работа с файлами формата *.3ds


Для удобства загрузки трехмерных объектов в данной работе используется 3ds формат. Этот формат поддерживается большинством распространенных пакетов моделирования. 3ds формат является закрытым, т.е. нет точного указания места хранения нужной информации, что немного усложняет работу с ним.

Формат 3ds-файла имеет следующую особенность: все данные разделены на блоки – чанки.[9] Каждый чанк описывается именем и длиной. Чанки образуют древовидную структуру: один чанк может содержать внутри себя несколько других подчанков.

Каждый чанк имеет следующий формат:

  • Заголовок чанка – 2 байта

  • Его размер (= 6+n+m) – 4 байта

  • Данные – n байт

  • Подчанки – m байт


Т.о., чанк 3DS-Version (будет рассмотрен далее) в двоичном виде будет иметь вид:




Рисунок 20

где

1 – это 0002, заголовок чанка

2 – это число 10, длина чанка (2[имя чанка] + 4[длина информационной части] + 4[сама информационная часть])

3 - информационная часть, может содержать подчанки


3ds-файл содержит очень много информации об объекте: координаты вершин, информация о гранях объекта, текстурные координаты, данные о материале, освещении и т.д. Но в поставленной задаче важна только геометрия объекта, т.о. необходимо учитывать информацию только о вершинах и гранях трехмерного объекта.

Объект в 3ds формате имеет специфичное представление: координаты вершин хранятся отдельно, а грани представляют собой три указателя на индекс каждой из трех вершин. Все вершины обходятся по часовой стрелке, исключая хранение нормалей (об этом говорилось выше). Именно с учетом этого в данной работе используется аналогичное представление трехмерного объекта.

Для работы с геометрией объекта достаточно знать информацию о нескольких чанках. Их структура представлена ниже:




Рисунок 21


Как уже говорилось выше, чанки, помимо подчанков, могут содержать некоторую информацию. Для данной задачи необходима только информация, содержащаяся в CHUNK_VERTLIST и CHUNK_FACELIST. Ниже они рассматриваются более детально.


CHUNK_VERTLIST (0x4110):

  • Количество вершин – 2 байта

  • Координаты каждой из вершин:

    • x – 4 байта (float)

    • z – 4 байта (float)

    • y – 4 байта (float)


На каждую координату выделяется 4 байта. Всего у вершины три координаты, значит, на каждую вершину 12 байт. Учитывая количество вершин легко посчитать количество необходимых байт.


Следует заметить, что в 3ds-формате координаты вершины идут не в порядке (x, y, z), а в порядке (x, z, y).


CHUNK_FACELIST (0x4120):

  • Количество граней – 2 байта

  • Для каждой грани:

    • Индекс первой вершины – 2 байта

    • Индекс второй вершины – 2 байта

    • Индекс третей вершины – 2 байта

    • Флаги – 2 байта


Флаги позволяют манипулировать с отображением граней:

  • 0й бит – грань АВ видима

  • 1й бит – грань ВС видима

  • 2й бит – грань СА видима


В 3ds-файле может содержаться информация о нескольких экспортированных в него объектах. Поэтому (если такая ситуация возможна), нужно в CHUNK_OBJBLOCK извлечь имя нужного объекта. Оно представляет собой строку, оканчивающуюся нулем (C-string).


2.1. Функция импорта из *.3ds-файла


Идея алгоритма импорта из *.3ds-файла состоит в том, чтобы побитово считывать информацию, строго придерживаясь структуры файла. Т.е. нельзя искать идентификатор нужного чанка, не найдя идентификатор родителя. Так для извлечения информации о вершинах и гранях объекта необходимо пройти следующие этапы:


  • Находим CHUNK_MAIN. Обычно он идет сразу с начала файла, но могут быть и исключения (если использованы чанки глобального уровня [12])

  • Ищем CHUNK_OBJMESH. При этом нужно пропустить все ненужные чанки, которые могут также содержаться в CHUNK_MAIN. Если этого не сделать, то можно ошибиться, приняв за идентификатор искомого чанка величину 0x3D3D, которая на самом деле представляет данные ненужного чанка.

  • Ищем CHUNK_OBJBLOCK.

  • Ищем CHUNK_TRIMESH.

  • Ищем CHUNK_VERTLIST. Этот чанк уже содержит важную информацию. Извлекаем информацию о количестве вершин, а затем сами вершины (три их координаты). Больше в этом блоке ничего не надо, впрочем, в нем больше ничего быть и не должно. В любом случае неплохо сделать проверку на то, что указатель позиции в файле стоит за CHUNK_VERTLIST.

  • Ищем CHUNK_FACELIST. Здесь содержатся данные о гранях. Извлекаем их. В данном блоке могут быть (в отличие от предыдущего) другие подблоки. Поэтому важно переместить указатель позиции в файле на конец данного чанка.

  • Теперь вся необходимая информация считана. Но для данной задачи необходимо рассчитать нормали к треугольникам, ограничивающим объект. Это удобно сделать на данном этапе.



2.2. Функция экспорта в *.3ds файл


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

Функция экспорта представляет собой побитовую запись информации в файл. При экспорте, помимо структуры формата, важно помнить о границе каждого чанка. Если при импорте (считывание из 3ds-файла) приходилось искать нужный чанк по имени и длина чанка, хоть и играла роль, но отступ на несколько байт не был критичным, то при экспорте (запись в 3ds-файл) важен каждый байт.

Что касается четкой границы каждого чанка, то важно помнить, что в файл записывается длина всего чанка, т.е. данные + длина + название [6]. Кроме того, байты пишутся в обратном порядке см. Рисунок 20.


Помимо чанков, которые просматривались для извлечения информации из файла, при записи необходимо знать точные данные следующих чанков:


Обозначения:

Chunk # : кодовое имя

Name : название чанка

Level : уровень в дереве чанков

Size : длина

Father : кодовое имя родительского чанка

Чанки:

________________________________________________________

0x0002 : 3DS-Version


Chunk # : 0x0002

Name : 3DS-Version

Level : 1

Size : 4

Father : 0x4D4D (Main chunk)


________________________________________________________

0x3D3E : Mesh version


Chunk # : 0x3D3E

Name : Mesh version

Level : 2

Size : 4

Father : 0x3D3D (3D editor chunk)


________________________________________________________

0x0100 : One unit

Chunk # : 0x0100

Name : One unit

Level : 2

Size : 4

Father : 3D Editor chunk


В данной работе для них используются стандартные для 3D Studio Max 8.0 значения:

3DS-Version: (int) 3

Mesh version: (int) 3

One unit: 0x0000803F


Остальные чанки описывают различные особенности сцены. Для данной задачи их использование не обязательно. В Приложении Г находится пример 3ds файла в двоичном виде.


Алгоритм экспорта объекта в *.3ds-файл состоит в подсчете длины чанка не в тот момент, когда чанк пишется в файл, а в тот, когда он полностью записан. Это связано с тем, что изначально длины чанков неизвестны (они зависят от длин самых «глубинных» чанков). Удобно изначально оставить место (4 байта) для длины текущего чанка, а потом, подсчитав его длину, на оставленное место записать точное значение.


3. Разработка динамически подключаемой библиотеки классов (DLL)


Библиотека классов (DLL) - это один или несколько объединенных общим назначением классов или функций, скомпилированных в форму разделяемой библиотеки с расширением dll.

Код из разделяемой библиотеки может использоваться в различных программах с помощью динамического связывания на этапе выполнения программы.

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

Чтобы функции были доступны из внешних приложений, их необходимо объявлять рассмотренным ниже способом.


3.1. Функция экспорта в dll-файл


В приложении, в котором будет «собираться» библиотека классов, т.е. будет происходить экспорт в dll-файл, нужно указать следующее:




extern "C" //здесь хранятся функции, видимые из внешних приложений

{

_declspec (dllexport) type NameFunction (parametres)

{



}



}



<здесь могут быть функции, видимые только внутри библиотеки>

Экспорт классов осуществляется несколько сложнее. В dll нет понятия класса как такового. Альтернативой является структура. Поэтому, при необходимости экспорта некоторого класса, для него нужно реализовать интерфейс, представленный структурой с основными переменными класса. Во внешнем приложении также необходимо объявить этот интерфейс.

В данной работе для успешного выполнения задачи необходимо лишь задать объекты. Следовательно, необходим интерфейс для класса OBJECT3D, реализованного в библиотеки классов. Но для описания объекта используется также класс POINT3D. Значит и для этого класса нужен интерфейс:


typedef struct point_type

{

double x, y, z;

}point_3d;


typedef struct object_type

{

vector
vertexes;

vector faces[3];

}object_3d;


Эти 2 структуры также нужно объявить во внешнем приложении, использующем данную библиотеку.

Так как приложение, экспортирующее в dll функции, работает с классами, а приложение, импортирующее функции – со структурами, необходимо реализовать переход от класса к структуре и обратно. Все это сделано в библиотеке классов. В Приложении Б приведен код объявления функций, экспортирующих данные в dll.

3.2. Функция импорта из *.dll - файла


Для использования dll из внешнего приложения, следует придерживаться следующих этапов: сначала нужно объявить, как уже говорилось выше, все интерфейсы для классов. Затем нужно подгрузить библиотеку. Сделать это можно двумя способами: статически и динамически.[2]

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

При динамической загрузке библиотека подгружается не при старте приложения, а когда это действительно необходимо. Преимуществом такого метода является быстрота работы приложения, т.к. библиотека не хранится в памяти все время. Выгрузить ее можно также вручную, либо она выгрузится сама при завершении работы приложения. Еще одним преимуществом такого способа является быстрый старт приложения, а также, что необходим только один файл *.dll. при статической загрузке нужен также *.lib файл, скомпонованный одновременно с *.dll файлом.


В демонстрационной программе используется динамическая загрузка dll.

Синтаксис следующий:


HINSTANCE hinstLib = LoadLibrary("graphics3d.dll");

if (hinstLib == NULL)

{

printf("ERROR: unable to load DLL\n");

getchar();

}


Нужная функция из файла dll импортируется следующим образом:


1) Объявления типа:

typedef object_3d* (*JoinObjects)(object_3d *, object_3d *);

2)Объявление переменной:

JoinObjects JoinObj;

3)Получение адреса функции:

JoinObj = (JoinObjects)::GetProcAddress (hinstLib, "JoinObjects");


С этого момента можно использовать функцию JoinObj:

object3 = JoinObj (object1, object2);


В Приложении Е размещен фрагмент кода из внешнего приложения, иллюстрирующий импорт из dll

4. Разработка плагина для 3D Studio Max 8.0


Для того, чтобы удобнее использовать результат вышеизложенных алгоритмов, было разработано расширение (далее плагин) для 3D Studio Max.

Под плагином (англ. plug-in) понимают независимо компилируемый программный модуль динамически подключаемый к основной программе, предназначенный для расширения или использования её возможностей [4]


Разработка плагинов под 3dmax возможна двумя способами:
1. с помощью языка скриптов (MAXScript)

  1. с помощью 3D Studio MAX SDK (Software Development Kit) и Visual Studio C++

Возможна еще реализация, совмещающая в себе оба пункта.


Под скриптом (сценарием) понимают программу, которая автоматизирует некоторую задачу, которую без сценария пользователь делал бы вручную, используя интерфейс программы [4]

MAXScript – объектно-ориентированный скриптовый язык программирования, встроенный в 3D Studio Max. Он очень удобен для написании небольших скриптов, позволяющих автоматизировать какие-либо действия в среде 3dmax. Разрабатывать на нем сложные плагины нецелесообразно ввиду относительно медленной скорости выполнения команд. Но MAXScript имеет заметное преимущество по сравнению со вторым методом: простота разработки кода.

Большая часть плагинов для 3dmax – это плагины, реализованные с помощью 3D Studio MAX SDK [10]. Главным преимуществом такого подхода является высокая скорость исполнения команд.

Удобным для разработки кода является способ, при котором интерфейс приложения реализован на MAXScript, а логика с помощью SDK. Это связано с тем, что в среде 3D Studio Max все плагины загружаются в память при запуске приложения. В данном случае интерфейс будет «зафиксирован» средой при запуске, а логика будет подгружаться при выполнении каких-либо действий с формой.

Т.о. плагин (plug-in) обычно понимают как динамически подключаемую библиотеку (DLL), которая экспортирует несколько функций, распознающихся тем приложением, для которого пишется плагин. Единого стандарта типов экспортируемых функций нет, для каждого приложения требуются строго определенные функции, однако, приложения, предназначенные для одного типа задач, могут «понимать» плагины друг друга [11]

В 3D Studio Max существует огромное множество типов плагинов. Это могут быть экспортеры и импортеры геометрии, утилиты, модификаторы, плагины текстур и материалов и многие другие. Принято соглашение об именовании *.dll файлов согласно их предназначению. Например, для экспортеров характерно расширение *.dle. При этом файл не меняет своей структуры, а является все тем же *.dll-файлом. Для утилит характерно именование *.dlu .


Далее рассмотрены основные моменты реализации утилиты для 3D Studio Max, позволяющей работать с трехмерными объектами.


Структура плагина

Для того, чтобы 3D Studio Max мог распознать плагин, необходимо реализовать несколько, определенных в классах SDK, функций [13]

1. DllMain

Стандартная main-функция используемая Windows для инициализации DLL

2. LibNumberClasses

В одной библитекеDLL может быть реализовано несколько плагинов. Каждый плагин описывается специальным классом (об этом рассказано ниже) Данная функция возвращает их количество.

3. LibVersion

Возвращает версию 3D Max, для которой предназначен плагин. Ее можно получить из глобальной константы VERSION_3DSMAX, прописанной в Max SDK

4. LibDescription

Если при запуске среды файл плагина не доступен, то строка, возвращаемая данной функцией, будет показан пользователю

5. LibClassDesc

Возвращает указатель на экземпляр класса-описателя конкретного плагина.


Все эти функции должны быть экспортируемыми.


Базовый класс

Если реализуется утилита, то класс, описывающий подобный плагин, должен быть порожден от базового класса UtilityObj, описанного в SDK. Именно с помощью этого класса ведется работа с формой. Этот класс является виртуальным и имеет пять методов, три из них разработчик должен реализовать в своём порожденном классе [13]

  1. DeleteThis

Используется для удаления экземпляра класса плагина.

  1. BeginEditParams

  2. EndEditParams

Два последних метода используются для панели управления. Первый – загружает ее в память в тот момент, когда пользователь открывает плагин. Второй – удаляет ее при завершении пользователем работы с плагином.

Панель управления представляет собой обычное диалоговое окно, созданное средствами Visual Studio (см. Рисунок 22).





Рисунок 22. Слева – диалоговое окно, открытое в редакторе Visual Studio, справа – в 3D Studio Max


Все объекты, которые должны реагировать на события (кнопки, поля вывода), являются объектами Custom Controls, что позволяет более удобную обработку событий [13]. Для работы с панелью управления используется класс Interface. Указатель на экземпляр этого класса передается средой в аргументы функций BeginEditParams и EndEditParams.

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


Класс-описатель плагина

Этот класс необходим для того, чтобы сообщить сведения системе о типе плагина. Он должен быть порожденным от класса ClassDesc2 (который порожден от класса ClassDesc), описанном в MAX SDK.

Для указания типа плагина используется уникальный общий идентификатор. Для плагинов утилитного типа его значение хранится в константе UTILITY_CLASS_ID.

Кроме того, каждый конкретный плагин должен иметь свой уникальный идентификатор. Для его генерации можно воспользоваться файлом gencid.exe, который поставляется со стандартным набором MAX SDK.

Ниже приведен фрагмент кода, где показан класс-описатель.


//получение уникального идентификатора

#define PLUGIN_CLASS_ID Class_ID(0x1218491c, 0x405444d4)


class PlaginClassDesc : public ClassDesc2

{

public:

SClass_ID SuperClassID();

Class_ID ClassID();

void * Create(BOOL loading);

const TCHAR * ClassName();

const TCHAR * Category();

int IsPublic();

};


Функция SuperClassID возвращает идентификатор UTILITY_CLASS_ID.

Функция ClassID возвращает идентификатор PLUGIN_CLASS_ID.

Функция Create возвращает указатель на экземпляр базового класса.

Функция ClassName возвращает строку, которая будет отображаться на кнопке вызова скрипта.

Функция Category возвращает строку, которая указывает принадлежность плагина к одной из категорий. Категории можно посмотреть в стандартном окне Configure Button Sets




Рисунок 23. Категории плагинов


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

1   2   3   4

Похожие:

Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconМинобрнауки томский государственный университет факультет информатики утверждаю
Цель курса – закрепление теоретических знаний по теоретическим и математическим основам информатики, навыков создания и анализа программных...
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconМинобрнауки томский государственный университет факультет информатики утверждаю
Цель курса – изучение математических основ и алгоритмов представления и обработки изображений
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconМинобрнауки томский государственный университет факультет информатики утверждаю
Цель курса – формирование основ знаний по теории информации, принципам кодирования, изучение важнейших алгоритмов в этой области
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики icon«Российский экономический университет им. Г. В. Плеханова» Факультет информатики Кафедра информатики
БД. Рассматриваются экономические и технологические характеристики процессов в информационных системах
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики icon«Томский государственный университет систем управления и радиоэлектроники» Кафедра экономики
А. Г. Буймов – Министерство образования и науки Российской Федерации, Федеральное государственное бюджетное образовательное учреждение...
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconРоссийской Федерации Томский государственный университет Философский факультет Кафедра политологии
Молодежные политические объединения как политтехнологии –22
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconГеофизический факультет кафедра информатики и гис
Министерство образования и науки РФ российский государственный геологоразведочный университет имени серго орджоникидзе
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconРоссийской Федерации Томский государственный университет Исторический факультет Кафедра истории и документоведения
Специальность 032001 – Документоведение и документационное обеспечение управления
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconМинобрнауки томский государственный университет факультет информатики утверждаю
Требования к уровню освоения дисциплины – владение методами математического анализа
Образования Российской Федерации томский государственный университет факультет информатики Кафедра теоретических основ информатики iconМинобрнауки томский государственный университет факультет информатики утверждаю
Цель курса – изучение методов объектно-ориентированного анализа и проектирования
Разместите кнопку на своём сайте:
Библиотека


База данных защищена авторским правом ©lib.znate.ru 2014
обратиться к администрации
Библиотека
Главная страница