Repository: staff0rd/polygon-map-unity Branch: master Commit: 4d1796dffd93 Files: 91 Total size: 156.4 KB Directory structure: gitextract_80dnjzni/ ├── .gitignore ├── MIT-LICENSE ├── README.md └── demo/ ├── Assets/ │ ├── Camera.cs │ ├── Camera.cs.meta │ ├── Demo.unity │ ├── Demo.unity.meta │ ├── Extensions/ │ │ ├── Vector2Extensions.cs │ │ └── Vector2Extensions.cs.meta │ ├── Extensions.meta │ ├── Main.cs │ ├── Main.cs.meta │ ├── Map/ │ │ ├── Biome.cs │ │ ├── Biome.cs.meta │ │ ├── Center.cs │ │ ├── Center.cs.meta │ │ ├── Corner.cs │ │ ├── Corner.cs.meta │ │ ├── Edge.cs │ │ ├── Edge.cs.meta │ │ ├── Graph.cs │ │ ├── Graph.cs.meta │ │ ├── IslandShape.cs │ │ ├── IslandShape.cs.meta │ │ ├── Map.cs │ │ ├── Map.cs.meta │ │ ├── MapTexture.cs │ │ └── MapTexture.cs.meta │ ├── Map.meta │ ├── Materials/ │ │ ├── Selector.mat │ │ └── Selector.mat.meta │ ├── Materials.meta │ ├── Unity-delaunay/ │ │ ├── Delaunay/ │ │ │ ├── DelaunayHelpers.cs │ │ │ ├── DelaunayHelpers.cs.meta │ │ │ ├── Edge.cs │ │ │ ├── Edge.cs.meta │ │ │ ├── EdgeList.cs │ │ │ ├── EdgeList.cs.meta │ │ │ ├── EdgeReorderer.cs │ │ │ ├── EdgeReorderer.cs.meta │ │ │ ├── Halfedge.cs │ │ │ ├── Halfedge.cs.meta │ │ │ ├── HalfedgePriorityQueue.cs │ │ │ ├── HalfedgePriorityQueue.cs.meta │ │ │ ├── ICoord.cs │ │ │ ├── ICoord.cs.meta │ │ │ ├── LR.cs │ │ │ ├── LR.cs.meta │ │ │ ├── Site.cs │ │ │ ├── Site.cs.meta │ │ │ ├── SiteList.cs │ │ │ ├── SiteList.cs.meta │ │ │ ├── Triangle.cs │ │ │ ├── Triangle.cs.meta │ │ │ ├── Vertex.cs │ │ │ ├── Vertex.cs.meta │ │ │ ├── Voronoi.cs │ │ │ └── Voronoi.cs.meta │ │ ├── Delaunay.meta │ │ ├── Plane Material.mat │ │ ├── Plane Material.mat.meta │ │ ├── geom/ │ │ │ ├── Circle.cs │ │ │ ├── Circle.cs.meta │ │ │ ├── LineSegment.cs │ │ │ ├── LineSegment.cs.meta │ │ │ ├── Polygon.cs │ │ │ ├── Polygon.cs.meta │ │ │ ├── Winding.cs │ │ │ └── Winding.cs.meta │ │ ├── geom.meta │ │ ├── utils/ │ │ │ ├── IDisposable.cs │ │ │ └── IDisposable.cs.meta │ │ └── utils.meta │ └── Unity-delaunay.meta └── ProjectSettings/ ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # =============== # # Unity generated # # =============== # Temp/ Obj/ UnityGenerated/ Library/ # ===================================== # # Visual Studio / MonoDevelop generated # # ===================================== # ExportedObj/ *.svd *.userprefs *.csproj *.pidb *.suo *.sln *.user *.unityproj *.booproj .vs # ============ # # OS generated # # ============ # .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes Icon? ehthumbs.db Thumbs.db demo/Assets/UnityVS/ ================================================ FILE: MIT-LICENSE ================================================ Copyright (c) 2009 Alan Shaw Unity C# Translation Copyright (c) 2014 Julian Ceipek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ polygon-map-unity ============== A C#/Unity3d implementation of Polygon Map Generation per the article [here](http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/), using the as3delaunay library from [here](https://github.com/jceipek/Unity-delaunay) ![Polygon Map Generator](/screenshot.PNG?raw=true) ================================================ FILE: demo/Assets/Camera.cs ================================================ using UnityEngine; using System.Collections; using Assets.Map; public class Camera : MonoBehaviour { public Map Map; float _mousePosX; float _mousePosY; float _scrollSpeed = 0.2f; float _zoomSpeed = 1f; Vector2 _mouseLeftClick; void Update() { float deltaX = Input.mousePosition.x - _mousePosX; float deltaY = Input.mousePosition.y - _mousePosY; _mousePosX = Input.mousePosition.x; _mousePosY = Input.mousePosition.y; if (Input.GetMouseButton(0)) { Ray ray = GetComponent().ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { _mouseLeftClick = hit.point; Map.Click(_mouseLeftClick); } } if (Input.GetMouseButton(1)) { var newX = Mathf.Clamp(transform.parent.position.x + deltaX * _scrollSpeed, 0, Map.Width); var newY = Mathf.Clamp(transform.parent.position.y + deltaY * _scrollSpeed, 0, Map.Height); transform.parent.position = new Vector3(newX, newY, transform.parent.position.z); } if (Input.GetAxis("Mouse ScrollWheel") < 0 && transform.parent.localPosition.z > -20) { transform.parent.Translate(new Vector3(0, 0, -_zoomSpeed)); } if (Input.GetAxis("Mouse ScrollWheel") > 0 && transform.parent.localPosition.z < -5) { transform.parent.Translate(new Vector3(0, 0, _zoomSpeed)); } } } ================================================ FILE: demo/Assets/Camera.cs.meta ================================================ fileFormatVersion: 2 guid: ebee29ebdbfbce74297756dd0f6f3a0f MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Demo.unity ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!29 &1 SceneSettings: m_ObjectHideFlags: 0 m_PVSData: m_PVSObjectsArray: [] m_PVSPortalsArray: [] m_OcclusionBakeSettings: smallestOccluder: 5 smallestHole: .25 backfaceThreshold: 100 --- !u!104 &2 RenderSettings: m_Fog: 0 m_FogColor: {r: .5, g: .5, b: .5, a: 1} m_FogMode: 3 m_FogDensity: .00999999978 m_LinearFogStart: 0 m_LinearFogEnd: 300 m_AmbientLight: {r: .200000003, g: .200000003, b: .200000003, a: 1} m_SkyboxMaterial: {fileID: 0} m_HaloStrength: .5 m_FlareStrength: 1 m_FlareFadeSpeed: 3 m_HaloTexture: {fileID: 0} m_SpotCookie: {fileID: 0} m_ObjectHideFlags: 0 --- !u!127 &3 LevelGameManager: m_ObjectHideFlags: 0 --- !u!157 &4 LightmapSettings: m_ObjectHideFlags: 0 m_LightProbes: {fileID: 0} m_Lightmaps: [] m_LightmapsMode: 1 m_BakedColorSpace: 0 m_UseDualLightmapsInForward: 0 m_LightmapEditorSettings: m_Resolution: 50 m_LastUsedResolution: 0 m_TextureWidth: 1024 m_TextureHeight: 1024 m_BounceBoost: 1 m_BounceIntensity: 1 m_SkyLightColor: {r: .860000014, g: .930000007, b: 1, a: 1} m_SkyLightIntensity: 0 m_Quality: 0 m_Bounces: 1 m_FinalGatherRays: 1000 m_FinalGatherContrastThreshold: .0500000007 m_FinalGatherGradientThreshold: 0 m_FinalGatherInterpolationPoints: 15 m_AOAmount: 0 m_AOMaxDistance: .100000001 m_AOContrast: 1 m_LODSurfaceMappingDistance: 1 m_Padding: 0 m_TextureCompression: 0 m_LockAtlas: 0 --- !u!196 &5 NavMeshSettings: m_ObjectHideFlags: 0 m_BuildSettings: agentRadius: .5 agentHeight: 2 agentSlope: 45 agentClimb: .400000006 ledgeDropHeight: 0 maxJumpAcrossDistance: 0 accuratePlacement: 0 minRegionArea: 2 widthInaccuracy: 16.666666 heightInaccuracy: 10 m_NavMesh: {fileID: 0} --- !u!1 &620502837 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 4 m_Component: - 4: {fileID: 620502838} m_Layer: 0 m_Name: Camera m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!4 &620502838 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 620502837} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 25, y: 25, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 2037205295} - {fileID: 818690204} m_Father: {fileID: 0} m_RootOrder: 1 --- !u!1 &818690203 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 4 m_Component: - 4: {fileID: 818690204} - 108: {fileID: 818690205} m_Layer: 0 m_Name: Directional light m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!4 &818690204 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 818690203} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 620502838} m_RootOrder: 1 --- !u!108 &818690205 Light: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 818690203} m_Enabled: 1 serializedVersion: 3 m_Type: 1 m_Color: {r: 1, g: 1, b: 1, a: 1} m_Intensity: .5 m_Range: 10 m_SpotAngle: 30 m_CookieSize: 10 m_Shadows: m_Type: 0 m_Resolution: -1 m_Strength: 1 m_Bias: .0500000007 m_Softness: 4 m_SoftnessFade: 1 m_Cookie: {fileID: 0} m_DrawHalo: 0 m_ActuallyLightmapped: 0 m_Flare: {fileID: 0} m_RenderMode: 0 m_CullingMask: serializedVersion: 2 m_Bits: 4294967295 m_Lightmapping: 1 m_ShadowSamples: 1 m_ShadowRadius: 0 m_ShadowAngle: 0 m_IndirectIntensity: 1 m_AreaSize: {x: 1, y: 1} --- !u!1 &1071619055 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 4 m_Component: - 4: {fileID: 1071619059} - 33: {fileID: 1071619058} - 135: {fileID: 1071619057} - 23: {fileID: 1071619056} m_Layer: 0 m_Name: Selector m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!23 &1071619056 Renderer: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1071619055} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 m_LightmapIndex: 255 m_LightmapTilingOffset: {x: 1, y: 1, z: 0, w: 0} m_Materials: - {fileID: 2100000, guid: 6dca14a4c7e41c646a06c11e677259d1, type: 2} m_SubsetIndices: m_StaticBatchRoot: {fileID: 0} m_UseLightProbes: 0 m_LightProbeAnchor: {fileID: 0} m_ScaleInLightmap: 1 m_SortingLayerID: 0 m_SortingOrder: 0 --- !u!135 &1071619057 SphereCollider: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1071619055} m_Material: {fileID: 0} m_IsTrigger: 0 m_Enabled: 1 serializedVersion: 2 m_Radius: .5 m_Center: {x: 0, y: 0, z: 0} --- !u!33 &1071619058 MeshFilter: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1071619055} m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} --- !u!4 &1071619059 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1071619055} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 11.3982372, y: 29.8553162, z: -14.5} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 2 --- !u!1 &1149984434 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 4 m_Component: - 4: {fileID: 1149984438} - 33: {fileID: 1149984437} - 64: {fileID: 1149984436} - 23: {fileID: 1149984435} - 114: {fileID: 1149984439} m_Layer: 0 m_Name: Map m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!23 &1149984435 Renderer: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1149984434} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 m_LightmapIndex: 255 m_LightmapTilingOffset: {x: 1, y: 1, z: 0, w: 0} m_Materials: - {fileID: 2100000, guid: 361fa52b5561d434baaff15f2fe36f3d, type: 2} m_SubsetIndices: m_StaticBatchRoot: {fileID: 0} m_UseLightProbes: 0 m_LightProbeAnchor: {fileID: 0} m_ScaleInLightmap: 1 m_SortingLayerID: 0 m_SortingOrder: 0 --- !u!64 &1149984436 MeshCollider: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1149984434} m_Material: {fileID: 0} m_IsTrigger: 0 m_Enabled: 1 serializedVersion: 2 m_SmoothSphereCollisions: 0 m_Convex: 0 m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} --- !u!33 &1149984437 MeshFilter: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1149984434} m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} --- !u!4 &1149984438 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1149984434} m_LocalRotation: {x: 0, y: .707106829, z: -.707106829, w: 0} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 5, y: 5, z: 5} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 --- !u!114 &1149984439 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1149984434} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 6b8eb48d5779546089555c7b0bd5341e, type: 3} m_Name: m_EditorClassIdentifier: --- !u!1 &2037205290 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 4 m_Component: - 4: {fileID: 2037205295} - 20: {fileID: 2037205294} - 92: {fileID: 2037205293} - 124: {fileID: 2037205292} - 81: {fileID: 2037205291} - 114: {fileID: 2037205296} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!81 &2037205291 AudioListener: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_Enabled: 1 --- !u!124 &2037205292 Behaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_Enabled: 1 --- !u!92 &2037205293 Behaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_Enabled: 1 --- !u!20 &2037205294 Camera: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_Enabled: 1 serializedVersion: 2 m_ClearFlags: 1 m_BackGroundColor: {r: 0, g: 0, b: 0, a: .0196078438} m_NormalizedViewPortRect: serializedVersion: 2 x: 0 y: 0 width: 1 height: 1 near clip plane: .300000012 far clip plane: 1000 field of view: 60 orthographic: 0 orthographic size: 30 m_Depth: -1 m_CullingMask: serializedVersion: 2 m_Bits: 4294967295 m_RenderingPath: -1 m_TargetTexture: {fileID: 0} m_TargetDisplay: 0 m_HDR: 0 m_OcclusionCulling: 1 m_StereoConvergence: 10 m_StereoSeparation: .0219999999 --- !u!4 &2037205295 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_LocalRotation: {x: -.258819044, y: 0, z: 0, w: .965925813} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 620502838} m_RootOrder: 0 --- !u!114 &2037205296 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2037205290} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: ebee29ebdbfbce74297756dd0f6f3a0f, type: 3} m_Name: m_EditorClassIdentifier: ================================================ FILE: demo/Assets/Demo.unity.meta ================================================ fileFormatVersion: 2 guid: 79883178826fb4e77a1f5cda54f78635 DefaultImporter: userData: ================================================ FILE: demo/Assets/Extensions/Vector2Extensions.cs ================================================ using System.Collections.Generic; using UnityEngine; using System.Linq; public static class Vector2Extensions { public static Vector2 Interpolate(Vector2 pt1, Vector2 pt2, float f) { var x = f * pt1.x + (1 - f) * pt2.x; var y = f * pt1.y + (1 - f) * pt2.y; return new Vector2(x, y); } public static void DrawLine(this Texture2D tex, int x0, int y0, int x1, int y1, Color col) { int dy = (int)(y1 - y0); int dx = (int)(x1 - x0); int stepx, stepy; if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } dy <<= 1; dx <<= 1; float fraction = 0; tex.SetPixel(x0, y0, col); if (dx > dy) { fraction = dy - (dx >> 1); while (Mathf.Abs(x0 - x1) > 1) { if (fraction >= 0) { y0 += stepy; fraction -= dx; } x0 += stepx; fraction += dy; tex.SetPixel(x0, y0, col); } } else { fraction = dx - (dy >> 1); while (Mathf.Abs(y0 - y1) > 1) { if (fraction >= 0) { x0 += stepx; fraction -= dy; } y0 += stepy; fraction += dx; tex.SetPixel(x0, y0, col); } } } public struct Point { public short x; public short y; public Point(short aX, short aY) { x = aX; y = aY; } public Point(int aX, int aY) : this((short)aX, (short)aY) { } } public static void FillPolygon(this Texture2D texture, Vector2[] points, Color color) { // http://alienryderflex.com/polygon_fill/ var IMAGE_BOT = (int)points.Max(p => p.y); var IMAGE_TOP = (int)points.Min(p => p.y); var IMAGE_LEFT = (int)points.Min(p => p.x); var IMAGE_RIGHT = (int)points.Max(p => p.x); var MAX_POLY_CORNERS = points.Count(); var polyCorners = MAX_POLY_CORNERS; var polyY = points.Select(p => p.y).ToArray(); var polyX = points.Select(p => p.x).ToArray(); int[] nodeX = new int[MAX_POLY_CORNERS]; int nodes, pixelX, i, j, swap; // Loop through the rows of the image. for (int pixelY = IMAGE_TOP; pixelY <= IMAGE_BOT; pixelY++) { // Build a list of nodes. nodes = 0; j = polyCorners - 1; for (i = 0; i < polyCorners; i++) { if (polyY[i] < (float)pixelY && polyY[j] >= (float)pixelY || polyY[j] < (float)pixelY && polyY[i] >= (float)pixelY) { nodeX[nodes++] = (int)(polyX[i] + (pixelY - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i])); } j = i; } // Sort the nodes, via a simple “Bubble” sort. i = 0; while (i < nodes - 1) { if (nodeX[i] > nodeX[i + 1]) { swap = nodeX[i]; nodeX[i] = nodeX[i + 1]; nodeX[i + 1] = swap; if (i != 0) i--; } else { i++; } } // Fill the pixels between node pairs. for (i = 0; i < nodes; i += 2) { if (nodeX[i] >= IMAGE_RIGHT) break; if (nodeX[i + 1] > IMAGE_LEFT) { if (nodeX[i] < IMAGE_LEFT) nodeX[i] = IMAGE_LEFT; if (nodeX[i + 1] > IMAGE_RIGHT) nodeX[i + 1] = IMAGE_RIGHT; for (j = nodeX[i]; j < nodeX[i + 1]; j++) texture.SetPixel(j, pixelY, color); } } } } } ================================================ FILE: demo/Assets/Extensions/Vector2Extensions.cs.meta ================================================ fileFormatVersion: 2 guid: 409695d23ff505645855976e99707c87 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Extensions.meta ================================================ fileFormatVersion: 2 guid: 9a8f1e17724625a4f9126906c5829861 folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Main.cs ================================================ using UnityEngine; using System.Collections.Generic; using Delaunay; using Delaunay.Geo; using System.Linq; using Assets.Map; public class Main : MonoBehaviour { Map _map; const int _textureScale = 50; GameObject _selector; public bool Regenerate; public int Seed; public float PerlinCheckValue = 0.3f; void Update() { if (_map != null && _map.SelectedCenter != null) { _selector.transform.localPosition = new Vector3(_map.SelectedCenter.point.x, _map.SelectedCenter.point.y, 1); } if (Regenerate) { Regenerate = false; Awake(); } } void Awake () { IslandShape.PERLIN_CHECK_VALUE = PerlinCheckValue; _selector = GameObject.Find("Selector"); Random.seed = Seed; _map = new Map(); GameObject.Find("Main Camera").GetComponentInChildren().Map = _map; new MapTexture(_textureScale).AttachTexture(GameObject.Find("Map"), _map); } } ================================================ FILE: demo/Assets/Main.cs.meta ================================================ fileFormatVersion: 2 guid: 6b8eb48d5779546089555c7b0bd5341e MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Biome.cs ================================================ using System.Collections.Generic; using UnityEngine; namespace Assets.Map { public static class BiomeProperties { public static Dictionary Colors = new Dictionary { { Biome.Ocean, HexToColor("44447a") }, //{ COAST, HexToColor("33335a") }, //{ LAKESHORE, HexToColor("225588") }, { Biome.Lake, HexToColor("336699") }, //{ RIVER, HexToColor("225588") }, { Biome.Marsh, HexToColor("2f6666") }, { Biome.Ice, HexToColor("99ffff") }, { Biome.Beach, HexToColor("a09077") }, //{ ROAD1, HexToColor("442211") }, //{ ROAD2, HexToColor("553322") }, //{ ROAD3, HexToColor("664433") }, //{ BRIDGE, HexToColor("686860") }, //{ LAVA, HexToColor("cc3333") }, { Biome.Snow, HexToColor("ffffff") }, { Biome.Tundra, HexToColor("bbbbaa") }, { Biome.Bare, HexToColor("888888") }, { Biome.Scorched, HexToColor("555555") }, { Biome.Taiga, HexToColor("99aa77") }, { Biome.Shrubland, HexToColor("889977") }, { Biome.TemperateDesert, HexToColor("c9d29b") }, { Biome.TemperateRainForest, HexToColor("448855") }, { Biome.TemperateDeciduousForest, HexToColor("679459") }, { Biome.Grassland, HexToColor("88aa55") }, { Biome.SubtropicalDesert, HexToColor("d2b98b") }, { Biome.TropicalRainForest, HexToColor("337755") }, { Biome.TropicalSeasonalForest, HexToColor("559944") } }; static Color HexToColor(string hex) { byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber); byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber); byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber); return new Color32(r, g, b, 255); } } public enum Biome { Ocean, Marsh, Ice, Lake, Beach, Snow, Tundra, Bare, Scorched, Taiga, Shrubland, TemperateDesert, TemperateRainForest, TemperateDeciduousForest, Grassland, TropicalRainForest, TropicalSeasonalForest, SubtropicalDesert } } ================================================ FILE: demo/Assets/Map/Biome.cs.meta ================================================ fileFormatVersion: 2 guid: cecdebe37f8d1974cb9939167f280bdc MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Center.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace Assets.Map { public class Center { public int index; public Vector2 point; // location public bool water; // lake or ocean public bool ocean; // ocean public bool coast; // land polygon touching an ocean public bool border; // at the edge of the map public Biome biome; // biome type public float elevation; // 0.0-1.0 public float moisture; // 0.0-1.0 public List
neighbors = new List
(); public List borders = new List(); public List corners = new List(); public bool PointInside(float x, float y) { // http://alienryderflex.com/polygon/ // Globals which should be set before calling this function: // // int polyCorners = how many corners the polygon has // float polyX[] = horizontal coordinates of corners // float polyY[] = vertical coordinates of corners // float x, y = point to be tested // // (Globals are used in this example for purposes of speed. Change as // desired.) // // The function will return YES if the point x,y is inside the polygon, or // NO if it is not. If the point is exactly on the edge of the polygon, // then the function may return YES or NO. // // Note that division by zero is avoided because the division is protected // by the "if" clause which surrounds it. var polyCorners = corners.Count; int j = polyCorners - 1; bool oddNodes = false; var polyX = corners.Select(p => p.point.x).ToArray(); var polyY = corners.Select(p => p.point.y).ToArray(); for (var i = 0; i < polyCorners; i++) { if ((polyY[i] < y && polyY[j] >= y || polyY[j] < y && polyY[i] >= y) && (polyX[i] <= x || polyX[j] <= x)) { oddNodes ^= (polyX[i] + (y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]) < x); } j = i; } return oddNodes; } } } ================================================ FILE: demo/Assets/Map/Center.cs.meta ================================================ fileFormatVersion: 2 guid: cbea49a0f7f303249bd2f75bb089d732 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Corner.cs ================================================ using System.Collections.Generic; using UnityEngine; namespace Assets.Map { public class Corner { public int index; public Vector2 point; // location public bool ocean; // ocean public bool water; // lake or ocean public bool coast; // touches ocean and land polygons public bool border; // at the edge of the map public float elevation; // 0.0-1.0 public float moisture; // 0.0-1.0 public List
touches = new List
(); public List protrudes = new List(); public List adjacent = new List(); public int river; // 0 if no river, or volume of water in river public Corner downslope; // pointer to adjacent corner most downhill public Corner watershed; // pointer to coastal corner, or null public int watershed_size; } } ================================================ FILE: demo/Assets/Map/Corner.cs.meta ================================================ fileFormatVersion: 2 guid: c7a8fe7402f2c0042b39747d693377ad MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Edge.cs ================================================ using System.Collections.Generic; using UnityEngine; namespace Assets.Map { public class Edge { public int index; public Center d0, d1; // Delaunay edge public Corner v0, v1; // Voronoi edge public Vector2 midpoint; // halfway between v0,v1 public int river; // volume of water, or 0 } } ================================================ FILE: demo/Assets/Map/Edge.cs.meta ================================================ fileFormatVersion: 2 guid: c1a292e422f56c64f87c50773e2aa693 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Graph.cs ================================================ using Delaunay; using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace Assets.Map { public class Graph { List> _cornerMap = new List>(); Func inside; bool _needsMoreRandomness; public int Width { get; private set; } public int Height { get; private set; } public List
centers = new List
(); public List corners = new List(); public List edges = new List(); private List LandCorners { get { return corners.Where(p => !p.ocean && !p.coast).ToList(); } } public Graph(IEnumerable points, Voronoi voronoi, int width, int height, float lakeThreshold) { Width = width; Height = height; inside = IslandShape.makePerlin(); BuildGraph(points, voronoi); AssignCornerElevations(); AssignOceanCoastAndLand(lakeThreshold); RedistributeElevations(); AssignPolygonElevations(); // Determine downslope paths. CalculateDownslopes(); // Determine watersheds: for every corner, where does it flow // out into the ocean? CalculateWatersheds(); // Create rivers. CreateRivers(); // Determine moisture at corners, starting at rivers // and lakes, but not oceans. Then redistribute // moisture to cover the entire range evenly from 0.0 // to 1.0. Then assign polygon moisture as the average // of the corner moisture. AssignCornerMoisture(); RedistributeMoisture(); AssignPolygonMoisture(); centers.ForEach(p => p.biome = GetBiome(p)); } private void BuildGraph(IEnumerable points, Delaunay.Voronoi voronoi) { // Build graph data structure in 'edges', 'centers', 'corners', // based on information in the Voronoi results: point.neighbors // will be a list of neighboring points of the same type (corner // or center); point.edges will be a list of edges that include // that point. Each edge connects to four points: the Voronoi edge // edge.{v0,v1} and its dual Delaunay triangle edge edge.{d0,d1}. // For boundary polygons, the Delaunay edge will have one null // point, and the Voronoi edge may be null. var libedges = voronoi.Edges(); var centerLookup = new Dictionary(); // Build Center objects for each of the points, and a lookup map // to find those Center objects again as we build the graph foreach (var point in points) { var p = new Center { index = centers.Count, point = point }; centers.Add(p); centerLookup[point] = p; } // Workaround for Voronoi lib bug: we need to call region() // before Edges or neighboringSites are available foreach (var p in centers) { voronoi.Region(p.point); } foreach (var libedge in libedges) { var dedge = libedge.DelaunayLine(); var vedge = libedge.VoronoiEdge(); // Fill the graph data. Make an Edge object corresponding to // the edge from the voronoi library. var edge = new Edge { index = edges.Count, river = 0, // Edges point to corners. Edges point to centers. v0 = MakeCorner(vedge.p0), v1 = MakeCorner(vedge.p1), d0 = centerLookup[dedge.p0], d1 = centerLookup[dedge.p1] }; if (vedge.p0.HasValue && vedge.p1.HasValue) edge.midpoint = Vector2Extensions.Interpolate(vedge.p0.Value, vedge.p1.Value, 0.5f); edges.Add(edge); // Centers point to edges. Corners point to edges. if (edge.d0 != null) { edge.d0.borders.Add(edge); } if (edge.d1 != null) { edge.d1.borders.Add(edge); } if (edge.v0 != null) { edge.v0.protrudes.Add(edge); } if (edge.v1 != null) { edge.v1.protrudes.Add(edge); } // Centers point to centers. if (edge.d0 != null && edge.d1 != null) { AddToCenterList(edge.d0.neighbors, edge.d1); AddToCenterList(edge.d1.neighbors, edge.d0); } // Corners point to corners if (edge.v0 != null && edge.v1 != null) { AddToCornerList(edge.v0.adjacent, edge.v1); AddToCornerList(edge.v1.adjacent, edge.v0); } // Centers point to corners if (edge.d0 != null) { AddToCornerList(edge.d0.corners, edge.v0); AddToCornerList(edge.d0.corners, edge.v1); } if (edge.d1 != null) { AddToCornerList(edge.d1.corners, edge.v0); AddToCornerList(edge.d1.corners, edge.v1); } // Corners point to centers if (edge.v0 != null) { AddToCenterList(edge.v0.touches, edge.d0); AddToCenterList(edge.v0.touches, edge.d1); } if (edge.v1 != null) { AddToCenterList(edge.v1.touches, edge.d0); AddToCenterList(edge.v1.touches, edge.d1); } } // TODO: use edges to determine these var topLeft = centers.OrderBy(p => p.point.x + p.point.y).First(); AddCorner(topLeft, 0, 0); var bottomRight = centers.OrderByDescending(p => p.point.x + p.point.y).First(); AddCorner(bottomRight, Width, Height); var topRight = centers.OrderByDescending(p => Width - p.point.x + p.point.y).First(); AddCorner(topRight, 0, Height); var bottomLeft = centers.OrderByDescending(p => p.point.x + Height - p.point.y).First(); AddCorner(bottomLeft, Width, 0); // required for polygon fill foreach (var center in centers) { center.corners.Sort(ClockwiseComparison(center)); } } private static void AddCorner(Center topLeft, int x, int y) { if (topLeft.point.x != x || topLeft.point.y != y) topLeft.corners.Add(new Corner { ocean = true, point = new Vector2(x, y) }); } private Comparison ClockwiseComparison(Center center) { Comparison result = (a, b) => { return (int)(((a.point.x - center.point.x) * (b.point.y - center.point.y) - (b.point.x - center.point.x) * (a.point.y - center.point.y)) * 1000); }; return result; } private Corner MakeCorner(Vector2? nullablePoint) { // The Voronoi library generates multiple Point objects for // corners, and we need to canonicalize to one Corner object. // To make lookup fast, we keep an array of Points, bucketed by // x value, and then we only have to look at other Points in // nearby buckets. When we fail to find one, we'll create a new // Corner object. if (nullablePoint == null) return null; var point = nullablePoint.Value; for (var i = (int)(point.x - 1); i <= (int)(point.x + 1); i++) { foreach (var kvp in _cornerMap.Where(p => p.Key == i)) { var dx = point.x - kvp.Value.point.x; var dy = point.y - kvp.Value.point.y; if (dx * dx + dy * dy < 1e-6) return kvp.Value; } } var corner = new Corner { index = corners.Count, point = point }; corners.Add(corner); corner.border = point.x == 0 || point.x == Width || point.y == 0 || point.y == Height; _cornerMap.Add(new KeyValuePair((int)(point.x), corner)); return corner; } private void AddToCornerList(List v, Corner x) { if (x != null && v.IndexOf(x) < 0) v.Add(x); } private void AddToCenterList(List
v, Center x) { if (x != null && v.IndexOf(x) < 0) { v.Add(x); } } private void AssignCornerElevations() { // Determine elevations and water at Voronoi corners. By // construction, we have no local minima. This is important for // the downslope vectors later, which are used in the river // construction algorithm. Also by construction, inlets/bays // push low elevation areas inland, which means many rivers end // up flowing out through them. Also by construction, lakes // often end up on river paths because they don't raise the // elevation as much as other terrain does. //var q:Corner, s:Corner; var queue = new Queue(); foreach (var q in corners) { q.water = !inside(q.point); } foreach (var q in corners) { // The edges of the map are elevation 0 if (q.border) { q.elevation = 0; queue.Enqueue(q); } else { q.elevation = float.PositiveInfinity; } } // Traverse the graph and assign elevations to each point. As we // move away from the map border, increase the elevations. This // guarantees that rivers always have a way down to the coast by // going downhill (no local minima). while (queue.Any()) { var q = queue.Dequeue(); foreach (var s in q.adjacent) { // Every step up is epsilon over water or 1 over land. The // number doesn't matter because we'll rescale the // elevations later. var newElevation = 0.01f + q.elevation; if (!q.water && !s.water) { newElevation += 1; if (_needsMoreRandomness) { // HACK: the map looks nice because of randomness of // points, randomness of rivers, and randomness of // edges. Without random point selection, I needed to // inject some more randomness to make maps look // nicer. I'm doing it here, with elevations, but I // think there must be a better way. This hack is only // used with square/hexagon grids. newElevation += UnityEngine.Random.value; ; } } // If this point changed, we'll add it to the queue so // that we can process its neighbors too. if (newElevation < s.elevation) { s.elevation = newElevation; queue.Enqueue(s); } } } } private void AssignOceanCoastAndLand(float lakeThreshold) { // Compute polygon attributes 'ocean' and 'water' based on the // corner attributes. Count the water corners per // polygon. Oceans are all polygons connected to the edge of the // map. In the first pass, mark the edges of the map as ocean; // in the second pass, mark any water-containing polygon // connected an ocean as ocean. var queue = new Queue
(); //var p:Center, q:Corner, r:Center, numWater:int; foreach (var p in centers) { var numWater = 0; foreach (var q in p.corners) { if (q.border) { p.border = true; p.ocean = true; q.water = true; queue.Enqueue(p); } if (q.water) numWater += 1; } p.water = (p.ocean || numWater >= p.corners.Count * lakeThreshold); } while (queue.Any()) { var p = queue.Dequeue(); foreach (var r in p.neighbors) { if (r.water && !r.ocean) { r.ocean = true; queue.Enqueue(r); } } } // Set the polygon attribute 'coast' based on its neighbors. If // it has at least one ocean and at least one land neighbor, // then this is a coastal polygon. foreach (var p in centers) { var numOcean = 0; var numLand = 0; foreach (var r in p.neighbors) { numOcean += r.ocean ? 1 : 0; numLand += !r.water ? 1 : 0; } p.coast = (numOcean > 0) && (numLand > 0); } // Set the corner attributes based on the computed polygon // attributes. If all polygons connected to this corner are // ocean, then it's ocean; if all are land, then it's land; // otherwise it's coast. foreach (var q in corners) { var numOcean = 0; var numLand = 0; foreach (var p in q.touches) { numOcean += p.ocean ? 1 : 0; numLand += !p.water ? 1 : 0; } q.ocean = (numOcean == q.touches.Count); q.coast = (numOcean > 0) && (numLand > 0); q.water = q.border || ((numLand != q.touches.Count) && !q.coast); } } private void RedistributeElevations() { // Change the overall distribution of elevations so that lower // elevations are more common than higher // elevations. Specifically, we want elevation X to have frequency // (1-X). To do this we will sort the corners, then set each // corner to its desired elevation. var locations = LandCorners; // SCALE_FACTOR increases the mountain area. At 1.0 the maximum // elevation barely shows up on the map, so we set it to 1.1. var SCALE_FACTOR = 1.1f; locations.Sort((a, b) => a.elevation.CompareTo(b.elevation)); for (int i = 0; i < locations.Count; i++) { // Let y(x) be the total area that we want at elevation <= x. // We want the higher elevations to occur less than lower // ones, and set the area to be y(x) = 1 - (1-x)^2. var y = (float)i / (locations.Count - 1); // Now we have to solve for x, given the known y. // * y = 1 - (1-x)^2 // * y = 1 - (1 - 2x + x^2) // * y = 2x - x^2 // * x^2 - 2x + y = 0 // From this we can use the quadratic equation to get: float x = Mathf.Sqrt(SCALE_FACTOR) - Mathf.Sqrt(SCALE_FACTOR * (1 - y)); if (x > 1.0) x = 1.0f; // TODO: does this break downslopes? locations[i].elevation = x; } // Assign elevations to non-land corners corners.Where(p => p.ocean || p.coast).ToList().ForEach(p => p.elevation = 0); } private void AssignPolygonElevations() { // Polygon elevations are the average of their corners foreach (var p in centers) { var sumElevation = 0.0f; foreach (var q in p.corners) { sumElevation += q.elevation; } p.elevation = sumElevation / p.corners.Count; } } private void CalculateDownslopes() { // Calculate downslope pointers. At every point, we point to the // point downstream from it, or to itself. This is used for // generating rivers and watersheds. foreach (var q in corners) { var r = q; foreach (var s in q.adjacent) { if (s.elevation <= r.elevation) { r = s; } } q.downslope = r; } } private void CalculateWatersheds() { // Calculate the watershed of every land point. The watershed is // the last downstream land point in the downslope graph. TODO: // watersheds are currently calculated on corners, but it'd be // more useful to compute them on polygon centers so that every // polygon can be marked as being in one watershed. // Initially the watershed pointer points downslope one step. foreach (var q in corners) { q.watershed = q; if (!q.ocean && !q.coast) { q.watershed = q.downslope; } } // Follow the downslope pointers to the coast. Limit to 100 // iterations although most of the time with numPoints==2000 it // only takes 20 iterations because most points are not far from // a coast. TODO: can run faster by looking at // p.watershed.watershed instead of p.downslope.watershed. for (var i = 0; i < 100; i++) { var changed = false; foreach (var q in corners) { if (!q.ocean && !q.coast && !q.watershed.coast) { var r = q.downslope.watershed; if (!r.ocean) q.watershed = r; changed = true; } } if (!changed) break; } // How big is each watershed? foreach (var q in corners) { var r = q.watershed; r.watershed_size = 1 + r.watershed_size; } } private void CreateRivers() { // Create rivers along edges. Pick a random corner point, then // move downslope. Mark the edges and corners as rivers. for (var i = 0; i < (Width + Height) / 4; i++) { var q = corners[UnityEngine.Random.Range(0, corners.Count - 1)]; if (q.ocean || q.elevation < 0.3 || q.elevation > 0.9) continue; // Bias rivers to go west: if (q.downslope.x > q.x) continue; while (!q.coast) { if (q == q.downslope) { break; } var edge = lookupEdgeFromCorner(q, q.downslope); edge.river = edge.river + 1; q.river++; q.downslope.river++; // TODO: fix double count q = q.downslope; } } } private void AssignCornerMoisture() { // Calculate moisture. Freshwater sources spread moisture: rivers // and lakes (not oceans). Saltwater sources have moisture but do // not spread it (we set it at the end, after propagation). var queue = new Queue(); // Fresh water foreach (var q in corners) { if ((q.water || q.river > 0) && !q.ocean) { q.moisture = q.river > 0 ? Mathf.Min(3.0f, (0.2f * q.river)) : 1.0f; queue.Enqueue(q); } else { q.moisture = 0; } } while (queue.Any()) { var q = queue.Dequeue(); foreach (var r in q.adjacent) { var newMoisture = q.moisture * 0.9f; if (newMoisture > r.moisture) { r.moisture = newMoisture; queue.Enqueue(r); } } } // Salt water foreach (var q in corners) { if (q.ocean || q.coast) { q.moisture = 1.0f; } } } private void AssignPolygonMoisture() { // Polygon moisture is the average of the moisture at corners foreach (var p in centers) { var sumMoisture = 0.0f; foreach (var q in p.corners) { if (q.moisture > 1.0) q.moisture = 1.0f; sumMoisture += q.moisture; } p.moisture = sumMoisture / p.corners.Count; } } private Edge lookupEdgeFromCenter(Center p, Center r) { foreach (var edge in p.borders) { if (edge.d0 == r || edge.d1 == r) return edge; } return null; } private Edge lookupEdgeFromCorner(Corner q, Corner s) { foreach (var edge in q.protrudes) { if (edge.v0 == s || edge.v1 == s) return edge; } return null; } private void RedistributeMoisture() { // Change the overall distribution of moisture to be evenly distributed. var locations = LandCorners; locations.Sort((a, b) => a.moisture.CompareTo(b.moisture)); for (var i = 0; i < locations.Count; i++) { locations[i].moisture = (float)i / (locations.Count - 1); } } static Biome GetBiome(Center p) { if (p.ocean) { return Biome.Ocean; } else if (p.water) { if (p.elevation < 0.1) return Biome.Marsh; if (p.elevation > 0.8) return Biome.Ice; return Biome.Lake; } else if (p.coast) { return Biome.Beach; } else if (p.elevation > 0.8) { if (p.moisture > 0.50) return Biome.Snow; else if (p.moisture > 0.33) return Biome.Tundra; else if (p.moisture > 0.16) return Biome.Bare; else return Biome.Scorched; } else if (p.elevation > 0.6) { if (p.moisture > 0.66) return Biome.Taiga; else if (p.moisture > 0.33) return Biome.Shrubland; else return Biome.TemperateDesert; } else if (p.elevation > 0.3) { if (p.moisture > 0.83) return Biome.TemperateRainForest; else if (p.moisture > 0.50) return Biome.TemperateDeciduousForest; else if (p.moisture > 0.16) return Biome.Grassland; else return Biome.TemperateDesert; } else { if (p.moisture > 0.66) return Biome.TropicalRainForest; else if (p.moisture > 0.33) return Biome.TropicalSeasonalForest; else if (p.moisture > 0.16) return Biome.Grassland; else return Biome.SubtropicalDesert; } } public static IEnumerable RelaxPoints(IEnumerable startingPoints, float width, float height) { Delaunay.Voronoi v = new Delaunay.Voronoi(startingPoints.ToList(), null, new Rect(0, 0, width, height)); foreach (var point in startingPoints) { var region = v.Region(point); point.Set(0, 0); foreach (var r in region) point.Set(point.x + r.x, point.y + r.y); point.Set(point.x / region.Count, point.y / region.Count); yield return point; } } } } ================================================ FILE: demo/Assets/Map/Graph.cs.meta ================================================ fileFormatVersion: 2 guid: e8a146a4bf4be4b47a37168e1541a1ff MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/IslandShape.cs ================================================ using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace Assets.Map { public class IslandShape { // This class has factory functions for generating islands of // different shapes. The factory returns a function that takes a // normalized point (x and y are -1 to +1) and returns true if the // point should be on the island, and false if it should be water // (lake or ocean). // The radial island radius is based on overlapping sine waves public static float ISLAND_FACTOR = 1.07f; // 1.0 means no small islands; 2.0 leads to a lot public static float PERLIN_CHECK_VALUE = 0.3f; public static System.Func makeRadial() { var bumps = Random.Range(1, 6); var startAngle = Random.value * 2 * Mathf.PI; var dipAngle = Random.value * 2 * Mathf.PI; var random = Random.value; var start = 0.2f; var end = 0.7f; var dipWidth = (end - start) * random + start; System.Func inside = q => { var angle = Mathf.Atan2(q.y, q.x); var length = 0.5 * (Mathf.Max(Mathf.Abs(q.x), Mathf.Abs(q.y)) + q.magnitude); var r1 = 0.5 + 0.40 * Mathf.Sin(startAngle + bumps * angle + Mathf.Cos((bumps + 3) * angle)); var r2 = 0.7 - 0.20 * Mathf.Sin(startAngle + bumps * angle - Mathf.Sin((bumps + 2) * angle)); if (Mathf.Abs(angle - dipAngle) < dipWidth || Mathf.Abs(angle - dipAngle + 2 * Mathf.PI) < dipWidth || Mathf.Abs(angle - dipAngle - 2 * Mathf.PI) < dipWidth) { r1 = r2 = 0.2; } var result = (length < r1 || (length > r1 * ISLAND_FACTOR && length < r2)); return result; }; return inside; } // The Perlin-based island combines perlin noise with the radius public static System.Func makePerlin() { var offset = Random.Range(0, 100000); System.Func inside = q => { q = new Vector2(q.x / 25 - 1, q.y / 25 - 1); var x = q.x + offset; var y = q.y + offset; var perlin = Mathf.PerlinNoise(x/10 , y/10); var checkValue = (PERLIN_CHECK_VALUE + PERLIN_CHECK_VALUE * q.magnitude * q.magnitude); var result = perlin > checkValue; return result; }; return inside; } // The square shape fills the entire space with land public static System.Func makeSquare() { System.Func inside = q => { return true; }; return inside; } } } ================================================ FILE: demo/Assets/Map/IslandShape.cs.meta ================================================ fileFormatVersion: 2 guid: c5b3ffa4871be074aa1ce33f637c319f MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/Map.cs ================================================ using Delaunay; using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace Assets.Map { public class Map { private int _pointCount = 500; float _lakeThreshold = 0.3f; public const float Width = 50; public const float Height = 50; const int NUM_LLOYD_RELAXATIONS = 2; public Graph Graph { get; private set; } public Center SelectedCenter { get; private set; } public Map() { List colors = new List(); var points = new List(); for (int i = 0; i < _pointCount; i++) { colors.Add(0); points.Add(new Vector2( UnityEngine.Random.Range(0, Width), UnityEngine.Random.Range(0, Height)) ); } for (int i = 0; i < NUM_LLOYD_RELAXATIONS; i++) points = Graph.RelaxPoints(points, Width, Height).ToList(); var voronoi = new Voronoi(points, colors, new Rect(0, 0, Width, Height)); Graph = new Graph(points, voronoi, (int)Width, (int)Height, _lakeThreshold); } internal void Click(Vector2 point) { SelectedCenter = Graph.centers.FirstOrDefault(p => p.PointInside(point.x, point.y)); } } } ================================================ FILE: demo/Assets/Map/Map.cs.meta ================================================ fileFormatVersion: 2 guid: d04dc414d23e3bf43ae38677c94982f3 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map/MapTexture.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace Assets.Map { public class MapTexture { int _textureScale; public MapTexture(int textureScale) { _textureScale = textureScale; } public void AttachTexture(GameObject plane, Map map) { int _textureWidth = (int)Map.Width * _textureScale; int _textureHeight = (int)Map.Height * _textureScale; Texture2D texture = new Texture2D(_textureWidth, _textureHeight); texture.SetPixels(Enumerable.Repeat(Color.magenta, _textureWidth * _textureHeight).ToArray()); var lines = map.Graph.edges.Where(p => p.v0 != null).Select(p => new[] { p.v0.point.x, p.v0.point.y, p.v1.point.x, p.v1.point.y }).ToArray(); foreach (var c in map.Graph.centers) texture.FillPolygon(c.corners.Select(p => new Vector2(p.point.x * _textureScale, p.point.y * _textureScale)).ToArray(), BiomeProperties.Colors[c.biome]); foreach (var line in lines) DrawLine(texture, line[0], line[1], line[2], line[3], Color.black); foreach (var line in map.Graph.edges.Where(p => p.river > 0 && !p.d0.water && !p.d1.water)) DrawLine(texture, line.v0.point.x, line.v0.point.y, line.v1.point.x, line.v1.point.y, Color.blue); texture.Apply(); plane.GetComponent().material.mainTexture = texture; plane.transform.localPosition = new Vector3(Map.Width / 2, Map.Height / 2, 1); } private void DrawLine(Texture2D texture, float x0, float y0, float x1, float y1, Color color) { texture.DrawLine((int)(x0 * _textureScale), (int)(y0 * _textureScale), (int)(x1 * _textureScale), (int)(y1 * _textureScale), color); } } } ================================================ FILE: demo/Assets/Map/MapTexture.cs.meta ================================================ fileFormatVersion: 2 guid: c460af6532c409546ae639121253b9dd MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Map.meta ================================================ fileFormatVersion: 2 guid: 8974cff9fe327e543b7a4c7516d81785 folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Materials/Selector.mat ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!21 &2100000 Material: serializedVersion: 3 m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_Name: Selector m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0} m_ShaderKeywords: [] m_CustomRenderQueue: -1 m_SavedProperties: serializedVersion: 2 m_TexEnvs: data: first: name: _MainTex second: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} data: first: name: _BumpMap second: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} data: first: name: _Illum second: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} m_Floats: data: first: name: _Cutoff second: .5 data: first: name: _EmissionLM second: 0 m_Colors: data: first: name: _Color second: {r: 1, g: 0, b: 0, a: .858823538} ================================================ FILE: demo/Assets/Materials/Selector.mat.meta ================================================ fileFormatVersion: 2 guid: 6dca14a4c7e41c646a06c11e677259d1 NativeFormatImporter: userData: ================================================ FILE: demo/Assets/Materials.meta ================================================ fileFormatVersion: 2 guid: 6cc64df6c68419e4aaa0adb31c277cbd folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/DelaunayHelpers.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.Geo; using Delaunay.LR; namespace Delaunay { public class Node { public static Stack pool = new Stack (); public Node parent; public int treeSize; } public enum KruskalType { MINIMUM, MAXIMUM } public static class DelaunayHelpers { public static List VisibleLineSegments (List edges) { List segments = new List (); for (int i = 0; i p1 = edge.clippedEnds [Side.LEFT]; Nullable p2 = edge.clippedEnds [Side.RIGHT]; segments.Add (new LineSegment (p1, p2)); } } return segments; } public static List SelectEdgesForSitePoint (Vector2 coord, List edgesToTest) { return edgesToTest.FindAll (delegate (Edge edge) { return ((edge.leftSite != null && edge.leftSite.Coord == coord) || (edge.rightSite != null && edge.rightSite.Coord == coord)); }); } public static List SelectNonIntersectingEdges (/*keepOutMask:BitmapData,*/List edgesToTest) { // if (keepOutMask == null) // { return edgesToTest; // } // var zeroPoint:Point = new Point(); // return edgesToTest.filter(myTest); // // function myTest(edge:Edge, index:int, vector:Vector.):Boolean // { // var delaunayLineBmp:BitmapData = edge.makeDelaunayLineBmp(); // var notIntersecting:Boolean = !(keepOutMask.hitTest(zeroPoint, 1, delaunayLineBmp, zeroPoint, 1)); // delaunayLineBmp.dispose(); // return notIntersecting; // } } public static List DelaunayLinesForEdges (List edges) { List segments = new List (); Edge edge; for (int i = 0; i < edges.Count; i++) { edge = edges [i]; segments.Add (edge.DelaunayLine ()); } return segments; } /** * Kruskal's spanning tree algorithm with union-find * Skiena: The Algorithm Design Manual, p. 196ff * Note: the sites are implied: they consist of the end points of the line segments */ public static List Kruskal (List lineSegments, KruskalType type = KruskalType.MINIMUM) { Dictionary,Node> nodes = new Dictionary,Node> (); List mst = new List (); Stack nodePool = Node.pool; switch (type) { // note that the compare functions are the reverse of what you'd expect // because (see below) we traverse the lineSegments in reverse order for speed case KruskalType.MAXIMUM: lineSegments.Sort (delegate (LineSegment l1, LineSegment l2) { return LineSegment.CompareLengths (l1, l2); }); break; default: lineSegments.Sort (delegate (LineSegment l1, LineSegment l2) { return LineSegment.CompareLengths_MAX (l1, l2); }); break; } for (int i = lineSegments.Count; --i > -1;) { LineSegment lineSegment = lineSegments [i]; Node node0 = null; Node rootOfSet0; if (!nodes.ContainsKey (lineSegment.p0)) { node0 = nodePool.Count > 0 ? nodePool.Pop () : new Node (); // intialize the node: rootOfSet0 = node0.parent = node0; node0.treeSize = 1; nodes [lineSegment.p0] = node0; } else { node0 = nodes [lineSegment.p0]; rootOfSet0 = Find (node0); } Node node1 = null; Node rootOfSet1; if (!nodes.ContainsKey (lineSegment.p1)) { node1 = nodePool.Count > 0 ? nodePool.Pop () : new Node (); // intialize the node: rootOfSet1 = node1.parent = node1; node1.treeSize = 1; nodes [lineSegment.p1] = node1; } else { node1 = nodes [lineSegment.p1]; rootOfSet1 = Find (node1); } if (rootOfSet0 != rootOfSet1) { // nodes not in same set mst.Add (lineSegment); // merge the two sets: int treeSize0 = rootOfSet0.treeSize; int treeSize1 = rootOfSet1.treeSize; if (treeSize0 >= treeSize1) { // set0 absorbs set1: rootOfSet1.parent = rootOfSet0; rootOfSet0.treeSize += treeSize1; } else { // set1 absorbs set0: rootOfSet0.parent = rootOfSet1; rootOfSet1.treeSize += treeSize0; } } } foreach (Node node in nodes.Values) { nodePool.Push (node); } return mst; } private static Node Find (Node node) { if (node.parent == node) { return node; } else { Node root = Find (node.parent); // this line is just to speed up subsequent finds by keeping the tree depth low: node.parent = root; return root; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/DelaunayHelpers.cs.meta ================================================ fileFormatVersion: 2 guid: 3e5cf667cd9df4f68a86433bcfff21d4 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Edge.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.Geo; using Delaunay.LR; namespace Delaunay { // import com.nodename.geom.LineSegment; // // import flash.display.BitmapData; // import flash.display.CapsStyle; // import flash.display.Graphics; // import flash.display.LineScaleMode; // import flash.display.Sprite; // import flash.geom.Point; // import flash.geom.Rectangle; // import flash.utils.Dictionary; /** * The line segment connecting the two Sites is part of the Delaunay triangulation; * the line segment connecting the two Vertices is part of the Voronoi diagram * @author ashaw * */ public sealed class Edge { private static Stack _pool = new Stack (); /** * This is the only way to create a new Edge * @param site0 * @param site1 * @return * */ public static Edge CreateBisectingEdge (Site site0, Site site1) { float dx, dy, absdx, absdy; float a, b, c; dx = site1.x - site0.x; dy = site1.y - site0.y; absdx = dx > 0 ? dx : -dx; absdy = dy > 0 ? dy : -dy; c = site0.x * dx + site0.y * dy + (dx * dx + dy * dy) * 0.5f; if (absdx > absdy) { a = 1.0f; b = dy / dx; c /= dx; } else { b = 1.0f; a = dx / dy; c /= dy; } Edge edge = Edge.Create (); edge.leftSite = site0; edge.rightSite = site1; site0.AddEdge (edge); site1.AddEdge (edge); edge._leftVertex = null; edge._rightVertex = null; edge.a = a; edge.b = b; edge.c = c; //trace("createBisectingEdge: a ", edge.a, "b", edge.b, "c", edge.c); return edge; } private static Edge Create () { Edge edge; if (_pool.Count > 0) { edge = _pool.Pop (); edge.Init (); } else { edge = new Edge (); } return edge; } // private static const LINESPRITE:Sprite = new Sprite(); // private static const GRAPHICS:Graphics = LINESPRITE.graphics; // // private var _delaunayLineBmp:BitmapData; // internal function get delaunayLineBmp():BitmapData // { // if (!_delaunayLineBmp) // { // _delaunayLineBmp = makeDelaunayLineBmp(); // } // return _delaunayLineBmp; // } // // // making this available to Voronoi; running out of memory in AIR so I cannot cache the bmp // internal function makeDelaunayLineBmp():BitmapData // { // var p0:Point = leftSite.coord; // var p1:Point = rightSite.coord; // // GRAPHICS.clear(); // // clear() resets line style back to undefined! // GRAPHICS.lineStyle(0, 0, 1.0, false, LineScaleMode.NONE, CapsStyle.NONE); // GRAPHICS.moveTo(p0.x, p0.y); // GRAPHICS.lineTo(p1.x, p1.y); // // var w:int = int(Math.ceil(Math.max(p0.x, p1.x))); // if (w < 1) // { // w = 1; // } // var h:int = int(Math.ceil(Math.max(p0.y, p1.y))); // if (h < 1) // { // h = 1; // } // var bmp:BitmapData = new BitmapData(w, h, true, 0); // bmp.draw(LINESPRITE); // return bmp; // } public LineSegment DelaunayLine () { // draw a line connecting the input Sites for which the edge is a bisector: return new LineSegment (leftSite.Coord, rightSite.Coord); } public LineSegment VoronoiEdge () { if (!visible) return new LineSegment (null, null); return new LineSegment (_clippedVertices [Side.LEFT], _clippedVertices [Side.RIGHT]); } private static int _nedges = 0; public static readonly Edge DELETED = new Edge (); // the equation of the edge: ax + by = c public float a, b, c; // the two Voronoi vertices that the edge connects // (if one of them is null, the edge extends to infinity) private Vertex _leftVertex; public Vertex leftVertex { get { return _leftVertex;} } private Vertex _rightVertex; public Vertex rightVertex { get { return _rightVertex;} } public Vertex Vertex (Side leftRight) { return (leftRight == Side.LEFT) ? _leftVertex : _rightVertex; } public void SetVertex (Side leftRight, Vertex v) { if (leftRight == Side.LEFT) { _leftVertex = v; } else { _rightVertex = v; } } public bool IsPartOfConvexHull () { return (_leftVertex == null || _rightVertex == null); } public float SitesDistance () { return Vector2.Distance (leftSite.Coord, rightSite.Coord); } public static int CompareSitesDistances_MAX (Edge edge0, Edge edge1) { float length0 = edge0.SitesDistance (); float length1 = edge1.SitesDistance (); if (length0 < length1) { return 1; } if (length0 > length1) { return -1; } return 0; } public static int CompareSitesDistances (Edge edge0, Edge edge1) { return - CompareSitesDistances_MAX (edge0, edge1); } // Once clipVertices() is called, this Dictionary will hold two Points // representing the clipped coordinates of the left and right ends... private Dictionary> _clippedVertices; public Dictionary> clippedEnds { get { return _clippedVertices;} } // unless the entire Edge is outside the bounds. // In that case visible will be false: public bool visible { get { return _clippedVertices != null;} } // the two input Sites for which this Edge is a bisector: private Dictionary _sites; public Site leftSite { get{ return _sites [Side.LEFT];} set{ _sites [Side.LEFT] = value;} } public Site rightSite { get { return _sites [Side.RIGHT];} set { _sites [Side.RIGHT] = value;} } public Site Site (Side leftRight) { return _sites [leftRight]; } private int _edgeIndex; public void Dispose () { // if (_delaunayLineBmp) { // _delaunayLineBmp.Dispose (); // _delaunayLineBmp = null; // } _leftVertex = null; _rightVertex = null; if (_clippedVertices != null) { _clippedVertices [Side.LEFT] = null; _clippedVertices [Side.RIGHT] = null; _clippedVertices = null; } _sites [Side.LEFT] = null; _sites [Side.RIGHT] = null; _sites = null; _pool.Push (this); } private Edge () { // if (lock != PrivateConstructorEnforcer) // { // throw new Error("Edge: constructor is private"); // } _edgeIndex = _nedges++; Init (); } private void Init () { _sites = new Dictionary (); } public override string ToString () { return "Edge " + _edgeIndex.ToString () + "; sites " + _sites [Side.LEFT].ToString () + ", " + _sites [Side.RIGHT].ToString () + "; endVertices " + ((_leftVertex != null) ? _leftVertex.vertexIndex.ToString () : "null") + ", " + ((_rightVertex != null) ? _rightVertex.vertexIndex.ToString () : "null") + "::"; } /** * Set _clippedVertices to contain the two ends of the portion of the Voronoi edge that is visible * within the bounds. If no part of the Edge falls within the bounds, leave _clippedVertices null. * @param bounds * */ public void ClipVertices (Rect bounds) { float xmin = bounds.xMin; float ymin = bounds.yMin; float xmax = bounds.xMax; float ymax = bounds.yMax; Vertex vertex0, vertex1; float x0, x1, y0, y1; if (a == 1.0 && b >= 0.0) { vertex0 = _rightVertex; vertex1 = _leftVertex; } else { vertex0 = _leftVertex; vertex1 = _rightVertex; } if (a == 1.0) { y0 = ymin; if (vertex0 != null && vertex0.y > ymin) { y0 = vertex0.y; } if (y0 > ymax) { return; } x0 = c - b * y0; y1 = ymax; if (vertex1 != null && vertex1.y < ymax) { y1 = vertex1.y; } if (y1 < ymin) { return; } x1 = c - b * y1; if ((x0 > xmax && x1 > xmax) || (x0 < xmin && x1 < xmin)) { return; } if (x0 > xmax) { x0 = xmax; y0 = (c - x0) / b; } else if (x0 < xmin) { x0 = xmin; y0 = (c - x0) / b; } if (x1 > xmax) { x1 = xmax; y1 = (c - x1) / b; } else if (x1 < xmin) { x1 = xmin; y1 = (c - x1) / b; } } else { x0 = xmin; if (vertex0 != null && vertex0.x > xmin) { x0 = vertex0.x; } if (x0 > xmax) { return; } y0 = c - a * x0; x1 = xmax; if (vertex1 != null && vertex1.x < xmax) { x1 = vertex1.x; } if (x1 < xmin) { return; } y1 = c - a * x1; if ((y0 > ymax && y1 > ymax) || (y0 < ymin && y1 < ymin)) { return; } if (y0 > ymax) { y0 = ymax; x0 = (c - y0) / a; } else if (y0 < ymin) { y0 = ymin; x0 = (c - y0) / a; } if (y1 > ymax) { y1 = ymax; x1 = (c - y1) / a; } else if (y1 < ymin) { y1 = ymin; x1 = (c - y1) / a; } } // _clippedVertices = new Dictionary(true); // XXX: Weak ref'd dict might be a problem to use standard _clippedVertices = new Dictionary> (); if (vertex0 == _leftVertex) { _clippedVertices [Side.LEFT] = new Vector2 (x0, y0); _clippedVertices [Side.RIGHT] = new Vector2 (x1, y1); } else { _clippedVertices [Side.RIGHT] = new Vector2 (x0, y0); _clippedVertices [Side.LEFT] = new Vector2 (x1, y1); } } } } //class PrivateConstructorEnforcer {} ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Edge.cs.meta ================================================ fileFormatVersion: 2 guid: 49202b1d309f140d6bd015a7fbce4b64 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/EdgeList.cs ================================================ using UnityEngine; using Delaunay.Utils; namespace Delaunay { internal sealed class EdgeList: Utils.IDisposable { private float _deltax; private float _xmin; private int _hashsize; private Halfedge[] _hash; private Halfedge _leftEnd; public Halfedge leftEnd { get { return _leftEnd;} } private Halfedge _rightEnd; public Halfedge rightEnd { get { return _rightEnd;} } public void Dispose () { Halfedge halfEdge = _leftEnd; Halfedge prevHe; while (halfEdge != _rightEnd) { prevHe = halfEdge; halfEdge = halfEdge.edgeListRightNeighbor; prevHe.Dispose (); } _leftEnd = null; _rightEnd.Dispose (); _rightEnd = null; int i; for (i = 0; i < _hashsize; ++i) { _hash [i] = null; } _hash = null; } public EdgeList (float xmin, float deltax, int sqrt_nsites) { _xmin = xmin; _deltax = deltax; _hashsize = 2 * sqrt_nsites; _hash = new Halfedge[_hashsize]; // two dummy Halfedges: _leftEnd = Halfedge.CreateDummy (); _rightEnd = Halfedge.CreateDummy (); _leftEnd.edgeListLeftNeighbor = null; _leftEnd.edgeListRightNeighbor = _rightEnd; _rightEnd.edgeListLeftNeighbor = _leftEnd; _rightEnd.edgeListRightNeighbor = null; _hash [0] = _leftEnd; _hash [_hashsize - 1] = _rightEnd; } /** * Insert newHalfedge to the right of lb * @param lb * @param newHalfedge * */ public void Insert (Halfedge lb, Halfedge newHalfedge) { newHalfedge.edgeListLeftNeighbor = lb; newHalfedge.edgeListRightNeighbor = lb.edgeListRightNeighbor; lb.edgeListRightNeighbor.edgeListLeftNeighbor = newHalfedge; lb.edgeListRightNeighbor = newHalfedge; } /** * This function only removes the Halfedge from the left-right list. * We cannot dispose it yet because we are still using it. * @param halfEdge * */ public void Remove (Halfedge halfEdge) { halfEdge.edgeListLeftNeighbor.edgeListRightNeighbor = halfEdge.edgeListRightNeighbor; halfEdge.edgeListRightNeighbor.edgeListLeftNeighbor = halfEdge.edgeListLeftNeighbor; halfEdge.edge = Edge.DELETED; halfEdge.edgeListLeftNeighbor = halfEdge.edgeListRightNeighbor = null; } /** * Find the rightmost Halfedge that is still left of p * @param p * @return * */ public Halfedge EdgeListLeftNeighbor (Vector2 p) { int i, bucket; Halfedge halfEdge; /* Use hash table to get close to desired halfedge */ bucket = (int)((p.x - _xmin) / _deltax * _hashsize); if (bucket < 0) { bucket = 0; } if (bucket >= _hashsize) { bucket = _hashsize - 1; } halfEdge = GetHash (bucket); if (halfEdge == null) { for (i = 1; true; ++i) { if ((halfEdge = GetHash (bucket - i)) != null) break; if ((halfEdge = GetHash (bucket + i)) != null) break; } } /* Now search linear list of halfedges for the correct one */ if (halfEdge == leftEnd || (halfEdge != rightEnd && halfEdge.IsLeftOf (p))) { do { halfEdge = halfEdge.edgeListRightNeighbor; } while (halfEdge != rightEnd && halfEdge.IsLeftOf(p)); halfEdge = halfEdge.edgeListLeftNeighbor; } else { do { halfEdge = halfEdge.edgeListLeftNeighbor; } while (halfEdge != leftEnd && !halfEdge.IsLeftOf(p)); } /* Update hash table and reference counts */ if (bucket > 0 && bucket < _hashsize - 1) { _hash [bucket] = halfEdge; } return halfEdge; } /* Get entry from hash table, pruning any deleted nodes */ private Halfedge GetHash (int b) { Halfedge halfEdge; if (b < 0 || b >= _hashsize) { return null; } halfEdge = _hash [b]; if (halfEdge != null && halfEdge.edge == Edge.DELETED) { /* Hash table points to deleted halfedge. Patch as necessary. */ _hash [b] = null; // still can't dispose halfEdge yet! return null; } else { return halfEdge; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/EdgeList.cs.meta ================================================ fileFormatVersion: 2 guid: 0f2bfd7ed370844afb774f34e1d6366a MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/EdgeReorderer.cs ================================================ using Delaunay.LR; using Delaunay.Utils; using System.Collections.Generic; namespace Delaunay { public enum VertexOrSite { VERTEX, SITE } sealed class EdgeReorderer: Utils.IDisposable { private List _edges; private List _edgeOrientations; public List edges { get { return _edges;} } public List edgeOrientations { get{ return _edgeOrientations;} } public EdgeReorderer (List origEdges, VertexOrSite criterion) { _edges = new List (); _edgeOrientations = new List (); if (origEdges.Count > 0) { _edges = ReorderEdges (origEdges, criterion); } } public void Dispose () { _edges = null; _edgeOrientations = null; } private List ReorderEdges (List origEdges, VertexOrSite criterion) { int i; int n = origEdges.Count; Edge edge; // we're going to reorder the edges in order of traversal bool[] done = new bool[n]; int nDone = 0; for (int j=0; j newEdges = new List (); // TODO: Switch to Deque if performance is a concern i = 0; edge = origEdges [i]; newEdges.Add (edge); _edgeOrientations.Add (Side.LEFT); ICoord firstPoint = (criterion == VertexOrSite.VERTEX) ? (ICoord)edge.leftVertex : (ICoord)edge.leftSite; ICoord lastPoint = (criterion == VertexOrSite.VERTEX) ? (ICoord)edge.rightVertex : (ICoord)edge.rightSite; if (firstPoint == Vertex.VERTEX_AT_INFINITY || lastPoint == Vertex.VERTEX_AT_INFINITY) { return new List (); } done [i] = true; ++nDone; while (nDone < n) { for (i = 1; i < n; ++i) { if (done [i]) { continue; } edge = origEdges [i]; ICoord leftPoint = (criterion == VertexOrSite.VERTEX) ? (ICoord)edge.leftVertex : (ICoord)edge.leftSite; ICoord rightPoint = (criterion == VertexOrSite.VERTEX) ? (ICoord)edge.rightVertex : (ICoord)edge.rightSite; if (leftPoint == Vertex.VERTEX_AT_INFINITY || rightPoint == Vertex.VERTEX_AT_INFINITY) { return new List (); } if (leftPoint == lastPoint) { lastPoint = rightPoint; _edgeOrientations.Add (Side.LEFT); newEdges.Add (edge); done [i] = true; } else if (rightPoint == firstPoint) { firstPoint = leftPoint; _edgeOrientations.Insert (0, Side.LEFT); // TODO: Change datastructure if this is slow newEdges.Insert (0, edge); done [i] = true; } else if (leftPoint == firstPoint) { firstPoint = rightPoint; _edgeOrientations.Insert (0, Side.RIGHT); newEdges.Insert (0, edge); done [i] = true; } else if (rightPoint == lastPoint) { lastPoint = leftPoint; _edgeOrientations.Add (Side.RIGHT); newEdges.Add (edge); done [i] = true; } if (done [i]) { ++nDone; } } } return newEdges; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/EdgeReorderer.cs.meta ================================================ fileFormatVersion: 2 guid: a6e9c0c7f4ae649678b34ec5397e4079 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Halfedge.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.LR; using Delaunay.Geo; using Delaunay.Utils; namespace Delaunay { public sealed class Halfedge: Delaunay.Utils.IDisposable { private static Stack _pool = new Stack (); public static Halfedge Create (Edge edge, Nullable lr) { if (_pool.Count > 0) { return _pool.Pop ().Init (edge, lr); } else { return new Halfedge (edge, lr); } } public static Halfedge CreateDummy () { return Create (null, null); } public Halfedge edgeListLeftNeighbor, edgeListRightNeighbor; public Halfedge nextInPriorityQueue; public Edge edge; public Nullable leftRight; public Vertex vertex; // the vertex's y-coordinate in the transformed Voronoi space V* public float ystar; public Halfedge (Edge edge = null, Nullable lr = null) { Init (edge, lr); } private Halfedge Init (Edge edge, Nullable lr) { this.edge = edge; leftRight = lr; nextInPriorityQueue = null; vertex = null; return this; } public override string ToString () { return "Halfedge (leftRight: " + leftRight.ToString () + "; vertex: " + vertex.ToString () + ")"; } public void Dispose () { if (edgeListLeftNeighbor != null || edgeListRightNeighbor != null) { // still in EdgeList return; } if (nextInPriorityQueue != null) { // still in PriorityQueue return; } edge = null; leftRight = null; vertex = null; _pool.Push (this); } public void ReallyDispose () { edgeListLeftNeighbor = null; edgeListRightNeighbor = null; nextInPriorityQueue = null; edge = null; leftRight = null; vertex = null; _pool.Push (this); } internal bool IsLeftOf (Vector2 p) { Site topSite; bool rightOfSite, above, fast; float dxp, dyp, dxs, t1, t2, t3, yl; topSite = edge.rightSite; rightOfSite = p.x > topSite.x; if (rightOfSite && this.leftRight == Side.LEFT) { return true; } if (!rightOfSite && this.leftRight == Side.RIGHT) { return false; } if (edge.a == 1.0) { dyp = p.y - topSite.y; dxp = p.x - topSite.x; fast = false; if ((!rightOfSite && edge.b < 0.0) || (rightOfSite && edge.b >= 0.0)) { above = dyp >= edge.b * dxp; fast = above; } else { above = p.x + p.y * edge.b > edge.c; if (edge.b < 0.0) { above = !above; } if (!above) { fast = true; } } if (!fast) { dxs = topSite.x - edge.leftSite.x; above = edge.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1.0 + 2.0 * dxp / dxs + edge.b * edge.b); if (edge.b < 0.0) { above = !above; } } } else { /* edge.b == 1.0 */ yl = edge.c - edge.a * p.x; t1 = p.y - yl; t2 = p.x - topSite.x; t3 = yl - topSite.y; above = t1 * t1 > t2 * t2 + t3 * t3; } return this.leftRight == Side.LEFT ? above : !above; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Halfedge.cs.meta ================================================ fileFormatVersion: 2 guid: e873e30775b564fbd9b4b27ac5b0787a MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/HalfedgePriorityQueue.cs ================================================ using UnityEngine; using System.Collections.Generic; using Delaunay.Utils; namespace Delaunay { internal sealed class HalfedgePriorityQueue: Utils.IDisposable // also known as heap { private Halfedge[] _hash; private int _count; private int _minBucket; private int _hashsize; private float _ymin; private float _deltay; public HalfedgePriorityQueue (float ymin, float deltay, int sqrt_nsites) { _ymin = ymin; _deltay = deltay; _hashsize = 4 * sqrt_nsites; Initialize (); } public void Dispose () { // get rid of dummies for (int i = 0; i < _hashsize; ++i) { _hash [i].Dispose (); _hash [i] = null; } _hash = null; } private void Initialize () { int i; _count = 0; _minBucket = 0; _hash = new Halfedge[_hashsize]; // dummy Halfedge at the top of each hash for (i = 0; i < _hashsize; ++i) { _hash [i] = Halfedge.CreateDummy (); _hash [i].nextInPriorityQueue = null; } } public void Insert (Halfedge halfEdge) { Halfedge previous, next; int insertionBucket = Bucket (halfEdge); if (insertionBucket < _minBucket) { _minBucket = insertionBucket; } previous = _hash [insertionBucket]; while ((next = previous.nextInPriorityQueue) != null && (halfEdge.ystar > next.ystar || (halfEdge.ystar == next.ystar && halfEdge.vertex.x > next.vertex.x))) { previous = next; } halfEdge.nextInPriorityQueue = previous.nextInPriorityQueue; previous.nextInPriorityQueue = halfEdge; ++_count; } public void Remove (Halfedge halfEdge) { Halfedge previous; int removalBucket = Bucket (halfEdge); if (halfEdge.vertex != null) { previous = _hash [removalBucket]; while (previous.nextInPriorityQueue != halfEdge) { previous = previous.nextInPriorityQueue; } previous.nextInPriorityQueue = halfEdge.nextInPriorityQueue; _count--; halfEdge.vertex = null; halfEdge.nextInPriorityQueue = null; halfEdge.Dispose (); } } private int Bucket (Halfedge halfEdge) { int theBucket = (int)((halfEdge.ystar - _ymin) / _deltay * _hashsize); if (theBucket < 0) theBucket = 0; if (theBucket >= _hashsize) theBucket = _hashsize - 1; return theBucket; } private bool IsEmpty (int bucket) { return (_hash [bucket].nextInPriorityQueue == null); } /** * move _minBucket until it contains an actual Halfedge (not just the dummy at the top); * */ private void AdjustMinBucket () { while (_minBucket < _hashsize - 1 && IsEmpty(_minBucket)) { ++_minBucket; } } public bool Empty () { return _count == 0; } /** * @return coordinates of the Halfedge's vertex in V*, the transformed Voronoi diagram * */ public Vector2 Min () { AdjustMinBucket (); Halfedge answer = _hash [_minBucket].nextInPriorityQueue; return new Vector2 (answer.vertex.x, answer.ystar); } /** * remove and return the min Halfedge * @return * */ public Halfedge ExtractMin () { Halfedge answer; // get the first real Halfedge in _minBucket answer = _hash [_minBucket].nextInPriorityQueue; _hash [_minBucket].nextInPriorityQueue = answer.nextInPriorityQueue; _count--; answer.nextInPriorityQueue = null; return answer; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/HalfedgePriorityQueue.cs.meta ================================================ fileFormatVersion: 2 guid: 6ba85128b77e245478cd4bc1ac6c8f60 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/ICoord.cs ================================================ using UnityEngine; namespace Delaunay { public interface ICoord { Vector2 Coord { get; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/ICoord.cs.meta ================================================ fileFormatVersion: 2 guid: 6a0a816d1340149068ec7fa5bc31c72c MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/LR.cs ================================================ namespace Delaunay { namespace LR { public enum Side { LEFT = 0, RIGHT } public class SideHelper { public static Side Other (Side leftRight) { return leftRight == Side.LEFT ? Side.RIGHT : Side.LEFT; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/LR.cs.meta ================================================ fileFormatVersion: 2 guid: 42741f042d2e748aaaf15e94b6ba71dd MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Site.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.Geo; using Delaunay.LR; namespace Delaunay { public sealed class Site: ICoord, IComparable { private static Stack _pool = new Stack (); public static Site Create (Vector2 p, uint index, float weight, uint color) { if (_pool.Count > 0) { return _pool.Pop ().Init (p, index, weight, color); } else { return new Site (p, index, weight, color); } } internal static void SortSites (List sites) { // sites.sort(Site.compare); sites.Sort (); // XXX: Check if this works } /** * sort sites on y, then x, coord * also change each site's _siteIndex to match its new position in the list * so the _siteIndex can be used to identify the site for nearest-neighbor queries * * haha "also" - means more than one responsibility... * */ public int CompareTo (System.Object obj) // XXX: Really, really worried about this because it depends on how sorting works in AS3 impl - Julian { Site s2 = (Site)obj; int returnValue = Voronoi.CompareByYThenX (this, s2); // swap _siteIndex values if necessary to match new ordering: uint tempIndex; if (returnValue == -1) { if (this._siteIndex > s2._siteIndex) { tempIndex = this._siteIndex; this._siteIndex = s2._siteIndex; s2._siteIndex = tempIndex; } } else if (returnValue == 1) { if (s2._siteIndex > this._siteIndex) { tempIndex = s2._siteIndex; s2._siteIndex = this._siteIndex; this._siteIndex = tempIndex; } } return returnValue; } private static readonly float EPSILON = .005f; private static bool CloseEnough (Vector2 p0, Vector2 p1) { return Vector2.Distance (p0, p1) < EPSILON; } private Vector2 _coord; public Vector2 Coord { get { return _coord;} } public uint color; public float weight; private uint _siteIndex; // the edges that define this Site's Voronoi region: private List _edges; internal List edges { get { return _edges;} } // which end of each edge hooks up with the previous edge in _edges: private List _edgeOrientations; // ordered list of points that define the region clipped to bounds: private List _region; private Site (Vector2 p, uint index, float weight, uint color) { // if (lock != PrivateConstructorEnforcer) // { // throw new Error("Site constructor is private"); // } Init (p, index, weight, color); } private Site Init (Vector2 p, uint index, float weight, uint color) { _coord = p; _siteIndex = index; this.weight = weight; this.color = color; _edges = new List (); _region = null; return this; } public override string ToString () { return "Site " + _siteIndex.ToString () + ": " + Coord.ToString (); } private void Move (Vector2 p) { Clear (); _coord = p; } public void Dispose () { // _coord = null; Clear (); _pool.Push (this); } private void Clear () { if (_edges != null) { _edges.Clear (); _edges = null; } if (_edgeOrientations != null) { _edgeOrientations.Clear (); _edgeOrientations = null; } if (_region != null) { _region.Clear (); _region = null; } } public void AddEdge (Edge edge) { _edges.Add (edge); } public Edge NearestEdge () { _edges.Sort (delegate (Edge a, Edge b) { return Edge.CompareSitesDistances (a, b); }); return _edges [0]; } public List NeighborSites () { if (_edges == null || _edges.Count == 0) { return new List (); } if (_edgeOrientations == null) { ReorderEdges (); } List list = new List (); Edge edge; for (int i = 0; i < _edges.Count; i++) { edge = _edges [i]; list.Add (NeighborSite (edge)); } return list; } private Site NeighborSite (Edge edge) { if (this == edge.leftSite) { return edge.rightSite; } if (this == edge.rightSite) { return edge.leftSite; } return null; } internal List Region (Rect clippingBounds) { if (_edges == null || _edges.Count == 0) { return new List (); } if (_edgeOrientations == null) { ReorderEdges (); _region = ClipToBounds (clippingBounds); if ((new Polygon (_region)).Winding () == Winding.CLOCKWISE) { _region.Reverse (); } } return _region; } private void ReorderEdges () { //trace("_edges:", _edges); EdgeReorderer reorderer = new EdgeReorderer (_edges, VertexOrSite.VERTEX); _edges = reorderer.edges; //trace("reordered:", _edges); _edgeOrientations = reorderer.edgeOrientations; reorderer.Dispose (); } private List ClipToBounds (Rect bounds) { List points = new List (); int n = _edges.Count; int i = 0; Edge edge; while (i < n && ((_edges[i] as Edge).visible == false)) { ++i; } if (i == n) { // no edges visible return new List (); } edge = _edges [i]; Side orientation = _edgeOrientations [i]; if (edge.clippedEnds [orientation] == null) { Debug.LogError ("XXX: Null detected when there should be a Vector2!"); } if (edge.clippedEnds [SideHelper.Other (orientation)] == null) { Debug.LogError ("XXX: Null detected when there should be a Vector2!"); } points.Add ((Vector2)edge.clippedEnds [orientation]); points.Add ((Vector2)edge.clippedEnds [SideHelper.Other (orientation)]); for (int j = i + 1; j < n; ++j) { edge = _edges [j]; if (edge.visible == false) { continue; } Connect (points, j, bounds); } // close up the polygon by adding another corner point of the bounds if needed: Connect (points, i, bounds, true); return points; } private void Connect (List points, int j, Rect bounds, bool closingUp = false) { Vector2 rightPoint = points [points.Count - 1]; Edge newEdge = _edges [j] as Edge; Side newOrientation = _edgeOrientations [j]; // the point that must be connected to rightPoint: if (newEdge.clippedEnds [newOrientation] == null) { Debug.LogError ("XXX: Null detected when there should be a Vector2!"); } Vector2 newPoint = (Vector2)newEdge.clippedEnds [newOrientation]; if (!CloseEnough (rightPoint, newPoint)) { // The points do not coincide, so they must have been clipped at the bounds; // see if they are on the same border of the bounds: if (rightPoint.x != newPoint.x && rightPoint.y != newPoint.y) { // They are on different borders of the bounds; // insert one or two corners of bounds as needed to hook them up: // (NOTE this will not be correct if the region should take up more than // half of the bounds rect, for then we will have gone the wrong way // around the bounds and included the smaller part rather than the larger) int rightCheck = BoundsCheck.Check (rightPoint, bounds); int newCheck = BoundsCheck.Check (newPoint, bounds); float px, py; if ((rightCheck & BoundsCheck.RIGHT) != 0) { px = bounds.xMax; if ((newCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.yMax; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { py = bounds.yMin; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height) { py = bounds.yMin; } else { py = bounds.yMax; } points.Add (new Vector2 (px, py)); points.Add (new Vector2 (bounds.xMin, py)); } } else if ((rightCheck & BoundsCheck.LEFT) != 0) { px = bounds.xMin; if ((newCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.yMax; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { py = bounds.yMin; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.RIGHT) != 0) { if (rightPoint.y - bounds.y + newPoint.y - bounds.y < bounds.height) { py = bounds.yMin; } else { py = bounds.yMax; } points.Add (new Vector2 (px, py)); points.Add (new Vector2 (bounds.xMax, py)); } } else if ((rightCheck & BoundsCheck.TOP) != 0) { py = bounds.yMin; if ((newCheck & BoundsCheck.RIGHT) != 0) { px = bounds.xMax; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { px = bounds.xMin; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.BOTTOM) != 0) { if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width) { px = bounds.xMin; } else { px = bounds.xMax; } points.Add (new Vector2 (px, py)); points.Add (new Vector2 (px, bounds.yMax)); } } else if ((rightCheck & BoundsCheck.BOTTOM) != 0) { py = bounds.yMax; if ((newCheck & BoundsCheck.RIGHT) != 0) { px = bounds.xMax; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.LEFT) != 0) { px = bounds.xMin; points.Add (new Vector2 (px, py)); } else if ((newCheck & BoundsCheck.TOP) != 0) { if (rightPoint.x - bounds.x + newPoint.x - bounds.x < bounds.width) { px = bounds.xMin; } else { px = bounds.xMax; } points.Add (new Vector2 (px, py)); points.Add (new Vector2 (px, bounds.yMin)); } } } if (closingUp) { // newEdge's ends have already been added return; } points.Add (newPoint); } if (newEdge.clippedEnds [SideHelper.Other (newOrientation)] == null) { Debug.LogError ("XXX: Null detected when there should be a Vector2!"); } Vector2 newRightPoint = (Vector2)newEdge.clippedEnds [SideHelper.Other (newOrientation)]; if (!CloseEnough (points [0], newRightPoint)) { points.Add (newRightPoint); } } public float x { get { return _coord.x;} } internal float y { get { return _coord.y;} } public float Dist (ICoord p) { return Vector2.Distance (p.Coord, this._coord); } } } // class PrivateConstructorEnforcer {} // import flash.geom.Point; // import flash.geom.Rectangle; static class BoundsCheck { public static readonly int TOP = 1; public static readonly int BOTTOM = 2; public static readonly int LEFT = 4; public static readonly int RIGHT = 8; /** * * @param point * @param bounds * @return an int with the appropriate bits set if the Point lies on the corresponding bounds lines * */ public static int Check (Vector2 point, Rect bounds) { int value = 0; if (point.x == bounds.xMin) { value |= LEFT; } if (point.x == bounds.xMax) { value |= RIGHT; } if (point.y == bounds.yMin) { value |= TOP; } if (point.y == bounds.yMax) { value |= BOTTOM; } return value; } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Site.cs.meta ================================================ fileFormatVersion: 2 guid: fa5d818389dce40d29f97fb47bf83081 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/SiteList.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.Geo; using Delaunay.Utils; namespace Delaunay { public sealed class SiteList: Utils.IDisposable { private List _sites; private int _currentIndex; private bool _sorted; public SiteList () { _sites = new List (); _sorted = false; } public void Dispose () { if (_sites != null) { for (int i = 0; i < _sites.Count; i++) { Site site = _sites [i]; site.Dispose (); } _sites.Clear (); _sites = null; } } public int Add (Site site) { _sorted = false; _sites.Add (site); return _sites.Count; } public int Count { get { return _sites.Count;} } public Site Next () { if (_sorted == false) { UnityEngine.Debug.LogError ("SiteList::next(): sites have not been sorted"); } if (_currentIndex < _sites.Count) { return _sites [_currentIndex++]; } else { return null; } } internal Rect GetSitesBounds () { if (_sorted == false) { Site.SortSites (_sites); _currentIndex = 0; _sorted = true; } float xmin, xmax, ymin, ymax; if (_sites.Count == 0) { return new Rect (0, 0, 0, 0); } xmin = float.MaxValue; xmax = float.MinValue; for (int i = 0; i<_sites.Count; i++) { Site site = _sites [i]; if (site.x < xmin) { xmin = site.x; } if (site.x > xmax) { xmax = site.x; } } // here's where we assume that the sites have been sorted on y: ymin = _sites [0].y; ymax = _sites [_sites.Count - 1].y; return new Rect (xmin, ymin, xmax - xmin, ymax - ymin); } public List SiteColors (/*BitmapData referenceImage = null*/) { List colors = new List (); Site site; for (int i = 0; i< _sites.Count; i++) { site = _sites [i]; colors.Add (/*referenceImage ? referenceImage.getPixel(site.x, site.y) :*/site.color); } return colors; } public List SiteCoords () { List coords = new List (); Site site; for (int i = 0; i<_sites.Count; i++) { site = _sites [i]; coords.Add (site.Coord); } return coords; } /** * * @return the largest circle centered at each site that fits in its region; * if the region is infinite, return a circle of radius 0. * */ public List Circles () { List circles = new List (); Site site; for (int i = 0; i<_sites.Count; i++) { site = _sites [i]; float radius = 0f; Edge nearestEdge = site.NearestEdge (); if (!nearestEdge.IsPartOfConvexHull ()) { radius = nearestEdge.SitesDistance () * 0.5f; } circles.Add (new Circle (site.x, site.y, radius)); } return circles; } public List> Regions (Rect plotBounds) { List> regions = new List> (); Site site; for (int i = 0; i< _sites.Count; i++) { site = _sites [i]; regions.Add (site.Region (plotBounds)); } return regions; } /** * * @param proximityMap a BitmapData whose regions are filled with the site index values; see PlanePointsCanvas::fillRegions() * @param x * @param y * @return coordinates of nearest Site to (x, y) * */ public Nullable NearestSitePoint (/*proximityMap:BitmapData,*/float x, float y) { // uint index = proximityMap.getPixel(x, y); // if (index > _sites.length - 1) // { return null; // } // return _sites[index].coord; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/SiteList.cs.meta ================================================ fileFormatVersion: 2 guid: d11fa694a445f4fbb9c6ef8f51d7d549 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Triangle.cs ================================================ using System.Collections.Generic; using Delaunay.Utils; namespace Delaunay { public sealed class Triangle: IDisposable { private List _sites; public List sites { get { return this._sites; } } public Triangle (Site a, Site b, Site c) { _sites = new List () { a, b, c }; } public void Dispose () { _sites.Clear (); _sites = null; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Triangle.cs.meta ================================================ fileFormatVersion: 2 guid: c86ee3287678f413e99d8256fcbbbd6f MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Vertex.cs ================================================ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.LR; namespace Delaunay { public sealed class Vertex: ICoord { public static readonly Vertex VERTEX_AT_INFINITY = new Vertex (float.NaN, float.NaN); private static Stack _pool = new Stack (); private static Vertex Create (float x, float y) { if (float.IsNaN (x) || float.IsNaN (y)) { return VERTEX_AT_INFINITY; } if (_pool.Count > 0) { return _pool.Pop ().Init (x, y); } else { return new Vertex (x, y); } } private static int _nvertices = 0; private Vector2 _coord; public Vector2 Coord { get { return _coord;} } private int _vertexIndex; public int vertexIndex { get { return _vertexIndex;} } public Vertex (float x, float y) { Init (x, y); } private Vertex Init (float x, float y) { _coord = new Vector2 (x, y); return this; } public void Dispose () { _pool.Push (this); } public void SetIndex () { _vertexIndex = _nvertices++; } public override string ToString () { return "Vertex (" + _vertexIndex + ")"; } /** * This is the only way to make a Vertex * * @param halfedge0 * @param halfedge1 * @return * */ public static Vertex Intersect (Halfedge halfedge0, Halfedge halfedge1) { Edge edge0, edge1, edge; Halfedge halfedge; float determinant, intersectionX, intersectionY; bool rightOfSite; edge0 = halfedge0.edge; edge1 = halfedge1.edge; if (edge0 == null || edge1 == null) { return null; } if (edge0.rightSite == edge1.rightSite) { return null; } determinant = edge0.a * edge1.b - edge0.b * edge1.a; if (-1.0e-10 < determinant && determinant < 1.0e-10) { // the edges are parallel return null; } intersectionX = (edge0.c * edge1.b - edge1.c * edge0.b) / determinant; intersectionY = (edge1.c * edge0.a - edge0.c * edge1.a) / determinant; if (Voronoi.CompareByYThenX (edge0.rightSite, edge1.rightSite) < 0) { halfedge = halfedge0; edge = edge0; } else { halfedge = halfedge1; edge = edge1; } rightOfSite = intersectionX >= edge.rightSite.x; if ((rightOfSite && halfedge.leftRight == Side.LEFT) || (!rightOfSite && halfedge.leftRight == Side.RIGHT)) { return null; } return Vertex.Create (intersectionX, intersectionY); } public float x { get { return _coord.x;} } public float y { get{ return _coord.y;} } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Vertex.cs.meta ================================================ fileFormatVersion: 2 guid: 16e154efbeed043e1865a7d95f623368 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Voronoi.cs ================================================ /* * The author of this software is Steven Fortune. Copyright (c) 1994 by AT&T * Bell Laboratories. * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ using UnityEngine; using System; using System.Collections.Generic; using Delaunay.Geo; using Delaunay.Utils; using Delaunay.LR; namespace Delaunay { public sealed class Voronoi: Utils.IDisposable { private SiteList _sites; private Dictionary _sitesIndexedByLocation; private List _triangles; private List _edges; // TODO generalize this so it doesn't have to be a rectangle; // then we can make the fractal voronois-within-voronois private Rect _plotBounds; public Rect plotBounds { get { return _plotBounds;} } public void Dispose () { int i, n; if (_sites != null) { _sites.Dispose (); _sites = null; } if (_triangles != null) { n = _triangles.Count; for (i = 0; i < n; ++i) { _triangles [i].Dispose (); } _triangles.Clear (); _triangles = null; } if (_edges != null) { n = _edges.Count; for (i = 0; i < n; ++i) { _edges [i].Dispose (); } _edges.Clear (); _edges = null; } // _plotBounds = null; _sitesIndexedByLocation = null; } public Voronoi (List points, List colors, Rect plotBounds) { _sites = new SiteList (); _sitesIndexedByLocation = new Dictionary (); // XXX: Used to be Dictionary(true) -- weak refs. AddSites (points, colors); _plotBounds = plotBounds; _triangles = new List (); _edges = new List (); FortunesAlgorithm (); } private void AddSites (List points, List colors) { int length = points.Count; for (int i = 0; i < length; ++i) { AddSite (points [i], (colors != null) ? colors [i] : 0, i); } } private void AddSite (Vector2 p, uint color, int index) { if (_sitesIndexedByLocation.ContainsKey (p)) return; // Prevent duplicate site! (Adapted from https://github.com/nodename/as3delaunay/issues/1) float weight = UnityEngine.Random.value * 100f; Site site = Site.Create (p, (uint)index, weight, color); _sites.Add (site); _sitesIndexedByLocation [p] = site; } public List Edges () { return _edges; } public List Region (Vector2 p) { Site site = _sitesIndexedByLocation [p]; if (site == null) { return new List (); } return site.Region (_plotBounds); } // TODO: bug: if you call this before you call region(), something goes wrong :( public List NeighborSitesForSite (Vector2 coord) { List points = new List (); Site site = _sitesIndexedByLocation [coord]; if (site == null) { return points; } List sites = site.NeighborSites (); Site neighbor; for (int nIndex =0; nIndex Circles () { return _sites.Circles (); } public List VoronoiBoundaryForSite (Vector2 coord) { return DelaunayHelpers.VisibleLineSegments (DelaunayHelpers.SelectEdgesForSitePoint (coord, _edges)); } public List DelaunayLinesForSite (Vector2 coord) { return DelaunayHelpers.DelaunayLinesForEdges (DelaunayHelpers.SelectEdgesForSitePoint (coord, _edges)); } public List VoronoiDiagram () { return DelaunayHelpers.VisibleLineSegments (_edges); } public List DelaunayTriangulation (/*BitmapData keepOutMask = null*/) { return DelaunayHelpers.DelaunayLinesForEdges (DelaunayHelpers.SelectNonIntersectingEdges (/*keepOutMask,*/_edges)); } public List Hull () { return DelaunayHelpers.DelaunayLinesForEdges (HullEdges ()); } private List HullEdges () { return _edges.FindAll (delegate (Edge edge) { return (edge.IsPartOfConvexHull ()); }); } public List HullPointsInOrder () { List hullEdges = HullEdges (); List points = new List (); if (hullEdges.Count == 0) { return points; } EdgeReorderer reorderer = new EdgeReorderer (hullEdges, VertexOrSite.SITE); hullEdges = reorderer.edges; List orientations = reorderer.edgeOrientations; reorderer.Dispose (); Side orientation; int n = hullEdges.Count; for (int i = 0; i < n; ++i) { Edge edge = hullEdges [i]; orientation = orientations [i]; points.Add (edge.Site (orientation).Coord); } return points; } public List SpanningTree (KruskalType type = KruskalType.MINIMUM/*, BitmapData keepOutMask = null*/) { List edges = DelaunayHelpers.SelectNonIntersectingEdges (/*keepOutMask,*/_edges); List segments = DelaunayHelpers.DelaunayLinesForEdges (edges); return DelaunayHelpers.Kruskal (segments, type); } public List> Regions () { return _sites.Regions (_plotBounds); } public List SiteColors (/*BitmapData referenceImage = null*/) { return _sites.SiteColors (/*referenceImage*/); } /** * * @param proximityMap a BitmapData whose regions are filled with the site index values; see PlanePointsCanvas::fillRegions() * @param x * @param y * @return coordinates of nearest Site to (x, y) * */ public Nullable NearestSitePoint (/*BitmapData proximityMap,*/float x, float y) { return _sites.NearestSitePoint (/*proximityMap,*/x, y); } public List SiteCoords () { return _sites.SiteCoords (); } private Site fortunesAlgorithm_bottomMostSite; private void FortunesAlgorithm () { Site newSite, bottomSite, topSite, tempSite; Vertex v, vertex; Vector2 newintstar = Vector2.zero; //Because the compiler doesn't know that it will have a value - Julian Side leftRight; Halfedge lbnd, rbnd, llbnd, rrbnd, bisector; Edge edge; Rect dataBounds = _sites.GetSitesBounds (); int sqrt_nsites = (int)(Mathf.Sqrt (_sites.Count + 4)); HalfedgePriorityQueue heap = new HalfedgePriorityQueue (dataBounds.y, dataBounds.height, sqrt_nsites); EdgeList edgeList = new EdgeList (dataBounds.x, dataBounds.width, sqrt_nsites); List halfEdges = new List (); List vertices = new List (); fortunesAlgorithm_bottomMostSite = _sites.Next (); newSite = _sites.Next (); for (;;) { if (heap.Empty () == false) { newintstar = heap.Min (); } if (newSite != null && (heap.Empty () || CompareByYThenX (newSite, newintstar) < 0)) { /* new site is smallest */ //trace("smallest: new site " + newSite); // Step 8: lbnd = edgeList.EdgeListLeftNeighbor (newSite.Coord); // the Halfedge just to the left of newSite //trace("lbnd: " + lbnd); rbnd = lbnd.edgeListRightNeighbor; // the Halfedge just to the right //trace("rbnd: " + rbnd); bottomSite = FortunesAlgorithm_rightRegion (lbnd); // this is the same as leftRegion(rbnd) // this Site determines the region containing the new site //trace("new Site is in region of existing site: " + bottomSite); // Step 9: edge = Edge.CreateBisectingEdge (bottomSite, newSite); //trace("new edge: " + edge); _edges.Add (edge); bisector = Halfedge.Create (edge, Side.LEFT); halfEdges.Add (bisector); // inserting two Halfedges into edgeList constitutes Step 10: // insert bisector to the right of lbnd: edgeList.Insert (lbnd, bisector); // first half of Step 11: if ((vertex = Vertex.Intersect (lbnd, bisector)) != null) { vertices.Add (vertex); heap.Remove (lbnd); lbnd.vertex = vertex; lbnd.ystar = vertex.y + newSite.Dist (vertex); heap.Insert (lbnd); } lbnd = bisector; bisector = Halfedge.Create (edge, Side.RIGHT); halfEdges.Add (bisector); // second Halfedge for Step 10: // insert bisector to the right of lbnd: edgeList.Insert (lbnd, bisector); // second half of Step 11: if ((vertex = Vertex.Intersect (bisector, rbnd)) != null) { vertices.Add (vertex); bisector.vertex = vertex; bisector.ystar = vertex.y + newSite.Dist (vertex); heap.Insert (bisector); } newSite = _sites.Next (); } else if (heap.Empty () == false) { /* intersection is smallest */ lbnd = heap.ExtractMin (); llbnd = lbnd.edgeListLeftNeighbor; rbnd = lbnd.edgeListRightNeighbor; rrbnd = rbnd.edgeListRightNeighbor; bottomSite = FortunesAlgorithm_leftRegion (lbnd); topSite = FortunesAlgorithm_rightRegion (rbnd); // these three sites define a Delaunay triangle // (not actually using these for anything...) //_triangles.push(new Triangle(bottomSite, topSite, rightRegion(lbnd))); v = lbnd.vertex; v.SetIndex (); lbnd.edge.SetVertex ((Side)lbnd.leftRight, v); rbnd.edge.SetVertex ((Side)rbnd.leftRight, v); edgeList.Remove (lbnd); heap.Remove (rbnd); edgeList.Remove (rbnd); leftRight = Side.LEFT; if (bottomSite.y > topSite.y) { tempSite = bottomSite; bottomSite = topSite; topSite = tempSite; leftRight = Side.RIGHT; } edge = Edge.CreateBisectingEdge (bottomSite, topSite); _edges.Add (edge); bisector = Halfedge.Create (edge, leftRight); halfEdges.Add (bisector); edgeList.Insert (llbnd, bisector); edge.SetVertex (SideHelper.Other (leftRight), v); if ((vertex = Vertex.Intersect (llbnd, bisector)) != null) { vertices.Add (vertex); heap.Remove (llbnd); llbnd.vertex = vertex; llbnd.ystar = vertex.y + bottomSite.Dist (vertex); heap.Insert (llbnd); } if ((vertex = Vertex.Intersect (bisector, rrbnd)) != null) { vertices.Add (vertex); bisector.vertex = vertex; bisector.ystar = vertex.y + bottomSite.Dist (vertex); heap.Insert (bisector); } } else { break; } } // heap should be empty now heap.Dispose (); edgeList.Dispose (); for (int hIndex = 0; hIndex s2.y) return 1; if (s1.x < s2.x) return -1; if (s1.x > s2.x) return 1; return 0; } public static int CompareByYThenX (Site s1, Vector2 s2) { if (s1.y < s2.y) return -1; if (s1.y > s2.y) return 1; if (s1.x < s2.x) return -1; if (s1.x > s2.x) return 1; return 0; } } } ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay/Voronoi.cs.meta ================================================ fileFormatVersion: 2 guid: 8a659b037ca774ad4b255ac68dbe65ae MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/Delaunay.meta ================================================ fileFormatVersion: 2 guid: 7ea91cd8b2a424a0f97e63013b752cdc folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Unity-delaunay/Plane Material.mat ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!21 &2100000 Material: serializedVersion: 3 m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_Name: Plane Material m_Shader: {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} m_ShaderKeywords: [] m_CustomRenderQueue: -1 m_SavedProperties: serializedVersion: 2 m_TexEnvs: data: first: name: _MainTex second: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} data: first: name: _Illum second: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} m_Floats: data: first: name: _EmissionLM second: 0 m_Colors: data: first: name: _Color second: {r: 1, g: 1, b: 1, a: 1} ================================================ FILE: demo/Assets/Unity-delaunay/Plane Material.mat.meta ================================================ fileFormatVersion: 2 guid: 361fa52b5561d434baaff15f2fe36f3d NativeFormatImporter: userData: ================================================ FILE: demo/Assets/Unity-delaunay/geom/Circle.cs ================================================ using UnityEngine; using System; namespace Delaunay { namespace Geo { public sealed class Circle { public Vector2 center; public float radius; public Circle (float centerX, float centerY, float radius) { this.center = new Vector2 (centerX, centerY); this.radius = radius; } public override string ToString () { return "Circle (center: " + center.ToString () + "; radius: " + radius.ToString () + ")"; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/geom/Circle.cs.meta ================================================ fileFormatVersion: 2 guid: e5300884d68b94e1c958b6328944dcca MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/geom/LineSegment.cs ================================================ using UnityEngine; using System; namespace Delaunay { namespace Geo { public sealed class LineSegment { public static int CompareLengths_MAX (LineSegment segment0, LineSegment segment1) { float length0 = Vector2.Distance ((Vector2)segment0.p0, (Vector2)segment0.p1); float length1 = Vector2.Distance ((Vector2)segment1.p0, (Vector2)segment1.p1); if (length0 < length1) { return 1; } if (length0 > length1) { return -1; } return 0; } public static int CompareLengths (LineSegment edge0, LineSegment edge1) { return - CompareLengths_MAX (edge0, edge1); } public Nullable p0; public Nullable p1; public LineSegment (Nullable p0, Nullable p1) { this.p0 = p0; this.p1 = p1; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/geom/LineSegment.cs.meta ================================================ fileFormatVersion: 2 guid: 76312350a2abb4fa9a9926fc7da2287d MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/geom/Polygon.cs ================================================ using UnityEngine; using System.Collections.Generic; namespace Delaunay { namespace Geo { public sealed class Polygon { private List _vertices; public Polygon (List vertices) { _vertices = vertices; } public float Area () { return Mathf.Abs (SignedDoubleArea () * 0.5f); // XXX: I'm a bit nervous about this; not sure what the * 0.5 is for, bithacking? } public Winding Winding () { float signedDoubleArea = SignedDoubleArea (); if (signedDoubleArea < 0) { return Geo.Winding.CLOCKWISE; } if (signedDoubleArea > 0) { return Geo.Winding.COUNTERCLOCKWISE; } return Geo.Winding.NONE; } private float SignedDoubleArea () // XXX: I'm a bit nervous about this because Actionscript represents everything as doubles, not floats { int index, nextIndex; int n = _vertices.Count; Vector2 point, next; float signedDoubleArea = 0; // Losing lots of precision? for (index = 0; index < n; ++index) { nextIndex = (index + 1) % n; point = _vertices [index]; next = _vertices [nextIndex]; signedDoubleArea += point.x * next.y - next.x * point.y; } return signedDoubleArea; } } } } ================================================ FILE: demo/Assets/Unity-delaunay/geom/Polygon.cs.meta ================================================ fileFormatVersion: 2 guid: e59bb833c9cf045e992b44a5e23837cb MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/geom/Winding.cs ================================================ namespace Delaunay { namespace Geo { public enum Winding { NONE = 0, CLOCKWISE, COUNTERCLOCKWISE } } } ================================================ FILE: demo/Assets/Unity-delaunay/geom/Winding.cs.meta ================================================ fileFormatVersion: 2 guid: 1a38f1425b42547898d3b2ef6c865e05 MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/geom.meta ================================================ fileFormatVersion: 2 guid: 2ee5f0dcc71544e1dade82ac72f7fc3d folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Unity-delaunay/utils/IDisposable.cs ================================================ namespace Delaunay { namespace Utils { public interface IDisposable { void Dispose (); } } } ================================================ FILE: demo/Assets/Unity-delaunay/utils/IDisposable.cs.meta ================================================ fileFormatVersion: 2 guid: 7cb01ead474dc485fa87ef0e202dcc6d MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: ================================================ FILE: demo/Assets/Unity-delaunay/utils.meta ================================================ fileFormatVersion: 2 guid: 6505f93572a1d41a38b2f1aeee65897b folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/Assets/Unity-delaunay.meta ================================================ fileFormatVersion: 2 guid: adf918391394e4918943cbf0bb3dd6ea folderAsset: yes DefaultImporter: userData: ================================================ FILE: demo/ProjectSettings/AudioManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!11 &1 AudioManager: m_ObjectHideFlags: 0 m_Volume: 1 Rolloff Scale: 1 m_SpeedOfSound: 347 Doppler Factor: 1 Default Speaker Mode: 2 m_DSPBufferSize: 0 m_DisableAudio: 0 ================================================ FILE: demo/ProjectSettings/ClusterInputManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!236 &1 ClusterInputManager: m_ObjectHideFlags: 0 m_Inputs: [] ================================================ FILE: demo/ProjectSettings/DynamicsManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!55 &1 PhysicsManager: m_ObjectHideFlags: 0 m_Gravity: {x: 0, y: -9.81000042, z: 0} m_DefaultMaterial: {fileID: 0} m_BounceThreshold: 2 m_SleepVelocity: .150000006 m_SleepAngularVelocity: .140000001 m_MaxAngularVelocity: 7 m_MinPenetrationForPenalty: .00999999978 m_SolverIterationCount: 6 m_RaycastsHitTriggers: 1 m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ================================================ FILE: demo/ProjectSettings/EditorBuildSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!1045 &1 EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 m_Scenes: [] ================================================ FILE: demo/ProjectSettings/EditorSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!159 &1 EditorSettings: m_ObjectHideFlags: 0 serializedVersion: 3 m_ExternalVersionControlSupport: Hidden Meta Files m_SerializationMode: 2 m_WebSecurityEmulationEnabled: 0 m_WebSecurityEmulationHostUrl: http://www.mydomain.com/mygame.unity3d m_DefaultBehaviorMode: 1 m_SpritePackerMode: 0 ================================================ FILE: demo/ProjectSettings/GraphicsSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!30 &1 GraphicsSettings: m_ObjectHideFlags: 0 serializedVersion: 12 m_Deferred: m_Mode: 1 m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} m_DeferredReflections: m_Mode: 1 m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} m_ScreenSpaceShadows: m_Mode: 1 m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} m_LegacyDeferred: m_Mode: 1 m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} m_DepthNormals: m_Mode: 1 m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} m_MotionVectors: m_Mode: 1 m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} m_LightHalo: m_Mode: 1 m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} m_LensFlare: m_Mode: 1 m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} m_AlwaysIncludedShaders: - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} m_CustomRenderPipeline: {fileID: 0} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} m_DefaultRenderingPath: 1 m_DefaultMobileRenderingPath: 1 m_TierSettings: [] m_LightmapStripping: 0 m_FogStripping: 0 m_InstancingStripping: 0 m_LightmapKeepPlain: 1 m_LightmapKeepDirCombined: 1 m_LightmapKeepDynamicPlain: 1 m_LightmapKeepDynamicDirCombined: 1 m_LightmapKeepShadowMask: 1 m_LightmapKeepSubtractive: 1 m_FogKeepLinear: 1 m_FogKeepExp: 1 m_FogKeepExp2: 1 m_AlbedoSwatchInfos: [] m_LightsUseLinearIntensity: 0 m_LightsUseColorTemperature: 0 ================================================ FILE: demo/ProjectSettings/InputManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!13 &1 InputManager: m_ObjectHideFlags: 0 m_Axes: - serializedVersion: 3 m_Name: Horizontal descriptiveName: descriptiveNegativeName: negativeButton: left positiveButton: right altNegativeButton: a altPositiveButton: d gravity: 3 dead: .00100000005 sensitivity: 3 snap: 1 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Vertical descriptiveName: descriptiveNegativeName: negativeButton: down positiveButton: up altNegativeButton: s altPositiveButton: w gravity: 3 dead: .00100000005 sensitivity: 3 snap: 1 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Fire1 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: left ctrl altNegativeButton: altPositiveButton: mouse 0 gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Fire2 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: left alt altNegativeButton: altPositiveButton: mouse 1 gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Fire3 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: left cmd altNegativeButton: altPositiveButton: mouse 2 gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Jump descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: space altNegativeButton: altPositiveButton: gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Mouse X descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: altNegativeButton: altPositiveButton: gravity: 0 dead: 0 sensitivity: .100000001 snap: 0 invert: 0 type: 1 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Mouse Y descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: altNegativeButton: altPositiveButton: gravity: 0 dead: 0 sensitivity: .100000001 snap: 0 invert: 0 type: 1 axis: 1 joyNum: 0 - serializedVersion: 3 m_Name: Mouse ScrollWheel descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: altNegativeButton: altPositiveButton: gravity: 0 dead: 0 sensitivity: .100000001 snap: 0 invert: 0 type: 1 axis: 2 joyNum: 0 - serializedVersion: 3 m_Name: Horizontal descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: altNegativeButton: altPositiveButton: gravity: 0 dead: .189999998 sensitivity: 1 snap: 0 invert: 0 type: 2 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Vertical descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: altNegativeButton: altPositiveButton: gravity: 0 dead: .189999998 sensitivity: 1 snap: 0 invert: 1 type: 2 axis: 1 joyNum: 0 - serializedVersion: 3 m_Name: Fire1 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: joystick button 0 altNegativeButton: altPositiveButton: gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Fire2 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: joystick button 1 altNegativeButton: altPositiveButton: gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Fire3 descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: joystick button 2 altNegativeButton: altPositiveButton: gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 - serializedVersion: 3 m_Name: Jump descriptiveName: descriptiveNegativeName: negativeButton: positiveButton: joystick button 3 altNegativeButton: altPositiveButton: gravity: 1000 dead: .00100000005 sensitivity: 1000 snap: 0 invert: 0 type: 0 axis: 0 joyNum: 0 ================================================ FILE: demo/ProjectSettings/NavMeshAreas.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!126 &1 NavMeshLayers: m_ObjectHideFlags: 0 Built-in Layer 0: name: Default cost: 1 editType: 2 Built-in Layer 1: name: Not Walkable cost: 1 editType: 0 Built-in Layer 2: name: Jump cost: 2 editType: 2 User Layer 0: name: cost: 1 editType: 3 User Layer 1: name: cost: 1 editType: 3 User Layer 2: name: cost: 1 editType: 3 User Layer 3: name: cost: 1 editType: 3 User Layer 4: name: cost: 1 editType: 3 User Layer 5: name: cost: 1 editType: 3 User Layer 6: name: cost: 1 editType: 3 User Layer 7: name: cost: 1 editType: 3 User Layer 8: name: cost: 1 editType: 3 User Layer 9: name: cost: 1 editType: 3 User Layer 10: name: cost: 1 editType: 3 User Layer 11: name: cost: 1 editType: 3 User Layer 12: name: cost: 1 editType: 3 User Layer 13: name: cost: 1 editType: 3 User Layer 14: name: cost: 1 editType: 3 User Layer 15: name: cost: 1 editType: 3 User Layer 16: name: cost: 1 editType: 3 User Layer 17: name: cost: 1 editType: 3 User Layer 18: name: cost: 1 editType: 3 User Layer 19: name: cost: 1 editType: 3 User Layer 20: name: cost: 1 editType: 3 User Layer 21: name: cost: 1 editType: 3 User Layer 22: name: cost: 1 editType: 3 User Layer 23: name: cost: 1 editType: 3 User Layer 24: name: cost: 1 editType: 3 User Layer 25: name: cost: 1 editType: 3 User Layer 26: name: cost: 1 editType: 3 User Layer 27: name: cost: 1 editType: 3 User Layer 28: name: cost: 1 editType: 3 ================================================ FILE: demo/ProjectSettings/NavMeshLayers.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!126 &1 NavMeshLayers: m_ObjectHideFlags: 0 Built-in Layer 0: name: Default cost: 1 editType: 2 Built-in Layer 1: name: Not Walkable cost: 1 editType: 0 Built-in Layer 2: name: Jump cost: 2 editType: 2 User Layer 0: name: cost: 1 editType: 3 User Layer 1: name: cost: 1 editType: 3 User Layer 2: name: cost: 1 editType: 3 User Layer 3: name: cost: 1 editType: 3 User Layer 4: name: cost: 1 editType: 3 User Layer 5: name: cost: 1 editType: 3 User Layer 6: name: cost: 1 editType: 3 User Layer 7: name: cost: 1 editType: 3 User Layer 8: name: cost: 1 editType: 3 User Layer 9: name: cost: 1 editType: 3 User Layer 10: name: cost: 1 editType: 3 User Layer 11: name: cost: 1 editType: 3 User Layer 12: name: cost: 1 editType: 3 User Layer 13: name: cost: 1 editType: 3 User Layer 14: name: cost: 1 editType: 3 User Layer 15: name: cost: 1 editType: 3 User Layer 16: name: cost: 1 editType: 3 User Layer 17: name: cost: 1 editType: 3 User Layer 18: name: cost: 1 editType: 3 User Layer 19: name: cost: 1 editType: 3 User Layer 20: name: cost: 1 editType: 3 User Layer 21: name: cost: 1 editType: 3 User Layer 22: name: cost: 1 editType: 3 User Layer 23: name: cost: 1 editType: 3 User Layer 24: name: cost: 1 editType: 3 User Layer 25: name: cost: 1 editType: 3 User Layer 26: name: cost: 1 editType: 3 User Layer 27: name: cost: 1 editType: 3 User Layer 28: name: cost: 1 editType: 3 ================================================ FILE: demo/ProjectSettings/NetworkManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!149 &1 NetworkManager: m_ObjectHideFlags: 0 m_DebugLevel: 0 m_Sendrate: 15 m_AssetToPrefab: {} ================================================ FILE: demo/ProjectSettings/Physics2DSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!19 &1 Physics2DSettings: m_ObjectHideFlags: 0 m_Gravity: {x: 0, y: -9.81000042} m_DefaultMaterial: {fileID: 0} m_VelocityIterations: 8 m_PositionIterations: 3 m_VelocityThreshold: 1 m_MaxLinearCorrection: .200000003 m_MaxAngularCorrection: 8 m_MaxTranslationSpeed: 100 m_MaxRotationSpeed: 360 m_BaumgarteScale: .200000003 m_BaumgarteTimeOfImpactScale: .75 m_TimeToSleep: .5 m_LinearSleepTolerance: .00999999978 m_AngularSleepTolerance: 2 m_RaycastsHitTriggers: 1 m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ================================================ FILE: demo/ProjectSettings/ProjectSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 serializedVersion: 12 productGUID: 0af961f893b0243a1953a65081cbafc9 AndroidProfiler: 0 defaultScreenOrientation: 0 targetDevice: 2 useOnDemandResources: 0 accelerometerFrequency: 60 companyName: DefaultCompany productName: demo defaultCursor: {fileID: 0} cursorHotspot: {x: 0, y: 0} m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} m_ShowUnitySplashScreen: 1 m_ShowUnitySplashLogo: 1 m_SplashScreenOverlayOpacity: 1 m_SplashScreenAnimation: 1 m_SplashScreenLogoStyle: 1 m_SplashScreenDrawMode: 0 m_SplashScreenBackgroundAnimationZoom: 1 m_SplashScreenLogoAnimationZoom: 1 m_SplashScreenBackgroundLandscapeAspect: 1 m_SplashScreenBackgroundPortraitAspect: 1 m_SplashScreenBackgroundLandscapeUvs: serializedVersion: 2 x: 0 y: 0 width: 1 height: 1 m_SplashScreenBackgroundPortraitUvs: serializedVersion: 2 x: 0 y: 0 width: 1 height: 1 m_SplashScreenLogos: [] m_SplashScreenBackgroundLandscape: {fileID: 0} m_SplashScreenBackgroundPortrait: {fileID: 0} m_VirtualRealitySplashScreen: {fileID: 0} m_HolographicTrackingLossScreen: {fileID: 0} defaultScreenWidth: 1024 defaultScreenHeight: 768 defaultScreenWidthWeb: 960 defaultScreenHeightWeb: 600 m_StereoRenderingPath: 0 m_ActiveColorSpace: 0 m_MTRendering: 1 m_MobileMTRendering: 0 m_StackTraceTypes: 010000000100000001000000010000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 tizenShowActivityIndicatorOnLoading: -1 iosAppInBackgroundBehavior: 0 displayResolutionDialog: 1 iosAllowHTTPDownload: 1 allowedAutorotateToPortrait: 1 allowedAutorotateToPortraitUpsideDown: 1 allowedAutorotateToLandscapeRight: 1 allowedAutorotateToLandscapeLeft: 1 useOSAutorotation: 1 use32BitDisplayBuffer: 1 disableDepthAndStencilBuffers: 0 defaultIsFullScreen: 1 defaultIsNativeResolution: 1 runInBackground: 1 captureSingleScreen: 0 muteOtherAudioSources: 0 Prepare IOS For Recording: 0 Force IOS Speakers When Recording: 0 submitAnalytics: 1 usePlayerLog: 1 bakeCollisionMeshes: 0 forceSingleInstance: 0 resizableWindow: 0 useMacAppStoreValidation: 0 macAppStoreCategory: public.app-category.games gpuSkinning: 0 graphicsJobs: 0 xboxPIXTextureCapture: 0 xboxEnableAvatar: 0 xboxEnableKinect: 0 xboxEnableKinectAutoTracking: 0 xboxEnableFitness: 0 visibleInBackground: 0 allowFullscreenSwitch: 1 graphicsJobMode: 0 macFullscreenMode: 2 d3d9FullscreenMode: 1 d3d11FullscreenMode: 1 xboxSpeechDB: 0 xboxEnableHeadOrientation: 0 xboxEnableGuest: 0 xboxEnablePIXSampling: 0 n3dsDisableStereoscopicView: 0 n3dsEnableSharedListOpt: 1 n3dsEnableVSync: 0 ignoreAlphaClear: 0 xboxOneResolution: 0 xboxOneMonoLoggingLevel: 0 xboxOneLoggingLevel: 1 xboxOneDisableEsram: 0 videoMemoryForVertexBuffers: 0 psp2PowerMode: 0 psp2AcquireBGM: 1 wiiUTVResolution: 0 wiiUGamePadMSAA: 1 wiiUSupportsNunchuk: 0 wiiUSupportsClassicController: 0 wiiUSupportsBalanceBoard: 0 wiiUSupportsMotionPlus: 0 wiiUSupportsProController: 0 wiiUAllowScreenCapture: 1 wiiUControllerCount: 0 m_SupportedAspectRatios: 4:3: 1 5:4: 1 16:10: 1 16:9: 1 Others: 1 bundleVersion: 1.0 preloadedAssets: [] metroInputSource: 0 m_HolographicPauseOnTrackingLoss: 1 xboxOneDisableKinectGpuReservation: 0 xboxOneEnable7thCore: 0 vrSettings: cardboard: depthFormat: 0 enableTransitionView: 0 daydream: depthFormat: 0 useSustainedPerformanceMode: 0 hololens: depthFormat: 1 protectGraphicsMemory: 0 useHDRDisplay: 0 targetPixelDensity: 0 resolutionScalingMode: 0 applicationIdentifier: Android: Standalone: unity.DefaultCompany.demo Tizen: iOS: com.Company.ProductName tvOS: buildNumber: iOS: AndroidBundleVersionCode: 1 AndroidMinSdkVersion: 16 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: stripEngineCode: 1 iPhoneStrippingLevel: 0 iPhoneScriptCallOptimization: 0 ForceInternetPermission: 0 ForceSDCardPermission: 0 CreateWallpaper: 0 APKExpansionFiles: 0 keepLoadedShadersAlive: 0 StripUnusedMeshComponents: 0 VertexChannelCompressionMask: serializedVersion: 2 m_Bits: 238 iPhoneSdkVersion: 988 iOSTargetOSVersionString: tvOSSdkVersion: 0 tvOSRequireExtendedGameController: 0 tvOSTargetOSVersionString: uIPrerenderedIcon: 0 uIRequiresPersistentWiFi: 0 uIRequiresFullScreen: 1 uIStatusBarHidden: 1 uIExitOnSuspend: 0 uIStatusBarStyle: 0 iPhoneSplashScreen: {fileID: 0} iPhoneHighResSplashScreen: {fileID: 0} iPhoneTallHighResSplashScreen: {fileID: 0} iPhone47inSplashScreen: {fileID: 0} iPhone55inPortraitSplashScreen: {fileID: 0} iPhone55inLandscapeSplashScreen: {fileID: 0} iPadPortraitSplashScreen: {fileID: 0} iPadHighResPortraitSplashScreen: {fileID: 0} iPadLandscapeSplashScreen: {fileID: 0} iPadHighResLandscapeSplashScreen: {fileID: 0} appleTVSplashScreen: {fileID: 0} tvOSSmallIconLayers: [] tvOSLargeIconLayers: [] tvOSTopShelfImageLayers: [] tvOSTopShelfImageWideLayers: [] iOSLaunchScreenType: 0 iOSLaunchScreenPortrait: {fileID: 0} iOSLaunchScreenLandscape: {fileID: 0} iOSLaunchScreenBackgroundColor: serializedVersion: 2 rgba: 0 iOSLaunchScreenFillPct: 100 iOSLaunchScreenSize: 100 iOSLaunchScreenCustomXibPath: iOSLaunchScreeniPadType: 0 iOSLaunchScreeniPadImage: {fileID: 0} iOSLaunchScreeniPadBackgroundColor: serializedVersion: 2 rgba: 0 iOSLaunchScreeniPadFillPct: 100 iOSLaunchScreeniPadSize: 100 iOSLaunchScreeniPadCustomXibPath: iOSDeviceRequirements: [] iOSURLSchemes: [] iOSBackgroundModes: 0 iOSMetalForceHardShadows: 0 metalEditorSupport: 1 metalAPIValidation: 1 iOSRenderExtraFrameOnPause: 1 appleDeveloperTeamID: iOSManualSigningProvisioningProfileID: tvOSManualSigningProvisioningProfileID: appleEnableAutomaticSigning: 0 AndroidTargetDevice: 0 AndroidSplashScreenScale: 0 androidSplashScreen: {fileID: 0} AndroidKeystoreName: AndroidKeyaliasName: AndroidTVCompatibility: 1 AndroidIsGame: 1 androidEnableBanner: 1 m_AndroidBanners: - width: 320 height: 180 banner: {fileID: 0} androidGamepadSupportLevel: 0 resolutionDialogBanner: {fileID: 0} m_BuildTargetIcons: [] m_BuildTargetBatching: [] m_BuildTargetGraphicsAPIs: - m_BuildTarget: AndroidPlayer m_APIs: 08000000 m_Automatic: 0 m_BuildTargetVRSettings: [] openGLRequireES31: 0 openGLRequireES31AEP: 0 webPlayerTemplate: APPLICATION:Default m_TemplateCustomTags: {} wiiUTitleID: 0005000011000000 wiiUGroupID: 00010000 wiiUCommonSaveSize: 4096 wiiUAccountSaveSize: 2048 wiiUOlvAccessKey: 0 wiiUTinCode: 0 wiiUJoinGameId: 0 wiiUJoinGameModeMask: 0000000000000000 wiiUCommonBossSize: 0 wiiUAccountBossSize: 0 wiiUAddOnUniqueIDs: [] wiiUMainThreadStackSize: 3072 wiiULoaderThreadStackSize: 1024 wiiUSystemHeapSize: 128 wiiUTVStartupScreen: {fileID: 0} wiiUGamePadStartupScreen: {fileID: 0} wiiUDrcBufferDisabled: 0 wiiUProfilerLibPath: playModeTestRunnerEnabled: 0 actionOnDotNetUnhandledException: 1 enableInternalProfiler: 0 logObjCUncaughtExceptions: 1 enableCrashReportAPI: 0 cameraUsageDescription: locationUsageDescription: microphoneUsageDescription: switchNetLibKey: switchSocketMemoryPoolSize: 6144 switchSocketAllocatorPoolSize: 128 switchSocketConcurrencyLimit: 14 switchScreenResolutionBehavior: 2 switchUseCPUProfiler: 0 switchApplicationID: 0x01004b9000490000 switchNSODependencies: switchTitleNames_0: switchTitleNames_1: switchTitleNames_2: switchTitleNames_3: switchTitleNames_4: switchTitleNames_5: switchTitleNames_6: switchTitleNames_7: switchTitleNames_8: switchTitleNames_9: switchTitleNames_10: switchTitleNames_11: switchPublisherNames_0: switchPublisherNames_1: switchPublisherNames_2: switchPublisherNames_3: switchPublisherNames_4: switchPublisherNames_5: switchPublisherNames_6: switchPublisherNames_7: switchPublisherNames_8: switchPublisherNames_9: switchPublisherNames_10: switchPublisherNames_11: switchIcons_0: {fileID: 0} switchIcons_1: {fileID: 0} switchIcons_2: {fileID: 0} switchIcons_3: {fileID: 0} switchIcons_4: {fileID: 0} switchIcons_5: {fileID: 0} switchIcons_6: {fileID: 0} switchIcons_7: {fileID: 0} switchIcons_8: {fileID: 0} switchIcons_9: {fileID: 0} switchIcons_10: {fileID: 0} switchIcons_11: {fileID: 0} switchSmallIcons_0: {fileID: 0} switchSmallIcons_1: {fileID: 0} switchSmallIcons_2: {fileID: 0} switchSmallIcons_3: {fileID: 0} switchSmallIcons_4: {fileID: 0} switchSmallIcons_5: {fileID: 0} switchSmallIcons_6: {fileID: 0} switchSmallIcons_7: {fileID: 0} switchSmallIcons_8: {fileID: 0} switchSmallIcons_9: {fileID: 0} switchSmallIcons_10: {fileID: 0} switchSmallIcons_11: {fileID: 0} switchManualHTML: switchAccessibleURLs: switchLegalInformation: switchMainThreadStackSize: 1048576 switchPresenceGroupId: switchLogoHandling: 0 switchReleaseVersion: 0 switchDisplayVersion: 1.0.0 switchStartupUserAccount: 0 switchTouchScreenUsage: 0 switchSupportedLanguagesMask: 0 switchLogoType: 0 switchApplicationErrorCodeCategory: switchUserAccountSaveDataSize: 0 switchUserAccountSaveDataJournalSize: 0 switchApplicationAttribute: 0 switchCardSpecSize: -1 switchCardSpecClock: -1 switchRatingsMask: 0 switchRatingsInt_0: 0 switchRatingsInt_1: 0 switchRatingsInt_2: 0 switchRatingsInt_3: 0 switchRatingsInt_4: 0 switchRatingsInt_5: 0 switchRatingsInt_6: 0 switchRatingsInt_7: 0 switchRatingsInt_8: 0 switchRatingsInt_9: 0 switchRatingsInt_10: 0 switchRatingsInt_11: 0 switchLocalCommunicationIds_0: switchLocalCommunicationIds_1: switchLocalCommunicationIds_2: switchLocalCommunicationIds_3: switchLocalCommunicationIds_4: switchLocalCommunicationIds_5: switchLocalCommunicationIds_6: switchLocalCommunicationIds_7: switchParentalControl: 0 switchAllowsScreenshot: 1 switchDataLossConfirmation: 0 switchSupportedNpadStyles: 3 switchSocketConfigEnabled: 0 switchTcpInitialSendBufferSize: 32 switchTcpInitialReceiveBufferSize: 64 switchTcpAutoSendBufferSizeMax: 256 switchTcpAutoReceiveBufferSizeMax: 256 switchUdpSendBufferSize: 9 switchUdpReceiveBufferSize: 42 switchSocketBufferEfficiency: 4 switchSocketInitializeEnabled: 1 switchNetworkInterfaceManagerInitializeEnabled: 1 switchPlayerConnectionEnabled: 1 ps4NPAgeRating: 12 ps4NPTitleSecret: ps4NPTrophyPackPath: ps4ParentalLevel: 11 ps4ContentID: ED1633-NPXX51362_00-0000000000000000 ps4Category: 0 ps4MasterVersion: 01.00 ps4AppVersion: 01.00 ps4AppType: 0 ps4ParamSfxPath: ps4VideoOutPixelFormat: 0 ps4VideoOutInitialWidth: 1920 ps4VideoOutBaseModeInitialWidth: 1920 ps4VideoOutReprojectionRate: 120 ps4PronunciationXMLPath: ps4PronunciationSIGPath: ps4BackgroundImagePath: ps4StartupImagePath: ps4SaveDataImagePath: ps4SdkOverride: ps4BGMPath: ps4ShareFilePath: ps4ShareOverlayImagePath: ps4PrivacyGuardImagePath: ps4NPtitleDatPath: ps4RemotePlayKeyAssignment: -1 ps4RemotePlayKeyMappingDir: ps4PlayTogetherPlayerCount: 0 ps4EnterButtonAssignment: 1 ps4ApplicationParam1: 0 ps4ApplicationParam2: 0 ps4ApplicationParam3: 0 ps4ApplicationParam4: 0 ps4DownloadDataSize: 0 ps4GarlicHeapSize: 2048 ps4ProGarlicHeapSize: 2560 ps4Passcode: eaoEiIgxIX4a2dREbbSqWy6yhKIDCdJO ps4pnSessions: 1 ps4pnPresence: 1 ps4pnFriends: 1 ps4pnGameCustomData: 1 playerPrefsSupport: 0 restrictedAudioUsageRights: 0 ps4UseResolutionFallback: 0 ps4ReprojectionSupport: 0 ps4UseAudio3dBackend: 0 ps4SocialScreenEnabled: 0 ps4ScriptOptimizationLevel: 0 ps4Audio3dVirtualSpeakerCount: 14 ps4attribCpuUsage: 0 ps4PatchPkgPath: ps4PatchLatestPkgPath: ps4PatchChangeinfoPath: ps4PatchDayOne: 0 ps4attribUserManagement: 0 ps4attribMoveSupport: 0 ps4attrib3DSupport: 0 ps4attribShareSupport: 0 ps4attribExclusiveVR: 0 ps4disableAutoHideSplash: 0 ps4videoRecordingFeaturesUsed: 0 ps4contentSearchFeaturesUsed: 0 ps4attribEyeToEyeDistanceSettingVR: 0 ps4IncludedModules: [] monoEnv: psp2Splashimage: {fileID: 0} psp2NPTrophyPackPath: psp2NPSupportGBMorGJP: 0 psp2NPAgeRating: 12 psp2NPTitleDatPath: psp2NPCommsID: psp2NPCommunicationsID: psp2NPCommsPassphrase: psp2NPCommsSig: psp2ParamSfxPath: psp2ManualPath: psp2LiveAreaGatePath: psp2LiveAreaBackroundPath: psp2LiveAreaPath: psp2LiveAreaTrialPath: psp2PatchChangeInfoPath: psp2PatchOriginalPackage: psp2PackagePassword: yapnxrpMCARCr4zdGc81tBDKsMlaZTXC psp2KeystoneFile: psp2MemoryExpansionMode: 0 psp2DRMType: 0 psp2StorageType: 0 psp2MediaCapacity: 0 psp2DLCConfigPath: psp2ThumbnailPath: psp2BackgroundPath: psp2SoundPath: psp2TrophyCommId: psp2TrophyPackagePath: psp2PackagedResourcesPath: psp2SaveDataQuota: 10240 psp2ParentalLevel: 1 psp2ShortTitle: Not Set psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF psp2Category: 0 psp2MasterVersion: 01.00 psp2AppVersion: 01.00 psp2TVBootMode: 0 psp2EnterButtonAssignment: 2 psp2TVDisableEmu: 0 psp2AllowTwitterDialog: 1 psp2Upgradable: 0 psp2HealthWarning: 0 psp2UseLibLocation: 0 psp2InfoBarOnStartup: 0 psp2InfoBarColor: 0 psp2ScriptOptimizationLevel: 0 psmSplashimage: {fileID: 0} splashScreenBackgroundSourceLandscape: {fileID: 0} splashScreenBackgroundSourcePortrait: {fileID: 0} spritePackerPolicy: webGLMemorySize: 256 webGLExceptionSupport: 1 webGLNameFilesAsHashes: 0 webGLDataCaching: 0 webGLDebugSymbols: 0 webGLEmscriptenArgs: webGLModulesDirectory: webGLTemplate: APPLICATION:Default webGLAnalyzeBuildSize: 0 webGLUseEmbeddedResources: 0 webGLUseWasm: 0 webGLCompressionFormat: 1 scriptingDefineSymbols: {} platformArchitecture: {} scriptingBackend: {} incrementalIl2cppBuild: {} additionalIl2CppArgs: scriptingRuntimeVersion: 0 apiCompatibilityLevelPerPlatform: {} m_RenderingPath: 1 m_MobileRenderingPath: 1 metroPackageName: demo metroPackageVersion: metroCertificatePath: metroCertificatePassword: metroCertificateSubject: metroCertificateIssuer: metroCertificateNotAfter: 0000000000000000 metroApplicationDescription: demo wsaImages: {} metroTileShortName: metroCommandLineArgsFile: metroTileShowName: 0 metroMediumTileShowName: 0 metroLargeTileShowName: 0 metroWideTileShowName: 0 metroDefaultTileSize: 1 metroTileForegroundText: 1 metroTileBackgroundColor: {r: 0, g: 0, b: 0, a: 1} metroSplashScreenBackgroundColor: {r: 0, g: 0, b: 0, a: 1} metroSplashScreenUseBackgroundColor: 0 platformCapabilities: {} metroFTAName: metroFTAFileTypes: [] metroProtocolName: metroCompilationOverrides: 1 tizenProductDescription: tizenProductURL: tizenSigningProfileName: tizenGPSPermissions: 0 tizenMicrophonePermissions: 0 tizenDeploymentTarget: tizenDeploymentTargetType: -1 tizenMinOSVersion: 1 n3dsUseExtSaveData: 0 n3dsCompressStaticMem: 1 n3dsExtSaveDataNumber: 0x12345 n3dsStackSize: 131072 n3dsTargetPlatform: 2 n3dsRegion: 7 n3dsMediaSize: 0 n3dsLogoStyle: 3 n3dsTitle: GameName n3dsProductCode: n3dsApplicationId: 0xFF3FF stvDeviceAddress: stvProductDescription: stvProductAuthor: stvProductAuthorEmail: stvProductLink: stvProductCategory: 0 XboxOneProductId: XboxOneUpdateKey: XboxOneSandboxId: XboxOneContentId: XboxOneTitleId: XboxOneSCId: XboxOneGameOsOverridePath: XboxOnePackagingOverridePath: XboxOneAppManifestOverridePath: XboxOnePackageEncryption: 0 XboxOnePackageUpdateGranularity: 2 XboxOneDescription: XboxOneLanguage: - enus XboxOneCapability: [] XboxOneGameRating: {} XboxOneIsContentPackage: 0 XboxOneEnableGPUVariability: 0 XboxOneSockets: {} XboxOneSplashScreen: {fileID: 0} XboxOneAllowedProductIds: [] XboxOnePersistentLocalStorageSize: 0 xboxOneScriptCompiler: 0 vrEditorSettings: daydream: daydreamIconForeground: {fileID: 0} daydreamIconBackground: {fileID: 0} cloudServicesEnabled: {} facebookSdkVersion: 7.9.4 apiCompatibilityLevel: 2 cloudProjectId: projectName: organizationId: cloudEnabled: 0 enableNativePlatformBackendsForNewInputSystem: 0 disableOldInputManagerSupport: 0 ================================================ FILE: demo/ProjectSettings/ProjectVersion.txt ================================================ m_EditorVersion: 2017.1.1f1 ================================================ FILE: demo/ProjectSettings/QualitySettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!47 &1 QualitySettings: m_ObjectHideFlags: 0 serializedVersion: 5 m_CurrentQuality: 3 m_QualitySettings: - serializedVersion: 2 name: Fastest pixelLightCount: 0 shadows: 0 shadowResolution: 0 shadowProjection: 1 shadowCascades: 1 shadowDistance: 15 blendWeights: 1 textureQuality: 1 anisotropicTextures: 0 antiAliasing: 0 softParticles: 0 softVegetation: 0 vSyncCount: 0 lodBias: .300000012 maximumLODLevel: 0 particleRaycastBudget: 4 excludedTargetPlatforms: [] - serializedVersion: 2 name: Fast pixelLightCount: 0 shadows: 0 shadowResolution: 0 shadowProjection: 1 shadowCascades: 1 shadowDistance: 20 blendWeights: 2 textureQuality: 0 anisotropicTextures: 0 antiAliasing: 0 softParticles: 0 softVegetation: 0 vSyncCount: 0 lodBias: .400000006 maximumLODLevel: 0 particleRaycastBudget: 16 excludedTargetPlatforms: [] - serializedVersion: 2 name: Simple pixelLightCount: 1 shadows: 1 shadowResolution: 0 shadowProjection: 1 shadowCascades: 1 shadowDistance: 20 blendWeights: 2 textureQuality: 0 anisotropicTextures: 1 antiAliasing: 0 softParticles: 0 softVegetation: 0 vSyncCount: 0 lodBias: .699999988 maximumLODLevel: 0 particleRaycastBudget: 64 excludedTargetPlatforms: [] - serializedVersion: 2 name: Good pixelLightCount: 2 shadows: 2 shadowResolution: 1 shadowProjection: 1 shadowCascades: 2 shadowDistance: 40 blendWeights: 2 textureQuality: 0 anisotropicTextures: 1 antiAliasing: 0 softParticles: 0 softVegetation: 1 vSyncCount: 1 lodBias: 1 maximumLODLevel: 0 particleRaycastBudget: 256 excludedTargetPlatforms: [] - serializedVersion: 2 name: Beautiful pixelLightCount: 3 shadows: 2 shadowResolution: 2 shadowProjection: 1 shadowCascades: 2 shadowDistance: 70 blendWeights: 4 textureQuality: 0 anisotropicTextures: 2 antiAliasing: 2 softParticles: 1 softVegetation: 1 vSyncCount: 1 lodBias: 1.5 maximumLODLevel: 0 particleRaycastBudget: 1024 excludedTargetPlatforms: [] - serializedVersion: 2 name: Fantastic pixelLightCount: 4 shadows: 2 shadowResolution: 2 shadowProjection: 1 shadowCascades: 4 shadowDistance: 150 blendWeights: 4 textureQuality: 0 anisotropicTextures: 2 antiAliasing: 2 softParticles: 1 softVegetation: 1 vSyncCount: 1 lodBias: 2 maximumLODLevel: 0 particleRaycastBudget: 4096 excludedTargetPlatforms: [] m_PerPlatformDefaultQuality: {} ================================================ FILE: demo/ProjectSettings/TagManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!78 &1 TagManager: tags: - Builtin Layer 0: Default Builtin Layer 1: TransparentFX Builtin Layer 2: Ignore Raycast Builtin Layer 3: Builtin Layer 4: Water Builtin Layer 5: UI Builtin Layer 6: Builtin Layer 7: User Layer 8: User Layer 9: User Layer 10: User Layer 11: User Layer 12: User Layer 13: User Layer 14: User Layer 15: User Layer 16: User Layer 17: User Layer 18: User Layer 19: User Layer 20: User Layer 21: User Layer 22: User Layer 23: User Layer 24: User Layer 25: User Layer 26: User Layer 27: User Layer 28: User Layer 29: User Layer 30: User Layer 31: m_SortingLayers: - name: Default userID: 0 uniqueID: 0 locked: 0 ================================================ FILE: demo/ProjectSettings/TimeManager.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!5 &1 TimeManager: m_ObjectHideFlags: 0 Fixed Timestep: .0199999996 Maximum Allowed Timestep: .333333343 m_TimeScale: 1 ================================================ FILE: demo/ProjectSettings/UnityConnectSettings.asset ================================================ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!310 &1 UnityConnectSettings: m_ObjectHideFlags: 0 m_Enabled: 0 m_TestMode: 0 m_TestEventUrl: m_TestConfigUrl: m_TestInitMode: 0 CrashReportingSettings: m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes m_Enabled: 0 m_CaptureEditorExceptions: 1 UnityPurchasingSettings: m_Enabled: 0 m_TestMode: 0 UnityAnalyticsSettings: m_Enabled: 0 m_InitializeOnStartup: 1 m_TestMode: 0 m_TestEventUrl: m_TestConfigUrl: UnityAdsSettings: m_Enabled: 0 m_InitializeOnStartup: 1 m_TestMode: 0 m_EnabledPlatforms: 4294967295 m_IosGameId: m_AndroidGameId: m_GameIds: {} m_GameId: PerformanceReportingSettings: m_Enabled: 0