'use strict'

function getIso1 (p, mat1, mat2, mat3, mat4, blendFactor) {

    const iso1 = opTransform(p, mat1, (p) => getIsoSphere(p, 5))
    const iso2 = opTransform(p, mat2, (p) => getIsoSphere(p, 5))
    const iso3 = opTransform(p, mat3, (p) => getIsoSphere(p, 5))
    const iso4 = opTransform(p, mat4, (p) => opRepeat(p, [4, 4, 4], (p) => getIsoBox(p, [1.0, 1.0, 1.0])))

    return Math.max(sminCubic(iso2, sminCubic(iso1, iso3, blendFactor), blendFactor), iso4)
}

function sminCubic (a, b, k)
{
    const h = Math.max( k-Math.abs(a-b), 0.0 )/k
    return Math.min( a, b ) - h*h*h*k*(1.0/6.0)
}

modules['metaballRay'] = {
    config: [
        ['animation', 'float', 0],
        ['fieldStrength', 'float', 1],
        ['blendFactor', 'float', 1],
    ],

    render: async (time, self, config) => {
        const {
            animation,
            fieldStrength,
            blendFactor,
        } = { ...config }

        const sDist = 8 //- t*2
        const t = animation
        const mat1 = m4.translation(Math.sin((t+2.32)*2.12) * sDist, Math.sin((t+1.18)*1.97) * sDist, Math.sin((t+4.75)*1.01) * sDist)
        const mat2 = m4.translation(Math.sin((t+1.59)*3.88) * sDist, Math.sin((t+5.11)*2.35) * sDist, Math.sin((t+0.23)*2.18) * sDist)
        const mat3 = m4.translation(Math.sin((t+6.23)*5.32) * sDist, Math.sin((t+9.31)*6.21) * sDist, Math.sin((t+9.13)*6.53) * sDist)
        const mat4 = m4.translation(-12, -12, -12)

        const fieldSize = 15
        const isoField = makeIsoField(fieldSize, (x, y, z) => getIso1([x, y, z], mat1, mat2, mat3, mat4, blendFactor))
        const lists = renderIsoField(fieldSize, isoField, fieldStrength)
        renderer.drawLists(greyscaleBuffers[getOutputBufferId()], m4.identity(), lists.verts, lists.lines, 1.2, lists.tris, .05, [], 1)
    }
}
