Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Rotating Spline Tangents?

    SDK Help
    0
    6
    562
    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.
    • H
      Helper
      last edited by

      On 23/11/2013 at 13:17, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   13 
      Platform:   Windows  ;   
      Language(s) :     C++  ;

      ---------
      Hi,
      I'm trying to figure out how to rotate spline tangents. But I'm stuck.
      According to this old thread. I have to use the RotAxisToMatrix() function:
      https://developers.maxon.net/forum/topic/884/202_how-to-rotate-tangents&KW=rotate+spline+tangent&PID=565#565
      But it's too vague and incomplete for me to figure it out.

      I understand that I need to create a matrix for the tangent so I can rotate it.
      But after that part I'm stuck.

          BaseObject *spline = doc->SearchObject("Spline");    //Find the spline in the OM (Not a primitive!!)  
        if(!spline) return FALSE;  
        SplineObject *sp = ToSpline(spline);                 //Cast it to a spline object type so we can work on it if desired  
          
        Vector *points = sp->GetPointW();                    //Get it's array of points  
        Tangent *tangents = sp->GetTangentW();               //Get it's array of tangents  
        LONG pointCount = sp->GetPointCount();  
        
        Vector t0 = sp->GetSplineTangent(0, 0);              //The first tangent in the spline to rotate  
              
        Real angle = 25;  
        Vector axis = t0;                                    //The axis for the new matrix?  
        Matrix newmtx;  
        newmtx = RotAxisToMatrix(axis, angle);               //Create a matrix based on t0  
        
        //What do I do next?  
        tangents[0].vl ^= ?  
        tangents[0].vr ^= ?
      

      -ScottA

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 23/11/2013 at 18:51, xxxxxxxx wrote:

        What do you mean by "Rotating Spline tangents" ? Rotating around the tangents axis 
        vector doesn't make much sense, so i guess you do want to rotate around that vectors 
        normal or binormal. I have never used RotAxisToMatrix(), so i cannot say much about 
        that method (I think it does the same for what I am about to describe for the z-axis of the
        matrix constructedwith the passed axis vector (which will be the z-axis in this system)). 
        I would construct a matrix for that vertex manually and then just put my desired rotation 
        on top of it (you could also use the spline helper class for the vertex matrix). In pseudo 
        code, to lazy for proper code :

        # construct vertex matrix tng = tangent.right - tagent.left nrm = tng % someUpVector brnm = tng % nrm vermg = Matrix(vertexpos, nrm, bnrm, tng) # our rot matrix rotmg = HBPtoMatrix(Vector(pi,0,0)) # put everything together, i think you might have to invert your vertex matrix for one of the # tangents, but i can't wrap my head around it, without trying it for myself. tangent.left = (vermg * rotmg).MulV(tangent.left) tangent.right = (vermg * rotmg).MulV(tangent.right)
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 23/11/2013 at 20:13, xxxxxxxx wrote:

          By rotating tangents I mean like when you select a point in a spline then rotate it with the rotate tool. The tangents will rotate around the spline point. And the R&L tangents maintain their lengths while this happens.
          I'm guessing that a matrix is being create using the R&L tangent handles. And the spline point is acting as the matrix center?

          I did attempt to use the SplineHelp class's GetMatrix() function. But the problem I ran into was after I changed the point's matrix. There's nothing in the docs that tells me how to "Set" that changed matrix back to the point to update it.
          tangent(0)->SetMg(pmtx) didn't work.

          The Rotate tool is doing exactly what I want to do with code.
          Mikael Sterner seemed to know how to do it. But he's long gone.

          -ScottA

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 24/11/2013 at 00:26, xxxxxxxx wrote:

            Hi,

            1. Rotating in "spline space" isn't as easy as you might think, at least when you want 
            to rotate multiple tangents accordingly. The reason is that the splines normals aren't 
            mathematically defined that way humans would consider them as normal normals (pun
             intended 😉 ). The result are flipping normals if you calculate the vertex frames (frame 
            means matrix) vertex by vertex. There are several ways around that problem. The 
            easiest is called Parallel Transport Frame. The idea is simply that you don't calculate 
            each vertex frame with an arbitrary up vector but with the normal of the previous vertex. 
            For a real algorithm you will have also correct the frame torsion and recalculate the first 
            frame with the last frame if you have a closed spline.
            However also this algorithm has its problems (especially with fast turns, depending on how 
            sophisticated you build your torsion correction). There is a better (and more complicated)
            algorithm called Rotation Minimizing Frames that does give better results.

            2. Sadly maxon does not expose its spline normal calculation algorithms ('banking'). The
            vertex frames returned by the SplineHelper class are the raw frames (at least they were
            the last time I did check in R14 something).

            3. Some basic code showing rotation in global and spline space with the raw frames.

            http://codepad.org/K7GRidGo

            edit : toggle globrot = True
            edit2: i now just see that i have accidentally taken the x-axis for spline space instead of the 
            z-axis in the final tangent calculation.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 24/11/2013 at 08:03, xxxxxxxx wrote:

              Thanks for the code LD.

              I'm not using SetTangents() in my code. I'm changing the point's matrix. Then trying to apply the changes to the tangents (vr & vl) directly.
              I'll play around with that approach and see if it gets me closer.

              -ScottA

              Edit-  Apparently SetTangents() is a Python only function.
              In C++ There's no such function in the SplineObject class. And it looks like we have move the vr & vl directly. The way I was doing it.
              I hate it when people post incomplete C++ code solutions. It's really frustrating.

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 25/11/2013 at 11:46, xxxxxxxx wrote:

                I gave up on that old thread.
                And I came up with my own solution to the problem.

                C++ version

                //This code uses a temporary null object to rotate a spline point's tangent handles  
                //I used a temporary object here because it's simpler to rotate objects than a matrix  
                //The C4D rotate tool seems to be doing a similar thing (creating a temp. matrix while rotating a spline point)  
                  
                  
                  BaseObject *spline = doc->SearchObject("Spline"); //Find the spline in the OM (Not a primitive!!)  
                  if(!spline) return FALSE;  
                  SplineObject *sp = ToSpline(spline);              //Cast it to a spline object type so we can work on it if desired  
                     
                  Vector *points = sp->GetPointW();                 //Get it's array of points  
                  Tangent *tangents = sp->GetTangentW();            //Get it's array of tangents  
                  LONG pointCount = sp->GetPointCount();  
                  
                  AutoAlloc<SplineHelp> sh;  
                  if(!sh) return FALSE;  
                  sh->InitSpline(spline);  
                  if(!sh->Exists()) return FALSE;  
                  
                  Vector t0 = sp->GetSplineTangent(0, 0);          //The first tangent in the spline to rotate  
                            
                  //Get the matrix of the first spline point  
                  Matrix mtx = sh->GetMatrix(0);  
                  
                  //Create a Null object in memory  
                  //There's no need to pyhsically add the object to the scene  
                  //Because we will only be using it's matrix then deleting it  
                  BaseObject *null = BaseObject::Alloc(Onull);  
                  
                  //Set the null's position and rotation matrix values to the same as the spline's point  
                  null->SetMg(mtx);  
                  
                  //Rotate the null as desired  
                  null->SetRelRot(Vector(0,0,0));  //<---Change this to rotate the tangents via the null  
                  
                  //Get the nulls new matrix values  
                  Matrix nmtx = null->GetMg();  
                           
                  //Apply the null's matrix values to the spline point's tangent handles to rotate them  
                  tangents[0].vl = -(nmtx).MulV(Vector(tangents[0].vl.GetLength(),0,0));  
                  tangents[0].vr =  (nmtx).MulV(Vector(tangents[0].vr.GetLength(),0,0));  
                  
                  sp->Message(MSG_POINTS_CHANGED);  
                  sp->Message(MSG_UPDATE);  
                  null->Remove();  
                  BaseObject::Free(null);    //Delete the memory used to allocate the null object  
                  EventAdd();
                

                Python version

                #This script uses a temporary null object to rotate a spline point's tangent handles  
                #I used a temporary object here because it's simpler to rotate objects than a matrix  
                #The C4D rotate tool seems to be doing a similar thing (creating a temp. matrix while rotating a spline point)  
                  
                import c4d  
                from c4d import utils  
                from c4d.utils import SplineHelp  
                def main() :  
                    
                  obj = doc.SearchObject("Spline")   #The spline to work on  
                  if not obj: return False  
                  
                  sh = SplineHelp()  
                  sh.InitSpline(obj, use_deformed_points=True)  
                  
                  #Get the first spline tangent  
                  tan0 = obj.GetTangent(0)  
                  
                  #Get the matrix of the first spline point  
                  mtx = sh.GetMatrix(0)  
                  
                  #Create a Null object in memory  
                  #There's no need to pyhsically add the object to the scene  
                  #Because we will only be using it's matrix then deleting it  
                  null = c4d.BaseObject(c4d.Onull)  
                  
                  #Set the null's position and rotation matrix values to the same as the spline's point  
                  null.SetMg(mtx)  
                  
                  #Rotate the null as desired  
                  null.SetRelRot(c4d.Vector(0,0,0))  #<---Change this to rotate the tangents via the null  
                  
                  #Get the nulls new matrix values  
                  nmtx = null.GetMg()          
                           
                  #Apply the null's matrix values to the spline point's tangent handles to rotate them  
                  obj.SetTangent(0, -(nmtx).MulV(c4d.Vector(tan0["vl"].GetLength(),0,0)),  
                                     (nmtx).MulV(c4d.Vector(tan0["vr"].GetLength(),0,0)))          
                    
                  obj.Message(c4d.MSG_POINTS_CHANGED)  
                  obj.Message(c4d.MSG_UPDATE)  
                  sh.FreeSpline()  
                  null.Remove()  
                  c4d.EventAdd()  
                    
                if __name__=='__main__':  
                  main()
                

                -ScottA

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