C++ ReplaceVertexWeight


#1

Anybody can show me how I can replace a vertex weight in my code?

#include <BonesDef.h>
#include <maxscript/macros/define_instantiation_functions.h>

def_visible_primitive(TestFunction, "TestFunction");
Value* TestFunction_cf(Value **arg_list, int count)
{
	Object* bone_Obj = (Object*)GetCOREInterface()->CreateInstance(GEOMOBJECT_CLASS_ID, Class_ID(SPHERE_CLASS_ID, 0));
	IParamBlock2* bone_ParamBlock = (IParamBlock2*)bone_Obj->GetReference(0);
	bone_ParamBlock->SetValue(SPHERE_RADIUS, 0, (float)5);
	bone_ParamBlock->SetValue(SPHERE_SEGS, 0, 6);
	INode* bone_Node = GetCOREInterface()->CreateObjectNode(bone_Obj);

	Object* mesh_Obj = (Object*)GetCOREInterface()->CreateInstance(GEOMOBJECT_CLASS_ID, PLANE_CLASS_ID);
	IParamBlock2* mesh_ParamBlock = (IParamBlock2*)mesh_Obj->GetReference(0);
	mesh_ParamBlock->SetValue(0, 0, (float)10);
	mesh_ParamBlock->SetValue(1, 0, (float)10);
	INode* mesh_Node = GetCOREInterface()->CreateObjectNode(mesh_Obj);

	Modifier* skin = (Modifier*)GetCOREInterface()->CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
	GetCOREInterface17()->AddModifier(*mesh_Node, *skin);

	ISkin* iSkin = (ISkin*)skin->GetInterface(I_SKIN);
	BonesDefMod* bonesDefMod = (BonesDefMod*)iSkin;
	bonesDefMod->AddBoneEx(bone_Node, 1);
	
	//ReplaceVertexWeight?

	return &ok;
}

#2

we have already shown you in other posts that this is not right…

you should decide what to use ISkin interfaces or BonesDefMod methods. You don’t need bothю Usually, one thing is enough.


#3

Well, which one you prefer? I saw skinops used BonesDef, But about ISkin, I’m not sure it has all functions. for example removebone. Actually I’m looking for the efficient method. Also I’m trying to get rid of functions that only works if modifiy panel is active. What you think?


#4

BonesDef methods work only if the Modifier Panel is opened on the Skin modifier. My goal always was to do skin operations without modifier panel and node selection. that’s why i use ISkin interfaces

ISkin interfaces don’t provide all methods which BonesDef can do. But there is nothing what ISkin can but BonesDef can not.

Did i answer your question?

PS.
BonesDef methods usually expect UI update and redraw, and send notification messages for it, including cases when it’s not necessary.


#5

So it seems ISkin is better, but as I said how we can implement functions like removebone with ISkin? Any library or sample in SDK?


#6

the same way as they do it in BonesDef. The code is there… the only problem is do update of BonesDef local data after that.


#7

I’m just trying to do it with ISkin:

#include <BonesDef.h>
#include <modstack.h>
#include <maxscript/macros/define_instantiation_functions.h>

def_visible_primitive(TestFunction, "TestFunction");
Value* TestFunction_cf(Value **arg_list, int count)
{
	int boneCount = 2;

	// Mesh

	Object* mesh_Obj = (Object*)GetCOREInterface()->CreateInstance(GEOMOBJECT_CLASS_ID, PLANE_CLASS_ID);
	IParamBlock2* mesh_ParamBlock = (IParamBlock2*)mesh_Obj->GetReference(0);
	mesh_ParamBlock->SetValue(0, 0, (float)10);
	mesh_ParamBlock->SetValue(1, 0, (float)10);
	INode* mesh_Node = GetCOREInterface()->CreateObjectNode(mesh_Obj);

	// Bones

	Tab<INode*> bones; bones.SetCount(boneCount);
	for (size_t i = 0; i < boneCount; i++)
	{
		Object* object = (Object*)GetCOREInterface()->CreateInstance(GEOMOBJECT_CLASS_ID, Class_ID(SPHERE_CLASS_ID, 0));
		IParamBlock2* paramBlock = (IParamBlock2*)object->GetReference(0);
		paramBlock->SetValue(SPHERE_RADIUS, 0, (float)5);
		paramBlock->SetValue(SPHERE_SEGS, 0, 6);
		INode* node = GetCOREInterface()->CreateObjectNode(object);
		bones[i] = node;
	}

	// Skin Modifier

	Modifier *skinModifier = (Modifier*)CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
	IDerivedObject* derivedObject = CreateDerivedObject(mesh_Obj);
	mesh_Node->SetObjectRef(derivedObject);
	derivedObject->SetAFlag(A_LOCK_TARGET);
	derivedObject->AddModifier(skinModifier);
	derivedObject->ClearAFlag(A_LOCK_TARGET);

	// Add Bones

	ISkinImportData* iSkinImportData = (ISkinImportData*)skinModifier->GetInterface(I_SKINIMPORTDATA);
	for (size_t i = 0; i < boneCount; i++)
	{
		iSkinImportData->AddBoneEx(bones[i], i - 1 == boneCount);
	}

	// Replace Weights

	ISkin* iSkin = static_cast<ISkin*>(skinModifier->GetInterface(I_SKIN));
	ISkinContextData* iSkinContextData = iSkin->GetContextInterface(mesh_Node);
	//int vertexCount = iSkinContextData->GetNumPoints();

	Tab<float>weights; weights.SetCount(boneCount);
	weights[0] = 0.1f;
	weights[1] = 0.9f;
	iSkinImportData->AddWeights(mesh_Node, 1, bones, weights);

	return &ok;
}
`indent preformatted text by 4 spaces`

But It doesn’t change any vertex data at all. Also if I uncomment the line:
//int vertexCount = iSkinContextData->GetNumPoints();
I will get several errors.


#8

I just realized that the problem is not from the skin data, When I apply the function to the existing modifier in the scene, its work:

#include <BonesDef.h>
#include <modstack.h>
#include <maxscript/macros/define_instantiation_functions.h>

def_visible_primitive(TestFunction, "TestFunction");
Value* TestFunction_cf(Value **arg_list, int count)
{
	INode* skinNode = arg_list[0]->to_node();
	Modifier* modifier = arg_list[1]->to_modifier();
	ISkin* iSkin = (ISkin*)modifier->GetInterface(I_SKIN);
	BonesDefMod* bonesDefMod = (BonesDefMod*)iSkin;
	BoneModData *boneModData = bonesDefMod->GetBMD(skinNode);
	boneModData->GetNumPoints();

	return &ok;
}

#9

Do I need to update something after object creation?


#10

you do realize that ^^^ is nonsense to anyone else, you may as well post maxscript that uses custom functions great if you want to have a conversation with yourself :smiley:


#11

Sorry, I don’t undrstand what are you talking about, what is ^^^ ?


#12

^^^^^ just means up there you know the code you posted up there ^^^^^ is useless to anyone else as it’s non compilable nonsense.


#13

Ok, but my assumption was someone that has build environment (like you!) Can compile the code easily. Also I’m sure for someone that has expreince in this field (again like you! Or Denis) makes sense even just by looking at the code.
Anyway, my goal is to translate some parts of my maxscript code to cpp. And I started from skin functions which I’m sure can be faster.


#14

I want to share my opinion on why we need the mechanism “mxs function publishing”.
At a certain point, many tools developers (3DS MAX in particular) are wondering whether to stay with the scripts or switch to c ++ sdk.

So, if you have started to actively use “function publishing”, it just says that you stay with the scripts. And this, in my opinion, is the most effective and productive method of 3ds max tools development.

In your code, I see that you include c++ methods that do not give you any advantages over mxs (for example, creating nodes and objects).


#15

here is how your task with skinned plane might look in my framework with my mxs extension:

(
	node = plane width:x length:y widthsegs:xs lengthsegs:ys
	node = converttopoly n
	sk = skin()
	addmodifier node sk
	pp = getpointpositions node
	bones = for p in pp collect (sphere radius:r pos:p)
	addskinbone sk bones 
	sk_data = getskindata sk
	normalizeSkinWeights sk_data verts:#all neighbors:2 type:#linear 
	setskindata sk sk_data update:on
)

published functions are:

getPointPositions – get point positions of any deformable object in a specified coordinate system
addSkinBone – adds bone(s) without node and/or modifier selection
getSkinData – collect both skin and mesh data with information about skin and mesh geometry(topology)
normalizeSkinWeights – smooth and normalize skin data based on mesh(neighbors) or geometry distance
setSkinData – sets skin data to the skin (like a replace weights)

everything else can be simply done with mxs


#16

Yes, Exactly! Thank You!

Actually I wanted to explore the SDK world a little bit more to know how the mechanism works. For example what is the node, object, drived object, modcontext and relationship between them. That’s why I created all in C++. But You right, I should skip the unnecessary parts.


#17

Nice!, So you completely get the skin data and set it back after modification right? what is the data type of skin data? c++ class or max’s structure or just some arrays?
Another side question is why you converted the mesh to poly? where it might help?


#18

very clever questions. I will be happy to answer them …

let’s start with the second.
poly vs mesh is a more organized system, it gives an advantage in finding vertex neighbors, edge rings / loops, in-between face, edge, vertex conversions. it helps a lot during advanced skin weights operations (smooth, blend, average, contrast, etc.) and advanced selection.
the skin modifier itself uses mesh local data which is more close to poly structures

i store skin data in my mxs published class which doesn’t use script memory and provides quick (c++) methods to work with.