
#ifndef OGRASS3_H_INCLUDED
#define OGRASS3_H_INCLUDED

/*
OBJET       herbe 3eme methode > compute shader + tesselation

DATE        07/2025

AUTEUR      philippe Thebaud

COMMENTAIRE
*/


#include <GL/glew.h>
#include <string>
#include <vector>
#include <fstream>

#include "../ECO/OUtils.h"
#include "../ECO/OTextureList.h"
#include "../ECO/shader/OShader.h"
#include "../ECO/OSurface.h"
#include "../ECO/OCollision.h"
#include "../ECO/OMesh_obj.h"


/*
le mesh.obj (sol) doit être aligné sur l'abscisse et l'ordonnée (pas de rotation)
préférentiellement avec une échelle métrique (10 x 10 pas 10.1 x 10.5)

le mesh doit avoir des coordonnées de texture, calées en 0.0 > 1.1 (pas de portion !)
la texture peut être une simple couleur (elle n'est pas prise en compte)

le decalage est la position finale de la carte

// donnees/image/herbe_ne.png donnees/mesh/zone/zone_ne.obj / decalage pos.xyz / echelle densite /
// image png du masque (RVB) / mesh obj (calé en 0,0,0 ; avec texture 0->1) / position finale / densité de l'herbe
*/
bool OGrass2_make(std::string filepng, std::string filecol, OVec3_f decalage, float taille = 1.0f, float densite = 0.05f);
bool OGrass2_make(std::string flux);


// code flux load save
#define FLUX_GRASS3      "grass3"

class OShGrass3 : public OShader
{
public:

    OShGrass3();

    bool        create();

    void        setVP(const OMat4& vp);
    void        setAmbient(float value);
    void        setEyePos(const OVec3_f& pos);
    void        setTexture(uint32_t grass);
    //void        setTime(float value);

private:

	uint32_t    m_vp;
	//uint32_t    m_time;
	uint32_t    m_eyePos;
	uint32_t    m_ambient;
	//uint32_t    m_grassMap;
};

class OShGrass3_cpt : public OShader
{
public:

    OShGrass3_cpt();

    bool        create();

    void        setTime(float time, float delta_time);
    void        setWind(float magnitude, float wave, float period);

private:

	uint32_t    m_time, m_delta_time;
	uint32_t    m_wind_mag, m_wind_wav, m_wind_per;
};

class OGrass3
{
public:

    OGrass3();
    ~OGrass3();

    void        create(std::string flux);
    void    	create(std::ifstream& flux);

    void        draw(OMat4& vp, OVec3_f& eyePos, float ambient);

    void        save(std::ofstream& flux);

    void        update();

private:

    void        _composition();

    uint32_t    _load_texture(std::string file);

    void        _make_vao();

    std::vector<Blade> generate_blades();

private:

    OTextureList    textureList;
    std::string     m_code, m_path, m_file;

    uint32_t        m_vao;
    OShGrass3       shGrass;
    OShGrass3_cpt   shGrass_cpt;
    uint32_t        blades_count;

public:

    // Wind parameters
    float wind_magnitude = 1.0f;
    float wind_wave_length = 1.0f;
    float wind_wave_period = 1.0f;

    //using DeltaDuration = std::chrono::duration<float, std::milli>;

    // Indirect drawing structure
    struct NumBlades {
        uint32_t vertexCount = 5;
        uint32_t instanceCount = 1;
        uint32_t firstVertex = 0;
        uint32_t firstInstance = 0;
    };

    struct Blade {
    OVec4_f v0; // xyz: Position, w: orientation (in radius)
    OVec4_f v1; // xyz: Bezier point w: height
    OVec4_f v2; // xyz: Physical model guide w: width
    OVec4_f up; // xyz: Up vector w: stiffness coefficient
    };
};



#endif
