C++ Skin

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

 
Thread Tools Display Modes
  3 Weeks Ago
C++ Skin

Any body can show me a C++ function-example how I can remove a bone from a skin modifier? I can't see any built-in functions like skinops.
__________________
http://3dcutout.com/

Last edited by MZ : 3 Weeks Ago at 03:27 PM.
 
  3 Weeks Ago
could try something like....


#include ..\...\maxsdk\samples\modifiers\bonesdef\bonesdef.  h

Modifier *mod = //what ever method you are using to acquire the skin mod
if(mod->ClassID() == Class_ID(9815843,87654))
{   
    BonesDefMod *bmod = (BonesDefMod*)mod;
   bmod->RemoveBone(boneID); // you test that boneid is within the correct range etc
  bmod->NotifyDependents(FOREVER, GEOM_CHANNEL, REFMSG_CHANGE);
  bmod->ip->RedrawViews(bmod->ip->GetTime());
}
 
  3 Weeks Ago
Originally Posted by Klvnk: could try something like....


#include ..\...\maxsdk\samples\modifiers\bonesdef\bonesdef.  h

Modifier *mod = //what ever method you are using to acquire the skin mod
if(mod->ClassID() == Class_ID(9815843,87654))
{   
    BonesDefMod *bmod = (BonesDefMod*)mod;
   bmod->RemoveBone(boneID); // you test that boneid is within the correct range etc
  bmod->NotifyDependents(FOREVER, GEOM_CHANNEL, REFMSG_CHANGE);
  bmod->ip->RedrawViews(bmod->ip->GetTime());
}

This is my code that is a function to remove unused bones:


#include <maxscript/maxscript.h>
#include <maxscript/foundation/3dmath.h>
#include <maxscript/macros/define_instantiation_functions.h>
#include "iskin.h"
#include "bonesdef.h"
def_visible_primitive(RemoveUnusedBones, "RemoveUnusedBones");
Value* RemoveUnusedBones_cf(Value **arg_list, int count)
{
   INode* node = arg_list[0]->to_node();
   Modifier* modifier = arg_list[1]->to_modifier();
   ISkin* skin = (ISkin *)modifier->GetInterface(I_SKIN);
   BonesDefMod* bkin = (BonesDefMod*)skin;
   ISkinContextData *skinData = skin->GetContextInterface(node);
   BitArray usedbones = BitArray(skin->GetNumBones());
   for (int i = 0; i < skinData->GetNumPoints(); i++)
   {
      for (int j = 0; j < skinData->GetNumAssignedBones(i); j++)
      {
         int boneIndex = skinData->GetAssignedBone(i, j);
         float boneWeight = skinData->GetBoneWeight(i, j);
         if (boneWeight > 0) usedbones.Set(boneIndex);
      }
   }
   for (int i = usedbones.GetSize(); i < 0; i--)
   {
      if (usedbones[i] == 0) bkin->RemoveBone(i);
   }
   return new BitArrayValue(usedbones);
}


This should work, right? But I got several errors:



Do you see any error in the code? or you think errors comes from build environment and project setting? Note that when I open bonesdef project, I got .Net version error.
__________________
http://3dcutout.com/
 
  2 Weeks Ago
what you could do is add your function to skinops in the CommandModes.cpp file of the bonesdef modifier project then recompile the project to replace the current skin etc Otherwize you'll need to create a pared back bonesdef.h for it to work "independently"

Last edited by Klvnk : 2 Weeks Ago at 10:43 AM.
 
  2 Weeks Ago
Originally Posted by Klvnk: what you could do is add your function to skinops in the CommandModes.cpp file of the bonesdef modifier project then recompile the project to replace the current skin etc Otherwize you'll need to create a pared back bonesdef.h for it to work "independently"
So my questions are:
1 - Where the MS function "skinOps" in the SDK? Is itbonesdef? I mean Skinops is created by usingbonesdef.h?
2 - How I can "pared back" thebonesdef.h?
3 - Again, do you think the code itself works correctly?
4 - I think I installed every SDK requirements, but I got this error when I want to openbonesdef.h:

F:\Software\3dsMax\SDK\3ds Max 2018 SDK\maxsdk\samples\render\NotificationSystem\Notif icationSystem.vcxproj : error : A numeric comparison was attempted on "$(_TargetFrameworkVersionWithoutV)" that evaluates to "V4.6" instead of a number, in condition "'$(ImplicitlyExpandNETStandardFacades)' == '' AND '$(_TargetFrameworkVersionWithoutV)' >= '4.6.1'". C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\Microsoft. NET.Build.Extensions\Microsoft.NET.Build.Extension s.NETFramework.targets

I removed all .Net versions from my computer, then I installed several versions until 4.6 , but I still get the error. my build information is:
Windows 7
Max 2018
VS 2017
Latest Windows 10 SDk installed
__________________
http://3dcutout.com/
 
  2 Weeks Ago
1 - Where the MS function "skinOps" in the SDK? Is itbonesdef?

as I said above the code for skinops is in CommandModes.cpp file of the bonesdef modifier project, add your function there copying the methods used by the other function recompile the project and your function will be available to mxs
 
  2 Weeks Ago
Do you think we can use this?

macroRecorder->FunctionCall(_T("skinOps.removeBone"), 2, 0, mr_reftarg, skin, mr_int, boneID + 1);
__________________
http://3dcutout.com/

Last edited by MZ : 2 Weeks Ago at 09:43 PM.
 
  2 Weeks Ago
if you want to ? surely if you want to take that route you may as well do it all in mxs.
 
  2 Weeks Ago
Originally Posted by Klvnk: if you want to ? surely if you want to take that route you may as well do it all in mxs.
I want to use c++ because of speed. do you think calling MS in C++ is not efficient? I saw many examples in SDK that used macro. Apart from the checking the macro, side problem is that this function doesn't do the job in MaxScript:

#include <maxscript/maxscript.h>
#include <maxscript/foundation/3dmath.h>
#include <maxscript/macros/define_instantiation_functions.h>
#include "iskin.h"
#include "modstack.h"
#include "macrorec.h"
#include "maxscript/util/listener.h"

def_visible_primitive(RemoveUnusedBones, "RemoveUnusedBones");
Value* RemoveUnusedBones_cf(Value **arg_list, int count)
{
 INode* node = arg_list[0]->to_node();
 Modifier* modifier = arg_list[1]->to_modifier();
 
 Interface* core = GetCOREInterface();
 TimeValue t = core->GetTime();
 Object *obj = node->GetObjectRef()->Eval(t).obj;
 IDerivedObject *drivedObj = CreateDerivedObject(obj);
 ISkin* skin = (ISkin *)modifier->GetInterface(I_SKIN);
 ISkinContextData *skinData = skin->GetContextInterface(node);
 BitArray usedbones = BitArray(skin->GetNumBones());

 for (int i = 0; i < skinData->GetNumPoints(); i++)
 {
  for (int j = 0; j < skinData->GetNumAssignedBones(i); j++)
  {
   int boneIndex = skinData->GetAssignedBone(i, j);
   float boneWeight = skinData->GetBoneWeight(i, j);
   if (boneWeight > 0) usedbones.Set(boneIndex);
  }
 }
 for (int i = usedbones.GetSize(); i > 0; i--)
 {
  //if (usedbones[i] != 1)
  //{
   macroRecorder->FunctionCall(_T("skinOps.selectBone"), 2, 0, mr_reftarg, skin, mr_int, i + 1);
   macroRecorder->FunctionCall(_T("skinOps.removeBone"), 2, 0, mr_reftarg, skin, mr_int, i + 1);
  //}
 }

 drivedObj->NotifyDependents(FOREVER, GEOM_CHANNEL, REFMSG_CHANGE);
 core->RedrawViews(t);

 return &ok;
}
__________________
http://3dcutout.com/

Last edited by MZ : 2 Weeks Ago at 11:31 AM.
 
  1 Week Ago
Originally Posted by Klvnk: what you could do is add your function to skinops in the CommandModes.cpp file of the bonesdef modifier project then recompile the project to replace the current skin etc Otherwize you'll need to create a pared back bonesdef.h for it to work "independently"
After struggling with SDK requirements and installing VS 2015, I just added my following code to the "bonesdef" project and now I can compiled it, I replaced MaxFolder/Stdplugs/bonesdef.dlm with my code and now my function works perfectly in max.


#include "mods.h"
#include "bonesdef.h"
#include <maxscript/macros/define_instantiation_functions.h>
#include "modstack.h"

Modifier* FindSkinModifier(INode* nodePtr)
{
 Object* ObjectPtr = nodePtr->GetObjectRef();
 if (!ObjectPtr) return NULL;
 while (ObjectPtr && ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
 {
  IDerivedObject *DerivedObjectPtr = (IDerivedObject *)(ObjectPtr);
  int ModStackIndex = 0;
  while (ModStackIndex < DerivedObjectPtr->NumModifiers())
  {
   Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex);
   if (ModifierPtr->ClassID() == Class_ID(SKIN_CLASSID)) 
   {
    return ModifierPtr;
   }
   ModStackIndex++;
  }
  ObjectPtr = DerivedObjectPtr->GetObjRef();
 }
 return NULL;
}

void RecursiveRemoveUnusedBones(INode* node)
{
 Modifier* skin = FindSkinModifier(node);
 if (skin)
 {
  ISkin* iskin = (ISkin *)skin->GetInterface(I_SKIN);
  BonesDefMod* bmod = (BonesDefMod*)iskin;
  ISkinContextData *skinData = iskin->GetContextInterface(node);
  BitArray usedbones = BitArray(iskin->GetNumBones());
  for (int i = 0; i < skinData->GetNumPoints(); i++)
  {
   for (int j = 0; j < skinData->GetNumAssignedBones(i); j++)
   {
    int boneIndex = skinData->GetAssignedBone(i, j);
    float boneWeight = skinData->GetBoneWeight(i, j);
    if (boneWeight > 0) usedbones.Set(boneIndex);
   }
  }
  for (int i = usedbones.GetSize(); i >= 0; i--)
  {
   if (usedbones[i] != 1) bmod->RemoveBone(i);
  }
 }

 for (int i = 0; i < node->NumberOfChildren(); ++i)
 {
  RecursiveRemoveUnusedBones(node->GetChildNode(i));
 }
}

def_visible_primitive(RemoveUnusedBones, "RemoveUnusedBones");
Value* RemoveUnusedBones_cf(Value **arg_list, int count)
{
 RecursiveRemoveUnusedBones(GetCOREInterface()->GetRootNode());
 return &ok;
}

Now my question is how I can make the independent version?
__________________
http://3dcutout.com/

Last edited by MZ : 1 Week Ago at 11:17 AM.
 
  1 Week Ago
Yes, just change the classID of the modifier to something different, and your plugin will register independently from the built-in one (so long as you don't replace/delete the original plugin file like you did).

3dsmax keeps track of which plugin is which through classIDs alone. Make sure you search the project files for all instances of any classIDs being registered, since some projects contain more than one registered class, and if max detects any duplicate IDs on launch it will generate an error.

The classID values are just random numbers and can be anything, so long as they are not duplicates of another plugin's values.
__________________
http://www.tysonibele.com
 
  1 Week Ago
Originally Posted by ivanisavich: Yes, just change the classID of the modifier to something different, and your plugin will register independently from the built-in one (so long as you don't replace/delete the original plugin file like you did).

3dsmax keeps track of which plugin is which through classIDs alone. Make sure you search the project files for all instances of any classIDs being registered, since some projects contain more than one registered class, and if max detects any duplicate IDs on launch it will generate an error.

The classID values are just random numbers and can be anything, so long as they are not duplicates of another plugin's values.
Would you please explain more? I just want to expose a function to the MaxScript, I don't want to create any new class (modifier?), my thought was we don't need to generate ClassID for the function publishing pipeline. actually my question was how we can include-use bonesdef methods out of the bonesdef project.
__________________
http://3dcutout.com/
 
  1 Week Ago
Oh I thought you wanted to branch the sample plugin code into your own plugin, and have them both load.
__________________
http://www.tysonibele.com
 
  1 Week Ago
Originally Posted by ivanisavich: Oh I thought you wanted to branch the sample plugin code into your own plugin, and have them both load.
The only problem is how to include skin functions in my project.
__________________
http://3dcutout.com/
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 08:57 AM.


Powered by vBulletin
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.