/*-----------------------------------------------------------------------------*
| headerfile TlMeshBuffer.h                                                    |
|                                                                              |
| version 0.12                                                                 |
| date: (28.12.2006)                                                           |
|                                                                              |
| author:  Michal Švantner                                                     |
|                                                                              |
| for Irrlicht engine v. 1.2                                                   |
| meshbuffer for TlTerrainSceneNode                                            |
*-----------------------------------------------------------------------------*/

#ifndef TLMESHBUFFER_H
#define TLMESHBUFFER_H

#include <irrlicht.h>
using namespace irr;

// structure holding pointers to 4 vertices of tile
/*
struct Tile
{
    video::S3DVertex* vertex[4];
};
*/

typedef struct tag_Tile
{
    video::S3DVertex* vertex[4];
} Tile;


// structure holding mesh of visible part of tiled terrain
class TlMeshBuffer : public scene::SMeshBuffer
{
public:
    // dinamic array of tiles
    Tile** tile;

    // size of array
    u32 size;

    // position on terrain counted in tiles
    core::vector2d<u32> position;

    // constructor
    TlMeshBuffer(u32 isize, f32 tileSize)
    {
        size = isize;
        position = core::vector2d<u32>(0,0);

        // create array of tiles
        tile = new Tile*[size];
        for(u16 i=0; i<size; i++) tile[i] = new Tile[size];

        Vertices.set_used(size * size * 4); // four vertices per tile
        Indices.set_used(size * size * 6);  // two triangles per tile three indices per triangle

        // asign vertices to tiles
        u16 n = 0;
        // vertex ID later used to fill indice array
        u16*** vertexID;
        vertexID = new u16**[size];
        for(u16 i=0; i<size; i++) vertexID[i] = new u16*[size];
        for(u32 j=0; j<size; j++)
            for(u32 i=0; i<size; i++) vertexID[i][j] = new u16[4];

        for(u32 j=0; j<size; j++)
            for(u32 i=0; i<size; i++)
            {
                // lower left vertex of tile
                tile[i][j].vertex[0] = &Vertices[n];
                vertexID[i][j][0] = n;
                n++;
                // upper left vertex of tile
                tile[i][j].vertex[1] = &Vertices[n];
                vertexID[i][j][1] = n;
                n++;
                // upper right vertex of tile
                tile[i][j].vertex[2] = &Vertices[n];
                vertexID[i][j][2] = n;
                n++;
                // lower right vertex of tile
                tile[i][j].vertex[3] = &Vertices[n];
                vertexID[i][j][3] = n;
                n++;
            }

        // asign indices
        n = 0;
        for(u16 j=0; j<size; j++)
            for(u16 i=0; i<size; i++)
            {
                // upper left triangle of tile
                Indices[n] = vertexID[i][j][0];
                n++;
                Indices[n] = vertexID[i][j][1];
                n++;
                Indices[n] = vertexID[i][j][2];
                n++;
                // lower right triangle of tile
                Indices[n] = vertexID[i][j][0];
                n++;
                Indices[n] = vertexID[i][j][2];
                n++;
                Indices[n] = vertexID[i][j][3];
                n++;
            }

        // clear ID array out, no longer needed
        for(u32 j=0; j<size; j++)
            for(u32 i=0; i<size; i++) delete [] vertexID[i][j];
        for(u16 i=0; i<size; i++) delete [] vertexID[i];
        delete [] vertexID;

        // set position, normal, color and UV of vertices
        for(u16 j=0; j<size; j++)
            for(u16 i=0; i<size; i++)
            {
                // lower left vertex
                tile[i][j].vertex[0]->Pos = core::vector3df(i*tileSize,0,j*tileSize);
                tile[i][j].vertex[0]->Normal = core::vector3df(0,1,0);
                tile[i][j].vertex[0]->Color = video::SColor(255,255,255,255);
                tile[i][j].vertex[0]->TCoords = core::vector2df(0,1);
                // upper left vertex
                tile[i][j].vertex[1]->Pos = core::vector3df(i*tileSize,0,(j+1)*tileSize);
                tile[i][j].vertex[1]->Normal = core::vector3df(0,1,0);
                tile[i][j].vertex[1]->Color = video::SColor(255,255,255,255);
                tile[i][j].vertex[1]->TCoords = core::vector2df(0,0);
                // upper right vertex
                tile[i][j].vertex[2]->Pos = core::vector3df((i+1)*tileSize,0,(j+1)*tileSize);
                tile[i][j].vertex[2]->Normal = core::vector3df(0,1,0);
                tile[i][j].vertex[2]->Color = video::SColor(255,255,255,255);
                tile[i][j].vertex[2]->TCoords = core::vector2df(1,0);
                // lower right vertex
                tile[i][j].vertex[3]->Pos = core::vector3df((i+1)*tileSize,0,j*tileSize);
                tile[i][j].vertex[3]->Normal = core::vector3df(0,1,0);
                tile[i][j].vertex[3]->Color = video::SColor(255,255,255,255);
                tile[i][j].vertex[3]->TCoords = core::vector2df(1,1);
            }
    }

    // destructor
    ~TlMeshBuffer()
    {
        // remove array of tiles
        for(u16 i=0; i<size; i++) delete [] tile[i];
        delete [] tile;
    }
};
#endif
