Skip to content
Jocelyn Beedie edited this page Feb 17, 2021 · 18 revisions

A lot of data within the Node structure is dependent on the resource_id.

struct Node {
    int32_t parent_node_id; // 0 for root node
    int32_t unknown_node_ids[3];
    int32_t resource_id; // Depends on what this node is for; lighting nodes tend to use LIGHT files, particle nodes tend to use PARTICLE files, etc.
    int32_t datatype_id; // Data type (see table below)
    // if datatype_id != 0:
        NodeDataUnion node_data; // Structure depends on datatype_id; has variable size
    //
    int32_t light_id; // LIGHT file, may be 0
    int32_t hfog_id; // HFOG file, may be 0
    uint32_t userdefine_id; // USERDEFINE file, may be 0
    float floatv1[9]; // Unknown usage, related to transforms somehow
    float floatv2[9]; // Unknown usage, related to transforms somehow
    Mat4x4 local_transform;
    Vector3 local_translation;
    char junk[4];
    Quaternion local_rotation;
    Vector3 local_scale;
    char junk2[4];
    float unk1[2]; // Somehow related to sound, maybe distance attenuation? Always (0, 0) on nodes with no sound data
    uint32_t unk2_1[4]; // Graphics chunk index?
    uint32_t unk2_2[4]; // Collision chunk index?
    float unk3[4]; // Always (0, 0, 0, 1)
    uint16_t unk4[2]; // some kind of flag value?
    Mat4x4 global_transform;
    Mat4x4 global_transform_inverse;
}

NodeDataUnion

union NodeDataUnion {
    NodeDataLod lod;             // variable size
    NodeDataSkin skin;           // variable size
    NodeDataSurface surface;     // 40B
    NodeDataRotshape rotshape;   // 62B
    NodeDataMesh mesh;           // 28B
    NodeDataParticles particles; // 30B
}
struct NodeDataLod {
    int32_t path_id;
    int32_t subtype_id;
    float unk1[5];
    uint32_t num_unk2; // Always 1
    int32_t data_type; // Either "MESHDATA" or "SKEL"
    NodeDataUnion data; // variant depends on data_type
    char unk2[100]; // I'll look through this later
    int32_t node_id; // NODE reference, usually to parent
    int32_t light1_id; // LIGHT reference
    int32_t light2_id; // LIGHT reference, usually equal to light1_id
    uint32_t num_nodes; // Usually 1
    int32_t nodes[num_nodes]; // NODE reference(s)
    uint32_t num_unk3;
    uint32_t unk3[num_unk3];
}
struct NodeDataSkin {
    int32_t path_id;
    int32_t subtype_id;
    float unk1[5];
    uint32_t num_unk2;
    NodeLodSkelUnk2 unk2[num_unk2];
    int32_t unk3_id;
    uint32_t num_materials;
    NodeLodSkel_Material materials[num_materials];
    uint32_t num_unk4;
    NodeLodSkel_Unk unk4[num_unk4];
    uint32_t num_unk5;
    NodeLodSkel_Unk unk5[num_unk5];
    uint32_t num_unk6;
    NodeLodSkel_Unk unk6[num_unk6];
    uint32_t num_unk7;
    NodeLodSkelUnk7_Part1 unk7[num_unk7];
    NodeLodSkelUnk7_Part2 unk7[num_unk7];
}
struct NodeDataSurface {
    int32_t data_id;
    int32_t subtype_id;
    float data[5]; // Always {0.0, 0.0, 0.0, 1.0}
    uint32_t num_unk1;
    NodeDataSurfaceUnk unk1[num_unk1];
    uint32_t num_unk2; // Always 0
    uint32_t unk3;
}
struct NodeDataSurfaceUnk {
    char unk[104];
}
struct NodeDataRotshape {
    int32_t data_id;
    int32_t subtype_id;
    uint32_t unk1[6]; // Always {0, 0, 0, 0, 0, 1}
    uint16_t unk2; // Always 0
    char junk[28]; // first byte might not be junk? idk, this one is weird
}
struct NodeDataMesh {
    int32_t data_id;
    int32_t subtype_id;
    float data[5]; // Always {0.0, 0.0, 0.0, 0.0, 1.0}
}
struct NodeDataParticles {
    int32_t data_id;
    int32_t subtype_id;
    float unk1[5];
    uint16_t unk2;
}

Lod data structure

struct NodeLodSkelUnk2 {
    int32_t unk_ids[5]; // IDs of some kind
    int32_t extra_data_id; // If non-zero, then this structure includes extra data.
    // if extra_data_id != 0:
    NodeLodSkelUnk2ExtraDataUnion extra_data;
    // end if
    Vector3 local_translation;
    char junk[4];
    Quaternion local_rotation;
    Vector3 local_scale;
    float floatv1[9]; // Somehow related to transform
    float floatv2[9]; // Somehow related to transform
    Mat4x4 tx1;
    Mat4x4 tx2;
}
union NodeLodSkelUnk2ExtraDataUnion {
    NodeLodSkelUnk2ExtraData_UserDefine userdefine;
}
struct NodeLodSkelUnk2ExtraData_UserDefine {
    int32_t userdefine_type; // Usually SKELDEFINE
    int32_t userdefine_type; // Usually SKELDEFINE
    uint32_t length;
    char usedefine[length];
}
struct NodeLodSkel_Material {
    int32_t filetype_id; // Same as in archive; always "MATERIAL" here.
    int32_t filename_id; // Same as in archive
    int32_t subtype_id; // Same as in archive
    Material material;
}
struct NodeLodSkel_Unk {
    float unk1[4];
    int32_t unk2_id; // ID
    int32_t unk3_id; // ID
}
struct NodeLodSkelUnk7_Part1 {
    int32_t datatype_id; // Generally  either"MESHDATA" or "SURFACEDATAS"
    NodeDataUnion data; // Depends on datatype_id
}
struct NodeLodSkelUnk7_Part2 {
    uint32_t num_ids;
    int32_t ids[num_ids];
}

See: https://github.com/Jellonator/chum-world/wiki/MATERIAL

General substructure info

data_id is often the hash of the string that subtype_id hashes, but with "_DATA" concatenated to the end; for example, if subtype_id is the hash of "GOOBUBBLEPOP", then data_id is the hash of "GOOBUBBLEPOP_DATA".

Resource Type datatype_id (hash of)
SURFACE SURFACEDATA
SKIN SKEL
ROTSHAPE ROTSHAPEDATA
LOD LODDATA
MESH MESHDATA
PARTICLES PARTICLESDATA
Clone this wiki locally