Skip to content
Snippets Groups Projects
Commit dcbb8c47 authored by Knuiman, Bart's avatar Knuiman, Bart
Browse files

First commit

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 1277 additions and 0 deletions
*.unity filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.flv filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.dds filter=lfs diff=lfs merge=lfs -text
*.eps filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.otf filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.7z filter=lfs diff=lfs merge=lfs -text
*.avi filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.mpg filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text
*.wmv filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
Assets/Content/** filter=lfs diff=lfs merge=lfs -text
_InstallDependencies/** filter=lfs diff=lfs merge=lfs -text
\ No newline at end of file
# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
# Learn more about .gitignore:
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
# Node artifact files
node_modules/
dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files
*.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS
.DS_Store
# Generated by Windows
Thumbs.db
# Applications
*.app
*.exe
*.war
# Large media files
*.mp4
*.tiff
*.avi
*.flv
*.mov
*.wmv
## Utils
Core library for various helper functions and extensions.
### Dependencies - None
- None (Should remain none)
## Terrain
Builds up a terrain using PDOK BGT information.
### Dependencies (GIT Pacakages)
- geotiff
- utils
### Usage:
Sweep the BuildTerrain prefab into the Hierarchy and press 'Build' on the BuildTerrain script.
```
```
### Important:
fileFormatVersion: 2
guid: 2665e26779c333f4489435e19a5d60b3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 8261ce8acebad7a44b3bd63b8ffbbf13
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 1599b4453c438874296b1092f7891c34
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
namespace LAZNamespace
{
#if UNITY_EDITOR
public class ReadOnlyAttribute : PropertyAttribute
{
}
[CustomPropertyDrawer( typeof( ReadOnlyAttribute ) )]
public class ReadOnlyDrawer : PropertyDrawer
{
public override float GetPropertyHeight( SerializedProperty property, GUIContent label )
{
return EditorGUI.GetPropertyHeight( property, label, true );
}
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
{
GUI.enabled = false;
EditorGUI.PropertyField( position, property, label, true );
GUI.enabled = true;
}
}
#endif
}
\ No newline at end of file
fileFormatVersion: 2
guid: 68bcae11682ef85409f0c438287818e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
namespace Wander
{
struct TileDownload
{
public int deltaTileX;
public int deltaTileY;
public UnityWebRequest request;
}
[ExecuteInEditMode()]
public class TerrainBuilder : MonoBehaviour
{
public enum MapType
{
Trees,
BGT_achtergrond,
BGT_standaard,
BRT
}
public MapType mapType;
public bool runOnStart = false;
public float offsetX = 174041;
public float offsetY = 444126;
public int zoom = 11;
public int numTilesWidth = 10;
public int numTilesHeight = 10;
public GameObject tilePrefab;
GameObject root;
int numRetries = 0;
bool showedResult = false;
List<TileDownload> requests = new List<TileDownload>();
private void Start()
{
if (Application.isPlaying)
{
Build();
}
}
internal void Build()
{
StopAllCoroutines();
StartCoroutine( BuildRoutine() );
}
internal void Cancel()
{
}
IEnumerator BuildRoutine()
{
yield break;
}
private void Update()
{
CheckDownloadsDone();
}
string GetUrl(int tileX, int tileY, int zoom)
{
string url = "";
switch( mapType )
{
case MapType.BGT_achtergrond:
url = $"https://service.pdok.nl/lv/bgt/wmts/v1_0/achtergrondvisualisatie/EPSG:28992/{zoom}/{tileX}/{tileY}.png";
break;
case MapType.BGT_standaard:
url = $"https://service.pdok.nl/lv/bgt/wmts/v1_0/standaardvisualisatie/EPSG:28992/{zoom}/{tileX}/{tileY}.png";
break;
case MapType.BRT:
url = $"https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0?layer=standaard&style=default&tilematrixset=EPSG:28992&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/Fpng&TileMatrix=EPSG:28992:{zoom}&TileCol={tileX}&TileRow={tileY}";
break;
case MapType.Trees:
url = $"https://services.geodan.nl/data/geodan/gws/nld/landuse/wmts?layer=trees&style=default&tilematrixset=EPSG:28992&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix={zoom}&TileCol={tileX}&TileRow={tileY}&servicekey=b28cce8a-abe7-11e6-84a1-005056805b87";
break;
}
return url;
}
GameObject Download()
{
//Debug.Log( "Start downloading Topo" );
//Vector2Int tileCentre = RDUtils.RD2Tile( new Vector2( offsetX, offsetY ), zoom );
//// Calculate how much the chosen centre RD is from tile alignment.
//Vector2 rdTileCentre = RDUtils.Tile2RD( tileCentre, zoom );
//float rdShiftX = offsetX - rdTileCentre.x;
//float rdShiftY = offsetY - rdTileCentre.y;
//// Apply the shift to the root.
//root = new GameObject(mapType.ToString());
//root.transform.position = -new Vector3( rdShiftX, 0, rdShiftY );
//// Start downloading all the tiles
//for ( int x = -numTilesWidth/2; x < numTilesWidth/2; x++ )
//{
// for ( int y = -numTilesHeight/2; y < numTilesHeight/2; y++ )
// {
// int tileX = x + tileCentre.x;
// int tileY = y + tileCentre.y;
// string url = GetUrl(tileX, tileY, zoom);
// UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
// www.SendWebRequest();
// TileDownload td = new TileDownload();
// td.request = www;
// td.deltaTileX = x;
// td.deltaTileY = -y;
// requests.Add( td );
// }
//}
return root;
}
void CheckDownloadsDone()
{
if (root==null)
return;
//float tileSize = (float) RDUtils.CalcTileSizeRD(zoom);
//for ( int i = 0; i < requests.Count; i++ )
//{
// var td = requests[i];
// var www = td.request;
// if ( www.isDone )
// {
// if ( www.result != UnityWebRequest.Result.Success )
// {
// Debug.Log( www.error );
// // retry
// td.request = UnityWebRequestTexture.GetTexture( www.url );
// td.request.SendWebRequest();
// requests[i] = td;
// numRetries++;
// }
// else
// {
// GameObject tile = Instantiate(tilePrefab);
// // setup transform
// tile.transform.parent = root.transform;
// tile.transform.localPosition = new Vector3( td.deltaTileX * tileSize, 0, td.deltaTileY * tileSize );
// tile.transform.localScale = new Vector3( tileSize, 1, tileSize );
// // setup material
// MeshRenderer mr = tile.transform.GetChild( 0 ).GetComponent<MeshRenderer>();
// Material mat = new Material(mr.sharedMaterial);
// mat.mainTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
// mr.sharedMaterial = mat;
// tile.name = $"Tile_{td.deltaTileX}_{td.deltaTileY}";
// // remove request
// requests.RemoveAt( i );
// i--;
// continue;
// }
// }
//}
//if ( requests.Count == 0 && !showedResult )
//{
// Debug.Log( "Finished downloading Topo. Num retires: " + numRetries );
// showedResult = true;
//}
}
}
#if UNITY_EDITOR
[CustomEditor( typeof( TerrainBuilder ) )]
[InitializeOnLoad]
public class TerrainBuilderEditor : Editor
{
public override void OnInspectorGUI()
{
TerrainBuilder builder = (TerrainBuilder)target;
EditorGUILayout.HelpBox( "If the 'Tree setup' section is changed, cached meshes may not load back correctly, because the tree structure is not cached to disk. Always clear cache if altering the 'Tree setup'. This is not needed if 'Cache Meshes To Scene' is unticked.", MessageType.Warning, true );
GUILayout.BeginHorizontal();
{
if (GUILayout.Button( "Build" ))
{
builder.Build();
}
if (GUILayout.Button( "Cancel" ))
{
builder.Cancel();
}
}
GUILayout.EndHorizontal();
DrawDefaultInspector();
}
}
#endif
}
\ No newline at end of file
fileFormatVersion: 2
guid: 36e12874954798f42a9631ebe943a290
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
This diff is collapsed.
fileFormatVersion: 2
guid: d276505899852134bab23367d780e06c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace Wander
{
public static class GeomUtil
{
/* Reduce resolution of a normalized vector. */
public static Vector3 ReduceResolution(this Vector3 v, float resolution=32)
{
Debug.Assert( Mathf.Abs( Vector3.Dot( v, v )-1 )<0.001f ); // Assert normalized.
float invRes = 1.0f / resolution;
var n = v * resolution;
n.x = Mathf.Round( n.x );
n.y = Mathf.Round( n.y );
n.z = Mathf.Round( n.z );
return n*invRes;
}
public static Vector3 CrossWithUpVector( Vector3 v )
{
return new Vector3( -v.z, 0, v.x );
}
public static void GenerateUvs( Vector3 n, Vector3 v0, Vector3 v1, Vector3 v2, out Vector2 uv0, out Vector2 uv1, out Vector2 uv2 )
{
Vector3 u = CrossWithUpVector( n );
Debug.Assert( u.IsSane(), "Vector contains invalid number" );
if (Vector3.Dot( u, u ) < 0.01f)
u = Vector3.right;
else
u = u.normalized;
Debug.Assert( u.IsSane(), "Vector contains invalid number" );
Vector3 v = (Vector3.Cross(n, u)).normalized;
Debug.Assert( v.IsSane(), "Vector contains invalid number" );
uv0 = new Vector2( Vector3.Dot( v0, u ), Vector3.Dot( v0, v ) );
uv1 = new Vector2( Vector3.Dot( v1, u ), Vector3.Dot( v1, v ) );
uv2 = new Vector2( Vector3.Dot( v2, u ), Vector3.Dot( v2, v ) );
Debug.Assert( uv0.IsSane() && uv1.IsSane() && uv2.IsSane(), "Vector contains invalid number" );
}
// It works! Verified.
public static bool IsPointInsideConvexHull( Vector3 point, List<Vector3> verts, List<int> tris )
{
for (int i = 0;i < tris.Count; i+=3)
{
var i0 = tris[i];
var i1 = tris[i+1];
var i2 = tris[i+2];
Vector3 v1 = verts[i0];
Vector3 v2 = verts[i1];
Vector3 v3 = verts[i2];
Vector3 triNormal = Vector3.Cross(v3 - v1, v2 - v1).normalized;
float side = Vector3.Dot(point - v1, triNormal);
if (side < 0)
return false;
}
return true;
}
// It works! Verified.
public static bool IsBoundingBoxInsideConvexHull( List<Vector3> convexHull, Bounds boundingBox )
{
// The number of edges in the convex hull
int edgeCount = convexHull.Count;
// A variable to keep track of whether the bounding box is inside the convex hull or not
bool isInside = true;
for (int i = 0;i < edgeCount;i++)
{
// The current edge
Vector3 edge = convexHull[(i + 1) % edgeCount] - convexHull[i];
// The normal of the current edge
Vector3 normal = Vector3.Cross(edge, Vector3.up).normalized;
// The minimum and maximum values of the projection of the convex hull onto the current normal
float minConvexHull = float.PositiveInfinity;
float maxConvexHull = float.NegativeInfinity;
// Project all the points of the convex hull onto the current normal
for (int j = 0;j < edgeCount;j++)
{
float projection = Vector3.Dot(convexHull[j], normal);
minConvexHull = Mathf.Min( minConvexHull, projection );
maxConvexHull = Mathf.Max( maxConvexHull, projection );
}
// The minimum and maximum values of the projection of the bounding box onto the current normal
float minBoundingBox = float.PositiveInfinity;
float maxBoundingBox = float.NegativeInfinity;
// Project the 8 corners of the bounding box onto the current normal
for (int j = 0;j < 8;j++)
{
Vector3 corner = boundingBox.min + new Vector3(boundingBox.size.x * (j & 1), boundingBox.size.y * ((j >> 1) & 1), boundingBox.size.z * (j >> 2));
float projection = Vector3.Dot(corner, normal);
minBoundingBox = Mathf.Min( minBoundingBox, projection );
maxBoundingBox = Mathf.Max( maxBoundingBox, projection );
}
// If the maximum value of the convex hull projection is less than the minimum value of the bounding box projection or vice versa, then there is no intersection and the bounding box is not inside the convex hull.
if (maxConvexHull < minBoundingBox || minConvexHull > maxBoundingBox)
{
isInside = false;
break;
}
}
return isInside;
}
// It Works! Computes volume of mesh (must be convex).
public static float CalcVolume( List<Vector3> verts, List<int> tris, List<Vector3> normals )
{
float volume = 0;
for (int t = 0;t < tris.Count;t += 3)
{
var i0 = tris[t+0];
var i1 = tris[t+1];
var i2 = tris[t+2];
Vector3 v0 = verts[i0];
Vector3 v1 = verts[i1];
Vector3 v2 = verts[i2];
Vector3 cr = Vector3.Cross( (v1-v0), (v2-v0) );
Vector3 n = cr.normalized;
float area = cr.magnitude * 0.5f;
float h = -Vector3.Dot( verts[0] - v0, n );
float v = (area * h)/3;
volume += v;
}
return volume;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: f146ce771711d0a458653e9d45bbc351
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace Wander
{
public static class MathUtil
{
public static void ClampAngle360( ref float ang )
{
const float oneOver = 1.0f / 360;
if (ang < 0) ang -= Mathf.FloorToInt( ang * oneOver ) * 360;
if (ang > 360) ang -= Mathf.FloorToInt( ang * oneOver ) * 360;
}
public static int ClampAngle360Int( float ang )
{
ClampAngle360( ref ang );
int iAng = Mathf.RoundToInt(ang);
Debug.Assert( iAng >= 0 && iAng <= 360 );
return iAng;
}
public static float DistSq( this Vector3 a, Vector3 b )
{
Vector3 diff = a-b;
return Vector3.Dot( diff, diff );
}
// Function for life
public static float Friction( float friction, float dt )
{
return Mathf.Clamp( Mathf.Exp( -friction * dt ), 0.0f, 1.0f );
}
public static float Smooth( float smooth, float dt )
{
return (1.0f - Friction( smooth, dt ));
}
public static void AnimateWithAccel( ref float speed, float accel, float maxSpeed, float friction, float dt, bool isAccelerating )
{
if (isAccelerating)
{
speed += accel*dt;
if (speed > maxSpeed) speed = maxSpeed;
}
else
{
speed *= Friction( friction, dt );
}
}
public static bool IsSane( this float f )
{
return f >= float.MinValue && f <= float.MaxValue;
}
public static bool IsSane( this Vector2 v )
{
return v.x.IsSane() && v.y.IsSane();
}
public static bool IsSane( this Vector3 v )
{
return v.x.IsSane() && v.y.IsSane() && v.z.IsSane();
}
public static bool IsSane( this double d )
{
return d >= double.MinValue && d <= double.MaxValue;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 4a9f3579e216686489d8c71f5a5f1c80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Buffers;
using System.Diagnostics;
using System.IO;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Rendering;
using System.Linq;
using System.Threading.Tasks;
namespace Wander
{
/* Generalized naming for loading mesh array's from formats like .Obj, .Ply, .STL, etc. */
public struct MeshArrays
{
public Vector3 [] vertices;
public Vector3 [] normals;
public Color [] colors;
public int [] indices;
public Mesh ToMesh()
{
Stopwatch st = new Stopwatch();
st.Start();
Mesh m = new Mesh();
m.indexFormat = IndexFormat.UInt32;
m.SetVertices( vertices );
m.SetNormals( normals );
m.SetColors( colors );
if (indices == null || indices.Length == 0)
{
// Assume all points
UnityEngine.Debug.Log( "No Indices found -> Assuming all points" );
int [] indices = new int[vertices.Length];
for (int i = 0;i < vertices.Length;i++)
indices[i] = i;
m.SetIndices( indices, MeshTopology.Points, 0 );
}
else
{
// Assume triangles
if (indices.Length % 3 == 0)
m.SetIndices( indices, MeshTopology.Triangles, 0 );
else if (indices.Length % 4 == 0)
m.SetIndices( indices, MeshTopology.Quads, 0 );
}
st.Stop();
UnityEngine.Debug.Log( nameof( ToMesh ) + " call time: " + st.Elapsed.TotalSeconds + " seconds" );
return m;
}
}
/* Generalized naming for loading mesh array's from formats like .Obj, .Ply, .STL, etc. */
public struct MeshNativeArrays
{
[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential )]
public struct Vertex
{
public Vector3 pos;
public Vector3 nor;
public Color col;
}
public NativeArray<Vertex> vertices;
public NativeArray<int> indices;
bool disposed;
public Mesh ToMeshPositionNormalColor( bool markUploadedMeshNoLongerReadable )
{
Stopwatch st = new Stopwatch();
st.Start();
var flags = MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontRecalculateBounds;
Mesh m = new Mesh();
m.indexFormat = IndexFormat.UInt32;
var layout = new[]
{
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4),
};
m.SetVertexBufferParams( vertices.Length, layout );
m.SetVertexBufferData( vertices, 0, 0, vertices.Length, 0, flags );
m.SetIndexBufferParams( indices.Length, IndexFormat.UInt32 );
m.SetIndexBufferData( indices, 0, 0, indices.Length, flags );
var submesh = new []
{
new SubMeshDescriptor(0, indices.Length, MeshTopology.Triangles)
};
m.SetSubMeshes( submesh, flags );
m.RecalculateBounds( MeshUpdateFlags.DontValidateIndices|MeshUpdateFlags.DontNotifyMeshUsers|MeshUpdateFlags.DontResetBoneBounds );
m.UploadMeshData( markUploadedMeshNoLongerReadable );
st.Stop();
// UnityEngine.Debug.Log( nameof( ToMeshPositionNormalColor ) + " call time: " + st.Elapsed.TotalSeconds + " seconds" );
return m;
}
public unsafe static MeshNativeArrays FromCache( string file )
{
MeshNativeArrays arr = new MeshNativeArrays();
arr.disposed = true;
if (!File.Exists( file ))
return arr;
using var fs = new BinaryReader( File.Open( file, FileMode.Open ) );
int numVertices = fs.ReadInt32();
int numIndices = fs.ReadInt32();
arr.vertices = new NativeArray<Vertex>( numVertices, Allocator.Persistent, NativeArrayOptions.UninitializedMemory );
arr.indices = new NativeArray<int>( numIndices, Allocator.Persistent, NativeArrayOptions.UninitializedMemory );
void* pVertices = NativeArrayUnsafeUtility.GetUnsafePtr( arr.vertices );
void* pIndices = NativeArrayUnsafeUtility.GetUnsafePtr( arr.indices );
arr.disposed = false;
var spanVertices = new Span<byte>( pVertices, sizeof( Vertex )*numVertices );
var spanIndices = new Span<byte>( pIndices, sizeof( int )*numIndices );
byte [] byteVertices = ArrayPool<byte>.Shared.Rent( sizeof( Vertex )*numVertices );
byte [] byteIndices = ArrayPool<byte>.Shared.Rent( sizeof( int )*numIndices );
try
{
fs.Read( byteVertices, 0, sizeof( Vertex )*numVertices );
fs.Read( byteIndices, 0, sizeof( int )*numIndices );
byteVertices.CopyTo( pVertices, sizeof( Vertex )*numVertices );
byteIndices.CopyTo( pIndices, sizeof( int )*numIndices );
}
finally
{
ArrayPool<byte>.Shared.Return( byteVertices );
ArrayPool<byte>.Shared.Return( byteIndices );
}
return arr;
}
public unsafe void ToCache( string file )
{
if (disposed || !vertices.IsCreated || !indices.IsCreated || vertices.Length < 1024 || indices.Length < 1024)
return;
using (var fs = new BinaryWriter( File.Open( file, FileMode.Create ) ))
{
fs.Write( vertices.Length );
fs.Write( indices.Length );
void* pVertices = NativeArrayUnsafeUtility.GetUnsafePtr( vertices );
void* pIndces = NativeArrayUnsafeUtility.GetUnsafePtr( indices );
fs.Write( new ReadOnlySpan<byte>( pVertices, vertices.Length*sizeof( Vertex ) ) );
fs.Write( new ReadOnlySpan<byte>( pIndces, indices.Length*sizeof( int ) ) );
}
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
var thisCpy = this;
Task.Run( () =>
{
if (thisCpy.vertices.IsCreated) thisCpy.vertices.Dispose();
if (thisCpy.indices.IsCreated) thisCpy.indices.Dispose();
} );
}
}
}
public struct PointCloudNativeArrays
{
[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential )]
public struct Vertex
{
public Vector3 pos;
public Color col;
}
public NativeArray<Vertex> vertices;
bool disposed;
public Vector3 [] ToPositionsAndDispose()
{
var array = vertices.ToArray().Select( v => v.pos ).ToArray();
Dispose();
return array;
}
public Mesh ToMeshPositionColor( bool markUploadedMeshNoLongerReadable )
{
Stopwatch st = new Stopwatch();
st.Start();
var flags = MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontRecalculateBounds;
Mesh m = new Mesh();
var layout = new[]
{
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.Float32, 4),
};
m.SetVertexBufferParams( vertices.Length, layout );
m.SetVertexBufferData( vertices, 0, 0, vertices.Length, 0, flags );
int [] indices = new int [vertices.Length];
for (int i = 0;i < indices.Length;i++) indices[i] = i;
m.SetIndexBufferParams( indices.Length, IndexFormat.UInt32 );
m.SetIndexBufferData( indices, 0, 0, indices.Length, flags );
var submesh = new []
{
new SubMeshDescriptor(0, indices.Length, MeshTopology.Points)
};
m.SetSubMeshes( submesh, flags );
m.RecalculateBounds( flags );
m.UploadMeshData( markUploadedMeshNoLongerReadable );
st.Stop();
// UnityEngine.Debug.Log( nameof( ToMeshPositionNormalColor ) + " call time: " + st.Elapsed.TotalSeconds + " seconds" );
return m;
}
public unsafe static PointCloudNativeArrays FromCache( string file )
{
PointCloudNativeArrays arr = new PointCloudNativeArrays();
arr.disposed = true;
if (!File.Exists( file ))
return arr;
using var fs = new BinaryReader( File.Open( file, FileMode.Open ) );
int numVertices = fs.ReadInt32();
int numIndices = fs.ReadInt32();
arr.vertices = new NativeArray<Vertex>( numVertices, Allocator.Persistent, NativeArrayOptions.UninitializedMemory );
void* pVertices = NativeArrayUnsafeUtility.GetUnsafePtr( arr.vertices );
arr.disposed = false;
var spanVertices = new Span<byte>( pVertices, sizeof( Vertex )*numVertices );
byte [] byteVertices = ArrayPool<byte>.Shared.Rent( sizeof( Vertex )*numVertices );
byte [] byteIndices = ArrayPool<byte>.Shared.Rent( sizeof( int )*numIndices );
try
{
fs.Read( byteVertices, 0, sizeof( Vertex )*numVertices );
fs.Read( byteIndices, 0, sizeof( int )*numIndices );
byteVertices.CopyTo( pVertices, sizeof( Vertex )*numVertices );
}
finally
{
ArrayPool<byte>.Shared.Return( byteVertices );
ArrayPool<byte>.Shared.Return( byteIndices );
}
return arr;
}
public unsafe void ToCache( string file )
{
if (disposed || !vertices.IsCreated || vertices.Length < 1024 )
return;
Directory.CreateDirectory( Path.GetDirectoryName( file ) );
using (var fs = new BinaryWriter( File.Open( file, FileMode.CreateNew ) ))
{
fs.Write( vertices.Length );
void* pVertices = NativeArrayUnsafeUtility.GetUnsafePtr( vertices );
fs.Write( new ReadOnlySpan<byte>( pVertices, vertices.Length*sizeof( Vertex ) ) );
}
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
var thisCpy = this;
Task.Run( () =>
{
if (thisCpy.vertices.IsCreated) thisCpy.vertices.Dispose();
} );
}
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 355d5f7fe96e9ab46bd2e64d2eb1e492
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace Wander
{
public static class MiscUtils
{
public static T Random<T>( this T[] arr )
{
return arr[UnityEngine.Random.Range( 0, arr.Length )];
}
public static T Random<T>( this T[] arr, int min, int count )
{
return arr[UnityEngine.Random.Range( min, Mathf.Min( count, arr.Length ) )];
}
public static T Random<T>( this List<T> list )
{
return list[UnityEngine.Random.Range( 0, list.Count )];
}
public static T Random<T>( this List<T> list, int min, int count )
{
return list[UnityEngine.Random.Range( min, Mathf.Min( count, list.Count ) )];
}
public static KeyValuePair<T, R> Random<T, R>( this Dictionary<T, R> dic )
{
int r = UnityEngine.Random.Range(0, dic.Count);
foreach (var kvp in dic)
if (r-- == 0)
return kvp;
throw new System.InvalidOperationException( "Dictionary does not contain elements" );
}
public static KeyValuePair<T, R> Random<T, R>( this Dictionary<T, R> dic, int min, int count )
{
int r = UnityEngine.Random.Range(0, count) + min;
foreach (var kvp in dic)
if (r-- == 0)
return kvp;
throw new System.InvalidOperationException( "Min/count out of dictionary range" );
}
public static string ToAssetsPath( this string fullPath, bool includeAssets = true )
{
string result = fullPath.Replace( Application.dataPath, "" );
if (includeAssets)
{
result = "Assets" + result;
}
return result.NormalizePath();
}
public static string NormalizePath( this string path )
{
return path.Replace( '\\', '/' ).Trim( '/' );
}
/* Converts , to ., then does the parse. */
public static float ToFloat( this string s )
{
s = s.Replace( ',', '.' );
try
{
return float.Parse( s, System.Globalization.CultureInfo.InvariantCulture );
}
catch (Exception e)
{
UnityEngine.Debug.LogException( e );
return 0;
}
}
public static double ToDouble( this string s )
{
s = s.Replace( ',', '.' );
try
{
return double.Parse( s, System.Globalization.CultureInfo.InvariantCulture );
}
catch (Exception e)
{
UnityEngine.Debug.LogException( e );
return 0;
}
}
public static int ParseInt( string s )
{
if (string.IsNullOrEmpty( s ))
return 0;
bool isNegative = s[0] == '-';
int res = 0;
int i = isNegative ? 1 : 0;
char c = s[i];
while (c != '\0')
{
if (c < '0' || c > '9')
return 0; // weird character (could also switch to int.parse here if desired
res = (res * 10) + (c - '0');
if (++i == s.Length)
break;
c = s[i];
}
return res * (isNegative ? -1 : 1);
}
static readonly double[] _denoms =
{
1,
1/10.0,
1/100.0,
1/1000.0,
1/10000.0,
1/100000.0,
1/1000000.0,
1/10000000.0,
1/100000000.0,
1/1000000000.0,
1/10000000000.0,
1/100000000000.0,
1/1000000000000.0,
1/10000000000000.0,
1/100000000000000.0,
1/1000000000000000.0,
1/10000000000000000.0,
1/100000000000000000.0,
1/1000000000000000000.0,
};
public static double ParseDouble( string s )
{
if (string.IsNullOrEmpty( s ))
return 0;
long res = 0;
bool isNegative = s[0] =='-';
int i = isNegative ? 1 : 0;
char c = s[i];
int decimalPos = -1;
while (c != '\0')
{
if (c == '.')
decimalPos = i;
else if (c >= '0' && c <= '9')
res = (res * 10) + (c - '0');
else
{ // weird character inside
if (double.TryParse( s, out double dd ))
return dd;
return 0;
}
if (++i == s.Length)
break;
c = s[i];
}
double d = res;
if (decimalPos != -1) d *= _denoms[i-decimalPos-1];
if (isNegative) d = -d;
return d;
}
public static void Destroy( this UnityEngine.Object o )
{
if (o == null) return;
if (o is Transform transform)
{
o = transform.gameObject;
}
if (!Application.isPlaying)
UnityEngine.Object.DestroyImmediate( o );
else
UnityEngine.Object.Destroy( o );
}
public static void SetLayerRecursively( this GameObject go, int layer )
{
if (go == null)
return;
go.layer = layer;
for (int i = 0;i< go.transform.childCount;i++)
{
SetLayerRecursively( go.transform.GetChild( i ).gameObject, layer );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static bool Raycast( this Vector3 pos, Vector3 dir, float dist, LayerMask mask, out RaycastHit hit )
{
return Physics.Raycast( pos, dir, out hit, dist, mask );
}
// This does not return a zero vector on a 'random threshold set by unity' when it finds the vector too small to do a normalize.
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Vector3 normalize2( this Vector3 v )
{
float l = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
// do not check for 'almost zero'
if (l == 0) return Vector3.zero;
// just try normalize
l = 1.0f/l;
return v*l;
}
public static T GetOrAddComponent<T>( this GameObject go ) where T : Component
{
if (go == null)
return null;
var c = go.GetComponent<T>();
if (c == null)
c = go.AddComponent<T>();
return c;
}
public static List<double[]> CsvToDoubles( string path, char delim )
{
List<double[]> result = new List<double[]>();
if (!File.Exists( path ))
return result;
string [] rows = File.ReadAllLines( path );
for (int i = 1;i < rows.Length;i++)
{
string [] cells = rows[i].Split( delim );
double [] vs = new double[cells.Length];
for (int j = 0;j < cells.Length;j++)
{
vs[j] = cells[j].ToDouble();
}
result.Add( vs );
}
return result;
}
public static Transform FindChildRecursive2( this Transform parent, string name )
{
foreach (Transform child in parent)
{
if (child.name == name)
return child;
var result = child.FindChildRecursive2(name);
if (result != null)
return result;
}
return null;
}
public static bool HasContent( this string s )
{
return !string.IsNullOrWhiteSpace( s );
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static void RemoveSwapBack2<T>( this List<T> list, Func<T, bool> predicate )
{
for (int i = 0;i < list.Count;i++)
{
if (predicate( list[i] ))
{
list[i] = list[list.Count-1]; // If has only 1 element, copies itself.
list.RemoveAt( list.Count-1 );
}
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static void ReplaceOrAdd<T>( this List<T> list, Func<T, bool> predicate, T item )
{
for (int i = 0;i < list.Count;i++)
{
if (predicate( list[i] ))
{
list[i] = item;
return;
}
}
list.Add( item );
}
// https://stackoverflow.com/questions/19497765/equivalent-of-cs-reinterpret-cast-in-c-sharp
public static unsafe TDest ReinterpretCast<TSource, TDest>( TSource source )
{
var sourceRef = __makeref(source);
var dest = default(TDest);
var destRef = __makeref(dest);
*(IntPtr*)&destRef = *(IntPtr*)&sourceRef;
return __refvalue(destRef, TDest);
}
public static Color RandomColor( Color lowRandom, Color highRandom )
{
return new Color(
UnityEngine.Random.Range( lowRandom.r, highRandom.r ),
UnityEngine.Random.Range( lowRandom.g, highRandom.g ),
UnityEngine.Random.Range( lowRandom.b, highRandom.b )
);
}
public static Material LitMaterialFromColor( Color c )
{
var baseFromShader = Shader.Find( "Universal Render Pipeline/Lit" );
var m = new Material( baseFromShader );
m.color = c;
return m;
}
public static void StopAndPrintTiming( this Stopwatch sw, string text )
{
sw.Stop();
UnityEngine.Debug.Log( text + " took: " + sw.ElapsedMilliseconds+"ms" );
}
// Thank you internet.
public static void DrawBox( Vector3 pos, Quaternion rot, Vector3 scale, Color c )
{
Matrix4x4 m = new Matrix4x4();
m.SetTRS( pos, rot, scale );
var point1 = m.MultiplyPoint(new Vector3(-0.5f, -0.5f, 0.5f));
var point2 = m.MultiplyPoint(new Vector3(0.5f, -0.5f, 0.5f));
var point3 = m.MultiplyPoint(new Vector3(0.5f, -0.5f, -0.5f));
var point4 = m.MultiplyPoint(new Vector3(-0.5f, -0.5f, -0.5f));
var point5 = m.MultiplyPoint(new Vector3(-0.5f, 0.5f, 0.5f));
var point6 = m.MultiplyPoint(new Vector3(0.5f, 0.5f, 0.5f));
var point7 = m.MultiplyPoint(new Vector3(0.5f, 0.5f, -0.5f));
var point8 = m.MultiplyPoint(new Vector3(-0.5f, 0.5f, -0.5f));
UnityEngine.Debug.DrawLine( point1, point2, c );
UnityEngine.Debug.DrawLine( point2, point3, c );
UnityEngine.Debug.DrawLine( point3, point4, c );
UnityEngine.Debug.DrawLine( point4, point1, c );
UnityEngine.Debug.DrawLine( point5, point6, c );
UnityEngine.Debug.DrawLine( point6, point7, c );
UnityEngine.Debug.DrawLine( point7, point8, c );
UnityEngine.Debug.DrawLine( point8, point5, c );
UnityEngine.Debug.DrawLine( point1, point5, c );
UnityEngine.Debug.DrawLine( point2, point6, c );
UnityEngine.Debug.DrawLine( point3, point7, c );
UnityEngine.Debug.DrawLine( point4, point8, c );
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment