#include "SM_Engine3DPCH.h"
#include <math.h>
#include "SM_VertexShader.h"


#define NUMOFFSETS 64

float g_fNoiseOffset[NUMOFFSETS];

int   NoiseNormalShader::Init()
{
  int i;
  for (i=0 ; i<NUMOFFSETS ; i++)
  {
    g_fNoiseOffset[i]=float(rand())/float(RAND_MAX);
  }

  return 0;
};

int   NoiseNormalShader::Shutdown()
{
  return 0;
}

void  NoiseNormalShader::ProcessVertices(FVF_PosNormalDiffuseTex1* pDst, FVF_PosNormalDiffuseTex1* pSrc, unsigned uVertices, unsigned short* pusIndices, unsigned uIndices, Matrix4X4* pWorldTransform)
{
  unsigned i;

  float fTime=Timer::GetTime();

  for (i=0 ; i<uVertices ; i++)
  {
    float fScale=2.0f*sinf(0.2f*(pSrc[i].x+pSrc[i].y+pSrc[i].z)+6.0f*fTime);
    pDst[i].x      = pSrc[i].x+pSrc[i].nx*fScale;
    pDst[i].y      = pSrc[i].y+pSrc[i].ny*fScale;
    pDst[i].z      = pSrc[i].z+pSrc[i].nz*fScale;
    pDst[i].nx     = pSrc[i].nx;
    pDst[i].ny     = pSrc[i].ny;
    pDst[i].nz     = pSrc[i].nz;
    pDst[i].diffuse= pSrc[i].diffuse;
    pDst[i].u      = pSrc[i].u;
    pDst[i].v      = pSrc[i].v;
  }
}



int   NoiseXYZShader::Init()
{
  int i;
  for (i=0 ; i<NUMOFFSETS ; i++)
  {
    g_fNoiseOffset[i]=float(rand())/float(RAND_MAX);
  }

  m_fAmplitudeX    =0;
  m_fAmplitudeY    =0;
  m_fAmplitudeZ    =0;
  m_fSpaceFrequency=0;
  m_fTimeFrequency =1.0f;
  return 0;
}

int   NoiseXYZShader::Shutdown()
{
  return 0;
}

void  NoiseXYZShader::ProcessVertices(FVF_PosNormalDiffuseTex1* pDst, FVF_PosNormalDiffuseTex1* pSrc, unsigned uVertices, unsigned short* pusIndices, unsigned uIndices, Matrix4X4* pM)
{
  unsigned i;

  float fTime=Timer::GetTime();

  float fScale;
  m_ExpSlider.GetValue(fTime, &fScale);

  if (fScale)
  {
    Vector3D* pv3d=new Vector3D[uVertices];
    if (!pv3d)
    {
      return;
    }
  
    for (i=0 ; i<uVertices ; i++)
    {
      float fCode1=fScale*sinf(m_fSpaceFrequency*(pSrc[i].x+pSrc[i].y+pSrc[i].z)+m_fTimeFrequency*fTime);
      float fCode2=fScale*sinf(m_fSpaceFrequency*(pSrc[i].x*pSrc[i].y+pSrc[i].z)+m_fTimeFrequency*fTime);
      float fCode3=fScale*sinf(m_fSpaceFrequency*(pSrc[i].x*pSrc[i].y*pSrc[i].z)+m_fTimeFrequency*fTime);

      pv3d[i].x=pSrc[i].x+m_fAmplitudeX*fCode1;
      pv3d[i].y=pSrc[i].y+m_fAmplitudeY*fCode2;
      pv3d[i].z=pSrc[i].z+m_fAmplitudeZ*fCode3;    
    }

    Vector3D* pvNormal=new Vector3D[uIndices/3];
    int iTri;
    for (i=0, iTri=0 ; i<uIndices ; i+=3, iTri++)
    {
      pvNormal[iTri]=
        Vector3D::Cross(
          pv3d[pusIndices[i+2]]-pv3d[pusIndices[i]],
          pv3d[pusIndices[i+1]]-pv3d[pusIndices[i]]);
    }

    Vector3D* pvVertexNormal=new Vector3D[uVertices];
    memset(pvVertexNormal, 0, sizeof(Vector3D)*uVertices);
    for (i=0, iTri=0 ; i<uIndices ; i+=3, iTri++)
    {
      pvVertexNormal[pusIndices[i]]  +=pvNormal[iTri];
      pvVertexNormal[pusIndices[i+1]]+=pvNormal[iTri];
      pvVertexNormal[pusIndices[i+2]]+=pvNormal[iTri];
    }

    for (i=0 ; i<uVertices ; i++)
    {
      pvVertexNormal[i].Normalize();
    }


    if (pM)
    {
      for (i=0 ; i<uVertices ; i++)
      {
        pDst[i].x      = pM->m_11*pv3d[i].x+pM->m_21*pv3d[i].y+pM->m_31*pv3d[i].z+pM->m_41;;
        pDst[i].y      = pM->m_12*pv3d[i].x+pM->m_22*pv3d[i].y+pM->m_32*pv3d[i].z+pM->m_42;
        pDst[i].z      = pM->m_13*pv3d[i].x+pM->m_23*pv3d[i].y+pM->m_33*pv3d[i].z+pM->m_43;
        pDst[i].nx     = pM->m_11*pvVertexNormal[i].x+pM->m_21*pvVertexNormal[i].y+pM->m_31*pvVertexNormal[i].z;
        pDst[i].ny     = pM->m_12*pvVertexNormal[i].x+pM->m_22*pvVertexNormal[i].y+pM->m_32*pvVertexNormal[i].z;
        pDst[i].nz     = pM->m_13*pvVertexNormal[i].x+pM->m_23*pvVertexNormal[i].y+pM->m_33*pvVertexNormal[i].z;
        pDst[i].diffuse= pSrc[i].diffuse;
        pDst[i].u      = pSrc[i].u;
        pDst[i].v      = pSrc[i].v;
      }
    }
    else
    {
      for (i=0 ; i<uVertices ; i++)
      {
        pDst[i].x      = pv3d[i].x;
        pDst[i].y      = pv3d[i].y;
        pDst[i].z      = pv3d[i].z;
        pDst[i].nx     = pvVertexNormal[i].x;
        pDst[i].ny     = pvVertexNormal[i].y;
        pDst[i].nz     = pvVertexNormal[i].z;
        pDst[i].diffuse= pSrc[i].diffuse;
        pDst[i].u      = pSrc[i].u;
        pDst[i].v      = pSrc[i].v;
      }
    }

    delete[] pv3d;
    delete[] pvNormal;
    delete[] pvVertexNormal;
  }
  else
  {
    memcpy(pDst, pSrc, sizeof(FVF_PosNormalDiffuseTex1)*uVertices);
  }
}

int   TwistShader::Init()
{
  return 0;
}

int   TwistShader::Shutdown()
{
  return 0;
}

void  TwistShader::ProcessVertices(FVF_PosNormalDiffuseTex1* pDst, FVF_PosNormalDiffuseTex1* pSrc, unsigned uVertices, unsigned short* pusIndices, unsigned uIndices, Matrix4X4* pWorldTransform)
{
  unsigned i;

  float fTime=Timer::GetTime();

  for (i=0 ; i<uVertices ; i++)
  {
    float fScale=2.0f*sinf(4.0f*fTime+2.0f*3.14f*g_fNoiseOffset[i&(NUMOFFSETS-1)]);
    pDst[i].x      = pSrc[i].x+pSrc[i].nx*fScale;
    pDst[i].y      = pSrc[i].y+pSrc[i].ny*fScale;
    pDst[i].z      = pSrc[i].z+pSrc[i].nz*fScale;
    pDst[i].nx     = pSrc[i].nx;
    pDst[i].ny     = pSrc[i].ny;
    pDst[i].nz     = pSrc[i].nz;
    pDst[i].diffuse= pSrc[i].diffuse;
    pDst[i].u      = pSrc[i].u;
    pDst[i].v      = pSrc[i].v;
  }
}



NoiseNormalShader     TheNormalNoiseShader;
NoiseXYZShader        TheNoiseXYZShader;
TwistShader           TheTwistShader;

int   InitVertexShaders    ()
{
  TheNormalNoiseShader.Init();
  TheNoiseXYZShader.Init();
  TheTwistShader.Init();

  return 0;
}

int   ShutdownVertexShaders()
{
  TheNormalNoiseShader.Shutdown();

  return 0;
}
