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.
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
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]
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.