/*
 * UsePhysicsEngine.h
 *
 * Copyright (C) 2007 J. "MUFTI" Scheurich
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#ifndef _USE_PHYSICS_ENGINE_H
#define _USE_PHYSICS_ENGINE_H

#include "config.h"

#ifdef HAVE_LIBODE

#include "ode/ode.h"

#include "NodeArray.h"
#include "Arrays.h"

// license from the Xj3D project
/*****************************************************************************
 *                        Web3d.org Copyright (c) 2001 - 2006
 *                               Java Source
 *
 * This source is licensed under the GNU LGPL v2.1
 * Please read http://www.gnu.org/copyleft/lgpl.html for more information
 *
 * This software comes with the standard NO WARRANTY disclaimer for any
 * purpose. Use it at your own risk. If there's a problem you get to fix it.
 *
 ****************************************************************************/

/**
 * Manager for the rigid body physics model nodes.
 * <p>
 *
 * Keeps track of both the collections of bodies and the individual joints.
 * The collection nodes are evaluated at the end of the frame so as to modify
 * the final object locations for this frame. The joints are managed so that
 * those that need to produce output will be evaluated at the start of the
 * next frame. This requires the manager to register as both pre and post
 * event model node manager, as it manages both sets of nodes, though
 * independently.
 * <p>
 *
 * The physics model is run at a somewhat fixed frame rate. Physics models
 * don't like to have variable frame rate as input, so we smooth these out
 * over a fixed number of frames. Every set of frame resets the calculation
 * interval based on recent history.
 *
 * @author Justin Couch
 * @version $Revision: 1.4 $
 */

class UsePhysicsEngine {
public:
                UsePhysicsEngine();
                ~UsePhysicsEngine() { dCloseODE(); }

    void        setVRMLClock(double clk);
    void        resetTimeZero();

    void        addOrRemoveManagedNode(Node* node, bool add);

    void        addManagedNode(Node* node);
    void        removeManagedNode(Node* node);
 
    void        executePreEventModel(double time);
    void        executePostEventModel(double time);

    void        clear();

protected:

    /** List of managed node types */
    IntArray m_managedNodeTypes;

    /** Average out the timesteps every so often */
    static const int m_recalc_interval = 10;

    /** Manager for all the RigidBodyCollection nodes here */
    NodeArray m_collections;

    /** The updated set of collections */
    NodeArray m_updatedCollections;

    /** Manager for all the joint nodes here */
    NodeArray m_joints;

    /** The updated set of joints */
    NodeArray m_updatedJoints;

    /** Manager for all the body nodes here */
    NodeArray m_bodies;

    /** The updated set of collections */
    NodeArray m_updatedBodies;

    /** Manager for the nbody collidable nodes */
    NodeArray m_collidables;

    /** The updated set of collidables */
    NodeArray m_updatedCollidables;

    /** Manager for the nbody collision space nodes */
    NodeArray m_collisionSpaces;

    /** The updated set of collision spaces */
     NodeArray m_updatedCollisionSpaces;

    /** Manager for the nbody sensor nodes */
    NodeArray m_sensors;

    /** The updated set of sensors */
    NodeArray m_updatedSensors;

    /** Time in seconds this was last called. The dT passed to ODE. */
    double m_lastTime;

    /** Elapsed time since the last recalc interval */
    double m_elapsedTime;

    /** The current counter in the recalc time */
    int m_countTick;

    /** The current deltaT calculated to feed to the physics model */
    float m_deltaT;

    /** The clock used to reinitialise time with */
    double m_vrmlClock;

/*
protected:
    dWorldID _odeWorld;
    dSpaceID _collisionSpace;
    float _gravity; 
    double _constraintForceMixing;
    double _errorReductionParameter;
*/
};

#endif

#endif
