bool SpatialNode::LookAt(const Vector3& target, const Vector3& up, TransformSpace space) { SpatialNode* parentNode = SpatialParent(); Vector3 worldSpaceTarget; switch (space) { case TS_LOCAL: worldSpaceTarget = WorldTransform() * target; break; case TS_PARENT: worldSpaceTarget = !parentNode ? target : parentNode->WorldTransform() * target; break; case TS_WORLD: worldSpaceTarget = target; break; } Vector3 lookDir = worldSpaceTarget - WorldPosition(); // Check if target is very close, in that case can not reliably calculate lookat direction if (lookDir.Equals(Vector3::ZERO)) return false; Quaternion newRotation; // Do nothing if setting look rotation failed if (!newRotation.FromLookRotation(lookDir, up)) return false; SetWorldRotation(newRotation); return true; }
void RigidBody::OnMarkedDirty(Node* node) { // If node transform changes, apply it back to the physics transform. However, do not do this when a SmoothedTransform // is in use, because in that case the node transform will be constantly updated into smoothed, possibly non-physical // states; rather follow the SmoothedTransform target transform directly // Also, for kinematic objects Bullet asks the position from us, so we do not need to apply ourselves if (!kinematic_ && (!physicsWorld_ || !physicsWorld_->IsApplyingTransforms()) && !smoothedTransform_) { // Physics operations are not safe from worker threads Scene* scene = GetScene(); if (scene && scene->IsThreadedUpdate()) { scene->DelayedMarkedDirty(this); return; } // Check if transform has changed from the last one set in ApplyWorldTransform() Vector3 newPosition = node_->GetWorldPosition(); Quaternion newRotation = node_->GetWorldRotation(); if (!newRotation.Equals(lastRotation_)) { lastRotation_ = newRotation; SetRotation(newRotation); } if (!newPosition.Equals(lastPosition_)) { lastPosition_ = newPosition; SetPosition(newPosition); } } }
bool Node::LookAt(const Vector3& target, const Vector3& up) { Vector3 lookDir = target - GetWorldPosition(); // Check if target is very close, in that case can not reliably calculate lookat direction if (lookDir.Equals(Vector3::ZERO)) return false; Quaternion rotation; // Do nothing if setting look rotation failed if (!rotation.FromLookRotation(lookDir, up)) return false; SetRotation((parent_ == scene_ || !parent_) ? rotation : parent_->GetWorldRotation().Inverse() * rotation); return true; }
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 = GetComponent<AnimationController>(); // Update the in air timer. Reset if grounded if (!onGround_) inAirTimer_ += timeStep; else inAirTimer_ = 0.0f; // When character has been in air less than 1/10 second, it's still interpreted as being on ground bool softGrounded = inAirTimer_ < INAIR_THRESHOLD_TIME; // Update movement & animation const Quaternion& rot = node_->GetRotation(); Vector3 moveDir = Vector3::ZERO; const Vector3& velocity = body->GetLinearVelocity(); // Velocity on the XZ plane Vector3 planeVelocity(velocity.x_, 0.0f, velocity.z_); if (controls_.IsDown(CTRL_FORWARD)) moveDir += Vector3::FORWARD; if (controls_.IsDown(CTRL_BACK)) moveDir += Vector3::BACK; if (controls_.IsDown(CTRL_LEFT)) moveDir += Vector3::LEFT; if (controls_.IsDown(CTRL_RIGHT)) moveDir += Vector3::RIGHT; // Normalize move vector so that diagonal strafing is not faster if (moveDir.LengthSquared() > 0.0f) moveDir.Normalize(); // If in air, allow control, but slower than when on ground body->ApplyImpulse(rot * moveDir * (softGrounded ? MOVE_FORCE : INAIR_MOVE_FORCE)); if (softGrounded) { // When on ground, apply a braking force to limit maximum ground velocity Vector3 brakeForce = -planeVelocity * BRAKE_FORCE; body->ApplyImpulse(brakeForce); // Jump. Must release jump control inbetween jumps if (controls_.IsDown(CTRL_JUMP)) { if (okToJump_) { body->ApplyImpulse(Vector3::UP * JUMP_FORCE); okToJump_ = false; } } else okToJump_ = true; } // Play walk animation if moving on ground, otherwise fade it out if (softGrounded && !moveDir.Equals(Vector3::ZERO)) animCtrl->PlayExclusive("Models/Jack_Walk.ani", 0, true, 0.2f); else animCtrl->Stop("Models/Jack_Walk.ani", 0.2f); // Set walk animation speed proportional to velocity animCtrl->SetSpeed("Models/Jack_Walk.ani", planeVelocity.Length() * 0.3f); // Reset grounded flag for next frame onGround_ = false; }