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

    Converting morphs into CAMorphs

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

      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

      On 09/01/2012 at 06:25, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R12-R13 
      Platform:   Windows  ;   Mac OSX  ; 
      Language(s) :     C++  ;

      ---------
      While the documentation helps a bit, I am very confused about how to proceed with converting morphs from my plugin into the new Pose Morph tag (CAMorphTag, CAMorph, CAMorphNode).  Here is the skeletal code for how I think it should be working (untested, just coding it out) but am uncertain (e.g.: do you need to call UpdateMorphs() after each change or can it be called after all changes as I am showing? and so on).

          // Morph tag  
        CAPoseMorphTag*    mtag =        CAPoseMorphTag::Alloc();  
        if (!mtag)                    return ErrorException::OOMThrow(EE_DIALOG, GeLoadString(IPPERR_MEMORY_TEXT), "Morphs_Figure_R12.mtag");  
        mtag->SetName("Morphs");  
        mesh->InsertTag(mtag);  
        doc->AddUndo(UNDOTYPE_NEW, mtag);  
        // - Must be initialized prior to any use  
        mtag->InitMorphs();  
        // - Apply any edits before modifying (?)  
        mtag->ExitEdit(doc,TRUE);  
        
        // - For each bone, add its morphs and configure (CAMorphNode)  
        BaseObject*        bone =        NULL;  
        BaseContainer*    bbc =        NULL;  
        BaseTag*        tag =        NULL;  
        BaseContainer*    tbc =        NULL;  
        IPPDial*        ippd =        NULL;  
        CAMorph*        camorph =    NULL;  
        CAMorphNode*    camnode =    NULL;  
        String            prefix;  
        LONG            m, lbi =    bpidx+1L;  
        LONG            i =            0L;  
        for (m = FIRST_BPINDEX; m != lbi; ++m)  
        {  
            bone =                fbc->GetObjectLink(m, doc);  
            if (!bone)            continue;  
            bbc =                bone->GetDataInstance();  
            if (!bbc)            continue;  
            prefix =            bone->GetName()+".";  
            for (tag = bone->GetFirstTag(); tag; tag = tag->GetNext())  
            {  
                if (!tag->IsInstanceOf(ID_IPPDIALTAG))    continue;  
                ippd =                        (IPPDial* )tag->GetNodeData();  
                if (!ippd)                    continue;  
                if (!ippd->HasMorphs())        continue;  
                tbc =                        tag->GetDataInstance();  
                if (!tbc)                    continue;  
                // Add morph to the list  
                mtag->AddMorph();  
                camorph =                    mtag->GetMorph(i);  
                camnode =                    camorph->GetFirst();  
                // Expand morph data  
                camorph->SetMode(doc,mtag,CAMORPH_MODE_FLAGS_ALL|CAMORPH_MODE_FLAGS_EXPAND,CAMORPH_MODE_ABS);  
                if (!(camnode->GetInfo() & CAMORPH_DATA_FLAGS_POINTS))    continue;  
                // Access morph point data  
                // ...  
                // Compress morph data  
                camorph->SetMode(doc,mtag,CAMORPH_MODE_FLAGS_ALL|CAMORPH_MODE_FLAGS_COLLAPSE,CAMORPH_MODE_AUTO);  
                mtag->Message(MSG_UPDATE);  
                ++i;  
                break;  
            }  
        }  
        // Must be called after changes to tag  
        mtag->UpdateMorphs();  
        return TRUE;
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

        On 12/01/2012 at 05:47, xxxxxxxx wrote:

        Let me update my question a bit: Is it even possible to create morphs from scratch programmatically using the CAMorphTag, CAMorph, CAMorphNode system?  I'm hitting roadblocks, especially at CAMorphNode.GetInfo().  The tag itself has an 'Add Pose' button but CAMorphTag.AddMorph() doesn't seem to be resulting in the same thing.  Should I be using CAMorphTag.SetParameter() to trigger the creation of a new morph (Add Pose) and then use that?

        I'd appreciate some help here since there is not a single example, not a single topic here, nothing but what is in the documentation - and it is vague and doesn't specify this scenario.

        Thanks,

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

          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

          On 12/01/2012 at 06:46, xxxxxxxx wrote:

          Making a bit of headway.  It is extremely confusing and unintuitive.  Thanks.

          Is there ANY way to make folders (ITEMTREE - no information) and put the morphs into the folders?  I'd like to make a folder for each body part (polygon selection used for rigging on the polygon object).

          Thanks,

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

            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

            On 13/01/2012 at 01:44, xxxxxxxx wrote:

            Hi Robert,

            I contacted the developers.

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

              THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

              On 13/01/2012 at 07:14, xxxxxxxx wrote:

              Hi Robert,

              Here is the information I got on this:

              Much of the posted code seems correct.
              The problem is probably due to not having set what data the morph is storing and not creating the data in the morph itself.
              You can use the API to create morphs, this is used in VAMP for example.

              ExitEdit() is not needed as this is a new tag, calling this method is only required if making changes to an existing tag that could be in the middle of editing.

              You also need to enable what data the morph will hold, e.g. in the tags container ID_CA_POSE_POINTS needs to be TRUE for point data to be stored.

              After calling AddMorph() the morph is empty. It needs to be filled. You can use morph.Store() as a start point.
              A morph isn't just a single object, it could contain a hierarchy so you have to deal with each node within the morph. After calling  morph.Store(), which will fill in the morph, you can start to edit/set the data.
              UpdateMorphs() should be the last call. This updates the morph tag UI (morph list) and internal tables.

              And finally, the API currently has no way to add folders to the morph list.

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

                THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                On 14/01/2012 at 05:24, xxxxxxxx wrote:

                Hi Yannick,

                Thank you and the developers!  This should get me to a reasonable point where I can test that the morphs are acting the same as my plugin.  Users will have to live with long lists of morphs for the time being. 🙂

                Take care,

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

                  THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                  On 15/01/2012 at 06:35, xxxxxxxx wrote:

                  My morph data only stores the non-zero delta values and the index to the points that are non-zero. Does the CAMorphNode need to have the PointCount of the morphed polygon object or can it be sparse (though
                  I don't see a way to index points sparsely)?  If each must have a PointCount equal to the polygon object it references then I will make sure to do this.

                  Thanks,

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

                    THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                    On 16/01/2012 at 04:13, xxxxxxxx wrote:

                    Originally posted by xxxxxxxx

                    My morph data only stores the non-zero delta values and the index to the points that are non-zero. Does the CAMorphNode need to have the PointCount of the morphed polygon object or can it be sparse (though
                    I don't see a way to index points sparsely)?  If each must have a PointCount equal to the polygon object it references then I will make sure to do this.

                    From the morph API you have no access to the sparse data format, however, all you need to do is to copy the base points, change only those you need and then when you use SetMode() to restore the data (with CAMORPH_MODE_FLAGS_COLLAPSE) flag it will sort out the data itself from the base.

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

                      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                      On 16/01/2012 at 05:47, xxxxxxxx wrote:

                      Originally posted by xxxxxxxx

                      Originally posted by xxxxxxxx

                      My morph data only stores the non-zero delta values and the index to the points that are non-zero. Does the CAMorphNode need to have the PointCount of the morphed polygon object or can it be sparse (though
                      I don't see a way to index points sparsely)?  If each must have a PointCount equal to the polygon object it references then I will make sure to do this.

                      From the morph API you have no access to the sparse data format, however, all you need to do is to copy the base points, change only those you need and then when you use SetMode() to restore the data (with CAMORPH_MODE_FLAGS_COLLAPSE) flag it will sort out the data itself from the base.

                      Excellent! 😄

                      Thanks again!!

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

                        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                        On 17/01/2012 at 23:13, xxxxxxxx wrote:

                        How do I go about setting the individual morph Strength settings?  Do the settings in Edit mode carry over to Animate mode (vice versa, does it matter)?  Currently, all CA morphs are initiated to 1.0 (100%) but I'd like to set them to the values from my morphs.

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

                          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                          On 18/01/2012 at 01:54, xxxxxxxx wrote:

                          Originally posted by xxxxxxxx

                          How do I go about setting the individual morph Strength settings?  Do the settings in Edit mode carry over to Animate mode (vice versa, does it matter)?  Currently, all CA morphs are initiated to 1.0 (100%) but I'd like to set them to the values from my morphs.

                          The strength isn't currently in the API but can be accessed through SetParameter(), each morph (CAMorph) has an ID (GetID()) that can be used to set the strength.

                          In tcaposemorph.h are the IDs, the animate data is stored using the DescID as:

                          DescID(ID_CA_POSE_ANIMATE_DATA,morph->GetID()*ID_CA_POSE_ANIMATE_CNT+ID_CA_POSE_ANIMATE_OFFSET+ID_CA_POSE_ANIMATE_STRENGTH);
                          

                          e.g.

                          CAPoseMorphTag *mtag=(CAPoseMorphTag* )doc->GetFirstObject()->GetTag(Tposemorph);
                          CAMorph *morph=mtag->GetActiveMorph();
                          DescID id=DescID(ID_CA_POSE_ANIMATE_DATA,morph->GetID()*ID_CA_POSE_ANIMATE_CNT+ID_CA_POSE_ANIMATE_OFFSET+ID_CA_POSE_ANIMATE_STRENGTH);
                          mtag->SetParameter(id,0.5,DESCFLAGS_SET_USERINTERACTION);
                          

                          DESCFLAGS_SET_USERINTERACTION is needed when you set the parameter if not in Animate mode, when in Edit only a user action is allowed to change the strength.

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

                            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                            On 18/01/2012 at 03:31, xxxxxxxx wrote:

                            Aha!  The DescID was what was not working for me.  I was using:

                            camorph = mtag->GetMorph(i);  
                            mtag->SetParameter(camorph->GetID(), value, DESCFLAGS_SET_0);  
                            ++i;
                            

                            Now it works perfectly and IPP can convert IPP morphs to CA morphs and retain the strength values! Yay!

                            Thank you very much,

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

                              On 06/09/2013 at 19:56, xxxxxxxx wrote:

                              Sorry to bring up this old post. But I can't get the code posted here to work for me.
                              I'm just trying to move the points of an object that has a posemorph tag on it. But it just won't work for me.
                              No matter what I put in this thing. The morph tag prevents the point from moving.

                                  BaseObject *obj = doc->GetFirstObject();  
                                PointObject *pobj = ToPoint(obj);            //Cast the BaseObject type to a PointObject type and assign it to a variable "pobj"  
                                Vector *points = pobj->GetPointW();  
                                
                                CAPoseMorphTag *pmTag=(CAPoseMorphTag* )obj->GetTag(Tposemorph);   //Cast the tag to a type we can access the data from  
                                  
                                pmTag->ExitEdit(doc,TRUE);                       //First exit any editing  
                                CAMorph *morph = pmTag->GetMorph(1);             //Get the morph to be changed  
                                GePrint(morph->GetName());  
                                CAMorphNode *mnode = morph->GetFirst();          //The first will be the object with the morph tag  
                                mnode->GetInfo() & CAMORPH_DATA_FLAGS_POINTS;    //Make sure the data exists  
                                
                                pmTag->SetParameter(DescID(ID_CA_POSE_POINTS), GeData(TRUE), DESCFLAGS_SET_0); //Set the points option  
                                
                                //Go into edit mode so we can alter the object's points  
                                Bool edit = pmTag->SetParameter(DescID(ID_CA_POSE_MODE), GeData(ID_CA_POSE_MODE_EDIT), DESCFLAGS_SET_0);  
                                
                                //The data must be made editable before we change it  
                                morph->SetMode(doc,pmTag,CAMORPH_MODE_FLAGS_ALL|CAMORPH_MODE_FLAGS_EXPAND,CAMORPH_MODE_ABS);  
                                
                                //Move the points around as desired  
                                points[0] = Vector(0,400,0);           //<---Not Working!!  
                                GePrint(RealToString(points[0].y));    //Point is changed in memory. But the morph tag is preventing it from moving  
                                pobj->Message(MSG_UPDATE);  
                                
                                //Once finished put the data back to its original form.  
                                morph->SetMode(doc,pmTag,CAMORPH_MODE_FLAGS_ALL|CAMORPH_MODE_FLAGS_COLLAPSE,CAMORPH_MODE_AUTO);  
                                  
                                pmTag->UpdateMorphs();                      //Updates the tag  
                                pmTag->Message(MSG_UPDATE);  
                                EventAdd();
                              

                              What am I doing wrong?

                              -ScottA

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

                                On 07/09/2013 at 11:55, xxxxxxxx wrote:

                                Never mind. I found that I was missing the Store() function.

                                Just in case anyone needs it.
                                This is an example of how to edit an object's pose data(points).

                                    BaseObject *obj = doc->GetFirstObject();  
                                  PointObject *pobj = ToPoint(obj);          //Cast the BaseObject type to a PointObject type and assign it to a variable "pobj"  
                                  Vector *points = pobj->GetPointW();  
                                  
                                  //Cast the tag from a BaseTag type to a type we can access the data from  
                                  CAPoseMorphTag *pmTag=(CAPoseMorphTag* )obj->GetTag(Tposemorph);  
                                   
                                  //Get the morph to you want to be changed    
                                  CAMorph *morph = pmTag->GetMorph(1);    //The first pose in the list of poses  
                                  
                                  //Move the object's points around as desired  
                                  points[0] = Vector(0,400,0);    
                                  pobj->Message(MSG_UPDATE);  
                                  
                                  //VERY IMPORTANT!!! Store the moved point positions  
                                  morph->Store(doc,pmTag,CAMORPH_DATA_FLAGS_POINTS);  
                                  
                                  EventAdd();
                                

                                -ScottA

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