[Closed] Sdk basic modifier
I’m trying to build a basic multi slice modifier.
I’m a bit confused about the trimesh and mnmesh classes. If I use a triobject the slice function works fine no issues but if I apply a poly mnmesh slice the plugin will crash if I interact with it. I use an if subojbectclass so it isn’t the obvious incompatible node type issue.
Do I need to convert to a trimesh then convert to mnmesh? These object types are a little confusing to the novice. Also how would one go about getting node bounding box size ie height on zaxis. Maxscript is a simple node.max, min.
Thanks guys.
post the code and we can comment otherwize it’s a wild guess, I’m going with “it’s witches”
Sorry, forgot to add it.
//SLICE FUNCTION
void TimberBoarding_mod::SlicePolyObject(MNMesh & mesh, Point3 & N, float offset) {
mesh.SetFlag(MN_MESH_TEMP_1);
mesh.Slice(N, offset, 0, false, true);
mesh.ClearFlag(MN_MESH_TEMP_1);
}
/*************************************************************************************************
*
ModifyObject will do all the work in a full modifier
This includes casting objects to their correct form, doing modifications
changing their parameters, etc
*
************************************************************************************************/
//MAIN MOD ACTION ON MESH
void TimberBoarding_mod::ModifyObject(TimeValue t, ModContext& mc, ObjectState* os, INode* node)
{
//#pragma message(TODO(“Add the code for actually modifying the object”))
/**/
Interval valid = GetValidity(t);
//SEE CHANLED USED
valid &= os->obj->ChannelValidity(t, GEOM_CHAN_NUM);
valid &= os->obj->ChannelValidity(t, TOPO_CHAN_NUM);
//operations on mesh
float tention;
pblock->GetValue(pb_spin, t, tention, valid);
if (os->obj->CanConvertToType(polyObjectClassID))
{
PolyObject *triObj = (PolyObject *)os->obj->ConvertToType(t, polyObjectClassID);
MNMesh &mesh = triObj->GetMesh();
//error on slice function
SlicePolyObject(mesh, Point3(0.0f, 0.0f, 1.0f), tention);
}
//update velidity
NotifyDependents(Interval(t, t), PART_GEOM &PART_TOPO, REFMSG_CHANGE);
os->obj->UpdateValidity(PART_GEOM &PART_TOPO, valid);
//END
}
this is how i would lay it out (it’s not tested)
void TimberBoarding_mod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{
Object *obj = os->obj;
if(!obj) return;
Interval iv = FOREVER;
iv &= obj->ChannelValidity(t, GEOM_CHAN_NUM);
iv &= obj->ChannelValidity(t, TOPO_CHAN_NUM);
TimberBoarding_mod_params p;
GetParams(p,t,iv);
if(obj->IsSubClassOf(triObjectClassID)) // Handle any triobject types
{
ModifyTriObject((TriObject*)obj, p.normal, p.offset);
}
else if(obj->IsSubClassOf(polyObjectClassID)) // Handle any PolyObject types
{
ModifyPolyObject((PolyObject*)obj, p.normal, p.offset);
}
else if(obj->CanConvertToType(triObjectClassID)) // all others should try to convert to a triobject,
{
TriObject *triOb = (TriObject *)obj->ConvertToType(t, triObjectClassID);
os->obj = triOb; // Now stuff this into the pipeline!
ModifyTriObject(triOb, p.normal, p.offset);
}
obj->UpdateValidity(GEOM_CHAN_NUM, iv);
obj->UpdateValidity(TOPO_CHAN_NUM, iv);
}
void TimberBoarding_mod::ModifyTriObject(TriObject* tobj, Point3 &normal, float offset)
{
Mesh& mesh = tobj->GetMesh();
SliceMesh(mesh, normal, offset);
)
void TimberBoarding_mod::ModifyPolyObject(PolyObject* pobj, Point3 &normal, float offset)
{
MNMesh& pmesh = pobj->GetMesh();
pmesh.Slice(normal, offset, 0.0, false, true);
}
Perhaps this is not a matter of substance … but why do you write such a plugin on c++?
if you want to use the “superior” poly cut for all object types then you handle it like this…
static PolyObject* GetPipeAsPoly(TimeValue t, Object *pipe)
{
PolyObject *poly = NULL;
if(pipe->IsSubClassOf (polyObjectClassID))
poly = static_cast<PolyObject *>(pipe);
else
{
if (pipe->CanConvertToType(polyObjectClassID))
poly = static_cast<PolyObject *>(pipe->ConvertToType(t, polyObjectClassID));
else
{
TriObject* tri = static_cast<TriObject *>(pipe->ConvertToType(t, triObjectClassID));
poly = static_cast<PolyObject *>(tri->ConvertToType(t, polyObjectClassID));
if (tri != pipe)
tri->DeleteThis();
}
}
return poly;
}
void TimberBoarding_mod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{
Object *obj = os->obj;
if(!obj) return;
// get our params
Interval iv = FOREVER;
TimberBoarding_mod_params p;
GetParams(p, t, iv);
// start the validity
iv &= obj->ChannelValidity(t, TOPO_CHAN_NUM);
iv &= obj->ChannelValidity(t, GEOM_CHAN_NUM);
// we need the pipeline to be editable poly
PolyObject *polyobj = GetPipeAsPoly(t, os->obj);
if(polyobj != os->obj) // new object push it into the pipe
{
os->obj = polyobj;
os->obj->UnlockObject();
}
// get the mesh and slice
MNMesh& pmesh = polyobj->GetMesh();
pmesh.Slice(p.normal, p.offset, 0.0, false, true);
obj->UpdateValidity(GEOM_CHAN_NUM, iv);
obj->UpdateValidity(TOPO_CHAN_NUM, iv);
}
some types don’t convert directly to poly so you need an interim step i guess. It’s copied directly from tessmod.cpp
Hi Klvnk, really appreciate all the help, fantastic!! I’ve tried the fist suggestion but still the same error crashing on mnmesh.Slice() function, bit stange.
I will try your second poly convert suggestion.
This will eventually be a plugin that slices an object x number of times in z axis then will extrude and bevel faces. Its something that we already use as a script but as a learning experience I wanted to turn it into an interactive modifier.
so the goal is to basically make this maxscript code into an interactive modifier. Its not easy but I’m learning loads!!
SliceMin = $.min
SliceMax = $.max
Xmins = SliceMax.x-SliceMin.x
XEnteredNo = 10
XBoardNo = Xmins/XEnteredNo
xchops = XBoardNo -- number of slices
slicelen = slicemax-slicemin
slicelen = slicelen/xchops
--make slices
for i = 1 to (xchops-1) do
(
slicepoint = [(slicemin.x+(i*slicelen.x)), (slicemin.y+(i*slicelen.y)), (slicemin.z+(i*slicelen.z))]
$.slice [0,0,1] (slicepoint-$.pos)
)
--poly ops after slicing
max modify mode
subobjectLevel = 2
$.edgeExtrudeHeight = 4 *-1
$.edgeExtrudeWidth = 12
$.EditablePoly.buttonOp #Extrude
$.EditablePoly.SelectEdgeRing ()
max create mode
polyop.chamferEdges $ #selection 3
make sure you have the following set
ChannelMask ChannelsUsed() { return GEOM_CHANNEL|TOPO_CHANNEL|TEXMAP_CHANNEL|SELECT_CHANNEL|SUBSEL_TYPE_CHANNEL|VERTCOLOR_CHANNEL; }
ChannelMask ChannelsChanged() { return GEOM_CHANNEL|TOPO_CHANNEL|SELECT_CHANNEL|TEXMAP_CHANNEL|VERTCOLOR_CHANNEL; }
IIRC editpoly cutting routines will start to add mapping and vertex color verts and it causes an issue if the channel are not set… you should add them to the ChannelValidity and UpdateValidity calls