#include "DevLib.h"
/******************************************************************************
 * Background.cpp                                                             *
 ******************************************************************************
 * Project      : Futura (DevLib Demo)                                        *
 * License      : LGPL (full notice can be found at root directory)           *
 * Created by   : Arnaud Storq (norecess@devlib-central.org)                  *
 ******************************************************************************/
#include "Background.h"
#include "Application.h"

// ---------------------------------------------------------------------------- DEFINE
#define SCALE_CLOUDS        5.0f
#define SCALE_WRAP          50.0f

// ---------------------------------------------------------------------------- CONSTRUCTOR
Background::Background( )
{
    m_background = 0;
    m_clouds = 0;

    m_meshClouds = Mesh::createMesh( );

    VertexBuffer *vertexBuffer = VertexBuffer::createVertexBuffer( false, 4 );
    assert( vertexBuffer );

    Vertice *vertices = vertexBuffer->lock( );
    vertices[0].posX = -1.0f;
    vertices[0].posY = 1.0f;
    vertices[0].posZ = 0.0f;
    vertices[0].u1 = 0.0f;
    vertices[0].v1 = SCALE_WRAP;
    vertices[1].posX = 1.0f;
    vertices[1].posY = 1.0f;
    vertices[1].posZ = 0.0f;
    vertices[1].u1 = SCALE_WRAP;
    vertices[1].v1 = SCALE_WRAP;
    vertices[2].posX = -1.0f;
    vertices[2].posY = -1.0f;
    vertices[2].posZ = 0.0f;
    vertices[2].u1 = 0.0f;
    vertices[2].v1 = 0.0f;
    vertices[3].posX = 1.0f;
    vertices[3].posY = -1.0f;
    vertices[3].posZ = 0.0f;
    vertices[3].u1 = SCALE_WRAP;
    vertices[3].v1 = 0.0f;
    vertexBuffer->unlock( );
    m_meshClouds->setVertexBuffer( vertexBuffer );

    IndexBuffer *indexBuffer = IndexBuffer::createIndexBuffer( false, 6 );
    int *indices = indexBuffer->lock( );
    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 2;
    indices[3] = 2;
    indices[4] = 1;
    indices[5] = 3;
    indexBuffer->unlock( );
    m_meshClouds->setIndexBuffer( indexBuffer );

    Material *material = m_meshClouds->createMaterial( );
    material->setBoundary( 0, indexBuffer->getNumIndices( ), 0, vertexBuffer->getNumVertices( ) );
    material->setRenderState( 0, RS_MAPPING, RV_MAPPING_VERTEX_UV_WRAPPING );
    material->setRenderState( 0, RS_BLENDING, RV_BLENDING_TEXTURE_ADDITIVE );
}

// ---------------------------------------------------------------------------- DESTRUCTOR
Background::~Background( )
{
    if ( m_background )
        delete m_background;

    if ( m_clouds )
        delete m_clouds;

    if ( m_meshClouds )
        delete m_meshClouds;
}

// ---------------------------------------------------------------------------- CREATE BACKGROUND
Background *Background::createBackground( )
{
    return new Background( );
}

// ---------------------------------------------------------------------------- DISPLAY UPDATE
void Background::displayUpdate( )
{
    float time = Application::getInstance( )->getTime( );

    RenderSystem *rs = RenderSystemManager::getRenderSystem( );

    // Set matrix projection
    rs->setMatrixMode( MATRIX_MODE_PROJECTION );
    Matrix matrixProjection;
    matrixProjection.setPerspective(    0.00001f, // minimum Z-value
                                        1000.0f, // maximum Z-value
                                        45.0f, // focal
                                        ( (float) rs->getWidth( ) ) / ( (float) rs->getHeight( ) ) // ratio
                                        );
    rs->loadMatrix( matrixProjection );

    // Set view projection
    rs->setMatrixMode( MATRIX_MODE_MODELVIEW );	
    rs->loadIdentityMatrix( );

    // Display background texture (scaled to viewport)
    m_background->render( 0, 0, rs->getWidth( ), rs->getHeight( ) );

    // Set view projection
    rs->translateMatrix( cos( time * 0.15f ), -0.04f, sin( time * 0.1f ) );
    rs->rotateMatrix( -90.0f, 1.0f, 0.0f, 0.0f );
    rs->scaleMatrix( SCALE_CLOUDS, SCALE_CLOUDS, SCALE_CLOUDS );

    // Set Z-buffer state
    rs->setRenderState( RS_ZBUFFER, RV_ZBUFFER_NEVER );

    // Set culling
    rs->setRenderState( RS_CULLING, RV_CULLING_NONE );
    
    m_meshClouds->render( );
}

// ---------------------------------------------------------------------------- SET TEXTURES
void Background::setTextures( const string backgroundFilename, const string cloudsFilename )
{
    if ( m_background )
        delete m_background;
    m_background = Texture::createTexture( false, backgroundFilename );

    if ( m_clouds )
        delete m_clouds;
    m_clouds = Texture::createTexture( false, cloudsFilename );

    Material *material = m_meshClouds->getMaterial( 0 );
    material->setTexture( 0, m_clouds );
}
