How to increase the number of calculations in a Python tag?
-
Windows 10
Cinema 4d 2023.2.1Good afternoon. I've encountered a problem where the calculation of object behavior written in the Python tag is either not synchronized with the scene frame rate, or otherwise does not have time to calculate some parameters. Because of this, when the amplitude of movements is large, the springs that connect the cubes in the scene look in the wrong direction. In the parameters of the python tag, I have not found a setting for the calculation frequency. Is there any way to increase the number of calculations per frame?
P.S. I made a video in viewport, but when rendering the picture does not change.
-
Hello @ll2pakll,
Thank you for reaching out to us. I assume with calculation frequency you mean how often your tag is invoked, i.e., how often Cinema 4D calls its
TagData::Execute
or by extension themain
function of a python programming tag.Cinema 4D, at least in the classic API you are bound to here, is event driven and follows its so called Scene Execution Pipeline. So your tag(s) are simply as often updated as
EVMSG_CHANGE
is broadcasted into your scene. You cannot cause the tags of type T or set of instances S of type T to be updated more frequently than the rest.You could write a plugin which permanently
EVMSG_CHANGE
into the scene, or to similar effect, permanently marks your tags as dirty (to more or less the same effect). But both these things would be terrible ideas, as they both would always bring Cinema 4D to a crawl, at it would be always recalculating all of the scene.What can I do?
I am a bit fuzzy on what you are trying to do, but it looks like some kind of spring dynamics system.
- Execute the passes yourself. You can execute the passes yourself on a document with
BaseDocument.ExecutePasses
, we talked for example recently about it here. Since you are in a tag you are bound by the threading restrictions as already pointed out in the other thread. So you cannot execute the passes on the scene you are in. But you could create a temporary document, copy all the stuff over you need, and then execute the passes until 'things settle'. Then you can copy back parameters like positions and orientations from your little simulation dummy scene. You cannot copy back the object itself, because that would mean modifying the scene from themain
function of your tag which runs off-main-thread. - The problem with (1.) is that it is quite expensive to do, even in the best scenario of running things in a dummy document. Executing the passes is never cheap, because it is the main event loop of a document. Writing a solver be it springs, or rigid bodies in general, is not trivial, but you should have some kind of centralized abstraction in there. I.e., only one 'solver' tag and then as many 'data' tags as you need to express springs between objects. The solver tag would then do as many iterations on as many objects as you want and simply write the results back into the objects which are marked with the data tags.
Long story short, the primary event loop of Cinema 4D is not a good thing to tie a solver too, because you will run for once into performance problems and also be sometimes event-starved, i.e., your solver does simply not update as there is a longer period without
EVMSG_CHANGE
being emitted.If I get this, right, this all has an educational/explorational context. If I were you, I would try to write abstractly a solver which takes in a system S with N objects and M springs. And then computes any number of iterations/time you want on that system S. Once this runs, you can then tie it to c4d by for example running your spring model in a tag which then writes its result into a scene.
Cheers,
Ferdinand - Execute the passes yourself. You can execute the passes yourself on a document with
-
@ferdinand Thank you for your answer, I didn’t think that the solution would be so difficult. From this point of view, unfortunately, the use of the python tag, in a sense, loses its relevance in the case of complex calculations. I tried the option with ExecutePasses, but it completely hangs the entire program. As a result, the only thing that more or less works, without completely reworking the code, is increasing the FPS of the scene from 25 to 100, this is exactly what I wanted - increasing the number of calculations per second. Unfortunately, this does a lot of unnecessary work related to calculating graphics for frames, which I will reduce to 25 per second anyway. Perhaps my comment will help someone who encounters a similar problem, and who, like me, is not a professional programmer. As always, I thank you and wish you a good mood.
-
Hey @ll2pakll,
yes, any kind of simulation/solver is usually quite a bit of work; and as with most things, most of it is pushing data around in a 'clever' way and not the actual algorithm. You might get away with just saturating the system (add frames or "redraws"), but be warned, you will run into more problems with this approach.
To have a robust solver, you must decouple it from the FPS and scene update events; this is not just a Cinema 4D thing, but universal.
Cheers,
Ferdinand -