Game Development Community

RotateTo extension

by Christian Armeanu · in Torque Game Builder · 08/24/2005 (10:05 am) · 14 replies

Hi,

I extended the engine (fxPhysics2D) with a rotateTo implementation and would like to know if anybody would be interested in:

void fxPhysics2D::rotateTo( const F32 angle, const bool left ) ...

"angle" is the destination angle and the boolean "left" indicates if the rotation should be CC.
Setting autorotation will perform the rotation with the given speed.

Cheers,
Chris

#1
08/24/2005 (10:10 am)
Absolutely. I've been getting by with a scripted function, but an engine class would be great.
#2
08/24/2005 (4:36 pm)
Sounds interesting are you going to post it as a Resource?
#3
08/24/2005 (8:20 pm)
Cool... please submit it if you want to... would help alot.. :)
#4
08/25/2005 (7:53 am)
Eh, I didn't have a lot of time to check the features of the GG site, so I'll just ask: Where should I put it? I was going to just post it here, but I assume as a resource would probably make more sense.

Just need to finish my path implementation (today or tomorrow) so I can give it a test drive and will post it latest this weekend (sorry, am a bit short on time).

@LoTekK: It's not a new class as it would require to many extensions to the engine, so I just extended the engine physics (where it seems to belong with the given T2D design anyway).
#5
08/25/2005 (8:02 am)
I think this has been suggested several times. Is Melv planning on adding something like this to the next release? I know I could use it a lot!

-Peter
#6
08/25/2005 (8:09 am)
@Melv: If you're happy with my implementation it, please feel free to include it.
#7
08/27/2005 (11:53 am)
For some reason adding a resource didn't work for me (trying to access the resource after adding reports an invalid / deleted reference ...), so I post it here for now ...

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 ...

- 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
//##########################################################################################################################################
#8
08/27/2005 (11:57 am)
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;
}
#9
08/27/2005 (12:04 pm)
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
}
#10
08/27/2005 (12:06 pm)
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
//##########################################################################################################################################
#11
08/27/2005 (12:09 pm)
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
//##########################################################################################################################################
#12
08/27/2005 (12:09 pm)
Part 6:

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

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

//##########################################################################################################################################
//## end of extensions
//##########################################################################################################################################
#13
08/27/2005 (12:11 pm)
And to test it, just try something like this:

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

Have fun!

- Chris
#14
08/30/2005 (12:03 pm)
I assume I didn't miss anything and it works?

- Chris