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

@ -6,7 +6,7 @@
normals or other such things.
The following materials must be set for model triangles: "a" for body, "b"
for rear wheels, "c" and "d" for front wheels.
for front wheels, "c" and "d" for back wheels.
*/
#include <stdio.h>

View file

@ -58,7 +58,6 @@ TPE_Vec3 _LCR_TPE_vec3DividePlain(TPE_Vec3 v, TPE_Unit d)
TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
{
return TPE_envAABoxInside(point,TPE_vec3(0,0,0),TPE_vec3(
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS,
(LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS) / 2,

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
}

View file

@ -102,7 +102,7 @@
#ifndef LCR_SETTING_CAMERA_HEIGHT
/** Base height of the car follow camera, in 4ths of map block height. */
#define LCR_SETTING_CAMERA_HEIGHT 7
#define LCR_SETTING_CAMERA_HEIGHT 5
#endif
#ifndef LCR_SETTING_CAMERA_HEIGHT_BAND
@ -110,10 +110,15 @@
#define LCR_SETTING_CAMERA_HEIGHT_BAND 1
#endif
#ifndef LCR_SETTING_CAMERA_MAX_DISTANCE
/** Maximum horizontal distance of the car follow camera, in 4ths of map block
#ifndef LCR_SETTING_CAMERA_DISTANCE
/** Base horizontal distance of the car follow camera, in 4ths of map block
width. */
#define LCR_SETTING_CAMERA_MAX_DISTANCE 5
#define LCR_SETTING_CAMERA_DISTANCE 4
#endif
#ifndef LCR_SETTING_CAMERA_DISTANCE_BAND
/** Band for distance of the car follow camera, in same units as base dist. */
#define LCR_SETTING_CAMERA_DISTANCE_BAND 3
#endif
#ifndef LCR_SETTING_GHOST_COLOR