Isoparm in Deformer plugin
-
Hello! I have a problem with my deformer plugin.
Plugin not only deforms shape of an object, but also adds new polygons and points to it.
Problem appears when i try to use isoparms mode.
What i figured out:
Problem was in SendModelingCommand(). It was solved by making new document, executing passes and copy to original object.Bool DeformerPlugin::Disconnect(BaseObject* main, BaseThread* thread) { BaseSelect* select = ToPoly(main)->GetPolygonS(); select->DeselectAll(); AutoAlloc<BaseDocument> basedocBuffer; BaseObject* clonedOp = (BaseObject*)main->GetClone(COPYFLAGS::NONE, nullptr); basedocBuffer->InsertObject(clonedOp, nullptr, nullptr); basedocBuffer->ExecutePasses(thread, true, true, true, BUILDFLAGS::INTERNALRENDERER); ModelingCommandData mcd; BaseContainer bc; bc.SetData(MDATA_DISCONNECT_PRESERVEGROUPS, false); mcd.doc = clonedOp->GetDocument(); mcd.op = clonedOp; mcd.mode = MODELINGCOMMANDMODE::POLYGONSELECTION; mcd.flags = MODELINGCOMMANDFLAGS::NONE; mcd.bc = &bc; if (!SendModelingCommand(MCOMMAND_DISCONNECT, mcd)) { ApplicationOutput("Disconnect error."); return false; } clonedOp->CopyTo(main, COPYFLAGS::NONE, nullptr); clonedOp->CopyMatrixTo(main); clonedOp->CopyTagsTo(main, NOTOK, NOTOK, NOTOK, nullptr); return true; }
I should mention that plugin works well with polygon mesh objects and problem appears only with generator objects in isoparm mode.
I guess problem is in Isoparm lines. I've tried to use BUILDFLAGS::ISOPARMS. I cannot use it with non-generator plugin. But i saw few plugins that change count of polygons and still work good. And due to my logic in code i cannot change plugin type to generator.Although creating a temporary document has been a solution, it still doesn't work good. Cinema4d crash appears randomly while i'm testing it. Usually it happens when i reduce amount of detail, i guess it is something with caches.
What isoparms even are? Why should i use it and how to prevent cinema from crash?
And what about SetIsoparm()? Can i use it in deformer plugin somehow? And should i? -
Isoparms are the fancy lines you see when you turn on "Isoparms" in the viewport display options.
I'm only aware of using
SetIsoparm()
in the context of a generator plugin, see Generating. -
Hi @Danchyg1337, thanks for reaching out us.
With regard to your question, I'm a bit confused because iso-parametrics are actually lightweight representations of geometrical elements which being governed by parameters can be drawn using curves defined by the driving parameters having the same value.
This usually applies to rational and non-rational surfaces where the s and t parameters can represent s and t iso-parametric curves defined by the locus of points characterized by the same parameter value.In the case of a generator, this is meaningful because, depending on the math behind the generator, you could take advantage of the iso-params representation but for a modifier I really don't get it. Usually modifiers when applied in a representation where iso-params are shown, automatically deform the isoparametric curves (check for example applying the bend deformer to a sphere represented via iso-params)
Assuming that the code you've posted is running in a BaseObject::ModifyObject() method then BaseObject::SetIsoparm() can not be called from there.
Finally, to my knowledge, deformers like the Bevel Deformer does nothing with regard to iso-params representation since being it applicable only to polygon objects iso-param representation coincides exactly with the edges representation.Cheers, R
-
Hi @r_gigante! Thanks for your ansver. We working together with @Danchyg1337 on this project.
Here is a little demo what happens when Deformer works with generator object (like Cube, Sphere, Plane etc.) in Isoparm Display mode.
https://drive.google.com/open?id=16GpN1otRIdRPaIlw4yHFctC0GW1k0tCO (video)
Cinema 4d crash happens only if deformer is applied to generator object, with polygon object it works as expected.
-
Hi,
I might be misunderstanding the quote:
@r_gigante said in Isoparm in Deformer plugin:
Bevel Deformer does nothing with regard to iso-params representation since being it applicable only to polygon objects iso-param representation coincides exactly with the edges representation.
, but the bevel deformer is applicable to parametric objects and the iso-lines for a parametric object are not always defined by its polygonal topology - this is very obvious for a paramteric sphere with a low polygon count.
@ topic
My guess would be that problematic part is the copying at the end of the method. I don't know how
CopyTo
does work innternally, but if it releases the vectors and matrices defining the object instead of modifying them (which seems likely), the crashing is not so surprising.What you could try is to write your resulting polygon object back manually in a 1:1 fashion for each point and polygon, modifying the existing instances instead of reallocating them, and once all "old" points and polygons have been consumed this way, resize the
PolygonObject
and add the remaining points and polygons in your result object as newly allocated objects.I would also remove the matrix and tag copying, as they seem unnecessary and are another source for possible problems.
ps: lol @ the video.
Cheers,
zipit -
@zipit Thanks for your reply! I tried to do it without copying matrixes and tags, but as i was expecting that didn't make any difference.
I understand that isoparms probably have nothing to do with it, but still a crash appears after choosing isoparms for some reason.
I'm not sure it is related toCopyTo
because the same problem occurs either with or without document buffer. But i can't deny that your guess can be right. -
Hi,
I was probably a bit unclear. I wasn't disputing that the iso-lines are causing the carsh. The video makes it very evident, that this is the case. I was just pointing out that when you nuke the whole cache instead of modifying it, you might risk crashes when something relies by reference onto something in that cache and points to some garbage in memory after you are done with the cache.
Cheers,
zipit -
@zipit I have
Optimize
call at the end ofModifyObject()
. It makes a little difference if i call it or not. WithOptimize
plugin works stable for a random amount of time. WithoutOptimize
it is instant crash. Here isOptimize
code, although it is pretty similar toDisconnect
.Bool DeformerPlugin::Optimize(BaseObject* main, BaseThread* thread) { BaseSelect* select = ToPoly(main)->GetPolygonS(); select->DeselectAll(); AutoAlloc<BaseDocument> basedocBuffer; BaseObject* clonedOp = (BaseObject*)main->GetClone(COPYFLAGS::NONE, nullptr); basedocBuffer->InsertObject(clonedOp, nullptr, nullptr); basedocBuffer->ExecutePasses(thread, true, true, true, BUILDFLAGS::INTERNALRENDERER); ModelingCommandData mcd; BaseContainer bc1; bc1.SetData(MDATA_OPTIMIZE_TOLERANCE, 0.); bc1.SetData(MDATA_OPTIMIZE_POINTS, true); bc1.SetData(MDATA_OPTIMIZE_UNUSEDPOINTS, true); bc1.SetData(MDATA_OPTIMIZE_POLYGONS, true); mcd.doc = clonedOp->GetDocument(); mcd.op = clonedOp; mcd.mode = MODELINGCOMMANDMODE::POLYGONSELECTION; mcd.flags = MODELINGCOMMANDFLAGS::NONE; mcd.bc = &bc1; if (!SendModelingCommand(MCOMMAND_OPTIMIZE, mcd)) { ApplicationOutput("Optimize error."); return false; } clonedOp->CopyTo(main, COPYFLAGS::NONE, nullptr); return true; }
Yeah, and without using document buffer it is instant crash in both cases.
I've tried to use COPYFLAGS::CACHE_BUILD for both
Optimize
andDisconnect
but didn't make a difference.I'm new in plugin development and don't really understand how cinema 4d pipeline works in details. Is
ModifyObject()
creates new object each iteration or just modifies it? Which functions doesObjectData
call and in which order? So many questions, so few answers. -
Hi,
I cannot give you better answer than I have already given you, but I can point out some stuff.
ObjectData
does not call anything. Tangible node types (objects, shaders, tags etc.) come in a pair. TheirNodeData
(e.g.ObjectData
) implementation holding all their logic and their tangibleBaseList2D
representation of that node in in the scene graph, which is shown in the editors, holding all their data.- Cinema will poll a
NodeData
implementation to modify the scene graph. For a generatorObjectData
that does mean building the static caches, for modifierObjectData
building the deform caches. The results are stored in the data layer, i.e. the tangibleBaseList2D
. - Caches come in two flavors in Cinema, the static cache, which is just named cache, and the deform cache. The static cache stores what the generator
ObjectData
has returned in itsGetVirtualObjects
function and the deform cache stores the modified state of the static cache after its has been processed by deformers. Note that caches can contain caches. Think of an parametric object that returns three parametric spheres parented to a null object. A deformer will be called three times for that object, once for the cache of each parametric sphere. - You might be better of doing whatever you want to do with generator objects, because modifiers that actual modify an object in the sense of adding or removing points are a somewhat alien concept to Cinema. The BevelModifier is proof that it is technically possible, but it is certainly not a well known path and might require some very intimate knowledge of Cinema, which is impossible or very hard to obtain for third parties.
Cheers,
zipit -
@zipit Thanks for your reply, it was really helpful for me to understand how things work! I probably should try to make the same with generator object. When i was starting this, i didn't know it would be that tricky to work with modifiers
-
@zipit said in Isoparm in Deformer plugin:
I might be misunderstanding the quote:
@r_gigante said in Isoparm in Deformer plugin:Bevel Deformer does nothing with regard to iso-params representation since being it applicable only to polygon objects iso-param representation coincides exactly with the edges representation.
Sorry for the lack of clarity. Let me put it differently: deformers have nothing to do with iso-params creation or deletion: a bend-deformer, to mention one, doesn't create or destroy the LineObject used in the deformed generator to represent the iso-param, but rather applies the deformation to that data as well.
@Danchyg1337: a deformer, when the iso-params visualization is active, is provided with a PolygonObject (the generator's cache) and with a LineObject (the generator's iso-params). In your code you never check the type of object you pass to DeformPlugin::Disconnect and this lead to indeed unpredictable results especially considering the operations you're executing there.
Last but not least, I warmly invite you to have a look at the examples (deformers and generators) shipped with the cinema4dsdk to getter a better understanding on how generators and deformers behave. As a rule of thumb whilst generators are supposed to create new BaseObject (or SplineObject) instances, deformers are instead supposed to modify the data of the generator without destroying those instance.
Best, Riccardo
-
@r_gigante Thanks for your reply! You were absolutely right about checking input type. When i did a simple type check everything started to work as it should!