Game Development Community

dev|Pro Game Development Curriculum

T2D rotateTo extension for fxPhysics2D

by Christian Armeanu · 09/02/2005 (5:14 pm) · 0 comments

There are several files that need to be touched for this to work, but nothing to be scared of ;-)
I hope I didn't miss anything, but I'm sure you'll let me know if I did ...

Ok, here we go ...

Part 1:

- add the following two blocks to class fxPhysics2D:

//##########################################################################################################################################
//## extensions by CA : 23-08-2005
//##########################################################################################################################################

inline bool isRotateTo(void)
	{ return mRotateTo; };
inline F32& getRotateToAngle(void)
	{ return mRotateToAngle; };
inline bool isRotateToLeft(void)
	{ return mRotateToLeft && mRotateTo; };
inline bool isRotateToRight(void)
	{ return (!mRotateToLeft) && mRotateTo; };
inline void disableRotateTo(void)
	{ mRotateTo = false; setAutoRotation(0); };	
void rotateTo( const F32 angle, const bool left = false );

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################

[b]And somewhere down with the member variables:[/b]

//##########################################################################################################################################
//## extensions by CA : 23-08-2005
//##########################################################################################################################################

bool	mRotateTo;		// if set, object will rotate in (mRotateToLeft) direction to mRotateToAngle
bool	mRotateToLeft;		// rotate to left if true
F32	mRotateToAngle;		// rotate to destination angle
bool	mRotateToOnReachCallback;	// if true, callback should be executed and flag reset to false

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################

Part 2:

- replace the following methods with the implementations below:

//-----------------------------------------------------------------------------
// Constructor.
//-----------------------------------------------------------------------------
fxPhysics2D::fxPhysics2D() :	T2D_Stream_HeaderID(makeFourCCTag('2','D','P','M')),
								T2D_Stream_Version(0X00000002),
								mLocalSerialiseID(1),
								mInitialised(false),
								mRefObjectId(0),
								mRefMetaString(StringTable->insert("")),
								mSize(10.0f, 10.0f),
								mHalfSize(5.0f, 5.0f),
								mDensity(defaultDensity),
								mCollisionScale(1.0f, 1.0f),
								mRotateTo(false),
								mRotateToOnReachCallback(false)
{
   // Set Vector Associations.
   VECTOR_SET_ASSOCIATION( mCollisionPolyList );
   VECTOR_SET_ASSOCIATION( mCollisionPolyBasisList );
}

//-----------------------------------------------------------------------------
// Initialise.
//-----------------------------------------------------------------------------
void fxPhysics2D::initialise( SimObjectId objectId, const char* pRefMetaString )
{
	// Set Reference Object-ID.
	mRefObjectId = objectId;

	// Set Reference Meta-String.
	if ( pRefMetaString )
		mRefMetaString = StringTable->insert( pRefMetaString );
	else
		mRefMetaString = StringTable->insert("");

	// Reset Net Velocities.
	mNetLinearVelocity.zero();
	mNetAngularVelocity = 0.0f;

	// Physics Suppression Off.
	setPhysicsSuppress(false);

	// Set Minimum/Maximum Linear/Angular Velocities.
	// NOTE:-	We do it without using the appropriate functions as they
	//			do specific checking which we don't want here.
	mMinLinearVelocity	= 0.0f;
	mMinAngularVelocity = 0.0f;
	mMaxLinearVelocity	= 2500.0f;
	mMaxAngularVelocity	= 2500.0f;

	//##########################################################################################################################################
//## extensions by CA : 23-08-2005
//##########################################################################################################################################

	mRotateTo = false;
	mRotateToOnReachCallback = false;
	
	// Disable rotate to angle 
	disableRotateTo();

	//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################
	
	// Set Velocities.
	setLinearVelocity( fxVector2D::getZero() );
	setAngularVelocity( 0.0f );

	// Set Other Material Properties.
	setDynamicFriction( defaultDynamicFriction );
	setRestitution( defaultRestitution );
	setRelaxation( defaultRelaxation );
	setForceScale( defaultForceScale );
	setDamping( defaultDamping );

	// Set Default Physical Metrics.
	setPosition( fxVector2D::getZero() );
	setAutoRotation( 0.0f );
	setRotation( 0.0f );

	// Reset Constant Force.
	setConstantForce( fxVector2D::getZero(), false );

	// Setup Initial Polygon.
	setCollisionPolyPrimitive( 4 );

	// Flag as Initialised.
	mInitialised = true;
}

Part 3:

//-----------------------------------------------------------------------------
// Update Physics Model.
//-----------------------------------------------------------------------------
void fxPhysics2D::update( F32 elapsedTime )
{
	// Cannot proceed without parent initialisation.
	if ( !isInitialised() )
	{
		// Warn.
		Con::warnf("fxPhysics2D::update() - Cannot proceed without initialisation!");
		return;
	}

// T2D Debug Profiling.
#ifdef T2D_DEBUG_PROFILING
		PROFILE_START(T2D_fxPhysics2D_update);
#endif

	// Nothing to do on immovable objects!
	if ( isImmovable() )
	{
		// Reset Linear/Angular Velocities.
		mLinearVelocity.zero();
		mAngularVelocity = 0.0f;
	}

	F32 fstep, fnow = mRotation, fdest;
	fxVector2D svc;

	// Update Physics if not suppressed.
	if ( !getPhysicsSuppress() )
	{
		// Get Velocities.
		fxVector2D linearVelocity = getLinearVelocity();
		F32 angularVelocity = mRadToDeg(getAngularVelocity());

		// Damping?
		if ( mNotZero( mDamping ) )
		{
			// Calculate integrated damping.
			F32 dampIntegral = mDamping * elapsedTime;

			// Yes, so any Linear Velocity?
			if ( mNotZero(linearVelocity.len()) )
			{
				// Yes, so damp Linear Velocity ...

				// Fetch Velocity Magnitude.
				F32 linVelMag = linearVelocity.len();
				// Calculate Renormalised Damped-Velocity.
				linearVelocity.normalise( getMax(linVelMag - (linVelMag * dampIntegral), 0.0f) );
			}

			// Any Angular Velocity?
			if ( mNotZero(angularVelocity) )
			{
				// Yes, so damp Angular Velocity ...

				// Calculate  damped-angular velocity delta.
				F32 deltaAngVel = angularVelocity * dampIntegral;
				// Ensure we don't get angular reversal!
				if ( angularVelocity < 0.0f )
					angularVelocity = getMin(angularVelocity-deltaAngVel, 0.0f);
				else
					angularVelocity = getMax(angularVelocity-deltaAngVel, 0.0f);
			}
		}

		// Integrate and clamp Velocities.
		setLinearVelocity( linearVelocity + (mNetLinearVelocity * mInverseMass * elapsedTime) );
		setAngularVelocity( angularVelocity + (mNetAngularVelocity * mInverseInertialMoment * elapsedTime) );

		// Integrate Position/Rotation.
		setPosition( mPosition + (linearVelocity * elapsedTime) );

		// Use maximum angular velocity of either inherent spin or auto-rotation.
		// NOTE:-	We need to determine which angular velocity causes the biggest
		//			change in current rotation.
		angularVelocity = mRadToDeg(getAngularVelocity());

//########################
//## extensions by CA : 23-08-2005
//## implemented rotateTo processing 
//########################
		
		if ( mFabs(mFmod(mAutoRotation,360.0f)) > mFabs(mFmod(angularVelocity,360.0f)) ) {
			// Auto-rotation.
			fstep = -(mAutoRotation * elapsedTime);
		} else {
			// Inherent Spin.
			fstep = (angularVelocity * elapsedTime);
		}
		
		if( mRotateTo && mAutoRotation > 0 ) {
			if( !mRotateToLeft ) {
				// turn left
				fnow -= mFabs(fstep);
				if( fnow < 0.0f ) fnow += 360.0f;
				if( ((mRotation >= mRotateToAngle) && (fnow < mRotateToAngle)) || ((mRotation <= mRotateToAngle) && (fnow < mRotateToAngle) && (fnow > mRotation)) ) {
					fnow = mRotateToAngle;
					mRotateToOnReachCallback = true;
					disableRotateTo();
				}
			} else {
				// turn right
				fnow += mFabs(fstep);
				if( fnow >= 360.0f ) fnow -= 360.0f;
				if( ((mRotation <= mRotateToAngle) && (fnow > mRotateToAngle)) || ((mRotation >= mRotateToAngle) && (fnow > mRotateToAngle) && (fnow < mRotation)) ) {
					fnow = mRotateToAngle;
					mRotateToOnReachCallback = true;
					disableRotateTo();
				}
			}
		} else {
			fnow = mRotation + fstep;
		}

		fnow = mFmod( fnow, 360.0f );
		setRotation( fnow );
//##################
	}
    
	// Reset Net Velocities.
	mNetLinearVelocity.zero();
	mNetAngularVelocity = 0.0f;

// T2D Debug Profiling.
#ifdef T2D_DEBUG_PROFILING
		PROFILE_END();
#endif
}

Part 4:

- add the following:

//##########################################################################################################################################
//## extensions by CA : 23-08-2005
//##########################################################################################################################################

void fxPhysics2D::rotateTo( const F32 angle, const bool left )
{
	mRotateToAngle = mFmod( angle, 360.0f );
	mRotateToLeft = left; 
	mRotateTo = true;
}

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################

Part 5:

add the following:

//##########################################################################################################################################
//## extensions by CA : 23-08-2005
//##########################################################################################################################################

ConsoleMethod(fxSceneObject2D, rotateTo, void, 4, 4, "(destAngle, mode) - Set autoRotation destination angle and rotation mode (0=shortest distance, 1=Left, >1=Right).")
{
	F32 fto, fmode, fact = object->getParentPhysicsModel().getRotation();
	
	dSscanf(argv[2],"%f", &fto);
	dSscanf(argv[3],"%f", &fmode);
	
	if( (isZero(fmode) && (distTurnRight(fact, fto) > distTurnLeft(fact, fto))) || fmode == 1 ) 
		object->getParentPhysicsModel().rotateTo(fto, true);
	else
		object->getParentPhysicsModel().rotateTo(fto, false);
}

ConsoleMethod(fxSceneObject2D, isRotateTo, bool, 2, 2, "() - Returns true if this object is auto rotating to a destination angle.")
{
	return object->getParentPhysicsModel().isRotateTo();
}

ConsoleMethod(fxSceneObject2D, isRotateToLeft, bool, 2, 2, "() - Returns true if this object is auto rotating to a destination angle counter clock wise.")
{
	return object->getParentPhysicsModel().isRotateToLeft();
}

ConsoleMethod(fxSceneObject2D, isRotateToRight, bool, 2, 2, "() - Returns true if this object is auto rotating to a destination angle clock wise.")
{
	return object->getParentPhysicsModel().isRotateToRight();
}

ConsoleMethod(fxSceneObject2D, onReachRotateTo, void, 3, 3, "(elapsedTime) - Default callback function when rotateTo destination angle is reached.") 
{
	return;
}

void fxSceneObject2D::updateRotateTo(F32 elapsedTime)
{
	if( getParentPhysicsModel().mRotateToOnReachCallback ) {
		getParentPhysicsModel().mRotateToOnReachCallback = false;

		Con::executef( this, 2, "onReachRotateTo", Con::getFloatArg( elapsedTime ) );
	}
}

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################

Part 6:

- insert the following at line [2596] after the physics update:

//##########################################################################################################################################
//## extensions by CA : 25-08-2005
//##########################################################################################################################################
				
pSceneObject2D->updateRotateTo( elapsedTime ); 

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################


And to test it, just try something like this:

$player.rotateTo( 123, true );
$player.setAutoRotation( 10 );

- Chris

About the author

Recent Blogs