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 to CopyTo 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 of ModifyObject(). It makes a little difference if i call it or not. With Optimize plugin works stable for a random amount of time. Without Optimize it is instant crash. Here is Optimize code, although it is pretty similar to Disconnect.

    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 and Disconnect 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 does ObjectData 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.

    1. ObjectData does not call anything. Tangible node types (objects, shaders, tags etc.) come in a pair. Their NodeData (e.g. ObjectData) implementation holding all their logic and their tangible BaseList2D representation of that node in in the scene graph, which is shown in the editors, holding all their data.
    2. Cinema will poll a NodeData implementation to modify the scene graph. For a generator ObjectData that does mean building the static caches, for modifier ObjectData building the deform caches. The results are stored in the data layer, i.e. the tangible BaseList2D.
    3. 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 its GetVirtualObjects 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.
    4. 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


Log in to reply