60 lines
2.1 KiB
C
60 lines
2.1 KiB
C
#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);
|
|
}
|