[Closed] The Quick 'n' Dirty Way to extend MXS with the SDK
requirements…
3ds max
sdk installed for the max version you want to extend for
[and the correct version of microsoft visual studio]( http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__files_GUID_6E179A56_5552_4D0B_BA61_BBD37B9E52DB_htm)
1. go to \Autodesk\<max version> SDK\maxsdk\samples\maxscript\mxsagni
2. double click on mxsagni.vcproj this should open the mxsagni project in visual studio
3. in the solution configurations drop down in the main toobar select [b]Release [/b]from the menu (should be displaying Debug when you start) if you doing a x64 build you'll need to change Solution Platforms dropdown from Win32 to x64.
4. From the solution explorer/Source Files open the file avg_DLX.cpp
5. Copy the following Code
def_visible_primitive(MtlPreviewToBitmap, "MtlPreviewToBitmap");
Value* MtlPreviewToBitmap_cf(Value** arg_list, int count)
{
check_arg_count(MtlPreviewToBitmap, 2, count);
MtlBase* mb = arg_list[0]->to_mtlbase();
int sz = arg_list[1]->to_int();
PStamp *ps = mb->CreatePStamp(sz,1);
if(ps)
{
int d = PSDIM(sz);
int scanw = ByteWidth(d);
int nb = scanw*d;
UBYTE *buf = new UBYTE[nb + sizeof(BITMAPINFOHEADER)];
if(!buf)
&undefined;
// get the image data
ps->GetImage(&buf[sizeof(BITMAPINFOHEADER)]);
// and create the header info
BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)buf;
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biWidth = d;
bih->biHeight = d;
bih->biPlanes = 1;
bih->biBitCount = 24;
bih->biCompression = BI_RGB;
bih->biSizeImage = 0;
Bitmap *map = TheManager->Create((PBITMAPINFO)buf);
delete [] buf;
if(map)
{
one_typed_value_local(MAXBitMap* mbm);
vl.mbm = new MAXBitMap();
vl.mbm->bi.CopyImageInfo(&map->Storage()->bi);
vl.mbm->bi.SetFirstFrame(0);
vl.mbm->bi.SetLastFrame(0);
vl.mbm->bi.SetName("");
vl.mbm->bi.SetDevice("");
if(vl.mbm->bi.Type() > BMM_TRUE_64)
vl.mbm->bi.SetType(BMM_TRUE_64);
vl.mbm->bm = map;
return_value(vl.mbm);
}
}
return &undefined;
}
or other more useful bits of code just before other stuff can be found here
// =================================================
// Spline methods
// =================================================
6. press F7 to build the solution
7. if the Output window displays the following all is good
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Otherwise there are compiler issues, eg a coding syntax error or linker errors.
8. goto the folder Autodesk<Max Version> SDK\exe\stdplugs and copy the file MXSAgni.dlx to \Autodesk<Max Version>\stdplugs. You can back up the original or rename it to MXSAgni.bak or something.
9. restart max
10. run the following from the MXS listener.
display (MtlPreviewToBitmap (getMeditMaterial 1) 0)
11. remember to add [b]MXSAgni.dlx [/b]to any redistributables.
Klvnk, thank you! I will try this! Shouldn’t you use smth like loadscript, filin or smth like this?
the best extending functions by a country mile are
def_struct_primitive(polyop_getMapVertsUsingVert, polyop, "getMapVertsUsingVert");
// <bitarray> polyop.getMapVertsUsingVert <Poly poly> <int mapChannel> <vertlist>
Value* polyop_getMapVertsUsingVert_cf(Value** arg_list, int arg_count)
{
// the usual arg check
check_arg_count(getMapVertsUsingVert, 3, arg_count);
// get the poly mesh
MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getMapVertsUsingVert);
int channel = arg_list[1]->to_int();
checkMapChannel(pmesh,channel);
// ok to access the map
MNMap* map = pmesh->M(channel);
int nVerts = pmesh->numv;
int nMapVerts = map->numv;
int nMapFaces = map->numf;
// create a new bitarray from input which could be a bitarray, int or array of ints
BitArray verts(nVerts);
ValueToBitArray(arg_list[2], verts, nVerts, GetString(IDS_VERTEX_INDEX_OUT_OF_RANGE));
// create the return bitarray variable on the stack
one_typed_value_local(BitArrayValue* mapVerts);
vl.mapVerts = new BitArrayValue(nMapVerts);
for(int f=0; f < nMapFaces; f++)
{
MNFace* face = pmesh->F(f);
// skip over dead faces
if(face->GetFlag(MN_DEAD))
continue;
MNMapFace* mapface = map->F(f);
for(int j=0; j < face->deg; j++)
{
if(verts[face->vtx[j]])
{
vl.mapVerts->bits.Set(mapface->tv[j]);
break; // should only be one per face
}
}
}
return_value(vl.mapVerts);
}
and the mesh varient
//********************************************************************************************
// meshop.getMapVertsUsingVert
//<bitarray mapverts> meshop.getMapVertsUsingVert <Mesh mesh\> <int mapChannel> <int vert>
def_struct_primitive(meshop_getMapVertsUsingVert, meshop, "getMapVertsUsingVert");
Value* meshop_getMapVertsUsingVert_cf(Value **arg_list, int count)
{
check_arg_count(getMapVertsUsingVert, 3, count);
// mesh
Mesh* mesh = get_meshForValue(arg_list[0], MESH_READ_ACCESS, NULL, getMapVertsUsingVert);
// channel
int mapChannel = arg_list[1]->to_int();
range_check(mapChannel, -NUM_HIDDENMAPS, MAX_MESHMAPS-1, GetString(IDS_MESH_MAP_CHANNEL_OUT_OF_RANGE));
if(!mesh->mapSupport(mapChannel))
throw RuntimeError (GetString(IDS_MAP_SUPPORT_NOT_ENABLED_FOR_CHANNEL), Integer::intern(mapChannel));
// vert
int vert = arg_list[2]->to_int() - 1; // mxs to sdk
range_check(vert,0,(mesh->numVerts - 1), GetString(IDS_VERTEX_INDEX_OUT_OF_RANGE));
// create the return bitarray variable on the stack
one_typed_value_local(BitArrayValue* mapVerts);
vl.mapVerts = new BitArrayValue(mesh->getNumMapVerts(mapChannel));
// get the pointer to the map faces
TVFace* mapfaces = mesh->mapFaces(mapChannel);
// for all the faces, find our vert, and tag the same "corner" in the map face
int nfaces = mesh->numFaces;
for(int i = 0; i < nfaces; ++i)
{
Face& geoface = mesh->faces[i]; //
for(int j=0; j < 3; ++j)
{
if(geoface.v[j] == vert)
{
vl.mapVerts->bits.Set(mapfaces[i].t[j]);
break; // should only be one per face
}
}
}
return_value(vl.mapVerts);
}
Is there a way to return the collection of BitArrayValues? Say if I’d like to get all the mesh elements as an array of bitarrays. Is it even possible?
Thanks
upd Found the answer in this incredible thread. Thank you guys!