// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2004.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement http://www.wild-magic.com/License/WildMagic3.pdf and
// may not be copied or disclosed except in accordance with the terms of that
// agreement.

#include "Section3p4p3b.h"

WM3_WINDOW_APPLICATION(Section3p4p3b);

//----------------------------------------------------------------------------
Section3p4p3b::Section3p4p3b ()
    :
    WindowApplication3("Section3p4p3b",0,0,320,240,ColorRGB::WHITE)
{
}
//----------------------------------------------------------------------------
bool Section3p4p3b::OnInitialize ()
{
    if ( !WindowApplication3::OnInitialize() )
        return false;

    // camera and view frustum
    m_spkCamera->SetFrustum(-0.055f,0.055f,-0.04125f,0.04125f,0.1f,10.0f);
#ifdef ONE_SQUARE
    Vector3f kCLoc(0.0f,0.0f,3.0f);
#else
    Vector3f kCLoc(0.0f,0.0f,1.45f);
#endif
    Vector3f kCDir(0.0f,0.0f,-1.0f);
    Vector3f kCUp(0.0f,1.0f,0.0f);
    Vector3f kCRight = kCDir.Cross(kCUp);
    m_spkCamera->SetFrame(kCLoc,kCDir,kCUp,kCRight);

    m_spkScene = new Node(1);

#ifdef ONE_SQUARE
    // one square
    Vector3f* akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f( 1.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f( 1.0f, 1.0f,0.0f);
    akVertex[3] = Vector3f(-1.0f, 1.0f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(5,akVertex);

    Vector2f* akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(2.0f,0.0f);
    akUV[2] = Vector2f(2.0f,2.0f);
    akUV[3] = Vector2f(0.0f,2.0f);
    Vector2fArray* pkUVs = new Vector2fArray(4,akUV);

    int* aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    IntArray* pkIndices = new IntArray(6,aiIndex);

    m_spkMesh = new TriMesh(pkVertices,pkIndices,false);
    m_spkScene->AttachChild(m_spkMesh);

    m_spkTexture = new Texture(Image::Load("Water.wmif"));
    m_spkTexture->CoordU = Texture::WM_REPEAT;
    m_spkTexture->CoordV = Texture::WM_REPEAT;
    Effect* pkEffect = new TextureEffect(m_spkTexture,pkUVs);
    m_spkMesh->SetEffect(pkEffect);
#else
    // two squares
    Vector3f* akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(-1.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f( 0.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f( 0.0f, 1.0f,0.0f);
    akVertex[3] = Vector3f(-1.0f, 1.0f,0.0f);
    Vector3fArray* pkVertices = new Vector3fArray(5,akVertex);

    Vector2f* akUV = new Vector2f[4];
    akUV[0] = Vector2f(0.0f,0.0f);
    akUV[1] = Vector2f(1.0f,0.0f);
    akUV[2] = Vector2f(1.0f,1.0f);
    akUV[3] = Vector2f(0.0f,1.0f);
    Vector2fArray* pkUVs = new Vector2fArray(4,akUV);

    int* aiIndex = new int[6];
    aiIndex[0] = 0;  aiIndex[1] = 1;  aiIndex[2] = 2;
    aiIndex[3] = 0;  aiIndex[4] = 2;  aiIndex[5] = 3;
    IntArray* pkIndices = new IntArray(6,aiIndex);

    m_spkMesh0 = new TriMesh(pkVertices,pkIndices,false);
    m_spkScene->AttachChild(m_spkMesh0);

    m_spkTexture0 = new Texture(Image::Load("Water0.wmif"));
    m_spkTexture0->CoordU = Texture::WM_CLAMP;
    m_spkTexture0->CoordV = Texture::WM_CLAMP;
    Effect* pkEffect = new TextureEffect(m_spkTexture0,pkUVs);
    m_spkMesh0->SetEffect(pkEffect);

    akVertex = new Vector3f[4];
    akVertex[0] = Vector3f(0.0f,-1.0f,0.0f);
    akVertex[1] = Vector3f(1.0f,-1.0f,0.0f);
    akVertex[2] = Vector3f(1.0f, 1.0f,0.0f);
    akVertex[3] = Vector3f(0.0f, 1.0f,0.0f);
    pkVertices = new Vector3fArray(5,akVertex);

    m_spkMesh1 = new TriMesh(pkVertices,pkIndices,false);
    m_spkScene->AttachChild(m_spkMesh1);

    m_spkTexture1 = new Texture(Image::Load("Water1.wmif"));
    m_spkTexture1->CoordU = Texture::WM_CLAMP;
    m_spkTexture1->CoordV = Texture::WM_CLAMP;
    pkEffect = new TextureEffect(m_spkTexture1,pkUVs);
    m_spkMesh1->SetEffect(pkEffect);
#endif

    m_spkScene->UpdateGS();
    m_spkScene->UpdateRS();

    InitializeCameraMotion(0.0001f,0.001f);
    InitializeObjectMotion(m_spkScene);
    return true;
}
//----------------------------------------------------------------------------
void Section3p4p3b::OnTerminate ()
{
    m_spkScene = 0;
#ifdef ONE_SQUARE
    m_spkMesh = 0;
    m_spkTexture = 0;
#else
    m_spkMesh0 = 0;
    m_spkTexture0 = 0;
    m_spkMesh1 = 0;
    m_spkTexture1 = 0;
#endif
    WindowApplication3::OnTerminate();
}
//----------------------------------------------------------------------------
void Section3p4p3b::OnIdle ()
{
    MoveCamera();
    if ( MoveObject() )
        m_spkScene->UpdateGS();

    m_pkRenderer->ClearBuffers();
    if ( m_pkRenderer->BeginScene() )
    {
        m_pkRenderer->DrawScene(m_spkScene);
        m_pkRenderer->EndScene();
    }
    m_pkRenderer->DisplayBackBuffer();
}
//----------------------------------------------------------------------------
bool Section3p4p3b::OnKeyDown (unsigned char ucKey, int iX, int iY)
{
    if ( WindowApplication3::OnKeyDown(ucKey,iX,iY) )
        return true;

#ifdef ONE_SQUARE
    switch ( ucKey )
    {
    case '0':  // wrap u, wrap v
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_REPEAT;
        m_spkTexture->CoordV = Texture::WM_REPEAT;
        m_spkTexture->BorderColor = ColorRGBA::INVALID;
        return true;
    case '1':  // wrap u, clamp v
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_REPEAT;
        m_spkTexture->CoordV = Texture::WM_CLAMP;
        m_spkTexture->BorderColor = ColorRGBA::INVALID;
        return true;
    case '2':  // clamp u, wrap v
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_CLAMP;
        m_spkTexture->CoordV = Texture::WM_REPEAT;
        m_spkTexture->BorderColor = ColorRGBA::INVALID;
        return true;
    case '3':  // clamp u, clamp v
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_CLAMP;
        m_spkTexture->CoordV = Texture::WM_CLAMP;
        m_spkTexture->BorderColor = ColorRGBA::INVALID;
        return true;
    case '4':  // clamp to border
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_CLAMP_BORDER;
        m_spkTexture->CoordV = Texture::WM_CLAMP_BORDER;
        m_spkTexture->BorderColor = ColorRGBA(1.0f,0.0f,0.0f,1.0f);
        return true;
    case '5':  // clamp to edge
        m_pkRenderer->ReleaseTexture(m_spkTexture);
        m_spkTexture->CoordU = Texture::WM_CLAMP_EDGE;
        m_spkTexture->CoordV = Texture::WM_CLAMP_EDGE;
        m_spkTexture->BorderColor = ColorRGBA::INVALID;
        return true;
    }
#else
    switch ( ucKey )
    {
    case '0':  // clamp
        m_pkRenderer->ReleaseTexture(m_spkTexture0);
        m_spkTexture0->CoordU = Texture::WM_CLAMP;
        m_spkTexture0->CoordV = Texture::WM_CLAMP;
        m_spkTexture0->BorderColor = ColorRGBA::INVALID;

        m_pkRenderer->ReleaseTexture(m_spkTexture1);
        m_spkTexture1 = new Texture(Image::Load("Water1.wmif"));
        m_spkTexture1->CoordU = Texture::WM_CLAMP;
        m_spkTexture1->CoordV = Texture::WM_CLAMP;
        m_spkTexture1->BorderColor = ColorRGBA::INVALID;
        m_spkMesh1->GetEffect()->Textures[0] = m_spkTexture1;
        return true;
    case '1':  // clamp to border
        m_pkRenderer->ReleaseTexture(m_spkTexture0);
        m_spkTexture0->CoordU = Texture::WM_CLAMP_BORDER;
        m_spkTexture0->CoordV = Texture::WM_CLAMP_BORDER;
        m_spkTexture0->BorderColor = ColorRGBA(1.0f,0.0f,0.0f,1.0f);

        m_pkRenderer->ReleaseTexture(m_spkTexture1);
        m_spkTexture1 = new Texture(Image::Load("Water1.wmif"));
        m_spkTexture1->CoordU = Texture::WM_CLAMP_BORDER;
        m_spkTexture1->CoordV = Texture::WM_CLAMP_BORDER;
        m_spkTexture1->BorderColor = ColorRGBA(1.0f,0.0f,0.0f,1.0f);
        m_spkMesh1->GetEffect()->Textures[0] = m_spkTexture1;
        return true;
    case '2':  // clamp to edge
        m_pkRenderer->ReleaseTexture(m_spkTexture0);
        m_spkTexture0->CoordU = Texture::WM_CLAMP_EDGE;
        m_spkTexture0->CoordV = Texture::WM_CLAMP_EDGE;
        m_spkTexture0->BorderColor = ColorRGBA::INVALID;

        m_pkRenderer->ReleaseTexture(m_spkTexture1);
        m_spkTexture1 = new Texture(Image::Load("Water1.wmif"));
        m_spkTexture1->CoordU = Texture::WM_CLAMP_EDGE;
        m_spkTexture1->CoordV = Texture::WM_CLAMP_EDGE;
        m_spkTexture1->BorderColor = ColorRGBA::INVALID;
        m_spkMesh1->GetEffect()->Textures[0] = m_spkTexture1;
        return true;
    case '3':  // clamp to edge, duplicate pixels on boundary
        m_pkRenderer->ReleaseTexture(m_spkTexture0);
        m_spkTexture0->CoordU = Texture::WM_CLAMP_EDGE;
        m_spkTexture0->CoordV = Texture::WM_CLAMP_EDGE;
        m_spkTexture0->BorderColor = ColorRGBA::INVALID;

        m_pkRenderer->ReleaseTexture(m_spkTexture1);
        m_spkTexture1 = new Texture(Image::Load("Water2.wmif"));
        m_spkTexture1->CoordU = Texture::WM_CLAMP_EDGE;
        m_spkTexture1->CoordV = Texture::WM_CLAMP_EDGE;
        m_spkTexture1->BorderColor = ColorRGBA::INVALID;
        m_spkMesh1->GetEffect()->Textures[0] = m_spkTexture1;
        return true;
    }
#endif

    return false;
}
//----------------------------------------------------------------------------
