#include "camera_controller.h" #include "utils/mirror.h" START_REFLECT(CameraController); REFLECT_TYPECLASS(CameraController, SceneNodeEntity); END_REFLECT(CameraController); impl_Drop_for(CameraController, DestroyCameraController ) impl_SceneNodeEntity_for(CameraController, CameraControllerEnterTree, CameraControllerExitTree, CameraControllerTick ) SceneNode *CreateCameraController(Transformable target) { CameraController *self = new(CameraController); *self = (CameraController){ .transform = tc_null(Transformable), .rotation_speed = 5.f, .max_speed_time = 4.f, .target = target, .time_rotated = 0.f }; SceneNode *node = CreateSceneNode(CameraController_as_SceneNodeEntity(self)); return node; } void DestroyCameraController(CameraController *self) { free(self); } void CameraControllerEnterTree(CameraController *self) { self->transform = TC_CAST(self->node->parent->entity, Transformable); self->global = self->transform.tc->get_global_transform(self->transform.data); } void CameraControllerExitTree(CameraController *self) {} void CameraControllerTick(CameraController *self, double delta) { Transform current = self->transform.tc->get_global_transform(self->transform.data); self->target.tc->force_update(self->target.data); Transform target = self->target.tc->get_global_transform(self->target.data); // calculate time multiplier... float const time_mul = fminf(1.f, fmaxf(0.1f, powf(self->time_rotated / self->max_speed_time, 0.5f))); // ... angle difference ... float const angle = QuaternionAngleDifference(current.rotation, target.rotation); // ... and maximum frame step size float const step = self->rotation_speed * time_mul * delta; if(angle > 0.f) target.rotation = QuaternionSlerp(current.rotation, target.rotation, fminf(fminf(step, angle) / angle, 0.99f)); if(step > angle && self->time_rotated > delta) self->time_rotated -= 3.f * delta; else if(step > angle) self->time_rotated = 0.f; self->time_rotated += delta; self->transform.tc->set_global_transform(self->transform.data, target); }