Skip to content

Instantly share code, notes, and snippets.

@LotteMakesStuff
Created January 18, 2019 12:44
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save LotteMakesStuff/6198f966e414a88d1337b0360cb891f5 to your computer and use it in GitHub Desktop.
Save LotteMakesStuff/6198f966e414a88d1337b0360cb891f5 to your computer and use it in GitHub Desktop.
using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
using UnityEngine;
public class NativeMesh : IDisposable
{
public NativeArray<float3> VertexBuffer;
public NativeArray<float3> NormalBuffer;
public NativeArray<float2> UVBuffer;
public NativeArray<float2> UV2Buffer;
public NativeArray<float4> TangetBuffer;
public NativeArray<int> IndexBuffer;
public bool HasNormals, HasUV2s, HasTangents;
public bool IsInitialized;
public int TriangleCount;
public int VertexCount;
public NativeMesh(Mesh mesh)
{
// copy the array data into a NativeArray. This lets us pass it into Jobs
var vertexArray = mesh.vertices;
VertexBuffer = GetNativeArray(vertexArray);
var triangleArray = mesh.triangles;
IndexBuffer = GetNativeArray(triangleArray);
var normalArray = mesh.normals;
HasNormals = normalArray.Length > 0;
if (HasNormals)
NormalBuffer = GetNativeArray(normalArray);
var uvArray = mesh.uv;
UVBuffer = GetNativeArray(uvArray);
var uv2Array = mesh.uv2;
HasUV2s = uv2Array.Length > 0;
if (HasUV2s)
UV2Buffer = GetNativeArray(uv2Array);
var tangentArray = mesh.tangents;
HasTangents = tangentArray.Length > 0;
if (HasTangents)
TangetBuffer = GetNativeArray(tangentArray);
// todo what happens if these change?
TriangleCount = triangleArray.Length / 3;
VertexCount = vertexArray.Length;
IsInitialized = true;
}
#region managed to native
unsafe NativeArray<float3> GetNativeArray(Vector3[] source)
{
// create a destination NativeArray to hold the vertices
NativeArray<float3> verts = new NativeArray<float3>(source.Length, Allocator.Persistent,
NativeArrayOptions.UninitializedMemory);
// pin the mesh's vertex buffer in place...
fixed (void* vertexBufferPointer = source)
{
// ...and use memcpy to copy the Vector3[] into a NativeArray<floar3> without casting. whould be fast!
UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts),
vertexBufferPointer, source.Length * (long) UnsafeUtility.SizeOf<float3>());
}
// we only hve to fix the .net array in place, the NativeArray is allocated in the C++ side of the engine and
// wont move arround unexpectedly. We have a pointer to it not a reference! thats basically what fixed does,
// we create a scope where its 'safe' to get a pointer and directly manipulate the array
return verts;
}
unsafe NativeArray<int> GetNativeArray(int[] source)
{
NativeArray<int> verts = new NativeArray<int>(source.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
fixed (void* vertexBufferPointer = source)
{
UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts),
vertexBufferPointer, source.Length * (long) UnsafeUtility.SizeOf<int>());
}
return verts;
}
unsafe NativeArray<float2> GetNativeArray(Vector2[] source)
{
NativeArray<float2> verts = new NativeArray<float2>(source.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
fixed (void* vertexBufferPointer = source)
{
UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts),
vertexBufferPointer, source.Length * (long) UnsafeUtility.SizeOf<float2>());
}
return verts;
}
unsafe NativeArray<float4> GetNativeArray(Vector4[] source)
{
NativeArray<float4> verts = new NativeArray<float4>(source.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
fixed (void* vertexBufferPointer = source)
{
UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts),
vertexBufferPointer, source.Length * (long) UnsafeUtility.SizeOf<float4>());
}
return verts;
}
#endregion
#region native to managed
unsafe void CopyDataFromNativeArray(NativeArray<float2> source, Vector2[] target)
{
// pin the target vertex array and get a pointer to it
fixed (void* vertexArrayPointer = target)
{
// memcopy the native array over the top
UnsafeUtility.MemCpy(vertexArrayPointer,
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(source),
target.Length * (long) UnsafeUtility.SizeOf<float2>());
}
}
unsafe void CopyDataFromNativeArray(NativeArray<float3> source, Vector3[] target)
{
fixed (void* vertexArrayPointer = target)
{
UnsafeUtility.MemCpy(vertexArrayPointer,
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(source),
target.Length * (long) UnsafeUtility.SizeOf<float3>());
}
}
unsafe void CopyDataFromNativeArray(NativeArray<float4> source, Vector4[] target)
{
fixed (void* vertexArrayPointer = target)
{
UnsafeUtility.MemCpy(vertexArrayPointer,
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(source),
target.Length * (long) UnsafeUtility.SizeOf<float4>());
}
}
unsafe void CopyDataFromNativeArray(NativeArray<int> source, int[] target)
{
fixed (void* vertexArrayPointer = target)
{
UnsafeUtility.MemCpy(vertexArrayPointer,
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(source),
target.Length * (long) UnsafeUtility.SizeOf<int>());
}
}
#endregion
public void Dispose()
{
VertexBuffer.Dispose();
if (HasNormals) NormalBuffer.Dispose();
if (HasUVs) UVBuffer.Dispose();
if (HasUV2s) UV2Buffer.Dispose();
if (HasTangents) TangetBuffer.Dispose();
IndexBuffer.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment