// **** CYCLIC ANIMATION SHADER ****
// Contributors: Zlevir

// Based on shapekey shader by Cybertron, SinsOfSeven

struct VertexAttributes {
    uint2 position;
    uint normal; 
    uint tangent;
    uint color;
    uint texcoord;
    uint texcoord1;
};

RWStructuredBuffer<VertexAttributes> rw_buffer : register(u5);
StructuredBuffer<VertexAttributes> base : register(t50);
StructuredBuffer<VertexAttributes> shapekey : register(t51);

Texture1D<float4> IniParams : register(t120);
#define FREQ IniParams[88].x
int i8toi32(uint src);
uint i32toi8(int src);
[numthreads(1, 1, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
    uint i = threadID.x;
    VertexAttributes diff;
    float4 t1, t2;
    //diff.position = shapekey[i].position - base[i].position ;
    t1.x = f16tof32(shapekey[i].position.x >> 16) - f16tof32(base[i].position.x >> 16);
    t1.y = f16tof32(shapekey[i].position.x & 0xffff) - f16tof32(base[i].position.x & 0xffff);
    t1.z = f16tof32(shapekey[i].position.y >> 16) - f16tof32(base[i].position.y >> 16);
    t1.w = f16tof32(shapekey[i].position.y & 0xffff) - f16tof32(base[i].position.y & 0xffff);
    //diff.normal = shapekey[i].normal - base[i].normal;
    //diff.tangent = shapekey[i].tangent - base[i].tangent;

    // (0.5*(sin(TIME*(SPEED+1)*10)+1))
    //rw_buffer[i].position += diff.position*1.0;
    t2.x = f16tof32(rw_buffer[i].position.x >> 16);
    t2.y = f16tof32(rw_buffer[i].position.x & 0xffff);
    t2.z = f16tof32(rw_buffer[i].position.y >> 16);
    t2.w = f16tof32(rw_buffer[i].position.y & 0xffff);
    t2 += t1 * (0.5*(sin(FREQ*30)+1));
    rw_buffer[i].position.x = (uint)f32tof16(t2.x)<<16 | (uint)f32tof16(t2.y);
    rw_buffer[i].position.y = (uint)f32tof16(t2.z)<<16 | (uint)f32tof16(t2.w);
    //rw_buffer[i].normal += diff.normal*(0.5*(sin(FREQ*30)+1));
    //rw_buffer[i].tangent += diff.tangent*(0.5*(sin(FREQ*30)+1));
    
    t1.x = float(i8toi32(shapekey[i].normal.x & 0xff) - i8toi32(base[i].normal.x & 0xff));
    t1.y = float(i8toi32(shapekey[i].normal.x>>8 & 0xff) - i8toi32(base[i].normal.x>>8 & 0xff));
    t1.z = float(i8toi32(shapekey[i].normal.x>>16 & 0xff) - i8toi32(base[i].normal.x>>16 & 0xff));
    t1.w = float(i8toi32(shapekey[i].normal.x>>24 & 0xff) - i8toi32(base[i].normal.x>>24 & 0xff));
    t2.x = float(i8toi32(rw_buffer[i].normal.x & 0xff));
    t2.y = float(i8toi32(rw_buffer[i].normal.x>>8 & 0xff));
    t2.z = float(i8toi32(rw_buffer[i].normal.x>>16 & 0xff));
    t2.w = float(i8toi32(rw_buffer[i].normal.x>>24 & 0xff));
    t2 += t1 * ((0.5*(sin(FREQ*30)+1)));
    rw_buffer[i].normal.x = i32toi8(int(t2.w))<<24 | i32toi8(int(t2.z))<<16 | i32toi8(int(t2.y))<<8 | i32toi8(int(t2.x));
    
}

int i8toi32(uint src) {
    if (src & 0x80) {
        return src & 0x7f | 0xffffff80;
    } else {
        return src & 0x7f;
    }
}

uint i32toi8(int src) {
    if (src > 127) {
        src = 127;
    }
    if (src < -128) {
        src = -128;
    }
    return (uint)src & 0x000000ff;
}