
//
// 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 "CPrimitives.h"
#include "CLensFlareSceneNode.h"
#include "CMirrorSceneNode.h"
//#include "CWrapperParticleSystemSceneNode.h"
/****h* /Scene
* NAME
*    Scene-Functions
* DESCRIPTION
*   With these functions you can easily load and add scene-Nodes.
*   There are some SceneNodes BuiltIn, like Cube, Sphere, Cylinder.
*   Also you can add a SkyBox or SkyDome, a Terrain , Water and more.
*
*   It is important to undertand, that some Function returns Pointers to
*   Objects (e.g. SceneNodes). You have to check the Return-Values befor you
*   use this Object-Pointers in other functions. the most functions don't
*   check rthe validity of the input-parameters. So mafter Creat a SceneNode,
*   check if the value unequal #Null, to make sure ther is a Object behind
*   that pointer !
*
*   You will find here also Function to access the SceneNode-Tree. You can make
*   look up for SceneNodes by Name or Id.
*
*   More Functions for the Scenenodes are under /nodes.
****
*/

/* ////////////////////////////////////////////////////////////////////////////
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"
{

/* ////////////////////////////////////////////////////////////////////////////
SCENE MESHS
*/

/****f* Scene/IrrGetMesh
* NAME
*    IrrGetMesh - Load a Mesh
* SYNOPSIS
*    *Mesh.l = IrrGetMesh(filename.s)
* FUNCTION
*    Returns pointer to an animateable mesh. Loads the file if not loaded already.
*
* INPUTS
*    filename.s        - name of the Mesh-File
*
* RESULT
*    Pointer to the loaded Mesh if Successfull, otherwise #Null
* EXAMPLE
*   *mesh.l = IrrGetMesh("MyOwnMesh.dmf")
*   If *mesh = #Null
*       ... if Irrlicht could not load the Mesh..
*   EndIf
* NOTES
*   Possible Mesh-Types :
*   3D Studio (.3ds):
*       Loader for 3D-Studio files which lots of 3D packages are able to export.
*       Only static meshes are currently supported by this importer.
*   Bliz Basic B3D (.b3d):
*       Loader for blitz basic files, developed by Mark Sibly, also supports animations.
*   Cartography shop 4 (.csm)
*
*   COLLADA (.dae, .xml)
*
*   Delgine DeleD (.dmf)
*
*   DirectX (.x)
*       Currently, Irrlicht only supports uncompressed .x files.
*
*   Maya (.obj)
*       Most 3D software can create .obj files which contain static geometry without
*       material data. The material files .mtl are also supported. This importer for
*       Irrlicht can load them directly
*
*   Milkshape (.ms3d)
*       .MS3D files contain models and sometimes skeletal animations from the Milkshape
*       3D modeling and animation software. This importer for Irrlicht can display
*       and/or animate these files.
*
*   My3D (.my3d)
*       .my3D is a flexible 3D file format. The My3DTools contains plug-ins to export
*       .my3D files from several 3D packages.
*
*   OCT (.oct)
*       The oct file format contains 3D geometry and lightmaps and can be loaded
*       directly by Irrlicht. OCT files
*
*   OGRE Meshes (.mesh)
*       Ogre .mesh files contain 3D data for the OGRE 3D engine. Irrlicht can read and
*       display them directly with this importer.
*
*   Pulsar LMTools (.lmts)
*       LMTools is a set of tools (Windows & Linux) for creating lightmaps. Irrlicht
*       can directly read
*
*   Quake 3 levels (.bsp)
*       Quake 3 is a popular game by IDSoftware, and .pk3 files contain .bsp files and
*       textures/lightmaps describing huge prelighted levels.
*
*   Quake 2 models (.md2)
*       Quake 2 models are characters with morph target animation. Irrlicht can read,
*       display and animate them directly with this importer.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMesh(filename.p-ascii)
*/

STATIC_EXPORT void * DLL_EXPORT IrrGetMesh( char *cptrFile )
{
	IAnimatedMesh* mesh = smgr->getMesh( cptrFile );
	return (void *)mesh;
}

/****f* Scene/IrrGetStaticFromMesh
* NAME
*    IrrGetStaticFromMesh - Get the Static of a Animated Mesh
* SYNOPSIS
*    *Mesh.l = IrrGetStaticFromMesh(*animatedMesh.l [,frameNumber.l])
* FUNCTION
*   Returns pointer to an static mesh, from e Animated Mesh.
*   It is important, since IrrGetMesh() loads only AnimatedMeshes.
*   But some Functions (like IrrAddWaterScenenNode() ) need a static Mesh.
*   If you load a 'static mesh' with IrrGetMesh(), then it is loaded as a
*   animated Mesh with only one Frame (FrameNumber=0) !
*
* INPUTS
*    *animatedMesh        - pointer to a previously loaded Mesh.
*    frameNumber.l        - (Optional) number of the Frame, if it was a Animated one.
*
* RESULT
*    Pointer to the static Mesh if Successfull, otherwise #Null
* EXAMPLE
*   *mesh.l = IrrGetMesh("MyOwnMesh.dmf")
*   If *mesh <> #Null
*       *staticMesh.l = IrrGetStaticFromMesh(*mesh,0)
*   EndIf
* NOTES
*
* HISTORY
*   Added for Version 1.05 (as i saw the need for the WaterSceneNode) by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetStaticFromMesh(*animatedMesh.l,frameNumber.l=0)
*/

STATIC_EXPORT void * DLL_EXPORT IrrGetStaticFromMesh( IAnimatedMesh* aniMesh, int frameNumber = 0 )
{
	IMesh* mesh = aniMesh->getMesh( frameNumber );
	return (void *)mesh;
}


/* ----------------------------------------------------------------------------
    Experimental Method For Catching Files with PB
*/

/** ***f* Scene/IrrGetMeshFromMemory
* NAME
*    IrrGetMeshFromMemory - Load a Mesh from Memory (Catch !)
* SYNOPSIS
*    *Mesh.l = IrrGetMeshFromMemory(*memoryadress.l, size.l, name.s, deleteMemoryWhenDropped.l )
* FUNCTION
*    Returns pointer to an animateable mesh.
*
* INPUTS
*    *memoryadress.l    - pointer to Memoryadress, where the Mesh is.
*    size.l             - size of the Mesh-File
*    name.s              - an Name to identify the Mesh
*   deleteMemoryWhenDropped - is a Boolean, to free Memory if the Mesh is dropped.
*
* RESULT
*    Pointer to the loaded Mesh if Successfull, otherwise #Null
* EXAMPLE
*   *mesh.l = IrrGetMeshFromMemory(?mymesh,?mymeshens-?mymesh,"MyMesh",#False)
*   If *mesh = #Null
*       ... if Irrlicht could not load the Mesh..
*   EndIf
*   DataSection
*   mymesh: IncludeFile "MyOwnMesh.dmf"
*   mymeshend:
*   EndDatasection
* NOTES
*   Loads all Meshes like IrrGetMesh(). See there for the valid Formats.
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMeshFromMemory(*memoryadress.l, size.l, name.p-ascii, deleteMemoryWhenDropped.l )
*/

STATIC_EXPORT void * DLL_EXPORT IrrGetMeshFromMemory( void* memory, s32 size, const char* cptrFile, bool deleteMemoryWhenDropped )
{
    // load a mesh and add it to the scene

	IAnimatedMesh* mesh = smgr->getMesh( device->getFileSystem()->createMemoryReadFile( memory, size, cptrFile,deleteMemoryWhenDropped ));

	return (void *)mesh;
}


/****f* Scene/IrrCreateMesh
* NAME
*    IrrCreateMesh - Create a own Mesh
* SYNOPSIS
*    *Mesh.l = IrrCreateMesh(name.p-ascii, vertexCount, *vertices.l, indicesCount.l, *indices.l )
* FUNCTION
*   Create a mesh from an array of verticies, an array of incidies to those
*   verticies that connect them to form triangles and finally texture co-ordinates
*   to map the verticies against a texture plane
* INPUTS
*   name.s              - an Name to identify the Mesh
*   vertexCount.l       - number of vertices
*   *vertices.IRR_VERT  - pointer to the Array of vertices
*   indicesCount.l      - number of indices
*   *indices.l          - pointer to the Array of indeces
*
* RESULT
*    Pointer to the loaded Mesh if Successfull, otherwise #Null
* EXAMPLE
*   See example 15_ExampleCreateCustomMesh.pb
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrCreateMesh(name.p-ascii, vertexCount, *vertices.l, indicesCount.l, *indices.l )
*/
STATIC_EXPORT void * DLL_EXPORT IrrCreateMesh(
                                char *cptrMeshName,
                                int iVertexCount,
                                IRR_VERT *vVertices,
                                int iIndicesCount,
                                unsigned short *usIndices )
{
    int iLoop;

    /* get the mesh cache for the scene */
    IMeshCache *mcache = smgr->getMeshCache();

    SMeshBuffer *smeshbuffer = new SMeshBuffer;
    SMesh *smesh = new SMesh;
    SAnimatedMesh * sanimmesh = new SAnimatedMesh;

    // add all of the verts
//    printf( "Adding %d verts\n", iVertexCount );
    smeshbuffer->Vertices.set_used(iVertexCount);
    for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
    {
        smeshbuffer->Vertices[iLoop].Pos.set(
                                            vVertices[iLoop].x,
                                            vVertices[iLoop].y,
                                            vVertices[iLoop].z );
        smeshbuffer->Vertices[iLoop].Normal.set(
                                            vVertices[iLoop].normal_x,
                                            vVertices[iLoop].normal_y,
                                            vVertices[iLoop].normal_z );
        smeshbuffer->Vertices[iLoop].Color.color = vVertices[iLoop].vcolor;
        smeshbuffer->Vertices[iLoop].TCoords.set(
                                            vVertices[iLoop].texture_x,
                                            vVertices[iLoop].texture_y );
    }

    // add all of the indices
//    printf( "Adding %d indicies\n", iIndicesCount );
    smeshbuffer->Indices.set_used(iIndicesCount);
    for ( iLoop = 0; iLoop < iIndicesCount; iLoop++ )
    {
        smeshbuffer->Indices[iLoop] = usIndices[iLoop];
    }

    // assemble the mesh objects
    smesh->addMeshBuffer( smeshbuffer );
    sanimmesh->addMesh( smesh );
    mcache->addMesh( cptrMeshName, sanimmesh );

    // recalculate the bounding box around the object for clipping purposes
    sanimmesh->recalculateBoundingBox();

	return (void *)sanimmesh;
}

/****f* Scene/IrrRemoveMesh
* NAME
*    IrrRemoveMesh - remove a mesh
* SYNOPSIS
*    IrrRemoveMesh(*mesh.l)
* FUNCTION
*   remove a loaded mesh from the scene cache useful if you are dealing with large
*   numbers of meshes that you dont want cached in memory at the same time (for
*   example when swapping between BSP maps for levels)
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrRemoveMesh(*mesh.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrRemoveMesh( IAnimatedMesh* mesh )
{
    /* get the mesh cache for the scene */
    IMeshCache *mcache = smgr->getMeshCache();

    /* remove the selected mesh */
    mcache->removeMesh( mesh );
}


/* ////////////////////////////////////////////////////////////////////////////
SCENE MESH MANIPULATION
*/

/****f* Scene/IrrGetMeshIndexCount
* NAME
*    IrrGetMeshIndexCount - get Mesh-Count
* SYNOPSIS
*    number.l = IrrGetMeshIndexCount(*mesh.l, Frame.l)
* FUNCTION
*   get the number of indicies in the mesh buffer
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - Frame of the Mehs (if animatied)
*
* RESULT
*    number of indices
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMeshIndexCount(*mesh.l, Frame.l)
*/
STATIC_EXPORT int DLL_EXPORT IrrGetMeshIndexCount( IAnimatedMesh* mesh, int iFrame )
{
    return mesh->getMesh(iFrame)->getMeshBuffer(0)->getIndexCount();
}

/****f* Scene/IrrGetMeshIndices
* NAME
*    IrrGetMeshIndices - Get Indices
* SYNOPSIS
*    IrrGetMeshIndices(*mesh.l, Frame.l, *memory.l)
* FUNCTION
*   copy the indicies of a mesh into the supplied buffer, the caller must ensure
*   that the buffer is big enough to store the data
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - number of the Frame (if animated mesh)
*   *memory.l           - pointer to the memory where the indices will be stored
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMeshIndices(*mesh.l, Frame.l, *memory.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrGetMeshIndices( IAnimatedMesh* mesh, int iFrame, unsigned short *indicies )
{
    int iLoop;
    int iIndexCount = mesh->getMesh(iFrame)->getMeshBuffer(0)->getIndexCount();
    unsigned short *us = mesh->getMesh(iFrame)->getMeshBuffer(0)->getIndices();

    for ( iLoop = 0; iLoop < iIndexCount; iLoop++ )
    {
        indicies[iLoop] = us[iLoop];
    }
}

/****f* Scene/IrrSetMeshIndices
* NAME
*    IrrSetMeshIndices - Set Indices
* SYNOPSIS
*    IrrSetMeshIndices(*mesh.l, Frame.l, *memory.l)
* FUNCTION
*   copy the indicies in the supplied buffer into the mesh , the caller must ensure
*   that the buffer is big enough to supply all of the data
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - number of the Frame (if animated mesh)
*   *memory.l           - pointer to the memory where the indices are
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetMeshIndices(*mesh.l, Frame.l, *memory.l)
*/
STATIC_EXPORT void DLL_EXPORT IrrSetMeshIndices( IAnimatedMesh* mesh, int iFrame, unsigned short *indicies )
{
    int iLoop;
    int iIndexCount = mesh->getMesh(iFrame)->getMeshBuffer(0)->getIndexCount();
    unsigned short *us = mesh->getMesh(iFrame)->getMeshBuffer(0)->getIndices();

    for ( iLoop = 0; iLoop < iIndexCount; iLoop++ )
    {
        us[iLoop] = indicies[iLoop];
    }
}

/****f* Scene/IrrGetMeshVertexCount
* NAME
*    IrrGetMeshVertexCount - Get count of Vertices
* SYNOPSIS
*    number.l = IrrGetMeshVertexCount(*mesh.l, Frame.l)
* FUNCTION
*   get the number of vertices in the mesh buffer
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - number of the Frame (if animated mesh)
* RESULT
*    number of vertices
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMeshVertexCount(*mesh.l, Frame.l)
*/
STATIC_EXPORT int DLL_EXPORT IrrGetMeshVertexCount( IAnimatedMesh* mesh, int iFrame )
{
    return mesh->getMesh(iFrame)->getMeshBuffer(0)->getVertexCount();
}

/****f* Scene/IrrGetMeshVertices
* NAME
*    IrrGetMeshVertices - Get Vertices
* SYNOPSIS
*    IrrGetMeshVertices(*mesh.l, Frame.l, *memory.IRR_VERT)
* FUNCTION
*   copy the vertices of a mesh into the supplied buffer, the caller must
*   ensure that the buffer is big enough to store the data
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - number of the Frame (if animated mesh)
*   *memory.IRR_VERT   - pointer to the memory where the vertices shoul stored
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetMeshVertices(*mesh.l, Frame.l, *memory.IRR_VERT)
*/
STATIC_EXPORT void DLL_EXPORT IrrGetMeshVertices( IAnimatedMesh* mesh, int iFrame, IRR_VERT *verts )
{
    int iLoop;
    S3DVertex *s3d_verts;
    S3DVertex2TCoords *texture_verts;
    S3DVertexTangents *tangent_verts;
    IMeshBuffer *mb = mesh->getMesh(iFrame)->getMeshBuffer(0);
    int iVertexCount = mb->getVertexCount();

    switch ( mb->getVertexType())
    {
    case EVT_STANDARD:
        // Standard vertex type used by the Irrlicht engine, video::S3DVertex
        s3d_verts = (S3DVertex *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            verts[iLoop].x = s3d_verts[iLoop].Pos.X;
            verts[iLoop].y = s3d_verts[iLoop].Pos.Y;
            verts[iLoop].z = s3d_verts[iLoop].Pos.Z;

            verts[iLoop].normal_x = s3d_verts[iLoop].Normal.X;
            verts[iLoop].normal_y = s3d_verts[iLoop].Normal.Y;
            verts[iLoop].normal_z = s3d_verts[iLoop].Normal.Z;

            verts[iLoop].vcolor = s3d_verts[iLoop].Color.color;
            verts[iLoop].texture_x = s3d_verts[iLoop].TCoords.X;
            verts[iLoop].texture_y = s3d_verts[iLoop].TCoords.Y;
        }
        break;

    case EVT_2TCOORDS:
        /* Vertex with two texture coordinates, video::S3DVertex2TCoords.
        Usually used for geometry with lightmaps or other special materials. */
        texture_verts = (S3DVertex2TCoords *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            verts[iLoop].x = texture_verts[iLoop].Pos.X;
            verts[iLoop].y = texture_verts[iLoop].Pos.Y;
            verts[iLoop].z = texture_verts[iLoop].Pos.Z;

            verts[iLoop].normal_x = texture_verts[iLoop].Normal.X;
            verts[iLoop].normal_y = texture_verts[iLoop].Normal.Y;
            verts[iLoop].normal_z = texture_verts[iLoop].Normal.Z;

            verts[iLoop].vcolor = texture_verts[iLoop].Color.color;
            verts[iLoop].texture_x = texture_verts[iLoop].TCoords.X;
            verts[iLoop].texture_y = texture_verts[iLoop].TCoords.Y;
        }
        break;

    case EVT_TANGENTS:
        /* Vertex with a tangent and binormal vector, video::S3DVertexTangents.
        Usually used for tangent space normal mapping. */
        tangent_verts = (S3DVertexTangents *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            verts[iLoop].x = tangent_verts[iLoop].Pos.X;
            verts[iLoop].y = tangent_verts[iLoop].Pos.Y;
            verts[iLoop].z = tangent_verts[iLoop].Pos.Z;

            verts[iLoop].normal_x = tangent_verts[iLoop].Normal.X;
            verts[iLoop].normal_y = tangent_verts[iLoop].Normal.Y;
            verts[iLoop].normal_z = tangent_verts[iLoop].Normal.Z;

            verts[iLoop].vcolor = tangent_verts[iLoop].Color.color;
            verts[iLoop].texture_x = tangent_verts[iLoop].TCoords.X;
            verts[iLoop].texture_y = tangent_verts[iLoop].TCoords.Y;
        }
        break;
    }
}

/****f* Scene/IrrSetMeshVertices
* NAME
*    IrrSetMeshVertices - Set Vertices
* SYNOPSIS
*    IrrGetMeshVertices(*mesh.l, Frame.l, *memory.IRR_VERT)
* FUNCTION
*   Copy the vertices from asupplied buffer into a  mesh.
*
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
*   Frame.l             - number of the Frame (if animated mesh)
*   *memory.IRR_VERT   - pointer to the memory where the vertices are
* RESULT
*    nothing
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetMeshVertices(*mesh.l, Frame.l, *memory.IRR_VERT)
*/

STATIC_EXPORT void DLL_EXPORT IrrSetMeshVertices( IAnimatedMesh* mesh, int iFrame, IRR_VERT *verts )
{
    int iLoop;
    S3DVertex *s3d_verts;
    S3DVertex2TCoords *texture_verts;
    S3DVertexTangents *tangent_verts;
    IMeshBuffer *mb = mesh->getMesh(iFrame)->getMeshBuffer(0);
    int iVertexCount = mb->getVertexCount();

    switch ( mb->getVertexType())
    {
    case EVT_STANDARD:
        // Standard vertex type used by the Irrlicht engine, video::S3DVertex
        s3d_verts = (S3DVertex *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            s3d_verts[iLoop].Pos.X = verts[iLoop].x;
            s3d_verts[iLoop].Pos.Y = verts[iLoop].y;
            s3d_verts[iLoop].Pos.Z = verts[iLoop].z;

            s3d_verts[iLoop].Normal.X = verts[iLoop].normal_x;
            s3d_verts[iLoop].Normal.Y = verts[iLoop].normal_y;
            s3d_verts[iLoop].Normal.Z = verts[iLoop].normal_z;

            s3d_verts[iLoop].Color.color = verts[iLoop].vcolor;
            s3d_verts[iLoop].TCoords.X = verts[iLoop].texture_x;
            s3d_verts[iLoop].TCoords.Y = verts[iLoop].texture_y;
        }
        break;

    case EVT_2TCOORDS:
        /* Vertex with two texture coordinates, video::S3DVertex2TCoords.
        Usually used for geometry with lightmaps or other special materials. */
        texture_verts = (S3DVertex2TCoords *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            texture_verts[iLoop].Pos.X = verts[iLoop].x;
            texture_verts[iLoop].Pos.Y = verts[iLoop].y;
            texture_verts[iLoop].Pos.Z = verts[iLoop].z;

            texture_verts[iLoop].Normal.X = verts[iLoop].normal_x;
            texture_verts[iLoop].Normal.Y = verts[iLoop].normal_y;
            texture_verts[iLoop].Normal.Z = verts[iLoop].normal_z;

            texture_verts[iLoop].Color.color = verts[iLoop].vcolor;
            texture_verts[iLoop].TCoords.X = verts[iLoop].texture_x;
            texture_verts[iLoop].TCoords.Y = verts[iLoop].texture_y;
        }
        break;

    case EVT_TANGENTS:
        /* Vertex with a tangent and binormal vector, video::S3DVertexTangents.
        Usually used for tangent space normal mapping. */
        tangent_verts = (S3DVertexTangents *)mb->getVertices();
        for ( iLoop = 0; iLoop < iVertexCount; iLoop++ )
        {
            tangent_verts[iLoop].Pos.X = verts[iLoop].x;
            tangent_verts[iLoop].Pos.Y = verts[iLoop].y;
            tangent_verts[iLoop].Pos.Z = verts[iLoop].z;

            tangent_verts[iLoop].Normal.X = verts[iLoop].normal_x;
            tangent_verts[iLoop].Normal.Y = verts[iLoop].normal_y;
            tangent_verts[iLoop].Normal.Z = verts[iLoop].normal_z;

            tangent_verts[iLoop].Color.color = verts[iLoop].vcolor;
            tangent_verts[iLoop].TCoords.X = verts[iLoop].texture_x;
            tangent_verts[iLoop].TCoords.Y = verts[iLoop].texture_y;
        }
        break;
    }
    // now that the geometry has been altered recalculate the bounding box
    //Disable for Irrlicht 1.4
//    smgr->getMeshManipulator()->recalculateBoundingBox(
//            mesh->getMesh(iFrame)->getMeshBuffer(0));
}


/* ////////////////////////////////////////////////////////////////////////////
SCENE NODE CREATION
*/


/****f* Scene/IrrAddMeshToScene
* NAME
*    IrrAddMeshToScene - Add a loaded Mesh to the Irrlicht SceneManager
* SYNOPSIS
*    *SceneNode.l = IrrAddMeshToScene(*mesh.l)
* FUNCTION
*   Wifth this function you can add a previoulsy loaded Mesh (see  IrrGetMesh() )
*   into the Irrlicht-Scene. You can then Use the Node-Functions to set Position,
*   rotation and Scale.*
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*   *mesh.l = IrrGetMesh("MyOwnMesh.dmf")
*   If *mesh = #Null
*       *node.l = IrrAddMeshToScene(*mesh.l)
*   EndIf
* TODO
*   We should offer a more 'open' Version, (oneshot), with Parent, Scale ect.
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddMeshToScene(*mesh.l)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddMeshToScene ( IAnimatedMesh* mesh )
{
	IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
	return (void *)node;
}

/****f* Scene/IrrAddMeshToSceneAsOcttree
* NAME
*    IrrAddMeshToSceneAsOcttree - Adds a Mesh as Octtree
* SYNOPSIS
*    *SceneNode.l = IrrAddMeshToSceneAsOcttree(*mesh.l)
* FUNCTION
*   Adds a scene node for rendering using a octtree to the scene graph.
*   This a good method for rendering scenes with lots of geometry. The
*   Octree is built on the fly from the mesh.
*
* INPUTS
*   *mesh.l             - pointer to a loaded/catched or created Mesh.
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*   *mesh.l = IrrGetMesh("MyOwnMesh.dmf")
*   If *mesh = #Null
*       *node.l = IrrAddMeshToSceneAsOcttree(*mesh.l)
*   EndIf
* TODO
*   We should offer a more 'open' Version, (oneshot), with Parent and minimalPolysPerNode
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddMeshToSceneAsOcttree(*mesh.l)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddMeshToSceneAsOcttree( void *vptrMesh )
{
    // add the mesh to the scene as an octtree
    return (void *)smgr->addOctTreeSceneNode((IAnimatedMesh*)vptrMesh);
}


/****f* Scene/IrrAddBillBoardToScene
* NAME
*    IrrAddBillBoardToScene - Adds a Billboard
* SYNOPSIS
*    *SceneNode.l = IrrAddBillBoardToScene(sizex.f, sizey.f,  x.f, y.f, z.f)
* FUNCTION
*   Adds a billboard scene node to the scene graph.
*
*   A Billboard is like a 3d sprite: A 2d element, which always looks to the camera.
*   It is usually used for things like explosions, fire, lensflares and things like that.
*
* INPUTS
*   sizex.f             - x-dimension of the Biillboard
*   sizey.f             - y-dimension of the Biillboard
*   x.f,y.f.z.f         - Position in the 3D-Space of the Biillboard
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *node.l = IrrAddBillBoardToScene(10.0, 10.0 0.0,0.0,-20.0)
* TODO
*   Maybe we could also attach a Texture in one step......
*
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddBillBoardToScene(sizex.f, sizey.f,  x.f, y.f, z.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddBillBoardToScene( float sizex, float sizey, float x, float y, float z )
{
    return (void *)smgr->addBillboardSceneNode(
            NULL,
            dimension2d<f32>( sizex, sizey ),
            vector3df(x, y, z )
    );
}

/****f* Scene/IrrAddParticleSystemToScene
* NAME
*    IrrAddParticleSystemToScene - Adds a Particle-System to the SceneManager
* SYNOPSIS
*    *ParticleSystemSceneNode.l = IrrAddParticleSystemToScene(bDefaultemitter.l)
* FUNCTION
*   Creates a default working point emitter which emitts some particles. Set this
*   to #True to see a particle system in action. If set to #False, you'll have to
*   set the emitter you want
*
* INPUTS
*   bDefaultemitter.l   - Use DefaultEmitter (#True or #False)
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *ps_node.l = IrrAddParticleSystemToScene(#True)
* TODO
*   Maybe we have to support size, pos and rotation, and also the Parent....
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleSystemToScene(bDefaultemitter.l)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddParticleSystemToScene ( bool defaultemitter )
{
/*
    IParticleSystemSceneNode* ps = new CWrapperParticleSystemSceneNode(defaultemitter, 0, smgr, -1,
                                    vector3df(0,0,0),
                                    vector3df(0,0,0),
                                    vector3df(1,1,1) );
*/
	return (void *) smgr->addParticleSystemSceneNode(defaultemitter);
}


/****f* Scene/IrrAddParticleSystemExtToScene
* NAME
*    IrrAddParticleSystemExtToScene - Adds a Extended Particle-System to the SceneManager
* SYNOPSIS
*    *ParticleSystemSceneNode.l = IrrAddParticleSystemExtToScene(bDefaultemitter.l)
* FUNCTION
*   Creates a default working point emitter which emitts some particles. Set this
*   to #True to see a particle system in action. If set to #False, you'll have to
*   set the emitter you want
*   In difference to the IrrAddParticleSystemToScene(), the Extended Particle-System
*   offers much more possibilities to control and manipulate the Particles.
*   there are now things like rotation, scaling, aligning possible.
*
*   Ther are also some special functions rely to the extended ParticleSystem
*
* INPUTS
*   bDefaultemitter.l   - Use DefaultEmitter (#True or #False)
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *ps_node.l = IrrAddParticleSystemToScene(#True)
* TODO
*   Maybe we have to support size, pos and rotation, and also the Parent....
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddParticleSystemExtToScene(bDefaultemitter.l)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddParticleSystemExtToScene ( bool defaultemitter )
{
	return (void *) smgr->addParticleSystemExtSceneNode(defaultemitter);
}


/****f* Scene/IrrAddSkyBoxToScene
* NAME
*    IrrAddSkyBoxToScene - Add a skybox to the irrlicht based on six pictures
* SYNOPSIS
*    *SkyBoxSceneNode.l = IrrAddSkyBoxToScene(*texture_up.l, *texture_down.l, *texture_left.l, *texture_right.l, * texture_front.l, *texture_back.l)
* FUNCTION
*   Adds a skybox scene node to the scene graph.
*   A skybox is a big cube with 6 textures on it and is drawn around the camera position
*
* INPUTS
*   *texture_up.l       - a pointer to loaded Texture ( IrrGetTexture() )
*   *texture_down.l     - a pointer to loaded Texture ( IrrGetTexture() )
*   *texture_left.l     - a pointer to loaded Texture ( IrrGetTexture() )
*   *texture_right.l    - a pointer to loaded Texture ( IrrGetTexture() )
*   *texture_front.l    - a pointer to loaded Texture ( IrrGetTexture() )
*   *texture_back.l     - a pointer to loaded Texture ( IrrGetTexture() )
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *sb_node.l = IrrAddSkyBoxToScene(*t1,*t2,*t3,*t4,*t5,*t6)
* TODO
*   Maybe we have to support size, pos and rotation, and also the Parent....
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddSkyBoxToScene(*texture_up.l, *texture_down.l, *texture_left.l, *texture_right.l, * texture_front.l, *texture_back.l)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddSkyBoxToScene (
                                       ITexture *texture_up,
                                       ITexture *texture_down,
                                       ITexture *texture_left,
                                       ITexture *texture_right,
                                       ITexture *texture_front,
                                       ITexture *texture_back )
{

    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
	return (void *)smgr->addSkyBoxSceneNode(
            texture_up,
            texture_down,
            texture_left,
            texture_right,
            texture_front,
            texture_back
    );
    driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
}


/****f* Scene/IrrAddCubeSceneNode
* NAME
*    IrrAddCubeSceneNode - Add a Cube
* SYNOPSIS
*    *SkyBoxSceneNode.l = IrrAddCubeSceneNode(size.f)
* FUNCTION
*   Adds a test scene node for test purposes to the scene.
*   It is a simple cube of (1,1,1) size.
* INPUTS
*   size.f      - size of the cube
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *cube_node.l = IrrAddCubeSceneNode(10.0)
* TODO
*   Maybe we have to support size, pos and rotation, and also the Parent....
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddCubeSceneNode(size.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddCubeSceneNode( float size )
{
    return (void *)smgr->addCubeSceneNode(size);
}

/****f* Scene/IrrAddPlaneSceneNode
* NAME
*    IrrAddPlaneSceneNode - Add a Plane
* SYNOPSIS
*    *PlaneSceneNode.l = IrrAddPlaneSceneNode(name.s, sizeX.f, sizeY.f, tilesX.l, tilesY.l, texRepeatX.f, texRepeatY.f)
* FUNCTION
*   Adds a Plane to the scene.
*   In fact it is a HillPlane, - but without hills....
*
* INPUTS
*   name.s                      - A Name for the Mesh
*   sizeX.f,sizeY.f             - Size of a tile of the mesh. (10.0f, 10.0f) would be a good value to start, for example.
*   tilesX.l, tilesY.l          - Specifies how much tiles there will be. If you specifiy for
*                                 example that a tile has the size (10.0f, 10.0f) and the tileCount is (10,10),
*                                 than you get a field of 100 tiles wich has the dimension 100.0fx100.0f.
*   texRepeatX.f,texRepeatY.f   - Defines how often the texture will be repeated in x and y direction.
*
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *plane_node.l = IrrAddPlaneSceneNode("MyPlane",10.0,10.0, 10.0,10.0,1.0,1.0)
* TODO
*   If possible, we should offer a 'easier version' of that. So only a sibple dimension.....
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddPlaneSceneNode(name.p-ascii, sizeX.f, sizeY.f, tilesX.l, tilesY.l, texRepeatX.f, texRepeatY.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddPlaneSceneNode( const char* name, float sizeX, float sizeY, int tilesX, int tilesY, float texRepeatX, float texRepeatY )
{
//    const dimension2d<s32>& tiles =
    IAnimatedMesh* animesh = smgr->addHillPlaneMesh(name, dimension2d<f32>(sizeX,sizeY),  dimension2d<u32>(tilesX,tilesY),0,0,dimension2d<f32>(00,00),dimension2d<f32>(texRepeatX,texRepeatY));
    if (animesh) {
        return (void *)smgr->addAnimatedMeshSceneNode( animesh );
    }else{
        return NULL;
    }
/*
			const core::dimension2d<f32>& tileSize, const core::dimension2d<u32>& tileCount,
			video::SMaterial* material = 0,	f32 hillHeight = 0.0f,
			const core::dimension2d<f32>& countHills = core::dimension2d<f32>(1.0f, 1.0f),
			const core::dimension2d<f32>& textureRepeatCount = core::dimension2d<f32>(1.0f, 1.0f));
    */
}

/****f* Scene/IrrAddHillPlaneSceneNode
* NAME
*    IrrAddHillPlaneSceneNode - Add a Plane with Hills...
* SYNOPSIS
*    *HillPlaneSceneNode.l = IrrAddHillPlaneSceneNode(name.s, sizeX.f, sizeY.f, tilesX.f, tilesY.f, texRepeatX.f, texRepeatY.f, hillsHeight.f, hillsCount.f)
* FUNCTION
*   Adds a HillPlane to the scene.
*
* INPUTS
*   name.s                      - A Name for the Mesh
*   sizeX.f,sizeY.f             - Size of a tile of the mesh. (10.0f, 10.0f) would be a good value to start, for example.
*   tilesX.f, tilesY.f          - Specifies how much tiles there will be. If you specifiy for
*                                 example that a tile has the size (10.0f, 10.0f) and the tileCount is (10,10),
*                                 than you get a field of 100 tiles wich has the dimension 100.0fx100.0f.
*   texRepeatX.f,texRepeatY.f   - Defines how often the texture will be repeated in x and y direction.
*   hillsHeight.f               - Height of the hills. If you specify a negative value you will get holes
*                                 instead of hills. If the height is 0, no hills will be created.
*   hillscCount.f               - Amount of hills on the plane. There will be countHills.X hills along the X axis
*                                 and countHills.Y along the Y axis. So in total there will be countHills.X * countHills.Y hills.
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *hillplane_node.l = IrrAddHillPlaneSceneNode("MyPlane",10.0,10.0, 10.0,10.0,1.0,1.0,30.0,200.0)
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddHillPlaneSceneNode(name.p-ascii, sizeX.f, sizeY.f, tilesX.f, tilesY.f, texRepeatX.f, texRepeatY.f, hillsHeight.f, hillsCount.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddHillPlaneSceneNode( const char* name, float sizeX, float sizeY, int tilesX, int tilesY, float texRepeatX, float texRepeatY, float hillsHeight, float hillsCount )
{
    IAnimatedMesh* animesh = smgr->addHillPlaneMesh(name, dimension2d<f32>(sizeX,sizeY),
    dimension2d<u32>(tilesX,tilesY),0,hillsHeight,dimension2d<f32>(hillsCount,hillsCount),
    dimension2d<f32>(texRepeatX,texRepeatY));
    if (animesh)
        return (void *)smgr->addAnimatedMeshSceneNode( animesh );
    else
        return NULL;
}


/****f* Scene/IrrAddHillPlaneMesh
* NAME
*    IrrAddHillPlaneMesh - Add a HillPlane-Mesh.
* SYNOPSIS
*    *HillPlaneMesh.l = IrrAddHillPlaneMesh(name.s, sizeX.f, sizeY.f, tilesX.l, tilesY.l, texRepeatX.f, texRepeatY.f, hillsHeight.f, hillsCount.f)
* FUNCTION
*   Adds a Mesh
*
* INPUTS
*   name.s                      - A Name for the Mesh
*   sizeX.f,sizeY.f             - Size of a tile of the mesh. (10.0f, 10.0f) would be a good value to start, for example.
*   tilesX.l, tilesY.l          - Specifies how much tiles there will be. If you specifiy for
*                                 example that a tile has the size (10.0f, 10.0f) and the tileCount is (10,10),
*                                 than you get a field of 100 tiles wich has the dimension 100.0fx100.0f.
*   texRepeatX.f,texRepeatY.f   - Defines how often the texture will be repeated in x and y direction.
*   hillsHeight.f               - Height of the hills. If you specify a negative value you will get holes
*                                 instead of hills. If the height is 0, no hills will be created.
*   hillscCount.f               - Amount of hills on the plane. There will be countHills.X hills along the X axis
*                                 and countHills.Y along the Y axis. So in total there will be countHills.X * countHills.Y hills.
* RESULT
*    Pointer to a Mesh (Animated-Mesh !!)
* EXAMPLE
*    *hillplane_mesh.l = IrrAddHillPlaneMesh("MyPlane",10.0,10.0, 10.0,10.0,1.0,1.0,30.0,200.0)
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddHillPlaneMesh(name.p-ascii, sizeX.f, sizeY.f, tilesX.l, tilesY.l, texRepeatX.f, texRepeatY.f, hillsHeight.f, hillsCount.f)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddHillPlaneMesh( const char* name, float sizeX, float sizeY, int tilesX, int tilesY, float texRepeatX, float texRepeatY, float hillsHeight, float hillsCount )
{
    return (void *) smgr->addHillPlaneMesh(name, dimension2d<f32>(sizeX,sizeY),
    dimension2d<u32>(tilesX,tilesY),0,hillsHeight,dimension2d<f32>(hillsCount,hillsCount),
    dimension2d<f32>(texRepeatX,texRepeatY));
}

/*
			const core::dimension2d<f32>& tileSize, const core::dimension2d<u32>& tileCount,
			video::SMaterial* material = 0,	f32 hillHeight = 0.0f,
			const core::dimension2d<f32>& countHills = core::dimension2d<f32>(1.0f, 1.0f),
			const core::dimension2d<f32>& textureRepeatCount = core::dimension2d<f32>(1.0f, 1.0f));
*/

/****f* Scene/IrrAddWaterSceneNode
* NAME
*    IrrAddWaterSceneNode - Add a WaterSceneNode
* SYNOPSIS
*    *WaterSceneNode.l = IrrAddWaterSceneNode(*mesh.l, [waveHeight.f, waveSpeed.f, waveLength.f])
* FUNCTION
*   Adds a scene node for rendering a animated water surface mesh.
*   Looks really good when the Material type #IRR_EMT_TRANSPARENT_REFLECTION is used
*
* INPUTS
*   *mesh.l                     - Pointer to the loaded static mesh to be displayed with water waves on it.
*   waveHeight.f                - Height of the water waves
*   waveSpeed.f                 - Speed of the water waves
*   waveLength.f                - Lemgth of the water waves
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *water_node.l = IrrAddWaterSceneNode(*mesh.l)
* HISTORY
*   Added for Version 1.05 of the IrrlichtWrapper by M.Taupitz
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddWaterSceneNode(*mesh.l, waveHeight.f=2.0, waveSpeed.f=100.0, waveLength.f=30.0)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddWaterSceneNode( IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength )
{
    return (void *)smgr->addWaterSurfaceSceneNode(mesh,waveHeight, waveSpeed, waveLength);
}


/****f* Scene/IrrAddSphereSceneNode
* NAME
*    IrrAddSphereSceneNode - Add a Sphere
* SYNOPSIS
*    *SphereSceneNode.l = IrrAddSphereSceneNode(radius.f, polyCount.l)
* INPUTS
*   radius.f    - radius of the Sphere
*   polyCount.l - Polycount of the sphere.
* FUNCTION
*   Create a Sphere-Scene-Node with Raduis and Polycount.
*   You have to change Color and Position and Parent with the other Commands.
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *sphere_node.l = IrrAddSphereSceneNode(10,10)
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddSphereSceneNode(radius.f, polyCount.l)
*/
STATIC_EXPORT void DLL_EXPORT* IrrAddSphereSceneNode(float radius, int polycount)
{
    return (void *) smgr->addSphereSceneNode(radius,polycount);
}

/****f* Scene/IrrAddCylinderSceneNode
* NAME
*    IrrAddCylinderSceneNode - Add a Cylinder
* SYNOPSIS
*    *CylinderSceneNode.l = IrrAddCylinderSceneNode(gridX.l, gridY.l, radius.f)
* FUNCTION
*   Adds a Cylinder to the scene.
*
* INPUTS
*   gridX.l     - Vertices in X-Direction
*   gridY.l     - Vertices in Y-Direction
*   radius.f    - radius of the Cylinder
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *cylinder_node.l = IrrAddCylinderSceneNode(10,10,4.0)
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddCylinderSceneNode(gridX.l=25, gridY.l=25, radius.f=1.0)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddCylinderSceneNode(int gridX, int gridY,f32 radius )
{
    ISceneNode* nodeCyl = smgr->addMeshSceneNode(CPrimitives::CreateCylinder(gridX,gridY,radius),0);
    nodeCyl->setMaterialFlag(EMF_BACK_FACE_CULLING, false);
    return (void *)nodeCyl;
}

/****f* Scene/IrrAddConeSceneNode
* NAME
*    IrrAddConeSceneNode - Add a Cone
* SYNOPSIS
*    *ConeSceneNode.l = IrrAddConeSceneNode([gridX.l, gridY.l, radius.f])
* FUNCTION
*   Adds a Cone to the scene.
*
* INPUTS
*   gridX.l     - Vertices in X-Direction
*   gridY.l     - Vertices in Y-Direction
*   radius.f    - radius of the Cone
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *cone_node.l = IrrAddConeSceneNode(10,10,4.0)
* TODO
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddConeSceneNode(gridX.l=25, gridY.l=25, radius.f=1.0)
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddConeSceneNode(int gridX, int gridY,f32 radius )
{
    return (void *) smgr->addMeshSceneNode(CPrimitives::CreateCone(gridX,gridY,radius),0);
}


/****f* Scene/IrrAddDiamondSceneNode
* NAME
*    IrrAddDiamondSceneNode - Add a Diamant
* SYNOPSIS
*    *DiaSceneNode.l = IrrAddDiamondSceneNode()
* FUNCTION
*   Adds a Diamant to the scene.
*
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*    *dia_node.l = IrrAddDiamondSceneNode()
* TODO
*
* NOTES
*   This Diamant-ScenenNode is based on the SceneNode from
*   - Panther in Irrlicht-Forum.
+   - Link : http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=15106&start=0&postdays=0&postorder=asc&highlight=
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddDiamondSceneNode()
*/
STATIC_EXPORT void * DLL_EXPORT IrrAddDiamondSceneNode()
{
    return (void *) smgr->addMeshSceneNode(CPrimitives::CreateDiamond(),0);
}


/****f* Scene/IrrAddTextSceneNode
* NAME
*    IrrAddTextSceneNode - Add a TextSceneNode
* SYNOPSIS
*    *TextSceneNode.l = IrrAddTextSceneNode(*font.l, text.s)
* INPUTS
*   *font.l     - Pointer to a Irrlicht-Font. Loaded with IrrGetFont() or use
*                 the BuiltIn Font with IrrGetBuitInFont().
*   text.s      - Text to Display.
* FUNCTION
*   Create a Text-Scene-Node with the given Font.
*   You have to change Color and Position and Parent with the other Commands.
*
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*   ;Get the BuiltIn-Font
*   *font.l = IrrGetBuitInFont()
*   ;Add the TextSceneNode
*   *text_node.l = IrrAddTextSceneNode(*font, "TestText")
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddTextSceneNode(*font.l, text.p-unicode)
*/

STATIC_EXPORT void DLL_EXPORT* IrrAddTextSceneNode(gui::IGUIFont * font, const wchar_t* text)
{
    return (void *) smgr->addTextSceneNode(font, text);
}


/****f* Scene/IrrAddEmptySceneNode
* NAME
*    IrrAddEmptySceneNode - Add a TextSceneNode
* SYNOPSIS
*    *TextSceneNode.l = IrrAddEmptySceneNode()
* FUNCTION
*   Adds an empty scene node to the scene graph.
*   Can be used for doing advanced transformations or structuring the scene graph.
*
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*   *empty_node.l = IrrAddEmptySceneNode()
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddEmptySceneNode()
*/
STATIC_EXPORT void DLL_EXPORT* IrrAddEmptySceneNode()
{
    return (void *) smgr->addEmptySceneNode();
}

/****f* Scene/IrrAddSkyDomeToScene
* NAME
*    IrrAddSkyDomeToScene - Add a SkyDome-SceneNode
* SYNOPSIS
*    *SkyDomeSceneNode.l = IrrAddSkyDomeToScene(*texture.l, horiRes.l, vertRes.l, texturePercentage.d, spherePercentage.d )
* INPUTS
*   *texture.l          - Texture for the dome.
*   horiRes.l           - Number of vertices of a horizontal layer of the sphere.
*   vertRes.l           - Number of vertices of a vertical layer of the sphere.
*   texturePercentage.d - How much of the height of the texture is used. Should be between 0 and 1.
*   spherePercentage.d  - How much of the sphere is drawn. Value should be between 0 and 2, where 1
*                         is an exact half-sphere and 2 is a full sphere.
* FUNCTION
*   Adds a skydome scene node to the scene graph.
*   A skydome is a large (half-) sphere with a panoramic texture on the inside
*   and is drawn around the camera position.
*
* RESULT
*    Pointer to a SceneNode
* EXAMPLE
*   *sd_node.l = IrrAddSkyDomeToScene(*skyTexture,128,64, 1, 1 )
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddSkyDomeToScene(*texture.l, horiRes.l, vertRes.l, texturePercentage.d, spherePercentage.d )
*/

STATIC_EXPORT void DLL_EXPORT* IrrAddSkyDomeToScene( ITexture* pTexture, int horiRes, int vertRes, double texturePercentage, double spherePercentage  )
{
    return (void *) smgr->addSkyDomeSceneNode(pTexture,horiRes,vertRes,texturePercentage,spherePercentage, 0);
}


/* ////////////////////////////////////////////////////////////////////////////
SCENE EFFECTS
*/


/****f* Scene/IrrSetShadowColor
* NAME
*    IrrSetShadowColor - Sets the color of stencil buffers shadows
* SYNOPSIS
*    IrrSetShadowColor(alpha.l, red.l, green.l, blue.l )
* INPUTS
*   alpha.l     - Alpha-Value of the Color (0 .. 255)
*   red.l       - Red-Value of the Color (0 .. 255)
*   green.l     - Green-Value of the Color (0 .. 255)
*   blue.l      - Blue-Value of the Color (0 .. 255)
* FUNCTION
*   Sets the color of stencil buffers shadows drawn by the scene manager.
*
* RESULT
*    Nothing
* EXAMPLE
*   ;White Shadows ;-)
*   IrrSetShadowColor(255,255,255,255 )
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetShadowColor(alpha.l, red.l, green.l, blue.l )
*/
STATIC_EXPORT void DLL_EXPORT IrrSetShadowColor( int alpha, int R, int G, int B )
{
	smgr->setShadowColor(video::SColor(alpha,R,G,B));
}


/****f* Scene/IrrSetFog
* NAME
*    IrrSetFog - Sets the fog mode.
* SYNOPSIS
*    IrrSetFog(alpha.l, red.l, green.l, blue.l , fogType.l, fogStart.f, fogEnd.f, fogDensity.f,  [pixelFog.l,[rangeFog.l ]])
* INPUTS
*   alpha.l     - Alpha-Value of the Fog-Color (0 .. 255)
*   red.l       - Red-Value of the Fog-Color (0 .. 255)
*   green.l     - Green-Value of the Fog-Color (0 .. 255)
*   blue.l      - Blue-Value of the Fog-Color (0 .. 255)
*   fogType.l   - Set this to #True for linear fog, otherwise exponential fog is applied
*   fogStart.f  - Only used in linear fog mode (linearFog=true). Specifies where fog starts.
*   fogEnd.f    - Only used in linear fog mode (linearFog=true). Specifies where fog ends.
*   fogDensity.f- Only used in expotential fog mode (linearFog=false). Must be a value between 0 and 1.
*   pixelFog.l  - Set this to #False for vertex fog, and #True if you want pixel fog.
*   rangeFog.l  - Set this to #True to enable range-based vertex fog. The distance from the viewer is used to
*                 compute the fog, not the z coordinate. This is better, but slower. This is only available
*                 with D3D and vertex fog.
* FUNCTION
*   Sets the fog mode.
*   These are global values attached to each 3d object rendered, which has the fog flag enabled in its material.
*
* RESULT
*    Nothing
* EXAMPLE
*   IrrSetFog(255,255,255,255,100,500,0.5 )
* TODO
+
* HISTORY
*   Changed for Version 1.05 to enable also Alpha-Value of the Color and optional pixelFog and
*   rangeFog.
*   M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSetFog(alpha.l, red.l, green.l, blue.l , fogType.l, fogStart.f, fogEnd.f, fogDensity.f, pixelFog.l = #False,rangeFog.l=#False)
*/

STATIC_EXPORT void DLL_EXPORT IrrSetFog( int Alpha, int R, int G, int B, bool fogtype, float start, float end, float density, bool pixelFog, bool rangeFog )
{
    driver->setFog( SColor(Alpha, R, G, B), fogtype, start, end, density, pixelFog, rangeFog );
}

/****f* Scene/IrrGetSceneNodeFromName
* NAME
*    IrrGetSceneNodeFromName - Returns the ScenenNode for this Name
* SYNOPSIS
*    *node.l = IrrGetSceneNodeFromName(nodeName.s)
* INPUTS
*   nodeName.s  - Name of the Node to find.
* FUNCTION
*   Returns the ScenenNode for this Name
* RESULT
*    Pointer to a SceneNode if Success, otherwise #Null
* EXAMPLE
*   *mioNoda.l = IrrGetSceneNodeFromName("MyNode")
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetSceneNodeFromName(nodeName.p-ascii)
*/
STATIC_EXPORT void DLL_EXPORT* IrrGetSceneNodeFromName(const char* name)
{
    return (void *) smgr->getSceneNodeFromName(name);
}

/****f* Scene/IrrGetSceneNodeFromId
* NAME
*    IrrGetSceneNodeFromId - Returns the ScenenNode for this ID
* SYNOPSIS
*    *node.l = IrrGetSceneNodeFromId(nodeId.l)
* INPUTS
*   nodeId.l  - Id of the Node to find.
* FUNCTION
*   Returns the ScenenNode for this Id
* RESULT
*    Pointer to a SceneNode if Success, otherwise #Null
* EXAMPLE
*   *mioNoda.l = IrrGetSceneNodeFromId(77)
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetSceneNodeFromId(nodeId.l)
*/
STATIC_EXPORT void DLL_EXPORT* IrrGetSceneNodeFromId(int id)
{
    return (void *) smgr->getSceneNodeFromId(id);
}

/****f* Scene/IrrGetRootSceneNode
* NAME
*    IrrGetRootSceneNode - Returns the Root-SceneNode
* SYNOPSIS
*    *node.l = IrrGetSceneNodeFromId(nodeId.l)
* FUNCTION
*   Returns the Root-SceneNode
* RESULT
*    Pointer to a SceneNode if Success, otherwise #Null
* EXAMPLE
*   *rootNode.l = IrrGetRootSceneNode()
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrGetRootSceneNode()
*/
STATIC_EXPORT void * DLL_EXPORT IrrGetRootSceneNode()
{
    return (void *) smgr->getRootSceneNode ();
}


/****f* Scene/IrrLoadScene
* NAME
*    IrrLoadScene - Loads a scene.
* SYNOPSIS
*    *node.l = IrrLoadScene(sceneFile.s)
* FUNCTION
*   Loads a scene. Note that the current scene is not cleared before.
*   The scene is usually load from an .irr file, an xml based format. .irr files can
*   Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org)
*   or saved directly by the engine using IrrSaveScene().
* RESULT
*    #True if successfull
* EXAMPLE
*   If IrrLoadScene("./media/myScene.irr")
*       ...
*   EndIf
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrLoadScene(sceneFile.p-ascii)
*/
STATIC_EXPORT int DLL_EXPORT IrrLoadScene(const char* filename)
{
    return  smgr->loadScene(filename);
}

/****f* Scene/IrrSaveScene
* NAME
*    IrrSaveScene - Saves the current scene into a file.
* SYNOPSIS
*    *node.l = IrrSaveScene(sceneFile.s)
* FUNCTION
*   Saves the current scene into a file.
*
*   Scene nodes with the option isDebugObject set to true are not being saved.
*   The scene is usually written to an .irr file, an xml based format. .irr files
*   can Be edited with the Irrlicht Engine Editor, irrEdit (http://irredit.irrlicht3d.org).
*   To load .irr files again, see IrrLoadScene().
* RESULT
*    #True if successfull
* EXAMPLE
*   If IrrSaveScene("./media/myScene.irr")
*       ...
*   EndIf
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrSaveScene(sceneFile.p-ascii)
*/
STATIC_EXPORT int DLL_EXPORT IrrSaveScene(const char* filename)
{
    return  smgr->saveScene(filename);
}


/****f* Scene/IrrClearScene
* NAME
*    IrrClearScene - Clears the Scene
* SYNOPSIS
*   IrrClearScene()
* FUNCTION
*   Clears the whole Scene
* RESULT
*    #True if successfull
* TODO
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrClearScene()
*/
STATIC_EXPORT void DLL_EXPORT IrrClearScene(const char* filename)
{
    smgr->clear();
}








/****f* Mesh/IrrMakePlanarTextureMapping
* NAME
*    IrrMakePlanarTextureMapping - Creates a planar texture mapping on the mesh.
* SYNOPSIS
*    IrrMakePlanarTextureMapping(*mesh.l, resolution.f)
* FUNCTION
*   Creates a planar texture mapping on the mesh.
* INPUTS
*   *mesh.l             - pointer to a !! static mesh !!
*   resolution.f        - resolution of the planar mapping. This is the value specifying which is
*                         the relation between world space and texture coordinate space.
* RESULT
*    nothing
* HISTORY
*   Added in Version 1.05 by M.Taupitz
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrMakePlanarTextureMapping(*mesh.l, resolution.f = 0.001)
*/
STATIC_EXPORT void DLL_EXPORT IrrMakePlanarTextureMapping(IMesh* mesh,f32 resolution = 0.001f)
{
    smgr->getMeshManipulator()->makePlanarTextureMapping(mesh,resolution);
}


/****f* Scene/IrrAddLensFlareSceneNode
* NAME
*    IrrAddLensFlareSceneNode - Add a Lensflare
* SYNOPSIS
*    *LensFlareSceneNode.l = IrrAddLensFlareSceneNode()
* FUNCTION
*   Creates a Lensflare. It needs as input a Image that contaions
*   the 5 flares (in the example it has 5 flares in size of 128x128).
*   This Flare-Images has to be in a Row (for the example the image is 640x128).
*
*   This LensFlare-SceneNode is from Acki' Extensions.
*
*   ILensFlareSceneNode -  by A. Buschhüter (Acki)
*   A_Buschhueter@gmx.de
*   http://abusoft.g0dsoft.com
*
* RESULT
*   Pointer to a SceneNode
* EXAMPLE
* TODO
* HISTORY
*   Added for Version 1.05 by M.Taupitz
+
****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrAddLensFlareSceneNode(*texture)
*/

STATIC_EXPORT void * DLL_EXPORT IrrAddLensFlareSceneNode()
{
    ILensFlareSceneNode* node = new CLensFlareSceneNode(NULL, smgr, -1, vector3df(0,0,0));
    printf("ILensFlareSceneNode=%h\n",node);
//    node->setMaterial(texture);
//    node->drop();
    return (void *)node;
}

/*
char  shader_hlsl[] = {"llll"
"llll"
"ll"};
*/

/****
* This is for creating the PB-Importfile, and avoiding to make everything manual
#PBIMPORT:IrrWriteMesh(filename.p-ascii, *mesh, type.l)
*/

STATIC_EXPORT bool  DLL_EXPORT IrrWriteMesh(c8* filename, IMesh* mesh, EMESH_WRITER_TYPE type)
{
    bool  retVal = false;
    IMeshWriter * mw = smgr->createMeshWriter (type);
    if (mw)
    {
        IWriteFile* wf = device->getFileSystem()->createAndWriteFile(filename,false);
        if (wf)
        {
            retVal = mw->writeMesh(wf, mesh);
        }
    }
    return retVal;
}


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