Hello,
I have a general question that assistance would be helpful. I have been able to get the physics update to work mostly. So ship flight. I have some code that I use similiar to the CharacterDemo.cpp.
Right now, I have to simulate gravity of a character which is a node with a rigidbody to a ship node with a rigidbody. When the character enters a ship I flag and save the ship rigidbody and node so the character component has the info as it also handle if a character is locked.
I’m trying to think of the best way to update the character rigidbody to allow movement inside a ship while maintaining the proper rotation and location inside the ship rigidbody. the character node is a independent node not under the ship node tree.
The rough code is below. The latter code is basically the RigidBody of the ship or whatever chosen object.
void CharacterComponent::FixedUpdate(float timeStep) {
static bool usUpdating = false;
// update if it is server or we set flag that it is local component
//if (!g_pApp->GetGameLogic()->IsProxy() || m_bIsLocal)
if (g_pApp->GetAppType() != ApplicationType_Server) {
// If RigidBody exist and animation controller
if (m_pBody && m_pAnimControl && !usUpdating) {
// if character is not locked
if (m_bLockedPosition == false) {
// Update the in air timer. Reset if grounded
if (!m_bIsOnGround) {
m_InAirTime += timeStep;
} else {
m_InAirTime = 0.0f;
}
// When CharacterComponent has been in air less than 1/10 second, it's still interpreted as being on ground
bool softGrounded = (m_InAirTime = 0.0f < g_InAirThreshHoldTime)
!= 0;
// Update movement & animation
const Quaternion& rot = node_->GetRotation();
// Normalize move vector so that diagonal strafing is not faster
if (m_MoveDir.LengthSquared() > 0.0f) {
m_MoveDir.Normalize();
}
// Calculate move force
m_MoveDir *= .5;
Vector3 MovementImpulse;
if (softGrounded) {
// If in air, allow control, but slower than when on ground
if (m_MoveDir != Vector3::ZERO) {
if (!m_bStopWalk) {
if (m_MoveForce != 0.0f) {
// m_pBody->ApplyImpulse(rot * m_MoveDir * (softGrounded ? m_MoveForce : INAIR_MOVE_FORCE));
MovementImpulse = rot * m_MoveDir
* (softGrounded ?
m_MoveForce : g_InAirMoveForce);
} else {
//m_pBody->ApplyImpulse(rot * m_MoveDir * (softGrounded ? MOVE_FORCE : INAIR_MOVE_FORCE));
MovementImpulse = rot * m_MoveDir
* (softGrounded ?
g_MoveForce : g_InAirMoveForce);
}
//m_pBody->ApplyImpulse(rot * m_MoveDir);
m_pBody->ApplyImpulse(MovementImpulse);
} else {
//Vector3 moveDir = Vector3::ZERO;
const Vector3& velocity =
m_pBody->GetLinearVelocity();
// Velocity on the XZ plane
Vector3 planeVelocity(velocity.x_, 0.0f,
velocity.z_);
// When on ground, apply a braking force to limit maximum ground velocity
Vector3 brakeForce = -planeVelocity;
m_pBody->SetLinearVelocity(brakeForce);
// Reset Stop Walk
m_bStopWalk = false;
}
// Reset move direction
m_MoveDir = Vector3::ZERO;
} else {
//Vector3 moveDir = Vector3::ZERO;
const Vector3& velocity = m_pBody->GetLinearVelocity();
// Velocity on the XZ plane
Vector3 planeVelocity(velocity.x_, 0.0f, velocity.z_);
// When on ground, apply a braking force to limit maximum ground velocity
Vector3 brakeForce = -planeVelocity * g_BrakeForce;
m_pBody->ApplyImpulse(brakeForce);
}
// Jump. Must release jump control inbetween jumps
if (m_bIsInJump) {
if (m_bIsOnJump) {
//Vector3 moveDir = Vector3::ZERO;
const Vector3& velocity =
m_pBody->GetLinearVelocity();
// If vvelocity below 0 or above 1 assume either falling or moving
if (velocity.y_ < 0.1f && velocity.y_ >= 0.0f) {
// Apply force to jump
if (m_JumpForce) {
m_pBody->ApplyImpulse(
Vector3::UP * m_JumpForce);
} else {
m_pBody->ApplyImpulse(
Vector3::UP * g_JumpForce);
}
} else {
// If force could not be apply assume model stopped set In Jump to false
m_bIsInJump = false;
}
m_bIsOnJump = false;
}
} else {
m_bIsOnJump = true;
}
// Set rotation based on turned direction
if (m_TurnDirection == TURN_LEFT) {
// Get node rotation quaternion
Quaternion rot = GetNode()->GetRotation();
// Create a quaternion
Quaternion baseRot = Quaternion(1.0f, 0.0f, 0.0f, 0.0f);
// Get a quaternion from a default quaternoin identity
baseRot.FromAngleAxis(-16, Vector3(0.0f, 1.0f, 0.0f));
Quaternion NewRot = rot * baseRot;
float dt;
if (timeStep > 1.0f / 30.0f) {
dt = 1.0f / 30.0f;
} else {
dt = timeStep;
}
//GetNode()->SetRotation(rot.Slerp(NewRot, timeStep/1.0f));
GetNode()->SetRotation(rot.Slerp(NewRot, dt));
} else if (m_TurnDirection == TURN_RIGHT) {
// Get node rotation quaternion
Quaternion rot = GetNode()->GetRotation();
// Create a quaternion
Quaternion baseRot = Quaternion(1.0f, 0.0f, 0.0f, 0.0f);
// Get a quaternion from a default quaternoin identity
baseRot.FromAngleAxis(16, Vector3(0.0f, 1.0f, 0.0f));
Quaternion NewRot = rot * baseRot;
float dt;
if (timeStep > 1.0f / 30.0f) {
dt = 1.0f / 30.0f;
} else {
dt = timeStep;
}
//GetNode()->SetRotation(rot.Slerp(NewRot, timeStep/1.0f));
GetNode()->SetRotation(rot.Slerp(NewRot, dt));
}
}
} else {
// Locked position
// Constraints handle the position of the character
}
}
}
// If camera exist
if (m_pCamera) {
// Updaw character yaw and povement
Quaternion Rot(1.0f, 0.0f, 0.0f, 0.0f);
// Get mouse position
IntVector2 MousePosition = m_pInput->GetMousePosition();
// Calculate look based on screen view
float mWindowBasePitched = (float) (MousePosition.x_
- (g_pApp->GetGraphics()->GetWidth() / 2));
float mWindowBaseYaw = (float) (MousePosition.y_
- (g_pApp->GetGraphics()->GetHeight() / 2));
float newPitch = Clamp((float) mWindowBasePitched, -90.0f, 90.0f);
float newYaw = Clamp((float) mWindowBaseYaw, -90.0f, 90.0f);
// If key is hard reseet
if (m_pInput->GetKeyDown(KEY_LALT) || m_pInput->GetKeyDown(KEY_RALT)) {
newPitch = 0;
newYaw = 0;
}
// Create a new quaternion
Quaternion CameraClamped(newYaw, newPitch, 0.0f);
Node * pViewCameraNode = m_pCamera->GetNode();
Quaternion RootRot = pViewCameraNode->GetRotation();
// Rotate Camera
if (m_pInput->GetKeyDown(KEY_LCTRL) || m_pInput->GetKeyDown(KEY_RCTRL)
|| m_pInput->GetKeyDown(KEY_LALT)
|| m_pInput->GetKeyDown(KEY_RALT)) {
if (pViewCameraNode) {
// Removed line to figure out better rotation
// Quaternion NewRot = RootRot.Slerp(Rot*CameraClamped, timeStep*.99);
Quaternion NewRot = Rot * CameraClamped;
pViewCameraNode->SetRotation(NewRot);
}
}
}
// if not updating
if (!g_pApp->GetGameLogic()->IsProxy() && !usUpdating) {
// Get node rotation quaternion
Vector3 pos = m_pBody->GetPosition();
Quaternion rotation = m_pBody->GetRotation();
// if position and rotation different
if (rotation != m_PreviousRotation || pos != m_PreviousPosition) {
// if changed
VariantMap data;
data["CONTENT_ID"] = 1;
data[CHARACTER_MOVE::P_GAME_ASSET_ID] = node_->GetID();
data[CHARACTER_MOVE::P_GAME_ASSET_LOCATION] = node_->GetVar(
"location").GetString();
data[CHARACTER_MOVE::P_NEW_ORIENTATION] = rotation;
data[CHARACTER_MOVE::P_NEW_POSITION] = pos;
SendEvent(REMOTE_EVENT_CHARACTER_MOVE, data);
// save position
m_PreviousPosition = pos;
m_PreviousRotation = rotation;
}
}
// Reset grounded flag for next frame
m_bIsOnGround = false;
m_TurnDirection = TURN_NONE;
// Reset move direction
m_MoveDir = Vector3::ZERO;
}
void CharacterComponent::SetGravityNode(Node * pNode) {
{
if (pNode) {
m_pGravityNode = pNode;
m_pGravityRigidBody = pNode->GetComponent<RigidBodyComponent>();
} else {
m_pGravityNode = nullptr;
m_pGravityRigidBody = nullptr;
}
}
}