Notifications
Clear all

[Closed] C# Value Conversion/Type Casting

Greetings

 In order to try to speed up some MXS I've written, I'm looking to move some massive functions into a class library.  I'm quite new to C#, and visual studio, and after going part way down the path of making my own Point/Vector classes/structs i found "System.Windows.Media.Media3D" which contains a lot of the base objects/methods already done.
 
 I wrote some simple static test methods.  For example, one takes threePoint3D values in as paramiters, and returns a Double.  
 
 But I can't seem to figure out how to convert anything with [b][b]dotNet[/b][/b].[b][b]ValueToDotNetObject [/b][/b]to a "System.Windows.Media.Media3D.Point3D" type to pass out of maxscript as a valid parameter to the method.  
 
 I've previously played with passing basic types back and forth, which was a breeze, but
 if it's this difficult with Points, how the heck are arrays of points, let alone custom structs in MXS ever going to get passed out?  Do they all need to get broken down somehow into their constituent base types? (as listed under Automatic Conversion in the MXS refernce?)
 
 for example, this method is within namespace "whatever", public class "blah" in my library.

  using System.Windows.Media.Media3D;
  
  //etc etc
  	  // checks if a point lies within an array of points (X,Y plane only).  uses count ray intersections through boundry method.
	  public static bool PointInBoundry(Point3D testPt, Point3D[] pointsArray)
	  {
		 Int32 paCount = pointsArray.Count();
		 Boolean result = false;
		 int j;
		 for (int i = 0; i <= (paCount-1); i++)
		 {
			j = (i == (paCount-1)) ? 0 : i+1;

			if ((((pointsArray[i].Y <= testPt.Y) && (pointsArray[j].Y > testPt.Y)) ||
				 ((pointsArray[j].Y <= testPt.Y) && (pointsArray[i].Y > testPt.Y))) &&
				 (testPt.X < (pointsArray[j].X - pointsArray[i].X) * (testPt.Y - pointsArray[i].Y) / (pointsArray[j].Y - pointsArray[i].Y) + pointsArray[i].X))
				 result = !result;		 
		 }

		 return result;

	  }

   }
     
     
 Thanks very much for the assistance :)
 
 Mikie
6 Replies

Further to the above

I found that If i loaded

dotnet.loadassembly @“PresentationCore.dll”

i could then…

newPt3 = dotnetobject “System.Windows.Media.Media3D.point3D” $S1.pos.x $S1.pos.y $S1.pos.z

and pass those points to my method…

now… as for an array of point3ds… ? :\

Mikie

hey Mike. as far as I know, maxscript cannot implicitly convert non-standard value / object types to dotnet. you have already found the answer to your question in your last post by constructing a new dotnet object from the x y z values of a mxs point3. to make an array, you can make use of the for loop/collect function to convert a point3 array to a dotnet Point3D array. eg:

point3Array = #([0,0,0], [1,2,3], [4,5,6])
 DotNetPoint3DArray = for p in point3Array collect dotnetobject "System.Windows.Media.Media3D.point3D" p.x p.y p.z

maxscript CAN implicitly convert standard maxscript arrays, that contain a single type of dotnet object, into a dotnet array of that type. the alternative is to create a point3D array of length point3Array.count and use the SetValue function.
FYI incase you didn’t know, you can create a dotnet array of any type by putting the square brackets [] after the class name in the string and then followed by an integer argument for the array length like this:

dotnetobject "System.Windows.Media.Media3D.point3D[]" 10

Cool, thanks for that! Saved a poop load more trial and error to get the syntax right!

I’ll be quite interested to see if there is any percievable improvements in performance running in C#. Given all of the calls, and extra stack/heap allocation that goes on, you’d think that would eat up a lot of the gains you get.

I’ll be sure to buy you a pint next time we’re in the same city

…actually by the time I port what I need to over to C# it will probably be a slab

Mikie

Interesting Results… I always knew that I would need to port a large bulk of my code to c# before i would see any gains, but this little axample shows how costly it is to create dotnet objects. As a starting test, I basically have 3 methods written using virtually the same code in MXS and C#.
I Iterate each method in a for loop 10,000 times, once with the dotnetobjects and paramiters created outside the loop, and once, assuming the objects need to be created each run.

for example one version does this…


t1 = timestamp()
for N = 1 to 10000 do
(
	tp = dotnetobject "System.Windows.Media.Media3D.point3D" 0 0 0
	p2 = dotnetobject "System.Windows.Media.Media3D.point3D" 1 1 1
	p3 = dotnetobject "System.Windows.Media.Media3D.point3D" 4 -6 3
	r1 = MathOps.AngleTest tp p2 p3
)
print "angletest C# took" + (timestamp() - t1) as string 

t1 = timestamp()
for N = 1 to 10000 do
(
	mxs_tp = [0,0,0]
	mxs_p2 = [1,1,1]
	mxs_p3 = [4,-6,3]
	r1 = AngleTest mxs_tp mxs_p2 mxs_p3
)
print "angletest MXS took" + (timestamp() - t1) as string 


and the other does this…


tp = dotnetobject "System.Windows.Media.Media3D.point3D" 0 0 0
p2 = dotnetobject "System.Windows.Media.Media3D.point3D" 1 1 1
p3 = dotnetobject "System.Windows.Media.Media3D.point3D" 4 -6 3
t1 = timestamp()
for N = 1 to 10000 do
(
	r1 = MathOps.AngleTest tp p2 p3
)
print "angletest C# took" + (timestamp() - t1) as string 

mxs_tp = [0,0,0]
mxs_p2 = [1,1,1]
mxs_p3 = [4,-6,3]
t1 = timestamp()
for N = 1 to 10000 do
(
	r1 = AngleTest mxs_tp mxs_p2 mxs_p3
)
print "angletest MXS took" + (timestamp() - t1) as string 

The results were as follows for creating dotnet objects each time:
“angletest C# took 11766”
“getangle C# took 7937”
“pib C# took 19672”
“angletest MXS took 125”
“angletest MXS took 109”
“PIB MXS took 469”

The results were as follows for creating dotnet objects only once, outside the loop:
“angletest C# took 235”
“getangle C# took 234”
“pib C# took 274”
“angletest MXS took 94”
“angletest MXS took 78”
“PIB MXS took 453”

I guess the key will be to get data out to C# as seldom as possible, and run as much of the looping/calc within C# itself in order to get any gains out of it. These teeney little methods, are nested within a few layers of other methods, and get called on transform change handellers, or tcbs. Hopefully the more of their parent methods I port, the more performace benefit I see.

I will be very currious to see how quickly a loop through the timeline can be done in c# vs
maxscript. I think my next bit of reasearch will be into figuring out the C# equivalent of

(at time T $Object.pos)

Cheers

Mikie

I had a look at optimizing your first test and it can be optimized enormously. all you have to do to is to first create a dotnetclass variable of the Point3D class and use it to construct your objects in the loop rather than using the string path. I’m guessing that there is some extra error checking and such when using dotnetobject <string> compared to dotnetobject <dotnetclass> that is slowing things down so much. my tests for the dotnet loop went from about 10300 milliseconds down to about 480 milliseconds – over 21 times faster!

p3DClass = dotnetclass "System.Windows.Media.Media3D.Point3D"
   num = 10000
   t1 = timestamp()
   for N = 1 to num do
   (
   	tp = dotnetobject p3DClass 0 0 0
   	p2 = dotnetobject p3DClass 1 1 1
   	p3 = dotnetobject p3DClass 4 -6 3
   )
   format "dotnet took % milliseconds
" (timestamp() - t1)
   
   t1 = timestamp()
   for N = 1 to num do
   (
   	mxs_tp = [0,0,0]
   	mxs_p2 = [1,1,1]
   	mxs_p3 = [4,-6,3]
   )
   format "MXS took % milliseconds
" (timestamp() - t1)

Very cool! They need a little gold star emoticon

I didn’t think you could do that, as point3D was listed as a ‘struct’ in the msdn help thingo.