GetVirtualObjects v GetContour for Spline Gen

On 07/11/2016 at 15:16, xxxxxxxx wrote:

I'm currently working on a Spline Generator object that takes a child spline object as an input and creates an outlined version of that spline. I'm not sure whether to return my object in GetVirtualObjects or GetContour.

- GetVirtualObjects
-- Pro: Includes hh object so that I can use BaseObject.GetAndCheckHierarchyClone() for caching.
-- Con: When I make the object editable I end up w/ a Null object half the time and a hierarchy structure that seems a bit confusing.

- GetContour
-- Pro: Recommended for spline objects.
-- Pro: Always get a spline object when I make editable.
-- Con: No way to auto-cache child objects.

Is there an official best practice in this scenario? The docs say to use GetContour for spline objects, and GetVirtualObjects for GetContour for splines - but what about a spline generator object that uses other splines as inputs?

Thank you!


On 08/11/2016 at 11:16, xxxxxxxx wrote:

Okay, my instincts are leading me to use GetContour.

The following were helpful in researching this issue:
- GetContour() refresh or uncache? How? - Plugin Cafe Forums - Page 1: Helped me figure out how to recalculate when changes to the source splines occured.
- cinema4d_py_sdk/Py-DoubleCircle.pyp: Good reference for working with spline points & tangents.
- [Points in local and global coordinates SOLVED">: Useful for dealing with the fact that the spline will be given a neutral matrix, so you have to transform the points from target to local space yourself.

Now, I'm on to figuring out how to automatically hide the first child object I'm using as the source for my generator.

On 08/11/2016 at 11:35, xxxxxxxx wrote:

- Plugin cookbook recipe #3: More info on Generating a Dynamic Spline in an Object Data Plugin. Steve says that you should use GetContour if it's important that your object be interpreted as a spline by most others (e.g. Hair).

Other folks trying to solve the same issue:
- Spline Generator Object - Plugin Cafe Forums

Some info on hiding children of generators objects when you can't just use GetAndCheckCache() because you don't have access to hh in GetContour() :

- [Object Plugin framework SOLVED"> - Plugin Cafe Forums
- [Hide Instance Master SOLVED"> - Plugin Cafe Forums

My initial experiments with Touch() were unsuccessful - the source objects flickered on/off.

Hmm... Can't use NewDependenceList() because AddDependence() also requires an hh.

Any recommendations on how to hide the child object of a Generator inside of GetContour()?

On 08/11/2016 at 12:37, xxxxxxxx wrote:

Hi Donovan, thanks for writing us.

From my tests I've succeeded in creating a  spline generator using another spline as a child. The spline creation takes place in the GetVirtualObject() method where the GetAndCheckHierarchyClone() is used to check the cache and to eventually generate the spline input clone. That said I also confirm that making the generated object "editable" has always  returned a spline object properly hiding the input child.

Let me know if any  additional detail should be provided.

Best, Riccardo

On 08/11/2016 at 13:04, xxxxxxxx wrote:

Hi Riccardo -

The issue is that if I use GetVirtualObjects() and then another plugin calls GetRealSpline() on my ObjectData it doesn't return a spline. Which means that any spline I generate won't work with Hair or SketchAndToon which appear to use GetRealSpline() to check whether a procedural object is a spline.


On 08/11/2016 at 13:05, xxxxxxxx wrote:

Also, I'm using GetRealSpline() to get a spline that I can use - and if I don't use GetContour, I can't use an instance of my plugin object as a source for my plugin object.

On 09/11/2016 at 06:10, xxxxxxxx wrote:

Hi Donovan, thanks for providing this additional info.

With reference to use the generated object with Hair I experience no flaws whilst invoking the GetRealSpline() on it returned, as you stated, a null pointer. But for this second case I suggest, rather than using the GetRealSpline to access its cache and than cast it onto a SplineObject. With this approach you should be able to retrieve a SplineObject as well from the output generated via the GetVirtualObject() in your spline-based generator.

Best, Riccardo

On 14/11/2016 at 14:30, xxxxxxxx wrote:

Unfortunately Python doesn't allow typecasting objects so the cache isn't necessarily useful. My current strategy is:

- Check type to see if it's c4d.Ospline
- CSTO and check to see if I get a spline result.

This is effective, but it feels like it could be unnecessarily slow.

On 16/11/2016 at 17:37, xxxxxxxx wrote:

Okay, my initial instincts were right. Using GetVirtualObjects instead of GetContour results in a lot of incompatibilities/issues with:

- Any plugin that calls GetRealSpline() as a test.
- Spline Mask Object: Cant' use generated splines as Source.
- Align to Spline Tag: Won't place objects on generated spline.
- Complicates accessing spline points for other deformers/generators.

So, now I'm back to one of my initial questions:

How do I hide and retrieve caches for the child objects of my SplineGenerator if I can't use GetAndCheckHierarchyClone() because I don't access to a HierarchyHelp in GetContour()?

On 18/11/2016 at 15:24, xxxxxxxx wrote:

- ObjectData plugin, parent change in OM - Plugin Cafe Forums: Thoughts on using CheckDirty to manually trigger recalculation.
- GetContour() issues - Plugin Cafe Forums: Another plugin running into the same issue of needing to use GetContour()
- GetContour() refresh or uncache? How? - Plugin Cafe Forums - Page 1: Tips on how to better calculate whether it's dirty.

On 24/11/2016 at 02:40, xxxxxxxx wrote:

Hi Donovan, thanks for writing us.

First of all let me apologize for the delay in answering here but it took longer than expected to come out with a reliable and (hopefully) final solution.
After running further analysis based on the issues you've reported we found that Cinema internally uses different approach to test spline based on the tool which is actually using the spline as input.
Although it seems that testing for the OBJECT_ISSPLINE is enough for most of the case the AlignToSpline Tag requires also the GetCountour to be implemented together with the GetVirtualObject.
Under this scenario I've prepared a simple Python plugin that puts the basis for your further development and should solve all the opened issue you've reported. It also hides the child spline in the generator as requested in this other thread of yours and works flawlessly with AlignToSpline, Hair, and all the other generators that make use of splines.

The code is available here and feel free to provide any further comments if other issues arise.

Best, Riccardo

On 28/11/2016 at 21:34, xxxxxxxx wrote:

Hi Knickknack,

Thanks so much for your detailed response! Your example:

- Works with Align to Spline
- Renders w/ Hair
- Renders w/ Sketch
- Is detected by plugins using "GetRealSpline()"

So that's great news!

Unfortunately, I'm still not able to conceal the child objects in the editor - in order to do that, I must make the OffsetYSpline object editable.

I look forward to your input in the other thread: Hide Input Child Objects in GetContour - Plugin Cafe Forums

On 01/12/2016 at 11:01, xxxxxxxx wrote:

Okay, I've modified your example and gotten it more-or-less working (I created a Frankenstein combo of it and my earlier experiments).

1. "GetVirtualObject" needed to become "GetVirtualObjects".
2. I needed to create a system that would convert input objects to Osplines so that it would work with primitive splines.
3. GetHierarchyClone doesn't seem to be working properly in Python, so I'm using GetAndCheckHierarchyClone instead.
4. I needed to create resource files in order to execute this, and the ID needed to be increased from 1000 to 10000 (as 1000 is within the protected range for IDs)
5. It was retrieving an Int instead of a Float for the offset value.
6. I added code to account for the transformation of source points back into generator space.
7. Updated the Spline copy code to account for splines with multiple segments.

Remaining issues:
8. Not compatible with Hair Render, but *is* compatible with Sketch.

For anyone trying to recreate this on their own, it seems like the key trick being used in Riccardo's example is to manually generate a SplineObject() to be returned by GetVirtualObjects instead of a c4d.BaseObject(c4d.Ospline).

On 02/12/2016 at 09:15, xxxxxxxx wrote:

Hi Donovan, thanks for the feedback.

I apologize for the silence but unfortunately in these last days I've had to focus on other tasks also beside this current one. I thank you for pointing out the typo in the code which was something I forgot to mention here and to update on PasteBin.
At this time of writing I confirm I've approached to a solution which works properly fine with most of the test case fixing all the issues you mentioned above as well as those others I run into during code design. The design has been ported on C++ and Python providing native hiding for the input spline on both.

I do look forward to post this solution on Monday after some other corner cases will be tested as well as to hear from your tests

Best, Riccardo

On 13/12/2016 at 03:40, xxxxxxxx wrote:

Thanks for responding. Any news on that example?

On 14/12/2016 at 00:23, xxxxxxxx wrote:

I apologize Donovan for the unexpected delay. I'm strongly still looking to solve some corner cases where it fails in order to provide a solid solution. Please keep tuned.

Best, Riccardo

On 15/12/2016 at 13:04, xxxxxxxx wrote:

Good morning Donovan, once again i'm terribly sorry for getting back to this topic after such a long period but the topic has revealed being trickier than expected with nifty situations tough to debug and solve in the end. 
At the following link you should find a solution which should properly work in almost all the cases although it's still susceptible of further improvements (for example with spline mask there are evident limitation compared to the c++ version)

Let me know how fits with your needs.

Best, Riccardo

On 15/12/2016 at 15:26, xxxxxxxx wrote:

Thanks you Riccardo.

For a c++ exemple does it's the same code converted in c++ or you use others functions?

On 15/12/2016 at 21:08, xxxxxxxx wrote:

Hi Riccardo,

Thank you so much for your work on this! I'll use this as a jumping-off point for my own work. For those reading, the following issues remain:

1. Tangents aren't properly handled when the OffsetSpline objects is moved/rotated away from world origin.
2. You get a console error if you put an empty spline mask generator as the child of the OffsetSpline object.
3. If you make the spline editable, the transformed points return to their starting position (I think this is because access to the deformed cache is lost?).
4. Making the spline editable results in a very dense spline (akin to what you would get after using Current State to Object instead of Make Editable) even though the generator is only doing simple point transformations on the input spline.
5. Disabling some of the middle OffsetYSpline generators in a heavily nested chain can give no result, but toggling them on/off again restores the object (perhaps an issue of a missing cache?)

It's proving to be a pretty thorny problem. If the C++ code works significantly better, I feel like enough of the bones are there that I could hack around and get a workable result even though I'm not familiar w/ C++. Do you have a working C++ example?

Thank you!


On 16/12/2016 at 03:48, xxxxxxxx wrote:

Hi Donovan, thanks for getting back and for posting your impressions.

With reference to the issue reported I confirm that:
1. Fixed in Pastebin (0.2.1)
2. Fixed in Pastebin (0.2.1)
3. Fixed in Pastebin (0.2.1)
4. Not reproducible (the topology is kept exactly as the input child)
5. Not reproducible (even with very complex nested OffsetYSpline hierarchies disabling/enabling child worked properly)

Best, Riccardo