Setting hair guides via SetGuides()
On 21/11/2015 at 01:48, xxxxxxxx wrote:
Cinema 4D Version: R17
Platform: Mac ;
Language(s) : C++ ;
I am trying to set some hair guides on a hair object directly.
I can create a HairGuides object using either AutoAlloc<> or via HairGuides::Alloc().
I can then set those hair guides using ((HairObject * )hairObj)->SetGuides(guidesObj, false).
However, I've noticed several things:
Calling SetGuides() with the second parameter ("clone") set to true will instantly crash C4D. What is this option for? The API documentation is just about as helpful as the function declaration ("true to clone the supplied guides").
If the HairGuides object is deallocated/freed at any time (either via AutoAlloc when I leave the scope, or via calling HairGuides::Free(guidesObj)), then the guides don't show up in the hair object and/or viewport. If I'm not using AutoAlloc<>, don't I need to free the HairGuides object afterwards? Or does the hair object take care of this for me after I call SetGuides()?
On 23/11/2015 at 04:44, xxxxxxxx wrote:
the point is, via SetGuides() you pass the pointer to the HairGuides instance to the HairObject. At this point the HairObject takes ownership of the HairGuides and will of course also take care of freeing the HairGuides, when necessary. This being said, it is probably not a good idea to pass AutoAlloc'ated HairGuides to SetGuides(), as the HairGuides will be deallocated after leaving the scope, leaving Cinema 4D working on unallocated memory...
And this is where the clone parameter comes into play. Instead of taking the ownership of the HairGuides instance, the guides will be cloned internally and the caller stays owner of the HairGuides instance, when clone is set to true. In this case you have to take care of freeing the HairGuides instance yourself and may want (and are allowed) to use AutoAlloc again.
I quickly checked the clone option by slightly modifying the hair_generator.cpp example. Leads to no crash here. So you may want to check your code with above explanation.
If the problem persists, please post some code, so I can reproduce your issue.
On 26/11/2015 at 18:38, xxxxxxxx wrote:
I thought that's what the clone argument was for, but using it causes C4D to crash instantly (and not when leaving the scope or anything, but on that exact line with the call to SetGuides()).
AFAIK, I'm not doing anything that I shouldn't be. My code is identical to the hair_generator.cpp example, except I setup the guide points before calling SetGuides(), not after. Is there some reason why this needs to be done?
PS: I should note that everything works great when I leave the second parameter to SetGuides as false and just pass it a pointer for a manually allocated HairGuides object. So my code is working fine, though I'm still curious as to why SetGuides() causes C4D to crap out. It did this under Python as well.
On 27/11/2015 at 11:27, xxxxxxxx wrote:
as already mentioned, I tried to reproduce your issue with the hair_generator example and had no problems (moving the SetGuides() call with clone set to true directly behind the for-loop, and of course adding deallocation of the allocated guides).
You are asking for a reason.. reason for what? The order of SetGuides() and setting up the points array. No, there is no reason. With clone equal false, the order shouldn't matter. But if clone is set to true, order becomes relevant of course.
Can you please check, if you get the crash with the hair_generator example as well?
On 27/11/2015 at 19:21, xxxxxxxx wrote:
The SDK example works fine.
The problem has to do with where the hair object is coming from.
In the SDK example, the code is creating a new HairObject instance and then configuring the guides on that. This works fine, I've tested that in my own code and I don't get a crash if I call SetGuides(guides, true).
The only problem is that my plugin works as a tag so that it can set the hair guides of a hair object directly when the tag resides on a hair object in the object manager.
So what I'm doing is I'm checking for op->IsInstanceOf(Ohair) in the tag's Execute() function, and if that returns true, then I go ahead and create a new guides object and set it using ((HairObject * )op)->SetGuides(guides, false).
This works fine so long as the hair guides were allocated manually (using HairGuides::Alloc()).
Originally, I was AutoAlloc'ing the HairGuides object and attempting to pass it to the hair object using ((HairObject * )op)->SetGuides(guides, true). This crashes C4D instantly. Even if I don't actually do anything with the guides, the moment I call SetGuides(guides, true)... Kaboom. Even if the HairGuides object was created without AutoAlloc, same result.
On 27/11/2015 at 19:32, xxxxxxxx wrote:
It looks like I need to call the Lock() function on the HairObject before I set the guides, and then call Unlock() afterwards. If I do this, then I can successfully set the guides using SetGuides(guides, true) on an existing hair object in the scene.
On 30/11/2015 at 10:10, xxxxxxxx wrote:
Didn't you say, you did everything like in the hair_generator example?
Yes, that lock is important!