How to run UVCOMMAND_OPTIMALCUBICMAPPING
-
@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()
-
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 invokeUVCOMMAND_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 -
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()
-
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
andcmdid
. 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,
FerdinandResult
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()