[Closed] C++ Detach by Elements
Hi, Ok I have been tring to use the ReferenceTarget to get the ApplyMeshDelta to work. Although its nots Null anymore, its still not doing anything. On meshop, its uses Value to set up the ReferenceTarget but as I don’t have that, can I just reference the Object ? or do I need to set it up differently ? Code below to show the Referencing.
Object *obj = ip->GetSelNode(0)->EvalWorldState(TimeValue(0)).obj;
TriObject *triObj = (TriObject *) obj;
ReferenceTarget *owner = NULL;
owner = triObj;
MeshDeltaUser *mdu = (owner) ? GetMeshDeltaUserInterface(owner) : NULL;
Mesh* DetachHalfFaces(INode* node, BOOL del = TRUE)
{
TimeValue t = MAXScript_time();
ObjectState os = node->EvalWorldState(t);
if (os.obj)
{
Object* ob = os.obj;
if (!ob || (ob->SuperClassID() != GEOMOBJECT_CLASS_ID && ob->SuperClassID() != SHAPE_CLASS_ID)) return NULL;
if (!ob->CanConvertToType(triObjectClassID)) return NULL;
TriObject *tri = (TriObject *)ob->ConvertToType(t, triObjectClassID);
if (!tri) return NULL;
ReferenceTarget* owner = (ReferenceTarget*)ob;
Mesh* mesh = new Mesh (tri->GetMesh());
if (ob != tri) tri->AutoDelete();
BitArray faces;
faces.SetSize(mesh->numVerts/2);
faces.SetAll();
faces.SetSize(mesh->numVerts, 1);
MeshDeltaUser *mdu = GetMeshDeltaUserInterface(owner);
MeshDelta tmd;
Mesh* newMesh = new Mesh();
tmd.Detach(*mesh, newMesh, faces, TRUE, del, FALSE);
if (mdu && del) GetMeshDeltaUserDataInterface(owner)->ApplyMeshDelta(tmd, mdu, t);
return newMesh;
}
return NULL;
}
now it’s full code that has to work
technically we don’t need recast Object to ReferenceTarget…
GetMeshDeltaUserInterface(ob)
GetMeshDeltaUserDataInterface(ob)
both should be OK
I’m back Sorry Your Code works perfectly and I have changed it so it will now detach each face. The question I have is how you would do this by Element ? As the BitArray is still doing it by faces/verts instead of Elements. Also by having the Element Bool to TRUE, it no longer puts the mesh into a node. So how would I Detach each Element and put them into a new node ? Thanks for your help again, I’m starting to understand this a bit more now
My code to detach by Faces is below :
void PolyTools::DetachNode(INode* node){
BOOL del = TRUE;
TimeValue t = MAXScript_time();
ObjectState os = node->EvalWorldState(t);
if (os.obj){
Object* ob = os.obj;
TriObject *tri = (TriObject *)ob->ConvertToType(t, triObjectClassID);
Mesh* mesh2 = new Mesh (tri->GetMesh());
if (ob != tri) tri->AutoDelete();
for(int i = 0; i < mesh2->numFaces; i++){
Mesh* mesh = new Mesh (tri->GetMesh());
BitArray faces;
faces.SetSize(1);
faces.SetAll();
faces.SetSize(mesh->numVerts, 1);
MeshDeltaUser *mdu = GetMeshDeltaUserInterface(ob);
MeshDelta tmd;
TriObject* newObj = CreateNewTriObject();
tmd.Detach(*mesh, &newObj->GetMesh(), faces, TRUE, del, FALSE);
if (mdu && del) GetMeshDeltaUserDataInterface(ob)->ApplyMeshDelta(tmd, mdu, t);
INode *newnode = ip->CreateObjectNode(newObj);
Matrix3 ntm = node->GetNodeTM(ip->GetTime());
newnode->CopyProperties (node);
newnode->SetNodeTM(ip->GetTime(),ntm);
newnode->FlagForeground(ip->GetTime(),FALSE);
newnode->SetMtl(node->GetMtl());
newnode->SetObjOffsetPos(node->GetObjOffsetPos());
newnode->SetObjOffsetRot(node->GetObjOffsetRot());
newnode->SetObjOffsetScale(node->GetObjOffsetScale());
newnode->CenterPivot(ip->GetTime(), FALSE);
int R = rand() % 256;
int G = rand() % 256;
int B = rand() % 256;
newnode->SetWireColor(RGB(R, G, B));
}
}
}
you can collect all elements first:
int numf = mesh->numFaces;
BitArray faces(numf);
faces.SetAll();
AdjEdgeList ae(*mesh);
AdjFaceList af(*mesh, ae);
FaceElementList elem(*mesh, af);
detach them from original mesh without deleting them from original mesh,
and after that delete them all at once
Hi, thanks for the elements code, I was able to get it all working perfectly! I have finished my code, but if you do a object with lots of elements/faces, then I get some serious lag once its finished. Max just freezes for a good minute or so before I can do anything. Wondering if im doing anything wrong ?? Code is below:
void PolyTools::Detach(){
ip = GetCOREInterface();
t = GetCOREInterface()->GetTime();
for (int i=0; i < ip->GetSelNodeCount(); i++){
INode *node = ip->GetSelNode(i);
DetachFacebyEle(node);
}
ip->FlushUndoBuffer();
ip->RedrawViews(ip->GetTime());
}
void PolyTools::DetachFacebyEle(INode* node){
clock_t clockstart = clock();
TCHAR str[256];
INodeTab ElementsList;
BOOL del = TRUE;
TimeValue t = MAXScript_time();
ObjectState os = node->EvalWorldState(t);
if (os.obj){
Object* ob = os.obj;
TriObject *firstobj = NULL;
if (!ob || (ob->SuperClassID() != GEOMOBJECT_CLASS_ID && ob->SuperClassID() != SHAPE_CLASS_ID) ||!ob->CanConvertToType(triObjectClassID)) {
return;
}
else{
if (ob->IsSubClassOf(Class_ID(TRIOBJ_CLASS_ID, 0))) {
firstobj = (TriObject *) ob;
}
else {
firstobj = (TriObject*) ob->ConvertToType(ip->GetTime(),Class_ID(TRIOBJ_CLASS_ID, 0));
node->SetObjectRef(firstobj);
node->SetNodeTM(ip->GetTime(),node->GetNodeTM(TimeValue(0)));
node->SetMtl(node->GetMtl());
ob = node->GetObjectRef();
firstobj = (TriObject*) ob;
}
}
Mesh* mesh2 = new Mesh (firstobj->GetMesh());
AdjEdgeList ae(*mesh2);
AdjFaceList af(*mesh2, ae);
FaceElementList elem(*mesh2, af);
int k = 0;
for(int i = 0; i < elem.count; i++){
int j = 0;
while(true)
{
if(k == mesh2->numFaces){
PolyList.push_back(j);
break;
}
if(elem[k] == i){
j++;
k++;
}
else {
PolyList.push_back(j);
break;
}
}
}
for(int i = 0; i < elem.count; i++){
Mesh* mesh = new Mesh (firstobj->GetMesh());
BitArray faces;
faces.SetSize(PolyList[i]);
faces.SetAll();
TriObject* newObj = CreateNewTriObject();
MeshDeltaUser *mdu = GetMeshDeltaUserInterface(ob);
MeshDelta tmd;
tmd.Detach(*mesh, &newObj->GetMesh(), faces, TRUE, del, FALSE);
if (mdu && del) GetMeshDeltaUserDataInterface(ob)->ApplyMeshDelta(tmd, mdu, t);
INode *newnode = ip->CreateObjectNode(newObj);
Matrix3 ntm = node->GetNodeTM(ip->GetTime());
newnode->CopyProperties (node);
newnode->SetNodeTM(ip->GetTime(),ntm);
newnode->FlagForeground(ip->GetTime(),FALSE);
newnode->SetMtl(node->GetMtl());
newnode->SetObjOffsetPos(node->GetObjOffsetPos());
newnode->SetObjOffsetRot(node->GetObjOffsetRot());
newnode->SetObjOffsetScale(node->GetObjOffsetScale());
newnode->CenterPivot(ip->GetTime(), FALSE);
int R = rand() % 256;
int G = rand() % 256;
int B = rand() % 256;
newnode->SetWireColor(RGB(R, G, B));
ElementsList.AppendNode(newnode);
mesh->DeleteThis();
}
mesh2->DeleteThis();
PolyList.clear();
PolyList.shrink_to_fit();
for(int i = 0; i < ElementsList.Count(); i++){
ob = ElementsList[i]->GetObjectRef();
firstobj = (TriObject*) ob;
mesh2 = new Mesh (firstobj->GetMesh());
for(int i = 0; i < mesh2->numFaces; i++){
Mesh* mesh = new Mesh (firstobj->GetMesh());
BitArray faces;
faces.SetSize(1);
faces.SetAll();
faces.SetSize(mesh->numVerts, 1);
MeshDeltaUser *mdu = GetMeshDeltaUserInterface(ob);
MeshDelta tmd;
TriObject* newObj = CreateNewTriObject();
tmd.Detach(*mesh, &newObj->GetMesh(), faces, TRUE, del, FALSE);
if (mdu && del) GetMeshDeltaUserDataInterface(ob)->ApplyMeshDelta(tmd, mdu, t);
INode *newnode = ip->CreateObjectNode(newObj);
Matrix3 ntm = node->GetNodeTM(ip->GetTime());
newnode->CopyProperties (node);
newnode->SetNodeTM(ip->GetTime(),ntm);
newnode->FlagForeground(ip->GetTime(),FALSE);
newnode->SetMtl(node->GetMtl());
newnode->SetObjOffsetPos(node->GetObjOffsetPos());
newnode->SetObjOffsetRot(node->GetObjOffsetRot());
newnode->SetObjOffsetScale(node->GetObjOffsetScale());
newnode->CenterPivot(ip->GetTime(), FALSE);
int R = rand() % 256;
int G = rand() % 256;
int B = rand() % 256;
newnode->SetWireColor(RGB(R, G, B));
newnode->InvalidateRect(t);
mesh->DeleteThis();
}
mesh2->DeleteThis();
}
ElementsList.Delete(0, ElementsList.Count());
double seconds = (double)(clock() - clockstart)/CLOCKS_PER_SEC;
swprintf(str, _T("Time taken was: %f
"), seconds);
mprintf(str);
mflush();
}
}
Btw, this code detaches by first splitting them into elements, and then detaching each element by each face. I’ve done this for speed, as its a lot faster than just detaching each face. Although, its worthless if I can’t get rid of the lag after its done.
Edit* : I don’t get the lag if I just do Elements, this seems to be a Faces issues. Which I don’t quite get as, its pretty much the same code, just does more faces at once.
there is a c++ code on this forum that shows how to collect all elements faster than using FaceElementList. the shown algorithm works very well in case where we have many small elements.
Thanks, I will have a look In the mean time, I found my issue within that code. It was lagging on the Face due to the BitArray. Got rid of this line :
faces.SetSize(mesh->numVerts, 1);
Got rid of that, and work fine.