[sdk] AttachMesh with tVerts and vertCol


#1

hello,
I have problem with mesh attach.
I use MeshDelta for it. And the code is

Matrix3 im;
im.IdentityMatrix();
MeshDelta nmd;
nmd.AttachMesh(mesh, tempMesh, im, -1)
nmd.Apply(mesh);
mesh.InvalidateTopologyCache();

The mesh was attached with tempMesh, but data of tVerts and vertCol was gone.
So, how do I attach with map and vertex color information?

thanks


#2

this what triops::Attach uses

MeshDelta nmd;
nmd.AttachMesh (GetMesh(), obj->GetMesh(), tm, mat2Offset);
ApplyMeshDelta (nmd, this, ip->GetTime());

and that seems to work correctly, this is the apply mesh delta function…

void EditTriObject::ApplyMeshDelta (MeshDelta & md, MeshDeltaUser *mdu, TimeValue t) {
	if (AreWeKeying(t)) {
		BOOL addedCont = FALSE;
		for (int i=0; i<md.vMove.Count(); i++) if (PlugControl(t, md.vMove[i].vid)) addedCont = TRUE;
		if (addedCont) NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
	}
	MeshTopoRestore *tchange = NULL;
	DWORD partsChanged = md.PartsChanged ();
	if (theHold.Holding() && !TestAFlag (A_HELD)) {
		if (partsChanged & (PART_TOPO|PART_TEXMAP|PART_VERTCOLOR)) {
			tchange = new MeshTopoRestore (this, partsChanged);
		} else {
			if (partsChanged & PART_GEOM) theHold.Put (new MeshVertRestore (this));
			if (partsChanged & PART_SELECT) theHold.Put (new MeshSelRestore (this));
		}
	}
#if defined(NEW_SOA)
	GetTriObjDescriptor()->Execute(I_EXEC_EVAL_SOA_TIME, reinterpret_cast<ULONG_PTR>(&t));
#endif

	for (int i=0; i<md.vMove.Count(); i++) {
		DWORD j = md.vMove[i].vid;
		Point3 pt = GetMesh().verts[j] + md.vMove[i].dv;
		if (cont.Count() && cont[j]) cont[j]->SetValue (t, &pt);
	}
	int nv = md.vClone.Count();
	if (nv != 0) {
		SynchContArray (GetMesh().numVerts+nv);
		IncreaseNamedSetSize (NS_VERTEX, GetMesh().numVerts, nv);
	}
	if (md.NumFCreate()) {
		IncreaseNamedSetSize (NS_EDGE, GetMesh().numFaces*3, md.NumFCreate()*3);
		IncreaseNamedSetSize (NS_FACE, GetMesh().numFaces, md.NumFCreate());
	}
	md.Apply (GetMesh());
	if (md.vDelete.NumberSet()) {
		DeletePointConts (md.vDelete);
		NotifyDependents (FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
		DeleteNamedSetArray (NS_VERTEX, md.vDelete);
	}
	if (md.fDelete.NumberSet()) {
		DeleteNamedSetArray (NS_EDGE, md.fDelete);
		DeleteNamedSetArray (NS_FACE, md.fDelete);
	}
	mdu->LocalDataChanged (partsChanged);
	if (tchange) {
		if (tchange->After()) theHold.Put (tchange);
		else delete tchange;
	}
}

doesn’t seem to do anything extra to make sure mapping and vertex colors are copied


#3

Thanks Klvnk,

But how do I reach EditTriObject class and any functions?
Do I need to implement all source of the EditableMesh from sdk sample?

thanks


#4

I wasn’t really suggesting doing that, as that works and uses the same calls as you then it must be something else you’re doing/not doing that’s causing the issue.

also from meshop.cpp in the mxsagni project

// meshop.attach $.baseobject $sphere02 targetNode:$
// meshop.attach $box01 $box02 attachMat:#IDToMat condenseMat:true deleteSourceNode:false
Value*
meshop_attach_cf(Value** arg_list, int count)
{	
// meshop.attach {<target_node> | <target_mesh>} {<source_node> | <source_mesh>} 
//               targetNode:<target_node> sourceNode:<source_node>
//               attachMat:{#neither | #MatToID | #IDToMat = #neither} condenseMat:<boolean = true>
//               deleteSourceNode:<boolean = true>
// 
	check_arg_count_with_keys(attach, 2, count);
	ReferenceTarget *owner;
	INode *node1, *node2;
	Value *tmp;
	bool sourceInLocalCoords = true;
	Mesh* targetMesh = get_meshForValue(arg_list[0], MESH_BASE_OBJ, &owner, attach);
	if (arg_list[0]->is_kind_of(class_tag(MAXNode)))
		node1 = arg_list[0]->to_node();
	else 
		node1 = node_key_arg(targetNode, tmp, NULL); 
	Mesh* sourceMesh = get_worldMeshForValue(arg_list[1], attach, false);
	if (arg_list[1]->is_kind_of(class_tag(MAXNode))) {
		sourceInLocalCoords = false;
		node2 = arg_list[1]->to_node();
	}
	else 
		node2 = node_key_arg(sourceNode, tmp, NULL); 
	bool bothAreNodes = node1 && node2;
	def_mtl_attach_types();
	int attachMat = GetID(mtlAttachTypes, elements(mtlAttachTypes), key_arg_or_default(attachMat, n_neither));
	BOOL condenseMat = bool_key_arg(condenseMat, tmp, TRUE);
	BOOL deleteSourceNode = bool_key_arg(deleteSourceNode, tmp, TRUE);

	MeshDeltaUser *mdu = (owner) ? GetMeshDeltaUserInterface(owner) : NULL;
	if (mdu && mdu->Editing()) mdu->ExitCommandModes();
	// Combine the materials of the two nodes.
	int mat2Offset=0;
	Mtl *m1 = node1 ? node1->GetMtl() : NULL;
	Mtl *m2 = node2 ? node2->GetMtl() : NULL;
	bool condenseMe = true;
	bool canUndo = true;
	if (bothAreNodes && m1 && m2 && (m1 != m2)) {
		if (attachMat == ATTACHMAT_IDTOMAT) {
			FitMeshIDsToMaterial (*targetMesh, m1);
			FitMeshIDsToMaterial (*sourceMesh, m2);
			if (condenseMat) condenseMe = true;
		}

		// the theHold calls here were a vain attempt to make this all undoable.
		// This should be revisited in the future so we don't have to use the SYSSET_CLEAR_UNDO.
		HoldSuspend theHoldSuspender (TRUE);
		if (attachMat == ATTACHMAT_MATTOID) {
			m1 = FitMaterialToMeshIDs (*targetMesh, m1);
			m2 = FitMaterialToMeshIDs (*sourceMesh, m2);
		}
		Mtl *multi = CombineMaterials(m1, m2, mat2Offset);
		theHoldSuspender.Resume();
		canUndo = false;	// Absolutely cannot undo material combinations.
		if (attachMat == ATTACHMAT_NEITHER) mat2Offset = 0;
		// We can't be in face subobject mode, else we screw up the materials:
		if (mdu) {
			DWORD oldSL = mdu->GetEMeshSelLevel();
			if (oldSL>EM_SL_EDGE) mdu->SetEMeshSelLevel(EM_SL_OBJECT);
			node1->SetMtl(multi);
			if (oldSL>EM_SL_EDGE) mdu->SetEMeshSelLevel(oldSL);
		}
		else
			node1->SetMtl(multi);
		m1 = multi;
	}
	if (bothAreNodes && !m1 && m2) {
		// This material operation seems safe.
		// We can't be in face subobject mode, else we screw up the materials:
		if (mdu) {
			DWORD oldSL = mdu->GetEMeshSelLevel();
			if (oldSL>EM_SL_EDGE) mdu->SetEMeshSelLevel(EM_SL_OBJECT);
			node1->SetMtl(m2);
			if (oldSL>EM_SL_EDGE) mdu->SetEMeshSelLevel(oldSL);
		}
		else
			node1->SetMtl(m2);
		m1 = m2;
	}

	// Construct a transformation that takes a vertex out of the space of
	// the source node and puts it into the space of the destination node.
	// mesh of source is in world space coordinates
	Matrix3 node1tm = node1 ? node1->GetObjectTM(MAXScript_time()) : Matrix3(TRUE);
	Matrix3 node2tm = (sourceInLocalCoords && node2) ? node2->GetObjectTM(MAXScript_time()) : Matrix3(TRUE);
	Matrix3 tm = node2tm * Inverse(node1tm);

	MeshDelta tmd;
	tmd.AttachMesh (*targetMesh, *sourceMesh, tm, mat2Offset);
	if (mdu) 
		GetMeshDeltaUserDataInterface(owner)->ApplyMeshDelta (tmd, mdu, MAXScript_time());
	else {
		tmd.Apply (*targetMesh);
//		DWORD partsChanged = tmd.PartsChanged ();
//		if (partsChanged & PART_TOPO) targetMesh->InvalidateTopologyCache();
//		else if (partsChanged & PART_GEOM) targetMesh->InvalidateGeomCache ();
	}

	if (deleteSourceNode && node2) MAXScript_interface->DeleteNode (node2, FALSE);

	if (m1 && condenseMe) {
		// Following clears undo stack.
		m1 = CondenseMatAssignments (*targetMesh, m1);
	}
	if (!canUndo) {
		theHold.Release();
		HoldSuspend hs (theHold.Holding()); // LAM - 6/13/02 - defect 306957
		MAXScript_interface->FlushUndoBuffer();
	}
	needs_redraw_set();
	return &ok;
}

again it’s not doing anything special to handle mapping and vertex colours