CKey Auto Tangents
-
When I try to use
GetTimeRight()
orGetValueRight()
to get a key frame with Preset set toCKEYPRESET::NEWAUTO
, the returned value is not the correct value (0 or some large value). How can I get the tangent of the curve, or Tell me how to calculate them by myself.Thinks,
AiMiDi -
Hello @AiMiDi,
thank you for reaching out to us. Please remember to add tags to your postings, so that we can answer them better.
With S24, there is no
CKEYPRESET::NEWAUTO
anymore, its has been depreciated. See the S24 change list forge_prepass.h
.Aside from that, I cannot reproduce the reported behavior of the preset
NEWAUTO
, or its S24 equivalentAUTO_OVERSHOOT
, not working in conjunction with retrieving the right tangent. See script attached at the end. The only thing we could think of, is that you might have created that key yourself and it has not been updated yet.To get any further help, I would have to ask you to provide more details and/or post code.
Cheers,
FerdinandThe code to test with:
import c4d if c4d.GetC4DVersion() >= 24000: CKEY_PRESET_SYMBOLS = { 1: "AUTO_CLAMP", 2: "AUTO_OVERSHOOT", 3: "FIXED_OVERSHOOTWEIGHTED", 4: "CUSTOM", 5: "AUTO_OVERSHOOTWEIGHTED", } else: CKEY_PRESET_SYMBOLS = { 1: "CLASSICAUTO", 2: "NEWAUTO", 3: "NEWAUTOWEIGHTED", 4: "CUSTOM", } CKEY_DATA_MESSAGE = "id: {}, mode: {}, left: {}, right: {}" def main(): """ """ def getKeyData(index, curve): """ """ key = curve.GetKey(index) preset = key[c4d.ID_CKEY_PRESET] mode = CKEY_PRESET_SYMBOLS[preset] left = (key.GetTimeLeft().Get(), key.GetValueLeft()) right = (key.GetTimeRight().Get(), key.GetValueRight()) return CKEY_DATA_MESSAGE.format(index, mode, left, right) if not op: return firstTrack = op.GetFirstCTrack() if not firstTrack: return curve = firstTrack.GetCurve() if curve is None: return for index in range(curve.GetKeyCount()): data = getKeyData(index, curve) print(data) if __name__ == '__main__': main()
The curve shown uses keys for all interpolation presets.
R23:
S24:
-
Hi @ferdinand,
thank you so much for replying to me.I read the code you provided, and I think I didn't express it clearly.
For the key frame I circled in this picture, its tangent should be horizontal(Used Remove Overshooting), so itsGetTimeRight()
orGetValueRight()
value should be0
instead of the number obtained in the picture, can you understand what I said.Thinks,
AiMiDi -
Hi @AiMiDi,
ah, I now do understand, you are right, these outputs look indeed to be wrong, I totally overlooked that. I will have to take a closer look if this is a bug, or you and I simply misunderstand the purpose of these methods. As I would also expect them to effectively provide a tangent vector relative to the key vertex.
Cheers,
Ferdinand -
Hello @aimidi,
so, I did revisit your problem and
CKey::GetValueLeft/Right
andCKey::GetTimeLeft/Right
do indeed not work with key presets. They will always return the non-adjusted values for the key, i.e., what equates to the presetCUSTOM
. It is a bit a matter of opinion if this could be considered a bug or not, since there are some indicators in our code that this has been implemented intentionally in this way for performance reasons.If you want to retrieve the true tangents for a key, i.e., the tangents which take the presets into account, you must use
CCurve::GetTangents
where the documentation already states that they do this.Currently there is no warning in the docs that
CKey::GetValueLeft/Right
andCKey::GetTimeLeft/Right
will behave in this way. I will reach out to the developers if we want to change this behavior. If we do not, we will update the documentation ofCKey::GetValueLeft/Right
andCKey::GetTimeLeft/Right
in an upcoming release to reflect that this will always return the underlying custom tangents (which are sort of invisibly always there).Below you will find a code example in C++ and the matching output which should be what you are after.
Sorry for the longwinded thread and cheers,
FerdinandThe output:
The code:
// For https://developers.maxon.net/forum/topic/13344 #include "c4d.h" #include "c4d_symbols.h" static maxon::Result<void> pc13344(BaseDocument* doc) { iferr_scope; BaseObject* op = doc->GetFirstObject(); if (op == nullptr) { ApplicationOutput("Please insert at least one object into the scene."); return maxon::OK; } CTrack* track = op->GetFirstCTrack(); if (track == nullptr) { ApplicationOutput("The first object in the scene has no animation track."); return maxon::OK; } CCurve* curve = track->GetCurve(); if (curve == nullptr) { ApplicationOutput("The first object's animation track has no curve/keys."); return maxon::OK; } for (int index = 0; index < curve->GetKeyCount(); index++) { CKey* key = curve->GetKey(index); CKEYPRESET preset = key->GetKeyPreset(); maxon::Float keyTleftX = key->GetTimeLeft().Get(), keyTleftY = key->GetValueLeft(), keyTRightX = key->GetTimeRight().Get(), keyTRightY = key->GetValueRight(); maxon::Float64 curveTleftX = 0., curveTleftY = 0., curveTRightX = 0., curveTRightY = 0.; curve->GetTangents(index, &curveTleftX, &curveTRightX, &curveTleftY, &curveTRightY); ApplicationOutput("index: @, mode: @, keyLeftTangent: (@, @), keyRightTangent: (@, @), curveLeftTangent: (@, @), curveRightTangent: (@, @)", index, preset, keyTleftX, keyTleftY, keyTRightX, keyTRightY, curveTleftX, curveTleftY, curveTRightX, curveTRightY); } return maxon::OK; }
-
Hi @ferdinand,
Thank you very much for your reply. Your reply solved my problem very well, thank you.thanks again,
AiMiDi -
Hi @AiMiDi with the latest update of Cinema 4D (R24 SP1), CKey::GetValueLeft/Right and CKey::GetTimeLeft/Right documentation have been improved to mention what was described by @ferdinand.
Cheers,
Maxime.