/*
 =======================================================================================
  Name        : TexProcedural.c
  Author      : vincent lhullier            Date :01/02/99
  Description : implementation of function for procedural texture
 =======================================================================================
 */
 
#ifdef PROCEDURAL_TEXTURE
 
#include "cpa_expt.h" 
#include "GLD.h"
 
#include "DllCaps.h"
#include "DLLInter.h"
 
#include "TexProcedural.h"
#include "Texture.h"
#include "TexName.h"
 
/*
 =======================================================================================
    Internal function to compute procedural texture surface
 =======================================================================================
 */
#define FREQ 0.2f
#define AMPL 200.f
 
void TEXPRO_fnv_DisruptSurface_Water( GLI_tdstTexture *_pst_Texture )
{
    unsigned char   *S1, *S2, N;
    static long     sl_K;
    unsigned long   ul_X, ul_Y , ul_Add;
    static long     lRate = 10;
    static long     lCount = 0;
    static long     lNRate = 2;
    
    if (lCount)
    {
        lCount--;
        return;
    }
    lCount = lRate;
 
    sl_K++;
    S1 = ((unsigned char *) _pst_Texture->p_vBitMap);
    S2 = ((unsigned char *) _pst_Texture->pv_Bitmap2);
    N = lNRate;
 
    while (N--)
    {
        ul_X = rand() % (_pst_Texture->lWidth - 8) + 4;
        ul_Y = rand() % (_pst_Texture->lHeight - 8) + 4;
        ul_Add = (unsigned long) (fabs(sin(sl_K * FREQ)) * AMPL);
        
        *(S1 + ul_X     + ( (ul_Y + 1) *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S1 + ul_X + 1 + ( ul_Y       *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S1 + ul_X + 1 + ( (ul_Y + 1) *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S1 + ul_X     + ( ul_Y       *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S2 + ul_X     + ( (ul_Y + 1) *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S2 + ul_X + 1 + ( ul_Y       *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S2 + ul_X + 1 + ( (ul_Y + 1) *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
        *(S2 + ul_X     + ( ul_Y       *_pst_Texture->lWidth )) += (unsigned char) ul_Add;
    }
}
 
void TEXPRO_fnv_ComputeSurface_Water( GLI_tdstTexture *_pst_Texture )
{
    char *S1, *S2;
    unsigned long Size;
    unsigned long X, Y, DX;
    unsigned long ulValue;
    
    DX = _pst_Texture->lWidth;
    
    S1 = ((char *) _pst_Texture->p_vBitMap) + _pst_Texture->lWidth + 1;
    S2 = ((char *) _pst_Texture->pv_Bitmap2) + _pst_Texture->lWidth + 1;
    
    Y = _pst_Texture->lHeight - 2;
    while (Y--)
    {
        X = _pst_Texture->lWidth - 2;
        while (X--)
        {
            ulValue = ((((unsigned long) *(S2 + 1)) + ((unsigned long) *(S2 - 1)) + ((unsigned long) *(S2 + DX)) + ((unsigned long) *(S2 - DX)))>> 1) - ((unsigned long) *(S1));
            /*ulValue = ( (
                            ((unsigned long) *(S2 + 1)) + 
                            ((unsigned long) *(S2 - 1)) + 
                            ((unsigned long) *(S2 + DX)) + 
                            ((unsigned long) *(S2 - DX)) +
                            ((unsigned long) *(S2 + 1 + DX)) + 
                            ((unsigned long) *(S2 - 1 + DX)) + 
                            ((unsigned long) *(S2 - DX + 1)) + 
                            ((unsigned long) *(S2 - DX -1 ))
                         ) >> 2 ) - ((unsigned long) *(S1));
                         */
            
            *S1 = (char) (ulValue - (ulValue>>5) );
            S1++;
            S2++;
        }
        S1 += 2;
        S2 += 2;
    }   
    
    S1 = ((char *) _pst_Texture->p_vBitMap) + DX;
    S2 = ((char *) _pst_Texture->pv_Bitmap2) + DX;
    
    Y = _pst_Texture->lHeight - 2;
    while (Y--)
    {
        ulValue = ((((unsigned long) *(S2 + 1)) + ((unsigned long) *(S2 + DX - 1)) + ((unsigned long) *(S2 + DX)) + ((unsigned long) *(S2 - DX))) >> 1) - ((unsigned long) *(S1));
        *S1 = (char) (ulValue - (ulValue>>5) );
        S1 += DX - 1;
        S2 += DX - 1;
 
        ulValue = ((((unsigned long) *(S2 - DX + 1)) + ((unsigned long) *(S2 - 1)) + ((unsigned long) *(S2 + DX)) + ((unsigned long) *(S2 - DX))) >> 1) - ((unsigned long) *(S1));
        *S1 = (char) (ulValue - (ulValue>>5) );
        S1++;
        S2++;
    }   
 
    S1 = ((char *) _pst_Texture->p_vBitMap) + 1;
    S2 = ((char *) _pst_Texture->pv_Bitmap2) + 1;
    X = DX - 2;
    Size = DX * (_pst_Texture->lHeight - 1) ;
    while (X--)
    {
        ulValue = ((((unsigned long) *(S2 + 1)) + ((unsigned long) *(S2 - 1)) + ((unsigned long) *(S2 + DX)) + ((unsigned long) *(S2 + Size))) >> 1) - ((unsigned long) *(S1));
        *S1 = (char) (ulValue - (ulValue>>5) );
        S1 += Size;
        S2 += Size;
        ulValue = ((((unsigned long) *(S2 + 1)) + ((unsigned long) *(S2 - 1)) + ((unsigned long) *(S2 - Size)) + ((unsigned long) *(S2 - DX))) >> 1) - ((unsigned long) *(S1));
        *S1 = (char) (ulValue - (ulValue>>5) );
        S1 -= Size - 1;
        S2 -= Size - 1;
    }   
 
    S1 = (char *) _pst_Texture->p_vBitMap;
    _pst_Texture->p_vBitMap = _pst_Texture->pv_Bitmap2;
    _pst_Texture->pv_Bitmap2 = (void *) S1;
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : init texture structure for procedural texture
 ----------------------------------------------------------------------------------------
 */
long TEXPRO_fnl_InitProceduralTexture( GLI_tdstTexture *_pst_Texture, long _l_Type, long _l_Width, long _l_Height, long _l_RefreshRate )
{
    long            i, j;
    unsigned short  *puw_Palette;
 
    _pst_Texture->lTextureCaps |= GLI_C_lProceduralTexture;
    _pst_Texture->lHeight = _pst_Texture->lRealHeight = (unsigned short) _l_Height;
    _pst_Texture->lWidth  = _pst_Texture->lRealWidth  = (unsigned short) _l_Width;
    _pst_Texture->lTextureCaps |= GLI_C_lAlphaTexture;
    _pst_Texture->l_Type = _l_Type;
    _pst_Texture->l_RefreshRate = _pst_Texture->l_RefreshCounter = _l_RefreshRate;
    _pst_Texture->l_RenderingCounter = 0;
 
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeTexture , NULL);
    GEO_M_CPAMalloc(_pst_Texture->p_vBitMap, void *, _l_Width * _l_Height, E_uwGEONotEnoughtMemory );
    
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeTexture , NULL);
    GEO_M_CPAMalloc(_pst_Texture->pv_Bitmap2, void *, _l_Width * _l_Height, E_uwGEONotEnoughtMemory );
    
    MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeTexture , NULL);
    GEO_M_CPAMalloc(_pst_Texture->p_vColorTable, void *, 512, E_uwGEONotEnoughtMemory );
 
    puw_Palette = (unsigned short *) _pst_Texture->p_vColorTable;
 
    for (i = 0; i < 256; i++, puw_Palette++ )
    {
        /**pul_Palette = i | (i<<8) | (i<<16) | ((i < 128) ? (i<<25) : 0xFF000000);*/
        j = i>>4;
        *puw_Palette = j | (j<<4) | (j<<8) | ((i < 128) ? (j<<13) : 0xF000);
    }
 
    strcpy( _pst_Texture->a255_cFileName, "Proc" );
    TEX_fnv_MakeItExisting( _pst_Texture );
 
    return 1;    
}
 
/*
 ----------------------------------------------------------------------------------------
  Description   : init texture structure for procedural texture 
                    (texture type is given by its name, used by script callback)
  Returns (long ) 0 if failed
 ----------------------------------------------------------------------------------------
 */
long TEXPRO_fnl_InitProceduralTextureWithName( GLI_tdstTexture *_pst_Texture, char *_sz_ProcName, long _l_Width, long _l_Height, long _l_RefreshRate )
{
    long l_Type;
 
    if (stricmp( _sz_ProcName, "Water") == 0)
        l_Type = TEXPRO_C_lWater;
    else if (stricmp( _sz_ProcName, "Fire") == 0)
        l_Type = TEXPRO_C_lFire;
    else 
        return 0;
 
    return TEXPRO_fnl_InitProceduralTexture( _pst_Texture, l_Type, _l_Width, _l_Height, _l_RefreshRate );
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : refresh procedural texture
 ----------------------------------------------------------------------------------------
 */
void TEXPRO_fnv_RefreshProceduralTexture( GLI_tdstTexture *_pst_Texture, long _l_ActualRefreshNumber )
{
    if (!( _pst_Texture->lTextureCaps & GLI_C_lProceduralTexture))
        return;
    if ( _pst_Texture->l_RenderingCounter == _l_ActualRefreshNumber )
        return;
 
    _pst_Texture->l_RenderingCounter = _l_ActualRefreshNumber;
 
    _pst_Texture->l_RefreshCounter--;
    if (_pst_Texture->l_RefreshCounter >= 0 )
        return;
 
    _pst_Texture->l_RefreshCounter = _pst_Texture->l_RefreshRate;
 
    switch (_pst_Texture->l_Type)
    {
        case TEXPRO_C_lWater:
            TEXPRO_fnv_DisruptSurface_Water( _pst_Texture );
            TEXPRO_fnv_ComputeSurface_Water( _pst_Texture );
            break;
        case TEXPRO_C_lFire:
            break;
    }
 
    /*
    {
        static  file = 0;
        FILE    *hpFile;
        char    szFile[64];
 
        if (file < 100)
        {
            sprintf(szFile, "snapshot/proc%04d.raw", file++ );
            hpFile = fopen( szFile, "wb" );
            fwrite( _pst_Texture->p_vBitMap, 128*128,1, hpFile);
            fclose( hpFile );
        }
 
        
    }
    */
 
 
 
    GLI_DRV_lRequest( GLIDLL_Request_ReloadTexture, (long) _pst_Texture, 0 );
}
 
#endif /*PROCEDURAL_TEXTURE*/
 
