//
// Irrlicht Wrapper for Imperative Languages
// Frank Dodd (2006)
//
// Additional Work
// Michael Taupitz (2006)
//
// This wrapper DLL encapsulates a sub-set of the features of the powerful
// Irrlicht 3D Graphics Engine exposing the Object Oriented architecture and
// providing a functional 3D SDK for languages that are not object oriented.
//
// This source was created with the help of the great examples in the Irrlicht
// SDK and the excellent Irrlicht documentation. This software was developed
// using the GCC compiler and Code::Blocks IDE
//

/* ////////////////////////////////////////////////////////////////////////////
includes
*/
#include "irrlichtwrapper.h"
#include"TlTerrainSceneNode.h"

/* ////////////////////////////////////////////////////////////////////////////
global variables
*/

/* ////////////////////////////////////////////////////////////////////////////
external variables
*/
extern IrrlichtDevice *device;
extern IVideoDriver* driver;
extern ISceneManager* smgr;
extern IGUIEnvironment* guienv;


/* ////////////////////////////////////////////////////////////////////////////
Global Function Declarations

all of the below functions are declared as C functions and are exposed without
any mangled names so that they can be easily imported into imperative
languages like FreeBasic
*/
extern "C"
{

/* ////////////////////////////////////////////////////////////////////////////
Tiled TERRAIN FUNCTIONS
*/

/* ----------------------------------------------------------------------------
create a Tiled-Terrain-ScenenNode and Add them to the Scene
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddTiledTerain(u32 sizeX, u32 sizeY, u32 visibility)
{
    return new TlTerrainSceneNode(smgr, dimension2d<u32>(sizeX,sizeY), visibility); //, f32 tlsize = 1.0f)
}



// number of materials used (only one is used)
STATIC_EXPORT long DLL_EXPORT IrrTlTGetMaterialCount(TlTerrainSceneNode* node)
{
    return node->getMaterialCount();
}


// return material used to render visible part of terrain
STATIC_EXPORT void* DLL_EXPORT IrrTlTGetMaterial(TlTerrainSceneNode* node,s32 i)
{
    return (& node->getMaterial(i) );
}


// set height of terrain at given coordinate
STATIC_EXPORT void DLL_EXPORT IrrTlTSetHeight(TlTerrainSceneNode* node,s32 posX, s32 posY, f32 newheight)
{
    node->setHeight(core::vector2d<s32>(posX,posY), newheight);
}

// return height of terrain at given coordinate
STATIC_EXPORT void DLL_EXPORT IrrTlTGetHeight(TlTerrainSceneNode* node,s32 posX, s32 posY, float &retHeight )
{
    retHeight = node->getHeight(core::vector2d<s32>(posX,posY));
}

// set normal vector at given coordinate
STATIC_EXPORT void DLL_EXPORT IrrTlTSetNormal(TlTerrainSceneNode* node,s32 posX, s32 posY , f32 normX, f32 normY, f32 normZ)
{
    node->setNormal(core::vector2d<s32>(posX,posY), core::vector3df(normX,normY,normZ));
}

// return normal vector at given coordinate
STATIC_EXPORT void DLL_EXPORT IrrTlTGetNormal(TlTerrainSceneNode* node,s32 posX, s32 posY , f32 &normX, f32 &normY, f32 &normZ)
{
    vector3df retVec = node->getNormal(core::vector2d<s32>(posX,posY));
    normX = retVec.X;
    normY = retVec.Y;
    normZ = retVec.Z;
}

// set UV coordinates of tile vertices starting with lower left vertice and
// going in clockwise order to lower right one
STATIC_EXPORT void DLL_EXPORT IrrTlTSetTileUVs(TlTerrainSceneNode* node,s32 posX, s32 posY ,
                                                f32 uv0_X,f32 uv0_Y,
                                                f32 uv1_X,f32 uv1_Y,
                                                f32 uv2_X,f32 uv2_Y,
                                                f32 uv3_X,f32 uv3_Y )
{
    node->setTileUVs(core::vector2d<s32>(posX,posY), core::vector2df(uv0_X,uv0_Y),
    core::vector2df(uv1_X,uv1_Y),
    core::vector2df(uv2_X,uv2_Y),
    core::vector2df(uv3_X,uv3_Y) ) ;
}

// return position of visible terrain in tiles and relative to whole terrain
// note that origin of visible terrain is in lower left corner not center
STATIC_EXPORT void DLL_EXPORT IrrTlTGetVisibleTerrainPosition(TlTerrainSceneNode* node,u32 &posX, u32 &posY )
{
    core::vector2d<u32> retPos = node->getVisibleTerrainPosition();
    posX = retPos.X;
    posY = retPos.Y;
}

// place visible part of terrain at given coordinates of whole terrain
// note that origin of visible terrain is in lower left corner not center
STATIC_EXPORT void DLL_EXPORT IrrTlTSetVisibleTerrainPosition(TlTerrainSceneNode* node,u32 posX, u32 posY )
{
//    virtual void setVisibleTerrainPosition(core::vector2d<s32> newposition)
    node->setVisibleTerrainPosition(core::vector2d<u32>(posX,posY));
}

// center part of terrain which is rendered at position in 3d space
STATIC_EXPORT void DLL_EXPORT IrrTlTCenterVisibleTerrainPos(TlTerrainSceneNode* node, f32 x, f32 y, f32 z )
{
    node->centerVisibleTerrain(core::vector3df(x,y,z));
//    virtual void centerVisibleTerrain(core::vector3df pos)
}

// center part of terrain which is rendered at position of node
// can be camera or player node for example
STATIC_EXPORT void DLL_EXPORT IrrTlTCenterVisibleTerrainNode(TlTerrainSceneNode* node, scene::ISceneNode* nodeFollow )
{
    node->centerVisibleTerrain(nodeFollow);
}

// set node which visible terrain should be centered around automaticaly
// can be camera or player node
STATIC_EXPORT void DLL_EXPORT IrrTlTFollow(TlTerrainSceneNode* node, scene::ISceneNode* nodeFollow )
{
    node->follow(nodeFollow);
}
// stop automatic centering
STATIC_EXPORT void DLL_EXPORT IrrTlTStopFollow(TlTerrainSceneNode* node )
{
    node->stopFollowing();
}

// get height of terrain at any position
STATIC_EXPORT void DLL_EXPORT IrrTlTgetHeightPos(TlTerrainSceneNode* node, f32 x, f32 y, f32 z, float &retHeight )
{
    retHeight = node->getHeight(core::vector3df(x,y,z));
}


// load texture
STATIC_EXPORT void DLL_EXPORT IrrTlTsetTexture(TlTerrainSceneNode* node, char* filename)
{
    node->setTexture(filename);
}

STATIC_EXPORT void DLL_EXPORT IrrTlTWireframe(TlTerrainSceneNode* node, bool i)
{
    node->wireframe(i);
}

STATIC_EXPORT void DLL_EXPORT IrrTlTLighting(TlTerrainSceneNode* node, bool i)
{
    node->lighting(i);
}

STATIC_EXPORT void DLL_EXPORT IrrTlTBackfaceCulling(TlTerrainSceneNode* node, bool i)
{
    node->backfaceCulling(i);
}

STATIC_EXPORT void DLL_EXPORT IrrTlTFog(TlTerrainSceneNode* node, bool i)
{
    node->fog(i);
}

STATIC_EXPORT void DLL_EXPORT IrrTlTGetSize(TlTerrainSceneNode* node, u32 &width, u32 &height)
{
    core::dimension2d<u32> retSize = node->getSize();
    width = retSize.Width;
    height = retSize.Height;

}

STATIC_EXPORT void DLL_EXPORT IrrTlTGetTileSize(TlTerrainSceneNode* node, float &retSize)
{
    retSize =  node->getTileSize();
}

// recalculare normals of whole terrain making it smooth
STATIC_EXPORT void DLL_EXPORT IrrTlTSmoothNormals(TlTerrainSceneNode* node)
{
    node->smoothNormals();
}


// this function can be used to check line of sight or bulet collision
// is slower than getHeight so use it only when appropirate
// returns an intersection with a 3d line -stored in "outIntersection"
// return true if line collide with mesh, false if not

STATIC_EXPORT void DLL_EXPORT IrrTlTGetIntersectionWithLine(TlTerrainSceneNode* node,
                                    IRR_VECTOR &vectorStart,
                                    IRR_VECTOR &vectorEnd,
                                    IRR_VECTOR &ourIntersection )
{
    line3d< f32 > ray(  vectorStart.x, vectorStart.y, vectorStart.z,
                        vectorEnd.x, vectorEnd.y, vectorEnd.z );

    vector3df vecRet;
    node->getIntersectionWithLine(ray,vecRet);
    ourIntersection.x = vecRet.X;
    ourIntersection.y = vecRet.Y;
    ourIntersection.z = vecRet.Z;

}


/* ////////////////////////////////////////////////////////////////////////////
all of the above functions are declared as C functions and are exposed without
any mangled names
*/
}
