//===============================================================================
// @ Player.cpp
// ------------------------------------------------------------------------------
// Player
//
// Copyright (C) 2004 by Elsevier, Inc. All rights reserved.
//
//
//
// This example demonstrates texture wrapping and clamping in the U and V
// dimensions.  A quad is drawn, and texture coordinates may be selected -
// one set of coordinates (the default) are in the unit square, and will not be
// affected by the wrapping mode.  The other set of UVs are outside of the unit
// square in both dimensions, and will exhibit different behavior, depending on
// the wrapping mode.  The texture is chosen from a set of two, so that the
// exact nature of wrapping and clamping may be explored
//
// The key commands are:
//
// h - switch horizontal texture wrapping (wrapping or clamping)
// v - switch vertical texture wrapping (wrapping or clamping)
// t - change texture image
// c - change texture coordinates
//
//===============================================================================

//-------------------------------------------------------------------------------
//-- Dependencies ---------------------------------------------------------------
//-------------------------------------------------------------------------------

#include <IvEventHandler.h>
#include <IvGLHelp.h>
#include <IvImage.h>
#include <IvMath.h>
#include <IvMatrix44.h>

#include "Player.h"
#include "Game.h"

//-------------------------------------------------------------------------------
//-- Static Members -------------------------------------------------------------
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
//-- Methods --------------------------------------------------------------------
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
// @ Player::Player()
//-------------------------------------------------------------------------------
// Constructor
//-------------------------------------------------------------------------------
Player::Player()
{
    mHorizontalWrap = true;
    mVerticalWrap = true;

    mCurrentUVIndex = 0;

    unsigned int i;
    for (i = 0; i < NUM_TEX; i++)
        mTextureIDs[i] = 0;

    mCurrentTexIndex = 0;

    glEnable( GL_TEXTURE_2D );

    // create a texture "name" to reference later
    glGenTextures( NUM_TEX, mTextureIDs );

    glBindTexture( GL_TEXTURE_2D, mTextureIDs[0] );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    // Load the soup can image into this texture
    IvImage* image = IvImage::CreateFromFile("image.tga");
    if (image)
    {
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 
            image->GetWidth(), image->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, 
            image->GetPixels() );
        delete image;
        image = 0;
    }

    // create a texture "name" to reference later
    glBindTexture( GL_TEXTURE_2D, mTextureIDs[1] );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    // create checkerboard texture
    const unsigned int size = 128;
    unsigned char pixels[3 * size * size]; // RGB per texel

    unsigned char* tempPixels = pixels;

    unsigned int j;
    for (i = 0; i < size; i++)
    {
        for (j = 0; j < size; j++)
        {
            // 8x8 texel squares of black and white
            unsigned char color;
            if (((j >> 3) + (i >> 3)) % 2)
                color = 255;
            else
                color = 0;

            // set all three components to the same value
            tempPixels[0] = tempPixels[1] = tempPixels[2] = color;
            
            tempPixels += 3;
        }
    }

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, 
        GL_UNSIGNED_BYTE, pixels );

    glDisable( GL_TEXTURE_2D );

    CreateQuadVertexArrays();
}   // End of Player::Player()


//-------------------------------------------------------------------------------
// @ Player::~Player()
//-------------------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------------------
Player::~Player()
{
    // release the allocated texture
    glDeleteTextures(NUM_TEX, mTextureIDs); 

}   // End of Player::~Player()


//-------------------------------------------------------------------------------
// @ Player::Update()
//-------------------------------------------------------------------------------
// Main update loop
//-------------------------------------------------------------------------------
void
Player::Update( float dt )
{
    // change texture
    if (IvGame::mGame->mEventHandler->IsKeyDown('t'))
    {
        mCurrentTexIndex = (mCurrentTexIndex + 1) % NUM_TEX;
        IvGame::mGame->mEventHandler->KeyUp('t');
    }

    // change texture UVs
    if (IvGame::mGame->mEventHandler->IsKeyDown('c'))
    {
        mCurrentUVIndex = (mCurrentUVIndex + 1) % NUM_UVS;
        IvGame::mGame->mEventHandler->KeyUp('c');
    }

    // change horizontal UV wrapping
    if (IvGame::mGame->mEventHandler->IsKeyDown('h'))
    {
        mHorizontalWrap = !mHorizontalWrap;
        IvGame::mGame->mEventHandler->KeyUp('h');
    }

    // change vertical UV wrapping
    if (IvGame::mGame->mEventHandler->IsKeyDown('v'))
    {
        mVerticalWrap = !mVerticalWrap;
        IvGame::mGame->mEventHandler->KeyUp('v');
    }

}   // End of Player::Update()


//-------------------------------------------------------------------------------
// @ Player::Render()
//-------------------------------------------------------------------------------
// Render stuff
//-------------------------------------------------------------------------------
void 
Player::Render()                                    
{   
    // turn off the lights
    glDisable( GL_LIGHTING );

    glEnable( GL_TEXTURE_2D );
    glBindTexture( GL_TEXTURE_2D, mTextureIDs[mCurrentTexIndex] );

    // Set the wrapping, based on the user-selected flags
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
        mHorizontalWrap ? GL_REPEAT : GL_CLAMP);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
        mVerticalWrap ? GL_REPEAT : GL_CLAMP);

    // draw geometry
    glColor3f(1.0f, 1.0f, 1.0f);
    DrawQuadVertexArrays();

    glDisable( GL_TEXTURE_2D );

}   // End of Player::Render()


//-------------------------------------------------------------------------------
// @ Player::DrawQuadVertexArrays()
//-------------------------------------------------------------------------------
// Draw vertex arrays for a quad centered around the origin
//-------------------------------------------------------------------------------
void
Player::DrawQuadVertexArrays()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, mQuadVerts); 
    glTexCoordPointer(2, GL_FLOAT, 0, mQuadUVs[mCurrentUVIndex]); 
    
    glDrawElements(GL_TRIANGLE_STRIP, QUAD_INDEX_COUNT, GL_UNSIGNED_SHORT, 
        mQuadIndices);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} // End of Player::DrawQuadVertexArrays()
    
//-------------------------------------------------------------------------------
// @ Player::CreateQuadVertexArrays()
//-------------------------------------------------------------------------------
// Create vertex arrays for a quad centered around the origin
//-------------------------------------------------------------------------------
void 
Player::CreateQuadVertexArrays()                                    
{
    const float size = 3.0f;

    // For each vertex, set a position and two texture coordinates
    mQuadVerts[0] = IvVector3(-size, 0, -size);
    mQuadUVs[0][0] = IvVector2(0.0f, 0.0f);
    mQuadUVs[1][0] = IvVector2(-1.0f, -1.0f);

    mQuadVerts[1] = IvVector3(size, 0, -size);
    mQuadUVs[0][1] = IvVector2(1.0f, 0.0f);
    mQuadUVs[1][1] = IvVector2(2.0f, -1.0f);

    mQuadVerts[2] = IvVector3(-size, 0, size);
    mQuadUVs[0][2] = IvVector2(0.0f, 1.0f);
    mQuadUVs[1][2] = IvVector2(-1.0f, 2.0f);

    mQuadVerts[3] = IvVector3(size, 0, size);
    mQuadUVs[0][3] = IvVector2(1.0f, 1.0f);
    mQuadUVs[1][3] = IvVector2(2.0f, 2.0f);

    // quad indices are simple - four indices that indicate the quad in CCW order
    mQuadIndices[0] = 0;
    mQuadIndices[1] = 1;
    mQuadIndices[2] = 2;
    mQuadIndices[3] = 3;

}   // End of Player::CreateQuadVertexArrays()



