Smooth out camera real good

This commit is contained in:
Miloslav Ciz 2024-09-10 20:11:31 +02:00
parent 0cedae66a9
commit 4754b33dfe
4 changed files with 72 additions and 37 deletions

View file

@ -1163,6 +1163,30 @@ void _LCR_rendererLoadMapChunk(uint8_t chunk, int8_t x, int8_t y, int8_t z)
}
}
/**
Serves for smoothing out angle change, e.g. that of camera rotation.
*/
S3L_Unit _LCR_smoothRotation(S3L_Unit angleOld, S3L_Unit angleNew)
{
S3L_Unit angleDiff = angleNew - angleOld;
if (angleDiff == 0)
return angleNew;
S3L_Unit angleDiffAbs = S3L_abs(angleDiff);
if (angleDiffAbs > S3L_F / 2) // consider e.g. 350 degrees minus 1 degree
{
angleDiffAbs -= S3L_F / 2;
angleDiff += (angleDiff > 0) ? -1 * (S3L_F / 2) : (S3L_F / 2);
}
if (angleDiffAbs > S3L_F / 4) // angle too big, rotate immediately
return angleNew;
return angleOld + angleDiff / 4; // smoothly interpolate
}
/**
Loads the map models with 8 chunks that are nearest to a certain point
towards which camera is looking.
@ -1337,36 +1361,45 @@ void LCR_rendererCameraFollow(void)
(LCR_SETTING_CAMERA_HEIGHT + LCR_SETTING_CAMERA_HEIGHT_BAND) *
LCR_RENDERER_UNIT / 8);
LCR_renderer.scene.camera.transform.translation.x =
S3L_clamp(
LCR_renderer.scene.camera.transform.translation.x,
LCR_renderer.carModel->transform.translation.x -
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_RENDERER_UNIT / 4,
LCR_renderer.carModel->transform.translation.x +
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_RENDERER_UNIT / 4);
S3L_Vec4 toCam =
LCR_renderer.scene.camera.transform.translation;
LCR_renderer.scene.camera.transform.translation.z =
S3L_clamp(
LCR_renderer.scene.camera.transform.translation.z,
LCR_renderer.carModel->transform.translation.z -
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_RENDERER_UNIT / 4,
LCR_renderer.carModel->transform.translation.z +
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_RENDERER_UNIT / 4);
S3L_vec3Sub(&toCam,
LCR_renderer.carModel->transform.translation);
/* Hotfix for a Gimbal lock kinda issue, don't do lookAt when completely
above the car, rather shift the camera a bit (needs some tuning). */
if (S3L_abs(LCR_renderer.scene.camera.transform.translation.x -
LCR_renderer.carModel->transform.translation.x) > 8 &&
S3L_abs(LCR_renderer.scene.camera.transform.translation.z -
LCR_renderer.carModel->transform.translation.z) > 8)
S3L_lookAt(LCR_renderer.carModel->transform.translation,
&(LCR_renderer.scene.camera.transform));
else
S3L_Unit horizontalDist =
S3L_sqrt(toCam.x * toCam.x + toCam.z * toCam.z);
if (horizontalDist == 0)
{
LCR_renderer.scene.camera.transform.translation.x += 4;
LCR_renderer.scene.camera.transform.translation.z -= 8;
toCam.z = 1;
horizontalDist = 1;
}
S3L_Unit horizontalDistNew =
S3L_clamp(horizontalDist,
(LCR_SETTING_CAMERA_DISTANCE - LCR_SETTING_CAMERA_DISTANCE_BAND)
* (LCR_RENDERER_UNIT / 4),
(LCR_SETTING_CAMERA_DISTANCE + LCR_SETTING_CAMERA_DISTANCE_BAND)
* (LCR_RENDERER_UNIT / 4));
if (horizontalDistNew != horizontalDist)
{
toCam.x = (toCam.x * horizontalDistNew) / horizontalDist;
toCam.z = (toCam.z * horizontalDistNew) / horizontalDist;
LCR_renderer.scene.camera.transform.translation.x =
LCR_renderer.carModel->transform.translation.x +
(toCam.x * horizontalDistNew) / horizontalDist;
LCR_renderer.scene.camera.transform.translation.z =
LCR_renderer.carModel->transform.translation.z +
(toCam.z * horizontalDistNew) / horizontalDist;
}
S3L_lookAt(LCR_renderer.carModel->transform.translation,
&(LCR_renderer.scene.camera.transform));
#if LCR_SETTING_SMOOTH_ANIMATIONS
// now average with previous transform to smooth the animation out:
S3L_vec3Add(&(LCR_renderer.scene.camera.transform.translation),
@ -1376,13 +1409,11 @@ void LCR_rendererCameraFollow(void)
LCR_renderer.scene.camera.transform.translation.y /= 2;
LCR_renderer.scene.camera.transform.translation.z /= 2;
transPrev.rotation.x -= LCR_renderer.scene.camera.transform.rotation.x;
transPrev.rotation.y -= LCR_renderer.scene.camera.transform.rotation.y;
LCR_renderer.scene.camera.transform.rotation.x = _LCR_smoothRotation(
transPrev.rotation.x,LCR_renderer.scene.camera.transform.rotation.x);
if (S3L_abs(transPrev.rotation.y) < S3L_F / 5)
LCR_renderer.scene.camera.transform.rotation.y += transPrev.rotation.y / 2;
LCR_renderer.scene.camera.transform.rotation.x += transPrev.rotation.x / 2;
LCR_renderer.scene.camera.transform.rotation.y = _LCR_smoothRotation(
transPrev.rotation.y,LCR_renderer.scene.camera.transform.rotation.y);
#endif
}