Cast Vector3[] to float3[]

Hey there,

I’m developing a critical part of an application that must iterate through an array of 1.000.000+ Vector3 objects. Through some testing I discovered that the speed of the existing algorithm improves 30% just by iterating through a float3 array instead.

After manipulation, the array must feed a mesh vertices array, so must be converted to Vector3.

As the distribution in memory of a Vector3 and a float3 is the same, I know there must be a way to quickly cast from one to the other (in C it would be through pointers, but doesn’t seem as easy in C+).

I also tried to copy from Vector3 to float3, but obviously this method makes me have a duplication in memory. The way I tried to do this is with the following:

    [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
    private static unsafe extern void CopyMemory(void* dest, void* src, int count);

    private static unsafe void Serialize(Vector3[] src, float3[] dst)
    {
        fixed (void* d = &dst[0])
        {
            fixed (void* s = &src[0])
            {
                CopyMemory(d, s, src.Length * sizeof(float) * 3);
            }
        }
    }

Anybody has an idea on how to achieve this?

_
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Assert = UnityEngine.Assertions.Assert;

public unsafe static void MemCpy <SRC,DST> ( SRC[] src , DST[] dst )
	where SRC : struct
	where DST : struct
{
	int srcSize = src.Length * UnsafeUtility.SizeOf<SRC>();
	int dstSize = dst.Length * UnsafeUtility.SizeOf<DST>();
	Assert.AreEqual( srcSize , dstSize , $"{nameof(srcSize)}:{srcSize} and {nameof(dstSize)}:{dstSize} must be equal." );
	void* srcPtr = UnsafeUtility.PinGCArrayAndGetDataAddress( src , out ulong srcHandle );
	void* dstPtr = UnsafeUtility.PinGCArrayAndGetDataAddress( dst , out ulong dstHandle );
	UnsafeUtility.MemCpy( destination:dstPtr , source:srcPtr , size:srcSize );
	UnsafeUtility.ReleaseGCObject( srcHandle );
	UnsafeUtility.ReleaseGCObject( dstHandle );
}

public unsafe static void MemCpy <SRC,DST> ( NativeArray<SRC> src , DST[] dst )
	where SRC : struct
	where DST : struct
{
	int srcSize = src.Length * UnsafeUtility.SizeOf<SRC>();
	int dstSize = dst.Length * UnsafeUtility.SizeOf<DST>();
	Assert.AreEqual( srcSize , dstSize , $"{nameof(srcSize)}:{srcSize} and {nameof(dstSize)}:{dstSize} must be equal." );
	void* srcPtr = NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr( src );
	void* dstPtr = UnsafeUtility.PinGCArrayAndGetDataAddress( dst , out ulong handle );
	UnsafeUtility.MemCpy( destination:dstPtr , source:srcPtr , size:srcSize );
	UnsafeUtility.ReleaseGCObject( handle );
}

_
< credits roll >

< credits roll >
_
unity3d player settings allow unsafe code tutorial

You can also use a NativeArray

using Unity.Collections;

NativeArray verts = new NativeArray(data, Allocator.Temp);
mesh.vertices = verts.Reinterpret().ToArray();

You may want to use other Allocator type too, maybe Persistent, but since there’s no much info in the docs, can’t tell you more details on these Allocators, besides what you can already figure out from their names.

I think it may be using reinterpret_cast in the C++ side of the engine, so, I assume it’s very performant.