WarCraft 3: Устройство файлов mdl

» Раздел: Моделлинг

Рекомендуем также посмотреть ещё одну статью по формату mdl - "Подробнее о mdl".

Устройство файлов mdl

Для работы нам понадобятся следующее: 3ds max 4 или выше, конвертер моделей в формат mdx (можно скачать здесь), конвертер mdx из в mdl и обратно (можно скачать здесь). Есть также конвертер для перекидывания анимации из макса в mdl вместе с моделями и текстурными координатами MDXExport.
Формат mdx специально разработан для большей архивации моделей, но при этом сам варкрафт не использует файлы в этом формате на прямую. Прежде чем работать с моделью, он конвертирует mdx в mdl, с которым уже работает. Формат mdl представляет собой нечто похожее на asc, но с той разницей, что в файле записываются все параметры модели и её анимации в текстовом виде. Именно на этом и основан мой способ. В принципе, разабраться в mdl не так уж и сложно, это может каждый, нужно только время и хотя бы начальное знание 3ds max.
А теперь по порядку о структуре mdl. Сначала идёт общий раздел.
Model "Tent" { название модели
NumGeosets 2, количество мешей
NumGeosetAnims 2, количество анимаций видимости
NumLights 1, количество источников света
NumHelpers 1, количество помощников
NumBones 2, количество костей
NumAttachments 3, количество прикреплений
NumParticleEmitters2 1, количество источников частиц
NumRibbonEmitters 1, количество источников следа
NumEvents 2, количество событий
BlendTime 150, время смешения
MinimumExtent { -219.2, -309.508, -222.794 }, минимальнык границы модели
MaximumExtent { 108.97, 261.674, 296.323 }, максимальные границы модели
Меш - это условно говоря собрание полигонов (треугольников). Они могут быть соединены или не соединены между собой, но они считаются единым целым. Это означает, что у них один на всех материал и ещё кое-что. Звучит непонятно, но я надеюсь из дальнейшего текста всё станет ясно. Анимация видимости - определяет в какой момент времени меш будет виден, а в какой нет. Каждому мешу соответствует своя анимация видимости. Помощник - всегда невидимый объект фиксированного размера, нужен для вспомогательных целей анимации. Кость - тоже помощник, но более узко специализирован. Нужен для передачи анимации мешу, то есть делаешь анимацию кости, а она передаёт анимацию отедельным участкам меша. Прикрепление - помните в тригерах есть событие: "привязать спецэффект к юниту orign"? Так вот orign - это название прикрепления. С помощью прикреплений, например, определяется, где у героя рука, чтобы вокруг неё летал огненный шар, если герой подобрал сферу огня. Источник следа - например когда оркский блейдмастер машет мечом, то благодаря такому источнику от меча остаётся след на воздухе. Событие - точно ещё не знаю, что это, но похоже, что с помощью него задаётся время анимации, в которое будет произведён тот или иной звук, например когда юнит умирает. Время смешения - пока трудно сказать за что отвечает этот параметр, так как во всех моделях, которые я видел, он был равен 150. Границ модели - относительные границы, за которые модель при любой анимации не выйдет.
Далее идёт описание последовательностей анимации. Заметьте, что здесь, как и в предыдущем разделе, указывается количество последовательностей анимации. Практически во всех разделах соблюдается это правило. Также немаловажно правильно раставлять фигурные скобки {}, так как при несоблюдении этого правила конвертер будет ругаться и не выполнит конвертацию.
Sequences 2 {
Anim "Birth" { название анимации
Interval { 33, 1000 }, временной интервал
NonLooping, не повторять сначала
MinimumExtent { -216.322, -313.805, -118.9 },
MaximumExtent { 283.259, 249.843, 379.521 },
BoundsRadius 408.918, ограничивающий радиус
}
Anim "Stand Work" {
Interval { 6667, 10000 },
MinimumExtent { -216.322, -313.805, -118.9 },
MaximumExtent { 283.259, 249.843, 379.521 },
BoundsRadius 408.918,
}
}
На самом деле, конечно же практически ни у одной модели нет такого малого количества анимаций, но они все описываются весьма похоже, поэтому достаточно привести такой небольшой пример. Название анимации - те самые названия, котоые указываются в тригере "играть stand work анимацию юнита". Временной интервал - с какого кадра по какой будет длиться эта анимация. Чтобы лучше понять, что это значит, откройте 3ds max, там внизу есть раскадровка сцены. Ограничивающий радиус - судя по всему радиус границ, за которые модель или отдельные её составляющие не пускаются, например при использовании источника частиц. Между Interval и MinimumExtent может стоять не только NonLooping. Rarity 3 или Rarity 5 - означает, что анмация редкая, цифра опередляет степень её редкости. В анимации движения, например "Walk", указывается MoveSpeed 290 - скорость движения.
После идёт описание последовательностей глобальных анимации.
GlobalSequences 2 {
Duration 967, длительность анимации
Duration 467,
}
Глобальная анимация - анимация, которая будет присуствовать во всех неглобальных анимациях, например развивание на ветру флага блейдмастера - глобальная анимация. Каждой такой анимации присваивается свой идентификационный номер, соответсвующий её порядковому номеру в приведённом списке минус 1, то есть у глобальной анимации номер 0 длительность - 967 кадров, у номер 1 - 467.
Далее описание используемых текстур.
Textures 2 {
Bitmap {
Image " objects\InventoryItems\TreasureChest\treasurechest
.blp", путь к текстуре
}
Bitmap {
Image "",
ReplaceableId 1, особый тип текстуры
}
Вобщем здесь всё понятно, замечу только, что текстура должа находиться либо внутри карты, либо war3.mpq, либо war3patch.mpq, и то, что текстурам также присваиваются идентификационые номера(ID). В дальнейшем, если в разделе присваиваются ID, то я буду прсто в конце описания ставить "ID". ReplaceableId 1 - цвет игрока, владеющего в данный момент юнитом.
Затем идут материалы.
Materials 2 {
Material {
ConstantColor, особенность материала
Layer { слой
FilterMode None, режим фильтрации слоя
Unshaded, особенность слоя
static TextureID 0, тип текстуры слоя и её ID
Alpha 2 { регулеровка прозрачности
Linear, тип регулеровки
3300: 0.23, номер кадра и использование альфы в долях (от 1 до 0)
3367: 0.48,
}
}
}
Material {
Layer {
FilterMode None,
Unshaded,
static TextureID 1,
}
Layer {
FilterMode Blend,
static TextureID 0,
static Alpha 0.7, определяет значение альфы в любой момент времени
}
}
}
Этот раздел - один из самых многообразных. Благодаря различным комбинациям, можно создать большое количество самых различных материалов. Особенность материала: ConstantColor - постоянный цвет, SortPrimsFarZ - пока не знаю что это означает, но материал с таким параметром использовался для создания свечения вокруг меча блейдмастера. Слой - в материале может использоваться несколько слоёв, накладываясь один на другой и создавая нужный эффект. Режим фильтрации - можно сказать, что этот параметр определяет тип слоя. None - простой непрозрачный слой. Blend - смешивание с остальными слоями материала. Transparent - прозрачность слоя определяется текстурой. Поясню, что это значит: каждая текстура состоит из самого изображения и слоя прозрачности (альфы). Этот слой фактически представляет собой чёрно-белую картинку, накладываемую на изображение, при этом, то место, где пиксел оказался белым, слой - непрозрачен, а где пиксел - чёрный, там слой полностью прозрачен и значит невидим. Оттенки серого соответствуют разной степени прозрачности. Для лучшего понимания этого аспекта откройте Photoshop или какой-нибудь другой редактор текстур такого типа. AddAlpha - при наложении на другие слои, в том числе и других материалов, альфа прозрачности всех наложенных слоёв математически складывается и результат будет являться альфой для этого слоя (сложение, конечно же, попиксельное). Также, возможно существование режимов вычитания, умножения, деления альфы (что-нибудь вроде SubtAlpha). Additive - это уже относится к текстуре, то есть при наложении слоёв происходит их сложение, а выдаётся результат, также возможно существование схожих с альфой режимов. Особенность слоя - существует множество различных особенностей. Unshaded - не затеняется, при этом теряется реалистичность. TwoSided - слой накладывается на обе стороны меша - лицевую и оборотную, если же этот параметр не указан, то текстура наносится только на лицевую сторону, если же посмотреть с обратной стороны, то будет видно сквозь меш. Unfogged - убирает дымчатость, что конкретно это означает, пока не знаю, но устанавливается этот параметр весьма редко, только если материал используется для создания спецэффекта, например звёздочек, летящих при лечении. Регулеровка прозрачности - определяет какую долю альфы брать в орпеделённый промежуток времени. При этом установленное число будет действовать до следующей установки другого числа или ближайшего ключевого кадра анимации, которыми являются кадры начала и окончания анимации, указанные в описании последовательностей анимации. Значение любого параметра в ключевых кадрах считается равным максимальному (в данном случае единице). Это очень важный момент, так как ключевые кадры, как я уже сказал, оказывают влияние на все параметры, а значит в них происходит обнуление внесённых изменений. Тип регулеровки прозрачности - влияет на то как прозрачность будет меняться от одного кадра до другого. DontInterp - мгновенный переход из одного значения в другое. Linear - постепенный переход. ID.
Далее следуют непосредственно сами меши.
Geoset {
Vertices 4 { вершины меша
{ -138.925, -309.508, 296.323 },
{ -138.925, -309.508, -222.794 },
{ -219.2, 261.674, 296.323 },
{ -219.2, 261.674, -222.794 },
}
Normals 4 { нормали вершин
{ 0.990268, 0.139173, -1.90921e-008 },
{ 0.990268, 0.139173, -1.90921e-008 },
{ 0.990268, 0.139173, -1.90921e-008 },
{ 0.990268, 0.139173, -1.90921e-008 },
}
TVertices 4 { текстурные вершины
{ 0, 0 },
{ 0, 1 },
{ 1, 0 },
{ 1, 1 },
}
VertexGroup { группы вершин(меша)
0,
0,
1,
1,
}
Faces 1 6 { поверхность
Triangles {
{ 0, 1, 2, 3, 2, 1 },
}
}
Groups 2 2 { группировка по костям
Matrices { 0 },
Matrices { 1 },
}
MinimumExtent { -219.2, -309.508, -222.794 }, см. описание последовательностей анимации
MaximumExtent { -138.925, 261.674, 296.323 },
Anim {
MinimumExtent { 3.40282e+038, 3.40282e+038, 3.40282e+038 },
MaximumExtent { -3.40282e+038, -3.40282e+038, -3.40282e+038 },
}
Anim {
MinimumExtent { -219.2, -309.508, -222.794 },
MaximumExtent { -138.925, 261.674, 296.323 },
BoundsRadius 388,
}
MaterialID 0, ID материала меша
SelectionGroup 0, группа выделения
}
Это меш номер 0. Далее идут все остальные меши, организованные таким же образом. В этой части файла и задаётся статическая геометрия (форма) модели. вершины меша - координаты вершин, ID. нормали вершин - координаты нормалей вершин, указывающие, где у точки лицевая сторона, а где оборотная. Звучит странно, но тем не менее. Текстурные вершины - координаты вершин меша на текстуре, благодаря им определяется как накладывается текстура на модель. Группы вершин меша - объеденение вершин для технических целей. В данном примере первые две вершины объединены в группу 0, другие две - в группу 1. Поверхность - здесь из вершин составляется поверхность. Вершины объединяются в треугольники, из которых уже состоит поверхность. Группировка по костям - немаловажная часть моделирования, определяет какие вершины управляются какими костями. ID номер Matrices(матрицы) соответсвует ID номеру группы вершин, а число в фигурных скобках соответствует объектному ID номеру кости. Подробнее об объектном ID номере будет сказано немного позднее. В данном примере, вершины, относящиеся к группе вершин номер 0, будут управляться костью с объектным номером 0. ID материала меша указывает, какой материал будет применён к этому мешу. Группа выделения - пока не знаю, что это, но во всех моделях равен 0 для всех мешей.
Затем идёт анимация видимости.
GeosetAnim {
Alpha 4 {
DontInterp, тип перехода
0: 0,
967: 1,
1333: 0,
5800: 0,
}
GeosetId 0, используемый меш
}
GeosetAnim {
Alpha 4 {
DontInterp,
0: 0,
967: 1,
733: 0,
4800: 0,
}
GeosetId 1,
}
Здесь также каждой анимации соответствует свой ID номер. Тип перехода - та же функция, что и у типа регулеровки прозрачности в разделе материала, даже те же названия используются. Устанавливается номер кадра и значение, при этом 1 - объект виден, 0 - невидим.
Далее идут вспомогательные объекты разных типов. При этом все они нумеруются независимо от типа.
Bone "Plane01" { тип и название объекта
ObjectId 0, номер объекта
Billboarded, особенность объекта
GeosetId 0, номер используемого меша
GeosetAnimId 0, номер используемой анимации видимости
Scaling 3 { тип преобразования
Linear, способ перехода
GlobalSeqId 0, номер глобальной анимации
0: { 1, 1, 1 },
67: { 1.54938, 1.54938, 1.54938 },
966: { 1, 1, 1 },
}
}
Bone "Box01" {
ObjectId 1,
Parent 3, "Dummy01" родитель объекта
GeosetId Multiple,
GeosetAnimId None,
Rotation 2 {
Hermite,
667: { 0, 0, 0, 1 },
InTan { 0.110167, 0.0903195, 0.0587129, 0.988058 },
OutTan { 0.110167, 0.0903195, 0.0587129, 0.988058 },
733: { -0.238667, -0.195669, -0.127196, 0.942641 },
InTan { -0.357136, -0.210093, -0.174873, 0.89316 },
OutTan { -0.357136, -0.210093, -0.174873, 0.89316 },
}
Translation 2 {
Hermite,
333: { 0, 0, -17.0679 },
InTan { 0, 0, -17.0679 },
OutTan { 0, 0, -3.75045 },
967: { 0, 0, -20.8183 },
InTan { 0, 0, -3.75045 },
OutTan { 0, 0, 3.75045 },
}
}
Словов bone значит, что объект - кость. Номер объекта - тот самый номер, который указывался в матрицах при групировке верши по костям. Запись "Matrices { 0 }" означает, что вершинами управляет кость с номером 0, в данном примере это кость "Plane01". Особенности объекта: Billboarded - всегда поворачивается к зрителю лицевой стороной. На этом принципе основаны шары на блейдмастере. На самом деле это не шары, а плоскости, на которые наложена текстура с альфой прозрачности, и эти плоскости всегда поворачиваются к нам лицом. Номер используемого меша нужен для ускорения работы компьютера. Если кость управляет сразу несколькими матрицами из разных мешей, то пишется GeosetId Multiple. Номер используемой анимации видимости указывает какая анимация отвечает за видимость кости. Если для этой кости не испоьзуется анимация видимости, то пишется GeosetAnimId None. Надо заметить, что поскольку к кости привязаны матрицы, то им передаются все изменения происходящие с костью, включая видимость. Ведь действительно, зачем управлять видимостью кости, если её всё равно не видно? Это нужно для передачи воздействия на матрицы. Но, как у матриц есть управляющий, так и костей он может быть. Обычно это помощник, хотя может быть и другая кость, при этом указывается Parent ID(номер родителя). В этом прмере родителем кости 1 является помощник 2. Тип преобразования - какое преобразование будет происходить с костью. Scaling - изменение масштаба. Задаётся в долях по каждой оси координат отдельно. Rotation - вращение. Первые две координаты задают точку на плоскости XY, через которую и начало координат проводится плоскость, параллельная оси Z. На этой плоскости оставшимися двумя координатами задаётся окончательная точка поворота. Translation - вроде премещение. Visibility - видимость. Способ перехода - то же, что и тип регулеровки в анимации видимости. Bezier - безье тип, то есть кривая прехода с регулируемой гладкостью. InTan - входящая в вершину гладкость, OutTan - выходящая. Глобальная анимация задаётся либо в костях либо в помощнике. Для этого достаточно после способа перехода написать GlobalSeqId и ID номер. Все последующие после этого координаты преобразования будут причисляться к глобальной анимации. У одной кости или помощника может быть несколько преобразований разного типа, в данном примере у кости "Box01" два преобразования: вращение и премещение.
После костей идут источники света.
Light "Omni01" { название
ObjectId 2,
Omnidirectional, тип
static AttenuationStart 80, начальноая граница затухания
static AttenuationEnd 200, конечная граница затухания
static Intensity 17, интенсивность
static Color { 0.87451, 0.984314, 1 }, цвет
static AmbIntensity 0, интенсивность внешней освещённости
static AmbColor { 1, 1, 1 }, цвет внешней освещённости
Visibility 6 {
DontInterp,
67: 0,
600: 0,
65033: 0,
65300: 1,
65467: 0,
240000: 0,
}
}
По типу, источники света делятся на точечные(omni) и направленные(direct). Omnidirectional - точечный. Свет затухает от начальной до конечной границы. До начальной его интенсивность не меняется и равна 100 процентам, а после конечной не изменяется и равна 0. Цвет задаётся в долях трёх основных цветов: красного, зелёного, синего.
Затем идут помощники.
Helper "Dummy01" {
ObjectId 3,
Translation 2 {
Linear,
5000: { 0, 0, 0 },
5333: { 3.43655, -4.24382, -13.444 },
}
}
Структура строения помощников весьма схожа со структурой костей. Главное отличие состоит в том, что у помощника указывается только его ID номер и задаётся преобразование.
Затем идут прикрепления.
Attachment "Origin Ref " {
ObjectId 4,
}
Attachment "Overhead Ref" {
ObjectId 5,
}
Attachment "Weapon Ref" {
ObjectId 6,
Parent 3,
Visibility 3 {
DontInterp,
133: 0,
567: 0,
667: 1,
}
}
Origin и Overhead - неправда ли знакомые названия? Именно эти прикрепления и определяют положение внешних эффектов, прикрепляемых к юниту. Но прикрепления могут быть не только статическими, им также как и костям с помощниками можно задавать преобразование и родителей. Обратите внимание, что нумерация прикреплений начинается не с нуля, а является продолжением общей нумерации объектов.
Далее идут геометрические центры.
PivotPoints 11 {
{ -5.57062, 0.220597, 20.2984 },
{ 3.28472, -4.53012, 30.8989 },
{ -4.28088, 17.2638, 32.6912 },
{ -8.02448, -0.0493665, 35.7101 },
{ -7.2794, 1.89344, 30.8989 },
{ -153.026, -86.0745, 368.757 },
{ -116.208, -193.252, 151.937 },
{ -7.2692, 5.58314, 344.523 },
{ -7.9371, 1.42364, 568.952 },
{ 189.757, 61.9468, 245.577 },
{ -23.4029, -5.56605, 105.132 },
}
Первая строчка - координаты геометрического центра объекта с ID равным 0. И так далее для всех объектов.
Следом идут источники частиц
ParticleEmitter2 "SmallBlastDebris" {
ObjectId 7,
SortPrimsFarZ,
Unshaded,
static Speed 440, скорость движения частиц
static Variation 0, вариация скорости
static Latitude 55,
static Gravity 749, мощность гравитации
Squirt, распылять
LifeSpan 0.71, время жизни
EmissionRate 4 { скорость воспроизводства
DontInterp,
65033: 0,
65333: 22,
65433: 0,
122167: 0,
}
static Width 24, ширина источника
static Length 24, длинна источника
Blend, смешение
Rows 1, количество строчек
Columns 1, количество столбиков
Head,
TailLength 0.1,
Time 0.7,
SegmentColor {
Color { 0, 0.682353, 1 },
Color { 0, 0.309804, 0.658824 },
Color { 0, 0, 0 },
},
Alpha {255, 255, 0},
ParticleScaling {5, 5, 5}, масштаб частиц
LifeSpanUVAnim {0, 0, 1},
DecayUVAnim {0, 0, 1},
TailUVAnim {0, 0, 1},
TailDecayUVAnim {0, 0, 1},
TextureID 2, ID используемой текстуры
}
Про источники частиц я ещё немного знаю, поэтому коментировать нечего, но многие параметры здесь те же, что и в предыдущих разделах.
Затем идут источники следа.
RibbonEmitter "BlizRibbon01" {
ObjectId 8,
Parent 3,
static HeightAbove 48.312,
static HeightBelow 48.372,
static Alpha 0.35,
static Color { 0, 0.635294, 1 },
static TextureSlot 0,
Visibility 2 {
DontInterp,
2333: 0,
6000: 0,
}
EmissionRate 35,
LifeSpan 0.35,
Rows 1,
Columns 1,
MaterialID 3,
}
Это совсем тёмный лес.
Далее идут камеры. Хотя обычно, если и есть в модели камера, то она одна.
Camera "Camera01" {
Position { 403.317, -10.8177, 202.115 }, позиция камеры
FieldOfView 0.538016, сила линзы
FarClip 1000, далнее отсечение
NearClip 8, ближнее отсечение
Target {
Position { -86.5748, -22.7399, 0.860381 }, координаты цели
}
}
Камера не входит в общую нумерацию объектов. Для неё задаётся координаты объектива и цели, на которую он смотрит. Сила линзы определяет угол обзора камеры, чем больше значение, тем больше угол. За пределами растояния, попадающего в промежуток между дальней и ближней границей отсечения, ничего для камеры не видно.
Последними идут события.
EventObject "SNDxDOLS" {
ObjectId 9,
EventTrack 1 {
667,
}
}
EventObject "UBRxDHSB" {
ObjectId 10,
EventTrack 1 {
5333,
}
}
Номер кадра указывает, когда начнёт играть звук. "SNDxDOLS" - название звука.
А теперь, как применив эти знания, создать свою модель. Прежде чем читать дальнейшее, я бы посоветовал тем, кто не читал статью на comstroller.narod.ru прочесть её.
Если у вас уже есть модель, то её надо сперва мысленно разбить на простые составляющие. Голова с туловищем, руками и ногами - один параллелепипед, конь - другой параллелепипед. Далее считаете количество вершин в каждом таком стставляющем. Создаёте свою mdl, в котором делаете столько мешей, сколько составляющих у вас получилось (в принципе можно и меньше). Заносите в них координаты необходимых вершин, не важно какие координаты, главное чтобы были все необходимые вершины. Затем запсываете триугольники, чтобы получились именно те простые фигуры, которые в получили. Задаёте остальные, необходимые для корректной работы параметры (например вершины текстуры), но не создаваёте пока анимации. Конвертите mdl в mdx, который имортируете в 3ds max. Там вы путём движения вершин востанавливаете свою модель и экспортируете её опять в mdx, его в mdl, координаты вершин вставляете в свою заготовку. Теперь модель готова. Опытным путём задаёте нужные координаты текстурных вершин. Анимация делается посредством всё тех же костей, помщников, источников частиц и т. д. Вообщем, как я и предупреждал, соэдание своей модели - тяжёлое занятие.
Некоторые особенности mdl.
  1. Координаты в mdl расположены не так как в максе, а именно, то, что в mdl x, y, z, то в максе -y, x, z. Вот такие странности, но это проверенно и подтвержденно.
  2. Вращение меша, привязанного к кости происходит вокруг геометрического центра(pivot) кости.

Просмотров: 10 876

» Лучшие комментарии


C0oo1D #1 - 9 лет назад 3
Хоть многое я уже знаю - новичкам будет в самый раз! Афтор - кросавец, не пожалел времени затраченного на это, уважаю!)
Balkock #2 - 9 лет назад 1
Вот у меня прога не 3DS max , а Google SketchUp..Он созхраняет модельки в формате Skp.. Есть ли какой-нибудь конвертер SKP\MDL???
Satreas #3 - 5 лет назад 0
думал сейчас зачитаюсь, папробую. Начала- все ссылки битые и пропало все желание (Для работы нам понадобятся следующее: 3ds max 4 или выше, конвертер моделей в формат mdx (можно скачать здесь), конвертер mdx из в mdl и обратно (можно скачать здесь). Есть также конвертер для перекидывания анимации из макса в mdl вместе с моделями и текстурными координатами MDXExport.)
Syndicat_e #4 - 5 лет назад -2
А как модели загружать в карту?
Стратег #5 - 5 лет назад 2
Ссылки не работают, дальше не читал, заливаете на шнягу всякую.