/*
 * NodeBallJoint.cpp
 *
 * Copyright (C) 1999 Stephen F. White, 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 */

/*****************************************************************************
 *                        Web3d.org Copyright (c) 2001
 *                               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.
 *
 ****************************************************************************/

#include <stdio.h>
#ifndef FLT_MAX
# include <float.h>
#endif
#include "stdafx.h"

#include "NodeBallJoint.h"
#include "Proto.h"
#include "Field.h"
#include "FieldValue.h"
#include "MFNode.h"
#include "SFBool.h"
#include "DuneApp.h"
#include "Scene.h"
#include "RenderState.h"
#include "NodeNavigationInfo.h"

ProtoBallJoint::ProtoBallJoint(Scene *scene)
  : AnchoredJointProto(scene, "BallJoint")
{
}

Node *
ProtoBallJoint::create(Scene *scene)
{ 
    return new NodeBallJoint(scene, this); 
}

NodeBallJoint::NodeBallJoint(Scene *scene, Proto *def)
  : AnchoredJointNode(scene, def)
{
#ifdef HAVE_LIBODE
    m_odeJoint = NULL;
#endif    
}

#ifdef HAVE_LIBODE
void    
NodeBallJoint::deleteFromODE(void)
{ 
    delete m_odeJoint; 
    m_odeJoint = NULL;
}

void
NodeBallJoint::updateRequestedOutputs(void)
{
// TODO: Fix the creation of a new array every frame.


    if(m_odeJoint == NULL)
        return;

/*
    // The implementation goes straight to the ODE C interface to avoid the
    // garbage generation that the getAnchor() method on JointBall creates.

    for(int i = 0; i < getProto()->getNumEventOuts(); i++) {
        switch(outputIndices[i]) {
            case FIELD_BODY1_ANCHOR_POINT:
                odeJoint.getAnchor(vfBody1AnchorPoint);

                hasChanged[FIELD_BODY1_ANCHOR_POINT] = true;
                fireFieldChanged(FIELD_BODY1_ANCHOR_POINT);
                break;

            case FIELD_BODY2_ANCHOR_POINT:
                odeJoint.getAnchor2(vfBody2AnchorPoint);

                hasChanged[FIELD_BODY2_ANCHOR_POINT] = true;
                fireFieldChanged(FIELD_BODY2_ANCHOR_POINT);
                break;
        }
    }
*/
}

/**
 * Set the parent world that this body belongs to. A null value clears
 * the world and indicates the physics model or body is no longer in use
 * by this world (eg deletes it).
 *
 * @param wld The new world instance to use or null
 * @param grp The group that this joint should belong to
 */
void 
NodeBallJoint::setODEWorld(dWorld wld, dJointGroup grp) 
{
    if(wld != NULL)
        m_odeJoint = new dBallJoint(wld, grp);
    else
        deleteFromODE();

    setBodiesToODEWorld();

    const float *vfAnchorPoint = anchorPoint()->getValue();
    m_odeJoint->setAnchor(vfAnchorPoint[0],
                          vfAnchorPoint[1],
                          vfAnchorPoint[2]);
}

#endif
