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

    Mannually set hair root [SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    5 Posts 0 Posters 463 Views
    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 Offline
      Helper
      last edited by

      On 03/01/2017 at 11:25, xxxxxxxx wrote:

      Is there a way for setting manually guide to and polygon id? I know I can do it automaticly with root => set root but that not allow me do to a very presize work.

      Moreover is there a way for generate very precise hair (I guess saying each vertex of each hair)? For the moment the only solution I have found is to draw guide and generate hair as guide which is really not optimized for animation purpose.

      Just a preview here is in 3ds max rendered with vray, generated with ornatrix
      http://img15.hostingpics.net/pics/857158ornatrix3ds.jpg

      And here the file exported as oxh(ornatrix export format) in c4d render with arnold / default alshader and skydome using each hair as guide and then doing a root => set root. But as said it's very not suitable for animation I would really love to be able to do create a hair in polygonID xx and then set his parented root to rootID xx.
      http://img15.hostingpics.net/pics/411830ornatrixcad.jpg

      Again I'm not sticky to python. But I would prefer.
      And happy new year to every one have a nice year with a lot of plugins !

      Thanks in advance 🙂

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

        On 06/01/2017 at 14:12, xxxxxxxx wrote:

        _<_!--startfragment--_>_
        Hi gr4ph0s, thanks for writing us.
        I've investigated your question and looking between the HairGuides() and the HairObject() classes I might have found something useful for your needs. I actually suggest you to have a look at the Cinema 4D SDK Hair Generator example which might give you some hints where to look for.
        In addition find a short snippet below showing how to create hair from scratch on a generic PolygonObject at its vertices.
        At the moment the code is in C++ since on Python it seems there are some issue I still need to address.

        Best, Riccardo

            if (!doc)
                return false;
            
            Int32 hairSegs = 12;
            Int32 hairCount = 1000;
            
            // get the selected object
            BaseObject* activeObj = doc->GetActiveObject();
            if (!activeObj || !activeObj->IsInstanceOf(Opolygon))
                return true;
            
            // cast to HairObject
            HairObject* hairObj = HairObject::Alloc();
            if (!hairObj)
                return true;
            
            BaseContainer* hairBC = hairObj->GetDataInstance();
            if (hairBC)
            {
                hairBC->SetLink(HAIRSTYLE_LINK,(C4DAtomGoal* ) activeObj);
                hairBC->SetInt32(HAIRSTYLE_HAIR_COUNT, hairCount);
            }
            
            // create material
            BaseMaterial* hairMat = BaseMaterial::Alloc(Mhair);
            doc->InsertMaterial(hairMat);
            
            // create the texture tag and assign to hair object
            TextureTag* ttag = TextureTag::Alloc();
            ttag->SetMaterial(hairMat);
            hairObj->InsertTag(ttag);
            
            // get some information to build the new hair guides
            PolygonObject* activePolyObj = ToPoly(activeObj);
            const Vector* activePolyPoints = activePolyObj->GetPointR();
            const CPolygon* activePolyPolygons = activePolyObj->GetPolygonR();
            Int32 activePolyPolygonsCnt = activePolyObj->GetPolygonCount();
            Int32 activePolyPointsCnt = activePolyObj->GetPointCount();
            
            // define the hair segs and allocate the guide
            HairGuides* customHairGuide = HairGuides::Alloc(activePolyPointsCnt, hairSegs);
            if (!customHairGuide)
                return false;
            
            // retrieve the pointer to the new guides points
            Vector* customHairGuidePoints = customHairGuide->GetPoints();
            Int32 customHairGuideGuidePointsCnt = customHairGuide->GetGuidePointCount();
            Random rng; rng.Init(SAFEINT32(GeGetMilliSeconds()/1000));
            
            // create a guide at each vertex of the root object
            for (Int32 i = 0; i < activePolyPolygonsCnt; i++)
            {
                CPolygon poly = activePolyPolygons[i];
          
                Int32 vtxCnt = poly.IsTriangle() ? 3 : 4;
          
                for (Int32 k = 0; k < vtxCnt; k++)
                {
                    Vector pos = activePolyPoints[poly.GetPoint(k)];
                    HairRootData rootData;
                    rootData.m_ID = poly.GetPoint(k);
                    rootData.m_Type = HAIR_ROOT_TYPE_VERTEX;
                    rootData.m_N = CalcFaceNormal(activePolyPoints, poly);
                    rootData.m_P = pos;
                    // increase y and add some noise to x and z at each point of the hair guide
                    for (Int32 j = 0; j < customHairGuideGuidePointsCnt; j++)
                    {
                        pos.x += j*2*rng.Get11();
                        pos.y += j*3;
                        pos.z += j*2*rng.Get11();
                        customHairGuidePoints[poly.GetPoint(k) * customHairGuideGuidePointsCnt + j] = pos;
                        
                        // set the hair root
                        if (customHairGuide->GetRoot(poly.GetPoint(k)).m_Type == -1)
                            customHairGuide->SetRoot(poly.GetPoint(k), rootData, false);
                    }
                }
            }
            
            // set the new hair guide
            hairObj->SetGuides(customHairGuide, false);
            
            // update the hair object
            hairObj->Update(doc);
            
            // add the hair object to the scene
            doc->InsertObject(hairObj, nullptr, nullptr);
          
            
            EventAdd();
                
            return true;
        

        _t-->

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

          On 06/01/2017 at 15:33, xxxxxxxx wrote:

          Firstly thanks you for your exemple.

          I got few questions about it.

          1. For root placement ornatrix use thoses structures
          struct OrnaExpRootTM
          {
          	float tm[4][3];				///< 4x3 transform matrix relative to object space
          };
            
          struct OrnaExpSurfDep
          {
          	unsigned long face;			///< index into mesh face array: face this root is placed on
          	float barycentricCoordinate[3];				///< barycentric coordinates of this root on face
          };
          

          > So for simulating this I need to understand a bit more clearly HairRootData parameters.
          >
          > m_ID, is the root id?
          >
          > m_Type (in my case it will be HAIR_ROOT_TYPE_POLY)
          >
          > m_S / m_T I acutually don't know thoses utilities.
          >
          > m_P is the position. But global position? relative to the object? Relative to polygon?
          >
          > m_N is the normal.
          >
          >
          >
          >
          > 2. Maybe it was not clear in my previous post but is it possible to make something like my screenshot. http://img11.hostingpics.net/pics/661554hair.jpg
          > 1 guide (which is placed where I want regarding my first ask and xx hairs linked to the guide (so to the polygon?) which are placed / lined as I want (doing like you have done in your script but instead for doing it for the guide, doing it for each hairs).
          >
          > Regarding the SDK it seem to not be possible since I was unable to find class related to hair but about the hairObject.
          >
          >
          >
          >
          > 3. I don't really understand the function of SetGuide what this function really do
          >
          >
          >
          >
          >
          And another ask a litlle bit out of context.
          It might be stupid but for executing your code I have register a command plugin is there another way to run C++ directly on the fly? (think not since it's a compilated language but that cost nothing to ask :p)

          Anyway thanks you alot for all the informations I understand a bit more how hair are managed by c4d for now (before I always missunderstand root / guide / hair).

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

            On 10/01/2017 at 06:40, xxxxxxxx wrote:

            Hi gr4ph0s, thanks for providing your further comments.

            With reference to your question, i prefer to answer point-by-point:
            1)

            • m_ID is the id of the geometrical element the root is bind to: in case of a guide rooted on a polygon it's the polygon index of the face used to let the guide grow, in case of a guide rooted on a vertex is the vertex index
            • m_Type is the type of root you'r going to use: check the available values here
            • m_S / m_T are the s and t parametric coordinates used to locate the guide on a polygon: if you have a face you're allowed by specifying those two values where the guide is effectively located on that polygonal face; these two values are useless when guides are rooted to a vertex
            • m_P is the root position, it's normally expressed in local coordinates with respect to the object; consider that this data is not required when m_S /m_T are specified on guide rooted to a polygon (m_type == HAIR_ROOT_TYPE_POLY)
            • m_N is the root normal;
            1. yes it's indeed possible, simply define one single guide rooted on the polygon, set the number of hair to the desired number and you're done;

            2. the SetGuide() method is used to set the guides you want your hair object to use: as you can see in my example i allocate an HairObject, then i allocate an HairGuides object, then i specify the points of the guides and in the end, by using the SetGuide() method, I set my HairObject object to create hair based on my HairGuides object just created;

            3. no it's not possible. C++ is a compiled language which can't be executed as an interpreted language in a on-the-fly fashion.

            Best, Riccardo

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

              On 11/01/2017 at 02:16, xxxxxxxx wrote:

              Thanks you Riccardo for all the informations.
              If I still got some questions I will open new thread in C++ section.

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