//objmc
//https://github.com/Godlander/objmc

#define PI 3.1415926535897932

ivec4 getmeta(ivec2 topleft, int offset) {
    return ivec4(texelFetch(Sampler0, topleft + ivec2(offset,0), 0) * 255);
}
vec3 getpos(ivec2 topleft, int w, int h, int index) {
    int i = index * 3;
    ivec4 x = ivec4(texelFetch(Sampler0, topleft + ivec2((i  ) % w, h + (i  ) / w), 0) * 255);
    ivec4 y = ivec4(texelFetch(Sampler0, topleft + ivec2((i+1) % w, h + (i+1) / w), 0) * 255);
    ivec4 z = ivec4(texelFetch(Sampler0, topleft + ivec2((i+2) % w, h + (i+2) / w), 0) * 255);
    int ix = (x.r << 16) | (x.g << 8) | x.b;
    int iy = (y.r << 16) | (y.g << 8) | y.b;
    int iz = (z.r << 16) | (z.g << 8) | z.b;
    return (vec3(ix, iy, iz) - 8388608.0) / 65536.0;
}
vec2 getuv(ivec2 topleft, int w, int h, int index) {
    int i = index*2;
    vec4 x = texelFetch(Sampler0, topleft + ivec2((i  )%w,h+((i  )/w)), 0);
    vec4 y = texelFetch(Sampler0, topleft + ivec2((i+1)%w,h+((i+1)/w)), 0);
    return vec2(
        ((x.g*65280)+(x.b*255))/65535,
        ((y.g*65280)+(y.b*255))/65535
    );
}
ivec2 getvert(ivec2 topleft, int w, int h, int index, bool compressionEnabled) {

    if(!compressionEnabled) {
        int i = index*2;
        ivec4 a = ivec4(texelFetch(Sampler0, topleft + ivec2((i  )%w,h+((i  )/w)), 0)*255);
        ivec4 b = ivec4(texelFetch(Sampler0, topleft + ivec2((i+1)%w,h+((i+1)/w)), 0)*255);
        return ivec2(
            ((a.r*65536)+(a.g*256)+a.b),
            ((b.r*65536)+(b.g*256)+b.b)
        );
    } else {
        ivec4 a = ivec4(texelFetch(Sampler0, topleft + ivec2((index  )%w,h+((index  )/w)), 0)*255);
        return ivec2(
            ((a.r*65536)+(a.g*256)+a.b),
            a.a - 1
        );
    }
}

ivec2 huv(int id) {
  if (id < 1056)
    return ivec2((32 + id % 32), (id/32));
  else
    id -= 1056;
    return ivec2((id % 64), 33 + int(id/64));
}

bool getb(int i, int b) {
    return bool((i>>b)&1);
}
int getb(int i, int b, int s) {
    return (i>>b)&((1<<s)-1);
}

//3d rotation matrix from Barf Creations
mat3 rotate(vec3 angles) {
    float sx = sin(angles.x);
    float cx = cos(angles.x);
    float sy = sin(-angles.y);
    float cy = cos(-angles.y);
    float sz = sin(-angles.z);
    float cz = cos(-angles.z);
    return mat3(
        -sx*sy*sz+cy*cz, -cx*sz, -sx*cy*sz-sy*cz,
        sx*sy*cz+cy*sz, cx*cz, -sy*sz+sx*cy*cz,
        cx*sy, -sx, cx*cy
    );
}

//gui item model detection from Onnowhere
bool isgui(mat4 ProjMat) {
    return ProjMat[2][3] == 0.0;
}
//first person hand item model detection (Bálint nonsense)
bool ishand(mat4 ProjMat) {
    return abs(ProjMat[3][2] + 0.10005) < 0.00001;
}

//hue to rgb
vec3 hrgb(float h) {
    vec3 K = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
    vec3 p = abs(fract(K.xyz + h) * 6.0 - 3.0);
    return clamp(p - K.xxx, 0.0, 1.0);
}

//4 point bezier formula from Dominexis
vec3 bezb(vec3 a, vec3 b, vec3 c, vec3 d, float t) {
    float t2 = t * t;
    float t3 = t2 * t;
    return (d-3*c+3*b-a)*t3 + (3*c-6*b+3*a)*t2 + (3*b-3*a)*t + a;
}
vec3 bezier(vec3 a, vec3 b, vec3 c, vec3 d, float t) {
    return bezb(b,b+(c-a)/6,c-(d-b)/6,c,t);
}


float over_color(float c_a, float a_a, float c_b, float a_b, float a_0) {
    return (c_a * a_a + c_b * a_b * (1.0 - a_a)) / a_0;
}
vec4 over(vec4 overC, vec4 under) {
    float a_0 = overC.a + (under.a * (1.0 - overC.a));
    return vec4(
        over_color(overC.r, overC.a, under.r, under.a, a_0),
        over_color(overC.g, overC.a, under.g, under.a, a_0),
        over_color(overC.b, overC.a, under.b, under.a, a_0),
        a_0
    );
}
