Notifications
Clear all

[Closed] [maxscript] KDTree. Can we make it faster?

You make make IArray at once…

It would also be better to pass an MXS point3 array instead of a mesh. In case you want to have a special list of points, not just all vertices.

1 Reply
(@serejah)
Joined: 11 months ago

Posts: 0

Yeah, it would be great to support lots of various point sources. With trimeshes you can use getHandleByAnim which is pretty convenient to get the IMesh on c# side.
Wish someone could show me how to get access to raw Point3 values of mxs array. I did a lot of attempts, but never succeed.

Yes, it definitely should be created inside same function

btw. Geometry3D library also contains a wrapper for Embree, but it uses old embree version so it doesn’t support node transform. All ray intersections happen in local space which is sad

not a big deal… you can easily convert rays in coodsys you need

we can convert point3 array to flat array of floats… this might be easier

It must be NativePointer, it was renamed after 2014 version

Available in 3ds Max 2018.2 Update and higher: Some native MAXScript types are converted into .NET arrays, as some .NET libraries do not support these types natively. Point2, Point3, Point4, Quat, EulerAngles, and Matrix3 types are all converted into float[] or double[] arrays.

Newer versions already can do it out of the box. This is great, but I’d still prefer a method that would fit most max versions, 2014+.
Can’t think of a way how to convert mxs point3 array to flat float array efficiently.

Just realized that Point3 arrays could be passed like this.

(
	arr = #([1,2,3],[4,5,6],[7,8,9])
	v   = g.executescript (g.stringstream.create "::arr") true
	fp  = g.fpvalue.create()
	v.tofpvalue fp

	for i=0 to 2 do
	(
		pt = fp.PTab.Item (dotNetObject "System.IntPtr" i)
		format "[%,%,%]\n" pt.x pt.y pt.z
	)
)

[1.0,2.0,3.0]
[4.0,5.0,6.0]
[7.0,8.0,9.0]

it might be slow

1 Reply
(@serejah)
Joined: 11 months ago

Posts: 0

Yes. Unfortunately, points aren’t located next to each other in memory so UnmananagedArray2Struct returns garbage.

i’m thinking about the passing a “single[]”

(
	delete objects
	s = geosphere segs:100
	addmodifier s (Edit_Poly())

	ii = #()
	for k=1 to numpoints s do 
	(
		p = getpointpos s k
		for i=1 to 3 do append ii p[i]  
	)
	vv = dotnet.valuetodotnetobject ii (dotnetclass "single[]")
	vv.length
)

looks pretty reasonable by performance …

we can do array of doubles if it’s better

			list = createGenericList "microsoft.xna.framework.vector3"
			vv = for p in pp collect (as_vec3 p)
			vec3_arr = dotnet.valuetodotnetobject vv (dotnetclass "microsoft.xna.framework.vector3[]")
			list.addrange vec3_arr

this is not bad …

One nitpick so far:

 ia_methods = ia_type.getmethods() -- [ 67 ] >> .create that takes list<t> as a parameter

Relying on the index number is not stable. I’m using max 2020 (I saw you were using 2016) and apparently the index is 75 in the associated .NET version.

Came up with this instead

	fn findEnumerableCreateMethod methods = (
	for i = 1 to ia_methods.count do (
		if methods[i].name != "Create" then continue
		local methodParams = methods[i].GetParameters()
		if (methodParams.count == 1 and 
			methodParams[1].ParameterType.ToString() == "System.Collections.Generic.IEnumerable`1[T]") then
		(
			return methods[i]	
		)
	)
	return undefined
)

As for this, I was involved in a discussion on the Autodesk forum about a similar thing – actually the same problem that brought me to this thread. I did not get the example code provided by the answerer to work, but it may help you to look: https://forums.autodesk.com/t5/3ds-max-programming/when-communicating-between-maxscript-and-net-how-can-i-detect-a/m-p/10226106/highlight/true#M27258

Unfortunately, points aren’t located next to each other in memory so UnmananagedArray2Struct returns garbage.

Considering this – could it be because the array in this case is generated being grown iteratively? What if you allocate the whole array at once, then fill it in instead? I.e., instead of pts = for i=1 to txt.numverts collect getvert txt i try

pts = #()
pts[txt.numverts] = [0.0,0.0,0.0]
for i = 1 to txt.numverts do pts[i] = getvert txt i

Not familiar enough with the internals to know whether these are equivalent, sorry.

Page 3 / 6