This file describes the fur for the creature.
It contains two main sections "radeon" and "hybrid". These names are misnomers.. it isn't
really specific to the radeon, I'm pretty sure it just pertains to more powerful cards. The
hybrid section simply counts much fewer hair objects, seemingly to provide fur for less
powerful cards. It is possible that this "hybrid" section can be entirely ignored. The vast
majority of people will have powerful cards now, and alot of work can be spared by not
creating an entire second fur outline for the few people with less powerful video cards.
The movement of fur on the body for each of the body morphs is also described in arrays
that move it around to follow the body geometry.
I'm skipping the outline of the 'hybrid' section. Note that if you do want to edit this,
many of the numbers or arrays are not specified in this section (like the list of body
parts). I assume this section simply uses the appropriate array from the actual 'radeon'
section instead of duplicating it. (This seems odd.. most other places in these files are
not arranged for space efficiency, why do it here...)
Though there are parts where I say things like, "If you remove values here, bad stuff
happens!" that doesn't mean you *can't* do it in all cases. You will just need to make
further adjustments to solve the problems. Like, if you remove body parts from the
material's body-part array, you'll need to re-assign or delete all the hair attached to
the part, re-organize the rotation/translation parameters in the hair section arrays,
....
FILE HEADER:
String[40]
FileHeader for the file. Usually just "LionheadCreature"
dword[1]
???? - Count of 4? If this is changed, the game crashes. Seems to be the same for
all creatures.
dword[1]
I think this may just be some sort of version number. It seems to have no effect,
however, it must remain "9035"
SECTION 1 - "Radeon"
String[32]
Name of the section
dword[1]
Size of this section in bytes
dword[1] - "MORPH_COUNT"
number of body morphs for this creature/model
Stringarray[MORPH_COUNT]
String[32]
Each string is the name of a morph, like "fat"
dword[1] - "MORALITY_COUNT"
number of 'morality' morphs. (Note 'gorilla' has 0. It is possible to have none. In
this case, there are no moarilty strings or other related arrays)
Stringarray[MORALITY_COUNT]
String[32]
Eachs string is the name of the moralities, usually "evil" , "good"
dword[1]
???????????? - Count of 3. All creatures have a count of 3 here. Changing it to 0-2
causes hair to not be rendered. Anything above 3 creates a possibility for the game
to crash.
dword[1] - "BODY_PART_MAX"
The total number of body parts in the model (hip, chest, toes, etc..)
dword[1]
The number of materials per major section (repeat the "material" section below this
number of times).
Material
There can be multiple materials in each section
dword[1]
???????????? - Count of 1. I'm *guessing* that this specifies the number of
textures/actual materials (hair-ribbon areas) in this hair section. All creature's
material sections always have this set to 1 (even in the 'mutiple' sections).
UnknownChars[384]
Material Descriptions. Currently Unknown format. 384 bytes long. This seems to
actully have no effect. This array can be set to all 0's and nothing changes.
I think this array is simply skipped.
dword[1] - "BODY_PART_MATAPPLIED_COUNT"
Number of body parts (from 0 to BODY_PART_MAX) this material is applied to.
dword[BODY_PART_MATAPPLIED_COUNT]
List of body parts in the range of 0 to BODY_PART_MAX that this material is placed
on. Most arrays seem to list 'extra' parts; parts that do not actually have hair on
them. Removing parts from this list causes the hair attached to that part to not be
rendered, OR (since parts are referenced as an index into this array) causes hair
to rotate/translate to the incorrect body parts).
dword[1] - "RIBBON_SUBARRAY_SIZE"
The size in bytes of each sub-array in the main hair-ribbon array (uually 36).
dword[1] - "RIBBON_SUBARRAY_COUNT"
The number of sub-arrays in the main hair-ribbon array
dword[1]
The size in bytes of the hair-ribbon array
Hair-Ribbon array struct - "struct:hair_ribbon"
*******
So, this needs explanation. To have a better idea of how this
works, look at the pictures inside of the t_strand.dds files. Notice
that they have an alpha channel.. look at the mask created by this
alpha channel. Notice there are 7 lines of hair, each line has 12
hair-types. Hairs can be up to 7 'sections' in length.
Evidently, this works by describing hair
in varying sizes, directions, colors, luminosity. The hairs are
described by sections. The longer hairs have up to 7 sections from
the base to the tip. Each hair section is described by TWO entries,
the values and meanings of some of the variables being averaged.
The longest hairs are described by 14 entries (7 sections). This
means that, for instance, for the second 'section' of a long hair
ribbon, you can make the darkness variable either the same for both
entries describing this section, making it very dark or very light,
or you can make the two darkness numbers different and the color
will be the average of these two ( grey instead of light or dark ).
float[3]
Normal describing the direction the hair-ribbon points. This is
in 'model-world coordinate' space, not relative to the
perpindicular placement of on the mesh. A normal of 0,0,0 seems
to point 'back' and 'down' at a 45 degree angle.
byte[4]
byte[1 , 4]
Note this is byte 1 and 4, not 1 through 4. These seem to
describe how much of the ambient light is taken in by the
hair section. 0 is little, higher numbers are more. This
does NOT mean 'darker' or 'lighter.' If the ambient light
is dark, the highlight is dark, and so forth. This is not
the 'directed' light, just the ambient light. For instance,
ribbons with a high number here will pick up a strong
orange glow duing sunsets *no matter* the direction the
ribbon is facing or whether it is in shadow. The directed
lights, like from sun or torches don't seem to affect the
highlight at all. Oddly, only byte 1 seems to have any
effect. If different from byte 1, there is no effect. In
all cases I see, these two bytes always match. retail
numbers used are 0, 64, 112, 147, 174, 194, 210. The
default is to make each hair section one tick higher
( 0 -> 64 -> 112 -> 147 ...). The base section is 0.
byte[2 , 3]
Information about the color, luminosity, transparency and
highlight information. I'm not quite sure how this all ends
up being done in 16 bits.. I do not understand how these
numbers are calculated... Unfortunately this is important..
Not knowing how to calculate these means that all hair
color and visibility cannot be controlled.
byte[5]
So, this works a little oddly. I'm not sure quite why or how these
numbers are caculated. This is basically a set of three numbers
which specify which body parts will affect rotation/translation of
the hair ribbon as the creature moves, inluding the interpolated
stretching and contracting of the skin. These three numbers are
seperated with two 0's. The magnitude of affect of each specified
body part is specified in the next set of numbers. In general the
body part the ribbon is actually attached to is specified in the
first number. Finally, the way the body parts are referenced is a
bit odd. All numbers are multiples of 3. They reference body parts
not directly as the body part number, but from the array of
body-parts specified in this material section above. 0 is te first
body part in this array, 3 is the second, 6 is the third, 15 is
the fifth, .... So (using numbers from the wolf), the material for
the head-hair has the body part array beginning with
[ 2 3 4 5 6 7 8 9 ...], so if the hair ribbon is on the back of
the neck, the array would probably be [ 3 0 6 0 9 ] which
references the body part 3, 4, and 5 (3=neck 4=back-neck-scruff
5=head). The movement and skin movement of these three bdy parts
will affect the movement of the ribbon. Finally, it is possible
that these are words (not dwords) instead of bytes. That would
explaing the 0's... the first 0 in the following 3-bytes would
then be part of the third number.
byte[3]
??????? - Padding? These seem to always be 0, but do in fact affect
movement of the ribbon. I think this can safely be igonred and
always set to 0.
byte[3]
These three bytes should add up to 255. These numbers define the
magnitude of the effect movement and skin movement of the body
parts specified in the 5-byte section have on this hair-ribbon's
movement. These numbers are in reverse order. The first number in
the 5-byte is affected by the third number in this set, the
second by the second, and the third byte in the 5-byte section by
the first byte in this section. If these numbers don't add up to a
total od 255, the ribbon will screw up. The numbers can be set to
0, like [ 0 0 255 ] in which case te ribbon will follow only the
first bodyart specified in the 5-byte section (usually, this will
screw up following skin movement). I'm not at all sure how these
numbers are calculated. I'm hoping it will become obvious after
decoding the other files. It may have something to do with
percentage overlap of body-part bounding boxes which I do not look
forward to calculating if is the case...
byte[1]
??????? - Padding? Alwasy 0, seems to have no effect.
byte[8]
Only the first 7 bytes are used (the retail hair-ribbon texture
files used only have 7 rows, so the 8th bit is unused). There are
only two values used, 0 and 255 (or -1). These indicate to which hair
'section' the line applies. In almost all cases, each section is
specified by two lines apiece. The order of section specification is
not obvious: [ 3 2 1 4 7 6 5 NA ]. So, for example, a 2-section hair
ribbon will usually have these as [0 0 255 0 0 0 0 0],
[0 0 255 0 0 0 0 0], [0 255 0 0 0 0 0 0], [0 255 0 0 0 0 0 0]. It
actually works to specify this out of order, but causes odd shapes in
the hair.
struct:hair_ribbon[RIBBON_SUBARRAY_COUNT]
Big, long, array of hair ribbon sections...
dword[1] - "RIBBON_COUNT"
The number of 'hair ribbons' in this material section. This is the number of ribbons,
not the number of hair sections (which is instead RIBBON_SUBARRAY_COUNT)
dword[1] - "MORPH_COUNT_PLUS_BASE"
This is the number of body morphs this model has plus 1 (for the 'base' morph).
floatarray[RIBBON_COUNT]
float[6]
Two points specified as (x,y,z) coordinates.
These are arrays of vertices that determine where the hair is placed. The coodinates use
'creature-world' coordinates, the same used to construct the model. This array describes
the placement of aech hair ribbon. Two points are specified per 'line'
(RIBBON_COUNT * (3)*(2) floats). The line formed between these two points specifies
where a hair ribbon will be placed.
floatarray[RIBBON_COUNT][MORPH_COUNT]
float[6]
Two points specified as (x,y,z) coordinates.
These arrays are similar to the array above. Each of the arrays describes the
*displacment* of each vertex for the corresponding morph. The morphs are in the order as
specified at the begining of the file where the morphs are named. There are two
point-displacment specifications per line (6 floats) which 'move' both side of the line
describing a hair ribbon.
dword[1] - "RIBBON_COUNT"
Number of hair ribbons. Identical to the one above.
dword[RIBBON_COUNT]
This is an array describing the number of 'ribbon sections' per hair ribbon. As
described above, hair can have up to 7 sections for length (usually comprised of 2 lines
apiece in the struct:hair_ribbon). In an ordered list corresponding to the order in the
struct:hair_ribbon, each dword gives the number of sections for that ribbon
dword[RIBBON_COUNT]
This array appears to describe the texture quality placed on the hair ribbon. Each
ribbon is assigned a quality number 0, 1, or 2. 0 = low, 1 = med, 2 = high. Lower
qualities look a little more fluffy, but do become obviously blurry. Usually, the short
hairs are made low quality (I assume to avoid high-quality rendering when not really
necessary)
dword[1] - "HAIR_UV_ROWS"
This is more of a guess than other values. I think this is either the number of maximum
hair sections or the number of rows of hair types as found in the t_strand.dds files
(These two numbers should generally be the same anyway). See the array notes for details.
dword[1] - "HAIR_UV_TYPES_PER_ROW"
This is more of a guess than other values. In each row of similar-length hair in the
t_strand.dds files, there are groups of hair that are very similar in appearance. I think
this number describes how many groups of similar hair on each row there are.
dword[1] - "HAIR_UV_PIECES_PER_GROUP"
This is more of a guess than other values. I think this desribes the number of individual
hair tesxtures per 'group' as defined in "HAIR_UV_TYPES_PER_ROW".
********
Rather than try to make a 'structure' for this array, I'm just going to explain how I
think it works...
lol, math
Let f(x) = Summation of 1 to x for:
([2*x] + 2) * (HAIR_UV_TYPES_PER_ROW) * (HAIR_UV_PIECES_PER_GROUP)
then:
********
------> float[ f(HAIR_UV_ROWS) ] <---------
This array describes UV points that define individual hair pieces in the hair
texture files (t_strand.dds). UV points are 'percentages' of the max 2D X,Y coordinates
dimensions of the picture file, so values range from 0 to 1 in both X,Y. The structure of
this is not completely straightforward. There are "HAIR_UV_ROWS" rows in the texture file.
I suspect the behavior of this row count is to add one hair 'section' per row in the .dds
file. For instance, the first row has one section desribed by 4 points (a box). The second
row is described by 6 points (two squares/boxes). The third row is described by 8 points
(three boxes). The 'boxes' define the hair sections that are used and referenced in the
hair length in the big "struct:hair_ribbon" above. On each row, there are
"HAIR_UV_TYPES_PER_ROW" groups of "HAIR_UV_PIECES_PER_GROUP" hairs. For example, the
retail texture files have 7 rows, 3 groups, 4 pieces-per-group. That means 7*3*4=84 hairs.
Rows 1-7 have 1-7 sections-per-hair respectively, described by (2n+2) points for a total of
840 points, described by two floating point numbers apiece = 1680 numbers, each floating
point is 4 bytes, for a total array size of 6720 bytes. incidently, the boxes are
described by a 'Z' pattern.. Top-left, Top-right, Bottom-left, Bottom-right.
dword[1] - "MORALITY_COUNT_PLUS_BASE"
I belive that this count will be "MORALITY_COUNT" + 1. This specifies the number of
different ribbon-length numbers to specify for each ribbon referenced in the following
array, one for each 'morality' plus a base number
floatarray[RIBBON_COUNT][MORALITY_COUNT_PLUS_BASE]
float[1]
This array seems to specify the length of each hair ribbon. The first array of
"RIBBON_COUNT" floats is the length of each hair ribbon in the base model, the subsequent
arrays define the hair length for each of the morailty sections (the order is determined by
the order of morailty section specificaiton in this major section's header). The maximum
length varies by the number of sections a hair ribbon has. beginning at "0.14285715" for a
two-section ribbon, each seaction added adds ~"0.14285715" more to the maximum length (some
rounding error, to be safe, add only "0.14285714") So, for instance a 7-section ribbon has
a maximum length of "0.85714289". I have no idea why these are the numbers. They don't
correspond to anything I see. I presumed they would be some sort of distance in the
hair-texture (t_strand.dds) file, but they aren't. They seem entirely arbitrary.
actual max's to 8-digit precision accounting for precision errors (starting with 2-section
ribbons) are [ 0.14285715 0.28571431 0.42857144 0.57142862 0.71428576 0.85714289 ]
dword[1] - "RIBBON_COUNT"
The number of hair ribbons. Identical to the ones above.
floatarray[RIBBON_COUNT]
float[3]
This array consists of one 3D point per-hair ribbon. The point is used to determine the
'Z' rendering of the ribbon.. In other words, which ribbons appear in 'front' of others.
Ribbons calculated to be in front will be shown to the camera, those behind will be hindden
behind those in front. It seems that the points are generally simply set to the first vertex
in the *base model* array of two-verticies-per-ribbon that create the hair ribbon positions
(the one before the other MORPH_COUNT arrays of dual-points).
dword[RIBBON_COUNT]
This array attaches each hair ribbon to a particular body part. In an ordered list accroding
to the "struct:hair_ribbon" array, the dword specifies a number found in the array of body
parts this material is attached to. The specified numbers is the 'actual' body part number,
not an index into the array of body parts, but the body part will be specified in the array.
dword[RIBBON_COUNT]
This array contains numbers that count from 0 to RIBBON_SUBARRAY_COUNT. The count follows
the ordered list of RIBBON_COUNT hair ribbons, each number for that indexed ribbon
corresponds to the index point at which the hair sections begin to be referenced in the
"struct:hair_ribbon" array. (Keep in mind that each hair section includes two
lines-per-section). For instance, if there are 3 hair ribbons 1 = 7 sections, 2 = 4 sections,
4 = 6 sections, the array would be [ 0, 14, 22 ]. The first ribbon has it's sections
beginning to be referenced at index point 0, the second at index point 14 (since the first
ribbon takes 14 lines to specify the 7 sections), the third at index 22.
dword[RIBBON_COUNT]
Related to the array directly above. This array specifies the number of hair-section lines
per hair ribbon, following the ordered list of hair ribbons in the "struct:hair_ribbon"
array. From the example above (3 hair ribbons 1 = 7 sections, 2 = 4 sections,
4 = 6 sections), the array would be [ 14, 8, 12 ].
dword[1] - "RIBBON_SUBARRAY_COUNT"
Identical to the one further up. I don't know why this is specified here.
************ Repeat material section *******************