//
// 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 "CWrapperMemoryReadFile.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"
{

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

/****h* Terrain
* NAME
*   Terrain-Functions
* DESCRIPTION
*   Under this Section we find the Function to create and modify terrains.
*   As base of a Terrain you need 'heightmap', thats a simple grayscaled
*   image. Based on the brightness, irrlicht creates a Mesh from that data.
*
*   The terrain scene node is capable of very quickly loading terrains and updating the indices
*   at runtime to enable viewing very large terrains. It uses a CLOD ( Continuous Level
*   of Detail ) algorithm which updates the indices for each patch based on a LOD ( Level
*   of Detail ) which is determined based on a patch's distance from the camera.
*
*   The Patch Size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ).
*   The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains
*   all of the indices to draw all the triangles at the max detail for a patch. As each LOD goes
*   up by 1 the step taken, in generating indices increases by - 2^LOD, so for LOD 1, the step
*   taken is 2, for LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than
*   the size of the patch, so having a LOD of 8, with a patch size of 17, is asking the algoritm
*   to generate indices every 2^8 ( 256 ) vertices, which is not possible with a patch size of 17.
*   The maximum LOD for a patch size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0
*   ( full detail ), LOD 1 ( every 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices )
*   and LOD 4 ( every 16 vertices ).
*
* TODO
*   Eanble to Load a Heightmap from Memory
*   Provide function to manipulate the Terrain....
*/

/****f* Terrain/IrrAddTerrain
* NAME
*    IrrAddTerrain - create a terrain node from a highfield map
* SYNOPSIS
*    IrrAddTerrain(filename.s)
* INPUTS
*   filename.s      -   name of the xml file
* FUNCTION
*   Adds a terrain scene node to the scene graph
* RESULT
*    #Null if no node created, otherwise the pointer to the node.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddTerrain(filename.p-ascii)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddTerrain( char *cptrFile )
{
    return smgr->addTerrainSceneNode( cptrFile);
}


/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddTerrainRAWFromMemory(*memory, len.l, bitsPerPixel.l)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddTerrainRAWFromMemory( void* memory, s32 len, s32 bitsPerPixel)
{
    ITerrainSceneNode* terrain = smgr->addTerrainSceneNodeRAW(device->getFileSystem()->createMemoryReadFile(memory, len, "something.raw"), bitsPerPixel);
    if (terrain)
        return (void*)terrain;
    return NULL;
}

/****f* Terrain/IrrScaleTexture
* NAME
*    IrrScaleTexture - Scales the base texture
* SYNOPSIS
*    IrrScaleTexture(*terrain, scale1.f, scale2.f)
* INPUTS
*   *terrain    - a pointer to terrain scene node
*   scale1.f    - The scaling amount. Values above 1.0 increase the number of time the texture
*                 is drawn on the terrain. Values below 0 will decrease the number of times the
*                 texture is drawn on the terrain. Using negative values will flip the texture,
*                 as well as still scaling it.
*   scale2.f    - If set to 0 (default value), this will set the second texture coordinate set to
*                 the same values as in the first set. If this is another value than zero, it will
*                 scale the second texture coordinate set by this value.
* FUNCTION
*   Scales the base texture, similar to makePlanarTextureMapping.
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrScaleTexture(*terrain, scale1.f, scale2.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrScaleTexture ( ITerrainSceneNode* terrain, float X, float Y )
{
    terrain->scaleTexture(X,Y);
}

/****f* Terrain/IrrTerrainHeight
* NAME
*    IrrTerrainHeight - Get the Height of a point.
* SYNOPSIS
*    IrrTerrainHeight(*terrain, x.f, y.f, *height.f)
* INPUTS
*   *terrain    - a pointer to terrain scene node
*   x.f, y.f    - point on the Terrain
*   *height.f   - returns the height
* FUNCTION
*   Returns height of a point of the terrain.
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainHeight(*terrain, x.f, y.f, *height.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainHeight ( ITerrainSceneNode* terrain, float X, float Y, float &retHeight )
{
    f32 r = terrain->getHeight(X,Y);
    retHeight = r;

//    printf("height for(%f,%f)=%f)\n", X,Y,retHeight);
}

/****f* Terrain/IrrTerrainGetIndexCount
* NAME
*    IrrTerrainGetIndexCount - Returns the number of indices
* SYNOPSIS
*    IrrTerrainGetIndexCount(*terrain)
* INPUTS
*   *terrain    - a pointer to terrain scene node
* FUNCTION
*   Returns the number of indices currently in the meshbuffer for this scene node.
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainGetIndexCount(*terrain)
*/
STATIC_EXPORT int DLL_EXPORT IrrTerrainGetIndexCount ( ITerrainSceneNode* terrain)
{
    return terrain->getIndexCount();
}

/****f* Terrain/IrrTerrainGetCenter
* NAME
*    IrrTerrainGetCenter - Returns center of terrain.
* SYNOPSIS
*    IrrTerrainGetCenter(*terrain,*x.f,*y.f,*z.f)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   *x.f,*y.f,*z.f  - returns the center vector
* FUNCTION
*   Returns center of terrain.
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainGetCenter(*terrain,*x.f,*y.f,*z.f)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainGetCenter ( ITerrainSceneNode* terrain, float &x, float &y, float &z)
{
    vector3df ret = terrain->getTerrainCenter();
    x = ret.X;
    y = ret.Y;
    z = ret.Z;
}

/****f* Terrain/IrrTerrainOverrideLODDistance
* NAME
*    IrrTerrainOverrideLODDistance - Override the default generation of distance thresholds.
* SYNOPSIS
*    IrrTerrainOverrideLODDistance(*terrain, LOD.l, newDistance.d)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   LOD.l           - new Level of Detail
*   newDistance.d   - ne distance
* FUNCTION
*   Override the default generation of distance thresholds.
*   For determining the LOD a patch is rendered at. If any LOD is overridden, then the
*   scene node will no longer apply scaling factors to these values. If you override
*   these distances, and then apply a scale to the scene node, it is your responsibility
*   to update the new distances to work best with your new terrain size.
*
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainOverrideLODDistance(*terrain, LOD.l, newDistance.d)
*/
STATIC_EXPORT bool DLL_EXPORT IrrTerrainOverrideLODDistance ( ITerrainSceneNode* terrain, s32 LOD, f64 newDistance)
{
    return terrain->overrideLODDistance(LOD,newDistance);
}

/****f* Terrain/IrrTerrainSetCameraMovementDelta
* NAME
*    IrrTerrainSetCameraMovementDelta - Sets the movement camera threshold.
* SYNOPSIS
*    IrrTerrainSetCameraMovementDelta(*terrain, delta.f)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   delta.f         - delta
* FUNCTION
*   Sets the movement camera threshold.
*   It is used to determine when to recalculate indices for the scene node. The default value is 10.0.
*
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainSetCameraMovementDelta(*terrain, delta.f = 10.0)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainSetCameraMovementDelta ( ITerrainSceneNode* terrain, f32 delta)
{
    terrain->setCameraMovementDelta(delta);
}

/****f* Terrain/IrrTerrainSetCameraRotationDelta
* NAME
*    IrrTerrainSetCameraRotationDelta - Sets the rotation camera threshold.
* SYNOPSIS
*    IrrTerrainSetCameraRotationDelta(*terrain, delta.f)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   delta.f         - delta
* FUNCTION
*   Sets the rotation camera threshold.
*   It is used to determine when to recalculate indices for the scene node. The default value is 1.0.
*
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainSetCameraRotationDelta(*terrain, delta.f=1.0)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainSetCameraRotationDelta ( ITerrainSceneNode* terrain, f32 delta)
{
    terrain->setCameraRotationDelta(delta);
}


/****f* Terrain/IrrTerrainSetDynamicSelectorUpdate
* NAME
*    IrrTerrainSetDynamicSelectorUpdate - Update its associated selector when change
* SYNOPSIS
*    IrrTerrainSetDynamicSelectorUpdate(*terrain, bbVal.l)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   bbVal.l         - #True or #False
* FUNCTION
*   Sets whether or not the node should dynamically update its associated selector
*   when the geomipmap data changes.
*
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainSetDynamicSelectorUpdate(*terrain, bbVal.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainSetDynamicSelectorUpdate ( ITerrainSceneNode* terrain, bool bVal)
{
    terrain->setDynamicSelectorUpdate(bVal);
}


/****f* Terrain/IrrTerrainSetLODOfPatch
* NAME
*    IrrTerrainSetLODOfPatch - Manually sets the LOD of a patch.
* SYNOPSIS
*    IrrTerrainSetLODOfPatch(*terrain, patchX.l, patchZ.l, LOD.l)
* INPUTS
*   *terrain        - a pointer to terrain scene node
*   patchX.l        - Patch x coordinate
*   patchZ.l        - Patch z coordinate
*   LOD.l           - Level of Detail
* FUNCTION
*   Manually sets the LOD of a patch.
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrTerrainSetLODOfPatch(*terrain, patchX.l, patchZ.l, LOD.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrTerrainSetLODOfPatch ( ITerrainSceneNode* terrain, s32 patchX, s32 patchZ, s32 LOD)
{
    terrain->setLODOfPatch(patchX,patchZ,LOD);
}

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