.net sdk memory management problem


after optimization the loop should look as (IMHO):

		  for (int i = 0; i < numMapVerts; i++)
			  IPoint3 vertex = mesh.GetVert(i);
			  mapVerts[i].X = 1; // if you need to double-check it
			if (vertex.Z > HeightThreshold)
				  mapVerts[i].Y = Math.Max(0, mapVerts[i].Y - FadeInValue);
				  //mapVerts[i].Z = Math.Max(0, mapVerts[i].Z - FadeInValue);  // if it's not a grey scale
				  mapVerts[i].Y = Math.Min(1, mapVerts[i].Y + FadeInValue);
				  //mapVerts[i].Z = Math.Min(1, mapVerts[i].Z + FadeInValue);  // if it's not a grey scale
			mapVerts[i].Z = mapVerts[i].Y; // if it's a grey scale

i believe we can do color assignment in place. and after compilation Math.Min or Math.Max is exactly the same as one comparison and one assignment.


If it is for previewing you can just initialize the default map faces and it should work.


Thank you Håvard, I now have a better idea of what this tool could be used for. Will try with an ocean.


I would had been surprised if avoiding the multiplications and divisions in this case would cause such a huge performance impact. So I tried it and as far as I can see it doesn’t speed up the function at all.


This runs over 2 times slower on my tests.

I suppose this is due to the constant access to the mapVerts List (mapVerts[i].X, mapVerts[i].Y, mapVerts[i].Z) instead of writing the value back at once as I did in the latest function.



Tried with an animated ocean and it works wonderful. Perfect for creating foam masks, among other things.

Performance is great, I don’t think it needs any further optimizations. After all, the ocean I tried is another example that probes the FPS are capped by the animation itself and not by coloring the vertices with this function.


Are you compiling with optimizations enabled?


Yes… I think :).
Are you getting different results? I mean for comparison with Denis’s code on #28 I get around 2.2 slowdown. Is that what you are talking about?


I haven’t tried compiling, just thought it would explain why you get such different performance.


I’ll test all these potential optimizations when I get back home from work. I appreciate all the tips so far!

Yeah, it works pretty well with just the height criterion. Here is a test the guy I helped made:



Would you try both functions if you get some time?
It would be great to have your opinion and findings.


slowing down for in-place method doesn’t make sense for me. probably it’s some issue specific to max .net sdk.
if removing unnecessary multiplications and divisions don’t really affect the performance that means 99% of time the method is doing something different. but i don’t see anything unless taking a value from one piece of memory and putting to another. in c++ sdk it’s almost nothing and doesn’t take any time.


I tried both versions and I get same result as PolyTools3D - the in-place version is about 60% slower for me.

I believe this is because that no value data is actually stored on the IPoint3:

bFlags = (dotnetClass "System.Reflection.BindingFlags")
allFields = dotnet.CombineEnums bFlags.Public bFlags.NonPublic bFlags.Instance
fields = ((((dotnetclass "Autodesk.Max.GlobalInterface").Instance.Point3.Create 1 1 1).GetType()).GetFields allFields)
for p in fields do print (p.ToString())

"Point3* unmanaged_"
"Boolean owning_"

The only data is a pointer to a native Point3. Each access requires dereferencing a native pointer, which I assume is slower from a c# assembly.

Nevertheless, the method runs very fast (1-2 ms for 40000 vertices on my machine), and if you need it any faster than this, you might as well start over in C++.


This runs about 18 times faster (yes, this is still c# code :stuck_out_tongue: )

//define this somewhere in your class
   struct Point3
            public float X;
            public float Y;
            public float Z;

Point3* mapP = (Point3*)(mapVerts[0] as Autodesk.Max.Wrappers.Point3).INativeObject__Handle;
Point3* meshP = (Point3*)(mesh.GetVert(0) as Autodesk.Max.Wrappers.Point3).INativeObject__Handle;

for (int i = 0; i < numMapVerts; i++)
    mapP->X = 1;
    if (meshP->Z > HeightThreshold)
        mapP->Y = Math.Max(0, mapP->Y - FadeInValue);
        mapP->Y = Math.Min(1, mapP->Y + FadeInValue);
    mapP->Z = mapP->Y;

for 1000 iterations:
previous fastest version: ~1800ms
this version: ~100ms

It requires you to reference Autodesk.Max.Wrappers in your project, and compile with unsafe code flag.

I wouldn’t recommend doing this in production code, I don’t know what issues could occur.

Converting simple renderer script to max sdk plugin

The C# takes 3ms to process a 100K mesh (3000ms for 1000 calls)

How much is “almost nothing” in C++? Just curious to know how much faster is the native code.


Great! 0.00016 seconds to process a 100K mesh isn’t bad, or is it? :slight_smile:


This would still be faster in C++, especially if it is SIMDed.


this is almost the same what c++ code has to do. excepting that mesh verts and map verts are already arrays of Point3.


i don’t think c++ code can do it much faster. only maybe getting the mesh might be a little faster.
another thing is update the render mesh after you set this colors and force rebuild of a cached one. and i’m not sure it’s possible to rebuild only colors. so the update will take much more time than a calculation.


I was actually expecting the C++ version to be 3-5 times faster, but 20 times faster is still a huge difference.

Although this function involves very common operations, I supposed the difference can be much larger than that in other cases.

Well, I guess a more flexible language comes with its price. What a shame that we can’t maintain and compile a single C++ version.

Thank you Rotem and Denis for your input, and thank you Håvard for sharing this.