global OctreeClass
(
struct AutodeskOctreeClassStruct
(
private
assemblies =
#(
dotnet.loadassembly @"geometry3d.dll",
dotnet.loadassembly @"immutablearray.dll",
dotnet.loadassembly @"monogame.framework.dll"
),
vec3_class = dotnetclass "microsoft.xna.framework.vector3",
vec3_type = dotnet.gettype vec3_class,
vec3_arr_class = dotnetclass "microsoft.xna.framework.vector3[]",
pnt3_class = dotnetclass "Autodesk.Max.Wrappers.Point3",
pnt3_type = dotnet.gettype pnt3_class,
pnt3_arr_class = dotnetclass "Autodesk.Max.Wrappers.Point3[]",
octree_class = dotnetclass "autodesk.geometry3d.vertexoctree",
iarray_class = dotnetclass "autodesk.sequences.immutablearray",
iarray_type = dotnet.gettype iarray_class,
_global = (dotnetclass "autodesk.max.globalinterface").Instance,
_point3_create = _global.Point3.Create,
public
points,
octree,
MemUtilsStruct =
(
struct MemUtilsStruct
(
private
_global = (dotnetclass "autodesk.max.globalinterface").Instance,
vec3_class = dotnetclass "microsoft.xna.framework.vector3",
vec3_type = dotnet.gettype vec3_class,
public
fn make_utils_assembly =
(
source = @"
using System;
using System.Runtime.InteropServices;
class MemUtils
{
public static T[] MarshalUnmananagedArray2Struct<T>(Int64 unmanagedArray, int length )
{
var size = Marshal.SizeOf(typeof(T));
var mangagedArray = new T[length];
for (int i = 0; i < length; i++)
{
IntPtr ins = new IntPtr(unmanagedArray + i * size);
mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
}
return mangagedArray;
}
}"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.AddRange #("System.dll")
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
compilerResults.CompiledAssembly.CreateInstance "MemUtils"
),
mem_utils = make_utils_assembly(),
array_marshal_method = (dotnet.gettype mem_utils).GetMethod "MarshalUnmananagedArray2Struct",
fn get_first_handle arr =
(
(arr.item 0).INativeObject__NativePointer
),
fn get_vec3_array unmananaged_ptr count =
(
method = array_marshal_method.MakeGenericMethod #(vec3_type)
method.Invoke 0 #(unmananaged_ptr, count) asdotnetobject:true
),
fn get_node_imesh node &vertPtr: &count: = if iskindof node GeometryClass do
(
inode = _global.Animatable.GetAnimByHandle (gethandlebyanim node)
os = inode.EvalWorldState 0 true
imesh = if os.Obj.ClassID == _global.TriObjectClassID then
(
os.Obj.Mesh_
)
else if os.Obj.CanConvertToType _global.TriObjectClassID == 1 do
(
tri = os.Obj.ConvertToType 0 _global.TriObjectClassID
tri.Mesh_
)
if imesh != undefined do
(
vertPtr = imesh.Verts.item[0].INativeObject__NativePointer
count = imesh.NumVerts_
)
imesh
),
fn get_mesh_verts node =
(
imesh = get_node_imesh node vertPtr:&_ptr count:&_num
if (imesh != undefined) do
(
vec3_arr = get_vec3_array _ptr _num
)
),
on create do
(
)
)
),
mxs_to_net_utils = MemUtilsStruct(),
fn as_vec3 p = dotnetobject vec3_class p.x p.y p.z,
fn create_generic_list class =
(
local genericType = dotnet.GetType "System.Collections.Generic.List`1"
if iskindof (local elementType = dotnet.GetType class) dotnetobject do
(
(dotnetclass "System.Activator").CreateInstance (genericType.MakeGenericType #(elementType))
)
),
fn iarray_create_method type:#array =
(
local typename = if type == #list then "List`1" else "T[]"
local _method = undefined
for method in iarray_type.GetMethods() while _method == undefined where method.Name == "ToIArray" do
(
local params = method.GetParameters()
if (params.count > 0 and params[1].ParameterType.Name == typename) do _method = method.MakeGenericMethod #(vec3_type)
)
_method
),
vec3_iarray_method = iarray_create_method(),
fn create_from_vectors vecs =
(
local vec3_arr = dotnet.valuetodotnetobject vecs vec3_arr_class
local method = iarray_create_method type:#array
local vec3_iarray = method.invoke 0 #(vec3_arr)
dotnetobject octree_class vec3_iarray
),
fn create_from_node node =
(
if (vec3_arr = mxs_to_net_utils.get_mesh_verts node) != undefined do
(
vec3_iarray = vec3_iarray_method.invoke 0 #(vec3_arr)
dotnetobject octree_class vec3_iarray
)
),
fn create_from_object obj =
(
vecs = for k=1 to numpoints obj collect as_vec3 (getpointpos obj k)
create_from_vectors vecs
),
fn find_nearest_index p =
(
octree.FindClosestPoint (as_vec3 p) + 1
),
fn find_nearest_point pt =
(
if (i = find_nearest_index p) > 0 do points[i]
),
on create do
(
)
)
global _oc = OctreeClass = AutodeskOctreeClassStruct()
ok
)
delete objects
gc()
s = geosphere segs:100
addmodifier s (Edit_Poly())
pp = for k=1 to numpoints s collect (getpointpos s k)
(
format ">>>>>>>>\n"
t0 = timestamp()
h0 = heapfree
if (oc_tree = _oc.create_from_node s) != undefined do
(
_oc.octree = oc_tree
)
format "\t octree:(%) time:% heap:%\n" (numpoints s) (timestamp() - t0) (h0 - heapfree)
)
(
num = 100
v = -1
seed 2
index = random 1 pp.count
t0 = timestamp()
h0 = heapfree
oc_find_nearest_index = _oc.find_nearest_index
for k=1 to num do
(
v = oc_find_nearest_index pp[index]
)
format "\t closest:(% >> %) time:% heap:%\n" index v (timestamp() - t0) (h0 - heapfree)
)
Am I missing anything?
I haven’t been practicing MAX c# lately, so you can probably clean up some things there.