Talk:M2: Difference between revisions

From wowdev
Jump to navigation Jump to search
 
(94 intermediate revisions by 15 users not shown)
Line 2: Line 2:
--[[User:Schlumpf|schlumpf_]] 00:53, 23 August 2008 (CEST)
--[[User:Schlumpf|schlumpf_]] 00:53, 23 August 2008 (CEST)


== On animations ==
== Deleted Blocks ==
=== old (schlumpf) ===
=== Block D ===
'''Offset Type Name Description'''
''0x000'' uint16 InterpolationType How the values are interpolated. (0=none, 1=linear, 2=hermite)
''0x002'' uint16 GlobalSequenceID If its made with a global sequence, its in here. Id is it is, -1 if not.
''0x004'' uint32 nTimestamps The number of timestamps. Is the same as the number of keys, most of the time.
''0x008'' uint32 ofsTimestamps Offset to the timestamps in the file.
''0x00C'' uint32 nKeys Number of the keys.
''0x010'' uint32 ofsKeys Values of the block.


The offsets point to a sub-structure now. Its like this:
*'''nD records of (int16, int16) starting at ofsD'''
'''Offset Type Name Description'''
''0x000'' uint32 Number It tells us where the values actually are.
''0x004'' uint32 Offset The offset to the data.


The easiest form is if you get a Number == 1 block straight as in single-value AnimationBlocks in some blocks. Particles have only such AnimationBlocks. It just gives you another offset where the data is. Its in this file at the given offset. But if you get a whole list with a lot of stupid values (such as offsets that can't be in the M2 and the .anims), you have a little problem. I don't know why, but Blizzard made some crap here. Most likely to get us confused. Or there is more information I know nothing of.
Maybe a lookup table for animations? Since the numbers happen to be in fixed positions. The first short seems to increase with the position for models with all animations (like characters), the second seems to be flags or a modifier? Or something.
 
What helped me so far was this "simple" conversion: Take nTimestamps / nKeys, substract 1, divide by 3. So out of 0x22 (34) you will get 11. This is the offset to the real sub-structure (if you start with the one pointed to at 0). This offset is then into one of the [[M2/WotLK/.anim|.anim]] files. I think its just "if the first file is full, we will take the next one". I am not sure about this. I have been sleepless for 2 days now and cba to look even more into these blocks.
 
The data at the final offset can be of any structure. It can be one float, a short, an integer but too a Vector of three floats or a quaternion which is made in four floats or shorts, depending on the occurence of the main AnimationBlock.
 
 
Actually I'd say that we may have gotten this structure:
'''Offset Type Name Description'''
''0x000'' uint16 InterpolationType How the values are interpolated. (0=none, 1=linear, 2=hermite)
''0x002'' uint16 GlobalSequenceID If its made with a global sequence, its in here. Id is it is, -1 if not.
''0x004'' uint32 offsetIntoList1 (This - 1) / 3 is the index into the list at offsetToTimestampsOfs.
''0x008'' uint32 offsetToTimestampsOfs Offset to the list which holds the offset to the data of the timestamps.
''0x00C'' uint32 offsetIntoList2 (This - 1) / 3 is the index into the list at offsetToKeysOfs.
''0x010'' uint32 offsetToKeysOfs Offset to the list which holds the offset to the data of the keys.
 
What the fuck, Blizzard?
 
After investigation, the structure shown above is spot on (though I'm not yet 100% sure about the "(this - 1) / 3" part -- still researching it.  There are two count/offset pairs.  One for the timeline reference and one for the keyframe reference (these are described below in detail).  Each AnimationBlock is 0x14 bytes.


=== new and improved (Slartibartfast) ===
Maybe you've already figured it out yourself, chuanhsing, but it still might be helpful as I cannot see any anymations in your latest WMV version:


Animation in WotLK is actually easy once you've understood what Blizzard has changed. They have essentially gone from one single, long timeline per model (with every single animation covering a slice of this timeline, based on their start and end times) to a multi-timeline approach where each animation has its own timeline, starting at 0 with the length as defined in the animation sequence data structure.
Contain indices into the texture animations list, or -1 meaning a static texture.


Because of this, the basic animation block structure had to be changed. They dumped the interpolation ranges (as those aren't necessary anymore if each animation has its own timeline), and they have added another layer of references for the timestamp and value information. This means instead of the number of timestamps followed by the offset to said timestamps there's now the number of timelines followed by an offset to the timeline data. This offset leads to a structure of 8 bytes per timeline, with the first 4 bytes making up the actual number of timestamps for one specific timeline and the next 4 being an offset to the actual timestamp data. The keyframe values are stored in a similar fashion.


All of this of course does not account for the new .anim files which seem to be single animations that aren't stored in the .m2 file itself - I haven't looked at those yet, so I can't give you any hints about their structure. But the changes described above will get all animations stored in the file itself to work fine, which is the vast majority of animations.


== Render Flags ==


Okay, now I think I've understood how those .anim-files fit into the picture. Blizzard has created them to externalize seldomly-needed animations such as dance animations from the main model file, probably to speed up the loading process by loading them on-demand when they are to be played.
''Please forgive any ignorance I show here as I'm not a professional programmer. I'm just trying to help improve Wow Model Viewer, which has very few staff left and these pages have been invaluable for understanding it :)  I just wanted to mention something that confused me and I'm not sure if it needs correcting...''


Their structure is simple: they don't have any structure on their own. They are just a pile of binary data, which is being referenced from the animation sub-blocks (I just decided to call those sub-structures in the animation blocks that contain the actual keyframe data for a single animation "animation sub-blocks", see my last post for details on this) in the exact same way as data in the main model file is being referenced: by offsets to timestamp/keyframe data. These references just point into the .anim-file corresponding to a specific animation id if an animation is stored externally.
The Render Flags section of this page has two different tables for blend modes, with no mention of what the difference is. Is one out of date? The settings they recommend are different for a few modes, but they agree on others. I also tried them out in WMV and found that blend mode 1 is not working right with the settings from the tables (sections are appearing completely invisible when they shouldn't be) so maybe it's out of date in both, or there's something I'm not understanding. Perhaps it's meant to be used in conjunction with GL_ALPHA_TEST or glAlphaFunc() or something.


The names of the animation data files are composed from the following template: [model file name][animation id]-[animation sub-id].anim
Thanks for all your work here! :)


However, there's still one thing I don't understand: how someone can decide if an animation sequence is stored internally (in the model file) or externally. Of course it's possible to check if a corresponding .anim file exists, but I don't think that this is how WoW actually does it as that would result in quite some overhead. That information is probably stored somewhere in the main model file, but I haven't found it yet...
- Wain


* Posted by Slartibartfast at the [http://www.wowmodelviewer.org/forum/index.php?topic=3672.40 wowmodelviewer-forums].
* the second table was created by relax by tracing directx stuff in the MoP client, the first one was later created by schlumpf based on reverse engineering the WoD beta client. The first table assumes alpha test to be the same, the second one lists them separate. there might be errors in both, tbh. feel free to fix them if you find them, or come to quakenet#modcraft to discuss them. :) --[[User:Schlumpf|Schlumpf]] ([[User talk:Schlumpf|talk]]) 16:47, 14 October 2015 (UTC)


== Animations in some beta-code ==
* Aha! Thanks very much :) I'll experiment with the modes more and see what I can find.
-- Wain


animated.h
void init(AnimationBlock &b, MPQFile &f, int *gs)


original code
== Particle Emitters ==
<pre>
    uint32 *ptimes = (uint32*)(f.getBuffer() + b.ofsTimes);
    for (size_t i=0; i<b.nTimes; i++)
      times.push_back(ptimes[i]);
   
    // keyframes
    assert((D*)(f.getBuffer() + b.ofsKeys));
    D *keys = (D*)(f.getBuffer() + b.ofsKeys);
    switch (type) {
      case INTERPOLATION_NONE:
      case INTERPOLATION_LINEAR:
        for (size_t i=0; i<b.nKeys; i++)
          data.push_back(Conv::conv(keys[i]));
        break;
      case INTERPOLATION_HERMITE:
        for (size_t i=0; i<b.nKeys; i++) {
          data.push_back(Conv::conv(keys[i*3]));
          in.push_back(Conv::conv(keys[i*3+1]));
          out.push_back(Conv::conv(keys[i*3+2]));
        }
        break;
    }
</pre>


modified code
I'm not yet sure what to do with the new parameters: '''MultiTexParamX''' (2 values), and '''MultiTexParam0''' and '''MultiTexParam1''' (each two pairs of x and y values).


<pre>
Below I've included values for a sample of models that use multitextured particles, along with some other parameters from the same particle emitter structure. You'll note that some of the texture tile rotation values are also unusual, as they are expected to be -1, 0 or 1.
if( b.nTimes == 0 )
return;


for(size_t j=0; j < b.nTimes; j++) {
Only particles that have multitexturing flagged are included, as the rest always seem to have zero for these parameters.
AnimationBlockHeader* pHeadTimes = (AnimationBlockHeader*)(f.getBuffer() + b.ofsTimes + j*sizeof(AnimationBlockHeader));
uint32 *ptimes = (uint32*)(f.getBuffer() + pHeadTimes->ofsEntrys);
for (size_t i=0; i < pHeadTimes->nEntrys; i++)
times[j].push_back(ptimes[i]);
}


// keyframes
for(size_t j=0; j < b.nKeys; j++) {
AnimationBlockHeader* pHeadKeys = (AnimationBlockHeader*)(f.getBuffer() + b.ofsKeys + j*sizeof(AnimationBlockHeader));


D *keys = (D*)(f.getBuffer() + pHeadKeys->ofsEntrys);
{| style="background:#FCFCFC ; color:black; text-align:left;"
switch (type) {
!! width="60" | Blend !! width="60" | Emitter !! width="80" |Texture !! width="200" colspan = "2" style="background: #CCCCCC" | MultitexParamX !! width="400"  colspan = "4" style="background: #DDDDDD" | MultitexParam0 !! width="400"  colspan = "4" style="background: #EEEEEE" | MultitexParam1
case INTERPOLATION_NONE:
|-
case INTERPOLATION_LINEAR:
| '''Type''' || '''Type''' || '''Tile Rotat''' || '''[0]''' || '''[1]''' || '''[0].x''' || '''[0].y'''  || '''[1].x''' || '''[1].y''' || '''[0].x''' || '''[0].y''' || '''[1].x''' || '''[1].y'''
for (size_t i = 0; i < pHeadKeys->nEntrys; i++)
|-
data[j].push_back(Conv::conv(keys[i]));
| colspan="13" | ''moosemount.m2''
break;
|-
case INTERPOLATION_HERMITE:
| 7 || 2 || 7 || 0.1875 || 0.09375 || 0.0234375 || 0.0234375 || -0.0136719 || -0.0136719 || 0.00585938 || 0.00585938 || 0.00585938 || 0.00585938
for (size_t i = 0; i < pHeadKeys->nEntrys; i++) {
|-
data[j].push_back(Conv::conv(keys[i*3]));
| 2 || 2 || 4 || 0.5 || 0.6875 || 0 || 0.138438 || 0 || 0.138438 || 0.0488281 || 0.0488281 || 0.0234375 || 0.0234375
in[j].push_back(Conv::conv(keys[i*3+1]));
|-
out[j].push_back(Conv::conv(keys[i*3+2]));
| 2 || 1 || 4 || 0.5 || 0.6875 || 0 || 0.0996094 || 0 || 0.0488281 || 0.00976562 || 0.00976562 || 0.00390625 || 0.00390625
}
|-
break;
| colspan="13" | ''saber2mount.m2''
}
|-
}
| 4 || 1 || 0 || 0.78125 || 1 || 0 || 0.0996094 || 0 || 0 || 0 || 0 || 0 || 0.0996094
</pre>
|-
| 4 || 1 || 0 || 0.375 || 0.28125 || 0 || 0.0996094 || 0 || 0 || 0 || 0 || 0 || 0.0996094
|-
| colspan="13" | ''ironhordeclefthoof.m2''
|-
| 7 || 1 || 1 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0.0585938 || 0.0585938 || 0.0488281 || 0.0488281
|-
| colspan="13" | ''ironhordeelekk.m2''
|-
| 7 || 1 || 1 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0.0585938 || 0.0585938 || 0.0488281 || 0.0488281
|-
| colspan="13" | ''ironhordewolf.m2''
|-
| 2 || 1 || 0 || 0.09375 || 0.1875 || 0.0292969 || 0.0292969 || -0.0292969 || 0.0292969 || 0.00390625 || 0.00390625 || 0.00390625 || 0.00390625
|-
| 7 || 1 || 1 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0.0585938 || 0.0585938 || 0.0488281 || 0.0488281
|-
| colspan="13" | ''archimonde3.m2''
|-
| 7 || 1 || 5 || 0.5 || 0.25 || 0 || 0.199219 || 0 || 0.199219 || 0 || 0.138438 || 0 || 0.138438
|-
| colspan="13" | ''voidcaller_v2.m2''
|-
| 2 || 2 || -3 || 1 || 1.375 || 0 || -0.199219 || 0 || -0.298828 || 0.0996094 || 0.0234375 || 0.138438 || 0.0488281
|-
| 2 || 2 || -1 || 0.5 || 0.6875 || 0 || 0.0488281 || 0 || 0.0742188 || 0.0234375 || 0.0234375 || 0.00390625 || 0.00390625
|-
| 7 || 2 || 2 || 1 || 0.5 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0
|-
| 7 || 2 || 0 || 0.5 || 0.1875 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0
|-
| 7 || 1 || 0 || 0.5 || 0.1875 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0
|-
| colspan="13" | ''lavahorse.m2''
|-
| 7 || 1 || 5 || 0.5 || 0.25 || 0 || 0.199219 || 0 || 0.199219 || 0 || 0.138438 || 0 || 0.138438
|-
| 4 || 1 || 0 || 0.25 || 0.5 || 0 || 0.00976562 || 0 || 0.0195312 || 0.00195312 || 0.00195312 || 0.00195312 || 0.00195312
|-
| colspan="13" | ''corehound2.m2''
|-
| 7 || 1 || 0 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0 || 0.0488281 || 0 || 0.0488281
|-
| 4 || 1 || 0 || 0.25 || 0.5 || 0 || 0.00976562 || 0 || 0.0195312 || 0.00195312 || 0.00195312 || 0.00195312 || 0.00195312
|-
| colspan="13" | ''dreadravenwarbirdfel.m2''
|-
| 4 || 1 || 0 || 0.25 || 0.5 || 0 || 0.00976562 || 0 || 0.0195312 || 0.00195312 || 0.00195312 || 0.00195312 || 0.00195312
|-
| 7 || 1 || 0 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0 || 0.0488281 || 0 || 0.0488281
|-
| colspan="13" | ''dreadravenwarbirdsun.m2''
|-
| 4 || 1 || 0 || 0.25 || 0.5 || 0 || 0.00976562 || 0 || 0.0195312 || 0.00195312 || 0.00195312 || 0.00195312 || 0.00195312
|-
| 7 || 1 || 0 || 0.25 || 0.4375 || 0 || 0.298828 || 0 || 0.199219 || 0 || 0.0488281 || 0 || 0.0488281
|}


modelheaders.h
-- [[User:Wain|Wain]] ([[User talk:Wain|talk]]) 14:57, 4 November 2015 (UTC)


  struct AnimationBlockHeader
Note that all the above MultitexParamX values are exact fractions of 32 (0.4375 = 14/32, etc.). This seems to be a complicated way of storing info that could be just represented as a simple uint8. -- [[User:Wain|Wain]] ([[User talk:Wain|talk]]) 03:15, 4 February 2016 (UTC)
  {
    uint32 nEntrys;
    uint32 ofsEntrys;
  };
 
Igor:
Yeap, it does work but not for all animations. The pHeadTimes->ofsEntrys can be 0 or an offset that points to absurd timestamps, same for keyframes. For nKeys/nTimes even by 3 or nope as well. Be honest, we don't know how to solve this puzzle ;)
 
== Deleted Blocks ==
=== Block D ===
 
*'''nD records of (int16, int16) starting at ofsD'''
 
Maybe a lookup table for animations? Since the numbers happen to be in fixed positions. The first short seems to increase with the position for models with all animations (like characters), the second seems to be flags or a modifier? Or something.


== Blend values ==


Contain indices into the texture animations list, or -1 meaning a static texture.
Those arrays were retrieved from client
char* blendModes[14] = {
    "Blend_Opaque",           //0
    "Blend_AlphaKey",          //1
    "Blend_Alpha",            //2
    "Blend_Add",              //3
    "Blend_Mod",              //4
    "Blend_Mod2x",            //5
    "Blend_ModAdd",            //6
    "Blend_InvSrcAlphaAdd",    //7
    "Blend_InvSrcAlphaOpaque", //8
    "Blend_SrcAlphaOpaque",    //9
    "Blend_NoAlphaAdd",        //10
    "Blend_ConstantAlpha",    //11
    "Blend_Screen",            //12
    "Blend_BlendAdd"          //13
}
uint64 sourceRGBBlendFactorEnum[14]  = {
    1,            //0
    1,            //1
    4,            //2
    4,            //3
    6,            //4
    6,            //5
    6,            //6
    5,            //7
    5,            //8
    4,            //9
    1,            //10
    0x0B,        //11
    7,            //12
    1            //13
}
uint64 destRGBBlendFactorEnum[14] = {
    0,          //0
    0,          //1
    5,          //2
    1,          //3
    0,          //4
    2,          //5
    1,          //6
    1,          //7
    0,          //8
    0,          //9
    1,          //10
    0x0C,        //11
    1,          //12
    5            //13
}
uint64 sourceAlphaBlendFactorEnum[14] = {
    1,            //0
    1,            //1
    1,            //2
    0,            //3
    8,            //4
    8,            //5
    8,            //6
    5,            //7
    5,            //8
    4,            //9
    0,            //10
    0x0D,        //11
    1,            //12
    1            //13
}
uint64 destAlphaBlendFactorEnum[14] = {
    0,            //0
    0,            //1
    5,            //2
    1,            //3
    0,            //4
    4,            //5
    1,            //6
    1,            //7
    0,            //8
    0,            //9
    1,            //10
    0x0E,        //11
    0,            //12
    5            //13
  }


=== Texture animations ===
I think the lower 5 bits of GxBlendStateDesc(where this comes from) is index into this array. So based on info from notes in https://wowdev.wiki/M2/WotLK#Render_flags the blend modes are mapped this way:
  0 - Blend_Opaque(0),
  1 - Blend_AlphaKey(1),
  2 - Blend_Alpha(2),
  3 - Blend_NoAlphaAdd(10),
  4 - Blend_Add(3)
  5 - Blend_Mod(4)
  6 - Blend_Mod2x(5)
  7 - Blend_BlendAdd(13)


*'''This block contains definitions for texture animations,''' for example, flowing water or lava in some models. The keyframe values are used in the texture transform matrix.
I this assumption, it's a matter of correlation between numbers and blend modes
{| class="wikitable sortable"
|-
!
! blendMode
! RenderFlag blend
! Src Color
! Dest Color
! Src Alpha
! Dest Alpha
|-
| 0
| Blend_Opaque
| 0
| 1
| 0
| 1
| 0
|-
| 1
| Blend_AlphaKey
| 1
| 1
| 0
| 1
| 0
|-
| 2
| Blend_Alpha
| 2
| 4
| 5
| 1
| 5
|-
| 3
| Blend_Add
| 4
| 4
| 1
| 0
| 1
|-
| 4
| Blend_Mod
| 5
| 6
| 0
| 8
| 0
|-
| 5
| Blend_Mod2x
| 6
| 6
| 2
| 8
| 4
|-
| 6
| Blend_ModAdd
| -1
| 6
| 1
| 8
| 1
|-
| 7
| Blend_InvSrcAlphaAdd
| -1
| 5
| 1
| 5
| 1
|-
| 8
| Blend_InvSrcAlphaOpaque
| -1
| 5
| 0
| 5
| 0
|-
| 9
| Blend_SrcAlphaOpaque
| -1
| 4
| 0
| 4
| 0
|-
| 10
| Blend_NoAlphaAdd
| 3
| 1
| 1
| 0
| 1
|-
| 11
| Blend_ConstantAlpha
| -1
| 11
| 12
| 13
| 14
|-
| 12
| Blend_Screen
| -1
| 7
| 1
| 1
| 0
|-
| 13
| Blend_BlendAdd
| 7
| 1
| 5
| 1
| 5
|}


nTexAnims records of 0x54 bytes starting at ofsTexAnims, followed by data referenced in these records.
Based on info from article my current guess for values in this table is:
'''Offset Type Description'''
<code>
0x00 AnimationBlock (float, float, float) Translation
#define GL_ZERO                            0
0x1C AnimationBlock (float, float, float ???) Rotation?
#define GL_ONE                            1
0x38 AnimationBlock (float, float, float) Scaling?
#define GL_SRC_COLOR                      2
#define GL_ONE_MINUS_SRC_COLOR            3
#define GL_SRC_ALPHA                      4
#define GL_ONE_MINUS_SRC_ALPHA            5
#define GL_DST_ALPHA                      6
#define GL_ONE_MINUS_DST_ALPHA            7
#define GL_DST_COLOR                      8
#define GL_ONE_MINUS_DST_COLOR            9
#define GL_SRC_ALPHA_SATURATE              10
#define GL_CONSTANT_COLOR                  11
#define GL_ONE_MINUS_CONSTANT_COLOR        12
#define GL_CONSTANT_ALPHA                  13
#define GL_ONE_MINUS_CONSTANT_ALPHA        14
</code>
{| class="wikitable sortable"
|-
!
! blendMode
! RenderFlag blend
! Src Color
! Dest Color
! Src Alpha
! Dest Alpha
|-
| 0
| Blend_Opaque
| 0
| GL_ONE
| GL_ZERO
| GL_ONE
| GL_ZERO
|-
| 1
| Blend_AlphaKey
| 1
| GL_ONE
| GL_ZERO
| GL_ONE
| GL_ZERO
|-
| 2
| Blend_Alpha
| 2
| GL_SRC_ALPHA
| GL_ONE_MINUS_SRC_ALPHA
| GL_ONE
| GL_ONE_MINUS_SRC_ALPHA
|-
| 3
| Blend_Add
| 4
| GL_SRC_ALPHA
| GL_ONE
| GL_ZERO
| GL_ONE
|-
| 4
| Blend_Mod
| 5
| GL_DST_ALPHA
| GL_ZERO
| GL_DST_COLOR
| GL_ZERO
|-
| 5
| Blend_Mod2x
| 6
| GL_DST_ALPHA
| GL_SRC_COLOR
| GL_DST_COLOR
| GL_SRC_ALPHA
|-
| 6
| Blend_ModAdd
| -1
| GL_DST_ALPHA
| GL_ONE
| GL_DST_COLOR
| GL_ONE
|-
| 7
| Blend_InvSrcAlphaAdd
| -1
| GL_ONE_MINUS_SRC_ALPHA
| GL_ONE
| GL_ONE_MINUS_SRC_ALPHA
| GL_ONE
|-
| 8
| Blend_InvSrcAlphaOpaque
| -1
| GL_ONE_MINUS_SRC_ALPHA
| GL_ZERO
| GL_ONE_MINUS_SRC_ALPHA
| GL_ZERO
|-
| 9
| Blend_SrcAlphaOpaque
| -1
| GL_SRC_ALPHA
| GL_ZERO
| GL_SRC_ALPHA
| GL_ZERO
|-
| 10
| Blend_NoAlphaAdd
| 3
| GL_ONE
| GL_ONE
| GL_ZERO
| GL_ONE
|-
| 11
| Blend_ConstantAlpha
| -1
| GL_CONSTANT_COLOR
| GL_ONE_MINUS_CONSTANT_COLOR
| GL_CONSTANT_ALPHA
| GL_ONE_MINUS_CONSTANT_ALPHA
|-
| 12
| Blend_Screen
| -1
| GL_ONE_MINUS_DST_ALPHA
| GL_ONE
| GL_ONE
| GL_ZERO
|-
| 13
| Blend_BlendAdd
| 7
| GL_ONE
| GL_ONE_MINUS_SRC_ALPHA
| GL_ONE
| GL_ONE_MINUS_SRC_ALPHA
|}


The three subrecords specify texture transforms. Translation seems to work, producing nice flowing lava and waterfalls.
(updated using fallenoak's findings)

Latest revision as of 20:06, 21 November 2016

Finished for Build 8820 now. Post changes here first! And please pay attention to the style when you add something.. --schlumpf_ 00:53, 23 August 2008 (CEST)

Deleted Blocks

Block D

  • nD records of (int16, int16) starting at ofsD

Maybe a lookup table for animations? Since the numbers happen to be in fixed positions. The first short seems to increase with the position for models with all animations (like characters), the second seems to be flags or a modifier? Or something.


Contain indices into the texture animations list, or -1 meaning a static texture.


Render Flags

Please forgive any ignorance I show here as I'm not a professional programmer. I'm just trying to help improve Wow Model Viewer, which has very few staff left and these pages have been invaluable for understanding it :) I just wanted to mention something that confused me and I'm not sure if it needs correcting...

The Render Flags section of this page has two different tables for blend modes, with no mention of what the difference is. Is one out of date? The settings they recommend are different for a few modes, but they agree on others. I also tried them out in WMV and found that blend mode 1 is not working right with the settings from the tables (sections are appearing completely invisible when they shouldn't be) so maybe it's out of date in both, or there's something I'm not understanding. Perhaps it's meant to be used in conjunction with GL_ALPHA_TEST or glAlphaFunc() or something.

Thanks for all your work here! :)

- Wain

  • the second table was created by relax by tracing directx stuff in the MoP client, the first one was later created by schlumpf based on reverse engineering the WoD beta client. The first table assumes alpha test to be the same, the second one lists them separate. there might be errors in both, tbh. feel free to fix them if you find them, or come to quakenet#modcraft to discuss them. :) --Schlumpf (talk) 16:47, 14 October 2015 (UTC)
  • Aha! Thanks very much :) I'll experiment with the modes more and see what I can find.

-- Wain


Particle Emitters

I'm not yet sure what to do with the new parameters: MultiTexParamX (2 values), and MultiTexParam0 and MultiTexParam1 (each two pairs of x and y values).

Below I've included values for a sample of models that use multitextured particles, along with some other parameters from the same particle emitter structure. You'll note that some of the texture tile rotation values are also unusual, as they are expected to be -1, 0 or 1.

Only particles that have multitexturing flagged are included, as the rest always seem to have zero for these parameters.


Blend Emitter Texture MultitexParamX MultitexParam0 MultitexParam1
Type Type Tile Rotat [0] [1] [0].x [0].y [1].x [1].y [0].x [0].y [1].x [1].y
moosemount.m2
7 2 7 0.1875 0.09375 0.0234375 0.0234375 -0.0136719 -0.0136719 0.00585938 0.00585938 0.00585938 0.00585938
2 2 4 0.5 0.6875 0 0.138438 0 0.138438 0.0488281 0.0488281 0.0234375 0.0234375
2 1 4 0.5 0.6875 0 0.0996094 0 0.0488281 0.00976562 0.00976562 0.00390625 0.00390625
saber2mount.m2
4 1 0 0.78125 1 0 0.0996094 0 0 0 0 0 0.0996094
4 1 0 0.375 0.28125 0 0.0996094 0 0 0 0 0 0.0996094
ironhordeclefthoof.m2
7 1 1 0.25 0.4375 0 0.298828 0 0.199219 0.0585938 0.0585938 0.0488281 0.0488281
ironhordeelekk.m2
7 1 1 0.25 0.4375 0 0.298828 0 0.199219 0.0585938 0.0585938 0.0488281 0.0488281
ironhordewolf.m2
2 1 0 0.09375 0.1875 0.0292969 0.0292969 -0.0292969 0.0292969 0.00390625 0.00390625 0.00390625 0.00390625
7 1 1 0.25 0.4375 0 0.298828 0 0.199219 0.0585938 0.0585938 0.0488281 0.0488281
archimonde3.m2
7 1 5 0.5 0.25 0 0.199219 0 0.199219 0 0.138438 0 0.138438
voidcaller_v2.m2
2 2 -3 1 1.375 0 -0.199219 0 -0.298828 0.0996094 0.0234375 0.138438 0.0488281
2 2 -1 0.5 0.6875 0 0.0488281 0 0.0742188 0.0234375 0.0234375 0.00390625 0.00390625
7 2 2 1 0.5 0 0 0 0 0 0 0 0
7 2 0 0.5 0.1875 0 0 0 0 0 0 0 0
7 1 0 0.5 0.1875 0 0 0 0 0 0 0 0
lavahorse.m2
7 1 5 0.5 0.25 0 0.199219 0 0.199219 0 0.138438 0 0.138438
4 1 0 0.25 0.5 0 0.00976562 0 0.0195312 0.00195312 0.00195312 0.00195312 0.00195312
corehound2.m2
7 1 0 0.25 0.4375 0 0.298828 0 0.199219 0 0.0488281 0 0.0488281
4 1 0 0.25 0.5 0 0.00976562 0 0.0195312 0.00195312 0.00195312 0.00195312 0.00195312
dreadravenwarbirdfel.m2
4 1 0 0.25 0.5 0 0.00976562 0 0.0195312 0.00195312 0.00195312 0.00195312 0.00195312
7 1 0 0.25 0.4375 0 0.298828 0 0.199219 0 0.0488281 0 0.0488281
dreadravenwarbirdsun.m2
4 1 0 0.25 0.5 0 0.00976562 0 0.0195312 0.00195312 0.00195312 0.00195312 0.00195312
7 1 0 0.25 0.4375 0 0.298828 0 0.199219 0 0.0488281 0 0.0488281

-- Wain (talk) 14:57, 4 November 2015 (UTC)

Note that all the above MultitexParamX values are exact fractions of 32 (0.4375 = 14/32, etc.). This seems to be a complicated way of storing info that could be just represented as a simple uint8. -- Wain (talk) 03:15, 4 February 2016 (UTC)

Blend values

Those arrays were retrieved from client

char* blendModes[14] = {
    "Blend_Opaque",            //0
    "Blend_AlphaKey",          //1
    "Blend_Alpha",             //2
    "Blend_Add",               //3
    "Blend_Mod",               //4
    "Blend_Mod2x",             //5
    "Blend_ModAdd",            //6
    "Blend_InvSrcAlphaAdd",    //7
    "Blend_InvSrcAlphaOpaque", //8
    "Blend_SrcAlphaOpaque",    //9
    "Blend_NoAlphaAdd",        //10
    "Blend_ConstantAlpha",     //11
    "Blend_Screen",            //12
    "Blend_BlendAdd"           //13
}
uint64 sourceRGBBlendFactorEnum[14]   = {
    1,            //0
    1,            //1
    4,            //2
    4,            //3
    6,            //4
    6,            //5
    6,            //6
    5,            //7
    5,            //8
    4,            //9
    1,            //10
    0x0B,         //11
    7,            //12
    1             //13
}
uint64 destRGBBlendFactorEnum[14] = {
    0,           //0
    0,           //1
    5,           //2
    1,           //3
    0,           //4
    2,           //5
    1,           //6
    1,           //7
    0,           //8
    0,           //9
    1,           //10
    0x0C,        //11
    1,           //12
    5            //13
}
uint64 sourceAlphaBlendFactorEnum[14] = {
    1,            //0
    1,            //1
    1,            //2
    0,            //3
    8,            //4
    8,            //5
    8,            //6
    5,            //7
    5,            //8
    4,            //9
    0,            //10
    0x0D,         //11
    1,            //12
    1             //13
}
uint64 destAlphaBlendFactorEnum[14] = {
    0,            //0
    0,            //1
    5,            //2
    1,            //3
    0,            //4
    4,            //5
    1,            //6
    1,            //7
    0,            //8
    0,            //9
    1,            //10
    0x0E,         //11
    0,            //12
    5             //13
 }

I think the lower 5 bits of GxBlendStateDesc(where this comes from) is index into this array. So based on info from notes in https://wowdev.wiki/M2/WotLK#Render_flags the blend modes are mapped this way:

 0 - Blend_Opaque(0),
 1 - Blend_AlphaKey(1),
 2 - Blend_Alpha(2),
 3 - Blend_NoAlphaAdd(10),
 4 - Blend_Add(3)
 5 - Blend_Mod(4)
 6 - Blend_Mod2x(5)
 7 - Blend_BlendAdd(13)

I this assumption, it's a matter of correlation between numbers and blend modes

blendMode RenderFlag blend Src Color Dest Color Src Alpha Dest Alpha
0 Blend_Opaque 0 1 0 1 0
1 Blend_AlphaKey 1 1 0 1 0
2 Blend_Alpha 2 4 5 1 5
3 Blend_Add 4 4 1 0 1
4 Blend_Mod 5 6 0 8 0
5 Blend_Mod2x 6 6 2 8 4
6 Blend_ModAdd -1 6 1 8 1
7 Blend_InvSrcAlphaAdd -1 5 1 5 1
8 Blend_InvSrcAlphaOpaque -1 5 0 5 0
9 Blend_SrcAlphaOpaque -1 4 0 4 0
10 Blend_NoAlphaAdd 3 1 1 0 1
11 Blend_ConstantAlpha -1 11 12 13 14
12 Blend_Screen -1 7 1 1 0
13 Blend_BlendAdd 7 1 5 1 5

Based on info from article my current guess for values in this table is:

  1. define GL_ZERO 0
  2. define GL_ONE 1
  3. define GL_SRC_COLOR 2
  4. define GL_ONE_MINUS_SRC_COLOR 3
  5. define GL_SRC_ALPHA 4
  6. define GL_ONE_MINUS_SRC_ALPHA 5
  7. define GL_DST_ALPHA 6
  8. define GL_ONE_MINUS_DST_ALPHA 7
  9. define GL_DST_COLOR 8
  10. define GL_ONE_MINUS_DST_COLOR 9
  11. define GL_SRC_ALPHA_SATURATE 10
  12. define GL_CONSTANT_COLOR 11
  13. define GL_ONE_MINUS_CONSTANT_COLOR 12
  14. define GL_CONSTANT_ALPHA 13
  15. define GL_ONE_MINUS_CONSTANT_ALPHA 14

blendMode RenderFlag blend Src Color Dest Color Src Alpha Dest Alpha
0 Blend_Opaque 0 GL_ONE GL_ZERO GL_ONE GL_ZERO
1 Blend_AlphaKey 1 GL_ONE GL_ZERO GL_ONE GL_ZERO
2 Blend_Alpha 2 GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_ONE GL_ONE_MINUS_SRC_ALPHA
3 Blend_Add 4 GL_SRC_ALPHA GL_ONE GL_ZERO GL_ONE
4 Blend_Mod 5 GL_DST_ALPHA GL_ZERO GL_DST_COLOR GL_ZERO
5 Blend_Mod2x 6 GL_DST_ALPHA GL_SRC_COLOR GL_DST_COLOR GL_SRC_ALPHA
6 Blend_ModAdd -1 GL_DST_ALPHA GL_ONE GL_DST_COLOR GL_ONE
7 Blend_InvSrcAlphaAdd -1 GL_ONE_MINUS_SRC_ALPHA GL_ONE GL_ONE_MINUS_SRC_ALPHA GL_ONE
8 Blend_InvSrcAlphaOpaque -1 GL_ONE_MINUS_SRC_ALPHA GL_ZERO GL_ONE_MINUS_SRC_ALPHA GL_ZERO
9 Blend_SrcAlphaOpaque -1 GL_SRC_ALPHA GL_ZERO GL_SRC_ALPHA GL_ZERO
10 Blend_NoAlphaAdd 3 GL_ONE GL_ONE GL_ZERO GL_ONE
11 Blend_ConstantAlpha -1 GL_CONSTANT_COLOR GL_ONE_MINUS_CONSTANT_COLOR GL_CONSTANT_ALPHA GL_ONE_MINUS_CONSTANT_ALPHA
12 Blend_Screen -1 GL_ONE_MINUS_DST_ALPHA GL_ONE GL_ONE GL_ZERO
13 Blend_BlendAdd 7 GL_ONE GL_ONE_MINUS_SRC_ALPHA GL_ONE GL_ONE_MINUS_SRC_ALPHA

(updated using fallenoak's findings)