Copying Polygon Objects

On 07/11/2017 at 01:30, xxxxxxxx wrote:

Hey guys. I'm having some issues copying my own polygon, a low-poly tree. Using a for loop that runs a 100 times with C4D primitives works fine, but my own polygons don't seem to copy. Here's my code:

  1. def main() :
  2. obj = op.GetObject()
  3. for i in range(1, len(getData(filepath)[1])) :
  4. obj = op.GetObject()
  5. posx = randint(-1000,1000)
  6. posy = randint(0,0)
  7. posz = randint(-1000,1000)
  8. obj.SetRelPos(c4d.Vector(posx, posy, posz))
  9. doc.InsertObject(obj)
  10. main()

I hve set the Python tag on my low-poly tree, hence the op.GetObject(). This doesn't work. If I were to replace obj = op.GetObject() with obj = c4d.BaseObject(c4d.Ocube) everything works fine.

On 07/11/2017 at 02:46, xxxxxxxx wrote:

obj = op.GetObject().GetClone()

will return you a copy, actually op.GetObject() return you the object that is already in the scene, while .GetClone() will make a clone of this object into the memory.

Anyway welcome here ! :)

On 07/11/2017 at 03:08, xxxxxxxx wrote:

Thanks gr4ph0s :)

I'm relatively new to Python and Python in Cinema 4D, so expect a ton more questions, haha. I'm mainly looking to use to for generative art and data visualization.

On 07/11/2017 at 05:32, xxxxxxxx wrote:

GetClone() seems to add unnecessary clones which I don't need and causes my C4D to crash in some cases. It gives me an error

AssertionError: Found next objects. Please add them seperately.

My code hasn't changed much, just added the GetClone() :

  1. def main() :
  2. obj = op.GetObject().GetClone()
  3. for i in range(1, len(getData(filepath))) :
  4. obj = op.GetObject().GetClone()
  5. posx = randint(-1000,1000)
  6. posy = randint(0,0)
  7. posz = randint(-1000,1000)
  8. obj.SetRelPos(c4d.Vector(posx, posy, posz))
  9. doc.InsertObject(obj)
  10. main()

On 07/11/2017 at 06:09, xxxxxxxx wrote:


welcome to the Plugin Café forums :slightly_smiling_face:

I'm sorry, but it won't help talking around. Unfortunately your approach is wrong.
But please, don't run away, I think we can get this straight.

So, you are implementing a Python Tag. That's not going to work. A Python Tag (actually tags in general) are not allowed to modify the scene structure. So a Python tag is neither allowed to create new object (actually same is true for other entities like Materials, Tags,...) and insert them into the scene, nor to delete any entities or change the scene hierarchy as it is displayed in the Object Manager. 
The code in the Python tag gets execute, whenever the scene gets executed/evaluated (which will be way more often than you might think). In your first post you inserted the object, which was already part of the scene over and over again into the scene (basically doing doc.InsertObject(op.GetObject()) ). In your last post you are flooding the scene with clones of the object. Remember, your tag doesn't stop being executed...

So, a Python tag is not the right approach.

In order to find the correct approach, we would need to know, what exactly you are planning to do.
If you want to dynamically create objects, like having a low poly tree input object with the goal of creating a high poly version which reacts to changes of the low poly input, you'd probably look into the Python Generator (which in the end boils down to being an ObjectData plugin).
Or maybe you just want to import some geometry data from a file and just single shot create an object from it, then you may even get away with just a script in Script Manager (which is roughly the equivalent of implementing a CommandData plugin).

I recommend to take a look at our Python examples. You can download them here (the examples are included in the Python SDK documentation download).
There are examples for the different plugin types and also a bunch of scripts and scenes. I think, these can provide you with a good idea, what can be done in what way.
And then provide us with some details about what you want to achieve and it will be way easier to provide you with guidance and tips on how to proceed.

On 08/11/2017 at 00:28, xxxxxxxx wrote:

Hey Andreas, thanks for your reply. I had no idea about those examples, but I can see how they're helpful. I'll be sure to check them out.

The short version of what I'd like to create:
An isometric forest with trees scale, position and color based on a dataset I have.

More detailed information about what I want to create:
I would like to load in a dataset I have, and based on that data I want the trees to have a specific place, size (scale) and color on a surface. Furthermore: the data is about carbon emissions, trees seemed like a cool way to visualize this.
1. The surface area would be about 1000x1000 px -- size of the area doesn't really matter, as long as it lines up with the rest. See down below for explanation.

2. I'd like to fill this surface with 175 trees.

3. The position of the trees on that surface would be linked to some data I have, but to keep things simple for now I will just use a random position of x 0 to x 1000 and z 0 to z 1000.

4. The scale of the trees would also be linked to data I have, but again to keep things simple I will use a random number for each.

5. The colors will be red to green and based on data (negative to positive values). I will use MixVec from c4d.utils for this for smooth color gradients, this seems like the least daunting task really, haha. 

6. The position of the trees must be so that the trees largest in scale will be in the back of the surface, say x and z position -1000, so the smaller trees in the front are still visible.

I'm looking forward to your reply. I tried to explain it as best as I could and I hope I have made myself a bit more clear. I'm happy to answer any further question you have. :)

- Kenny

On 08/11/2017 at 09:38, xxxxxxxx wrote:

Hi Kenny,

MAXON's SDK Team can't do any development for you (maybe I should have mentioned earlier on).
So I can only provide you with some hints and starters, where to look in the SDK, but I can't deliver answers on algorithmic questions, like your tree distribution or scaling. But on the other hand I'm sure someone in our community might be able to help here.

You might get pretty far with a Python Generator, at least for a proof of concept. An even better solution would be implementing your own ObjectData plugin. So maybe you want to prototype with a Python Generator and then later on port it into an ObjectData (basically the main function of the Python Generator maps to GetVirtualObjects() of an ObjectData plugin).

The trees, are they hard coded or is there some kind of parameter (e.g. link to an object or a filename parameter and loaded from a file, in ObjectData case maybe as input object)?

In any case, in main() (Python Generator) or GetVirtualObjects() (ObjectData) you will create a Null object as parent and then clones of the tree template object will be inserted under the Null object. Finally the parenting Null object gets returned.

Scaling and positioning of your trees is just a matter of modifying the global matrix of your tree clones.

The Python Generator has the drawback, that you only have the "GetVirtualObjects() part" of an ObjectData plugin. So you need to do the parsing of your input data directly in there, whereas in a dedicated plugin you could implement SetDParameter() and do the parsing only as a reaction to the user setting a different data set (well, even in the Python Generator there's a way to achieve something like this by implementing Message() but that probably leads to far for now). Definitely something to consider for performance reasons.

Parameters, like filename of your data set: For a Python Generator User Data will do the trick (see for example this thread on how to access user data), for an ObjectData plugin you certainly want to take a look at resource files (link to C++ docs, but really all about parameter description resources, no C++ knowledge needed).

To get an idea of an ObjectData, which can probably quite easily be modified for your needs, take a look at the Py-RoundedTube example.

On 09/11/2017 at 02:14, xxxxxxxx wrote:

Hi Andreas,

I'm slightly more confused now than I was before I read your post, sorry. :slightly_smiling_face:

I need to create this so I can load in different datasets as well, meaning the trees size, position and color all need to respond to the data I give them. I can't hardcode it.

But if I understand you correctly, I could use a Python Generator with User Data set on my polygon object/tree that responds to an external dataset?