Re-performing Hair Edit > Convert from Spline Command?
In learning the Hair API, I'm trying to re-perform the
Hair Edit > Convert from SplineCommand.
Basically, you select a spline and it gets converted to a hair object.
My main bottleneck is the
SetGuidewhich I believe creates guides in hair object.
The problem is the
c4d.modules.hair.HairGuidesdoesn't have an initialize command which I need to
- Define the points
- Define the position of the guide
Is there a way around this?
m_magalhaes last edited by m_magalhaes
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.
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:
Some general notes
- Spline's position is at world zero, so there's no reason for offset.
- There seems to be a stray point (i.e. it doesn't follow the original spline's vector position)
Here is the sample file:
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()
m_magalhaes last edited by
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()
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.