-
Notifications
You must be signed in to change notification settings - Fork 4
Model3 3D Model Format
The Model3
format (or so it is referred to in the source of SILENT HILL 2) is the model file format used throughout SILENT HILL 2 and 3. The file type is a binary format that contains data such as the skeleton, textures etcetera. Each file has the extension .mdl
.
The first block of data is the Model's file header. It is described with the following struct:
IMPORTANT NOTE! The following are revision 3 model structures. Revision 4 (the PC version) may have slightly different data (the Part
structure, for example, is different)
struct sh2gfw_Model_Header
{
unsigned char NoTextureID;
unsigned char padc[3];
unsigned int chara_id;
unsigned int texnum;
unsigned int toTexHead_offset;
unsigned int toClutsHead_offset;
unsigned int toModel_offset;
unsigned int toKg1_offset;
unsigned int pad;
void* pTexMAN[8];
};
The offsets in this struct are absolute.
These fields have the following meaning:
Field | Description |
---|---|
NoTextureID | No Texture flag(??) |
padc[3] | Pad bytes (always 0) |
chara_id | Character ID number (used in engine to identify a character/SubCharacter ). This looks like it could also be a "type" to determine if it's a drama model or not. |
texnum | Number of textures stored in this .mdl file |
toTexHead_offset | Offset to first texture (aka text block) |
toClutsHead_offset | Offset to cluster (animation?) data |
toModel_offset | Offset to model header |
toKg1_offset | Offset to embedded KG1 file header |
pads[2] | Padding words |
void* pTexMAN[8] | Data for texman(???) |
The next struct contains information about the model data itself:
struct Model
{
unsigned int id;
unsigned int revision;
unsigned int initial_matrices_offset;
unsigned int n_skeletons;
unsigned int skeleton_structure_offset;
unsigned int n_skeleton_pairs;
unsigned int skeleton_pairs_offset;
unsigned int default_pcms_offset;
unsigned int n_vu1_parts;
unsigned int vu1_parts_offset;
unsigned int n_vu0_parts;
unsigned int vu0_parts_offset;
unsigned int n_texture_blocks;
unsigned int texture_blocks_offset;
unsigned int n_text_poses;
unsigned int text_poses_offset;
unsigned int text_pos_params_offset;
unsigned int n_cluster_nodes;
unsigned int cluster_nodes_offset;
unsigned int n_clusters;
unsigned int clusters_offset;
unsigned int n_func_data;
unsigned int func_data_offset;
unsigned int hit_offset;
unsigned int box_offset;
unsigned int flag;
unsigned int relative_matrices_offset;
unsigned int relative_transes_offset;
unsigned int reserved_1c;
unsigned int reserved_1d;
unsigned int reserved_1e;
unsigned int reserved_1f;
};
The offsets are relative to the beginning of this structure.
These fields have the following meaning:
Field | Description |
---|---|
id | Magic Number. Always 0xFFFF0003 |
revision | Version number of this .mdl . 3 on PS2, 4 on PC |
initial_matrices_offset | Offset to the initi |
n_skeletons | Number of skeletons contained in this file. It is probably more appropriate to call this the number of bones. |
skeleton_structure_offset | Offset to the root shSkeleton structure |
n_skeleton_pairs | Number of skeletons pairs (???) |
skeleton_pairs_offset | Offset to the skeleton pairs |
default_pcms_offset | ? |
n_vu1_parts | Number of VU1 parts (sent to the VU1 on the PS2) |
vu1_parts_offset | Offset to beginning of VU1 part structures (see below) |
n_vu0_parts | Number of VU1 parts (sent to the VU1 on the PS2) |
vu0_parts_offset | Offset to beginning of VU1 part structures (see below) |
n_texture_blocks | Number of textures contained within this .mdl
|
texture_blocks_offset | Offset to texture data |
n_text_poses | Pose data (???) |
text_poses_offset | Offset to pose data (???) |
text_pos_params_offset | |
n_cluster_nodes | |
cluster_nodes_offset | |
n_clusters | |
clusters_offset | |
n_func_data | |
func_data_offset | |
hit_offset | Offset to hitbox (combat hitbox?) |
box_offset | Offset to hitbox (movement hitbox?) |
flag | No idea. Some kind of information related to model in game? |
relative_matrices_offset | |
relative_transes_offset; | |
reserved_1c; | Reserved for future use |
reserved_1d; | Reserved for future use |
reserved_1e; | Reserved for future use |
The next structure of interest is a Part
header. This describes a packet of data that, on the PlayStation 2, would be sent to the VU0. The format of the actual data itself (which I assume is vertex data) is currently unknown as of now.
The structure is as follows:
struct Part
{
unsigned int size;
unsigned int type;
unsigned int packet_offset;
unsigned int packet_qwc;
unsigned int xtop;
unsigned int n_cluster_data;
unsigned int cluster_data_offset;
unsigned int n_skeletons;
unsigned int skeletons_offset;
unsigned int n_skeleton_pairs;
unsigned int skeleton_pairs_offset;
unsigned int data_skeletons_offset;
unsigned int data_skeleton_pairs_offset;
unsigned int n_textures;
unsigned int text_pos_indices_offset;
unsigned int texture_params_offset;
unsigned char shading_type;
unsigned char specular_pos;
unsigned char equipment_id;
unsigned char hoge;
unsigned char backclip;
unsigned char envmap_param;
unsigned char reserved[2];
float phong_param_a;
float phong_param_b;
float blinn_param;
unsigned int padding[3];
float diffuse[4];
float ambient[4];
float specular[4];
};
Field | Description |
---|---|
size | Size of the this packet, including header. |
type | |
packet_offset | |
packet_qwc | |
xtop | |
n_cluster_data | |
cluster_data_offset | |
n_skeletons | |
skeletons_offset | |
n_skeleton_pairs | |
skeleton_pairs_offset | |
data_skeletons_offset | |
data_skeleton_pairs_offset | |
n_textures | |
text_pos_indices_offset | |
texture_params_offset | |
shading_type | |
specular_pos | |
equipment_id | |
hoge | |
backclip | |
envmap_param | |
reserved[2] | |
phong_param_a | |
phong_param_b | |
blinn_param | |
padding[3] | |
diffuse[4] | |
ambient[4] | |
specular[4] |