Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    CKey Auto Tangents

    Cinema 4D SDK
    c++ r23 s24
    3
    7
    1.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      AiMiDi
      last edited by m_adam

      When I try to use GetTimeRight() or GetValueRight() to get a key frame with Preset set to CKEYPRESET::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

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @AiMiDi
        last edited by ferdinand

        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 for ge_prepass.h.

        Aside from that, I cannot reproduce the reported behavior of the preset NEWAUTO, or its S24 equivalent AUTO_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,
        Ferdinand

        The 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:
        353598ec-c5ea-4324-bf6c-d9edac376c3f-image.png
        S24:
        8509742f-a466-40cc-844a-53e878b62116-image.png

        MAXON SDK Specialist
        developers.maxon.net

        A 1 Reply Last reply Reply Quote 0
        • A
          AiMiDi @ferdinand
          last edited by

          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.353598ec-c5ea-4324-bf6c-d9edac376c3f-image.png
          For the key frame I circled in this picture, its tangent should be horizontal(Used Remove Overshooting), so its GetTimeRight() or GetValueRight() value should be 0 instead of the number obtained in the picture, can you understand what I said.

          Thinks,
          AiMiDi

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by ferdinand

            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

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand @AiMiDi
              last edited by ferdinand

              Hello @aimidi,

              so, I did revisit your problem and CKey::GetValueLeft/Right and CKey::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 preset CUSTOM. 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 and CKey::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 of CKey::GetValueLeft/Right and CKey::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,
              Ferdinand

              The output:
              c565fc4d-8c1b-488d-8288-e8a508af90a5-image.png

              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;
              }
              
              

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • A
                AiMiDi
                last edited by

                Hi @ferdinand,
                Thank you very much for your reply. Your reply solved my problem very well, thank you.

                thanks again,
                AiMiDi

                1 Reply Last reply Reply Quote 0
                • M
                  m_adam
                  last edited by m_adam

                  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.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post