BloodRayne 2 is a hack and slash game that came out around 2005 depending on the platform. While there are many mods out there, there isn't much info on the BFM object file needed to create those mods. After having some fun looking at these files and modifying them, here is what I found out. Example values are for RAYNE.BFM. The data shows the offset followed by the value and the type along with a description.
Update: I've been able to figure out some more details about the points.

BFM File Sections.

1. Header
2. Parts
3. Textures
4. Bones
5. Mesh Descriptors
6. Meshes (Points and Triangles)

1. Header

0: 6 (dword) ?
4: 1 (dword) ?
8: 22 (dword) Number of Parts
12: 95 (dword) Number of Bones
16: 2 (dword) Number of Textures
20: 4 (dword) Number of Attached Parts (guns, weapons)
24: 1 (dword)
28: 0 (dword)
32: (80 bytes) skeleton filename nil terminated

2. Parts

Offset is from start of file.

Each part descriptor is 58 bytes long. There are as many as indicated by offset 8 in the header.

This is followed by Attached Parts. There are as many as indicated by offset 20 in the header.

112: (58 bytes * Number of Parts) Part names. followed by (76 bytes * Number of Attached parts)
Each regular part is as follows.

0: Part name (30 bytes)
30: (dword) Primary bone index associated with this Part (though multiple bones are allowed per part).
34: (float * 6) Bounding box in global space of each part. (x1,y1,z1)-(x2,y2,z2).

Extra parts have the following format

0: Part name (24 bytes)
24: (dword) Primary bone index associated with this Part.
28: (float * 12)  Unknown. Looks like two bounding boxes. Perhaps original is resized.

3. Textures

Don't know too much about this. 

There as many as indicated by offset 16 in the header. Each texture descriptor is 360 bytes long. There are usually three texture names. One for color, bump and gloss. Not sure what the rest of the data is for.

4. Bones

Not exactly sure on all the details.

It starts with bone offsets in 3D (x,y,z). There are as many of these as indicated by offset 12 in the header. These offsets are relative to other bones except for the first offset which is a global offset for everything. However, you don't use it when computing the bounding boxes in the Parts Descriptor.

What follows are 6 floats per bone. Not sure what this data is yet.

This is followed by one 32bit integer for each bone. Probably a bone type since the values are all 1 or 2.

Then this follows one 32bit integer for each bone again. This time, it indicates a child bone. It's rather odd. Many bones have many children. Bone 0 has 7 children. But I can't figure out how this works yet. But for certain, the number indicated here is a child bone. The position of the child bone mentioned above is relative to its parent bone.

5. Mesh Descriptors

The very first 32bit integer indicates how many mesh descriptors that follow. These are variable size.

Each mesh descriptor is as follows:

0: (dword) 3
4: (dword) 0 texture pack
8: (dword) 1
12: (dword) 16 part index
16: (word) 0 Number of extra words to follow (if 1, 1 extra word follows. If 4, 2 extra words follow. Not sure what they are.)
18: (dword) 2
22: (dword) 26068 number of bytes in the point and triangle chunk
26: (dword) 4
30: (dword) 194 number of points in mesh
34: (dword) 206 number of triangles in mesh
38: (dword) 95 Always the same. Perhaps an end marker.

6. Mesh (Points and Triangles)

I thought this part would be simple, but it's quite involved. Luckily, the triangle are dirt easy.

Each mesh follows in the same order as their descriptors. For each mesh, you have points followed immediately by the triangles. Then you have the next mesh and so on until the end of the file.
The number of points and triangles is specified in its respective Mesh Descriptor.

Points. Each point structure can actually contain 4 points. Each of these points represent the exact same point in global space. What these "subpoints" are is defining their positions relative to the bone that affects them. Offset 80 has 4 dwords (one for each subpoint) that indicates the bone index for each of these subpoints.

Points: (128 bytes)
0: (dword) # of subpoints. Max 4 subpoints.
4: (float * 3 * 4) coordinates. Only # of subpoints are valid.
52: (float * 4) This is the weight assigned to each subpoint. Adding all four must equal to 1.0.
68: (float * 3) Normal vector. Is a unit vector.
80: (dword * 4) bone index for each point
96: (float * 2) UV coordinate into texture. Range is 0 to 1.
104: (float * 3) 3D unit vector. Binormal. Points inward to center of model.
116: (float * 3) 3D unit vector. Tangent. Inverted.

The weights are very important. In determining the final point on screen, it will use bones to deform each subpoint. Then, if there are more than 1 subpoint, it will use the weights to use a percentage of each subpoint in figuring out the final point displayed on screen. This is what I've been able to understand as I've succesfully been able to add points and triangles.   

The normal vector is also important for shading. If you're updating points, you will want to take the normal vector of all adjacent triangles, then add each axis together and normalize it. This will give you the normal for this point. It is used in determining which direction light should be reflected.

Triangles:
0: (word * 3 * triangles) just a list of three words indicating the index of the points in each triangle.

That's it. If you can fill in the other details, please leave a comment.





Leave a Reply.