[Closed] nOOb question about moving vertices
Hi!
I come back in the wonderful worl of Max Development!
I have just a very simple question
maxOps.CloneNodes $ cloneType:#reference offset:[100, 0, 0] newNodes:&ObjectRef
select ObjectRef[1]
addModifier $ (Edit_Poly())
...
max modify mode
subobjectLevel = 1
for i = 1 to num_vert01 do
(
$.modifiers[#Edit_Poly].setSelection #Vertex #{}
$.modifiers[#Edit_Poly].Select #Vertex #{i}
$.modifiers[#Edit_Poly].SetOperation #Transform
$.modifiers[#Edit_Poly].MoveSelection [(random -1 1),(random -1 1), (random -1 1)]
$.modifiers[#Edit_Poly].Commit ()
)
Everything works fine, vertices are moved correctly. But, I had to change max mode to modify and I would like to avoid this.
Is there a direct way to move vertices on Edit_Poly modifier? (I try some other stuff but the original object was modified the same way as the reference…)
Here is the stuff I tried :
polyop.setvert $ verts VertPos
Thanks for your help
François
There’s no way around switching to modpanel, but you can maybe try the “with redraw off” context to do your actions in the modpanel and switch back when finished after your actions are finished. Look it up in the help file, it can seriously speed code up.
-Johan
Hi Francois,
as far as I know there is no way to access Edit Poly Modifier without having the command Panel open, in Modify mode and with EditPolyModifier as the currently active point in the Stack.
Here is the function I have got in my PolyWrapper structure to handle moveVerts for Editable Poly objects and Edit Poly Modifiers. Maybe it can help.
Before switching the Command Panel to Modify mode, you can store its status and restore it at the end of the move function.
/*
moveVerts <BitArray>vertsToMove <Point3 Array>shiftForEachVert <node>theNode <EditablePoly or EditPolyMod>theEditObj <bool>transformsInLocalSpace
*/
function moveVerts baVerts ap3Shift theNode theEditObj localSpace:true =
(
if ((classOf theEditObj) == Editable_Poly) then
(
if (localSpace) then
(
polyOp.moveVert theEditObj baVerts ap3Shift
)
else
(
polyOp.moveVert theEditObj baVerts ap3Shift node:theNode
)
)
else if ((classOf theEditObj) == Edit_Poly) then
(
if (getCommandPanelTaskMode() != #modify) do
setCommandPanelTaskMode #modify
if (modPanel.getCurrentObject() != theEditObj) do
modPanel.setCurrentObject theEditObj
if (localSpace) do
(
local localRM = theNode.transform.rotationPart as Matrix3
ap3Shift = for p3Shift in ap3Shift collect (p3Shift * localRM)
)
local aiVerts = baVerts as Array
with redraw off
(
local nRefCoordSys = getRefCoordSys()
local nSubSelLevel = theEditObj.getEPolySelLevel()
theEditObj.setEPolySelLevel #Vertex
local baVertSelection = theEditObj.getSelection #Vertex node:theNode
baVertSelection.count = theEditObj.getNumVertices()
local baSelVerts = #{aiVerts[1]}
baSelVerts.count = theEditObj.getNumVertices()
theEditObj.setSelection #Vertex baSelVerts node:theNode
setRefCoordSys #hybrid -- Needed, transformations are CoordSys sensitive
theEditObj.moveSelection [0,0,0] -- Hack needed to make all verts move
theEditObj.commit()
for i = 1 to aiVerts.count do
(
baSelVerts[aiVerts[i]] = true
theEditObj.setSelection #Vertex baSelVerts node:theNode
theEditObj.moveSelection ap3Shift[i] -- WorldSpace Required
theEditObj.commit()
baSelVerts[aiVerts[i]] = false
)
theEditObj.setSelection #Vertex baVertSelection node:theNode
theEditObj.setEPolySelLevel nSubSelLevel
setRefCoordSys nRefCoordSys
)
)
)
- Enrico
Thanks a lot JHN and SyncViewS for your quick answer
I just tried the With Redraw off command. Unfortunatelly, it didn’t speed up so much the process. I think I will need to go onto the SDK to really speed up the process.
If you have any idea how to do it C++ wise, your help will also be very appreciated
Once again thanks a lot!
SyncViewS : your piece of code is really full of information that I will use to modifiy a littl bit mine to be more bullet proof!
Hi Francois,
I’m glad it helped. Here is the code of a similar function I’ve got in a PolyWrapper class in C++. But I need to warn you: while I’m quite fluent with MaxScript and previous function has been tested quite a lot, following code is just a hint. You should implement guards to avoid falling in run-time or out-of-range errors.
It is good if you plan to make the function integrated into some other code you got to achieve your goal. But if you’re looking for a way to build a function you can call from MaxScript, the structure is a little different. Take a look at “Writing MAXScript Plug-ins” in the SDK help, and the “mxsagni” sample, filed under: …\maxsdk\samples\maxscript\mxsagni. In particular to “polyop.cpp”. Last but not least: good luck!
/* where:
BaseObject* baseObj = GetCOREInterface()->GetCurEditObject(); // where the current edit object in the stack is and Editable Poly Object or an Edit Poly Modifier.
const Class_ID EPOLYMOD_CLASS_ID(0x79aa6e1d, 0x71a075b7); // barely documented!
if (baseObj->ClassID() == EPOLYOBJ_CLASS_ID)
{
iep = GetEPolyInterface(baseObj->GetInterface(EPOLY_INTERFACE));
obj = static_cast<Object*>(baseObj);
}
else if (baseObj->ClassID() == EPOLYMOD_CLASS_ID)
{
iepm = GetEPolyModInterface(baseObj->GetInterface(EPOLY_MOD_INTERFACE));
obj = getEPModObj();
}
*/
bool moveVert(BitArray verts, Point3* shift, bool local)
{
if (baseObj->ClassID() == EPOLYOBJ_CLASS_ID)
{
if (local)
{
int j = 0;
for (int i = 0; i < verts.GetSize(); ++i)
{
if (verts[i] == TRUE)
{
obj->SetPoint(i, (obj->GetPoint(i) + shift[j++]));
}
}
}
else
{
Matrix3 nodeTM = node->GetNodeTM(GetCOREInterface()->GetTime());
nodeTM.Invert();
int j = 0;
for (int i = 0; i < verts.GetSize(); ++i)
{
if (verts[i] == TRUE)
{
obj->SetPoint(i, (obj->GetPoint(i) + nodeTM.VectorTransform(shift[j++]))); // world to local
}
}
}
iep->LocalDataChanged(GEOM_CHANNEL);
return true;
}
else if (baseObj->ClassID() == EPOLYMOD_CLASS_ID)
{
BitArray index(verts.GetSize());
if (local)
{
Matrix3 nodeTM = iepm->EpModGetNodeTM(GetCOREInterface()->GetTime());
int j = 0;
for (int i = 0; i < verts.GetSize(); ++i)
{
if (verts[i] == TRUE)
{
index.ClearAll();
index.Set(i, TRUE);
iepm->EPMeshSetVert(index, (iepm->EpMeshGetVertex(i) + nodeTM.VectorTransform(shift[j++]))); // local to world
}
}
}
else
{
int j = 0;
for (int i = 0; i < verts.GetSize(); ++i)
{
if (verts[i] == TRUE)
{
index.ClearAll();
index.Set(i, TRUE);
iepm->EPMeshSetVert(index, (iepm->EpMeshGetVertex(i) + shift[j++]));
}
}
}
iepm->EpModLocalDataChanged(GEOM_CHANNEL);
return true;
}
return false;
}
This little piece of code cost me a lot of perspiration, enjoy!
- Enrico