Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search

Properly cloning objects multiple times in GVO

Author
Message
  Topic Search Topic Search
CMPXCHG8B View Drop Down
Member
Member


Joined: 2011 Dec 11
Online Status: Offline
Posts: 95
Direct Link To This Post Topic: Properly cloning objects multiple times in GVO
    Posted: 2018 Mar 12 at 8:51am

User Information:

Cinema 4D Version:   R17 
Platform:    Mac  ;  
Language(s):     C++  ;   

---------

Greetings to all!

What is the recommended way to clone an input object multiple times inside GetVirtualObjects()?

Should GetHierarchyClone() be used each and every time? Or is it better to use GetHierarchyClone() once, and then call GetClone() on the GHC clone for each clone you need after that?

Also, I've noticed the SDK documents mention that generators with variable object output need to declare themselves as OBJECT_UNIQUEENUMERATION when registering and use SetUniqueIP() on the output objects. The example in the SDK docs simply shows some code applying a sequential IP to each clone returned from GetHierarchyClone(). Do these numbers need to change each time you rebuild the virtual object hierarchy? Or is it sufficient to simply count the number of clones generated, and assign the index number of each clone via SetUniqueIP()?

Thanks!
-CMPX


Edited by CMPXCHG8B - 2018 Mar 12 at 8:52am
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1878
Direct Link To This Post Posted: 2018 Mar 13 at 3:37am
Hi CMPX,

in general it's recommended to get the first clone via GetHierarchyClone() (and alike) and then do further cloning via GetClone() of the first one.

The idea of the unique IP is to make generated clones/objects identifiable over multiple frames (e.g. for motion blur). So actually these numbers should change, only, if the actual clone changed. Hm? Not sure, my explanation makes sense. Lets assume a simple cloner, creating clones with a certain lifespan. For example, it creates an additional clone per frame, each with a lifespan of two frames.

Could look like so, with frame number at beginning of each line and list of IP following:
#1 - 1          (created new clone with IP 1)
#2 - 1 2        (added new clone with IP 2)
#3 -   2 3      (clone with IP 1 died and a new one added with a _new_ IP 3)

Cheers,
Andreas
SDK Support Engineer
Back to Top
CMPXCHG8B View Drop Down
Member
Member


Joined: 2011 Dec 11
Online Status: Offline
Posts: 95
Direct Link To This Post Posted: 2018 Mar 13 at 4:30am
Thanks for the reply!

I'm already creating my first clone using GetHierarchyClone(), and all subsequent clones using GetClone().

How should I be managing the unique IPs for these? The manual states that I only need to set the IP for top level object returned from GetHierarchyClone(), but it doesn't say anything about the objects returned from GetClone().

Do I need to recurse the entire object hierarchy provided by GetClone() and call SetUniqueIP() on each child with a unique integer? Or do I just need to assign a unique IP to each top level object returned from GetClone()?

Likewise, what about custom objects allocated through BaseObject::Alloc()? Do those need their own IPs as well?

Last but not least- is it sufficient to just keep around a member variable and increment that every time I need a new IP?

Cheers,
-CMPX
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1878
Direct Link To This Post Posted: 2018 Mar 14 at 7:22am
Hi,

I guess, the answer to all of your questions depends a bit on what you are actually trying to achieve, or what's the actual situation.

If you need to assign unique IPs to children in your clones hierarchy basically depends on, if the renderer should be able to uniquely identify them from frame to frame independently from clone's root object. In the end the IP is a "string" of IDs through the hierarchy. So if a clone and its children can be viewed as an atomic unit, you probably won't need it.
Same for allocated objects.

If a simple counter in a member variable is sufficient, again, highly depends on your use-case. Usually it should be sufficient, but lets take a look at my example above:
This would be wrong (from a renderer point of view, all clones on all frames would be independent):
#1 - 1          (created new clone with IP 1)
#2 - 2 3        (using counter incremented on last frame)
#3 -   4 5

Similarly this would not work out as expected:
#1 - 1          (created new clone with IP 1)
#2 - 1 2        (using fresh counter on every frame)
#3 -   1 2      (clones with IP 1 and 2 are not identical to those in the frame before)

Cheers,
Andreas
SDK Support Engineer
Back to Top
CMPXCHG8B View Drop Down
Member
Member


Joined: 2011 Dec 11
Online Status: Offline
Posts: 95
Direct Link To This Post Posted: 2018 Mar 14 at 11:52pm
Right, that makes sense. So only "new" objects (or new clones) should receive different IPs.

Last question- sorry if this isn't really the thread to post it in, but it's kinda all related to the plugin I'm trying to develop...

Is it safe to modify and return an existing object cache within GetVirtualObjects()? It has occurred to me that there's no real reason to recreate the entire clone hierarchy from scratch every time something on the generator changes- for example, if I'm cloning objects in a grid pattern and I want to adjust the dimensions of the grid, then I don't see any reason why I should recreate all the clones- I could just use GetCache() to retrieve the existing hierarchy (if in fact it exists), iterate over that and update the clone positions using SetMl(), then return that same hierarchy from GetVirtualObjects(). Of course you'd still have to rebuild the entire hierarchy if any of the input objects change, but that's trivial to detect using GetHierarchyClone() with a dirty flag and/or CompareDependenceList().

Is this safe to do?

If it is, could I take that one step further and actually modify the existing cache (either adding or removing clones as needed) to further speed things up?

Cheers,
-CMPX


Edited by CMPXCHG8B - 2018 Mar 14 at 11:53pm
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1878
Direct Link To This Post Posted: 2018 Mar 16 at 9:51am
Hi,

my answer will be a bit fuzzy here. I see no actual reason, why it should not work to modify the cache directly. Searching our code base I found no evidence, this is actually done. So either there are reasons not to do it, which didn't occur to me yet, or nobody needed such an optimization yet.

Cheers,
Andreas
SDK Support Engineer
Back to Top
CMPXCHG8B View Drop Down
Member
Member


Joined: 2011 Dec 11
Online Status: Offline
Posts: 95
Direct Link To This Post Posted: 2018 Mar 18 at 4:36am
Thanks for all your help so far!

I'm not sure if you can answer this, but I figured I might as well ask anyways. How does the Mograph Cloner object handle clones? What I've noticed is that performance is quite poor in GVO if you're returning a large number of objects (for example, a 40x40 object array). The actual cloning completes fairly quickly, but then C4D seems to hang up somewhere in the viewport code for a few seconds while it sorts everything out and draws it on screen.

This was why I was asking about modifying existing caches- if you're just changing the dimension of the cloned array, then it seems to be far faster to modify the positions of the existing clones rather than creating the clones from scratch (which can cause the viewport to lag while it's processing the new clone hierarchy).

The Mograph Cloner object doesn't seem to suffer from the same performance issue when changing the dimensions of a grid array, which made me think it was modifying the existing clone cache rather than recreating it from scratch... Is this how the Cloner object does it? Or is there some other optimizations at play which keep the viewport operating relatively smoothly?

-CMPX
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1878
Direct Link To This Post Posted: 2018 Mar 23 at 9:10am
Hi,

the MoGraph Cloner is a totally different beast. Without going into too much detail (which I'm not allowed to), the MoGraph Cloner takes quite a few shortcuts only possible internally.
Not the answer you wanted to hear, I know...

Cheers,
Andreas
SDK Support Engineer
Back to Top
CMPXCHG8B View Drop Down
Member
Member


Joined: 2011 Dec 11
Online Status: Offline
Posts: 95
Direct Link To This Post Posted: 2018 Mar 25 at 2:00am
Hey, no, that's fine. I was half wondering if it was using some sort of internal APIs to achieve that sort of performance, which I assumed you wouldn't be able to talk about. Thank you for confirming that's the case nonetheless, since that in itself is an adequate answer considering what I'm trying to do (it at least confirms that what I'm doing is probably as fast as I'm going to get this thing running).

Anyways, thanks again for all your help here! I really do appreciate it.

Cheers,
-CMPX


Edited by CMPXCHG8B - 2018 Mar 25 at 2:01am
Back to Top

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.094 seconds.