Skip to content

Instantly share code, notes, and snippets.

@andrew-raphael-lukasik
Forked from LotteMakesStuff/NativeMesh.cs
Last active July 10, 2019 21:11
Show Gist options
  • Save andrew-raphael-lukasik/dbf61baae5a1c8a31dbb2b629badc5dd to your computer and use it in GitHub Desktop.
Save andrew-raphael-lukasik/dbf61baae5a1c8a31dbb2b629badc5dd to your computer and use it in GitHub Desktop.
using UnityEngine;
using Unity.Collections;
using Unity.Mathematics;
public class DynamicMeshData : System.IDisposable
{
#region FIELDS & PROPERTIES
public Mesh mesh { get; private set; }
public NativeArray<float3> vertices { get; private set; }
Vector3[] _vertices = null;
public NativeArray<float3> normals { get; private set; }
Vector3[] _normals = null;
public NativeArray<float2> uv { get; private set; }
Vector2[] _uv = null;
public NativeArray<float2> uv2 { get; private set; }
Vector2[] _uv2 = null;
public NativeArray<float4> tangents { get; private set; }
Vector4[] _tangents = null;
public NativeArray<int> triangles { get; private set; }
int[] _triangles = null;
public NativeArray<float4> colors { get; private set; }
Color[] _colors = null;
public int numTriangles => numVertices/3;
public int numVertices => vertices.Length;
#endregion
#region CONSTRUCTORS
public DynamicMeshData ( Mesh mesh )
{
this.mesh = mesh;
vertices = mesh.vertices.GetNativeArray();
triangles = mesh.triangles.GetNativeArray();
_normals = mesh.normals;
if( _normals.Length!=0 ) normals = _normals.GetNativeArray();
_uv = mesh.uv;
if( _uv.Length!=0 ) uv = _uv.GetNativeArray();
_uv2 = mesh.uv2;
if( _uv2.Length!=0 ) uv2 = _uv2.GetNativeArray();
_tangents = mesh.tangents;
if( _tangents.Length!=0 ) tangents = _tangents.GetNativeArray();
_colors = mesh.colors;
if( colors!=null ) this.colors = _colors.GetNativeArray<Color,float4>();
}
public DynamicMeshData
(
Mesh mesh ,
Vector3[] vertices ,
int[] triangles ,
Vector3[] normals = null ,
Vector2[] uv = null ,
Vector2[] uv2 = null ,
Vector4[] tangents = null ,
Color[] colors = null
)
{
this.mesh = mesh;
_vertices = vertices;
if( vertices!=null ) this.vertices = vertices.GetNativeArray();
_triangles = triangles;
if( triangles!=null ) this.triangles = triangles.GetNativeArray();
_normals = normals;
if( normals!=null ) this.normals = normals.GetNativeArray();
_uv = uv;
if( uv!=null ) this.uv = uv.GetNativeArray();
_uv2 = uv2;
if( uv2!=null ) this.uv2 = uv2.GetNativeArray();
_tangents = tangents;
if( tangents!=null ) this.tangents = tangents.GetNativeArray();
_colors = colors;
if( colors!=null ) this.colors = colors.GetNativeArray<Color,float4>();
}
public DynamicMeshData
(
Mesh mesh ,
NativeArray<float3> vertices ,
NativeArray<int> triangles ,
NativeArray<float3> normals = default(NativeArray<float3>) ,
NativeArray<float2> uv = default(NativeArray<float2>) ,
NativeArray<float2> uv2 = default(NativeArray<float2>) ,
NativeArray<float4> tangents = default(NativeArray<float4>) ,
NativeArray<float4> colors = default(NativeArray<float4>)
)
{
this.mesh = mesh;
if( vertices.IsCreated )
{
_vertices = new Vector3[ vertices.Length ];
this.vertices = vertices;
}
if( triangles.IsCreated )
{
_triangles = new int[ triangles.Length ];
this.triangles = triangles;
}
if( normals.IsCreated )
{
_normals = new Vector3[ normals.Length ];
this.normals = normals;
}
if( uv.IsCreated )
{
_uv = new Vector2[ uv.Length ];
this.uv = uv;
}
if( uv2.IsCreated )
{
_uv2 = new Vector2[ uv2.Length ];
this.uv2 = uv2;
}
if( tangents.IsCreated )
{
_tangents = new Vector4[ tangents.Length ];
this.tangents = tangents;
}
if( colors.IsCreated )
{
_colors = new Color[ colors.Length ];
this.colors = colors;
}
}
#endregion
#region DESTRUCTORS
~DynamicMeshData () => Dispose();
#endregion
#region PUBLIC METHODS
public void VerticesToMesh ()
{
vertices.MemCpy( _vertices );
mesh.vertices = _vertices;
}
public void TrianglesToMesh ()
{
triangles.MemCpy( _triangles );
mesh.triangles = _triangles;
}
public void NormalsToMesh ()
{
normals.MemCpy( _normals );
mesh.normals = _normals;
}
public void UVToMesh ()
{
uv.MemCpy( _uv );
mesh.uv = _uv;
}
public void UV2ToMesh ()
{
uv2.MemCpy( _uv2 );
mesh.uv2 = _uv2;
}
public void ColorToMesh ()
{
colors.MemCpy( _colors );
mesh.colors = _colors;
}
#endregion
#region IDISPOSABLE
public void Dispose ()
{
if( vertices.IsCreated ) vertices.Dispose();
if( triangles.IsCreated ) triangles.Dispose();
if( normals.IsCreated ) normals.Dispose();
if( uv.IsCreated ) uv.Dispose();
if( uv2.IsCreated ) uv2.Dispose();
if( tangents.IsCreated ) tangents.Dispose();
if( colors.IsCreated ) colors.Dispose();
}
#endregion
}
using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
public static class ExtensionMethods_NativeArray
{
public unsafe static NativeArray<DST> GetNativeArray <SRC,DST> ( this SRC[] source ) where SRC : unmanaged where DST : unmanaged
{
//ASSERTION: sizeof(SRC)==sizeof(DST)
// create a destination NativeArray to hold the vertices
var nativeArray = new NativeArray<DST>( source.Length , Allocator.Persistent , NativeArrayOptions.UninitializedMemory );
// pin the mesh's vertex buffer in place...
fixed( void* bufferPointer = source)
{
// ...and use memcpy to copy the Vector3[] into a NativeArray<floar3> without casting. whould be fast!
UnsafeUtility.MemCpy(
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(nativeArray) ,
bufferPointer ,
source.Length * (long)UnsafeUtility.SizeOf<SRC>()
);
}
// 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 nativeArray;
}
public unsafe static NativeArray<T> GetNativeArray <T> ( this T[] source ) where T : unmanaged
{
// create a destination NativeArray to hold the vertices
var nativeArray = new NativeArray<T>( source.Length , Allocator.Persistent , NativeArrayOptions.UninitializedMemory );
// pin the mesh's vertex buffer in place...
fixed( void* bufferPointer = source)
{
// ...and use memcpy to copy the Vector3[] into a NativeArray<floar3> without casting. whould be fast!
UnsafeUtility.MemCpy(
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(nativeArray) ,
bufferPointer ,
source.Length * (long)UnsafeUtility.SizeOf<T>()
);
}
// 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 nativeArray;
}
public unsafe static NativeArray<float3> GetNativeArray ( this Vector3[] source )
{
NativeArray<float3> verts = new NativeArray<float3>( source.Length , Allocator.Persistent , NativeArrayOptions.UninitializedMemory );
fixed( void* vertexBufferPointer = source)
{
UnsafeUtility.MemCpy(
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts) ,
vertexBufferPointer ,
source.Length * (long)UnsafeUtility.SizeOf<float3>()
);
}
return verts;
}
public unsafe static NativeArray<int> GetNativeArray ( this 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;
}
public unsafe static NativeArray<float2> GetNativeArray ( this 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;
}
public unsafe static NativeArray<float4> GetNativeArray ( this 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;
}
public unsafe static void MemCpy <SRC,DST> ( this NativeArray<SRC> source , DST[] target ) where SRC : unmanaged where DST : unmanaged
{
//ASSERTION: sizeof(SRC)==sizeof(DST)
fixed( void* arrayPointer = target )
{
UnsafeUtility.MemCpy(
arrayPointer ,
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(source) ,
target.Length * (long)UnsafeUtility.SizeOf<SRC>()
);
}
}
public unsafe static void MemCpy <SRC,DST> ( this SRC[] src , NativeArray<DST> dst ) where SRC : unmanaged where DST : unmanaged
{
//ASSERTION: sizeof(SRC)==sizeof(DST)
//ASSERTION: dst.IsCreated==true
fixed( void* bufferPointer = src )
{
UnsafeUtility.MemCpy(
NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(dst) ,
bufferPointer ,
src.Length * (long)UnsafeUtility.SizeOf<SRC>()
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment