-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CsCamera initial #531
CsCamera initial #531
Conversation
game/world/triggers/cscamera.h
Outdated
auto position(CamSpline& cs) -> Tempest::Vec3; | ||
auto spin(const Tempest::Vec3& d) -> Tempest::PointF; | ||
|
||
static inline uint8_t activeEvents; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
activeEvents
can be placed in WorldObjects
Also does it make sense to allow more than one CsCamera
at a time? Any idea on how vanilla react to it?
Also, no need to make it inline
- regular static variable is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also does it make sense to allow more than one CsCamera at a time?
There is a bug that makes two occur at the same time
Trigger: EVT_LEFT_UP_CAMERA_01
Trigger: EVT_LEFT_DOWN_CAMERA_01
Untrigger: EVT_LEFT_UP_CAMERA_01
Untrigger: EVT_LEFT_DOWN_CAMERA_01
In vanilla the up event is triggered first, the down event if the levers are used a second time at Irdorath switch riddle location. The variable is only used to guard against it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this suppose to be like "fist-in" scheme, than having a pointer to active CsCamera can be more convinient:
CsCamera* WorldObjects::currentCs = nullptr;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also does it make sense to allow more than one CsCamera at a time? Any idea on how vanilla react to it?
I tested a bit and during timedemo portal opening sequence can be triggered. Timedemo is not continued after finish. This would suggest a new cscamera disables the previous.
If this suppose to be like "fist-in" scheme,
Up
event is always first and zSpy
shows only one OnTrigger()
event in vanilla. There must be something else before that decides which event to take.
a pointer to active CsCamera can be more convinient:
Makes sense with the above observation. Should this be accessed by getter and setter methods through World
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be accessed by getter and setter methods through World ?
Yep, that is a good option; also in general - no need to ask such minor details ;)
game/world/triggers/cscamera.cpp
Outdated
|
||
const float step = 0.005f; | ||
uB = t + step; | ||
while(d>s->arcLength(t,uB)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I've missed something in PR description, but why this part is so complicated?
For spline, code samples here:
https://www.geometrictools.com/Documentation/KBSplines.pdf
and here:
https://github.com/astrowander/tcbspline-gui/blob/ab191b1a785dadfaa8c3577fb4660c6dbff87f88/tsbspline.cpp#L85
are way more simple; also there should not be an issue converting time
to position on spline (TSBSpline::interpolate
should fit?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, @thokkat and thanks for PR! Would be really nice to finally have |
I would refactor it out then. A library would need adaption anyway to accommodate the speed movement types and without integration it's relatively simple. Where should the class file be placed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where should the class file be placed?
Can be utils/
; private class CsCamera::KbSpline is also fine
game/world/triggers/cscamera.h
Outdated
auto position(CamSpline& cs) -> Tempest::Vec3; | ||
auto spin(const Tempest::Vec3& d) -> Tempest::PointF; | ||
|
||
static inline uint8_t activeEvents; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this suppose to be like "fist-in" scheme, than having a pointer to active CsCamera can be more convinient:
CsCamera* WorldObjects::currentCs = nullptr;
Addressed code review and removed movement base on arc length. Determination of next camera position is now only based on time as input which itself is rescaled based on keyframe motion types. I removed the tension/continuity/bias parameters because implementation was not correct. Non default values aren't in use, so I opted for removal instead of fixing. Like the movement types this can be revisited in case it's needed. |
Merged, thanks! One idea, that I still have on code-style is to move add |
Camera position and target point the camera is looking at move on a trajectory which is represented by a spline. According to some doc in G1 modkit they're of Kochanek-Bartels type. The movement speed along those curves is defined by the attribute
motion_type
which itself is set for every point that is used to construct the splines. Those points together with other attributes that define the camera trajectory are called Keyframes.Based on the
motion_type
of all points a speed curve is constructed. I used a hermite spline which is fully defined by the speed and the distance traveled at each point (see below for a comparison between vanilla and OG). I only considered typeslow
for start and end point because other types/points aren't used in Gothic (except defaultsmooth
) and behavior in testing was partially buggy e.g.fast
behaved likestep
. Other types can be added later in case there's some scene that uses those.For the position spline every frame we start with a parameter argument
t
which reflects the current position. The speed curve delivers a distance to move which results from the next frame time. Then a binary search is used to get the new argumenttNew
which matches the right distance. The length of the spline between these two points is computed numerically. In the end position is updated and applied to camera position. Spline for the target position is handled in the same way and used to compute camera spin.I tested the produced values against a library implementation to confirm the spline is correctly implemented. But there's still some derivation to the vanilla spline.
A camera Event can be ended by time or by trigger. According to doc
duration
should be zero in those case but actually it's not. This made it necessary to use a variable to track the activity state of each event. Test case was the lever room for the gates in Irdorath at the switch riddle location. There's also a bug that lower and upper gate camera sequence are played at the same time, so a counter for total active events has been introduced.For a quick test there's marvin command
ztoggle timedemo
available for a trip around Khorinis City. If someone has a scene that doesn't work or has wrong behavior feel free to share so I can look into it.Some comparisons between OpenGothic and vanilla for timedemo behavior:
Start and endpoint have type
slow
, otherssmooth
Green curve is covered by red one.
Approximation is ok. Noticeable is the drop of the orange curve shortly before 25s. This was visible in all tests. Unclear what's happening there.
Zoomed in:
Image is from an older implementation but current shouldn't look different.
Now all points
smooth
. OpoenGothic spline would assume average speed, a horizontal line at2000
.Sometimes straight line, sometimes sine like.
Start
slow
, otherssmooth
Here it looks like it should be a straight line with increasing speed from left to right.
Now mirrored. End
slow
, otherssmooth
Looks identical to allsmooth
instead of mirrored to the previous image. I will retest this to make sure it isn't a copy paste issue.Edit: new image, looks reasonable now. Speed at start seems to be doubled average. Resembles a straight decreasing line but pretty erratic micro movements. The oscillations were clearly noticeable ingame. My chosen approach seems to be wrong though.