Automating Dynamic Place
-
Hi,
I'm trying to write a script to place an object with an irregular shape onto a flat background object (like a floor). Is there a way to reproduce what the Dynamic Place (moving the Y-axis only) until it naturally sits on the floor? I'm writing a script that sets up several image renders at different angles at each frame.
The bounding box can't be used since the shape isn't regular and doesn't shrink wrap properly.
Anyone have a possible direction/solution?
Thanks!
-
Hello @markeee,
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
I really do not want to demotivate you in your first posting, but what you are trying is not trivial and this is one of the cases where when you have to ask, it is probably not for you. The Place tool is not exposed in the public API and so is not the general Rigid Body Dynamics API. Writing something like the place tool yourself is a very hard task.
What is relatively easy, is just to create an RBD setup, and then animate that for X frames, in the hopes that it until then has settled.
Cheers,
FerdinandResult
"""Creates a little RBD setup to place an object on top of another object. I am using here a plane as the object to settle on, but it could also be a non-planar object. Must be run as a Script Manager script and will place/create a Platonic, as if it had fallen on the world grid and settled on the origin of it. Since this must run a simulation, the script will run a while (and block the UI in the mean time). One could make this nicer with threading and statusbar spam, but I did not :) """ import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ # Generate a platonic object and a plane object, scale up the plane, move the platonic 500 units # up on the y-axis, and finally create a little RBD setup. platonic: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Oplatonic)) plane: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Oplane)) plane[c4d.PRIM_PLANE_WIDTH] = 5000 plane[c4d.PRIM_PLANE_HEIGHT] = 5000 platonic.SetMg(c4d.Matrix(off=c4d.Vector(0, 500, 0))) mxutils.CheckType(plane.MakeTag(c4d.Tcollider)) rbd: c4d.BaseTag = mxutils.CheckType(platonic.MakeTag(c4d.Trigidbody)) rbd[c4d.RIGIDBODY_PBD_CUSTOM_INITIAL_VELOCITY] = True rbd[c4d.RIGIDBODY_PBD_CUSTOM_INITIAL_ANGULAR_VELOCITY] = True rbd[c4d.RIGIDBODY_PBD_INITIAL_LINEAR_VELOCITY] = c4d.Vector(-.1) # Create a dummy document, insert our little rig, and execute the passes for 100 frames, in the # hopes that the platonic has settled until then. temp: c4d.documents.BaseDocument = mxutils.CheckType(c4d.documents.BaseDocument()) temp.InsertObject(plane) temp.InsertObject(platonic) fps: int = temp.GetFps() for i in range(100): temp.SetTime(c4d.BaseTime(i, fps)) if not temp.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE): raise RuntimeError(f"Failed to execute pass for {c4d.BaseTime(i, fps)} for {temp}.") # Get the matrix from the settled object. We can zero out the x/z pos, so that the objects sits # dead-center in the world grid. mg: c4d.Matrix = platonic.GetMg() mg.off = c4d.Vector(0, mg.off.y, 0) # Create a new platonic (with the same settings) and insert into the active document and set our # computed matrix. result: c4d.BaseObject = mxutils.CheckType(c4d.BaseObject(c4d.Oplatonic)) result.SetMg(mg) doc.InsertObject(result) # Cinema 4D will garbage collect #temp and its content on its own, but we can call flush to make # it a bit cleaner. temp.Flush() # Push an update event. c4d.EventAdd() if __name__ == '__main__': main()
-
Thanks Ferdinand, I totally understand I'm above my head. If I were to hire someone to do this, would it be possible you think? Or even there, it's so pigeon-holed that it's futile.
I will go and read the links you provided.
Markeee
-
Hey @markeee,
If I were to hire someone to do this, would it be possible you think?
Well, these 'is it possible?' questions are always hard to answer. As always, the wisdom applies that everything is possible in programming when you are just stubborn enough.
I am also not quite sure what you are exact question is. I assume you want some sort of interactive experience, where you drag the object, and it then places itself. Python is an exceptionally bad language for that, it is simply to slow. And even in C++, when you just try to use native tools, this does not look good.
When you would do what I did above in C++ while making it "nice", i.e., implement a tool that allows you to drag an object, and then for each tool update, let that dragged object state simulate in another thread in a dummy document for a few frames, you would probably end up with something that is quite slow. The reason is that we do not expose the core of our Simulation API, and you must go the overhead route of executing a whole document, when you just want to simulate two input objects for a few steps (i.e., frames in the context of document).
Long story short, even an experienced developer could not make this fast and interactive with the native public Cinema API. He or she would have to reimplement rigid body dynamics from scratch or use a lib like Bullet. All that is only sensible in the context of C++, and would probably cost 10's of thousands of Euros to develop, if not even 100's.
That is all to be taken with a grain of salt, because a good dev will look at your problem and say "what you want to do, is incredibly hard and expensive to realize, but I could do that which is orders of magnitude cheaper". And that route might work just fine for you. E.g., the little example I have shown above.
But that is all out of scope of support at the end of the day, we cannot give you advice on how to interact with contract developers. You would have to talk with one of them. And even for the "here is a cheap alternative"-route you probably are not done with a "here is 500€", but a good dev will charge you half a month of work for that. You can probably also just look on some forums or gum-road for a developer who is willing to do this for 500€ and be lucky, but chances are high that they will fail on such task.
Here are two examples for companies which do contract development for Cinema 4D.
https://www.gamelogicdesign.com/
https://www.pixel-nexus.com/Cheers,
FerdinandFYI: I mean that all with no offense, you could be very well the representee for a studio which really has to solve this task, and does not mind spending real money on it. I am just outlining that this is a complex task which requires experts which are usually not cheap.