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
    1. Maxon Developers Forum
    2. wuzelwazel
    3. Posts
    W
    • Profile
    • Following 0
    • Followers 0
    • Topics 12
    • Posts 42
    • Best 10
    • Controversial 0
    • Groups 0

    Posts made by wuzelwazel

    • Very Slow - AddUndo() Before Removing Object From the Document

      I'm looping through 397 objects in my current scene and removing them all with the following code:

      for obj, _ in instance_grp:
          self.doc.AddUndo(c4d.UNDOTYPE_DELETEOBJ, obj)
          obj.Remove()
      

      I've timed the sub-section of the script where this is happening. When I AddUndo() here the script takes a total of ~4.3 seconds to run and this section in particular takes ~3.1 seconds.

      If I comment out the AddUndo() line like so:

      for obj, mtx in instance_grp:
          #self.doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj)
          obj.Remove()
      

      Then the total runtime of the script is ~1.2 seconds and this section takes ~0.09 seconds. This is unexpected. Is there something I could be doing differently; is this a bug?

      posted in Cinema 4D SDK python 2023
      W
      wuzelwazel
    • RE: How to make Python Field react to camera?

      Calling AddEventNotification() in Python seems to consistently crash Cinema 4D 😞

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: How to make Python Field react to camera?

      @manuel Amazing! Thank you for stepping through this with me.

      I was thinking that messages could be the solution here but I'd only ever dealt with them in the context of a MessageData plug-in and was not aware of AddEventNotification().

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: How to make Python Field react to camera?

      @manuel thanks for getting back to me and apologies for the delay in providing more information.

      I'm attaching a C4D scene file here that includes the setup with Python Field and Camera object.

      camera_field_simple.c4d

      The part of the code where I'm attempting to trigger a refresh of the sampling is in the InitSampling() function and it's pretty simple:

      if camera.GetDirty(c4d.DIRTYFLAGS_MATRIX | c4d.DIRTYFLAGS_DATA):
              op.SetDirty(c4d.DIRTYFLAGS_DATA)
      

      I had also attempted getting the active BaseDraw from the document, checking whether it's linked camera was the one linked in the field, and checking the BaseDraw dirty state instead of the camera but that didn't work out.

      I've also noticed that if I transform the camera and undo the transform the field does not update.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • How to make Python Field react to camera?

      I'm working on a Python Field that updates based on a camera linked by user data. I was able to get the field to update as the camera attributes are modified or animated by "forwarding" the camera's dirty state to the field object. However, this doesn't work when viewing through the camera and manipulating with shortcuts in the viewport.

      I tried reading the dirty state of the associated BaseDraw but that didn't seem to work. Is this a priority issue? Is there an alternative method to trigger calculation of the field when manipulating the active camera?

      Thanks.

      posted in Cinema 4D SDK python 2023
      W
      wuzelwazel
    • Modifying Cinema 4D Preferences from External Python Script?

      I'm curious whether it would be possible to create a system whereby an external python script could modify the preferences of a running instance of Cinema 4D.

      My first thought was to generate some code in the external script and pass it to Cinema 4D for execution, but that seems (A) potentially unsafe and (B) more complex than it needs to be.

      My second thought was to set a system environment variable from the external script and read it from Cinema 4D. In my case it could be something simple like setting EXTERNAL_STATE = 1 under certain circumstances. This would require Cinema 4D to watch for changes to the environment variable and I'm not sure that's possible.

      The third approach might be for the external script to create a temporary file to represent one state and then remove it in another state. Alternatively it could write data into that file for Cinema 4D to read. This would still require some way for Cinema 4D to watch for changes.

      I suppose I'm curious if there are any known approaches to this sort of thing or which of my 3 potential approaches might be most reasonable. In the 2nd and 3rd cases I'm also curious whether anyone knows of an elegant/efficient way to watch for a change to an environment variable or file.

      Thinking on it a bit more I suppose the most elegant solution would be to send messages directly to Cinema 4D that it could catch and handle in a plug-in. Is that possible?

      Thanks!

      posted in Cinema 4D SDK r23 s24 r25 python sdk
      W
      wuzelwazel
    • Undo Block through Context Manager

      I was just brushing up on the Undo system for a simple Python script and it occurred to me that a context manager like this:

      with doc.UndoBlock():
          doc.AddUndo(...)
          #code that needs to be undone
      

      Might be a nice little quality of life improvement. I suspect that this would be a break from the C++ API so perhaps it's not in the cards, but I thought it was worth bringing up. I would propose that the current method remain valid but a context manager be added as well.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Python API OpenGL Information

      @ferdinand it looks like this hasn't changed in S24. Is there an expected timeline for a fix to these bindings?

      Thanks!

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Python API OpenGL Information

      Thanks again for the update. GPUtil came up as an option when I was researching external modules but it only works with NVIDIA hardware. That might not be so bad for now especially as the Python check for GPU hardware vendor in Cinema 4D does seem to be working.

      I'll mark this as solved for now. I look forward to the API updates!

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Python API OpenGL Information

      @zipit thank you so much! c4d.GeGetCinemaInfo() makes sense. Unfortunately the current Python documentation is a bit misleading as c4d.GeGetSystemInfo() is not listed as deprecated and the description for c4d.GeGetCinemaInfo() makes it sound like it's exclusively for determining if the current C4D session is NFR.

      Thank you very much for looking into c4d.storage.GeGetMemoryStat(). I'm excited to work on my little OpenGL control panel and stretch my GUI knowledge further 😂 👍

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • Python API OpenGL Information

      I wanted to try making a small python control panel to monitor viewport OpenGL memory usage. I was also going to explore methods to force a reduction in VRAM usage.

      However, I've noticed several pieces that seem to be missing or non-functional in the Python API and was hoping I could get some info on them.

      First it seems that several of the flags returned by c4d.GeGetSystemInfo() are missing from the python API. The only ones that appear to exist are c4d.SYSTEMINFO_NOGUI and c4d.SYSTEMINFO_OSX. I was hoping that c4d.SYSTEMINFO_OPENGL would be in there.

      Second and more importantly I can't seem to get any information that's useful in my case from c4d.storage.GeGetMemoryStat(). The BaseContainer returned seems to only have values for c4d.C4D_MEMORY_STAT_MEMORY_INUSE and c4d.C4D_MEMORY_STAT_MEMORY_PEAK. All of the other keys return 0 or the keys don't exist in the BaseContainer at all. The latter is the case for c4d.C4D_MEMORY_STAT_OPENGL_USED and c4d.C4D_MEMORY_STAT_OPENGL_ALLOCATED which are the ones I was hoping for.

      posted in Cinema 4D SDK r23 python
      W
      wuzelwazel
    • RE: Generating Splines from JSON Data

      Here are my results after 35 minutes of processing:

      Cinema_4D_2020-06-21_17-15-13.png

      Much better than the 12 hours and 0 results I got from my previous attempt 😂

      It looks like there are 5,183,087 segments. I have them split across 519 spline objects. The scene's viewport navigation is still fairly responsive, about 25fps when all the splines are visible. Higher if I zoom into a section.

      I'd still like to improve the method if anyone can provide more information on how I might use SetAllPoints for the splines here.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Generating Splines from JSON Data

      @zipit said in Generating Splines from JSON Data:

      1. Aside from instantiating the SplineObject in the first place, you would also have the problem that Cinema's splines are not static, i.e. are being dynamically cached. That would mean all this point data had to be reprocessed each time the cache for this spline is being build.

      Perhaps this is a reason it would be good to build splines made of fewer segments/points? I will not be modifying the curves after they're built the first time. Are you saying that the cache is built for the SplineObject even outside of the call to SplineObject.Message(c4d.MSG_UPDATE)? That's not the way it seems to behave based on my (limited) observations.

      1. This is more an academic point due to the mentioned problems, but setting each point individually seems very inefficient, you should push all points in at once, using PointObject.SetAllPoints.

      I'd like to use this method but I haven't found any examples of using it on a SplineObject. My concern is that I would have to call this once per SplineObject (as opposed to per segment) which would entail keeping a 10,000 element python list of which each entry is a 5 element python list of c4d.Vector alive until the SplineObject points are ready to be set. I might be able to use one of the methods from itertools to do this relatively quickly, but I'm just not sure if it'll actually be an improvement. I suppose it would be if the cache is in fact being built whenever a point is added.

      1. The only way to go would be to reduce the dataset in dimensionality, which would mean for a curve to do some curve fitting. Cinema has a curve fitting function in its API, its even accessible in Python in the c4d.utils module, but I somehow doubt that it is up to the task. You will probably have to use numpy and scipy for that.

      Each curve is already very simple; just 5 points that Disney expects to be interpolated (I'm using B-Spline in this case). Perhaps lowering the number of intermediate points for this case would be beneficial, especially as these splines are very distant from the majority of the scene (occupy a small section of the frame).

      I've gone ahead and modified my code to chunk the curve data so that each SplineObject ends up with only 10,000 segments. Now processing 100,000 curves takes only 42s down from the prior 10m13s. This seems to be a roughly linear increase in time from the 5s for 10,000 segments that I'd previously recorded... so I think I'm happy for now?

          point_count = 0
          segment_count = 0
          spline_count = 1
          num = 10000
      
          spline = srcSpline.GetClone()
          spline.SetName("{0}_{1:0>4d}".format(name, spline_count))
          curves = ijson.items(json_file, 'item', buf_size=32*1024)
          for i, curve in enumerate(curves):
              index = i % num
              if index >= (num - 1):
                  spline.InsertTag(texture_tag.GetClone())
                  spline.InsertTag(object_tag.GetClone())
                  spline.SetLayerObject(layer)
                  spline.Message(c4d.MSG_UPDATE)
                  doc.InsertObject(spline, group)
                  point_count = 0
                  segment_count = 0
                  spline_count += 1
                  spline = srcSpline.GetClone()
                  spline.SetName("{0}_{1:0>4d}".format(name, spline_count))
              if spline_count > 10:
                  break
              point_count += len(curve)
              segment_count += 1
              spline.ResizeObject(point_count, segment_count)
              for id, point in enumerate(reversed(curve)):
                  spline.SetSegment(segment_count-1, len(curve), False)
                  spline.SetPoint(point_count-id-1, flipMat * c4d.Vector(*(float(p) for p in point)))
      
      posted in Cinema 4D SDK
      W
      wuzelwazel
    • Generating Splines from JSON Data

      Hello!

      I'm revisiting the Moana Island data set and I'm making great progress; I've got almost all of the assets converted into Redshift Proxies.

      The biggest problem I'm currently facing is a 3GB JSON file that defines renderable curves on the largest mountain asset. I don't know exactly how many curves are defined in this file, but based on the curve count and data size of other JSON files I think its roughly 5.2 million curves. Each point of the curve is an array with 3 items, each curve is an array of N points, and the curves are stored inside of a top level array.

      The built-in json module must load the entire file into memory before operating on it. I've experienced extremely poor behavior on any JSON file over 500MB with the json module so I am instead parsing the files with ijson which allows for iterative reading of the JSON files as well as a much faster C backend based on YAJL.

      Using ijson I was able to read an 11GB file that stored transform matrices for instanced assets on the beach. However, even using ijson I cannot seem to build a spline from the curves in this 3GB file (I gave up after letting the script run for 12 hours). I have a suspicion it has more to do with the way I'm building the spline object than parsing the data. So I have some questions. Is there a performance penalty for building a single spline with millions of segments? Should I instead build millions of splines with a single segment? Or would it be better to try and split the difference and build thousands of splines with 10,000 segments each?

      I've done a little performance testing with my current code and right now it takes 10 minutes 13 seconds to build a single spline out of the first 100,000 curves in the file. However, if I build just the first 10,000 curves it only takes 5 seconds.

      I'm leaning heavily toward chunking the splines into 10,000 segment batches but I want to first see if my code could be further optimized, here is the relevant portion:

          curves = ijson.items(json_file, 'item', buf_size=32*1024) 
          #curves is a generator object that returns the points for each segment successively
      
          for i, curve in enumerate(curves):
              #for performance testing I'm limiting the number of segments parsed and created
              if i > num:
                  break
              point_count += len(curve) #tracking the total number of points
              segment_count += 1 #tracking the number of segments
              spline.ResizeObject(point_count, segment_count) #resizing the spline
              for id, point in enumerate(reversed(curve)):
                  spline.SetSegment(segment_count-1, len(curve), False)
                  spline.SetPoint(point_count-id-1, flipMat * c4d.Vector(*(float(p) for p in point)))
          
          spline.Message(c4d.MSG_UPDATE)
      
      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Packed Automatic UVs Command in S22?

      I never would've found the command id so thanks a ton for sharing that. Marking as solved.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Packed Automatic UVs Command in S22?

      Well, it was a beautiful dream. The CallUVCommand to UVCOMMAND_AUTOMATICUV still fails when supplying a settings container based on the MDATA I found. In retrospect it does seem odd that these would be MDATA when the other UV command settings are not.

      Looking forward to your examples. I'll keep stabbing blindly in the dark in the meantime.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Packed Automatic UVs Command in S22?

      @m_adam Thanks Maxime!

      I'd found UVCOMMAND_AUTOMATICUV while perusing the depths of symbols.h yesterday but I couldn't find a way to make it work and I wasn't sure if it was what I needed... so I stopped looking into it. Your post renewed my enthusiasm and I went looking in the C++ SDK docs to find this:

      https://developers.maxon.net/docs/cpp/2023_2/group___m_d_a_t_a___a_u_t_o_m_a_t_i_c_u_v.html#gadd449518eb3bc7a84abe96673e62488a

      Which I believe will allow me to create my settings container for the command. I'll try this later today and let you know the results.

      It would be nice to have the python documentation updated too 👍

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • RE: Packed Automatic UVs Command in S22?

      @wuzelwazel said in Packed Automatic UVs Command in S22?:

      Alternatively being able to invoke the Set UVW From Projection... command with the automatic packed option would be even more straightforward in this case. Is that possible?

      I should mention that I can use c4d.CallCommand(c4d.UV_SET_FROM_PROJECTION_CMD_ID) but in that case I don't know how to set the options for the command via Python.

      posted in Cinema 4D SDK
      W
      wuzelwazel
    • Packed Automatic UVs Command in S22?

      Hello, I'm struggling to figure out how to call the new Packed Automatic UV command from Python. I've found the BaseContainer where I can modify settings, but haven't figured out how to invoke the command.

      Alternatively being able to invoke the Set UVW From Projection... command with the automatic packed option would be even more straightforward in this case. Is that possible?

      posted in Cinema 4D SDK s22
      W
      wuzelwazel
    • RE: Ptex Shader Progress

      @kbar said in Ptex Shader Progress:

      I had planned on doing this again and converting the OBJ files to C4D files in the process, to make them smaller and faster to load. Which is what you are doing with Redshift proxies I believe?

      Yes, the Redshift Proxies work as a sort of reference so the main c4d file would be quite small. In addition the display of each proxy can be simplified to either reduce or eliminate the viewport being bogged down with drawing faces. Of course, when everything is just a bounding box the scene doesn't look like much before rendering!

      The other benefit of the proxy is specific to Redshift in that the mesh will not need to be processed before the BVH is constructed and rendering can begin.

      posted in General Talk
      W
      wuzelwazel