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

    Force polygon object to generate it's cache

    Cinema 4D SDK
    python 2024
    2
    7
    1.2k
    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.
    • bacaB
      baca
      last edited by baca

      Hi,

      I'm going to generate some polygon geometry and modify it's cache object in the same time.
      Then output bunch of these objects under single null in the main() of Python Generator, if it matters.

      Since there's no method like .SetCache() — I need somehow to enforce object to generate it's own cache or even deformCache.
      That's not a generator, just simple c4d.PolygonObject, so calling MCOMMAND_CURRENTSTATETOOBJECT with MDATA_CURRENTSTATETOOBJECT_NOGENERATE flag wouldn't build cache for me.

      Is there any solution for that?

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @baca
        last edited by ferdinand

        Hello @baca,

        Thank you for your question. Yes, that is possible, the relevant method is BaseDocument.ExecutePasses. We talked about it multiple times on the forum, for example here. In the geometry model section of our Python examples, I also went over caches and cache building in geometry_caches_s26.py.

        Note that you are not able to, but not allowed to, modify the caches of objects on your own; e. g., get the cache of an object and delete a point. Technically you can do it, but you need intimate knowledge of Cinema 4D to do it without causing crashes. If you want to modify the caches of things, you must write an ObjectData plugin and there overwrite ModifyObject. This will ensure that your cache modifications of another entity do not happen while something is still relying on that cache.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        bacaB 1 Reply Last reply Reply Quote 0
        • bacaB
          baca @ferdinand
          last edited by

          Hi @ferdinand,

          Unluckily ExecutePasses doesn't build cache for basic c4d.PolygonObjects
          To have an effect, there should be either a modifier under geometry, either it needs to be wrapped into generator, like Connect object.

          The purpose would be to use Python Generator to generate null with bunch of geometry objects,
          and I'm going to modify those geometry cache object by changing their point positions.

          If it matters — I need both non-deformed base mesh, and deformed cache — for soft-body-dynamics, where I can set "Mix Animation" -> "Follow Shape".
          So internally constraints would be aligned with rest state, rather then derived from deformed state.

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @baca
            last edited by ferdinand

            Hey @baca,

            without wanting to be snarky, I would recommend you read geometry_caches_s26.py I have linked to above.

            A PolygonObject has no generator cache because it is not a generator. So, BaseObject.GetCache will always return None. But it can have a deform cache, in fact only discrete geometry representations such as PolygonObject, PointObject, and LineObject can have a deform cache. And deform caches will be built by the cache pass just as the generator caches. If you want to modify discrete geometry, you can just do it. There is no cache. There is a lower level with the raw point and polygon data stored in PointTag and PolygonTag instances, but you usually do not have to mess with these (and can also break quite few things there).

            The purpose would be to use Python Generator to generate null with bunch of geometry objects, and I'm going to modify those geometry cache object by changing their point positions.

            I do not quite follow here, but as said above and as explained in geometry_caches_s26.py, you cannot modify the cache of objects. Technically you can, but you will crash Cinema 4D sooner than later. When you want to modify the cache of an object, you must implement a deformer.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

            bacaB 1 Reply Last reply Reply Quote 0
            • bacaB
              baca @ferdinand
              last edited by baca

              Ah @ferdinand ,

              With all the respect to you — I'm following your advices, before replying 😉
              Your reference is straight, but didn't help with my requirements.

              However your last statement made it clear for me — there's no way to build cache (retrieved with GetCache()) object for PolygonObject. Cool.

              So only deform cache might be available — which is not possible without applying deformers, or some other affection, like dynamics.
              I'll explore that way further.

              Just one more question — I'd like to keep context within the subject — is it possible to clone object with it's built cache?
              I found that once PolygonObject has built deformCache and I'm getting clone with GetClone() — clone's cache disappears.

              ferdinandF 1 Reply Last reply Reply Quote 0
              • ferdinandF
                ferdinand @baca
                last edited by ferdinand

                Hey @baca,

                it is great if you have read it already. But a good portion of the things you are asking here still contradict what I (tried to) explain in the geometry model documentation. It is fine that there are sometimes misunderstandings and misconceptions, but that it makes it difficult to answer questions. So, let us from a simple scenario:

                Generator Caches

                You have a Cube Generator Object O with a Bend B deformer attached to it. O will return a PolygonObject PC for GetCache which is the discrete polygonal form of O and its settings. PC returns None for GetCache and a PolygonObject PDC for GetDeformCache. PDC is the deform cache of PC because deform caches can only be applied to discrete geometry, you can only deform points which exist.

                92e60939-101f-40c3-9273-06b69f02eec7-image.png

                When we run the function GetCacheTree from the geometry model documentation on this setup, it will spit out the text below.

                Cache Tree of 'Cube':
                
                 Cube(Cube)
                	[cache] Cube(Polygon)
                		[deform cache] Cube(Polygon)
                	[child] Bend(Bend)
                

                You can technically reach into a cache, to get for example here the deform cache, and then just modify its points. But first, all this work will be gone the next time Cinema 4D builds the caches, it might also not be directly reflected in the viewport because Cinema 4D considers caches to be static, i.e., it does not expect you to poke around there. But most importantly, there is a good chance you will crash Cinema 4D. Because when you reallocate things or delete things, stuff in C++ which relies on a certain state of that cache then will induce an access violation.

                When you want to modify caches, you must write a deformer, which allows you to generate deform caches. As their name implies, they are primarily intended for deformation. You can bend the rules as for example the Bevel Deformer proves as it adds geometry, but that is a bit tricky to do.

                Non-Generator Caches

                Non-generators, like for example a PolygonObject can only have deform caches. Their discrete geometry data, the points and polygons, can be read and written at any time; at least in theory, threading restrictions also prevent you from modifying things here when you are off main-thread. If you want to know how to update a PolygonObject, you should have a look at geometry_polygonobject_s26.py.

                When you have modified a polygon object, you should send .Message(c4d.MSG_UPDATE) to it to inform it that its data has changed. But there is no cache, as discrete data does not have to be cached. Under the hood there is another level with VariableTag instances holding the raw data, but that is not meant to be used by frontend users and does also not yield any benefits to frontend users.

                What to do?

                So, from what I gather here by reading between the lines, you want to deform discrete geometry. I.e., do your soft body stuff, but want it to be non-destructive. You cannot do that directly, as this contradicts the discrete nature of discrete geometry. Once you have changed one of a point it remains changed.

                Generators or deformers are one way to solve this. They take an input and manipulate it and returns a result (be it a cache or a deform cache).

                But both do not work too well with simulations such as soft bodies where you always must feed your last output into yourself. The solution to that are than tags. You implement a tag which does all the deformation and cache the initial state yourself.

                acddd5e6-a7f6-4855-8659-9a8674d54d6b-image.png
                Fig. 1: The Soft Body tag is one of the examples where a tag in Cinema 4D establishes its own caching layer.

                In the end you just store some point data somewhere which you restore whenever the document is on its first frame. But that all is non-trivial and Python is also not a good language to implement anything soft body related.

                Cheers,
                Ferdinand

                MAXON SDK Specialist
                developers.maxon.net

                bacaB 1 Reply Last reply Reply Quote 0
                • bacaB
                  baca @ferdinand
                  last edited by

                  Thanks @ferdinand,

                  Thats gone too far, we can close this subj now.
                  I think I have a solution already.


                  I just wasn't clear enough in the beginning, I just wanted to know if PolygonObject can be forced to produce it's cache object by a command.

                  I made an experiment where I spawn flat geometries between other flat geometries. Like planes in-between of deformed soft body planes. Here's working example:
                  Setup:
                  417b1a04-77c9-4163-bc6f-36c2800323f5-image.png
                  And simulation:
                  cloth_multiply__03_.gif

                  Once you clone original geometry — it's flat, and there would be intersections and simulation will be broken.
                  So you need to blend newborn geo point positions in-between of existing geometry points.
                  Once you blend it — there are no intersections, it nicely continue with soft body simulation.
                  But softbody dynamics build constraints for every new object. And if geometry first appears as deformed — wrong constraints are initialized, and each new object becomes crumpled real quick.
                  Also there's "Mix Animation" -> "Follow Shape" checkbox, which rebuild constraints (or adjusts them - who knows?) — and it reads original point positions, as I understood.

                  So I had to have both — original geo, and cache.
                  Where cache used to simulate geometry in 3D, and original object (CacheParent?) will be used for constraints.

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