#include "SIM_ForceOrbit.h"
#include <UT/UT_DSOVersion.h>
#include <GU/GU_PrimPoly.h>
#include <PRM/PRM_Include.h>
#include <SIM/SIM_PRMShared.h>
#include <SIM/SIM_DopDescription.h>
#include <SIM/SIM_GuideShared.h>
using namespace HDK_Sample;
void
initializeSIM(void *)
{
IMPLEMENT_DATAFACTORY(SIM_ForceOrbit);
}
SIM_ForceOrbit::SIM_ForceOrbit(const SIM_DataFactory *factory)
: BaseClass(factory),
SIM_OptionsUser(this)
{
}
SIM_ForceOrbit::~SIM_ForceOrbit()
{
}
static PRM_Name theGuideShowName(SIM_NAME_SHOWGUIDE, "Show Guide");
static PRM_Name theGuideSizeName(SIM_NAME_SCALE, "Scale");
static PRM_Name theGuideColorName(SIM_NAME_COLOR, "Color");
const SIM_DopDescription *
SIM_ForceOrbit::getForceOrbitDopDescription()
{
static PRM_Name thePointPositionName(SIM_NAME_POINTPOSITION,
"Point Position");
static PRM_Name thePointMassName(SIM_NAME_POINTMASS,
"Point Mass");
static PRM_Template theTemplates[] = {
PRM_Template(PRM_XYZ_J, 3, &thePointPositionName),
PRM_Template(PRM_FLT_J, 1, &thePointMassName, PRMoneDefaults),
PRM_Template()
};
static PRM_Template theGuideTemplates[] = {
PRM_Template(PRM_TOGGLE, 1, &theGuideShowName, PRMoneDefaults),
PRM_Template(PRM_FLT_J, 1, &theGuideSizeName, PRMoneDefaults),
PRM_Template(PRM_RGB_J, 3, &theGuideColorName, PRMoneDefaults),
PRM_Template()
};
static SIM_DopDescription theDopDescription(true,
"hdk_orbit",
"Orbit Force",
SIM_FORCES_DATANAME "/Orbit",
classname(),
theTemplates);
theDopDescription.setGuideTemplates(theGuideTemplates);
theDopDescription.setDefaultUniqueDataName(1);
return &theDopDescription;
}
SIM_Guide *
SIM_ForceOrbit::createGuideObjectSubclass() const
{
return new SIM_GuideShared(this, true);
}
void
SIM_ForceOrbit::buildGuideGeometrySubclass(const SIM_RootData &root,
const SIM_Options &options,
const GU_DetailHandle &gdh,
UT_DMatrix4 *xform,
const SIM_Time &t) const
{
if( !options.hasOption(theGuideShowName.getToken()) ||
!options.getOptionB(theGuideShowName.getToken()) )
return;
if( !gdh.isNull() )
{
GU_DetailHandleAutoWriteLock gdl(gdh);
GU_Detail *gdp = gdl.getGdp();
GB_AttributeRef attCd = gdp->addDiffuseAttribute(GEO_PRIMITIVE_DICT);
UT_Vector3 color(1, 1, 1);
if( options.hasOption(theGuideColorName.getToken()) )
color = options.getOptionV3(theGuideColorName.getToken());
for(int axis = 0; axis < 3; ++axis)
{
GEO_Point *pt0 = gdp->appendPoint();
GEO_Point *pt1 = gdp->appendPoint();
UT_Vector4 pos(0, 0, 0);
pos(axis) = -0.5;
pt0->setPos(pos);
pos(axis) = 0.5;
pt1->setPos(pos);
GU_PrimPoly *poly = (GU_PrimPoly *)gdp->appendPrimitive(GEOPRIMPOLY);
if(attCd.isValid())
poly->setValue<UT_Vector3>(attCd, color);
poly->appendVertex(pt0);
poly->appendVertex(pt1);
}
}
if( xform )
{
xform->identity();
if( options.hasOption(theGuideSizeName.getToken()) )
{
fpreal scale = options.getOptionF(theGuideSizeName.getToken());
xform->scale(scale, scale, scale);
}
UT_Vector3 pos = getPointPosition();
xform->translate(pos.x(), pos.y(), pos.z());
}
}
void
SIM_ForceOrbit::getForceSubclass(const SIM_Object &,
const UT_Vector3 &position,
const UT_Vector3 &,
const UT_Vector3 &,
const fpreal mass,
UT_Vector3 &force,
UT_Vector3 &torque) const
{
UT_Vector3 pointposition = getPointPosition();
fpreal distancesquared;
distancesquared = distance2(position, pointposition);
if( !UTequalZero(distancesquared) )
{
force = pointposition - position;
force *= (mass * getPointMass()) / distancesquared;
}
else
force = 0.0;
torque = 0.0;
applyNoise(position, force);
}
void
SIM_ForceOrbit::getForceOnCircleSubclass(const SIM_Object &object,
const UT_Vector3 &position,
const UT_Vector3 &,
const fpreal,
const UT_Vector3 &velocity,
const UT_Vector3 &angvel,
const fpreal mass,
UT_Vector3 &force,
UT_Vector3 &torque) const
{
getForceSubclass(object, position, velocity, angvel, mass, force, torque);
}
void
SIM_ForceOrbit::getForceOnSphereSubclass(const SIM_Object &object,
const UT_Vector3 &position,
const fpreal,
const UT_Vector3 &velocity,
const UT_Vector3 &angvel,
const fpreal mass,
UT_Vector3 &force,
UT_Vector3 &torque) const
{
getForceSubclass(object, position, velocity, angvel, mass, force, torque);
}