Implement flyby spline looping in lua API

This commit is contained in:
Lwmte 2025-03-28 21:36:37 +01:00
parent 7ba9370281
commit 9fc370833b
5 changed files with 58 additions and 17 deletions

View file

@ -20,6 +20,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Lua API changes ### Lua API changes
* Added missing constructor for `Collision.Probe` without room number. * Added missing constructor for `Collision.Probe` without room number.
* Added optional looping argument for `View.GetFlybyPosition` and `View.GetFlybyRotation` functions.
## [Version 1.8](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8) - 2025-03-16 ## [Version 1.8](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8) - 2025-03-16

View file

@ -176,11 +176,11 @@
<td class="summary">Play a flyby sequence.</td> <td class="summary">Play a flyby sequence.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#GetFlybyPosition">GetFlybyPosition(seqID, progress)</a></td> <td class="name" ><a href="#GetFlybyPosition">GetFlybyPosition(seqID, progress[, loop])</a></td>
<td class="summary">Get a flyby sequence's position at a specified progress point in percent.</td> <td class="summary">Get a flyby sequence's position at a specified progress point in percent.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#GetFlybyRotation">GetFlybyRotation(seqID, progress)</a></td> <td class="name" ><a href="#GetFlybyRotation">GetFlybyRotation(seqID, progress[, loop])</a></td>
<td class="summary">Get a flyby sequence's rotation at a specified progress point in percent.</td> <td class="summary">Get a flyby sequence's rotation at a specified progress point in percent.</td>
</tr> </tr>
<tr> <tr>
@ -499,7 +499,7 @@
</dd> </dd>
<dt> <dt>
<a name = "GetFlybyPosition"></a> <a name = "GetFlybyPosition"></a>
<strong>GetFlybyPosition(seqID, progress)</strong> <strong>GetFlybyPosition(seqID, progress[, loop])</strong>
</dt> </dt>
<dd> <dd>
Get a flyby sequence's position at a specified progress point in percent. Get a flyby sequence's position at a specified progress point in percent.
@ -516,6 +516,11 @@
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Progress point in percent. Clamped to [0, 100]. Progress point in percent. Clamped to [0, 100].
</li> </li>
<li><span class="parameter">loop</span>
<span class="types"><span class="type">bool</span></span>
Smooth the position near start and end points, as if the sequence is looped.
(<em>optional</em>)
</li>
</ul> </ul>
<h3>Returns:</h3> <h3>Returns:</h3>
@ -531,7 +536,7 @@
</dd> </dd>
<dt> <dt>
<a name = "GetFlybyRotation"></a> <a name = "GetFlybyRotation"></a>
<strong>GetFlybyRotation(seqID, progress)</strong> <strong>GetFlybyRotation(seqID, progress[, loop])</strong>
</dt> </dt>
<dd> <dd>
Get a flyby sequence's rotation at a specified progress point in percent. Get a flyby sequence's rotation at a specified progress point in percent.
@ -548,6 +553,11 @@
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
Progress point in percent. Clamped to [0, 100]. Progress point in percent. Clamped to [0, 100].
</li> </li>
<li><span class="parameter">loop</span>
<span class="types"><span class="type">bool</span></span>
Smooth the position near start and end points, as if the sequence is looped.
(<em>optional</em>)
</li>
</ul> </ul>
<h3>Returns:</h3> <h3>Returns:</h3>

View file

@ -839,7 +839,7 @@ int Spline(int x, int* knots, int nk)
return ((__int64)x * (((__int64)x * (((__int64)x * c1 >> 16) + c2) >> 16) + (k[2] >> 1) + ((-k[0] - 1) >> 1)) >> 16) + k[1]; return ((__int64)x * (((__int64)x * (((__int64)x * c1 >> 16) + c2) >> 16) + (k[2] >> 1) + ((-k[0] - 1) >> 1)) >> 16) + k[1];
} }
Pose GetCameraTransform(int sequence, float alpha) Pose GetCameraTransform(int sequence, float alpha, bool loop)
{ {
alpha = std::clamp(alpha, 0.0f, 1.0f); alpha = std::clamp(alpha, 0.0f, 1.0f);
@ -873,15 +873,43 @@ Pose GetCameraTransform(int sequence, float alpha)
} }
// Compute spline interpolation of main flyby camera parameters. // Compute spline interpolation of main flyby camera parameters.
auto origin = Vector3(Spline(splineAlpha, xOrigins.data(), splinePoints), auto getInterpolatedPoint = [&](float t, std::vector<int>& x, std::vector<int>& y, std::vector<int>& z)
Spline(splineAlpha, yOrigins.data(), splinePoints), {
Spline(splineAlpha, zOrigins.data(), splinePoints)); int tAlpha = int(t * (float)USHRT_MAX);
return Vector3(Spline(tAlpha, x.data(), splinePoints),
Spline(tAlpha, y.data(), splinePoints),
Spline(tAlpha, z.data(), splinePoints));
};
auto target = Vector3(Spline(splineAlpha, xTargets.data(), splinePoints), auto getInterpolatedRoll = [&](float t)
Spline(splineAlpha, yTargets.data(), splinePoints), {
Spline(splineAlpha, zTargets.data(), splinePoints)); int tAlpha = int(t * (float)USHRT_MAX);
return Spline(tAlpha, rolls.data(), splinePoints);
};
short orientZ = Spline(splineAlpha, rolls.data(), splinePoints); Vector3 origin = {};
Vector3 target = {};
short orientZ = 0;
constexpr float BLEND_RANGE = 0.1f;
constexpr float BLEND_START = BLEND_RANGE;
constexpr float BLEND_END = 1.0f - BLEND_RANGE;
// If loop is enabled and we are at the start or end of the sequence, blend between the last and first cameras.
if (loop && (alpha < BLEND_START || alpha >= BLEND_END))
{
float blendFactor = (alpha < BLEND_START) ? 0.5f + (alpha / BLEND_RANGE) * 0.5f : (alpha - BLEND_END) / BLEND_START * 0.5f;
origin = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xOrigins, yOrigins, zOrigins), getInterpolatedPoint(BLEND_START, xOrigins, yOrigins, zOrigins), blendFactor);
target = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xTargets, yTargets, zTargets), getInterpolatedPoint(BLEND_START, xTargets, yTargets, zTargets), blendFactor);
orientZ = Lerp(getInterpolatedRoll(BLEND_END), getInterpolatedRoll(BLEND_START), blendFactor);
}
else
{
origin = getInterpolatedPoint(alpha, xOrigins, yOrigins, zOrigins);
target = getInterpolatedPoint(alpha, xTargets, yTargets, zTargets);
orientZ = getInterpolatedRoll(alpha);
}
auto pose = Pose(origin, EulerAngles(target - origin)); auto pose = Pose(origin, EulerAngles(target - origin));
pose.Orientation.z = orientZ; pose.Orientation.z = orientZ;

View file

@ -64,4 +64,4 @@ void InitializeSpotCam(short sequence);
void CalculateSpotCameras(); void CalculateSpotCameras();
int Spline(int x, int* knots, int nk); int Spline(int x, int* knots, int nk);
Pose GetCameraTransform(int sequence, float alpha); Pose GetCameraTransform(int sequence, float alpha, bool loop);

View file

@ -111,18 +111,18 @@ namespace TEN::Scripting::View
InitializeSpotCam(seqID); InitializeSpotCam(seqID);
} }
static Vec3 GetFlybyPosition(int seqID, float progress) static Vec3 GetFlybyPosition(int seqID, float progress, TypeOrNil<bool> loop)
{ {
constexpr auto PROGRESS_MAX = 100.0f; constexpr auto PROGRESS_MAX = 100.0f;
return Vec3(GetCameraTransform(seqID, progress / PROGRESS_MAX).Position); return Vec3(GetCameraTransform(seqID, progress / PROGRESS_MAX, ValueOr<bool>(loop, false)).Position);
} }
static Rotation GetFlybyRotation(int seqID, float progress) static Rotation GetFlybyRotation(int seqID, float progress, TypeOrNil<bool> loop)
{ {
constexpr auto PROGRESS_MAX = 100.0f; constexpr auto PROGRESS_MAX = 100.0f;
return Rotation(GetCameraTransform(seqID, progress / PROGRESS_MAX).Orientation); return Rotation(GetCameraTransform(seqID, progress / PROGRESS_MAX, ValueOr<bool>(loop, false)).Orientation);
} }
static void FlashScreen(TypeOrNil<ScriptColor> col, TypeOrNil<float> speed) static void FlashScreen(TypeOrNil<ScriptColor> col, TypeOrNil<float> speed)
@ -244,6 +244,7 @@ namespace TEN::Scripting::View
// @function GetFlybyPosition // @function GetFlybyPosition
// @tparam int seqID Flyby sequence ID. // @tparam int seqID Flyby sequence ID.
// @tparam float progress Progress point in percent. Clamped to [0, 100]. // @tparam float progress Progress point in percent. Clamped to [0, 100].
// @tparam[opt] bool loop Smooth the position near start and end points, as if the sequence is looped.
// @treturn Vec3 Position at the given progress point. // @treturn Vec3 Position at the given progress point.
tableView.set_function(ScriptReserved_GetFlybyPosition, &GetFlybyPosition); tableView.set_function(ScriptReserved_GetFlybyPosition, &GetFlybyPosition);
@ -251,6 +252,7 @@ namespace TEN::Scripting::View
// @function GetFlybyRotation // @function GetFlybyRotation
// @tparam int seqID Flyby sequence ID. // @tparam int seqID Flyby sequence ID.
// @tparam float progress Progress point in percent. Clamped to [0, 100]. // @tparam float progress Progress point in percent. Clamped to [0, 100].
// @tparam[opt] bool loop Smooth the position near start and end points, as if the sequence is looped.
// @treturn Rotation Rotation at the given progress point. // @treturn Rotation Rotation at the given progress point.
tableView.set_function(ScriptReserved_GetFlybyRotation, &GetFlybyRotation); tableView.set_function(ScriptReserved_GetFlybyRotation, &GetFlybyRotation);