Fusion360-Addons/usr/Src/Core/pVehicle/pWheel2Run.cpp
2021-10-31 19:39:29 +01:00

379 lines
9.4 KiB
C++

#include <StdAfx.h>
#include "vtPhysXAll.h"
#include <xDebugTools.h>
#include "pWorldCallbacks.h"
#include "pCallbackSignature.h"
#include "virtools/vtTools.h"
#include "pVehicleAll.h"
using namespace vtTools::AttributeTools;
using namespace vtTools::ParameterTools;
using namespace vtTools::BehaviorTools;
bool pWheel2::isTorqueFromVehicle()
{
return getWheelFlag(WF_Accelerated) &&
getVehicle() && getVehicle()->isValidEngine() &&
getDifferential() ;
}
bool pWheel2::isAxleSpeedFromVehicle()
{
return ( getWheelFlag(WF_Accelerated) ) &&
( getWheelShape()->getWheelFlags() & WSF_AxleSpeedOverride ) &&
getVehicle() && getVehicle()->isValidEngine() && getDifferential() ;
}
void pWheel2::applyTorqueToPhysics()
{
if (getDifferential())
{
pDifferential *diff = getDifferential();
float finalTorqueOut = diff->GetTorqueOut(differentialSide);
mWheelShape->setMotorTorque(finalTorqueOut);
// Add torque to body because of the accelerating drivetrain
// This gives a bit of the GPL effect where your car rolls when
// you throttle with the clutch disengaged.
float tr=getVehicle()->getEngine()->GetTorqueReaction();
if(tr>0)
{
// VxVector torque(0,0,diff->GetAccIn()*diff->inertiaIn*tr);
// getBody()->addTorque(torque);
}
/* if( (wheel->getWheelShape()->getWheelFlags() & WSF_AxleSpeedOverride ) )
{
float v = wheel->rotationV.x;
v = v * getEngine()->getEndRotationalFactor() * getEngine()->getTimeScale();
}
*/
}
}
void pWheel2::_createInternalContactModifyCallback()
{
if (mWheelShape)
{
if (!wheelContactModifyCallback)
{
wheelContactModifyCallback = new pWheelContactModify();
wheelContactModifyCallback->setWheel(this);
mWheelShape->setUserWheelContactModify((NxUserWheelContactModify*)wheelContactModifyCallback);
}
//----------------------------------------------------------------
//track information about callback
if (getBody())
getBody()->getCallMask().set(CB_OnWheelContactModify,true);
}
}
bool pWheelContactModify::onWheelContact(NxWheelShape* wheelShape,
NxVec3& contactPoint,
NxVec3& contactNormal,
NxReal& contactPosition,
NxReal& normalForce,
NxShape* otherShape,
NxMaterialIndex& otherShapeMaterialIndex,
NxU32 otherShapeFeatureIndex)
{
pWheel2 *wheel = static_cast<pWheel2*>(getWheel());
if (!getWheel())
return true;
int contactModifyFlags = 0 ;
bool createContact=true;
//----------------------------------------------------------------
//
// store compact :
//
if (wheel->getBody()->getCallMask().test(CB_OnWheelContactModify))
{
pWheelContactModifyData &contactData = lastData;
contactData.object = getEntityFromShape(wheelShape);
contactData.contactNormal = getFrom(contactNormal);
contactData.contactPoint = getFrom(contactPoint);
contactData.contactPosition = contactPosition;
contactData.normalForce = normalForce;
contactData.otherMaterialIndex = otherShapeMaterialIndex;
createContact = wheel->onWheelContactModify(contactModifyFlags,&contactData);
if (!createContact)
return false;
if (contactModifyFlags==0)
return true;
//----------------------------------------------------------------
//
// copy result back to sdk
//
contactNormal = getFrom(contactData.contactNormal);
contactPoint = getFrom(contactData.contactPoint);
contactPosition = contactData.contactPosition;
normalForce = contactData.normalForce;
}
//xWarning("whatever");
return true;
}
bool pWheel2::onWheelContactModify(int& changeFlags,pWheelContactModifyData* contact)
{
bool result = true;
//----------------------------------------------------------------
//
// sanity checks
//
if (!contact)
return true;
//----------------------------------------------------------------
//
// keep some informationens for our self
//
if( getProcessOptions() & pVPO_Wheel_UsePHYSX_Load &&
getProcessOptions() & pVPO_Wheel_UsePHYSX_CONTACT_DATA && getVehicle()
)
{
load = contact->contactNormal.y;
if (load > 1500)
load = 1500;
if (load <= 0)
load = 1000;
}
CKBehavior * beh = (CKBehavior*)GetPMan()->GetContext()->GetObject(getWheelContactScript());
if (beh && CKGetObject(ctx(),getEntID()))
{
SetInputParameterValue<CK_ID>(beh,bbIWC_SrcObject,getEntID());
SetInputParameterValue<VxVector>(beh,bbIWC_Point,contact->contactPoint);
SetInputParameterValue<VxVector>(beh,bbIWC_Normal,contact->contactNormal);
SetInputParameterValue<float>(beh,bbIWC_Position,contact->contactPosition);
SetInputParameterValue<float>(beh,bbIWC_NormalForce,contact->normalForce);
SetInputParameterValue<int>(beh,bbIWC_OtherMaterialIndex,contact->otherMaterialIndex);
//----------------------------------------------------------------
//
// execute:
//
beh->Execute(lastStepTimeSec);
//----------------------------------------------------------------
//
// refuse contact
//
result = GetOutputParameterValue<int>(beh,bbOWC_CreateContact);
if (!result)
return false;
//----------------------------------------------------------------
//
// nothing changed, return true
//
changeFlags = GetOutputParameterValue<int>(beh,bbOWC_ModificationFlags);
if (changeFlags == 0 )
{
return true;
}
//----------------------------------------------------------------
//
// pickup data, according to change flags
//
if (changeFlags & CWCM_ContactPoint )
contact->contactPoint = GetOutputParameterValue<VxVector>(beh,bbOWC_Point);
if (changeFlags & CWCM_ContactNormal)
contact->contactNormal= GetOutputParameterValue<VxVector>(beh,bbOWC_Normal);
if (changeFlags & CWCM_ContactPosition )
contact->contactPosition= GetOutputParameterValue<float>(beh,bbOWC_Position);
if (changeFlags & CWCM_NormalForce )
contact->normalForce = GetOutputParameterValue<float>(beh,bbOWC_NormalForce);
}
return true;
}
bool pWheel2::onWheelContact(CK3dEntity* wheelShapeReference, VxVector& contactPoint, VxVector& contactNormal, float& contactPosition, float& normalForce, CK3dEntity* otherShapeReference, int& otherShapeMaterialIndex)
{
//NxUserAllocator
return true;
}
void pWheel2::setWheelContactScript(int val)
{
CKBehavior * beh = (CKBehavior*)GetPMan()->GetContext()->GetObject(val);
if (!beh)
return;
XString errMessage;
if (!GetPMan()->checkCallbackSignature(beh,CB_OnWheelContactModify,errMessage))
{
xError(errMessage.Str());
return;
}
pCallbackObject::setWheelContactScript(val);
wheelContactModifyCallback = new pWheelContactModify();
wheelContactModifyCallback->setWheel(this);
getWheelShape()->setUserWheelContactModify((NxUserWheelContactModify*)wheelContactModifyCallback);
//----------------------------------------------------------------
//track information about callback
getBody()->getCallMask().set(CB_OnWheelContactModify,true);
}
void pWheel2::processPreScript()
{
}
void pWheel2::processPostScript()
{
}
int pWheel2::onPostProcess()
{
return 1;
}
int pWheel2::onPreProcess()
{
return 1;
}
void pWheel2::_tick(float dt)
{
float dt2 = dt;
NxWheelShape *wShape = getWheelShape();
if (!wShape) return;
NxVec3 _localVelocity;
bool _breaking=false;
NxWheelContactData wcd;
NxShape* contactShape = wShape->getContact(wcd);
if (contactShape)
{
NxVec3 relativeVelocity;
if ( !contactShape->getActor().isDynamic())
{
relativeVelocity = getActor()->getLinearVelocity();
} else {
relativeVelocity = getActor()->getLinearVelocity() - contactShape->getActor().getLinearVelocity();
}
NxQuat rotation = getActor()->getGlobalOrientationQuat();
_localVelocity = relativeVelocity;
rotation.inverseRotate(_localVelocity);
_breaking = false; //NxMath::abs(_localVelocity.z) < ( 0.1 );
// wShape->setAxleSpeed()
}
float rollAngle = getWheelRollAngle();
rollAngle+=wShape->getAxleSpeed() * (dt);
//rollAngle+=wShape->getAxleSpeed() * (1.0f/60.0f /*dt* 0.01f*/);
while (rollAngle > NxTwoPi) //normally just 1x
rollAngle-= NxTwoPi;
while (rollAngle< -NxTwoPi) //normally just 1x
rollAngle+= NxTwoPi;
setWheelRollAngle(rollAngle);
NxMat34& wheelPose = wShape->getGlobalPose();
NxReal stravel = wShape->getSuspensionTravel();
NxReal radius = wShape->getRadius();
//have ground contact?
if( contactShape && wcd.contactPosition <= (stravel + radius) ) {
wheelPose.t = NxVec3( wheelPose.t.x, wcd.contactPoint.y + getRadius(), wheelPose.t.z );
}
else {
wheelPose.t = NxVec3( wheelPose.t.x, wheelPose.t.y - getSuspensionTravel(), wheelPose.t.z );
}
float rAngle = getWheelRollAngle();
float steer = wShape->getSteerAngle();
NxVec3 p0;
NxVec3 dir;
/*
getWorldSegmentFast(seg);
seg.computeDirection(dir);
dir.normalize();
*/
NxReal r = wShape->getRadius();
NxReal st = wShape->getSuspensionTravel();
NxReal steerAngle = wShape->getSteerAngle();
p0 = wheelPose.t; //cast from shape origin
wheelPose.M.getColumn(1, dir);
dir = -dir; //cast along -Y.
NxReal castLength = r + st; //cast ray this long
NxMat33 rot, axisRot, rollRot;
rot.rotY( wShape->getSteerAngle() );
axisRot.rotY(0);
rollRot.rotX(rAngle);
wheelPose.M = rot * wheelPose.M * axisRot * rollRot;
setWheelPose(wheelPose);
}