SetTimeRight fail!
-
Hi, when the value I set is very small, such as BaseTime.get() is 0.001, by using SetTimeRight(), but when I access this value again by script, the result is BaseTime.get() is 0. but SetTimeLeft() can Successfully set, such as BaseTime.get() is -0.001 !
Thanks for any help!key.SetInterpolation(curve,c4d.CINTERPOLATION_SPLINE) key.SetTimeLeft(curve,L_time_v) key.SetValueLeft(curve,TL_vector[1]) key.SetTimeRight(curve, R_time_v) key.SetValueRight(curve, TR_vector[1]) key[c4d.ID_CKEY_PRESET] = c4d.ID_CKEY_PRESET__CUSTOM key.ChangeNBit(c4d.NBIT_CKEY_AUTO, c4d.NBITCONTROL_CLEAR) key.ChangeNBit(c4d.NBIT_CKEY_BREAK, c4d.NBITCONTROL_SET) key.ChangeNBit(c4d.NBIT_CKEY_KEEPVISUALANGLE, c4d.NBITCONTROL_SET)
-
Please use the
curve->SetTangents(index, &curveTleftX, &curveTRightX, &curveTleftY, &curveTRightY);
.
Detailed see:
https://developers.maxon.net/forum/topic/13352/ccurve-gettangents-broken
https://developers.maxon.net/forum/topic/13344/ckey-auto-tangents -
Hello @chuanzhen,
thank you for reaching out to us. There is some truncating going on when setting the time component of a key to a value which is within the sub-second range. But I cannot reproduce any differences between the left and right tangent and also not than a tangent is zero when it should not be zero. within a second.
I would declare this an acceptable limitation of the Cinema 4D; since animation definitions below the millisecond range do not seem particularly useful for most users. If you can reproduce differences for setting the left and right time value of a key, I would ask you to provide an example file and/or executable code. But even then, chances are good that we will declare this an acceptable limitation.
Cheers,
FerdinandThe output of the example code below:
doc.GetFps()=300 Key Index| Set Value| GetTimeLeft()| GetTimeRight() ---------------------------------------------------------------------------------------- 0| 0.0125| 0.013| 0.013 1| 0.012| 0.012| 0.012 2| 0.0115| 0.012| 0.012 3| 0.011| 0.011| 0.011 4| 0.0105| 0.011| 0.011 5| 0.01| 0.01| 0.01 6| 0.0095| 0.01| 0.01 7| 0.009000000000000001| 0.009| 0.009 8| 0.0085| 0.009| 0.009 9| 0.008| 0.008| 0.008 10| 0.0075| 0.008| 0.008 11| 0.007| 0.007| 0.007 12| 0.006500000000000001| 0.007| 0.007 13| 0.006| 0.006| 0.006 14| 0.0055| 0.006| 0.006 15| 0.005| 0.005| 0.005 16| 0.0045000000000000005| 0.005| 0.005 17| 0.004| 0.004| 0.004 18| 0.0035| 0.004| 0.004 19| 0.003| 0.003| 0.003 20| 0.0025| 0.003| 0.003 21| 0.002| 0.002| 0.002 22| 0.0015| 0.002| 0.002 23| 0.001| 0.001| 0.001 24| 0.0005| 0.001| 0.001
The code:
"""Provides an example for setting the time component of key-tangents to very low values. Creates a cube object with tweenty-five keys in a position-x track. Then loops over the time component of the key-tangents of these keys, sets them to increasingly smaller values and prints out the time values before and after the changes, as well as the true value of the time t. """ import c4d def main(): """Runs the example. """ # Creates a cube with a postion-x animation with 25 keys. cube = c4d.BaseList2D(c4d.Ocube) if cube is None: raise MemoryError("Could not allocate object.") descID = c4d.DescID (c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION), c4d.DescLevel(c4d.VECTOR_X)) track = c4d.CTrack(cube, descID) if track is None: raise MemoryError("Could not allocate track.") cube.InsertTrackSorted(track) curve = track.GetCurve() count = 25 for t in range(count): result = curve.AddKey(c4d.BaseTime(t)) if result is None: raise MemoryError("Could not allocate key.") result["key"].SetValue(curve, t ** 1.5) result["key"].SetInterpolation(curve, c4d.CINTERPOLATION_SPLINE) doc.InsertObject(cube) c4d.EventAdd() # Loop over the created key and print out their time-tagent values while # attempting to set them to incerasingly smaller values. print (f"{doc.GetFps()=}\n\n") print (f"{'Key Index':>10}|{'Set Value':>25}|{'GetTimeLeft()':>25}|" f"{'GetTimeRight()':>25}") line = "{:>10}|{:>25}|{:>25}|{:>25}" print ("-"*88) for i in range(curve.GetKeyCount()): ckey = curve.GetKey(i) t = (count - i) * 0.0005 ckey.SetTimeLeft(curve, c4d.BaseTime(t)) ckey.SetTimeRight(curve, c4d.BaseTime(t)) print (line.format( i, t, ckey.GetTimeLeft().Get(), ckey.GetTimeRight().Get())) c4d.EventAdd() if __name__ == '__main__': main()
-
@aimidi said in SetTimeRight fail!:
SetTangents
Thanks for your help,but not find SetTangents() in python sdk
-
Hello @chuanzhen,
SetTangent()
is a member ofCCurve
and you must use it when you want to access tangents of keys with a non-custom interpolation.CKey.Get/SetTimeLeft/Right
on the other hand always accesses the raw underlying tangent data. So, even whenkey[c4d.ID_CKEY_PRESET] != c4d.ID_CKEY_PRESET__CUSTOM
,CKey.Get/SetTimeLeft/Right
will always retrieve the then for the user invisible custom tangents.Long story short: using
CCurve.Get\SetTangent()
should not make a difference for you in this case. At least I do not see how it should. But you can of course try.Cheers,
Ferdinand -
@ferdinand Thanks for your help!
I have been looking for the source of the problem. After seeing your answer, I should have looked in the wrong direction (I always thought that SetTimeLeft() could not accurately transmit the value I calculated). Below I uploaded a GIF to show the problem I encountered more accurately.
1: I use Add key slider to dynamically add functions. It will call my autoweight function by default. It can be seen that in the process of dynamic addition, the error of RightTime == 0 of some key frames appears
2: When I dynamically use EasyInOut slider to perform the smoothing process, it also calls the autoweight function, and it still does not correct the wrong situation
3: When I use c4d's default auto tangent classic for these key frames, then use EasyInOut again to perform the smoothing process, the autoweight function will work normally.
So I don’t know why this happens, because the above code is used to set the key in the autoweight functionIt seems that can't see the gif in full,i upload a file ,can be download. easyinout2.gif
-
Hello @chuanzhen,
thank you for your detailed explanation, but I unfortunately still struggle a bit with the details. I will answer as best as I can from what I do understand.
I assume your major problem are the kinks that are introduced into your spline by incorrect tangents.
- Cinema 4D has multiple tangent modes which partially or fully take away the control from the user how the tangents between keys are set. So, when you are in another mode than
ID_CKEY_PRESET__CUSTOM
or have any of the automatisms enabled inID_CKEY_PRESET__CUSTOM
, then setting the raw tangents withCKey
won't help you, as they always set the raw tangents. As lined out before, when you want to set tangents with the automatisms enabled, you must must use the tangent methods attached toCCurve.
- When you just want to ensure the smoothness/continuity of your curve, you can also use
CCurve.SetTimeLeftAdjustValue
and its counter part for the right tangent. - Finally, when you want to construct a smooth spline from a to b with all automatisms turned of, you will have to get your hands dirty yourself. I once posted this example, but this is more complicated than your case, since this was for 3D.
- When you just want to subdivide a curve without changing its curvature, we cannot give you any detailed instructions on how the curve interpolation of ours works, but you should get pretty close with the common cubic-bezier curves.
If there are remaining questions, I would propose that you follow the recommended pattern of posting executable example code and line out what you would expect to happen and what happens instead.
Cheers,
Ferdinand - Cinema 4D has multiple tangent modes which partially or fully take away the control from the user how the tangents between keys are set. So, when you are in another mode than
-
@ferdinand Thank you for your detailed answer!
In my autoweight function, there is no error in the calculation result of the tangent, but when setting the CKey, there is a problem. It seems that there are too many parameters set, which causes the left and right time values of the key frame to be set according to the calculation results. Then an unknown change was made, causing the final value to not match the calculated value. Although I still don't know why those settings will cause the value to go wrong.wrong code:
key.SetInterpolation(curve,c4d.CINTERPOLATION_SPLINE) key.SetTimeLeft(curve,L_time_v) key.SetValueLeft(curve,TL_vector[1]) key.SetTimeRight(curve, R_time_v) key.SetValueRight(curve, TR_vector[1]) key[c4d.ID_CKEY_PRESET] = c4d.ID_CKEY_PRESET__CUSTOM key.ChangeNBit(c4d.NBIT_CKEY_AUTO, c4d.NBITCONTROL_CLEAR) key.ChangeNBit(c4d.NBIT_CKEY_BREAK, c4d.NBITCONTROL_SET) key.ChangeNBit(c4d.NBIT_CKEY_KEEPVISUALANGLE, c4d.NBITCONTROL_SET)
current code:
key.SetInterpolation(curve,c4d.CINTERPOLATION_SPLINE) key.SetTimeLeft(curve,L_time_v) key.SetValueLeft(curve,TL_vector[1]) key.SetTimeRight(curve, R_time_v) key.SetValueRight(curve, TR_vector[1]) key.ChangeNBit(c4d.NBIT_CKEY_AUTO, c4d.NBITCONTROL_CLEAR)
Using the current code, the left and right time values of CKey, the calculated result matches the final result.
this is an print example:Calculate_RTime: 0.0301874202486 After_Set_Get_from_Key_RTime 0.03
gif also shows that it is working fine now.
-
Hey @chuanzhen,
great to hear that you found your solution! Also: I have not missed that you reported problems with your GIFs. We have discussed this problem internally before (it was then me having a problem) but then moved on. I will reraise the topic and we will see what we can do. The problem is a bit weird; I cannot guarantee that we will fix it. I think it has something to do with standard conformance of file types. ScreenToGif, the tool I am using, seems to produce files that deviate from some sort of core standard. But in other cases, the same files load fine. As I said, it is a bit weird, but we will see if we can squeeze in some time for looking at it.
Cheers,
Ferdinand -
@ferdinand I also use ScreenToGif to make pictures!