// ----------------------------------------------------------------------------
// Blitz-Irrlicht 1.8.3 Wrapper by Ed Musolino 2015
// Based off of Frank Dodd's Irrlicht 1.7 Freebasic Wrapper (2006-2010)
// ----------------------------------------------------------------------------

//  This software is provided 'as-is', without any express Or implied
//  warranty.  In no event will the authors be held liable For any damages
//  arising from the use of this software.

//  Permission is granted To anyone To use this software For any purpose,
//  including commercial applications, And To alter it And redistribute it
//  freely, subject To the following restrictions:

//  1. The Origin of this software must Not be misrepresented; you must not
//     claim that you wrote the original software. If you use this software
//     in a product, an acknowledgement in the product documentation would be
//     appreciated but is Not required.
//  2. Altered source versions must be clearly marked as such, And must Not be
//     misrepresented as being the original software.
//  3. This notice may Not be removed Or altered from any source distribution.
//
// /////////////////////////////////////////////////////////////////////////////

/*
    Written by Asger Feldthaus modified to include billboard removal

    February 2007
    June 2010
*/

#ifndef _C_BILLBOARD_GROUP_SCENE_NODE_H_
#define _C_BILLBOARD_GROUP_SCENE_NODE_H_

#include <ISceneNode.h>
#include <SMeshBuffer.h>

namespace irr
{
namespace scene
{

/*!
    \brief Group of billboards.

    Updates and displays multiple billboards. The billboards can not be removed or moved around after they are added.
    Billboards may be added as free billboards or axis-aligned billboards.

    Small optimizations are made when the billboards reach a certain distance from the camera.
 */
class CBillboardGroupSceneNode : public ISceneNode
{
public:
    struct SBillboard
    {
        core::vector3df Position;
        core::dimension2df Size;
        f32 Roll;
        core::vector3df Axis;
        bool HasAxis;
        video::SColor Color;

        u32 vertexIndex;
        void * prev;
        void * next;

        SBillboard() {}
        SBillboard( const core::vector3df& pos, const core::dimension2df& size, f32 roll, video::SColor color )
            : Position(pos), Size(size), Roll(roll), HasAxis(false), Color(color), prev(NULL), next(NULL) {}
    };

    //! Standard constructor for scene nodes
    //! Contains no billboards by default
    CBillboardGroupSceneNode( ISceneNode* parent, ISceneManager* manager, s32 id=-1,
            const core::vector3df& position = core::vector3df(0,0,0),
            const core::vector3df& rotation = core::vector3df(0,0,0),
            const core::vector3df& scale = core::vector3df(1,1,1) );

    ~CBillboardGroupSceneNode();

	virtual ESCENE_NODE_TYPE getType() const { return (ESCENE_NODE_TYPE)MAKE_IRR_ID('b','i','l','g'); }

    //! Adds a billboard.
    SBillboard * addBillboard( const core::vector3df& position, const core::dimension2df& size, f32 roll=0.0f, video::SColor vertexColor=video::SColor(255,255,255,255) );

    //! Adds a billboard resitricted to an axis.
    SBillboard *  addBillboardWithAxis( const core::vector3df& position, const core::dimension2df& size, const core::vector3df& axis, f32 roll=0.0f, video::SColor vertexColor=video::SColor(255,255,255,255) );

    void removeBillboard( CBillboardGroupSceneNode::SBillboard * bill );

    s32 getBillboardCount() const;

    virtual void OnRegisterSceneNode();

    virtual void render();

    const core::aabbox3df& getBoundingBox() const;

    video::SMaterial& getMaterial(u32 i);

    u32 getMaterialCount() const;

    //! Sets the vertex colors to simulate shadows on the billboards. The entire group will be treated as the upper half of
    //! a big sphere and every billboard is lighted acoording to its position on the sphere.
    //! Should be called AFTER the billboards have been added. To update new billboards, this method must be called again.
    //! This may be called many times, if the light setting should change.
    //! \param lightDir: The incoming light direction. This vector must be normalized (have length 1).
    //! \param intensity: The light intensity, typically between 0 and 1, although values greater than 1 may be used.
    //! \param ambient: The ambient light intensity. Between 0 and 1. Typically zero or close to zero.
    void applyVertexShadows( const core::vector3df& lightDir, f32 intensity, f32 ambient );

    //! Gives vertices back their original color.
    void resetVertexShadows();

	void forceUpdate( void ) { refresh = true; }

private:
    void updateBillboards();

    f32 FarDistance;
    f32 Radius;
    s32 count;
	bool refresh;

    core::vector3df LastCamDir;

    core::aabbox3df BoundingBox;
    video::SMaterial Material;

    SBillboard * Billboards;
//    core::array<SBillboard> Billboards; // A billboard's index is proportional to its index in the mesh buffer

    SMeshBuffer MeshBuffer;
};

} // namespace scene
} // namespace irr

#endif
