Link to video
Link to code

Weapons point in (0,0,-1) in model space with the tip of the handle located at (0,0,0). startingOffset and endingOffset are two vectors controlling the direction of the swing – for the mace above, they’re set to (0,1,-1) and (0,-1,-1) and then normalized (before we hit the code below.) The code is longer than it needs to be mainly for debugging/clarity, as I’m trying to isolate the problem. Any help is much appreciated!

The code looks like:

// this will be the player's transform
Transform* parentTransform = (Transform*)parent->GetComponent( CT_Transform );

if( parentTransform )
{
Body* weaponBody = (Body*)owner->GetComponent( CT_Body );

// The location of the wielder
btVector3 parentPosition = btVector3( parentTransform->position.x, parentTransform->position.y, parentTransform->position.z );

// The rotation of the wielder
btQuaternion parentRotation = btQuaternion( parentTransform->rotation.x, parentTransform->rotation.y, parentTransform->rotation.z, parentTransform->rotation.w );

// The weapon is offset from the parent position (to a point corresponding to the player's hand)
// TODO: Pass this in from the character controller
btVector3 handOffset = btVector3( -4, 1, -4 );

// this was to handle weapons with widths that are even
if( weaponBody && weaponBody->offset.x > 0 )
{
handOffset.setX( handOffset.getX() + weaponBody->offset.x );
}

// currentVector is some portion of the way between starting and ending offset
float progress = currentSwingDuration / totalSwingDuration;

btVector3 parentAxis = parentRotation.getAxis();
float parentAngle = parentRotation.getAngle();

// Rotate starting/ending to align with player, interpolate based on progress to get current
btVector3 rotatedStart = startingOffset.rotate( parentAxis, parentAngle );
btVector3 rotatedEnd = endingOffset.rotate( parentAxis, parentAngle );
btVector3 currentVector = rotatedStart.lerp( rotatedEnd, progress );

// get axis/angle to rotate starting vector to current
btVector3 planeThatRotatesStartToCurrent = rotatedStart.cross( currentVector );
float angleThatRotatesStartToCurrent = rotatedStart.angle( currentVector );

// get axis/angle to rotate weapon to start
btVector3 planeThatRotatesWepToStart = btVector3( 0, 0, -1 ).cross( rotatedStart );
float angleThatRotatesWepToStart = btVector3( 0, 0, -1 ).angle( rotatedStart );

// Rotate the handOffset
handOffset = handOffset.rotate( parentRotation.getAxis(), parentRotation.getAngle() );

//DebugDraw::instance.drawLine( parentPosition + handOffset, parentPosition + handOffset + ( currentVector * 30.0f ), btVector3( 0, 1, 0 ) );

// get a quaternion to rotate the weapon from it's default direction (0, 0, -1) to current...
btQuaternion weaponRotation = btQuaternion( planeThatRotatesStartToCurrent, angleThatRotatesStartToCurrent ) * btQuaternion( planeThatRotatesWepToStart, angleThatRotatesWepToStart );

// Push currentVector out based on the length of the weapon (we want the handle of the weapon located at the origin)
if( weaponBody )
{
currentVector *= abs( weaponBody->offset.z );
}

currentVector = currentVector + handOffset + parentPosition;

// Communicate the new position + rotation to our parent composition
owner->ReceiveMessage( &DataMessage( MSG_SetRotation, XMFLOAT4( weaponRotation.getX(), weaponRotation.getY(), weaponRotation.getZ(), weaponRotation.getW() ) ) );
owner->ReceiveMessage( &DataMessage( MSG_SetPosition, XMFLOAT3( currentVector.getX(), currentVector.getY(), currentVector.getZ() ) ) );

Advertisements