Message 1 of 1
Accessing the Skin modifier and removing vertex weights

Not applicable
08-19-2009
12:50 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hey folks,
my question is this, I've written a little utility that allows me to view the associated vertex weights on a mesh (see included code). The problem is, I can't see any way to change vertex weights or actually remove a weight. for instance, a vertex has one too many weights assoicated with it and I'd like to drop the one with the least influence and then re-normalize. Am I missing something here? Neither ISkin nor ISkinContextData provide interfaces for doing this. And I'd rather not use maxscript for this.
my question is this, I've written a little utility that allows me to view the associated vertex weights on a mesh (see included code). The problem is, I can't see any way to change vertex weights or actually remove a weight. for instance, a vertex has one too many weights assoicated with it and I'd like to drop the one with the least influence and then re-normalize. Am I missing something here? Neither ISkin nor ISkinContextData provide interfaces for doing this. And I'd rather not use maxscript for this.
// Maxscript function for checking the vertex weights on a given skin
// arg_list: expecting the iNode of the mesh to check as well as the skin modifier to use
// returns: success or failure
// Example: CheckVertexWeights $ $.modifiers maxWeightPerVertexCount
// CheckVertexWeights $ $.modifiers 2
Value* CheckVertexWeights_cf(Value** arg_list, int count)
{
check_arg_count(CheckVertexWeights, 3, count)
type_check( arg_list, MAXNode, "CheckVertexWeights ")
type_check( arg_list, MAXModifier, "CheckVertexWeights ")
type_check( arg_list, Integer, "CheckVertexWeights ")
Interface *ip = GetCOREInterface()
// Get the mesh for the first parameter
INode* skinObj = (INode*)arg_list->to_node()
if ( skinObj == NULL )
{
mprintf("Alert: unable to convert the first parameter to a INode!\n" )
return NULL;
}
// convert the second parameter to an ISkin interface
Modifier* baseMod = arg_list->to_modifier()
if ( baseMod == NULL )
{
mprintf("Alert: unable to convert the second parameter to a Modifier!\n" )
return NULL;
}
// convert the third parameter to a number
int maximumWeightCount = arg_list->to_int()
// populate the data that we'll be using
ISkin* skinMod = (ISkin*)baseMod->GetInterface(I_SKIN)
if ( skinMod == NULL )
{
mprintf("Alert: unable to convert the second parameter to a Skin Modifier!\n" )
return NULL;
}
ISkinContextData* skinData = skinMod->GetContextInterface(skinObj)
if ( skinData == NULL )
{
mprintf("Alert: unable to access the skin data!\n" )
return NULL;
}
Tab<BoneData*> boneList;
// First off, generate an list to hold our 'bones'
int boneCount = skinMod->GetNumBones()
int mapIDCounter = 0;
for ( int index = 0; index < boneCount; ++index )
{
INode* node = skinMod->GetBone(index)
BoneData* data = new BoneData()
data->node = node;
TSTR name;
name.printf( "%s", node->GetName() )
data->SetOriginalName( name )
mprintf( "%s,", name.data() )
data->mapID = mapIDCounter++;
data->subID = -50;
boneList.Append( 1, &data )
}
mprintf("\n")
// Next look at all the vertices this skin modifier
int numberofPoints = skinData->GetNumPoints()
for ( int vertexIndex =0; vertexIndex < numberofPoints; ++vertexIndex )
{
int numberofWeights = skinData->GetNumAssignedBones(vertexIndex)
if ( numberofWeights >= maximumWeightCount )
{
mprintf("%d vertex has too many weights assigned to it!\n", vertexIndex )
Tab<VertexWeightData*> vertexWeightTable;
//mprintf("Vertex Data: vertexIndex: %d, number of Weights: %d \n", vertexIndex, numberofWeights)
for ( int weightIndex = 0; weightIndex < numberofWeights; ++weightIndex )
{
int boneIndex = skinData->GetAssignedBone(vertexIndex, weightIndex)
float boneWeight = skinData->GetBoneWeight(vertexIndex, weightIndex)
//mprintf("\t\tweightIndex: %d bone: %d, weight: %f\n", weightIndex, boneIndex, boneWeight)
VertexWeightData* weightData = new VertexWeightData()
weightData->boneIndex = boneIndex;
weightData->vertexIndex = vertexIndex;
weightData->weight = boneWeight;
if ( vertexWeightTable.Count() == 0 )
{
vertexWeightTable.Append(1, &weightData)
}
else
{
int location = 0;
for ( ; location < vertexWeightTable.Count() ++location)
{
if ( vertexWeightTable->weight < weightData->weight)
{
vertexWeightTable.Insert(location, 1, &weightData )
break;
}
}
if ( location >= vertexWeightTable.Count() )
{
vertexWeightTable.Append(1, &weightData)
}
}
}
// print out the weight table
mprintf("Vertex Weights for pruning\n")
for (int index = maximumWeightCount; index < vertexWeightTable.Count() ++index)
{
mprintf("\tbone: index Weight: %f\n", boneList->boneIndex]->GetDisplayName(), vertexWeightTable->boneIndex, vertexWeightTable->weight)
INode* boneNode = skinMod->GetBone(vertexWeightTable->boneIndex)
Object *obj = boneNode->GetObjectRef()
Class_ID id = obj->ClassID()
if ( id == BONE_OBJ_CLASSID )
{
if ( boneNode == NULL )
{
mprintf("Can't find bone!\n")
}
}
}
// Re-normalize what's left
}
}
return NULL;
}