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

    Re-performing Hair Edit > Convert from Spline Command?

    Cinema 4D SDK
    r21 python
    2
    5
    652
    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.
    • B
      bentraje
      last edited by

      Hi,

      In learning the Hair API, I'm trying to re-perform the Hair Edit > Convert from Spline Command.
      Basically, you select a spline and it gets converted to a hair object.

      My main bottleneck is the SetGuide which I believe creates guides in hair object.
      HairObject.SetGuides(guides, clone)

      The problem is the c4d.modules.hair.HairGuides doesn't have an initialize command which I need to

      1. Define the points
      2. Define the position of the guide

      Is there a way around this?

      Regards,
      Ben

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by Manuel

        hi,

        the set guides just define the guide, but you have to create them before.

        I've create this more generic example. From this, you should be able to create the guide from the spline.

        import c4d
        from c4d import gui
        # Welcome to the world of Python
        
        # Main function
        def main():
            # Creates the guides
            guideCnt = 10
            segmentPerGuide = 4
            pointsPerGuide = segmentPerGuide +1
            
            guides = c4d.modules.hair.HairGuides(guideCnt, segmentPerGuide)
            if guides is None:
                raise ValueError("coudln't create the guides")
        
            x = 0
            xspace = 10
            yspace = 10
            # set the points position of the guides.
            for guideIndex in range(guideCnt):
                # space each guide
                x += xspace
                for spid in range(pointsPerGuide):
                    # Calculate the vertical position of each point
                    pPos = c4d.Vector (x, yspace * spid, 0 )
                    # get the index of that point in the global guide array
                    pIndex = guideIndex * pointsPerGuide  + spid
                    # Sets the point
                    guides.SetPoint( pIndex, pPos )
            
            
            # Creates the Hair Object 
            hairObj = c4d.BaseObject(c4d.Ohair)
            
            # Sets the previously created guide to this hair object.
            hairObj.SetGuides(guides, False)
            
            # Inserts the hairObject in the document
            doc.InsertObject(hairObj, None, None)
            
            # Inserts an update event in the stack
            c4d.EventAdd()
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        after looking the result you need a bit more information about the command.

        the convert spline to hair is using the function UniformToNatural to convert bezier curves.
        It also take into account any hair tag that could change the render look of the spline.

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • B
          bentraje
          last edited by

          @m_magalhaes

          Thanks for the response. I was able to create guides but it doesn't seem to follow the original position of the splines.
          You can see the problem here:
          https://www.dropbox.com/s/g3qw5t7ueyqnlxp/c4d283_recreate_convert_from_spline_hair.mp4?dl=0

          Some general notes

          1. Spline's position is at world zero, so there's no reason for offset.
          2. There seems to be a stray point (i.e. it doesn't follow the original spline's vector position)

          Here is the sample file:
          https://www.dropbox.com/s/uovawaui1gdz7rs/c4d283_recreate_convert_from_spline_hair.c4d?dl=0

          Here is the code so far:

          import c4d
          from c4d import gui
          
          # Main function
          def main():
              spline = doc.SearchObject("spline")
              guide_count = spline.GetSegmentCount()
          
              segment_per_guide = 9
              points_per_guide = segment_per_guide
              spline_points = spline.GetAllPoints()
              
              guides = c4d.modules.hair.HairGuides(guide_count, segment_per_guide) 
              
              for guide_index in range(guide_count):
                  idx = 0
                  for spid in range (points_per_guide):
                      point_index = guide_index * points_per_guide  + spid
                      
                      if idx <= len(spline_points) - 1:
                          guides.SetPoint(point_index, spline_points[point_index])
                          idx += 1
                      else:
                          guides.SetPoint(point_index[-1], spline_points[-1]) # This was made to address the stray point but it is still a stray point. lol 
          
              hair = c4d.BaseObject(c4d.Ohair)
              hair.SetGuides(guides, False)
          
              doc.InsertObject(hair, None, None)
          
              c4d.EventAdd()
          
                     
              
          # Execute main()
          if __name__=='__main__':
              main()
          
          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by

            hi,

            hair guide are exactly as spline, they have points, segment.
            My example was more generic of course and that's why there was an offset on it.
            (we try sometimes to create more generic example so we can add them on github later)

            look at the following example, it does what you are looking for.

            import c4d
            from c4d import gui
            # Welcome to the world of Python
            
            # Main function
            def main():
                spline = op
                if spline is None:
                    raise ValueError("there's no object selected")
                if not spline.IsInstanceOf(c4d.Ospline):
                    raise ValueError("select a spline")
                # we can use a SplineLengthData to use the UniformToNatural function
                sld = c4d.utils.SplineLengthData()
                # Retrieves the spline matrix
                splineMg = spline.GetMg()
                
                segCount = spline.GetSegmentCount()
                # number of point in a segment is number of segment +1
                segmentPerGuide = 4
                pointsPerGuide = segmentPerGuide + 1
                # Creates the guides
                guides = c4d.modules.hair.HairGuides(segCount, segmentPerGuide)
                
                # for each segment of the spline
                for segIndex in range(segCount):
                    # initialize the splineLenghtData with the current segment
                    sld.Init(spline, segIndex)
                    for i in range(pointsPerGuide):
                        # for each point of the guide, calculate the position for that point
                        pos = spline.GetSplinePoint(sld.UniformToNatural(i / float(segmentPerGuide) ), segIndex)
                        # Calculates the points index on the guides points
                        pointIndex = segIndex * (pointsPerGuide ) + i
                        # Sets the point position in global space
                        pos = splineMg * pos
                        guides.SetPoint( pointIndex, pos )
                        
                # Creates the Hair Object 
                hairObj = c4d.BaseObject(c4d.Ohair)
                
                # Sets the previously created guide to this hair object.
                hairObj.SetGuides(guides, False)
                
                # Inserts the hairObject in the document
                doc.InsertObject(hairObj, None, None)
                
                # Inserts an update event in the stack
                c4d.EventAdd()
            
            
            # Execute main()
            if __name__=='__main__':
                main()
            

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 1
            • B
              bentraje
              last edited by

              @m_magalhaes

              Thanks! It works as expected.
              So that's what you mean by UniformToNatural. Basically, even if the segment guides are not the same as spline points, it will conform to its overall shape.

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