@r_gigante Thanks for the response, that's what I thought the case would be.
John Thomas
@r_gigante Thanks for the response, that's what I thought the case would be.
John Thomas
Hello,
I am trying to create a deformer plugin that will work on splines by modifying the positions of the points.
Using the code below I am getting the points from a spline and offsetting its position along the Z axis as a simple test.
Bool DeformPlugin::ModifyObject(BaseObject* mod, BaseDocument* doc, BaseObject* op, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread)
{
// Check the input parameters validity.
if (!mod || !op || !doc)
return false;
// Retrieve BaseContainer instance pointer and check for validity
BaseContainer* bc = mod->GetDataInstance();
if (!bc)
return false;
// Verify the modifier inherits from PointObject and cast the pointer to the corresponding PointObject.
if (!mod->IsInstanceOf(Opoint))
return false;
// Verify the modified object inherits from PointObject and cast the pointer to the corresponding PointObject.
if (!op->IsInstanceOf(Opoint))
return true;
SplineObject *opSplineObj = static_cast<SplineObject*>(op);
iferr(MovePoints(opSplineObj, modPointObj))
{
return false;
}
return true;
}
maxon::Result<void> DeformPlugin::MovePoints(SplineObject* opSplineObj, PointObject* modPointObj)
{
if (!opSplineObj)
return maxon::OK;
const Vector* opPointsR = opSplineObj->GetPointR();
const Int32 opPointsCnt = opSplineObj->GetPointCount();
Vector* opPointsW = opSplineObj->GetPointW();
if (!opPointsCnt)
return maxon::OK;
for (Int32 opPointIdx = 0; opPointIdx < opPointsCnt; opPointIdx++)
{
opPointsW[opPointIdx] = opPointsR[opPointIdx];
opPointsW[opPointIdx].z = opPointsR[opPointIdx].z + 20;
}
return maxon::OK;
}
The code is working to properly move the points, the problem is that I am getting the line points of the spline that I am deforming when I am trying to get the spline points.
This is the selection of points I am getting.
This is the selection of points I want to get.
I tried using the base SDK examples and they are also using the line points instead of the spline points.
Is there a way to get and use the spline points or do deformers only utilize the line points?
Any help would be greatly appreciated.
John Thomas
Thanks for the response.
I'll spend some time looking into it.
John Thomas
Thanks for the reply.
I went through the threads you linked but I've got a couple of clarification questions from them as I dig into them more.
I have concerns about the speed of some of the operations that are proposed.
From putting some prints in the GVO and GetContour of the OffsetYSpline, it seems like both GVO and GetContour are both getting called every time the plugin updates, so the entire spline is being rebuilt twice.
Is there a concern about the speed of the plugin given that it seems to be rebuilding twice?
From the code presented in https://plugincafe.maxon.net/topic/11408/getrealspline-not-returning-a-result/12
def GetCloneSpline(op):
#Emulates the GetHierarchyClone in the GetContour by using the SendModelingCommand
#:param op: The Object to clones and retrieves the current state (take care the whole hierarchy is join into one object.
#:return: The merged object or None, if the retrieved object is not a Spline
# Copies the original object
childSpline = op.GetClone(c4d.COPYFLAGS_NO_ANIMATION)
if childSpline is None:
raise RuntimeError("Failed to copy the child spline.")
# Retrieves the original document (so all links are kept)
doc = op.GetDocument() if op.GetDocument() else c4d.documents.BaseDocument()
if not doc:
raise RuntimeError("Failed to retrieve a Doc")
# Inserts the object into the document, this is needed for Current State To Object operation
doc.InsertObject(childSpline)
# Performs a Current State to Object
resultCSTO = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[childSpline], doc=doc)
if not isinstance(resultCSTO, list) or not resultCSTO:
raise RuntimeError("Failed to perform MCOMMAND_CURRENTSTATETOOBJECT.")
# Removes the original clone object
childSpline.Remove()
childSpline = resultCSTO[0]
# If the results is a Null, performs a Join command to retrieves only one object.
if childSpline.CheckType(c4d.Onull):
resultJoin = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_JOIN, list=[childSpline], doc=doc)
if not isinstance(resultJoin, list) or not resultJoin:
raise RuntimeError("Failed to perform MCOMMAND_JOIN.")
childSpline = resultJoin[0]
if childSpline is None:
raise RuntimeError("Failed to retrieves cached spline.")
# Checks if childSpline can be interpreted as a Spline.
if not childSpline.GetInfo() & c4d.OBJECT_ISSPLINE and not childSpline.IsInstanceOf(c4d.Ospline) and not childSpline.IsInstanceOf(c4d.Oline):
return None
return childSpline
It seems like cloning the object and inserting it back into the scene to CurrentStateToObject it and then removing it is going to be potentially really slow.
It seems like it would be a lot of overhead to just get the input points. Forgive my ignorance, but do native Cinema objects face this sort of overhead? Would this amount of overhead be a limiting factor?
John Thomas
I still haven't had any success in getting my code to work as expected. Any help would be appreciated.
John Thomas
Thanks for the response.
From my tests if GetHierarchyClone is commented out then the child object never disappears, as opposed to not appearing in the viewport. So it does seem to be doing something.
To be clear, my goal is to have the child objects correctly marked, (so they wouldn't appear when under the loft or at all), and to correctly retrieve the polygon/spline objects of the children for use in either GetContour(since sometimes I want to return a spline) or GetVirtualObject(since sometimes I want to return an polygon object).
From what I understand the ways to get the polygon/spline objects are CurrentStateToObject, GetCache, GetDeformCache, and GetHierarchyClone.
It seems like CurrentStateToObject doesn't seem like an option because cloning the object over to a new document and rebuilding it can be slow.
Using GetCache and GetDeformCache is faster but far more complicated given the number of exceptions that need to be handled. And these can't be used with AddDependence/TouchDependenceList clears the caches right?
GetHierarchyClone seems to work but that's only available in GetVirtualObjects, so what should be done in GetContour?
What would be the best approach to mark the children objects of my plugins and to retrieve the contents of those children in both GetContour and GetVirtualObject?
John Thomas
I've spent more time working on it and have still not found a solution. Any help would be greatly appreciated.
John Thomas
Hello,
For my plugin I am creating a SplineObject by using a child PolygonObject as input. From the child object I am properly getting the polygon data and using it to create the SplineObject as seen below.
This is working exactly as I want it to, including the child objects not appearing in the viewport.
The problem comes in when I create a Loft and place the copies of my plugin as its children.
For some reason the Loft is returning the child Cubes despite them being inputs to my plugin.
When I make the Loft editable this is what the hierarchy is showing.
This is the stripped down code I am using to do this example. In the code I am just taking the points of the first polygon from the child object and using it to generate the spline. I know that it doesn't have the proper safeguards in place to prevent a crash outside of the scope of my test.
class TestProblem : public ObjectData
{
INSTANCEOF(TestProblem, ObjectData)
public:
BaseObject* GetVirtualObjects(BaseObject *op, HierarchyHelp *hh);
virtual SplineObject* GetContour(BaseObject* op, BaseDocument* doc, Float lod, BaseThread* bt);
static NodeData* Alloc() { return NewObjClear(TestProblem); }
};
BaseObject* TestProblem::GetVirtualObjects(BaseObject * op, HierarchyHelp *hh)
{
Bool dirtyBool;
BaseObject* down = op->GetDown();
op->NewDependenceList();
while (down != nullptr)
{
op->GetHierarchyClone(hh, down, HIERARCHYCLONEFLAGS::ASPOLY | HIERARCHYCLONEFLAGS::ASSPLINE, &dirtyBool, nullptr);
down = down->GetNext();
}
op->TouchDependenceList();
return nullptr;
}
SplineObject* TestProblem::GetContour(BaseObject* op, BaseDocument* doc, Float lod, BaseThread* bt)
{
BaseObject *childObj = op->GetDown();
if (childObj == nullptr)
{
return nullptr;
}
BaseObject *cachedObject = childObj->GetCache();
PolygonObject *poly = (PolygonObject*)cachedObject;
Matrix polyObjMat = poly->GetMg();
if (poly == nullptr)
{
return nullptr;
}
// Get the data from the polygon object
const CPolygon *polyArray = poly->GetPolygonR();
if (polyArray == nullptr)
{
return nullptr;
}
const Vector *posArray = poly->GetPointR();
// Create a spline using the four points from the first polygon on the child object
SplineObject *spline;
spline = SplineObject::Alloc(2, SPLINETYPE::LINEAR);
spline->ResizeObject(4, 0);
Segment *splineSegment = spline->GetSegmentW();
Vector *vectors = spline->GetPointW();
vectors[0] = polyObjMat * posArray[polyArray[0].a];
vectors[1] = polyObjMat * posArray[polyArray[0].b];
vectors[2] = polyObjMat * posArray[polyArray[0].c];
vectors[3] = polyObjMat * posArray[polyArray[0].d];
BaseContainer *splineData = spline->GetDataInstance();
splineData->SetInt32(SPLINEOBJECT_CLOSED, TRUE);
spline->Message(MSG_UPDATE);
return spline;
}
Bool RegisterTestProblem()
{
return RegisterObjectPlugin(ID_TestProblem, "Test"_s, OBJECT_GENERATOR | OBJECT_ISSPLINE | OBJECT_INPUT, TestProblem::Alloc, "Test"_s, AutoBitmap("circle.tif"_s), 0);
}
Is there some method to prevent the Loft, and any other similar Cinema objects, from returning the child objects of my plugin?
Any help would be greatly appreciated.
John Thomas
Thanks for the response.
I tried using the code below to get the children and it does not properly return that there are child objects.
case MSG_EDITABLE_END:
{
BaseObject* op = (BaseObject*)node;
if (op != nullptr)
{
if (op->GetDown() != nullptr)
{
ApplicationOutput("Down");
BaseObject *down = op->GetDown();
}
}
break;
}
Is there a different way that you are meant to use to get the child objects to do the method you suggested?
John Thomas
I've spent more time working on it and have still not found a solution. Any help would be greatly appreciated.
John Thomas