#include "SM_CommonFXPCH.h"
#include "SM_Engine3DPCH.h"
#include "SM_DemoEffect.h"

#define RAYS    300

class FlareFX : public SM_DemoEffect
{
public:              
  FlareFX(char const* pcName) : SM_DemoEffect(pcName)
  {
  }

  virtual          ~FlareFX()
  {
  }

  int      Init(const char* pcCommand)
  {
    m_iShader=ShaderManager::LoadShader("flaretrace");

    int i;

    for (i=0 ; i<RAYS ; i++)
    {
        m_fRandoms[i]=float(rand())/float(RAND_MAX);
    }

    return (0);
  }

  int      Shutdown()
  {
    return (0);
  }

  int      Start(float fTime)
  {

    return (0);
  }

  int      Stop()
  {
    return (0);
  }

  int      Reset()
  {
    return (0);
  }  

  int      Run(float fTime)
  {
    RenderContext RC;   

    /*
    RC.Set(
    Vector3D(0.0f, 0.0f, 0.0f),
    Quaternion(1.0f, 0.0f, 0.0f, 0.0f),
    90,
    0.75f,
    1.0f,
    200.0f);
  
    RC.SetViewport(0, 0, 640, 480);
    RC.SyncRasterizer();
    RC.UpdateFrustum();
    */

    Matrix4X4 m;

    Coordinates::UpdatePhysicalSize();
    float fWidth =640;
    float fHeight=480;
    
    
    float w =4.0f /fWidth;
    float h =-4.0f/fHeight;
    float dw=-2.0f;
    float dh=2.0f;
    
    float fFar =2.0f;
    float fNear=0.001f;
    
    float Q =fFar/(fFar-fNear);
    
    m.m_11=w             ; m.m_12=0.0f; m.m_13=0.0f         ; m.m_14=0.0f;
    m.m_21=0.0f          ; m.m_22=h   ; m.m_23=0.0f         ; m.m_24=0.0f;
    m.m_31=0.0f          ; m.m_32=0.0f; m.m_33=Q            ; m.m_34=1.0f;
    m.m_41=dw            ; m.m_42=dh  ; m.m_43=-Q*fNear     ; m.m_44=1.0f;
    
    SM_D3d::Device()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&Matrix4X4::Identity);    
    SM_D3d::Device()->SetTransform(D3DTS_WORLD, (D3DMATRIX*) &Matrix4X4::Identity);      
    SM_D3d::Device()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&m); 
   

    D3DVIEWPORT8 Viewport;
    Viewport.X      =0;
    Viewport.Y      =0;
    Viewport.Width  =(DWORD) Coordinates::PhysicalWidth();
    Viewport.Height =(DWORD) Coordinates::PhysicalHeight();
    Viewport.MinZ   =0.0f;
    Viewport.MaxZ   =1.0f;

    SM_D3d::Device()->SetViewport(&Viewport);  

    MeshElement me;

    FVF_PosNormalDiffuseTex1 pVertices[3*RAYS];
    unsigned short pusIndices[3*RAYS]={0,2,1};

    int i;

    SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
        
    FVF_PosNormalDiffuseTex1* pV=pVertices;
    unsigned short* pus         =pusIndices;
    for (i=0 ; i<RAYS ; i++)
    {
        float fRayLength=m_fRandoms[i]*(200.0f+150.0f* (float) cosf(3.0f*fTime+i*i));
        float fRayArc   =m_fRandoms[i]*(0.2f+0.01f*(float) sinf(fTime+i));
        float fRayOffset=m_fRandoms[i]*(0.1f*fTime+6.23f*(float) cosf(13.0f*i));


        float fAngle     =cosf(fRayOffset);

        fRayOffset=fabsf(fmodf(fRayOffset, 3.1416f*2.0f));
        if (fRayOffset>=3.1416f && fRayOffset<2.0f*3.1416f)
        {
            fRayLength*=fabsf(fAngle);
        }
 


        float fx=320.0f;
        float fy=110.0;

        
        pV[0].x =fx; pV[0].y =fy; pV[0].z=1.0f; 
        pV[0].nx=0.0f  ; pV[0].ny=0.0f  ; pV[0].nz=1.0f;
        pV[0].u =0.0f  ; pV[0].v =0.0f  ; pV[0].diffuse=0xA0080803;

        pV[1].x =fx+fRayLength*cosf(fRayOffset); pV[1].y =fy+fRayLength*sinf(fRayOffset); pV[1].z=1.0f; 
        pV[1].nx=0.0f  ; pV[1].ny=0.0f  ; pV[1].nz=1.0f;
        pV[1].u =0.0f  ; pV[1].v =0.0f  ; pV[1].diffuse=0x00000000;

        pV[2].x =fx+fRayLength*cosf(fRayOffset+fRayArc); pV[2].y =fy+fRayLength*sinf(fRayOffset+fRayArc); pV[2].z=1.0f; 
        pV[2].nx=0.0f  ; pV[2].ny=0.0f  ; pV[2].nz=1.0f;
        pV[2].u =0.0f  ; pV[2].v =0.0f  ; pV[2].diffuse=0x00000000;

        pus[0]=3*i;
        pus[1]=3*i+2;
        pus[2]=3*i+1;

        pus+=3;
        pV+=3;

    }

    
    me.m_iShader            =m_iShader;
    me.m_iVB                =-1;
    me.m_iIB                =-1;
    me.m_pVertices          =pVertices; 
    me.m_pIndices           =pusIndices;
    me.m_uStartVertex       =0;
    me.m_uVertices          =RAYS*3;
    me.m_uStartIndex        =0;
    me.m_uPrimitives        =RAYS;
    me.m_WorldTransform     =Matrix4X4::Identity;
    me.m_iActiveLightMask   =-1;  
    me.m_fDepth             =0.0f;

    SM_D3d::SetRenderState(D3DRS_LIGHTING, FALSE);
    SM_D3d::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
    SM_D3d::SetRenderState(D3DRS_ZFUNC,    D3DCMP_ALWAYS);


    RenderPipeline::Render(&me);
    RenderPipeline::Flush();

    SM_D3d::SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
        

    return (1);
  }

  int      Command           (float fTime, const char* pcCommand)
  {
      SM_DemoEffect::Command(fTime, pcCommand);
    return (0);
  }
  
  float m_fRandoms[RAYS];
  int   m_iShader;
};

DEFINE_EFFECT(FlareFX)

FlareFX Flare00("FLARE_00");