Psycrow101 / Blender-3D-RW-Anm-plugin

Import and export RenderWare animations (.anm) into Blender 3D
31 stars 10 forks source link

Strange anm format #13

Closed alecss131 closed 3 months ago

alecss131 commented 3 months ago

game from ps2 renderware engine, developer Climax Action in rw anm files have 2 formats: 0x01 - uncompressed (36 bytes per frame) and 0x02 - compressed (22 bytes per frame) but i have format with id 0x0311, data split on two parts, first 8 bytes (time and offsets) and second part 12 bytes I don't understand what and how is stored in the second part of the data logically there should be a quaternion and a vector, but there are not enough 2 bytes for them (7x compressed floats = 14 bytes) anm file structure

struct Head{
    uint32_t type; //1B 00 00 00
    uint32_t size;
    uint32_t version; //65 00 02 1C
};

struct Ahead {
    uint32_t version; //always 00 01 00 00, gta
    uint32_t type; //always 03 11 00 00
    uint32_t count; //number of "packets"
    uint32_t flags; //always 00 00 00 00
    float length; //time length of animation
    std::array<float, 6> unknown; //looks like offset and scalar for positions from compressed anm
};

struct Data0{
    std::array<uint8_t, 4> unknown;
    float time;
};

struct Data1{
    std::array<uint8_t , 12> unknown;
};

struct File{
    Head head;
    Ahead ahead;
    std::array<Data0, ahead.count> frameData0;
    std::array<Data1, ahead.count> frameData1;
};

void uncompress(uint32_t src, float *dest){ 
    uint32_t nx = src & 0x7ff;
    uint32_t ny = (src >> 11) & 0x7ff;
    uint32_t nz = (src >> 22) & 0x3ff;
    int32_t ix = (int32_t)nx;
    int32_t iy = (int32_t)ny;
    int32_t iz = (int32_t)nz;
    dest[0] = (float)ix / 1023.0f; //half variant replace with 511.0f
    dest[1] = (float)iy / 1023.0f; //half variant replace with 511.0f
    dest[2] = (float)iz / 511.0f; //half variant replace with 255.0f
}

float decode(uint16_t value) {
    uint32_t fi = (value & 0x8000) << 16;
    if (value & 0x7fff) {
        fi |= (uint32_t)((uint32_t)(value & 0x7800) << 12) + 0x38000000;
        fi |= (uint32_t)((uint32_t)(value & 0x7ff) << 12);
    }
    return *((float*)&fi);
}

im trying decompress floats from uint16_t and decompress RwV3d from uint32_t in combination 4x uint16_t + 1x uint32_t or 3x uint16_t for xyz and restore w from this + 3x uint16_t for vector apply and not scalar and offset for translation in the end nothing comes of it link for dff and anm files (long and short) https://drive.google.com/drive/folders/1f_Ufu5BiD7tOaSYVbJuWj--lYsAMLJNT?usp=sharing

skeleton has 53 bones and looks like Screenshot_1 screen from my own animation viewer (it's faster to try different decryption options)

alecss131 commented 3 months ago

Found solution in internet

        RotCompressed1 = readUInt()
        RotCompressed2 = readUShort()
        qx = ((RotCompressed1 >> 20) - 2048.0 ) / 2047.0
        qy = (((RotCompressed1 >> 8) & 0xFFF) - 2048.0 ) / 2047.0
        qz =(((( RotCompressed1 * 16) & 0xFFF)|(RotCompressed2 >> 12)) - 2048.0 ) / 2047.0
        qw = ((RotCompressed2 & 0xFFF) - 2048.0 ) / 2047.0 
        tx = (readUShort() / 65535.0) * transScalar[0] + transOffset[0] 
        ty = (readUShort() / 65535.0) * transScalar[1] + transOffset[1] 
        tz = (readUShort() / 65535.0) * transScalar[2] + transOffset[2] 

result res1 and find some errors in my frame read code (frame order)

for i in range(frame_count)
        prevFrame = readUInt()
        time = readFloat()
        currentId = i
        prevId = currentId - prevFrame // 20

and sort frames by prevId[i] == currentId[i - 1]

Psycrow101 commented 3 months ago

@alecss131 Thanks! Added import support for this format https://github.com/Psycrow101/Blender-3D-RW-Anm-plugin/commit/e2360a37958e8460779c3a16ec8afa0325591973

image