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

    How to run UVCOMMAND_OPTIMALCUBICMAPPING

    Cinema 4D SDK
    2
    4
    673
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic was forked from Running Automatic UV for all objects ferdinand
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      ADCMHI
      last edited by ADCMHI

      @m_adam
      Hi!
      I'm trying to apply UVW mapping to child objects of an FBX file imported into Cinema 4D using this script.
      While I can assign UVW coordinates, the automatic cubic UV unwrapping isn't working. Can you advise on what modifications are needed to achieve this?

      import c4d
      from c4d import utils
      
      def apply_optimal_cubic_uv(obj, doc):
          if obj.GetType() == c4d.Opolygon:
              # UVWタグがなければ作成
              if not obj.GetTag(c4d.Tuvw):
                  uvw_tag = c4d.UVWTag(obj.GetPolygonCount())
                  obj.InsertTag(uvw_tag)
      
              # オブジェクトを選択
              doc.SetActiveObject(obj, c4d.SELECTION_NEW)
      
              # 最適化されたキュービックUVマッピングを適用
              settings = c4d.BaseContainer()
              settings[c4d.OPTIMALMAPPING_PRESERVEORIENTATION] = True  # 向きを保持
              settings[c4d.OPTIMALMAPPING_STRETCHTOFIT] = False  # ストレッチフィット
              settings[c4d.OPTIMALMAPPING_TWOD] = False  # 2D最適化
              settings[c4d.OPTIMALMAPPING_AREAFAK] = 0.0
              settings[c4d.OPTIMALMAPPING_RELAXCOUNT] = 0  # リラックス回数
              settings[c4d.OPTIMALMAPPING_SPACING] = 0.02  # スペーシング
              
      
              res = utils.SendModelingCommand(
                  command=c4d.UVCOMMAND_OPTIMALCUBICMAPPING,
                  list=[obj],
                  mode=c4d.MODELINGCOMMANDMODE_ALL,
                  bc=settings,
                  doc=doc
              )
      
              if not res:
                  print("Failed to apply optimal cubic mapping to {}".format(obj.GetName()))
      
      def main():
          doc = c4d.documents.GetActiveDocument()
          if not doc:
              return
      
          doc.StartUndo()
      
          objects = doc.GetObjects()  # シーン内の全オブジェクトを取得
          for obj in objects:
              apply_optimal_cubic_uv(obj, doc)
      
          doc.EndUndo()
          c4d.EventAdd()
      
      if __name__ == "__main__":
          main()
      
      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @ADCMHI
        last edited by ferdinand

        Hello @ADCMHI,

        Welcome to the Maxon developers forum and its community, it is great to have you with us!

        Getting Started

        Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.

        • Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
        • Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
        • Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.

        It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions.

        About your First Question

        Please do not hijack other threads with your questions. I have forked your question.

        The main problem with your code is that you try to use c4d.utils.SendModelingCommand to invoke UVCOMMAND_OPTIMALCUBICMAPPING. But as the symbol says, that is not a modelling but a UV command, you must use CallUVCommand instead. We also have an example for CallUVCommand on GitHub.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • A
          ADCMHI
          last edited by

          I'm sorry for posting without understanding the rules.
          Thank you for your response.
          I tried using this script, but it's not working properly. Could someone help me fix it?

          import c4d
          from c4d import utils
          
          def apply_optimal_cubic_uv(obj, doc):
              if obj.GetType() == c4d.Opolygon:
                  # UVWタグがなければ作成
                  if not obj.GetTag(c4d.Tuvw):
                      uvw_tag = c4d.UVWTag(obj.GetPolygonCount())
                      obj.InsertTag(uvw_tag)
          
                  # オブジェクトを選択
                  doc.SetActiveObject(obj, c4d.SELECTION_NEW)
          
                  # 最適化されたキュービックUVマッピングを適用
                  settings = c4d.BaseContainer()
                  settings[c4d.OPTIMALMAPPING_PRESERVEORIENTATION] = True  # 向きを保持
                  settings[c4d.OPTIMALMAPPING_STRETCHTOFIT] = False  # ストレッチフィット
                  settings[c4d.OPTIMALMAPPING_TWOD] = False  # 2D最適化
                  settings[c4d.OPTIMALMAPPING_AREAFAK] = 0.0
                  settings[c4d.OPTIMALMAPPING_RELAXCOUNT] = 0  # リラックス回数
                  settings[c4d.OPTIMALMAPPING_SPACING] = 0.02  # スペーシング
          
          
                  res = c4d.modules.bodypaint.CallUVCommand(points,
                  pointCount,
                  polys,
                  polyCount,
                  uvw,
                  polySelection,
                  pointSelection,
                  op=settings,
                  handle.GetMode(),
                  cmdid,
                  settings)
                      #command=c4d.UVCOMMAND_OPTIMALCUBICMAPPING,
                      #list=[obj],
                      #mode=c4d.MODELINGCOMMANDMODE_ALL,
                      #bc=settings,
                      #doc=doc
                  
          
                  if not res:
                      print("Failed to apply optimal cubic mapping to {}".format(obj.GetName()))
          
          def main():
              doc = c4d.documents.GetActiveDocument()
              if not doc:
                  return
          
              doc.StartUndo()
          
              objects = doc.GetObjects()  # シーン内の全オブジェクトを取得
              for obj in objects:
                  apply_optimal_cubic_uv(obj, doc)
          
              doc.EndUndo()
              c4d.EventAdd()
          
          if __name__ == "__main__":
              main()
          
          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @ADCMHI
            last edited by ferdinand

            Hello @ADCMHI,

            your code contains syntax errors, you have index arguments after a keyword argument in your CallUVCommand call and you also refer to module attributes that do not exist in your script, uvw and cmdid. You also did not properly follow the code example I provided.

            Your script could either be a product of some chat bot which is not knowing what is doing (but at least CoPilot/ChatGPT write better Cinema 4D code these days) or the struggles of a beginner. And while we understand that CoPilot is a useful tool (we use it ourselves) and that everyone has to start, we cannot help you with chatbot gibberish or with learning the basics of programming. See our Support Procedures for details.

            I personally operate by the rule: "Newcomers have one free" and therefore fixed here your script for you. Please understand that we cannot help you with further questions that are on such a fundamental level of non-functional code. Please also understand that this is not a commitment of SDK to always provide solutions for newcomers, no matter in which state their code is.

            Cheers,
            Ferdinand

            Result

            357f8ac9-f2a4-4d43-983b-53e9f9d1f4c0-image.png

            Code

            """Demonstrates how to apply the `UVCOMMAND_OPTIMALCUBICMAPPING` to a list of selected objects.
            """
            
            import c4d
            import mxutils
            
            from mxutils import CheckIterable, CheckType
            from c4d.modules import bodypaint
            
            def apply_cube_mapping(targets: list[c4d.PolygonObject], settings: c4d.BaseContainer) -> None:
                """Applies `UVCOMMAND_OPTIMALCUBICMAPPING` to each element in `targets` using the `settings` 
                provided.
                """
                # Check the input types.
                CheckType(settings, c4d.BaseContainer)
                CheckIterable(targets, c4d.PolygonObject, list)
            
                for obj in targets:
                    doc: c4d.documents.BaseDocument = CheckType(obj.GetDocument(), c4d.documents.BaseDocument)
            
                    # Make sure the object is the only selected object in the scene, as otherwise the UV command
                    # will get confused.
                    doc.SetActiveObject(obj)
            
                    # EMake sure the document is in UV mode.
                    if doc.GetMode() not in [c4d.Muvpoints, c4d.Muvpolygons]:
                        doc.SetMode(c4d.Muvpolygons)
            
                    # Acquire the active UVSet, if it doesn't exist, create one by opening the UV editor.
                    handle: bodypaint.TempUVHandle | None = bodypaint.GetActiveUVSet(doc, c4d.GETACTIVEUVSET_ALL)
                    if handle is None:
                        c4d.CallCommand(170103)
                        if c4d.API_VERSION >= 22000:
                            c4d.modules.bodypaint.UpdateMeshUV(False)
            
                        handle = c4d.modules.bodypaint.GetActiveUVSet(doc, c4d.GETACTIVEUVSET_ALL)
                        if handle is None:
                            raise RuntimeError("There is no Active UVSet")
            
                    # Retrieve the UVW data for the active UVSet.
                    uvw: list[dict] = handle.GetUVW()
                    if uvw is None:
                        raise RuntimeError(f"Failed to retrieve the uvw data for: {obj}")
            
                    # Call the uv command.
                    if not c4d.modules.bodypaint.CallUVCommand(
                        handle.GetPoints(), handle.GetPointCount(), handle.GetPolys(), handle.GetPolyCount(),
                        uvw, handle.GetPolySel(), handle.GetUVPointSel(), obj, handle.GetMode(),
                        c4d.UVCOMMAND_OPTIMALCUBICMAPPING, settings):
                        raise RuntimeError("CallUVCommand failed.")
            
                    # Update the handle with the new UVW data and release it.
                    if not handle.SetUVWFromTextureView(uvw, True, True, True):
                        raise RuntimeError("UVW from Texture View failed to be set.")
                    
                    c4d.modules.bodypaint.FreeActiveUVSet(handle)
                    print(f"Applied UV mapping to: {obj}")
            
            def main():
                """Entry point of the script.
                """
                # Your settings.
                settings = c4d.BaseContainer()
                settings[c4d.OPTIMALMAPPING_PRESERVEORIENTATION] = True
                settings[c4d.OPTIMALMAPPING_STRETCHTOFIT] = False
                settings[c4d.OPTIMALMAPPING_TWOD] = False
                settings[c4d.OPTIMALMAPPING_AREAFAK] = 0.0
                settings[c4d.OPTIMALMAPPING_RELAXCOUNT] = 0
                settings[c4d.OPTIMALMAPPING_SPACING] = 0.02
            
                # Get all the selected objects in the scene. Your code used here BaseDocument.GetObjects() which
                # does not make too much sense, as it will only return all the top-level objects in the scene.
                selection: list[c4d.BaseObject] = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
                if not selection:
                    c4d.gui.MessageDialog("Please select at least one object.")
                    return
                
                apply_cube_mapping(selection, settings)
            
            if __name__ == "__main__":
                main()
            

            MAXON SDK Specialist
            developers.maxon.net

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