#define HALF_PI 1.5707963267948966  // Pi / 2
#define PI 3.14159265358979323846   // Pi
#define TWO_PI 6.28318530717958647692  // 2 * Pi

vec3 rot(vec3 vertex, vec3 angles) {
    // Angles in radians
    float cx = cos(angles.x); // Cosine of the angle around the X axis
    float sx = sin(angles.x); // Sine of the angle around the X axis
    float cy = cos(angles.y); // Cosine of the angle around the Y axis
    float sy = sin(angles.y); // Sine of the angle around the Y axis
    float cz = cos(angles.z); // Cosine of the angle around the Z axis
    float sz = sin(angles.z); // Sine of the angle around the Z axis

    // Rotation matrix for the X axis
    mat3 rotX = mat3(
        1.0, 0.0,  0.0,
        0.0,  cx, -sx,
        0.0,  sx,  cx
    );

    // Rotation matrix for the Y axis
    mat3 rotY = mat3(
         cy, 0.0, sy,
         0.0, 1.0, 0.0,
        -sy, 0.0, cy
    );

    // Rotation matrix for the Z axis
    mat3 rotZ = mat3(
         cz, -sz, 0.0,
         sz,  cz, 0.0,
         0.0, 0.0, 1.0
    );

    // Apply rotations in the order: X -> Y -> Z
    return rotZ * rotY * rotX * vertex;
}


vec3 rotX(vec3 vertex, float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return vec3(
        vertex.x,
        c * vertex.y - s * vertex.z,
        s * vertex.y + c * vertex.z
    );
}


vec3 rotY(vec3 vertex, float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return vec3(
        c * vertex.x + s * vertex.z,
        vertex.y,
        -s * vertex.x + c * vertex.z
    );
}


vec3 rotZ(vec3 vertex, float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return vec3(
        c * vertex.x - s * vertex.y,
        s * vertex.x + c * vertex.y,
        vertex.z
    );
}


vec2 circle(float r, float a) {
    return vec2(
        r * cos(a),
        r * sin(a)
    );
}

vec2 circle2(float r, float a) {
    return vec2(
        r * abs(cos(a)),
        r * (sin(a))
    );
}


//    float angle = r < 0.0 ? -a : a;
//    float radius = abs(r);
//    return vec2(
//        radius * cos(angle),
//        radius * sin(angle)
//    );

//vec2 figure8(float r, float a) {
//    return vec2(
//        r * cos(a),
//        r * sin(a) * (cos(a * 2.) * 0.5 + 0.5)
//    );
//}

vec2 figure8(float r, float a) {
    return vec2(
        r * cos(a),
        r * sin(a) * cos(a)
    );
}

//vec2 figure8(float r, float a) {
//    // Skoryguj promień, aby zapobiec zerowej grubości w środku
////    float correctedRadius = r * sqrt(abs(cos(a)));
//    float correctedRadius = r * (1. + abs(cos(a)));
////    float correctedRadius = r;
//
//    // Oblicz współrzędne ósemki
//    return vec2(
//        correctedRadius * cos(a),          // X współrzędna (pozioma ósemka)
//        correctedRadius * sin(a) * cos(a) // Y współrzędna (ósemka)
//    );
//}




vec3 radial(vec3 cartesian) {
    // Radius: distance from the origin
    float radius = length(cartesian);

    // Azimuthal angle (φ): angle around the Z-axis (in the XY-plane)
    float azimuth = atan(cartesian.y, cartesian.x);

    // Polar angle (θ): angle from the Z-axis
    float polar = acos(cartesian.z / radius);

    return vec3(radius, azimuth, polar); // Return coordinates in the radial system
}

float wrapFullCircle(float polar) {
    return mod(polar, PI); // Modulo 2π
}


vec3 cartesian(vec3 radial) {
    // Radius: distance from the origin
    float radius = radial.x;

    // Azimuthal angle (φ): angle around the Z-axis (in the XY-plane)
    float azimuth = radial.y;

    // Polar angle (θ): angle from the Z-axis
//    float polar = radial.z;

    float polar = wrapFullCircle(radial.z);


    // Convert back to Cartesian coordinates
    float x = radius * sin(polar) * cos(azimuth);
    float y = radius * sin(polar) * sin(azimuth);
    float z = radius * cos(polar);

    return vec3(x, y, z); // Return coordinates in the Cartesian system
}