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
}
else
{
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.
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.
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.
Would you try both functions if you get some time?
It would be great to have your opinion and findings.
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:
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++.
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.
This runs about 18 times faster (yes, this is still c# code )
//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);
}
else
{
mapP->Y = Math.Min(1, mapP->Y + FadeInValue);
}
mapP->Z = mapP->Y;
mapP++;
meshP++;
}
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.
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.