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



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

  virtual          ~PulpoFX()
  {
  }

  int      Init(const char* pcCommand)
  {
    char* pcCopy =0;
    char* pcToken;
    int   iReturn=-1;


    InitMathAux();
    
    pcCopy=new char[strlen(pcCommand)+1];
    strcpy(pcCopy, pcCommand);

    pcToken=strtok(pcCopy, " \t");

    if (pcToken)
    if (strcmp(pcToken, "FILL THIS UP")==0)
    {
    }

    iReturn  = 0;

    ShaderManager::LoadShader("pulpo");
    
    if (pcCopy) { delete[] pcCopy; pcCopy=0; }

    return iReturn;        
  }

  int      Shutdown()
  {
    return (0);
  }

  int      Start(float fTime)
  {
    return (0);
  }

  int      Stop()
  {
    return (0);
  }

  int      Reset()
  {
    return 0;
  }

  void RenderPulpo(float fTime)
  {
    #define ROWS      10
    #define COLUMNS   3

    static unsigned short pusTentacle[6*(ROWS-1)*(COLUMNS)];
    FVF_PosNormalDiffuseTex1 pVTentacle[ROWS*COLUMNS];

    unsigned i,j;


    static bool bInit = false;
    if (!bInit)
    {
      bInit = true;

      unsigned short* pI = pusTentacle;
      unsigned uCurrent = 0;
      for (j = 0 ; j  <ROWS-1 ; j++, uCurrent+=COLUMNS)
      {
        for (i = 0 ; i < COLUMNS ; i++)
        {
          pI[0] = uCurrent+i;
          pI[2] = uCurrent+i+COLUMNS;
          pI[1] = uCurrent+((i+1)%COLUMNS);          
          pI[3] = uCurrent+i+COLUMNS;
          pI[5] = uCurrent+((i+1)%COLUMNS)+COLUMNS;
          pI[4] = uCurrent+((i+1)%COLUMNS);
          
          pI+=6;                   
        }
      }
    }

    MeshElement me;
    FVF_PosNormalDiffuseTex1 pV[24];
    unsigned short pusIndices[36]={0,2,1,0,2,3,
                                   0+4,2+4,1+4,0+4,2+4,3+4,
                                   0+8,2+8,1+8,0+8,2+8,3+8,
                                   0+12,2+12,1+12,0+12,2+12,3+12,
                                   0+16,2+16,1+16,0+16,2+16,3+16,
                                   0+20,2+20,1+20,0+20,2+20,3+20,};

    int iO = 0;
    pV[iO+0].x =-0.5f; pV[iO+0].y=-0.5f; pV[iO+0].z=-0.5f; pV[iO+0].nx=0.0f; pV[iO+0].ny=0.0f; pV[iO+0].nz=-1.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x = 0.5f; pV[iO+1].y=-0.5f; pV[iO+1].z=-0.5f; pV[iO+1].nx=0.0f; pV[iO+1].ny=0.0f; pV[iO+1].nz=-1.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x = 0.5f; pV[iO+2].y= 0.5f; pV[iO+2].z=-0.5f; pV[iO+2].nx=0.0f; pV[iO+2].ny=0.0f; pV[iO+2].nz=-1.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x =-0.5f; pV[iO+3].y= 0.5f; pV[iO+3].z=-0.5f; pV[iO+3].nx=0.0f; pV[iO+3].ny=0.0f; pV[iO+3].nz=-1.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    iO+=4;
    pV[iO+0].x =-0.5f; pV[iO+0].y=-0.5f; pV[iO+0].z= 0.5f; pV[iO+0].nx=0.0f; pV[iO+0].ny=0.0f; pV[iO+0].nz=1.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x = 0.5f; pV[iO+1].y=-0.5f; pV[iO+1].z= 0.5f; pV[iO+1].nx=0.0f; pV[iO+1].ny=0.0f; pV[iO+1].nz=1.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x = 0.5f; pV[iO+2].y= 0.5f; pV[iO+2].z= 0.5f; pV[iO+2].nx=0.0f; pV[iO+2].ny=0.0f; pV[iO+2].nz=1.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x =-0.5f; pV[iO+3].y= 0.5f; pV[iO+3].z= 0.5f; pV[iO+3].nx=0.0f; pV[iO+3].ny=0.0f; pV[iO+3].nz=1.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    iO+=4;
    pV[iO+0].x = 0.5f; pV[iO+0].y=-0.5f; pV[iO+0].z=-0.5f; pV[iO+0].nx=1.0f; pV[iO+0].ny=0.0f; pV[iO+0].nz=0.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x = 0.5f; pV[iO+1].y= 0.5f; pV[iO+1].z=-0.5f; pV[iO+1].nx=1.0f; pV[iO+1].ny=0.0f; pV[iO+1].nz=0.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x = 0.5f; pV[iO+2].y= 0.5f; pV[iO+2].z= 0.5f; pV[iO+2].nx=1.0f; pV[iO+2].ny=0.0f; pV[iO+2].nz=0.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x = 0.5f; pV[iO+3].y=-0.5f; pV[iO+3].z= 0.5f; pV[iO+3].nx=1.0f; pV[iO+3].ny=0.0f; pV[iO+3].nz=0.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    iO+=4;
    pV[iO+0].x =-0.5f; pV[iO+0].y=-0.5f; pV[iO+0].z=-0.5f; pV[iO+0].nx=-1.0f; pV[iO+0].ny=0.0f; pV[iO+0].nz=0.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x =-0.5f; pV[iO+1].y= 0.5f; pV[iO+1].z=-0.5f; pV[iO+1].nx=-1.0f; pV[iO+1].ny=0.0f; pV[iO+1].nz=0.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x =-0.5f; pV[iO+2].y= 0.5f; pV[iO+2].z= 0.5f; pV[iO+2].nx=-1.0f; pV[iO+2].ny=0.0f; pV[iO+2].nz=0.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x =-0.5f; pV[iO+3].y=-0.5f; pV[iO+3].z= 0.5f; pV[iO+3].nx=-1.0f; pV[iO+3].ny=0.0f; pV[iO+3].nz=0.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    iO+=4;
    pV[iO+0].x =-0.5f; pV[iO+0].y=-0.5f; pV[iO+0].z=-0.5f; pV[iO+0].nx=0.0f; pV[iO+0].ny=-1.0f; pV[iO+0].nz=0.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x = 0.5f; pV[iO+1].y=-0.5f; pV[iO+1].z=-0.5f; pV[iO+1].nx=0.0f; pV[iO+1].ny=-1.0f; pV[iO+1].nz=0.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x = 0.5f; pV[iO+2].y=-0.5f; pV[iO+2].z= 0.5f; pV[iO+2].nx=0.0f; pV[iO+2].ny=-1.0f; pV[iO+2].nz=0.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x =-0.5f; pV[iO+3].y=-0.5f; pV[iO+3].z= 0.5f; pV[iO+3].nx=0.0f; pV[iO+3].ny=-1.0f; pV[iO+3].nz=0.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    iO+=4;
    pV[iO+0].x =-0.5f; pV[iO+0].y= 0.5f; pV[iO+0].z=-0.5f; pV[iO+0].nx=0.0f; pV[iO+0].ny=1.0f; pV[iO+0].nz=0.0f; pV[iO+0].diffuse=0xFFFFFFFF;
    pV[iO+1].x = 0.5f; pV[iO+1].y= 0.5f; pV[iO+1].z=-0.5f; pV[iO+1].nx=0.0f; pV[iO+1].ny=1.0f; pV[iO+1].nz=0.0f; pV[iO+1].diffuse=0xFFFFFFFF;
    pV[iO+2].x = 0.5f; pV[iO+2].y= 0.5f; pV[iO+2].z= 0.5f; pV[iO+2].nx=0.0f; pV[iO+2].ny=1.0f; pV[iO+2].nz=0.0f; pV[iO+2].diffuse=0xFFFFFFFF;
    pV[iO+3].x =-0.5f; pV[iO+3].y= 0.5f; pV[iO+3].z= 0.5f; pV[iO+3].nx=0.0f; pV[iO+3].ny=1.0f; pV[iO+3].nz=0.0f; pV[iO+3].diffuse=0xFFFFFFFF;

    
    me.m_iShader            =ShaderManager::FindShader("pulpo");
    me.m_iVB                =-1;
    me.m_iIB                =-1;
    me.m_pVertices          =pV; 
    me.m_pIndices           =pusIndices;
    me.m_uStartVertex       =0;
    me.m_uVertices          =24;
    me.m_uStartIndex        =0;
    me.m_uPrimitives        =12;   
    ToTransform(&me.m_WorldTransform, &Vector3D(0.0f, 0.0f, 0.0f), &Quaternion(fTime, Vector3D(1.0f, 1.0f, 0.0).Normalize()));    
    me.m_iActiveLightMask   =-1;  
    me.m_fDepth             =0.0f;

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

    Vector3D VPN = Vector3D(0.0f, 0.0f, 1.0f);
    Vector3D VRP = Vector3D(3.0f, 0.0f, 0.0f);
    Vector3D VUP = Vector3D(0.0f, 3.0f, 0.0f);
    
    Matrix4X4 mAux;
    ToTransform(&mAux, &Vector3D(0.0f, 0.0f, 0.0f), &Quaternion(fTime, Vector3D(1.0f, 1.0f, 0.0).Normalize()));


    Vector3D vGrav(0.0f, -1.0, 0.0f);
    vGrav*=0.2f;
    
    int k;

    float fOriginal = fTime;
    for (k = 0 ; k < 40 ; k++)
    {
      fTime+=k;

      Vector3D vTarget(sinf(1.f*sinf(fTime)), 2.0f, cosf(1.f*sinf(fTime)));
      Vector3D vOld(-sinf(1.f*sinf(fTime)), 0.0f, -cosf(1.f*sinf(fTime)));    
    

      Vector3D vCurrent(0.0f, 0.0f, 0.0f);

      float fDist = 0.5f;
    
      
      Vector3D v3dHeading = vTarget.Normalize();
      for (j = 0 ; j < ROWS ; j++)
      {
        FVF_PosNormalDiffuseTex1* pV = pVTentacle+j*COLUMNS;    

        //fDist = j;

        float fRadius = 0.2f*(1.0f-float(j)*(1.0f/float(ROWS-1)));    
        //fRadius = 1.0f;
        
        if (Vector3D::Dot(Vector3D(0.0f, 0.0f, 1.0f), v3dHeading) > 0.2f)
        {
          VUP = Vector3D::Cross(Vector3D(0.0f, 0.0f, 1.0f), v3dHeading).Normalize();      
        }
        else
        {
          VUP = Vector3D::Cross(Vector3D(0.0f, 1.0f, 0.0f), v3dHeading).Normalize();      
        }
        VRP = Vector3D::Cross(VUP, v3dHeading);
        VUP.Normalize();
        VRP.Normalize();
      

        Vector3D vPos1 = vCurrent;
        Vector3D vPos2= vCurrent+VUP*fRadius;
        Vector3D vPos3 = vCurrent+VRP*fRadius;
        Vector3D vNorm1 = vPos2-vPos1;
        Vector3D vNorm2 = vPos3-vPos3;
        Vector3D vNorm3 = vPos1-vPos3;
      
        pV[0].x = vPos1.x; pV[0].y = vPos1.y; pV[0].z = vPos1.z; pV[0].nx = vNorm1.x; pV[0].ny = vNorm1.y; pV[0].nz = vNorm1.z; pV[0].diffuse=0xFFFFFFFF;
        pV[1].x = vPos2.x; pV[1].y = vPos2.y; pV[1].z = vPos2.z; pV[1].nx = vNorm2.x; pV[1].ny = vNorm2.y; pV[1].nz = vNorm2.z; pV[1].diffuse=0xFFFFFFFF;
        pV[2].x = vPos3.x; pV[2].y = vPos3.y; pV[2].z = vPos3.z; pV[2].nx = vNorm3.x; pV[2].ny = vNorm3.y; pV[2].nz = vNorm3.z; pV[2].diffuse=0xFFFFFFFF;
      
        v3dHeading += vGrav*0.2f+vOld*2.0f;
        v3dHeading.Normalize();
        vCurrent += v3dHeading*0.4f;            
      }


      me.m_iShader            =ShaderManager::FindShader("pulpo");
      me.m_iVB                =-1;
      me.m_iIB                =-1;
      me.m_pVertices          =pVTentacle; 
      me.m_pIndices           =pusTentacle;
      me.m_uStartVertex       =0;
      me.m_uVertices          =ROWS*COLUMNS;
      me.m_uStartIndex        =0;
      me.m_uPrimitives        =(ROWS-1)*(COLUMNS)*2;   
      me.m_WorldTransform     =Matrix4X4::Identity;
      me.m_iActiveLightMask   =-1;  
      me.m_fDepth             =0.0f;

      ToTransform(&me.m_WorldTransform, &Vector3D(0.0f, 2.0f, 0.0f), &Quaternion(fTime, Vector3D(0.0f, 1.0f, 0.0).Normalize()));    
    

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

  int      Run(float fTime)
  {

    // Paint a poly example!!! 
    RenderContext RC;   

    RC.Set(
    Vector3D(0.0f, 0.0f, -10.0f),
    Quaternion(1.0f, 0.0f, 0.0f, 0.0f),
    90,
    0.75f,
    1.0f,
    200.0f);

    RC.SetViewport(0, 0, 640.0f, 480.0f);  
  
    RC.SyncRasterizer();
    RC.UpdateFrustum();

    ShaderManager::SetRenderContext(&RC);

    RenderPulpo(fTime);
    

    return 1;
  }

  int      Command           (float fTime, const char* pcCommand)
  {
    SM_DemoEffect::Command(fTime, pcCommand);
    char* pcCopy =0;
    char* pcToken;
    int   iReturn=-1;
    
    pcCopy=new char[strlen(pcCommand)+1];
    strcpy(pcCopy, pcCommand);

    pcToken=strtok(pcCopy, " \t");

    if (pcToken)
    if (strcmp(pcToken, "FILL THIS UP")==0)
    {
    }

    iReturn  = 0;
    
    if (pcCopy) { delete[] pcCopy; pcCopy=0; }
    return iReturn;
  }  
};

DEFINE_EFFECT(PulpoFX)
PulpoFX ElPulpo("PULPOTEST");

/*
    // Paint a poly example!!! 
    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.0f, 480.0f);  
  
    RC.SyncRasterizer();
    RC.UpdateFrustum();

    MeshElement me;

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

    pVertices[0].x=0.0f; pVertices[0].y=0.0f; pVertices[0].z=10.0f; 
    pVertices[0].nx=0.0f; pVertices[0].ny=0.0f; pVertices[0].nz=1.0f;
    pVertices[0].u=0.0f; pVertices[0].v=0.0f; pVertices[0].diffuse=0xFFFFFFFF;

    pVertices[1].x=0.0f; pVertices[1].y=10.0f; pVertices[1].z=10.0f; 
    pVertices[1].nx=0.0f; pVertices[1].ny=0.0f; pVertices[1].nz=1.0f;
    pVertices[1].u=0.0f; pVertices[1].v=0.0f; pVertices[1].diffuse=0xFFFFFFFF;

    pVertices[2].x=10.0f; pVertices[2].y=10.0f; pVertices[2].z=10.0f; 
    pVertices[2].nx=1.0f; pVertices[2].ny=0.0f; pVertices[2].nz=0.0f;
    pVertices[2].u=0.0f; pVertices[2].v=0.0f; pVertices[2].diffuse=0xFFFFFFFF;
    
    me.m_iShader            =ShaderManager::FindShader("NULL");
    me.m_iVB                =-1;
    me.m_iIB                =-1;
    me.m_pVertices          =pVertices; 
    me.m_pIndices           =pusIndices;
    me.m_uStartVertex       =0;
    me.m_uVertices          =3;
    me.m_uStartIndex        =0;
    me.m_uPrimitives        =1;
    me.m_WorldTransform     =Matrix4X4::Identity;
    me.m_uActiveLightMask   =-1;  
    me.m_fDepth             =0.0f;

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