c# get vertex paint modifier

c# get vertex paint modifier

R.o.b.D
Participant Participant
1,716 Views
9 Replies
Message 1 of 10

c# get vertex paint modifier

R.o.b.D
Participant
Participant

I'm investigating using c# vs. maxscript or maxplus

As a test I'm trying to set vertex colors  using the VertexPaint modifier, would like to achieve a less destructive workflow than collapsing stacks and setting color values etc.

 

So far I've either got the existing modifier from the stack
dObj = (IIDerivedObject)obj;

IModifier tMod = dObj.GetModifier(0);

 

or added one

IModifier tMod = (IModifier)ip.CreateInstance(SClass_ID.Osm, global.Class_ID.Create(0x7ebb4645, 0x7be2044b)); // PAINTLAYERMOD_CLASS_ID
dObj.AddModifier(tMod, null, 0);

 

but when I try and cast the modifier

IIVertexPaint vp = (IIVertexPaint)tMod.GetInterface(global.Interface_ID.Create(0x3e262ef9, 0x220e7190)); // IVERTEXPAINT_INTERFACE_ID

 

I get ..

System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>

 

Can anyone help with what I'm doing wrong ?

Any help appreciated, thanks.

0 Likes
1,717 Views
9 Replies
Replies (9)
Message 2 of 10

R.o.b.D
Participant
Participant

tried something slightly different but still no success

IObject obj = node.ObjectRef;
IIDerivedObject dObj = (IIDerivedObject)obj;
IModifier tMod = dObj.GetModifier(0);
IIVertexPaint vp = global.IVertexPaint.Marshal(tMod.NativePointer) as IIVertexPaint;

any suggestions ?

0 Likes
Message 3 of 10

denisT.MaxDoctor
Advisor
Advisor

it should be simple as:

    public class IPaint
    {
        private static readonly IClass_ID PAINTLAYERMOD_CLASS_ID = GlobalInterface.Instance.Class_ID.Create(0x7ebb4645, 0x7be2044b);
        private static readonly IInterface_ID IVERTEXPAINT_INTERFACE_ID = GlobalInterface.Instance.Interface_ID.Create(0x3e262ef9, 0x220e7190);

        void Test()
        {
            IModifier vpMod = (IModifier)GlobalInterface.Instance.COREInterface.CreateInstance(SClass_ID.Osm, PAINTLAYERMOD_CLASS_ID);
            IIVertexPaint vp = (IIVertexPaint)vpMod.GetInterface(IVERTEXPAINT_INTERFACE_ID);
        }
    }

it works for me... how do you get a derived object from stack?

 

but it might be some maxplus casting problem ... look at similar issue and solution. it might help: Autodesk.Max.Wrappers

 

0 Likes
Message 4 of 10

R.o.b.D
Participant
Participant

Hi @denisT.MaxDoctor 

 

I've tried your example, creating the IModifier works fine but I still get the same error when casting to the IIVertexPaint interface.

Should mention I'm using 2018.4 just in case.

 

System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>

 

I've been trying either creating a new VP modifier and adding to stack or accessing an existing one on the stack which is why I had the derived object.

 

I had seen the other example in the post but thought I'd read in the help docs (can't currently find unfortunately) not to reference the wrapper assembly directly. But had found ... global.IVertexPaint.Marshal(tMod.NativePointer) as IIVertexPaint  ... the marshal as apart of IVertexPaint but had no success.

0 Likes
Message 5 of 10

kevinvandecar
Community Manager
Community Manager

Hi Guys,

I explored this a bit and think I have the solution to get the interface object...

object objMod = coreInterface.CreateInstance(SClass_ID.Osm, PAINTLAYERMOD_CLASS_ID);
IModifier mod = (IModifier)objMod;
dobj.AddModifier(mod, null, 0); // top of stack
node.ObjectRef = dobj;

IBaseInterface bi = mod.GetInterface(IVERTEXPAINT_INTERFACE_ID);
IIVertexPaint vp = global.IVertexPaint.Marshal(bi.NativePointer) as IIVertexPaint;

Once the interface object is set, then the methods can be called. But I do not have enough experience with this (even on C++ side) to know how it should work. The UI seems to have a number of other options than what the interface class has. For example, this executes, but not sure it succeeded to set appropriate parameters:

Autodesk.Max.IAssignVertexColors.IOptions vc = GlobalInterface.Instance.IAssignVertexColors.Options.Create();
vc.LightingModel = Autodesk.Max.LightingModel.LightingModel.ShadedLighting;
vc.UseMaps = false;
vc.MixVertColors = true;
vp.SetOptions(vc);

Then I was not able to figure out the correct way to set the color array using the ITab<IColor>. For example, this causes 3ds Max to crash, but not sure if it is setup correctly.

ITab<IColor> vertColors = global.Tab.Create<IColor>();
// color first ten vertices?
for (int i = 0; i < 10; i++)
{
    IColor color = global.Color.Create();
    color.R = 0.9f;
    color.G = 0.0f;
    color.B = 0.0f;
    vertColors.Insert(i, 1, color.NativePointer);
}
vp.SetColors(node, vertColors); // fails here.


Let me know what you guys think... If there is a bug there, I can report it.

hope it helps,

kevin


Kevin Vandecar
Developer Technical Services
Autodesk Developer Network



0 Likes
Message 6 of 10

denisT.MaxDoctor
Advisor
Advisor

@kevinvandecar wrote:
IBaseInterface bi = mod.GetInterface(IVERTEXPAINT_INTERFACE_ID);
IIVertexPaint vp = global.IVertexPaint.Marshal(bi.NativePointer) as IIVertexPaint;

Once the interface object is set, then the methods can be called. But I do not have enough experience with this (even on C++ side) 


that is what i expected... there can be some casting issue. I'm not a big fun of C# in MAX, so not use it often.

But I use c++ versions of all these a lot and long time, and never had a problem.

 

 

0 Likes
Message 7 of 10

R.o.b.D
Participant
Participant

@kevinvandecarthanks for helping

unfortunately I'm still doing something wrong, I've put my test code into its own project and stripped it back but I'm still getting the same error now happens in IBaseInterface bi = mod.GetInterface(IVERTEXPAINT_INTERFACE_ID);

 

Here's all the code I'm testing with (using 2018.4)

using System;
using Autodesk.Max;

namespace ClassLibraryTest
{
	public class MaxTest
	{
		private static IClass_ID PAINTLAYERMOD_CLASS_ID = GlobalInterface.Instance.Class_ID.Create(0x7ebb4645, 0x7be2044b);
		private static IInterface_ID IVERTEXPAINT_INTERFACE_ID = GlobalInterface.Instance.Interface_ID.Create(0x3e262ef9, 0x220e7190);
		private static IGlobal global = GlobalInterface.Instance;
		private static IInterface ip = global.COREInterface;

		public static void VertexPaint()
		{
			for (int i = 0; i < ip.SelNodeCount; ++i)
			{
				IINode node = ip.GetSelNode(i);

				IObject obj = node.ObjectRef;
				IIDerivedObject dobj = global.CreateDerivedObject(obj);

				object objMod = ip.CreateInstance(SClass_ID.Osm, PAINTLAYERMOD_CLASS_ID);
				IModifier mod = (IModifier)objMod;
				dobj.AddModifier(mod, null, 0);
				node.ObjectRef = dobj;

				IBaseInterface bi = mod.GetInterface(IVERTEXPAINT_INTERFACE_ID);
				IIVertexPaint vp = global.IVertexPaint.Marshal(bi.NativePointer) as IIVertexPaint;
			}
		}
	}
}

 

0 Likes
Message 8 of 10

kevinvandecar
Community Manager
Community Manager

Hi @R.o.b.D,

ah yes, sorry... I missed that this was for 2018. I double checked, and I also have the problem in 2018 (crash to CER dialog). I  can see in our database there was some related work done to make GetInterface work better in the Autodesk.Max assembly that was provided with 2019. I am able to run it in 2019 and above. However, I still have trouble creating the IColor tab.

For 2018, I would have to recommend at this point to use C++. If you have a lot of other code in C#/.NET maybe you could expose yourself just the basics you need in a helper (C++/CLI mixed mode) assembly. It's not ideal, but maybe could help to keep bulk of functionality in the .NET side.

I am not an expert in MAXScript either, and unfortunately I do not see it exposed there, unless it's under some other name (at least the help couldn't find anything).

Sorry for the bad news.

kevin


Kevin Vandecar
Developer Technical Services
Autodesk Developer Network



0 Likes
Message 9 of 10

R.o.b.D
Participant
Participant

@kevinvandecar- thanks for the help

 

As a point of reference for others, I've tried compiling against 2019 and I know longer get the crash in casting to IIVertexPaint. I stepped through the different SP releases and it only worked with 2019.3, the early SP versions all crashed.

 

I'll take a look at the C++/CLI option next, I'm investigating the different options for writing some tools.

Maxscript doesn't have the access I need at the modifier level and polyop is too slow for the vertex counts I'm looking at (and ideally this wouldn't be a destructive workflow by collapsing stacks).

 

MaxPlus looks to be limited by the amount of supported classes currently (also had some variable performance in some brief tests I tried vs. C#).

 

For color I've also considered channel copy/paste + DCM (+2019 has fixes over 2018) but is all very messy and doesn't solve interacting with other modifiers using the SDK.

0 Likes
Message 10 of 10

denisT.MaxDoctor
Advisor
Advisor

I'll take a look at the C++/CLI option next, I'm investigating the different options for writing some tools.

 

that's why I prefer to do all development on c++ API. Too many time I've been in a situation when starting do some tools on C# (or Python) and I couldn't finish them because of any unexpected issue. 

0 Likes