/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/


const uint particleSize = 4;

struct Particle
{
    vec3 position;
    float size;
    vec3 rotation;
    float age;
    vec4 color;
    vec3 center;
};

vec2 qt_indexToUV(in uint index)
{
    uint v = index / qt_countPerSlice;
    uint u = index - qt_countPerSlice * v;
    return (vec2(u * particleSize, v) + vec2(0.5)) * qt_oneOverParticleImageSize;
}

Particle qt_loadParticle(in uint index)
{
    Particle p;
    vec2 offset = qt_indexToUV(index);
    vec4 p0 = texture(qt_particleTexture, offset);
    vec4 p1 = texture(qt_particleTexture, vec2(offset.x + qt_oneOverParticleImageSize.x, offset.y));
    vec4 p2 = texture(qt_particleTexture, vec2(offset.x + 2.0 * qt_oneOverParticleImageSize.x, offset.y));
    vec4 p3 = texture(qt_particleTexture, vec2(offset.x + 3.0 * qt_oneOverParticleImageSize.x, offset.y));
    p.position = p0.xyz;
    p.size = p0.w;
    p.rotation = p1.xyz;
    p.age = p1.w;
    p.color = p2;
    p.center = p3.xyz;
    return p;
}

mat3 qt_fromEulerRotation(in vec3 rotation)
{
    float a = cos(rotation.x);
    float b = sin(rotation.x);
    float c = cos(rotation.y);
    float d = sin(rotation.y);
    float e = cos(rotation.z);
    float f = sin(rotation.z);
    mat3 ret;
    float bd = b * d;
    float ad = a * d;
    ret[0][0] = c * e;
    ret[0][1] = -c * f;
    ret[0][2] = d;
    ret[1][0] = bd * e + a * f;
    ret[1][1] = a * e - bd * f;
    ret[1][2] = -b * c;
    ret[2][0] = b * f - ad * e;
    ret[2][1] = ad * f + b * e;
    ret[2][2] = a * c;
    return ret;
}

vec3 qt_applyParticle(in vec3 position, in vec3 normal, in vec4 color, out vec3 outNormal, out vec4 outColor, in mat4 particleMatrix)
{
    uint index = (gl_VertexIndex + qt_particleIndexOffset) / 3;
    Particle p = qt_loadParticle(index);
    mat3 rotMat = qt_fromEulerRotation(p.rotation);
    vec3 particlePos = p.size * rotMat * (position - p.center);
    vec3 pos = particlePos + (particleMatrix * vec4(p.position, 1.0)).xyz;
    outNormal = normalize(rotMat * normal);
    outColor = color * p.color;
    return pos;
}
