No one asked how to spin your model by 180 in code. I guess everyone already knows how to do this, but here is how-to for some who don’t know.
Using 18_CharacterDemo, snippets of relevant sections.
Spinning your model by 180 in code
CharacterDemo.cpp
void CharacterDemo::CreateCharacter()
{
ResourceCache* cache = GetSubsystem<ResourceCache>();
Node* objectNode = scene_->CreateChild("Jack");
objectNode->SetPosition(Vector3(0.0f, 1.0f, 0.0f));
// rotate model by 180 ****************************
Node* adjustNode = objectNode->CreateChild("AdjNode");
Quaternion qAdjRot(180, Vector3(0,1,0) ); // rotate it by 180
adjustNode->SetRotation( qAdjRot );
// Create the rendering component + animation controller
AnimatedModel* object = adjustNode->CreateComponent<AnimatedModel>();
//********************* change the model and material name
object->SetModel(cache->GetResource<Model>("Models/Jack.mdl"));
object->SetMaterial(cache->GetResource<Material>("Materials/Jack.xml"));
object->SetCastShadows(true);
adjustNode->CreateComponent<AnimationController>();
// ******************** rename it to proper head joint name // Set the head bone for manual control
object->GetSkeleton().GetBone("Bip01_Head")->animated_ = false;
. . .
}
void CharacterDemo::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
{
if (!character_)
return;
Node* characterNode = character_->GetNode();
// Get camera lookat dir from character yaw + pitch
Quaternion rot = characterNode->GetRotation();
Quaternion dir = rot * Quaternion(character_->controls_.pitch_, Vector3::RIGHT);
// ************* rename it to proper head joint name // Turn head to camera pitch, but limit to avoid unnatural animation
Node* headNode = characterNode->GetChild("Bip01_Head", true);
float limitPitch = Clamp(character_->controls_.pitch_, -45.0f, 45.0f);
Quaternion headDir = rot * Quaternion(limitPitch, Vector3(1.0f, 0.0f, 0.0f));
// This could be expanded to look at an arbitrary target, now just look at a point in front
Vector3 headWorldTarget = headNode->GetWorldPosition() + headDir * Vector3(0.0f, 0.0f, -1.0f); // -z direction ****************************
headNode->LookAt(headWorldTarget, Vector3(0.0f, 1.0f, 0.0f));
// Correct head orientation because LookAt assumes Z = forward, but the bone has been authored differently (Y = forward)
// headNode->Rotate(Quaternion(0.0f, 90.0f, 90.0f)); //************************* dont need this
. . .
}
Character.cpp
void Character::FixedUpdate(float timeStep)
{
/// \todo Could cache the components for faster access instead of finding them each frame
RigidBody* body = GetComponent<RigidBody>();
AnimationController* animCtrl = node_->GetComponent<AnimationController>(true); //********** recursive get
. . .
}
Edit: changed comment to “recursive get”