Get VertexData Alpha from a Mesh

csharp

#1

Hello,

I’m trying to get vertices alpha values from a Mesh using 3dsMax SDK (DotNet version).


int VDATA_ALPHA = 2;

// assuming triObj is a valid ITriObject

// check if Vertex Alpha Data is supported
if (!triObj.Mesh.VDataSupport(VDATA_ALPHA))
{
    MaxUtils.MxsLogger("ENABLING SUPPORT ALPHA");
    triObj.Mesh.SetVDataSupport(VDATA_ALPHA, true);

    if (!triObj.Mesh.VDataSupport(VDATA_ALPHA))
        MaxUtils.MxsLogger("UNABLE TO SUPPORT ALPHA");
}

// get an array of float with vertex alpha data values
IntPtr alphaRawValues = triObj.Mesh.VertexFloat(VDATA_ALPHA);

if (alphaRawValues != null && alphaRawValues != IntPtr.Zero)
{ 
    MaxUtils.MxsLogger(alphaRawValues.ToString());                     // print the pointer address
    float[] alphaBytes = new float[triObj.Mesh.NumVerts];
    Marshal.Copy(alphaRawValues, alphaBytes, 0, triObj.Mesh.NumVerts); // fill the float array using values stored at this address
    MaxUtils.MxsLogger("ALPHA VALUES : ");
    foreach (float b in alphaBytes)
    {
        MaxUtils.MxsLogger(b.ToString());
    }
}

I tried this code in 2 differents scenarios, the first one on a Editable_Spline with an Edit Mesh modifier on top of its stack, and the second one on an Editable_Mesh.

Scenario 1 results:

  • Since the mesh is always re-evaluated (the object by reference on the node is a Shape), the alpha data support is always false, and the code needs to re-enable it.
  • The pointer address is always changing, which is understandable too.
  • All values (4 values for a rectangle by example) are equals to 1, no matter if i change Alpha values in the Modify panel.

Scenario 2 results:

  • The support needs to be enabled once.
  • The pointer address doesn’t change.
  • All values are, again, equals to 1.

So what is the way to get this vertex alpha values ?

EDIT

It seems i was looking for at the wrong place. Indeed the Alpha parameter value from Surface Properties panel is not stored in vertex data, but in map channel -2.

What i tried so far :

if (!triObj.Mesh.MapSupport(-2))
{
    MaxUtils.MxsLogger("ENABLING MAP SUPPORT ALPHA");
    triObj.Mesh.SetMapSupport(-2, true);

    if (!triObj.Mesh.MapSupport(-2))
        MaxUtils.MxsLogger("UNABLE TO MAP SUPPORT ALPHA");
}

IMeshMap alphaMap = triObj.Mesh.Map(-2);

if (alphaMap == null)
{
    MaxUtils.MxsLogger("UNABLE TO GET ALPHA MAP");
}
else if (alphaMap.NumVerts > 0)
{
    IPoint3 alphaValues = alphaMap.Tv;
    // ???
}

The weird thing happens here, the Tv properties of my IMeshMap is a IPoint3 instance, instead of an array of values like in the C++ SDK… i even feel like it’s a mistake from Autodesk, regarding the comment above the property :

// Autodesk.Max.IArray of texture vertices. This stores the UVW coordinates for
// the mapping channel. Note: typedef Autodesk.Max.IPoint3 UVVert;

How can I retrieve my values from this property ?

Thank you.


#2

I have finally found a workaround. I always think there’s a mistake in the DotNet wrapper about what kind of data returns the Tv property.

My workaround was to handle my mesh as a IMNMesh instead of IMesh (more functionalities but slower operations).

if (!triObj.Mesh.MapSupport(-2))
    triObj.Mesh.SetMapSupport(-2, true);
IMNMesh mnmesh = MaxInterfaces.Global.MNMesh.Create(triObj.Mesh);
IMNMap alphaMap = mnmesh.M(-2);
if (alphaMap.Numv > 0)
{
    for (int i = 0; i < alphaMap.Numv; i++)
    {
        MaxUtils.MxsLogger(string.Format("Alpha value for vertex {0} : {1}", i.ToString(), alphaMap.V(i).X.ToString()));
    }
}