├── Example ├── Decal.jpg ├── DrawTest.unity.meta ├── New Material.mat.meta ├── PaintTest.cs.meta ├── PaintTest.cs ├── Decal.jpg.meta ├── New Material.mat └── DrawTest.unity ├── Screenshots ├── Example1.png ├── Example2.png ├── Example3.png ├── Example4.png ├── Example1.png.meta ├── Example2.png.meta ├── Example3.png.meta └── Example4.png.meta ├── Example.meta ├── Scripts.meta ├── Screenshots.meta ├── Scripts ├── Triangulation2D │ ├── README.md.meta │ ├── Demo │ │ ├── Scenes │ │ │ ├── Demo.unity.meta │ │ │ └── Demo.unity │ │ ├── Materials │ │ │ ├── DemoMesh.mat.meta │ │ │ ├── CanvasLine.mat.meta │ │ │ ├── DemoMeshLine.mat.meta │ │ │ ├── DemoMesh.mat │ │ │ ├── CanvasLine.mat │ │ │ └── DemoMeshLine.mat │ │ ├── Prefabs │ │ │ ├── DemoMesh.prefab.meta │ │ │ └── DemoMesh.prefab │ │ ├── Scenes.meta │ │ ├── Materials.meta │ │ ├── Prefabs.meta │ │ ├── Scripts.meta │ │ ├── Shaders.meta │ │ ├── Shaders │ │ │ ├── DemoLine.shader.meta │ │ │ ├── DemoMesh.shader.meta │ │ │ ├── SimplexNoise3D.cginc.meta │ │ │ ├── DemoLine.shader │ │ │ ├── DemoMesh.shader │ │ │ └── SimplexNoise3D.cginc │ │ └── Scripts │ │ │ ├── Demo.cs.meta │ │ │ ├── DemoMesh.cs.meta │ │ │ ├── LocalStorage.cs.meta │ │ │ ├── LocalStorage.cs │ │ │ ├── DemoMesh.cs │ │ │ └── Demo.cs │ ├── Demo.meta │ ├── Scripts.meta │ ├── Scripts │ │ ├── Circle2D.cs.meta │ │ ├── Polygon2D.cs.meta │ │ ├── Segment2D.cs.meta │ │ ├── Utils2D.cs.meta │ │ ├── Vertex2D.cs.meta │ │ ├── HalfEdge2D.cs.meta │ │ ├── Triangle2D.cs.meta │ │ ├── Triangulation2D.cs.meta │ │ ├── HalfEdge2D.cs │ │ ├── Vertex2D.cs │ │ ├── Segment2D.cs │ │ ├── Circle2D.cs │ │ ├── Triangle2D.cs │ │ ├── Utils2D.cs │ │ ├── Polygon2D.cs │ │ └── Triangulation2D.cs │ └── README.md ├── Triangulation2D.meta ├── MeshGenerator.cs.meta └── MeshGenerator.cs ├── README.md ├── LICENSE └── .gitignore /Example/Decal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mr-sB/PolygonalLineGenerator/HEAD/Example/Decal.jpg -------------------------------------------------------------------------------- /Screenshots/Example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mr-sB/PolygonalLineGenerator/HEAD/Screenshots/Example1.png -------------------------------------------------------------------------------- /Screenshots/Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mr-sB/PolygonalLineGenerator/HEAD/Screenshots/Example2.png -------------------------------------------------------------------------------- /Screenshots/Example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mr-sB/PolygonalLineGenerator/HEAD/Screenshots/Example3.png -------------------------------------------------------------------------------- /Screenshots/Example4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mr-sB/PolygonalLineGenerator/HEAD/Screenshots/Example4.png -------------------------------------------------------------------------------- /Example/DrawTest.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a4fff8fb611e473f8b2ec528c585c6f 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb9c3a557aab44fb585bd62788b45c36 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8fde566f2ded421f97481126017fb92 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Screenshots.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 37b95db8cab68426bb694b015a547e19 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 161ce46da325c479db4f8f099ae60ca6 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Example/New Material.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5dfec8c2a3e074441940138f56ba47e6 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scenes/Demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99428221878334a8683529a91c6d2b53 3 | timeCreated: 1466517357 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 701d6dbf589ea4376b6b9f97ec9764d2 3 | folderAsset: yes 4 | timeCreated: 1465912489 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/DemoMesh.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad59dae05c2214026b6e4097e9fe27d2 3 | timeCreated: 1466515189 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d5eeb6844b10497092a5fac3e2ab776 3 | folderAsset: yes 4 | timeCreated: 1465912651 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/CanvasLine.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3cdb56c432dc643c99684f1e7daff9b8 3 | timeCreated: 1466516387 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/DemoMeshLine.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f0eacebf3e8c64a399242fae6d8dcbc8 3 | timeCreated: 1466694534 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Prefabs/DemoMesh.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01293f85e33724cffb1f6673f3588572 3 | timeCreated: 1466694480 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 57b5bb180f19c43439bb92113c0685ec 3 | folderAsset: yes 4 | timeCreated: 1466692452 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3207a8a0bde6547718c98ca16d9b64ba 3 | folderAsset: yes 4 | timeCreated: 1466754477 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ee545cc6c30e4a3181546264346d7ab 3 | folderAsset: yes 4 | timeCreated: 1466692483 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02f1bde77e07549fe8c002581af4bf39 3 | folderAsset: yes 4 | timeCreated: 1466692500 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 22ae8b0dfc64b479894a635234365124 3 | folderAsset: yes 4 | timeCreated: 1466692462 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4548c7205de644ae984fba97a98543a6 3 | folderAsset: yes 4 | timeCreated: 1466692475 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/DemoLine.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21e9e5ce29c1c4bf18deb2895e31bd70 3 | timeCreated: 1466516398 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/DemoMesh.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ea78bc862e0b4acc886e363496717b6 3 | timeCreated: 1466515194 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/SimplexNoise3D.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 27095d50a08104a8b8c1bd0cc39ee427 3 | timeCreated: 1466758276 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Example/PaintTest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82f1f9b4f0c7b4f43964f30c4c52f701 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/MeshGenerator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f75a7e17fd2e4a01adf47c510b04fac 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/Demo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77e8e35d5f324406abb67b63ec25336b 3 | timeCreated: 1466757756 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Circle2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f4a27231bfb4241f59d009b3ef7a7f55 3 | timeCreated: 1466752903 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Polygon2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4073f796194c44e5b175af9d4b35f40 3 | timeCreated: 1466753084 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Segment2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1f518ac0328164dc79a8882211b12ece 3 | timeCreated: 1466753053 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Utils2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 55e48844b4a884e5286a8968e1dcb026 3 | timeCreated: 1466753182 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Vertex2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e02b555c78fb545a09fcf73891eb2d3e 3 | timeCreated: 1466752955 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/DemoMesh.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bcb5140256a2f492abf35ca80af1c53a 3 | timeCreated: 1466693882 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/HalfEdge2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd14051ec1efb42118dd17e727f7b467 3 | timeCreated: 1466753012 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Triangle2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d9f67eb9a35bd43fbafca4352a90655d 3 | timeCreated: 1466753132 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/LocalStorage.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 179a565d3dde349a8ba57b9d77f383ae 3 | timeCreated: 1466755694 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Triangulation2D.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a78fb95b758004930bc6358a8f554b36 3 | timeCreated: 1465912497 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PolygonalLineGenerator 2 | Generate polygonal line mesh. 3 | 4 | ## Feature 5 | * Generate line mesh in unity play mode. 6 | * Auto generate UV and Normal. 7 | * Editable shape 8 | 9 | ## Effect 10 | ![image](Screenshots/Example1.png) 11 | ![image](Screenshots/Example2.png) 12 | ![image](Screenshots/Example3.png) 13 | ![image](Screenshots/Example4.png) 14 | 15 | ## Note 16 | Support 3D NOW! 17 | 18 | ## Thanks 19 | Thanks for mattatz/unity-triangulation2D providing triangulation2D function. https://github.com/mattatz/unity-triangulation2D 20 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/HalfEdge2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class HalfEdge2D { 11 | public Vector2 p; 12 | public HalfEdge2D from, to; 13 | public HalfEdge2D(Vector2 p) { 14 | this.p = p; 15 | } 16 | public void Invert () { 17 | var tmp = from; from = to; to = tmp; 18 | } 19 | public HalfEdge2D Split () { 20 | var m = (to.p + p) * 0.5f; 21 | var e = new HalfEdge2D(m); 22 | to.from = e; e.to = to; 23 | this.to = e; e.from = this; 24 | return e; 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Vertex2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Vertex2D { 11 | public int ReferenceCount { get { return reference; } } 12 | public Vector2 Coordinate { get { return coordinate; } } 13 | 14 | Vector2 coordinate; 15 | int reference; 16 | 17 | public Vertex2D (Vector2 coord) { 18 | coordinate = coord; 19 | } 20 | 21 | public int Increment () { 22 | return ++reference; 23 | } 24 | 25 | public int Decrement () { 26 | return --reference; 27 | } 28 | } 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Example/PaintTest.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using UnityEngine; 3 | 4 | public class PaintTest : MonoBehaviour 5 | { 6 | public float dis = 20; 7 | [SerializeField] private MeshGenerator MeshGenerator; 8 | private Camera cam; 9 | private Vector2? mLastPoint; 10 | private void Awake() 11 | { 12 | cam = Camera.main; 13 | } 14 | 15 | private void Update() 16 | { 17 | if(!Input.GetMouseButton(0)) return; 18 | if(mLastPoint.HasValue && Vector2.Distance(mLastPoint.Value, Input.mousePosition) < dis) return; 19 | mLastPoint = Input.mousePosition; 20 | if (Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out var hitInfo)) 21 | { 22 | MeshGenerator.Add(MeshGenerator.transform.InverseTransformPoint(hitInfo.point + new Vector3(0, 0.5f, 0))); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/DemoLine.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 | 3 | Shader "Triangulation2D/Demo/Line" { 4 | 5 | Properties { 6 | _Color ("Color", Color) = (0, 0, 1, 1) 7 | } 8 | 9 | SubShader { 10 | Tags { "RenderType"="Opaque" } 11 | LOD 100 12 | 13 | CGINCLUDE 14 | 15 | #include "UnityCG.cginc" 16 | 17 | #pragma target 3.0 18 | 19 | fixed4 _Color; 20 | 21 | struct appdata { 22 | float4 vertex : POSITION; 23 | float3 normal : NORMAL; 24 | float2 uv : TEXCOORD0; 25 | }; 26 | 27 | struct v2f { 28 | float4 vertex : SV_POSITION; 29 | float3 normal : NORMAL; 30 | float2 uv : TEXCOORD0; 31 | }; 32 | 33 | v2f vert (appdata v) { 34 | v2f o; 35 | o.vertex = UnityObjectToClipPos(v.vertex); 36 | o.normal = v.normal; 37 | o.uv = v.uv; 38 | return o; 39 | } 40 | 41 | ENDCG 42 | 43 | Pass { 44 | CGPROGRAM 45 | #pragma vertex vert 46 | #pragma fragment frag 47 | fixed4 frag (v2f i) : SV_Target { 48 | return _Color; 49 | } 50 | ENDCG 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 GH-ZJ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | README.md.meta 52 | LICENSE.meta 53 | 54 | # Unity3D generated file on crash reports 55 | sysinfo.txt 56 | 57 | # Builds 58 | *.apk 59 | *.unitypackage 60 | 61 | # Crashlytics generated file 62 | crashlytics-build.properties 63 | 64 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/LocalStorage.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Collections; 7 | using System.Collections.Generic; 8 | 9 | namespace mattatz.Utils { 10 | 11 | [Serializable] 12 | public class JsonSerialization { 13 | [SerializeField] List target; 14 | public List ToList() { return target; } 15 | public JsonSerialization(List target) { 16 | this.target = target; 17 | } 18 | } 19 | 20 | public class LocalStorage { 21 | 22 | public static void SaveList (List target, string fileName) { 23 | var text = JsonUtility.ToJson(new JsonSerialization(target)); 24 | Save(text, fileName); 25 | } 26 | 27 | public static List LoadList (string fileName) { 28 | string json = Load(fileName); 29 | return JsonUtility.FromJson>(json).ToList(); 30 | } 31 | 32 | public static void Save (string text, string fileName) { 33 | string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileName); 34 | FileInfo fi = new FileInfo(path); 35 | StreamWriter sw = fi.CreateText(); 36 | sw.WriteLine(text); 37 | sw.Flush(); 38 | sw.Close(); 39 | } 40 | 41 | public static string Load (string fileName) { 42 | string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileName); 43 | return System.IO.File.ReadAllText(path); 44 | } 45 | 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/DemoMesh.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Random = UnityEngine.Random; 3 | 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace mattatz.Triangulation2DSystem.Example { 8 | 9 | [RequireComponent (typeof(MeshFilter))] 10 | [RequireComponent (typeof(Rigidbody))] 11 | public class DemoMesh : MonoBehaviour { 12 | 13 | [SerializeField] Material lineMat; 14 | 15 | Triangle2D[] triangles; 16 | 17 | void Start () { 18 | var body = GetComponent(); 19 | body.AddForce(Vector3.forward * Random.Range(150f, 160f)); 20 | body.AddTorque(Random.insideUnitSphere * Random.Range(10f, 20f)); 21 | } 22 | 23 | void Update () {} 24 | 25 | public void SetTriangulation (Triangulation2D triangulation) { 26 | var mesh = triangulation.Build(); 27 | GetComponent().sharedMesh = mesh; 28 | this.triangles = triangulation.Triangle2Ds; 29 | } 30 | 31 | void OnRenderObject () { 32 | if(triangles == null) return; 33 | 34 | GL.PushMatrix(); 35 | GL.MultMatrix (transform.localToWorldMatrix); 36 | 37 | lineMat.SetColor("_Color", Color.black); 38 | lineMat.SetPass(0); 39 | GL.Begin(GL.LINES); 40 | for(int i = 0, n = triangles.Length; i < n; i++) { 41 | var t = triangles[i]; 42 | GL.Vertex(t.s0.a.Coordinate); GL.Vertex(t.s0.b.Coordinate); 43 | GL.Vertex(t.s1.a.Coordinate); GL.Vertex(t.s1.b.Coordinate); 44 | GL.Vertex(t.s2.a.Coordinate); GL.Vertex(t.s2.b.Coordinate); 45 | } 46 | GL.End(); 47 | GL.PopMatrix(); 48 | } 49 | 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/DemoMesh.shader: -------------------------------------------------------------------------------- 1 | // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' 2 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 3 | 4 | Shader "Triangulation2D/Demo/Mesh" { 5 | 6 | Properties { 7 | } 8 | 9 | SubShader { 10 | Tags { "RenderType"="Opaque" } 11 | LOD 100 12 | 13 | CGINCLUDE 14 | 15 | #include "UnityCG.cginc" 16 | 17 | #pragma target 3.0 18 | 19 | struct appdata { 20 | float4 vertex : POSITION; 21 | float3 normal : NORMAL; 22 | float2 uv : TEXCOORD0; 23 | }; 24 | 25 | struct v2f { 26 | float4 vertex : SV_POSITION; 27 | float3 normal : NORMAL; 28 | float2 uv : TEXCOORD0; 29 | }; 30 | 31 | v2f vert (appdata v) { 32 | v2f o; 33 | o.vertex = UnityObjectToClipPos(v.vertex); 34 | o.normal = mul(unity_ObjectToWorld, float4(v.normal, 0)).xyz; 35 | o.uv = v.uv; 36 | return o; 37 | } 38 | 39 | fixed3 normal_color (fixed3 norm) { 40 | return (normalize(norm) + 1.0) * 0.5; 41 | } 42 | 43 | ENDCG 44 | 45 | Pass { 46 | Cull Front 47 | CGPROGRAM 48 | #pragma vertex vert 49 | #pragma fragment frag 50 | fixed4 frag (v2f i) : SV_Target { 51 | fixed4 col = fixed4(normal_color(i.normal), 1); 52 | return col; 53 | } 54 | ENDCG 55 | } 56 | 57 | Pass { 58 | Cull Back 59 | CGPROGRAM 60 | #pragma vertex vert 61 | #pragma fragment frag 62 | fixed4 frag (v2f i) : SV_Target { 63 | fixed4 col = fixed4(normal_color(-i.normal), 1); 64 | return col; 65 | } 66 | ENDCG 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Segment2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Segment2D { 11 | 12 | public int ReferenceCount { get { return reference; } } 13 | public Vertex2D a, b; 14 | 15 | int reference; 16 | float length; 17 | 18 | public Segment2D (Vertex2D a, Vertex2D b) { 19 | this.a = a; 20 | this.b = b; 21 | } 22 | 23 | public Vector2 Midpoint () { 24 | return (a.Coordinate + b.Coordinate) * 0.5f; 25 | } 26 | 27 | public float Length () { 28 | if(length <= 0f) { 29 | length = (a.Coordinate - b.Coordinate).magnitude; 30 | } 31 | return length; 32 | } 33 | 34 | /* 35 | * check a given point "p" lies within diametral circle of segment(a, b) 36 | */ 37 | public bool EncroachedUpon (Vector2 p) { 38 | if(p == a.Coordinate || p == b.Coordinate) return false; 39 | var radius = (a.Coordinate - b.Coordinate).magnitude * 0.5f; 40 | return (Midpoint() - p).magnitude < radius; 41 | } 42 | 43 | public bool HasPoint (Vertex2D v) { 44 | return (a == v) || (b == v); 45 | } 46 | 47 | public bool HasPoint (Vector2 p) { 48 | return (a.Coordinate == p) || (b.Coordinate == p); 49 | } 50 | 51 | public int Increment () { 52 | a.Increment(); 53 | b.Increment(); 54 | return ++reference; 55 | } 56 | 57 | public int Decrement () { 58 | a.Decrement(); 59 | b.Decrement(); 60 | return --reference; 61 | } 62 | 63 | public void DrawGizmos () { 64 | Gizmos.DrawLine(a.Coordinate, b.Coordinate); 65 | } 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Circle2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Circle2D { 11 | public Vector2 center; 12 | public float radius ; 13 | 14 | public Circle2D (Vector2 c, float r) { 15 | this.center = c; 16 | this.radius = r; 17 | } 18 | 19 | public bool Contains (Vector2 p) { 20 | return (p - center).magnitude < radius; 21 | } 22 | 23 | public static Circle2D GetCircumscribedCircle(Triangle2D triangle) { 24 | var x1 = triangle.a.Coordinate.x; 25 | var y1 = triangle.a.Coordinate.y; 26 | var x2 = triangle.b.Coordinate.x; 27 | var y2 = triangle.b.Coordinate.y; 28 | var x3 = triangle.c.Coordinate.x; 29 | var y3 = triangle.c.Coordinate.y; 30 | 31 | float x1_2 = x1 * x1; 32 | float x2_2 = x2 * x2; 33 | float x3_2 = x3 * x3; 34 | float y1_2 = y1 * y1; 35 | float y2_2 = y2 * y2; 36 | float y3_2 = y3 * y3; 37 | 38 | // 外接円の中心座標を計算 39 | float c = 2f * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)); 40 | float x = ((y3 - y1) * (x2_2 - x1_2 + y2_2 - y1_2) + (y1 - y2) * (x3_2 - x1_2 + y3_2 - y1_2)) / c; 41 | float y = ((x1 - x3) * (x2_2 - x1_2 + y2_2 - y1_2) + (x2 - x1) * (x3_2 - x1_2 + y3_2 - y1_2)) / c; 42 | float _x = (x1 - x); 43 | float _y = (y1 - y); 44 | 45 | float r = Mathf.Sqrt((_x * _x) + (_y * _y)); 46 | return new Circle2D(new Vector2(x, y), r); 47 | } 48 | 49 | public void DrawGizmos (float step = 0.02f) { 50 | 51 | var points = new List(); 52 | for(float t = 0f; t <= 1f; t += step) { 53 | var r = t * Mathf.PI * 2f; 54 | float x = Mathf.Cos(r) * radius; 55 | float y = Mathf.Sin(r) * radius; 56 | points.Add(center + new Vector2(x, y)); 57 | } 58 | 59 | for(int i = 0, n = points.Count; i < n; i++) { 60 | var p0 = points[i]; 61 | var p1 = points[(i + 1) % n]; 62 | Gizmos.DrawLine(p0, p1); 63 | } 64 | 65 | } 66 | 67 | } 68 | 69 | 70 | } 71 | 72 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/DemoMesh.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: DemoMesh 11 | m_Shader: {fileID: 4800000, guid: 5ea78bc862e0b4acc886e363496717b6, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 5 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 2000 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _Glossiness: 0.5 64 | - _Metallic: 0 65 | - _Mode: 0 66 | - _OcclusionStrength: 1 67 | - _Parallax: 0.02 68 | - _SrcBlend: 1 69 | - _UVSec: 0 70 | - _ZWrite: 1 71 | m_Colors: 72 | - _Color: {r: 1, g: 1, b: 1, a: 1} 73 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 74 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/CanvasLine.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: CanvasLine 11 | m_Shader: {fileID: 4800000, guid: 21e9e5ce29c1c4bf18deb2895e31bd70, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 5 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 2000 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _Glossiness: 0.5 64 | - _Metallic: 0 65 | - _Mode: 0 66 | - _OcclusionStrength: 1 67 | - _Parallax: 0.02 68 | - _SrcBlend: 1 69 | - _UVSec: 0 70 | - _ZWrite: 1 71 | m_Colors: 72 | - _Color: {r: 1, g: 1, b: 1, a: 1} 73 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 74 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Materials/DemoMeshLine.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: DemoMeshLine 11 | m_Shader: {fileID: 4800000, guid: 21e9e5ce29c1c4bf18deb2895e31bd70, type: 3} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 5 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: 2000 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _Glossiness: 0.5 64 | - _Metallic: 0 65 | - _Mode: 0 66 | - _OcclusionStrength: 1 67 | - _Parallax: 0.02 68 | - _SrcBlend: 1 69 | - _UVSec: 0 70 | - _ZWrite: 1 71 | m_Colors: 72 | - _Color: {r: 0, g: 0, b: 0, a: 1} 73 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 74 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/README.md: -------------------------------------------------------------------------------- 1 | unity-triangulation2D 2 | ===================== 3 | 4 | Delaunay Triangulation and Ruppert's Delaunay Refinement Algorithm in Unity. 5 | 6 | 7 | 8 | Input contour points for [planar straight-line graph](https://en.wikipedia.org/wiki/Planar_straight-line_graph) 9 | 10 | 11 | 12 | Delaunay Triangulation 13 | 14 | 15 | 16 | Mesh Refinement with minimum angle α(22.5) 17 | 18 | 19 | 20 | ## Usage 21 | 22 | ```cs 23 | // input points for a polygon2D contor 24 | List points = new List(); 25 | 26 | // Add Vector2 to points 27 | points.Add(new Vector2(-2.5f, -2.5f)); 28 | points.Add(new Vector2(2.5f, -2.5f)); 29 | points.Add(new Vector2(4.5f, 2.5f)); 30 | points.Add(new Vector2(0.5f, 4.5f)); 31 | points.Add(new Vector2(-3.5f, 2.5f)); 32 | 33 | // construct Polygon2D 34 | Polygon2D polygon = Polygon2D.Contour(points.ToArray()); 35 | 36 | // construct Triangulation2D with Polygon2D and threshold angle (18f ~ 27f recommended) 37 | Triangulation2D triangulation = new Triangulation2D(polygon, 22.5f); 38 | 39 | // build a mesh from triangles in a Triangulation2D instance 40 | Mesh mesh = triangulation.Build(); 41 | // GetComponent().sharedMesh = mesh; 42 | ``` 43 | 44 | ## Demo 45 | 46 | 47 | 48 | ## Sources 49 | 50 | - Jim Ruppert. A Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh Generation - http://www.cis.upenn.edu/~cis610/ruppert.pdf 51 | 52 | - Ruppert's algorithm - https://en.wikipedia.org/wiki/Ruppert%27s_algorithm 53 | 54 | - Ruppert's Delaunay Refinement Algorithm - https://www.cs.cmu.edu/~quake/tripaper/triangle3.html 55 | 56 | - Chapter 7.pdf - http://www.ti.inf.ethz.ch/ew/Lehre/CG13/lecture/Chapter%207.pdf 57 | 58 | -------------------------------------------------------------------------------- /Example/Decal.jpg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb8f0a9267a59405195e8ad8caeee87f 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /Screenshots/Example1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d60e721604444b2cacdcd6591dc0061 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /Screenshots/Example2.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1a75e68d4eb6e4fe88a6234a424589b5 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /Screenshots/Example3.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 300f8d62a11724e9481a398962bb6a88 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /Example/New Material.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: New Material 11 | m_Shader: {fileID: 10703, guid: 0000000000000000f000000000000000, type: 0} 12 | m_ShaderKeywords: 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 2800000, guid: bb8f0a9267a59405195e8ad8caeee87f, type: 3} 44 | m_Scale: {x: 4, y: 4} 45 | m_Offset: {x: 0, y: 2.21} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Screenshots/Example4.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 52f130d060688423c8e4155a1a589a7b 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: 1 35 | aniso: 1 36 | mipBias: 0 37 | wrapU: 0 38 | wrapV: 0 39 | wrapW: 0 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scripts/Demo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | #if UNITY_EDITOR 4 | using UnityEditor; 5 | #endif 6 | 7 | using System; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Collections; 11 | using System.Collections.Generic; 12 | 13 | using mattatz.Utils; 14 | 15 | namespace mattatz.Triangulation2DSystem.Example { 16 | 17 | public class Demo : MonoBehaviour { 18 | 19 | [SerializeField, Range(0, 30f)] float angle = 20f; 20 | [SerializeField, Range(0, 2f)] float threshold = 1.5f; 21 | [SerializeField] GameObject prefab; 22 | [SerializeField] Material lineMat; 23 | [SerializeField] bool debug; 24 | 25 | [SerializeField] List points; 26 | 27 | Camera cam; 28 | float depth = 0f; 29 | bool dragging; 30 | 31 | void Start () { 32 | cam = Camera.main; 33 | depth = Mathf.Abs(cam.transform.position.z - transform.position.z); 34 | 35 | if(debug) { 36 | // points = LocalStorage.LoadList("points.json"); 37 | Build(); 38 | } 39 | else 40 | { 41 | points.Clear(); 42 | } 43 | } 44 | 45 | void Update () { 46 | if(Input.GetMouseButtonDown(0)) { 47 | dragging = true; 48 | Clear(); 49 | } else if(Input.GetMouseButtonUp(0)) { 50 | // LocalStorage.SaveList(points, "points.json"); 51 | 52 | dragging = false; 53 | Build(); 54 | } 55 | 56 | if(dragging) { 57 | var screen = Input.mousePosition; 58 | screen.z = depth; 59 | var p = cam.ScreenToWorldPoint(screen); 60 | var p2D = new Vector2(p.x, p.y); 61 | if(points.Count <= 0 || Vector2.Distance(p2D, points.Last()) > threshold) { 62 | points.Add(p2D); 63 | } 64 | } 65 | } 66 | 67 | void Build () { 68 | points = Utils2D.Constrain(points, threshold); 69 | var polygon = Polygon2D.Contour(points.ToArray()); 70 | 71 | var vertices = polygon.Vertices; 72 | if(vertices.Count < 3) return; // error 73 | 74 | var triangulation = new Triangulation2D(polygon, angle); 75 | var go = Instantiate(prefab); 76 | go.transform.SetParent(transform, false); 77 | go.GetComponent().SetTriangulation(triangulation); 78 | 79 | Clear(); 80 | } 81 | 82 | void Clear () { 83 | points.Clear(); 84 | } 85 | 86 | void OnRenderObject () { 87 | if(points != null) { 88 | GL.PushMatrix(); 89 | GL.MultMatrix (transform.localToWorldMatrix); 90 | lineMat.SetColor("_Color", Color.white); 91 | lineMat.SetPass(0); 92 | GL.Begin(GL.LINES); 93 | for(int i = 0, n = points.Count - 1; i < n; i++) { 94 | GL.Vertex(points[i]); GL.Vertex(points[i + 1]); 95 | } 96 | GL.End(); 97 | GL.PopMatrix(); 98 | } 99 | } 100 | 101 | void OnDrawGizmos () { 102 | } 103 | 104 | } 105 | 106 | } 107 | 108 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Triangle2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Triangle2D { 11 | 12 | public Vertex2D a, b, c; 13 | public Segment2D s0, s1, s2; 14 | private Circle2D circum; 15 | 16 | public Triangle2D (Segment2D s0, Segment2D s1, Segment2D s2) { 17 | this.s0 = s0; 18 | this.s1 = s1; 19 | this.s2 = s2; 20 | this.a = s0.a; 21 | this.b = s0.b; 22 | this.c = (s2.b == this.a || s2.b == this.b) ? s2.a : s2.b; 23 | } 24 | 25 | public bool HasPoint (Vertex2D p) { 26 | return (a == p) || (b == p) || (c == p); 27 | } 28 | 29 | public bool HasCommonPoint (Triangle2D t) { 30 | return HasPoint(t.a) || HasPoint(t.b) || HasPoint(t.c); 31 | } 32 | 33 | public bool HasSegment (Segment2D s) { 34 | return (s0 == s) || (s1 == s) || (s2 == s); 35 | } 36 | 37 | public bool HasSegment (Vector2 a, Vector2 b) { 38 | return (s0.HasPoint(a) && s0.HasPoint(b)) || (s1.HasPoint(a) && s1.HasPoint(b)) || (s2.HasPoint(a) && s2.HasPoint(b)); 39 | } 40 | 41 | public Vertex2D ExcludePoint (Segment2D s) { 42 | if(!s.HasPoint(a)) return a; 43 | else if(!s.HasPoint(b)) return b; 44 | return c; 45 | } 46 | 47 | public Vertex2D ExcludePoint (Vector2 p0, Vector2 p1) { 48 | if(p0 != a.Coordinate && p1 != a.Coordinate) return a; 49 | else if(p0 != b.Coordinate && p1 != b.Coordinate) return b; 50 | return c; 51 | } 52 | 53 | public Segment2D[] ExcludeSegment (Segment2D s) { 54 | if(s0.Equals(s)) { 55 | return new Segment2D[] { s1, s2 }; 56 | } else if(s1.Equals(s)) { 57 | return new Segment2D[] { s0, s2 }; 58 | } 59 | return new Segment2D[] { s0, s1 }; 60 | } 61 | 62 | public Vector2 Circumcenter () { 63 | if(circum == null) { 64 | circum = Circle2D.GetCircumscribedCircle(this); 65 | } 66 | return circum.center; 67 | } 68 | 69 | public bool ContainsInExternalCircle (Vertex2D v) { 70 | if(circum == null) { 71 | circum = Circle2D.GetCircumscribedCircle(this); 72 | } 73 | return circum.Contains(v.Coordinate); 74 | } 75 | 76 | float Angle (Vector2 from, Vector2 to0, Vector2 to1) { 77 | var v0 = (to0 - from); 78 | var v1 = (to1 - from); 79 | 80 | // 0 ~ PI 81 | float acos = Mathf.Acos(Vector2.Dot(v0, v1) / Mathf.Sqrt(v0.sqrMagnitude * v1.sqrMagnitude)); 82 | return acos; 83 | } 84 | 85 | // angle must to RADIAN 86 | public bool Skinny (float angle, float threshold) { 87 | if(s0.Length() <= threshold && s1.Length() <= threshold && s2.Length() <= threshold) return false; 88 | 89 | if(Angle(a.Coordinate, b.Coordinate, c.Coordinate) < angle) return true; // angle bac 90 | else if(Angle(b.Coordinate, a.Coordinate, c.Coordinate) < angle) return true; // angle abc 91 | else if(Angle(c.Coordinate, a.Coordinate, b.Coordinate) < angle) return true; // angle acb 92 | return false; 93 | } 94 | 95 | public bool Equals (Triangle2D t) { 96 | return HasPoint(t.a) && HasPoint(t.b) && HasPoint(t.c); 97 | } 98 | 99 | public void DrawGizmos () { 100 | s0.DrawGizmos(); 101 | s1.DrawGizmos(); 102 | s2.DrawGizmos(); 103 | } 104 | 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Prefabs/DemoMesh.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &111580 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 496996} 12 | - component: {fileID: 3356526} 13 | - component: {fileID: 2397546} 14 | - component: {fileID: 5423564} 15 | - component: {fileID: 11429206} 16 | m_Layer: 0 17 | m_Name: DemoMesh 18 | m_TagString: Untagged 19 | m_Icon: {fileID: 0} 20 | m_NavMeshLayer: 0 21 | m_StaticEditorFlags: 0 22 | m_IsActive: 1 23 | --- !u!4 &496996 24 | Transform: 25 | m_ObjectHideFlags: 0 26 | m_CorrespondingSourceObject: {fileID: 0} 27 | m_PrefabInstance: {fileID: 0} 28 | m_PrefabAsset: {fileID: 0} 29 | m_GameObject: {fileID: 111580} 30 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 31 | m_LocalPosition: {x: 0, y: 0, z: 0} 32 | m_LocalScale: {x: 1, y: 1, z: 1} 33 | m_Children: [] 34 | m_Father: {fileID: 0} 35 | m_RootOrder: 0 36 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 37 | --- !u!33 &3356526 38 | MeshFilter: 39 | m_ObjectHideFlags: 0 40 | m_CorrespondingSourceObject: {fileID: 0} 41 | m_PrefabInstance: {fileID: 0} 42 | m_PrefabAsset: {fileID: 0} 43 | m_GameObject: {fileID: 111580} 44 | m_Mesh: {fileID: 0} 45 | --- !u!23 &2397546 46 | MeshRenderer: 47 | m_ObjectHideFlags: 0 48 | m_CorrespondingSourceObject: {fileID: 0} 49 | m_PrefabInstance: {fileID: 0} 50 | m_PrefabAsset: {fileID: 0} 51 | m_GameObject: {fileID: 111580} 52 | m_Enabled: 1 53 | m_CastShadows: 1 54 | m_ReceiveShadows: 1 55 | m_DynamicOccludee: 1 56 | m_MotionVectors: 1 57 | m_LightProbeUsage: 1 58 | m_ReflectionProbeUsage: 1 59 | m_RenderingLayerMask: 1 60 | m_RendererPriority: 0 61 | m_Materials: 62 | - {fileID: 2100000, guid: ad59dae05c2214026b6e4097e9fe27d2, type: 2} 63 | m_StaticBatchInfo: 64 | firstSubMesh: 0 65 | subMeshCount: 0 66 | m_StaticBatchRoot: {fileID: 0} 67 | m_ProbeAnchor: {fileID: 0} 68 | m_LightProbeVolumeOverride: {fileID: 0} 69 | m_ScaleInLightmap: 1 70 | m_PreserveUVs: 0 71 | m_IgnoreNormalsForChartDetection: 0 72 | m_ImportantGI: 0 73 | m_StitchLightmapSeams: 0 74 | m_SelectedEditorRenderState: 3 75 | m_MinimumChartSize: 4 76 | m_AutoUVMaxDistance: 0.5 77 | m_AutoUVMaxAngle: 89 78 | m_LightmapParameters: {fileID: 0} 79 | m_SortingLayerID: 0 80 | m_SortingLayer: 0 81 | m_SortingOrder: 0 82 | --- !u!54 &5423564 83 | Rigidbody: 84 | m_ObjectHideFlags: 0 85 | m_CorrespondingSourceObject: {fileID: 0} 86 | m_PrefabInstance: {fileID: 0} 87 | m_PrefabAsset: {fileID: 0} 88 | m_GameObject: {fileID: 111580} 89 | serializedVersion: 2 90 | m_Mass: 1 91 | m_Drag: 0 92 | m_AngularDrag: 0.05 93 | m_UseGravity: 0 94 | m_IsKinematic: 0 95 | m_Interpolate: 0 96 | m_Constraints: 0 97 | m_CollisionDetection: 0 98 | --- !u!114 &11429206 99 | MonoBehaviour: 100 | m_ObjectHideFlags: 0 101 | m_CorrespondingSourceObject: {fileID: 0} 102 | m_PrefabInstance: {fileID: 0} 103 | m_PrefabAsset: {fileID: 0} 104 | m_GameObject: {fileID: 111580} 105 | m_Enabled: 1 106 | m_EditorHideFlags: 0 107 | m_Script: {fileID: 11500000, guid: bcb5140256a2f492abf35ca80af1c53a, type: 3} 108 | m_Name: 109 | m_EditorClassIdentifier: 110 | lineMat: {fileID: 2100000, guid: f0eacebf3e8c64a399242fae6d8dcbc8, type: 2} 111 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Utils2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Utils2D { 11 | 12 | // constrain a distance between two points to "threshold" length 13 | public static List Constrain (IList points, float threshold = 1f) 14 | { 15 | if (threshold <= 0) return new List(points); 16 | List result = new List(); 17 | var n = points.Count; 18 | for(int i = 0, j = 1; i < n && j < n; j++) { 19 | var from = points[i]; 20 | var to = points[j]; 21 | if(Vector2.Distance(from, to) > threshold) { 22 | result.Add(from); 23 | i = j; 24 | } 25 | } 26 | 27 | var p0 = result.Last(); 28 | var p1 = result.First(); 29 | if(Vector2.Distance(p0, p1) > threshold) { 30 | result.Add((p0 + p1) * 0.5f); 31 | } 32 | 33 | return result; 34 | } 35 | 36 | // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect 37 | // check intersection segment (p0, p1) to segment (p2, p3) 38 | public static bool Intersect (Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) { 39 | var s1 = p1 - p0; 40 | var s2 = p3 - p2; 41 | var s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y); 42 | var t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y); 43 | return (s >= 0 && s <= 1 && t >= 0 && t <= 1); 44 | } 45 | 46 | // http://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon 47 | public static bool Contains (Vector2 p, List vertices) { 48 | var n = vertices.Count; 49 | bool c = false; 50 | for(int i = 0, j = n - 1; i < n; j = i++) { 51 | if(vertices[i].Coordinate == p) return true; 52 | if ( 53 | ((vertices[i].Coordinate.y > p.y) != (vertices[j].Coordinate.y > p.y)) && 54 | (p.x < (vertices[j].Coordinate.x - vertices[i].Coordinate.x) * (p.y - vertices[i].Coordinate.y) / (vertices[j].Coordinate.y - vertices[i].Coordinate.y) + vertices[i].Coordinate.x) 55 | ) { 56 | c = !c; 57 | } 58 | } 59 | // c == true means odd, c == false means even 60 | return c; 61 | } 62 | 63 | // check p is left side of segment (from, to) 64 | public static bool LeftSide (Vector2 from, Vector2 to, Vector2 p) { 65 | float cross = ((to.x - from.x) * (p.y - from.y) - (to.y - from.y) * (p.x - from.x)); 66 | return (cross > 0f); 67 | } 68 | 69 | public static bool CheckEqual (Vertex2D v0, Vertex2D v1) { 70 | return (v0.Coordinate == v1.Coordinate); 71 | } 72 | 73 | public static bool CheckEqual (Segment2D s0, Segment2D s1) { 74 | return 75 | (CheckEqual(s0.a, s1.a) && CheckEqual(s0.b, s1.b)) || 76 | (CheckEqual(s0.a, s1.b) && CheckEqual(s0.b, s1.a)); 77 | } 78 | 79 | public static bool CheckEqual (Triangle2D t0, Triangle2D t1) { 80 | // 0,1,2 == 0,1,2 81 | // 0,1,2 == 0,2,1 82 | // 0,1,2 == 1,0,2 83 | // 0,1,2 == 1,2,0 84 | // 0,1,2 == 2,0,1 85 | // 0,1,2 == 2,1,0 86 | return 87 | (CheckEqual(t0.s0, t1.s0) && CheckEqual(t0.s1, t1.s1) && CheckEqual(t0.s2, t1.s2)) || 88 | (CheckEqual(t0.s0, t1.s0) && CheckEqual(t0.s1, t1.s2) && CheckEqual(t0.s2, t1.s1)) || 89 | 90 | (CheckEqual(t0.s0, t1.s1) && CheckEqual(t0.s1, t1.s0) && CheckEqual(t0.s2, t1.s2)) || 91 | (CheckEqual(t0.s0, t1.s1) && CheckEqual(t0.s1, t1.s2) && CheckEqual(t0.s2, t1.s0)) || 92 | 93 | (CheckEqual(t0.s0, t1.s2) && CheckEqual(t0.s1, t1.s0) && CheckEqual(t0.s2, t1.s1)) || 94 | (CheckEqual(t0.s0, t1.s2) && CheckEqual(t0.s1, t1.s1) && CheckEqual(t0.s2, t1.s0)); 95 | } 96 | 97 | } 98 | 99 | } 100 | 101 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Shaders/SimplexNoise3D.cginc: -------------------------------------------------------------------------------- 1 | // 2 | // Noise Shader Library for Unity - https://github.com/keijiro/NoiseShader 3 | // 4 | // Original work (webgl-noise) Copyright (C) 2011 Ashima Arts. 5 | // Translation and modification was made by Keijiro Takahashi. 6 | // 7 | // This shader is based on the webgl-noise GLSL shader. For further details 8 | // of the original shader, please see the following description from the 9 | // original source code. 10 | // 11 | 12 | // 13 | // Description : Array and textureless GLSL 2D/3D/4D simplex 14 | // noise functions. 15 | // Author : Ian McEwan, Ashima Arts. 16 | // Maintainer : ijm 17 | // Lastmod : 20110822 (ijm) 18 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 19 | // Distributed under the MIT License. See LICENSE file. 20 | // https://github.com/ashima/webgl-noise 21 | // 22 | 23 | float3 mod289(float3 x) 24 | { 25 | return x - floor(x / 289.0) * 289.0; 26 | } 27 | 28 | float4 mod289(float4 x) 29 | { 30 | return x - floor(x / 289.0) * 289.0; 31 | } 32 | 33 | float4 permute(float4 x) 34 | { 35 | return mod289((x * 34.0 + 1.0) * x); 36 | } 37 | 38 | float4 taylorInvSqrt(float4 r) 39 | { 40 | return 1.79284291400159 - r * 0.85373472095314; 41 | } 42 | 43 | float snoise(float3 v) 44 | { 45 | const float2 C = float2(1.0 / 6.0, 1.0 / 3.0); 46 | 47 | // First corner 48 | float3 i = floor(v + dot(v, C.yyy)); 49 | float3 x0 = v - i + dot(i, C.xxx); 50 | 51 | // Other corners 52 | float3 g = step(x0.yzx, x0.xyz); 53 | float3 l = 1.0 - g; 54 | float3 i1 = min(g.xyz, l.zxy); 55 | float3 i2 = max(g.xyz, l.zxy); 56 | 57 | // x1 = x0 - i1 + 1.0 * C.xxx; 58 | // x2 = x0 - i2 + 2.0 * C.xxx; 59 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 60 | float3 x1 = x0 - i1 + C.xxx; 61 | float3 x2 = x0 - i2 + C.yyy; 62 | float3 x3 = x0 - 0.5; 63 | 64 | // Permutations 65 | i = mod289(i); // Avoid truncation effects in permutation 66 | float4 p = 67 | permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0)) 68 | + i.y + float4(0.0, i1.y, i2.y, 1.0)) 69 | + i.x + float4(0.0, i1.x, i2.x, 1.0)); 70 | 71 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 72 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 73 | float4 j = p - 49.0 * floor(p / 49.0); // mod(p,7*7) 74 | 75 | float4 x_ = floor(j / 7.0); 76 | float4 y_ = floor(j - 7.0 * x_); // mod(j,N) 77 | 78 | float4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0; 79 | float4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0; 80 | 81 | float4 h = 1.0 - abs(x) - abs(y); 82 | 83 | float4 b0 = float4(x.xy, y.xy); 84 | float4 b1 = float4(x.zw, y.zw); 85 | 86 | //float4 s0 = float4(lessThan(b0, 0.0)) * 2.0 - 1.0; 87 | //float4 s1 = float4(lessThan(b1, 0.0)) * 2.0 - 1.0; 88 | float4 s0 = floor(b0) * 2.0 + 1.0; 89 | float4 s1 = floor(b1) * 2.0 + 1.0; 90 | float4 sh = -step(h, 0.0); 91 | 92 | float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; 93 | float4 a1 = b1.xzyw + s1.xzyw * sh.zzww; 94 | 95 | float3 g0 = float3(a0.xy, h.x); 96 | float3 g1 = float3(a0.zw, h.y); 97 | float3 g2 = float3(a1.xy, h.z); 98 | float3 g3 = float3(a1.zw, h.w); 99 | 100 | // Normalise gradients 101 | float4 norm = taylorInvSqrt(float4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3))); 102 | g0 *= norm.x; 103 | g1 *= norm.y; 104 | g2 *= norm.z; 105 | g3 *= norm.w; 106 | 107 | // Mix final noise value 108 | float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); 109 | m = m * m; 110 | m = m * m; 111 | 112 | float4 px = float4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3)); 113 | return 42.0 * dot(m, px); 114 | } 115 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Polygon2D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | using System; 4 | using System.Linq; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace mattatz.Triangulation2DSystem { 9 | 10 | public class Polygon2D { 11 | 12 | public Vertex2D[] VertexArray { get { return vertices.ToArray(); } } 13 | public Segment2D[] SegmentArray { get { return segments.ToArray(); } } 14 | 15 | public List Vertices => vertices; 16 | public List Segments => segments; 17 | List vertices; 18 | List segments; 19 | 20 | /* 21 | * slow incremental approach 22 | * O(n * log(n)) 23 | */ 24 | public static Polygon2D ConvexHull (Vector2[] points) { 25 | var ordered = points.ToList().OrderBy(p => p.x).ToList(); 26 | 27 | var upper = new List(); 28 | upper.Add(ordered[0]); 29 | upper.Add(ordered[1]); 30 | for(int i = 2, n = ordered.Count; i < n; i++) { 31 | upper.Add(ordered[i]); 32 | int l = upper.Count; 33 | if(l > 2) { 34 | var p = upper[l - 3]; 35 | var r = upper[l - 2]; 36 | var q = upper[l - 1]; 37 | if(Utils2D.LeftSide(p, q, r)) { // r is left side of pq 38 | upper.RemoveAt(l - 2); 39 | } 40 | } 41 | } 42 | 43 | var lower = new List(); 44 | lower.Add(ordered[ordered.Count - 1]); 45 | lower.Add(ordered[ordered.Count - 2]); 46 | for(int i = ordered.Count - 3; i >= 0; i--) { 47 | lower.Add(ordered[i]); 48 | int l = lower.Count; 49 | if(l > 2) { 50 | var p = lower[l - 3]; 51 | var r = lower[l - 2]; 52 | var q = lower[l - 1]; 53 | if(Utils2D.LeftSide(p, q, r)) { // r is left side of pq 54 | lower.RemoveAt(l - 2); 55 | } 56 | } 57 | } 58 | 59 | lower.RemoveAt(lower.Count - 1); 60 | lower.RemoveAt(0); 61 | 62 | upper.AddRange (lower); 63 | 64 | return new Polygon2D(upper.ToArray()); 65 | } 66 | 67 | public static Polygon2D Contour (Vector2[] points) { 68 | var n = points.Length; 69 | var edges = new List(); 70 | for(int i = 0; i < n; i++) { 71 | edges.Add(new HalfEdge2D(points[i])); 72 | } 73 | for(int i = 0; i < n; i++) { 74 | var e = edges[i]; 75 | e.from = edges[(i == 0) ? (n - 1) : (i - 1)]; 76 | e.to = edges[(i + 1) % n]; 77 | } 78 | edges = Polygon2D.SplitEdges(edges); 79 | 80 | var result = new List(); 81 | 82 | HalfEdge2D start = edges[0]; 83 | result.Add(start.p); 84 | 85 | HalfEdge2D current = start; 86 | 87 | while(true) { 88 | HalfEdge2D from = current, to = current.to; 89 | HalfEdge2D from2 = to.to, to2 = from2.to; 90 | 91 | bool flag = false; 92 | 93 | while(from2 != start && to2 != from) { 94 | if(flag = Utils2D.Intersect(from.p, to.p, from2.p, to2.p)) { 95 | break; 96 | } 97 | from2 = to2; 98 | to2 = to2.to; 99 | } 100 | 101 | if(!flag) { 102 | result.Add(to.p); 103 | current = to; // step to next 104 | } else { 105 | result.Add(from2.p); 106 | 107 | // reconnect 108 | from.to = from2; 109 | from2.to = from; // invert this edge later 110 | 111 | to.from = to2; 112 | to.Invert(); 113 | to2.from = to; 114 | 115 | HalfEdge2D e = from2; 116 | while(e != to) { 117 | e.Invert(); 118 | e = e.to; 119 | } 120 | 121 | current = from2; 122 | } 123 | 124 | if(current == start) break; 125 | } 126 | 127 | result.RemoveAt(result.Count - 1); // remove last 128 | 129 | return new Polygon2D(result.ToArray()); 130 | } 131 | 132 | // Disable to intersect more than two edges 133 | static List SplitEdges (List edges) { 134 | HalfEdge2D start = edges[0]; 135 | HalfEdge2D cur = start; 136 | 137 | while(true) { 138 | HalfEdge2D from = cur, to = from.to; 139 | HalfEdge2D from2 = to.to, to2 = from2.to; 140 | 141 | int intersections = 0; 142 | 143 | while(to2 != from.from) { 144 | if(Utils2D.Intersect(from.p, to.p, from2.p, to2.p)) { 145 | intersections++; 146 | if(intersections >= 2) { 147 | break; 148 | } 149 | } 150 | // next 151 | from2 = from2.to; 152 | to2 = to2.to; 153 | } 154 | 155 | if(intersections >= 2) { 156 | edges.Add(cur.Split()); 157 | } else { 158 | // next 159 | cur = cur.to; 160 | if(cur == start) break; 161 | } 162 | } 163 | 164 | return edges; 165 | } 166 | 167 | // contour must be inversed clockwise order. 168 | public Polygon2D (Vector2[] contour) { 169 | vertices = contour.Select(p => new Vertex2D(p)).ToList(); 170 | segments = new List(); 171 | for(int i = 0, n = vertices.Count; i < n; i++) { 172 | var v0 = vertices[i]; 173 | var v1 = vertices[(i + 1) % n]; 174 | segments.Add(new Segment2D(v0, v1)); 175 | } 176 | } 177 | 178 | public bool Contains (Vector2 p) { 179 | return Utils2D.Contains(p, vertices); 180 | } 181 | 182 | public void DrawGizmos () { 183 | segments.ForEach(s => s.DrawGizmos()); 184 | } 185 | 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Demo/Scenes/Demo.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &4 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 10 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_AtlasSize: 1024 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 0 64 | m_CompAOExponentDirect: 0 65 | m_Padding: 2 66 | m_LightmapParameters: {fileID: 0} 67 | m_LightmapsBakeMode: 1 68 | m_TextureCompression: 1 69 | m_FinalGather: 0 70 | m_FinalGatherFiltering: 1 71 | m_FinalGatherRayCount: 1024 72 | m_ReflectionCompression: 2 73 | m_MixedBakeMode: 1 74 | m_BakeBackend: 0 75 | m_PVRSampling: 1 76 | m_PVRDirectSampleCount: 32 77 | m_PVRSampleCount: 500 78 | m_PVRBounces: 2 79 | m_PVRFilterTypeDirect: 0 80 | m_PVRFilterTypeIndirect: 0 81 | m_PVRFilterTypeAO: 0 82 | m_PVRFilteringMode: 0 83 | m_PVRCulling: 1 84 | m_PVRFilteringGaussRadiusDirect: 1 85 | m_PVRFilteringGaussRadiusIndirect: 5 86 | m_PVRFilteringGaussRadiusAO: 2 87 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 88 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 89 | m_PVRFilteringAtrousPositionSigmaAO: 1 90 | m_ShowResolutionOverlay: 1 91 | m_LightingDataAsset: {fileID: 0} 92 | m_UseShadowmask: 0 93 | --- !u!196 &5 94 | NavMeshSettings: 95 | serializedVersion: 2 96 | m_ObjectHideFlags: 0 97 | m_BuildSettings: 98 | serializedVersion: 2 99 | agentTypeID: 0 100 | agentRadius: 0.5 101 | agentHeight: 2 102 | agentSlope: 45 103 | agentClimb: 0.4 104 | ledgeDropHeight: 0 105 | maxJumpAcrossDistance: 0 106 | minRegionArea: 2 107 | manualCellSize: 0 108 | cellSize: 0.16666667 109 | manualTileSize: 0 110 | tileSize: 256 111 | accuratePlacement: 0 112 | debug: 113 | m_Flags: 0 114 | m_NavMeshData: {fileID: 0} 115 | --- !u!1 &814989680 116 | GameObject: 117 | m_ObjectHideFlags: 0 118 | m_CorrespondingSourceObject: {fileID: 0} 119 | m_PrefabInstance: {fileID: 0} 120 | m_PrefabAsset: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 814989685} 124 | - component: {fileID: 814989684} 125 | - component: {fileID: 814989683} 126 | - component: {fileID: 814989682} 127 | - component: {fileID: 814989681} 128 | m_Layer: 0 129 | m_Name: Main Camera 130 | m_TagString: MainCamera 131 | m_Icon: {fileID: 0} 132 | m_NavMeshLayer: 0 133 | m_StaticEditorFlags: 0 134 | m_IsActive: 1 135 | --- !u!81 &814989681 136 | AudioListener: 137 | m_ObjectHideFlags: 0 138 | m_CorrespondingSourceObject: {fileID: 0} 139 | m_PrefabInstance: {fileID: 0} 140 | m_PrefabAsset: {fileID: 0} 141 | m_GameObject: {fileID: 814989680} 142 | m_Enabled: 1 143 | --- !u!124 &814989682 144 | Behaviour: 145 | m_ObjectHideFlags: 0 146 | m_CorrespondingSourceObject: {fileID: 0} 147 | m_PrefabInstance: {fileID: 0} 148 | m_PrefabAsset: {fileID: 0} 149 | m_GameObject: {fileID: 814989680} 150 | m_Enabled: 1 151 | --- !u!92 &814989683 152 | Behaviour: 153 | m_ObjectHideFlags: 0 154 | m_CorrespondingSourceObject: {fileID: 0} 155 | m_PrefabInstance: {fileID: 0} 156 | m_PrefabAsset: {fileID: 0} 157 | m_GameObject: {fileID: 814989680} 158 | m_Enabled: 1 159 | --- !u!20 &814989684 160 | Camera: 161 | m_ObjectHideFlags: 0 162 | m_CorrespondingSourceObject: {fileID: 0} 163 | m_PrefabInstance: {fileID: 0} 164 | m_PrefabAsset: {fileID: 0} 165 | m_GameObject: {fileID: 814989680} 166 | m_Enabled: 1 167 | serializedVersion: 2 168 | m_ClearFlags: 2 169 | m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0.019607844} 170 | m_projectionMatrixMode: 1 171 | m_SensorSize: {x: 36, y: 24} 172 | m_LensShift: {x: 0, y: 0} 173 | m_GateFitMode: 2 174 | m_FocalLength: 50 175 | m_NormalizedViewPortRect: 176 | serializedVersion: 2 177 | x: 0 178 | y: 0 179 | width: 1 180 | height: 1 181 | near clip plane: 0.3 182 | far clip plane: 1000 183 | field of view: 70 184 | orthographic: 0 185 | orthographic size: 5 186 | m_Depth: -1 187 | m_CullingMask: 188 | serializedVersion: 2 189 | m_Bits: 4294967295 190 | m_RenderingPath: -1 191 | m_TargetTexture: {fileID: 0} 192 | m_TargetDisplay: 0 193 | m_TargetEye: 3 194 | m_HDR: 0 195 | m_AllowMSAA: 1 196 | m_AllowDynamicResolution: 0 197 | m_ForceIntoRT: 0 198 | m_OcclusionCulling: 1 199 | m_StereoConvergence: 10 200 | m_StereoSeparation: 0.022 201 | --- !u!4 &814989685 202 | Transform: 203 | m_ObjectHideFlags: 0 204 | m_CorrespondingSourceObject: {fileID: 0} 205 | m_PrefabInstance: {fileID: 0} 206 | m_PrefabAsset: {fileID: 0} 207 | m_GameObject: {fileID: 814989680} 208 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 209 | m_LocalPosition: {x: 0, y: 0, z: -20} 210 | m_LocalScale: {x: 1, y: 1, z: 1} 211 | m_Children: [] 212 | m_Father: {fileID: 0} 213 | m_RootOrder: 0 214 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 215 | --- !u!1 &1941270117 216 | GameObject: 217 | m_ObjectHideFlags: 0 218 | m_CorrespondingSourceObject: {fileID: 0} 219 | m_PrefabInstance: {fileID: 0} 220 | m_PrefabAsset: {fileID: 0} 221 | serializedVersion: 6 222 | m_Component: 223 | - component: {fileID: 1941270118} 224 | - component: {fileID: 1941270119} 225 | m_Layer: 0 226 | m_Name: Demo 227 | m_TagString: Untagged 228 | m_Icon: {fileID: 0} 229 | m_NavMeshLayer: 0 230 | m_StaticEditorFlags: 0 231 | m_IsActive: 1 232 | --- !u!4 &1941270118 233 | Transform: 234 | m_ObjectHideFlags: 0 235 | m_CorrespondingSourceObject: {fileID: 0} 236 | m_PrefabInstance: {fileID: 0} 237 | m_PrefabAsset: {fileID: 0} 238 | m_GameObject: {fileID: 1941270117} 239 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 240 | m_LocalPosition: {x: 0, y: 0, z: 0} 241 | m_LocalScale: {x: 1, y: 1, z: 1} 242 | m_Children: [] 243 | m_Father: {fileID: 0} 244 | m_RootOrder: 1 245 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 246 | --- !u!114 &1941270119 247 | MonoBehaviour: 248 | m_ObjectHideFlags: 0 249 | m_CorrespondingSourceObject: {fileID: 0} 250 | m_PrefabInstance: {fileID: 0} 251 | m_PrefabAsset: {fileID: 0} 252 | m_GameObject: {fileID: 1941270117} 253 | m_Enabled: 1 254 | m_EditorHideFlags: 0 255 | m_Script: {fileID: 11500000, guid: 77e8e35d5f324406abb67b63ec25336b, type: 3} 256 | m_Name: 257 | m_EditorClassIdentifier: 258 | angle: 30 259 | threshold: 0.073 260 | prefab: {fileID: 111580, guid: 01293f85e33724cffb1f6673f3588572, type: 3} 261 | lineMat: {fileID: 2100000, guid: 3cdb56c432dc643c99684f1e7daff9b8, type: 2} 262 | debug: 1 263 | points: 264 | - {x: -0.5, y: -0.5} 265 | - {x: -0.5, y: 0.5} 266 | - {x: 0.5, y: 0.5} 267 | - {x: 0.5, y: -0.5} 268 | -------------------------------------------------------------------------------- /Scripts/Triangulation2D/Scripts/Triangulation2D.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mattatz / http://mattatz.github.io 3 | * 4 | * Ruppert's Delaunay Refinement Algorithm 5 | * Jim Ruppert. A Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh Generation / http://www.cis.upenn.edu/~cis610/ruppert.pdf 6 | * The Quake Group at Carnegie Mellon University / https://www.cs.cmu.edu/~quake/tripaper/triangle3.html 7 | * Wikipedia / https://en.wikipedia.org/wiki/Ruppert%27s_algorithm 8 | * ETH zurich CG13 Chapter 7 / http://www.ti.inf.ethz.ch/ew/Lehre/CG13/lecture/Chapter%207.pdf 9 | */ 10 | 11 | using UnityEngine; 12 | 13 | using System; 14 | using System.Linq; 15 | using System.Collections; 16 | using System.Collections.Generic; 17 | 18 | namespace mattatz.Triangulation2DSystem { 19 | 20 | public class Triangulation2D { 21 | 22 | const float kAngleMin = 0, kAngleMax = 30f; 23 | 24 | public Triangle2D[] Triangle2Ds { get { return T.ToArray(); } } 25 | 26 | public int[] Triangles 27 | { 28 | get 29 | { 30 | var triangles = new int[T.Count * 3]; 31 | for(int i = 0, n = T.Count; i < n; i++) { 32 | var t = T[i]; 33 | var i3 = i * 3; 34 | 35 | int a = P.IndexOf(t.a), b = P.IndexOf(t.b), c = P.IndexOf(t.c); 36 | if(Utils2D.LeftSide(t.a.Coordinate, t.b.Coordinate, t.c.Coordinate)) { 37 | triangles[i3] = a; 38 | triangles[i3 + 1] = c; 39 | triangles[i3 + 2] = b; 40 | } else { 41 | triangles[i3] = a; 42 | triangles[i3 + 1] = b; 43 | triangles[i3 + 2] = c; 44 | } 45 | } 46 | 47 | return triangles; 48 | } 49 | } 50 | 51 | List V; // vertices in PSLG 52 | List S; // segments in PSLG 53 | 54 | List P = new List(); // vertices in DT 55 | List E = new List(); // segments in DT 56 | 57 | Polygon2D PSLG; 58 | List T = new List(); 59 | 60 | public Triangulation2D (Polygon2D polygon, float angle = 20f, float threshold = 0.1f) { 61 | angle = Mathf.Clamp(angle, kAngleMin, kAngleMax) * Mathf.Deg2Rad; 62 | 63 | PSLG = polygon; 64 | V = new List(PSLG.Vertices); 65 | S = new List(PSLG.Segments); 66 | Triangulate (V.Select(v => v.Coordinate).ToArray(), angle, threshold); 67 | } 68 | 69 | public Mesh Build () { 70 | var mesh = new Mesh(); 71 | 72 | var vertices = P.Select(p => { 73 | var xy = p.Coordinate; 74 | var v = new Vector3(xy.x, xy.y, 0f); 75 | return v; 76 | }).ToArray(); 77 | 78 | 79 | mesh.vertices = vertices; 80 | mesh.SetTriangles(Triangles, 0); 81 | mesh.RecalculateNormals(); 82 | 83 | return mesh; 84 | } 85 | 86 | int FindVertex (Vector2 p, List Vertices) { 87 | return Vertices.FindIndex (v => v.Coordinate == p); 88 | } 89 | 90 | int FindSegment (Vertex2D a, Vertex2D b, List Segments) { 91 | return Segments.FindIndex (s => (s.a == a && s.b == b) || (s.a == b && s.b == a)); 92 | } 93 | 94 | Vertex2D CheckAndAddVertex (Vector2 coord) { 95 | var idx = FindVertex(coord, P); 96 | if(idx < 0) { 97 | var v = new Vertex2D(coord); 98 | P.Add(v); 99 | return v; 100 | } 101 | return P[idx]; 102 | } 103 | 104 | Segment2D CheckAndAddSegment (Vertex2D a, Vertex2D b) { 105 | var idx = FindSegment(a, b, E); 106 | Segment2D s; 107 | if(idx < 0) { 108 | s = new Segment2D(a, b); 109 | E.Add(s); 110 | } else { 111 | s = E[idx]; 112 | } 113 | s.Increment(); 114 | return s; 115 | } 116 | 117 | Triangle2D AddTriangle (Vertex2D a, Vertex2D b, Vertex2D c) { 118 | var s0 = CheckAndAddSegment(a, b); 119 | var s1 = CheckAndAddSegment(b, c); 120 | var s2 = CheckAndAddSegment(c, a); 121 | var t = new Triangle2D(s0, s1, s2); 122 | T.Add(t); 123 | return t; 124 | } 125 | 126 | void RemoveTriangle (Triangle2D t) { 127 | T.Remove(t); 128 | if(t.s0.Decrement() <= 0) RemoveSegment (t.s0); 129 | if(t.s1.Decrement() <= 0) RemoveSegment (t.s1); 130 | if(t.s2.Decrement() <= 0) RemoveSegment (t.s2); 131 | } 132 | 133 | void RemoveSegment (Segment2D s) { 134 | E.Remove(s); 135 | if(s.a.ReferenceCount <= 0) P.Remove(s.a); 136 | if(s.b.ReferenceCount <= 0) P.Remove(s.b); 137 | } 138 | 139 | void Bound (Vector2[] points, out Vector2 min, out Vector2 max) { 140 | min = Vector2.one * float.MaxValue; 141 | max = Vector2.one * float.MinValue; 142 | for(int i = 0, n = points.Length; i < n; i++) { 143 | var p = points[i]; 144 | min.x = Mathf.Min (min.x, p.x); 145 | min.y = Mathf.Min (min.y, p.y); 146 | max.x = Mathf.Max (max.x, p.x); 147 | max.y = Mathf.Max (max.y, p.y); 148 | } 149 | } 150 | 151 | public Triangle2D AddExternalTriangle (Vector2 min, Vector2 max) { 152 | var center = (max + min) * 0.5f; 153 | var diagonal = (max - min).magnitude; 154 | var dh = diagonal * 0.5f; 155 | var rdh = Mathf.Sqrt(3f) * dh; 156 | return AddTriangle( 157 | CheckAndAddVertex(center + new Vector2(-rdh, -dh) * 3f), 158 | CheckAndAddVertex(center + new Vector2(rdh, -dh) * 3f), 159 | CheckAndAddVertex(center + new Vector2(0f, diagonal) * 3f) 160 | ); 161 | } 162 | 163 | void Triangulate (Vector2[] points, float angle, float threshold) { 164 | Vector2 min, max; 165 | Bound(points, out min, out max); 166 | 167 | AddExternalTriangle(min, max); 168 | 169 | for(int i = 0, n = points.Length; i < n; i++) { 170 | var v = points[i]; 171 | UpdateTriangulation (v); 172 | } 173 | if(Mathf.Abs(angle) > 1e-4) 174 | Refine (angle, threshold); 175 | RemoveExternalPSLG (); 176 | } 177 | 178 | void RemoveCommonTriangles (Triangle2D target) { 179 | for(int i = 0, n = T.Count; i < n; i++) { 180 | var t = T[i]; 181 | if(t.HasCommonPoint(target)) { 182 | RemoveTriangle (t); 183 | i--; 184 | n--; 185 | } 186 | } 187 | } 188 | 189 | void RemoveExternalPSLG () { 190 | for(int i = 0, n = T.Count; i < n; i++) { 191 | var t = T[i]; 192 | if(ExternalPSLG(t) || HasOuterSegments(t)) { 193 | // if(ExternalPSLG(t)) { 194 | RemoveTriangle (t); 195 | i--; 196 | n--; 197 | } 198 | } 199 | } 200 | 201 | bool ContainsSegments (Segment2D s, List segments) { 202 | return segments.FindIndex (s2 => 203 | (s2.a.Coordinate == s.a.Coordinate && s2.b.Coordinate == s.b.Coordinate) || 204 | (s2.a.Coordinate == s.b.Coordinate && s2.b.Coordinate == s.a.Coordinate) 205 | ) >= 0; 206 | } 207 | 208 | bool HasOuterSegments (Triangle2D t) { 209 | if(!ContainsSegments(t.s0, S)) { 210 | return ExternalPSLG(t.s0); 211 | } 212 | if(!ContainsSegments(t.s1, S)) { 213 | return ExternalPSLG(t.s1); 214 | } 215 | if(!ContainsSegments(t.s2, S)) { 216 | return ExternalPSLG(t.s2); 217 | } 218 | return false; 219 | } 220 | 221 | void UpdateTriangulation (Vector2 p) { 222 | var tmpT = new List(); 223 | var tmpS = new List(); 224 | 225 | var v = CheckAndAddVertex(p); 226 | tmpT = T.FindAll(t => t.ContainsInExternalCircle(v)); 227 | tmpT.ForEach(t => { 228 | tmpS.Add(t.s0); 229 | tmpS.Add(t.s1); 230 | tmpS.Add(t.s2); 231 | 232 | AddTriangle(t.a, t.b, v); 233 | AddTriangle(t.b, t.c, v); 234 | AddTriangle(t.c, t.a, v); 235 | RemoveTriangle (t); 236 | }); 237 | 238 | while(tmpS.Count != 0) { 239 | var s = tmpS.Last(); 240 | tmpS.RemoveAt(tmpS.Count - 1); 241 | 242 | var commonT = T.FindAll(t => t.HasSegment(s)); 243 | if(commonT.Count <= 1) continue; 244 | 245 | var abc = commonT[0]; 246 | var abd = commonT[1]; 247 | 248 | if(abc.Equals(abd)) { 249 | RemoveTriangle (abc); 250 | RemoveTriangle (abd); 251 | continue; 252 | } 253 | 254 | var a = s.a; 255 | var b = s.b; 256 | var c = abc.ExcludePoint(s); 257 | var d = abd.ExcludePoint(s); 258 | 259 | var ec = Circle2D.GetCircumscribedCircle(abc); 260 | if(ec.Contains(d.Coordinate)) { 261 | RemoveTriangle (abc); 262 | RemoveTriangle (abd); 263 | 264 | AddTriangle(a, c, d); // add acd 265 | AddTriangle(b, c, d); // add bcd 266 | 267 | var segments0 = abc.ExcludeSegment(s); 268 | tmpS.Add(segments0[0]); 269 | tmpS.Add(segments0[1]); 270 | 271 | var segments1 = abd.ExcludeSegment(s); 272 | tmpS.Add(segments1[0]); 273 | tmpS.Add(segments1[1]); 274 | } 275 | } 276 | 277 | } 278 | 279 | bool FindAndSplit (float threshold) { 280 | for(int i = 0, n = S.Count; i < n; i++) { 281 | var s = S[i]; 282 | if(s.Length() < threshold) continue; 283 | 284 | for(int j = 0, m = P.Count; j < m; j++) { 285 | if(s.EncroachedUpon(P[j].Coordinate)) { 286 | SplitSegment(s); 287 | return true; 288 | } 289 | } 290 | } 291 | return false; 292 | } 293 | 294 | bool ExternalPSLG (Vector2 p) { 295 | return !Utils2D.Contains(p, V); 296 | } 297 | 298 | bool ExternalPSLG (Segment2D s) { 299 | return ExternalPSLG(s.Midpoint()); 300 | } 301 | 302 | bool ExternalPSLG (Triangle2D t) { 303 | // return ExternalPSLG(t.s0) && ExternalPSLG(t.s1) && ExternalPSLG(t.s2); 304 | return 305 | ExternalPSLG(t.a.Coordinate) || 306 | ExternalPSLG(t.b.Coordinate) || 307 | ExternalPSLG(t.c.Coordinate) 308 | ; 309 | } 310 | 311 | void Refine (float angle, float threshold) { 312 | while(T.Any(t => !ExternalPSLG(t) && t.Skinny(angle, threshold))) { 313 | RefineSubRoutine(angle, threshold); 314 | } 315 | } 316 | 317 | void RefineSubRoutine (float angle, float threshold) { 318 | 319 | while(true) { 320 | if(!FindAndSplit(threshold)) break; 321 | } 322 | 323 | var skinny = T.Find (t => !ExternalPSLG(t) && t.Skinny(angle, threshold)); 324 | var p = skinny.Circumcenter(); 325 | 326 | var segments = S.FindAll(s => s.EncroachedUpon(p)); 327 | if(segments.Count > 0) { 328 | segments.ForEach(s => SplitSegment(s)); 329 | } else { 330 | SplitTriangle(skinny); 331 | } 332 | } 333 | 334 | void SplitTriangle (Triangle2D t) { 335 | var c = t.Circumcenter(); 336 | UpdateTriangulation(c); 337 | } 338 | 339 | void SplitSegment (Segment2D s) { 340 | Vertex2D a = s.a, b = s.b; 341 | var mv = new Vertex2D(s.Midpoint()); 342 | 343 | // add mv to V 344 | // the index is between a and b. 345 | var idxA = V.IndexOf(a); 346 | var idxB = V.IndexOf(b); 347 | if(Mathf.Abs(idxA - idxB) == 1) { 348 | var idx = (idxA > idxB) ? idxA : idxB; 349 | V.Insert(idx, mv); 350 | } else { 351 | V.Add(mv); 352 | } 353 | 354 | UpdateTriangulation(mv.Coordinate); 355 | 356 | // Add two halves to S 357 | var sidx = S.IndexOf(s); 358 | S.RemoveAt(sidx); 359 | 360 | S.Add(new Segment2D(s.a, mv)); 361 | S.Add(new Segment2D(mv, s.b)); 362 | } 363 | 364 | bool CheckUnique () { 365 | var flag = false; 366 | 367 | for(int i = 0, n = P.Count; i < n; i++) { 368 | var v0 = P[i]; 369 | for(int j = i + 1; j < n; j++) { 370 | var v1 = P[j]; 371 | if(Utils2D.CheckEqual(v0, v1)) { 372 | Debug.LogWarning("vertex " + i + " equals " + j); 373 | flag = true; 374 | } 375 | } 376 | } 377 | 378 | for(int i = 0, n = E.Count; i < n; i++) { 379 | var s0 = E[i]; 380 | for(int j = i + 1; j < n; j++) { 381 | var s1 = E[j]; 382 | if(Utils2D.CheckEqual(s0, s1)) { 383 | Debug.LogWarning("segment " + i + " equals " + j); 384 | flag = true; 385 | } 386 | } 387 | } 388 | 389 | for(int i = 0, n = T.Count; i < n; i++) { 390 | var t0 = T[i]; 391 | for(int j = i + 1; j < n; j++) { 392 | var t1 = T[j]; 393 | if(Utils2D.CheckEqual(t0, t1)) { 394 | Debug.LogWarning("triangle " + i + " equals " + j); 395 | flag = true; 396 | } 397 | } 398 | } 399 | 400 | for(int i = 0, n = T.Count; i < n; i++) { 401 | var t = T[i]; 402 | if(Utils2D.CheckEqual(t.s0, t.s1) || Utils2D.CheckEqual(t.s0, t.s2) || Utils2D.CheckEqual(t.s1, t.s2)) { 403 | Debug.LogWarning("triangle " + i + " has duplicated segments"); 404 | flag = true; 405 | } 406 | } 407 | 408 | return flag; 409 | } 410 | 411 | public void DrawGizmos () { 412 | T.ForEach(t => t.DrawGizmos()); 413 | } 414 | 415 | } 416 | 417 | } 418 | -------------------------------------------------------------------------------- /Scripts/MeshGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | //using CustomizationInspector.Runtime; 4 | using mattatz.Triangulation2DSystem; 5 | using UnityEngine; 6 | 7 | [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] 8 | [ExecuteInEditMode] 9 | public class MeshGenerator : MonoBehaviour 10 | { 11 | [Serializable] 12 | public class PointInfo 13 | { 14 | public Vector3 Point; 15 | //不需要外部赋值 16 | public Vector3 TangentForward;//切面前方方向向量 17 | public Vector3 TangentUp;//切面上方方向向量 18 | public float Length;//距离起点的路径长度 19 | 20 | public PointInfo() { } 21 | 22 | public PointInfo(Vector3 point) 23 | { 24 | Point = point; 25 | TangentForward = Vector3.forward; 26 | TangentUp = Vector3.up; 27 | Length = 0; 28 | } 29 | 30 | public PointInfo(Vector3 point, float length) 31 | { 32 | Point = point; 33 | TangentForward = Vector3.forward; 34 | TangentUp = Vector3.up; 35 | Length = length; 36 | } 37 | } 38 | [Tooltip("横截面shape的旋转值")] 39 | [SerializeField] private float mRotateAngle; 40 | 41 | [Tooltip("最小锐角的阈值")] 42 | [SerializeField] private float mAngleThreshold = 10; 43 | 44 | [Tooltip("横截面的缩放")] 45 | [SerializeField] private Vector2 mScale = Vector2.one; 46 | 47 | [Tooltip("uv的缩放")] 48 | [SerializeField] private Vector2 mUVScale = Vector2.one; 49 | 50 | [Tooltip("是否自定义横截面shape,为false的话横截面为圆")] 51 | [SerializeField] private bool mCustomShapeVertices; 52 | 53 | [Tooltip("圆的半径")] 54 | // [HideIf(nameof(mCustomShapeVertices))] 55 | [SerializeField] private float mRadius = 0.5f; 56 | 57 | [Tooltip("横截面的顶点数")] 58 | // [HideIf(nameof(mCustomShapeVertices))] 59 | [SerializeField] private int mShapeVerticesLength = 4; 60 | 61 | [Tooltip("横截面顶点(顺时针)")] 62 | // [InfoBox(nameof(mCustomShapeVertices)+"为true时才编辑!")] 63 | [SerializeField] private Vector2[] mShapeVertices; 64 | 65 | [Header("横截面uv")] 66 | [Tooltip("是否自定义横截面uv,为false的话自动平铺计算")] 67 | [SerializeField] private bool mCustomShapeUVs; 68 | 69 | [Tooltip("横截面uv(顺时针),uv数量应该与mShapeVerticesLength相同")] 70 | // [InfoBox(nameof(mCustomShapeUVs)+"为true时才编辑!")] 71 | [SerializeField] private Vector2[] mShapeUVs; 72 | 73 | [Header("横截面边缘uv")] 74 | [Tooltip("是否自定义横截面边缘uv,为false的话自动平铺计算")] 75 | [SerializeField] private bool mCustomShapeEdgeUVs; 76 | 77 | [Tooltip("横截面顶点边缘的uv(顺时针),uv数量应该与mRealShapeVerticesLength相同")] 78 | // [InfoBox(nameof(mCustomShapeEdgeUVs)+"为true时才编辑!")] 79 | [SerializeField] private Vector2[] mShapeEdgeUVs; 80 | 81 | [Header("Debug edit")] 82 | [Tooltip("路径关键点")] 83 | public List PointInfos = new List();//所有关键点 84 | 85 | private Vector2[] mRealShapeVertices;//拉伸旋转之后真实的shape 86 | private Quaternion mRotation;//横截面shape的旋转值 87 | private List mVertices = new List();//所有顶点 88 | private List mUVs = new List();//所有uv 89 | private List mNormals = new List();//所有法线 90 | private List mTriangles = new List();//所有三角面 91 | private int[] mShapeTriangle;//横截面shape的三角面 92 | private MeshFilter m_MeshFilter; 93 | private Mesh mMmesh; 94 | private int mRealShapeVerticesLength;//真实的横截面顶点数。因为有一个uv缝,需要多复制一个顶点 95 | private float mUVFactor;//一米对应多少uv 96 | private Vector4 mShapeUVMinMax = Vector4.zero;//xMin,xMax,yMin,yMax 97 | 98 | public float PathLength => PointInfos.Count > 0 ? PointInfos[PointInfos.Count - 1].Length : 0; 99 | 100 | 101 | private void Awake() 102 | { 103 | PointInfos.Clear(); 104 | mMmesh = new Mesh {name = "GeneratedMesh"}; 105 | m_MeshFilter = GetComponent(); 106 | m_MeshFilter.sharedMesh = mMmesh; 107 | 108 | Clear(); 109 | InitData(); 110 | } 111 | 112 | [ContextMenu("InitData")] 113 | // [Button] 114 | public void InitData() 115 | { 116 | mRotation = Quaternion.Euler(0, 0, mRotateAngle); 117 | if (!mCustomShapeVertices) 118 | { 119 | mRealShapeVerticesLength = mShapeVerticesLength + 1; 120 | mShapeVertices = new Vector2[mShapeVerticesLength]; 121 | mRealShapeVertices = new Vector2[mShapeVerticesLength]; 122 | float degreeStep = 2 * Mathf.PI / mShapeVerticesLength; 123 | float degree = -Mathf.PI; 124 | 125 | for (int i = 0; i < mShapeVerticesLength; i++, degree -= degreeStep) 126 | { 127 | mShapeVertices[i] = new Vector2(mRadius * Mathf.Cos(degree), mRadius * Mathf.Sin(degree)); 128 | mRealShapeVertices[i] = mRotation * Vector2.Scale(mShapeVertices[i], mScale); 129 | } 130 | //三角化横截面 131 | int count = mShapeVerticesLength - 2; 132 | mShapeTriangle = new int[3 * count]; 133 | for (int i = 0; i < count; i++) 134 | { 135 | mShapeTriangle[i * 3] = 0; 136 | mShapeTriangle[i * 3 + 1] = i + 1; 137 | mShapeTriangle[i * 3 + 2] = i + 2; 138 | } 139 | } 140 | else 141 | { 142 | mShapeVerticesLength = mShapeVertices.Length; 143 | mRealShapeVerticesLength = mShapeVerticesLength + 1; 144 | mRealShapeVertices = new Vector2[mShapeVerticesLength]; 145 | for (int i = 0; i < mShapeVerticesLength; i++) 146 | mRealShapeVertices[i] = mRotation * Vector2.Scale(mShapeVertices[i], mScale); 147 | //三角化自定义的横截面 148 | var polygon = Polygon2D.Contour(mRealShapeVertices); 149 | var triangulation = new Triangulation2D(polygon, 0); 150 | mShapeTriangle = triangulation.Triangles; 151 | } 152 | 153 | float shapeCircumference = 0;//横截面的周长 154 | for (int i = 0; i < mShapeVerticesLength; i++) 155 | shapeCircumference += Vector3.Distance(mRealShapeVertices[i], mRealShapeVertices[(i + 1) % mShapeVerticesLength]); 156 | mUVFactor = 1 / shapeCircumference; 157 | 158 | //计算边缘uv 159 | if (!mCustomShapeEdgeUVs) 160 | { 161 | mShapeEdgeUVs = new Vector2[mRealShapeVerticesLength]; 162 | float uvX = 0; 163 | mShapeEdgeUVs[0] = Vector2.zero; 164 | for (int i = 0; i < mShapeVerticesLength; i++) 165 | { 166 | uvX += Vector3.Distance(mRealShapeVertices[(i + 1) % mShapeVerticesLength], mRealShapeVertices[i]) / shapeCircumference; 167 | mShapeEdgeUVs[i + 1] = new Vector2(uvX, 0); 168 | } 169 | } 170 | 171 | //计算底面uv 172 | if (!mCustomShapeUVs) 173 | { 174 | mShapeUVs = new Vector2[mShapeVerticesLength]; 175 | Vector2 factor = new Vector2(mUVFactor, mUVFactor); 176 | for (int i = 0; i < mShapeVerticesLength; i++) 177 | mShapeUVs[i] = Vector2.Scale(mRealShapeVertices[i], factor); 178 | mShapeUVMinMax = new Vector4(mShapeUVs[0].x, mShapeUVs[0].x, mShapeUVs[0].y, mShapeUVs[0].y); 179 | for (int i = 0; i < mShapeVerticesLength; i++) 180 | { 181 | if (mShapeUVs[i].x < mShapeUVMinMax.x)//xMin 182 | mShapeUVMinMax.x = mShapeUVs[i].x; 183 | else if(mShapeUVs[i].x > mShapeUVMinMax.x)//xMax 184 | mShapeUVMinMax.y = mShapeUVs[i].x; 185 | 186 | if (mShapeUVs[i].y < mShapeUVMinMax.z)//yMin 187 | mShapeUVMinMax.z = mShapeUVs[i].y; 188 | else if(mShapeUVs[i].y > mShapeUVMinMax.w)//yMax 189 | mShapeUVMinMax.w = mShapeUVs[i].y; 190 | } 191 | } 192 | } 193 | 194 | public void Add(Vector3 point, bool refresh = true) 195 | { 196 | bool addExtra = AddPoint(point); 197 | if (PointInfos.Count < 2) return; 198 | 199 | if (PointInfos.Count > 2) 200 | { 201 | //去除最后一圈顶点 202 | mVertices.RemoveRange(mVertices.Count - (mRealShapeVerticesLength + mShapeVerticesLength), mRealShapeVerticesLength + mShapeVerticesLength); 203 | //最后一圈的三角面 204 | mTriangles.RemoveRange(mTriangles.Count - (mShapeVerticesLength - 2) * 3, (mShapeVerticesLength - 2) * 3); 205 | mUVs.RemoveRange(mUVs.Count - (mRealShapeVerticesLength + mShapeVerticesLength), mRealShapeVerticesLength + mShapeVerticesLength); 206 | } 207 | 208 | if (addExtra) 209 | //计算最后三个点 210 | Generate(PointInfos.Count - 3); 211 | //计算最后两个点 212 | Generate(PointInfos.Count - 2); 213 | Generate(PointInfos.Count - 1); 214 | 215 | if (refresh) 216 | RefreshMesh(); 217 | } 218 | 219 | public bool AddPoint(Vector3 point) 220 | { 221 | bool addExtra = false; 222 | if (PointInfos.Count > 1) 223 | { 224 | var lastPointInfo = PointInfos[PointInfos.Count - 1]; 225 | Vector3 v1 = point - lastPointInfo.Point; 226 | Vector3 v2 = PointInfos[PointInfos.Count - 2].Point - lastPointInfo.Point; 227 | float angle = Vector3.Angle(v1, v2); 228 | //拐角太锐,增加一个拐点 229 | if (angle <= mAngleThreshold) 230 | { 231 | addExtra = true; 232 | //往最新点的方向靠 233 | Vector3 moveDir = Vector3.Cross(v1 + v2, Vector3.Cross(v1, v2)).normalized; 234 | Vector3 p = lastPointInfo.Point + moveDir * (Vector3.Dot(moveDir, v2) * Mathf.Sin(Mathf.Deg2Rad * angle)); 235 | AddPointInternal(p); 236 | } 237 | } 238 | AddPointInternal(point); 239 | return addExtra; 240 | } 241 | 242 | private void AddPointInternal(Vector3 point) 243 | { 244 | //添加的时候就进行计算,避免还没有Generate的时候访问长度出错 245 | float length = 0; 246 | if (PointInfos.Count > 0) 247 | { 248 | var lastPointInfo = PointInfos[PointInfos.Count - 1]; 249 | length = lastPointInfo.Length + Vector3.Distance(lastPointInfo.Point, point); 250 | } 251 | PointInfos.Add(new PointInfo(point, length)); 252 | } 253 | 254 | public void RefreshMesh() 255 | { 256 | mMmesh.SetVertices(mVertices); 257 | mMmesh.SetTriangles(mTriangles, 0); 258 | mMmesh.SetUVs(0, mUVs); 259 | //自动平滑法线 260 | mMmesh.RecalculateNormals(); 261 | //uv分界处有两个顶点,自动平滑的法线会出现两个方向。手动合成为一个方向 262 | mMmesh.GetNormals(mNormals); 263 | for (int index = mShapeVerticesLength, count = mNormals.Count - mShapeVerticesLength; index < count; index += mRealShapeVerticesLength) 264 | { 265 | var normal = mNormals[index] + mNormals[index + mShapeVerticesLength]; 266 | normal.Normalize(); 267 | mNormals[index] = mNormals[index + mShapeVerticesLength] = normal; 268 | } 269 | mMmesh.SetNormals(mNormals); 270 | } 271 | 272 | [ContextMenu("GenerateAll")] 273 | // [Button] 274 | public void GenerateAll(bool refresh = true) 275 | { 276 | if(PointInfos.Count < 2) return; 277 | mVertices.Clear(); 278 | mTriangles.Clear(); 279 | mUVs.Clear(); 280 | mNormals.Clear(); 281 | for (int i = 0, count = PointInfos.Count; i < count; i++) 282 | Generate(i); 283 | if (refresh) 284 | RefreshMesh(); 285 | } 286 | 287 | [ContextMenu("Clear")] 288 | // [Button] 289 | public void Clear() 290 | { 291 | PointInfos.Clear(); 292 | mVertices.Clear(); 293 | mTriangles.Clear(); 294 | mUVs.Clear(); 295 | mNormals.Clear(); 296 | //清空三角面,避免顶点数不满足三角面数产生报错 297 | mMmesh.SetTriangles(mTriangles, 0); 298 | RefreshMesh(); 299 | } 300 | 301 | private void Generate(int index) 302 | { 303 | var pointInfo = PointInfos[index]; 304 | if (index == 0) 305 | { 306 | pointInfo.Length = 0; 307 | //计算旋转 308 | Quaternion rot = CalcPointInfo(pointInfo, Vector3.forward, PointInfos[1].Point - PointInfos[0].Point, Vector3.up); 309 | //添加顶点 310 | AddForwardVerticesAndUVs(pointInfo, rot); 311 | AddMiddleVerticesAndUVs(pointInfo, rot); 312 | //添加三角面 313 | AddForwardPolygonTriangles(); 314 | } 315 | else 316 | { 317 | //计算长度 318 | var lastPointInfo = PointInfos[index - 1]; 319 | pointInfo.Length = lastPointInfo.Length + Vector3.Distance(lastPointInfo.Point, pointInfo.Point); 320 | if (index == PointInfos.Count - 1) 321 | { 322 | //计算旋转 323 | Quaternion rot = CalcPointInfo(pointInfo, lastPointInfo.TangentForward, PointInfos[index].Point - PointInfos[index - 1].Point, lastPointInfo.TangentUp); 324 | //添加顶点 325 | AddMiddleVerticesAndUVs(pointInfo, rot); 326 | AddBackVerticesAndUVs(pointInfo, rot); 327 | //添加三角面 328 | AddMiddlePolygonTriangles((index - 1) * mRealShapeVerticesLength + mShapeVerticesLength); 329 | AddBackPolygonTriangles((index + 1) * mRealShapeVerticesLength + mShapeVerticesLength); 330 | } 331 | else 332 | { 333 | var nextPointInfo = PointInfos[index + 1]; 334 | //计算旋转 335 | Vector3 v1 = (nextPointInfo.Point - pointInfo.Point).normalized; 336 | Vector3 v2 = (lastPointInfo.Point - pointInfo.Point).normalized; 337 | Vector3 forward = Vector3.Cross(v1 + v2, Vector3.Cross(v1, v2)).normalized; 338 | if (forward == Vector3.zero) 339 | forward = -v2; 340 | Quaternion rot = CalcPointInfo(pointInfo, lastPointInfo.TangentForward, forward, lastPointInfo.TangentUp); 341 | 342 | //返回到正常坐标系 343 | Quaternion inverseRot = Quaternion.Inverse(rot); 344 | var value = Quaternion.FromToRotation(inverseRot * -v2, inverseRot * forward).eulerAngles; 345 | //x代表y缩放,y代表x缩放 346 | var angle = new Vector2(value.y, value.x); 347 | //添加顶点 348 | AddMiddleVerticesAndUVs(pointInfo, rot, angle); 349 | //添加三角面 350 | AddMiddlePolygonTriangles((index - 1) * mRealShapeVerticesLength + mShapeVerticesLength); 351 | } 352 | } 353 | } 354 | 355 | private Quaternion CalcPointInfo(PointInfo pointInfo, Vector3 lastForward, Vector3 forward, Vector3 lastUp) 356 | { 357 | Quaternion rot = Quaternion.FromToRotation(lastForward, forward); 358 | Vector3 up = rot * lastUp; 359 | pointInfo.TangentForward = forward; 360 | pointInfo.TangentUp = up; 361 | return Quaternion.LookRotation(forward, up); 362 | } 363 | 364 | private void AddForwardPolygonTriangles() 365 | { 366 | for (int i = 0, len = mShapeTriangle.Length; i < len; i++) 367 | mTriangles.Add(mShapeTriangle[i]); 368 | } 369 | 370 | private void AddBackPolygonTriangles(int offset) 371 | { 372 | for (int i = mShapeTriangle.Length - 1; i >= 0; i--) 373 | mTriangles.Add(offset + mShapeTriangle[i]); 374 | } 375 | 376 | private void AddMiddlePolygonTriangles(int offset) 377 | { 378 | for (int i = 0; i < mShapeVerticesLength; i++) 379 | { 380 | mTriangles.Add(offset + i); mTriangles.Add(offset + mRealShapeVerticesLength + i); mTriangles.Add(offset + i + 1); 381 | mTriangles.Add(offset + mRealShapeVerticesLength + i); mTriangles.Add(offset + mRealShapeVerticesLength + i + 1); mTriangles.Add(offset + i + 1); 382 | } 383 | } 384 | 385 | private void AddForwardVerticesAndUVs(PointInfo pointInfo, Quaternion rot) 386 | { 387 | for (int i = 0; i < mShapeVerticesLength; i++) 388 | { 389 | var vertex = mRealShapeVertices[i]; 390 | mVertices.Add(pointInfo.Point + rot * vertex); 391 | 392 | var uv = mShapeUVs[i]; 393 | //移动到第四象限 避免uv重合 394 | uv -= new Vector2(mShapeUVMinMax.x, mShapeUVMinMax.w);//xMin yMax 395 | uv.Scale(mUVScale); 396 | mUVs.Add(uv); 397 | } 398 | } 399 | 400 | private void AddBackVerticesAndUVs(PointInfo pointInfo, Quaternion rot) 401 | { 402 | for (int i = 0; i < mShapeVerticesLength; i++) 403 | { 404 | var vertex = mRealShapeVertices[i]; 405 | mVertices.Add(pointInfo.Point + rot * vertex); 406 | 407 | var uv = mShapeUVs[i]; 408 | uv -= new Vector2(mShapeUVMinMax.x, mShapeUVMinMax.w);//xMin yMax 409 | //垂直镜像到第一象限 避免uv重合 410 | uv.y = -uv.y; 411 | uv.y += pointInfo.Length * mUVFactor; 412 | uv.Scale(mUVScale); 413 | mUVs.Add(uv); 414 | } 415 | } 416 | 417 | private void AddMiddleVerticesAndUVs(PointInfo pointInfo, Quaternion rot, Vector2? angle = null) 418 | { 419 | for (int i = 0; i < mRealShapeVerticesLength; i++) 420 | { 421 | var vertex = mRealShapeVertices[i % mShapeVerticesLength]; 422 | //缩放顶点 423 | if (angle.HasValue) 424 | { 425 | var factor = Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * angle.Value.x)); 426 | if (Mathf.Abs(factor) > 1e-4) 427 | vertex.x /= factor; 428 | factor = Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * angle.Value.y)); 429 | if (Mathf.Abs(factor) > 1e-4) 430 | vertex.y /= factor; 431 | } 432 | mVertices.Add(pointInfo.Point + rot * vertex); 433 | var uv = mShapeEdgeUVs[i]; 434 | uv.y += pointInfo.Length * mUVFactor; 435 | uv.Scale(mUVScale); 436 | mUVs.Add(uv); 437 | } 438 | } 439 | } -------------------------------------------------------------------------------- /Example/DrawTest.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 3 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0, g: 0.99999946, b: 0.99999946, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 1 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 12 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_AtlasSize: 1024 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 1 64 | m_CompAOExponentDirect: 0 65 | m_ExtractAmbientOcclusion: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVREnvironmentSampleCount: 500 81 | m_PVREnvironmentReferencePointCount: 2048 82 | m_PVRFilteringMode: 2 83 | m_PVRDenoiserTypeDirect: 0 84 | m_PVRDenoiserTypeIndirect: 0 85 | m_PVRDenoiserTypeAO: 0 86 | m_PVRFilterTypeDirect: 0 87 | m_PVRFilterTypeIndirect: 0 88 | m_PVRFilterTypeAO: 0 89 | m_PVREnvironmentMIS: 0 90 | m_PVRCulling: 1 91 | m_PVRFilteringGaussRadiusDirect: 1 92 | m_PVRFilteringGaussRadiusIndirect: 5 93 | m_PVRFilteringGaussRadiusAO: 2 94 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 95 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 96 | m_PVRFilteringAtrousPositionSigmaAO: 1 97 | m_ExportTrainingData: 0 98 | m_TrainingDataDestination: TrainingData 99 | m_LightProbeSampleCountMultiplier: 4 100 | m_LightingDataAsset: {fileID: 0} 101 | m_UseShadowmask: 1 102 | --- !u!196 &4 103 | NavMeshSettings: 104 | serializedVersion: 2 105 | m_ObjectHideFlags: 0 106 | m_BuildSettings: 107 | serializedVersion: 2 108 | agentTypeID: 0 109 | agentRadius: 0.5 110 | agentHeight: 2 111 | agentSlope: 45 112 | agentClimb: 0.4 113 | ledgeDropHeight: 0 114 | maxJumpAcrossDistance: 0 115 | minRegionArea: 2 116 | manualCellSize: 0 117 | cellSize: 0.16666667 118 | manualTileSize: 0 119 | tileSize: 256 120 | accuratePlacement: 0 121 | debug: 122 | m_Flags: 0 123 | m_NavMeshData: {fileID: 0} 124 | --- !u!1 &207033809 125 | GameObject: 126 | m_ObjectHideFlags: 0 127 | m_CorrespondingSourceObject: {fileID: 0} 128 | m_PrefabInstance: {fileID: 0} 129 | m_PrefabAsset: {fileID: 0} 130 | serializedVersion: 6 131 | m_Component: 132 | - component: {fileID: 207033812} 133 | - component: {fileID: 207033811} 134 | - component: {fileID: 207033810} 135 | m_Layer: 0 136 | m_Name: Main Camera 137 | m_TagString: MainCamera 138 | m_Icon: {fileID: 0} 139 | m_NavMeshLayer: 0 140 | m_StaticEditorFlags: 0 141 | m_IsActive: 1 142 | --- !u!81 &207033810 143 | AudioListener: 144 | m_ObjectHideFlags: 0 145 | m_CorrespondingSourceObject: {fileID: 0} 146 | m_PrefabInstance: {fileID: 0} 147 | m_PrefabAsset: {fileID: 0} 148 | m_GameObject: {fileID: 207033809} 149 | m_Enabled: 1 150 | --- !u!20 &207033811 151 | Camera: 152 | m_ObjectHideFlags: 0 153 | m_CorrespondingSourceObject: {fileID: 0} 154 | m_PrefabInstance: {fileID: 0} 155 | m_PrefabAsset: {fileID: 0} 156 | m_GameObject: {fileID: 207033809} 157 | m_Enabled: 1 158 | serializedVersion: 2 159 | m_ClearFlags: 2 160 | m_BackGroundColor: {r: 0.03034888, g: 0.34047383, b: 0.5849056, a: 0} 161 | m_projectionMatrixMode: 1 162 | m_GateFitMode: 2 163 | m_FOVAxisMode: 0 164 | m_SensorSize: {x: 36, y: 24} 165 | m_LensShift: {x: 0, y: 0} 166 | m_FocalLength: 50 167 | m_NormalizedViewPortRect: 168 | serializedVersion: 2 169 | x: 0 170 | y: 0 171 | width: 1 172 | height: 1 173 | near clip plane: 0.3 174 | far clip plane: 1000 175 | field of view: 60 176 | orthographic: 1 177 | orthographic size: 11.1 178 | m_Depth: -1 179 | m_CullingMask: 180 | serializedVersion: 2 181 | m_Bits: 4294967295 182 | m_RenderingPath: -1 183 | m_TargetTexture: {fileID: 0} 184 | m_TargetDisplay: 0 185 | m_TargetEye: 3 186 | m_HDR: 1 187 | m_AllowMSAA: 1 188 | m_AllowDynamicResolution: 0 189 | m_ForceIntoRT: 0 190 | m_OcclusionCulling: 1 191 | m_StereoConvergence: 10 192 | m_StereoSeparation: 0.022 193 | --- !u!4 &207033812 194 | Transform: 195 | m_ObjectHideFlags: 0 196 | m_CorrespondingSourceObject: {fileID: 0} 197 | m_PrefabInstance: {fileID: 0} 198 | m_PrefabAsset: {fileID: 0} 199 | m_GameObject: {fileID: 207033809} 200 | m_LocalRotation: {x: 0.46914923, y: -0, z: -0, w: 0.8831189} 201 | m_LocalPosition: {x: 0, y: 15.4, z: -9.7} 202 | m_LocalScale: {x: 1, y: 1, z: 1} 203 | m_Children: [] 204 | m_Father: {fileID: 0} 205 | m_RootOrder: 0 206 | m_LocalEulerAnglesHint: {x: 55.958004, y: 0, z: 0} 207 | --- !u!1 &212792341 208 | GameObject: 209 | m_ObjectHideFlags: 0 210 | m_CorrespondingSourceObject: {fileID: 0} 211 | m_PrefabInstance: {fileID: 0} 212 | m_PrefabAsset: {fileID: 0} 213 | serializedVersion: 6 214 | m_Component: 215 | - component: {fileID: 212792345} 216 | - component: {fileID: 212792344} 217 | - component: {fileID: 212792343} 218 | - component: {fileID: 212792342} 219 | m_Layer: 0 220 | m_Name: Sphere 221 | m_TagString: Untagged 222 | m_Icon: {fileID: 0} 223 | m_NavMeshLayer: 0 224 | m_StaticEditorFlags: 0 225 | m_IsActive: 1 226 | --- !u!135 &212792342 227 | SphereCollider: 228 | m_ObjectHideFlags: 0 229 | m_CorrespondingSourceObject: {fileID: 0} 230 | m_PrefabInstance: {fileID: 0} 231 | m_PrefabAsset: {fileID: 0} 232 | m_GameObject: {fileID: 212792341} 233 | m_Material: {fileID: 0} 234 | m_IsTrigger: 0 235 | m_Enabled: 1 236 | serializedVersion: 2 237 | m_Radius: 0.5 238 | m_Center: {x: 0, y: 0, z: 0} 239 | --- !u!23 &212792343 240 | MeshRenderer: 241 | m_ObjectHideFlags: 0 242 | m_CorrespondingSourceObject: {fileID: 0} 243 | m_PrefabInstance: {fileID: 0} 244 | m_PrefabAsset: {fileID: 0} 245 | m_GameObject: {fileID: 212792341} 246 | m_Enabled: 1 247 | m_CastShadows: 1 248 | m_ReceiveShadows: 1 249 | m_DynamicOccludee: 1 250 | m_MotionVectors: 1 251 | m_LightProbeUsage: 1 252 | m_ReflectionProbeUsage: 1 253 | m_RayTracingMode: 2 254 | m_RenderingLayerMask: 1 255 | m_RendererPriority: 0 256 | m_Materials: 257 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} 258 | m_StaticBatchInfo: 259 | firstSubMesh: 0 260 | subMeshCount: 0 261 | m_StaticBatchRoot: {fileID: 0} 262 | m_ProbeAnchor: {fileID: 0} 263 | m_LightProbeVolumeOverride: {fileID: 0} 264 | m_ScaleInLightmap: 1 265 | m_ReceiveGI: 1 266 | m_PreserveUVs: 0 267 | m_IgnoreNormalsForChartDetection: 0 268 | m_ImportantGI: 0 269 | m_StitchLightmapSeams: 1 270 | m_SelectedEditorRenderState: 3 271 | m_MinimumChartSize: 4 272 | m_AutoUVMaxDistance: 0.5 273 | m_AutoUVMaxAngle: 89 274 | m_LightmapParameters: {fileID: 0} 275 | m_SortingLayerID: 0 276 | m_SortingLayer: 0 277 | m_SortingOrder: 0 278 | --- !u!33 &212792344 279 | MeshFilter: 280 | m_ObjectHideFlags: 0 281 | m_CorrespondingSourceObject: {fileID: 0} 282 | m_PrefabInstance: {fileID: 0} 283 | m_PrefabAsset: {fileID: 0} 284 | m_GameObject: {fileID: 212792341} 285 | m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} 286 | --- !u!4 &212792345 287 | Transform: 288 | m_ObjectHideFlags: 0 289 | m_CorrespondingSourceObject: {fileID: 0} 290 | m_PrefabInstance: {fileID: 0} 291 | m_PrefabAsset: {fileID: 0} 292 | m_GameObject: {fileID: 212792341} 293 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 294 | m_LocalPosition: {x: 5.26, y: 0, z: 0} 295 | m_LocalScale: {x: 6.1303835, y: 6.1303835, z: 6.1303835} 296 | m_Children: [] 297 | m_Father: {fileID: 0} 298 | m_RootOrder: 6 299 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 300 | --- !u!1 &441480475 301 | GameObject: 302 | m_ObjectHideFlags: 0 303 | m_CorrespondingSourceObject: {fileID: 0} 304 | m_PrefabInstance: {fileID: 0} 305 | m_PrefabAsset: {fileID: 0} 306 | serializedVersion: 6 307 | m_Component: 308 | - component: {fileID: 441480479} 309 | - component: {fileID: 441480478} 310 | - component: {fileID: 441480477} 311 | - component: {fileID: 441480476} 312 | - component: {fileID: 441480480} 313 | m_Layer: 0 314 | m_Name: Plane 315 | m_TagString: Untagged 316 | m_Icon: {fileID: 0} 317 | m_NavMeshLayer: 0 318 | m_StaticEditorFlags: 0 319 | m_IsActive: 1 320 | --- !u!64 &441480476 321 | MeshCollider: 322 | m_ObjectHideFlags: 0 323 | m_CorrespondingSourceObject: {fileID: 0} 324 | m_PrefabInstance: {fileID: 0} 325 | m_PrefabAsset: {fileID: 0} 326 | m_GameObject: {fileID: 441480475} 327 | m_Material: {fileID: 0} 328 | m_IsTrigger: 0 329 | m_Enabled: 1 330 | serializedVersion: 4 331 | m_Convex: 1 332 | m_CookingOptions: 30 333 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 334 | --- !u!23 &441480477 335 | MeshRenderer: 336 | m_ObjectHideFlags: 0 337 | m_CorrespondingSourceObject: {fileID: 0} 338 | m_PrefabInstance: {fileID: 0} 339 | m_PrefabAsset: {fileID: 0} 340 | m_GameObject: {fileID: 441480475} 341 | m_Enabled: 1 342 | m_CastShadows: 1 343 | m_ReceiveShadows: 1 344 | m_DynamicOccludee: 1 345 | m_MotionVectors: 1 346 | m_LightProbeUsage: 1 347 | m_ReflectionProbeUsage: 1 348 | m_RayTracingMode: 2 349 | m_RenderingLayerMask: 1 350 | m_RendererPriority: 0 351 | m_Materials: 352 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} 353 | m_StaticBatchInfo: 354 | firstSubMesh: 0 355 | subMeshCount: 0 356 | m_StaticBatchRoot: {fileID: 0} 357 | m_ProbeAnchor: {fileID: 0} 358 | m_LightProbeVolumeOverride: {fileID: 0} 359 | m_ScaleInLightmap: 1 360 | m_ReceiveGI: 1 361 | m_PreserveUVs: 0 362 | m_IgnoreNormalsForChartDetection: 0 363 | m_ImportantGI: 0 364 | m_StitchLightmapSeams: 0 365 | m_SelectedEditorRenderState: 3 366 | m_MinimumChartSize: 4 367 | m_AutoUVMaxDistance: 0.5 368 | m_AutoUVMaxAngle: 89 369 | m_LightmapParameters: {fileID: 0} 370 | m_SortingLayerID: 0 371 | m_SortingLayer: 0 372 | m_SortingOrder: 0 373 | --- !u!33 &441480478 374 | MeshFilter: 375 | m_ObjectHideFlags: 0 376 | m_CorrespondingSourceObject: {fileID: 0} 377 | m_PrefabInstance: {fileID: 0} 378 | m_PrefabAsset: {fileID: 0} 379 | m_GameObject: {fileID: 441480475} 380 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 381 | --- !u!4 &441480479 382 | Transform: 383 | m_ObjectHideFlags: 0 384 | m_CorrespondingSourceObject: {fileID: 0} 385 | m_PrefabInstance: {fileID: 0} 386 | m_PrefabAsset: {fileID: 0} 387 | m_GameObject: {fileID: 441480475} 388 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 389 | m_LocalPosition: {x: 0, y: 0, z: 0} 390 | m_LocalScale: {x: 2.3967268, y: 0.25046, z: 2.3967268} 391 | m_Children: [] 392 | m_Father: {fileID: 0} 393 | m_RootOrder: 2 394 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 395 | --- !u!114 &441480480 396 | MonoBehaviour: 397 | m_ObjectHideFlags: 0 398 | m_CorrespondingSourceObject: {fileID: 0} 399 | m_PrefabInstance: {fileID: 0} 400 | m_PrefabAsset: {fileID: 0} 401 | m_GameObject: {fileID: 441480475} 402 | m_Enabled: 1 403 | m_EditorHideFlags: 0 404 | m_Script: {fileID: 11500000, guid: 82f1f9b4f0c7b4f43964f30c4c52f701, type: 3} 405 | m_Name: 406 | m_EditorClassIdentifier: 407 | dis: 20 408 | MeshGenerator: {fileID: 1518193155} 409 | --- !u!1 &1068837068 410 | GameObject: 411 | m_ObjectHideFlags: 0 412 | m_CorrespondingSourceObject: {fileID: 0} 413 | m_PrefabInstance: {fileID: 0} 414 | m_PrefabAsset: {fileID: 0} 415 | serializedVersion: 6 416 | m_Component: 417 | - component: {fileID: 1068837072} 418 | - component: {fileID: 1068837071} 419 | - component: {fileID: 1068837070} 420 | - component: {fileID: 1068837069} 421 | m_Layer: 0 422 | m_Name: Cube 423 | m_TagString: Untagged 424 | m_Icon: {fileID: 0} 425 | m_NavMeshLayer: 0 426 | m_StaticEditorFlags: 0 427 | m_IsActive: 1 428 | --- !u!65 &1068837069 429 | BoxCollider: 430 | m_ObjectHideFlags: 0 431 | m_CorrespondingSourceObject: {fileID: 0} 432 | m_PrefabInstance: {fileID: 0} 433 | m_PrefabAsset: {fileID: 0} 434 | m_GameObject: {fileID: 1068837068} 435 | m_Material: {fileID: 0} 436 | m_IsTrigger: 0 437 | m_Enabled: 1 438 | serializedVersion: 2 439 | m_Size: {x: 1, y: 1, z: 1} 440 | m_Center: {x: 0, y: 0, z: 0} 441 | --- !u!23 &1068837070 442 | MeshRenderer: 443 | m_ObjectHideFlags: 0 444 | m_CorrespondingSourceObject: {fileID: 0} 445 | m_PrefabInstance: {fileID: 0} 446 | m_PrefabAsset: {fileID: 0} 447 | m_GameObject: {fileID: 1068837068} 448 | m_Enabled: 1 449 | m_CastShadows: 1 450 | m_ReceiveShadows: 1 451 | m_DynamicOccludee: 1 452 | m_MotionVectors: 1 453 | m_LightProbeUsage: 1 454 | m_ReflectionProbeUsage: 1 455 | m_RayTracingMode: 2 456 | m_RenderingLayerMask: 1 457 | m_RendererPriority: 0 458 | m_Materials: 459 | - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} 460 | m_StaticBatchInfo: 461 | firstSubMesh: 0 462 | subMeshCount: 0 463 | m_StaticBatchRoot: {fileID: 0} 464 | m_ProbeAnchor: {fileID: 0} 465 | m_LightProbeVolumeOverride: {fileID: 0} 466 | m_ScaleInLightmap: 1 467 | m_ReceiveGI: 1 468 | m_PreserveUVs: 0 469 | m_IgnoreNormalsForChartDetection: 0 470 | m_ImportantGI: 0 471 | m_StitchLightmapSeams: 1 472 | m_SelectedEditorRenderState: 3 473 | m_MinimumChartSize: 4 474 | m_AutoUVMaxDistance: 0.5 475 | m_AutoUVMaxAngle: 89 476 | m_LightmapParameters: {fileID: 0} 477 | m_SortingLayerID: 0 478 | m_SortingLayer: 0 479 | m_SortingOrder: 0 480 | --- !u!33 &1068837071 481 | MeshFilter: 482 | m_ObjectHideFlags: 0 483 | m_CorrespondingSourceObject: {fileID: 0} 484 | m_PrefabInstance: {fileID: 0} 485 | m_PrefabAsset: {fileID: 0} 486 | m_GameObject: {fileID: 1068837068} 487 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 488 | --- !u!4 &1068837072 489 | Transform: 490 | m_ObjectHideFlags: 0 491 | m_CorrespondingSourceObject: {fileID: 0} 492 | m_PrefabInstance: {fileID: 0} 493 | m_PrefabAsset: {fileID: 0} 494 | m_GameObject: {fileID: 1068837068} 495 | m_LocalRotation: {x: 0.27010548, y: -0, z: -0, w: 0.9628307} 496 | m_LocalPosition: {x: -6.28, y: 0, z: 0} 497 | m_LocalScale: {x: 6.1303835, y: 6.1303835, z: 6.1303835} 498 | m_Children: [] 499 | m_Father: {fileID: 0} 500 | m_RootOrder: 5 501 | m_LocalEulerAnglesHint: {x: 31.341002, y: 0, z: 0} 502 | --- !u!1 &1331439252 503 | GameObject: 504 | m_ObjectHideFlags: 0 505 | m_CorrespondingSourceObject: {fileID: 0} 506 | m_PrefabInstance: {fileID: 0} 507 | m_PrefabAsset: {fileID: 0} 508 | serializedVersion: 6 509 | m_Component: 510 | - component: {fileID: 1331439254} 511 | - component: {fileID: 1331439253} 512 | m_Layer: 0 513 | m_Name: Directional Light 514 | m_TagString: Untagged 515 | m_Icon: {fileID: 0} 516 | m_NavMeshLayer: 0 517 | m_StaticEditorFlags: 0 518 | m_IsActive: 1 519 | --- !u!108 &1331439253 520 | Light: 521 | m_ObjectHideFlags: 0 522 | m_CorrespondingSourceObject: {fileID: 0} 523 | m_PrefabInstance: {fileID: 0} 524 | m_PrefabAsset: {fileID: 0} 525 | m_GameObject: {fileID: 1331439252} 526 | m_Enabled: 1 527 | serializedVersion: 10 528 | m_Type: 1 529 | m_Shape: 0 530 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 531 | m_Intensity: 0.6 532 | m_Range: 10 533 | m_SpotAngle: 30 534 | m_InnerSpotAngle: 21.802082 535 | m_CookieSize: 10 536 | m_Shadows: 537 | m_Type: 2 538 | m_Resolution: -1 539 | m_CustomResolution: -1 540 | m_Strength: 1 541 | m_Bias: 0.05 542 | m_NormalBias: 0.4 543 | m_NearPlane: 0.2 544 | m_CullingMatrixOverride: 545 | e00: 1 546 | e01: 0 547 | e02: 0 548 | e03: 0 549 | e10: 0 550 | e11: 1 551 | e12: 0 552 | e13: 0 553 | e20: 0 554 | e21: 0 555 | e22: 1 556 | e23: 0 557 | e30: 0 558 | e31: 0 559 | e32: 0 560 | e33: 1 561 | m_UseCullingMatrixOverride: 0 562 | m_Cookie: {fileID: 0} 563 | m_DrawHalo: 0 564 | m_Flare: {fileID: 0} 565 | m_RenderMode: 0 566 | m_CullingMask: 567 | serializedVersion: 2 568 | m_Bits: 4294967295 569 | m_RenderingLayerMask: 1 570 | m_Lightmapping: 4 571 | m_LightShadowCasterMode: 0 572 | m_AreaSize: {x: 1, y: 1} 573 | m_BounceIntensity: 1 574 | m_ColorTemperature: 6570 575 | m_UseColorTemperature: 0 576 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 577 | m_UseBoundingSphereOverride: 0 578 | m_ShadowRadius: 0 579 | m_ShadowAngle: 0 580 | --- !u!4 &1331439254 581 | Transform: 582 | m_ObjectHideFlags: 0 583 | m_CorrespondingSourceObject: {fileID: 0} 584 | m_PrefabInstance: {fileID: 0} 585 | m_PrefabAsset: {fileID: 0} 586 | m_GameObject: {fileID: 1331439252} 587 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 588 | m_LocalPosition: {x: 0, y: 100, z: 0} 589 | m_LocalScale: {x: 1, y: 1, z: 1} 590 | m_Children: [] 591 | m_Father: {fileID: 0} 592 | m_RootOrder: 1 593 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 594 | --- !u!1 &1518193154 595 | GameObject: 596 | m_ObjectHideFlags: 0 597 | m_CorrespondingSourceObject: {fileID: 0} 598 | m_PrefabInstance: {fileID: 0} 599 | m_PrefabAsset: {fileID: 0} 600 | serializedVersion: 6 601 | m_Component: 602 | - component: {fileID: 1518193156} 603 | - component: {fileID: 1518193158} 604 | - component: {fileID: 1518193157} 605 | - component: {fileID: 1518193155} 606 | m_Layer: 0 607 | m_Name: Mesh 608 | m_TagString: Untagged 609 | m_Icon: {fileID: 0} 610 | m_NavMeshLayer: 0 611 | m_StaticEditorFlags: 0 612 | m_IsActive: 1 613 | --- !u!114 &1518193155 614 | MonoBehaviour: 615 | m_ObjectHideFlags: 0 616 | m_CorrespondingSourceObject: {fileID: 0} 617 | m_PrefabInstance: {fileID: 0} 618 | m_PrefabAsset: {fileID: 0} 619 | m_GameObject: {fileID: 1518193154} 620 | m_Enabled: 1 621 | m_EditorHideFlags: 0 622 | m_Script: {fileID: 11500000, guid: 4f75a7e17fd2e4a01adf47c510b04fac, type: 3} 623 | m_Name: 624 | m_EditorClassIdentifier: 625 | mRotateAngle: 0 626 | mAngleThreshold: 20 627 | mScale: {x: 1, y: 1} 628 | mUVScale: {x: 1, y: 1} 629 | mCustomShapeVertices: 0 630 | mRadius: 0.5 631 | mShapeVerticesLength: 32 632 | mShapeVertices: 633 | - {x: -0.5, y: 0.00000004371139} 634 | - {x: -0.49039263, y: 0.097545244} 635 | - {x: -0.46193972, y: 0.19134183} 636 | - {x: -0.4157347, y: 0.27778524} 637 | - {x: -0.35355324, y: 0.35355353} 638 | - {x: -0.277785, y: 0.4157349} 639 | - {x: -0.19134156, y: 0.46193984} 640 | - {x: -0.09754496, y: 0.49039268} 641 | - {x: 0.00000024438103, y: 0.5} 642 | - {x: 0.09754544, y: 0.4903926} 643 | - {x: 0.19134201, y: 0.46193963} 644 | - {x: 0.27778542, y: 0.4157346} 645 | - {x: 0.35355368, y: 0.35355312} 646 | - {x: 0.41573507, y: 0.27778473} 647 | - {x: 0.46193996, y: 0.19134127} 648 | - {x: 0.49039274, y: 0.09754465} 649 | - {x: 0.5, y: -0.00000056425995} 650 | - {x: 0.49039254, y: -0.09754575} 651 | - {x: 0.4619395, y: -0.19134231} 652 | - {x: 0.41573444, y: -0.2777857} 653 | - {x: 0.35355288, y: -0.3535539} 654 | - {x: 0.27778447, y: -0.41573524} 655 | - {x: 0.19134097, y: -0.46194008} 656 | - {x: 0.097544335, y: -0.4903928} 657 | - {x: -0.00000088413884, y: -0.5} 658 | - {x: -0.09754607, y: -0.49039245} 659 | - {x: -0.19134238, y: -0.46193948} 660 | - {x: -0.27778557, y: -0.4157345} 661 | - {x: -0.35355362, y: -0.35355315} 662 | - {x: -0.4157349, y: -0.277785} 663 | - {x: -0.46193975, y: -0.19134177} 664 | - {x: -0.4903926, y: -0.09754542} 665 | mCustomShapeUVs: 0 666 | mShapeUVs: 667 | - {x: -0.15941086, y: 0.00000001393614} 668 | - {x: -0.15634783, y: 0.031099543} 669 | - {x: -0.14727642, y: 0.061003935} 670 | - {x: -0.13254526, y: 0.08856397} 671 | - {x: -0.11272045, y: 0.11272055} 672 | - {x: -0.0885639, y: 0.13254532} 673 | - {x: -0.06100385, y: 0.14727646} 674 | - {x: -0.031099454, y: 0.15634784} 675 | - {x: 0.00000007791398, y: 0.15941086} 676 | - {x: 0.031099604, y: 0.15634781} 677 | - {x: 0.06100399, y: 0.14727639} 678 | - {x: 0.08856403, y: 0.13254522} 679 | - {x: 0.112720594, y: 0.112720415} 680 | - {x: 0.13254537, y: 0.08856381} 681 | - {x: 0.14727649, y: 0.061003752} 682 | - {x: 0.15634786, y: 0.031099353} 683 | - {x: 0.15941086, y: -0.00000017989834} 684 | - {x: 0.1563478, y: -0.031099705} 685 | - {x: 0.14727636, y: -0.061004087} 686 | - {x: 0.13254517, y: -0.08856411} 687 | - {x: 0.11272034, y: -0.11272066} 688 | - {x: 0.088563725, y: -0.13254543} 689 | - {x: 0.06100366, y: -0.14727654} 690 | - {x: 0.031099254, y: -0.15634789} 691 | - {x: -0.00000028188268, y: -0.15941086} 692 | - {x: -0.031099807, y: -0.15634777} 693 | - {x: -0.06100411, y: -0.14727634} 694 | - {x: -0.088564076, y: -0.13254519} 695 | - {x: -0.11272058, y: -0.11272042} 696 | - {x: -0.13254532, y: -0.0885639} 697 | - {x: -0.14727643, y: -0.061003916} 698 | - {x: -0.15634781, y: -0.0310996} 699 | mCustomShapeEdgeUVs: 0 700 | mShapeEdgeUVs: 701 | - {x: 0, y: 0} 702 | - {x: 0.031250007, y: 0} 703 | - {x: 0.062500015, y: 0} 704 | - {x: 0.09375002, y: 0} 705 | - {x: 0.12500003, y: 0} 706 | - {x: 0.15625, y: 0} 707 | - {x: 0.1875, y: 0} 708 | - {x: 0.21875, y: 0} 709 | - {x: 0.25, y: 0} 710 | - {x: 0.28125, y: 0} 711 | - {x: 0.3125, y: 0} 712 | - {x: 0.34375, y: 0} 713 | - {x: 0.375, y: 0} 714 | - {x: 0.40625, y: 0} 715 | - {x: 0.4375, y: 0} 716 | - {x: 0.46875, y: 0} 717 | - {x: 0.5, y: 0} 718 | - {x: 0.53125, y: 0} 719 | - {x: 0.5625, y: 0} 720 | - {x: 0.59375, y: 0} 721 | - {x: 0.625, y: 0} 722 | - {x: 0.65625, y: 0} 723 | - {x: 0.6875, y: 0} 724 | - {x: 0.71875, y: 0} 725 | - {x: 0.75, y: 0} 726 | - {x: 0.78125, y: 0} 727 | - {x: 0.81249994, y: 0} 728 | - {x: 0.8437499, y: 0} 729 | - {x: 0.8749998, y: 0} 730 | - {x: 0.90624976, y: 0} 731 | - {x: 0.9374997, y: 0} 732 | - {x: 0.96874964, y: 0} 733 | - {x: 0.99999976, y: 0} 734 | PointInfos: [] 735 | --- !u!4 &1518193156 736 | Transform: 737 | m_ObjectHideFlags: 0 738 | m_CorrespondingSourceObject: {fileID: 0} 739 | m_PrefabInstance: {fileID: 0} 740 | m_PrefabAsset: {fileID: 0} 741 | m_GameObject: {fileID: 1518193154} 742 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 743 | m_LocalPosition: {x: 0, y: 0, z: 0} 744 | m_LocalScale: {x: 1, y: 1, z: 1} 745 | m_Children: [] 746 | m_Father: {fileID: 0} 747 | m_RootOrder: 3 748 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 749 | --- !u!23 &1518193157 750 | MeshRenderer: 751 | m_ObjectHideFlags: 0 752 | m_CorrespondingSourceObject: {fileID: 0} 753 | m_PrefabInstance: {fileID: 0} 754 | m_PrefabAsset: {fileID: 0} 755 | m_GameObject: {fileID: 1518193154} 756 | m_Enabled: 1 757 | m_CastShadows: 1 758 | m_ReceiveShadows: 1 759 | m_DynamicOccludee: 1 760 | m_MotionVectors: 1 761 | m_LightProbeUsage: 1 762 | m_ReflectionProbeUsage: 1 763 | m_RayTracingMode: 2 764 | m_RenderingLayerMask: 1 765 | m_RendererPriority: 0 766 | m_Materials: 767 | - {fileID: 2100000, guid: 5dfec8c2a3e074441940138f56ba47e6, type: 2} 768 | m_StaticBatchInfo: 769 | firstSubMesh: 0 770 | subMeshCount: 0 771 | m_StaticBatchRoot: {fileID: 0} 772 | m_ProbeAnchor: {fileID: 0} 773 | m_LightProbeVolumeOverride: {fileID: 0} 774 | m_ScaleInLightmap: 1 775 | m_ReceiveGI: 1 776 | m_PreserveUVs: 0 777 | m_IgnoreNormalsForChartDetection: 0 778 | m_ImportantGI: 0 779 | m_StitchLightmapSeams: 0 780 | m_SelectedEditorRenderState: 3 781 | m_MinimumChartSize: 4 782 | m_AutoUVMaxDistance: 0.5 783 | m_AutoUVMaxAngle: 89 784 | m_LightmapParameters: {fileID: 0} 785 | m_SortingLayerID: 0 786 | m_SortingLayer: 0 787 | m_SortingOrder: 0 788 | --- !u!33 &1518193158 789 | MeshFilter: 790 | m_ObjectHideFlags: 0 791 | m_CorrespondingSourceObject: {fileID: 0} 792 | m_PrefabInstance: {fileID: 0} 793 | m_PrefabAsset: {fileID: 0} 794 | m_GameObject: {fileID: 1518193154} 795 | m_Mesh: {fileID: 1735601594} 796 | --- !u!1 &1612085426 797 | GameObject: 798 | m_ObjectHideFlags: 0 799 | m_CorrespondingSourceObject: {fileID: 0} 800 | m_PrefabInstance: {fileID: 0} 801 | m_PrefabAsset: {fileID: 0} 802 | serializedVersion: 6 803 | m_Component: 804 | - component: {fileID: 1612085431} 805 | - component: {fileID: 1612085430} 806 | - component: {fileID: 1612085429} 807 | - component: {fileID: 1612085428} 808 | - component: {fileID: 1612085427} 809 | m_Layer: 0 810 | m_Name: Mesh (1) 811 | m_TagString: Untagged 812 | m_Icon: {fileID: 0} 813 | m_NavMeshLayer: 0 814 | m_StaticEditorFlags: 0 815 | m_IsActive: 0 816 | --- !u!114 &1612085427 817 | MonoBehaviour: 818 | m_ObjectHideFlags: 0 819 | m_CorrespondingSourceObject: {fileID: 0} 820 | m_PrefabInstance: {fileID: 0} 821 | m_PrefabAsset: {fileID: 0} 822 | m_GameObject: {fileID: 1612085426} 823 | m_Enabled: 1 824 | m_EditorHideFlags: 0 825 | m_Script: {fileID: 11500000, guid: 715477d305fa34731aaa6d2f72607cbd, type: 3} 826 | m_Name: 827 | m_EditorClassIdentifier: 828 | --- !u!114 &1612085428 829 | MonoBehaviour: 830 | m_ObjectHideFlags: 0 831 | m_CorrespondingSourceObject: {fileID: 0} 832 | m_PrefabInstance: {fileID: 0} 833 | m_PrefabAsset: {fileID: 0} 834 | m_GameObject: {fileID: 1612085426} 835 | m_Enabled: 1 836 | m_EditorHideFlags: 0 837 | m_Script: {fileID: 11500000, guid: 4f75a7e17fd2e4a01adf47c510b04fac, type: 3} 838 | m_Name: 839 | m_EditorClassIdentifier: 840 | mRotateAngle: 0 841 | mAngleThreshold: 20 842 | mScale: {x: 1, y: 1} 843 | mUVScale: {x: 1, y: 1} 844 | mCustomShapeVertices: 1 845 | mRadius: 0.5 846 | mShapeVerticesLength: 8 847 | mShapeVertices: 848 | - {x: -0.3, y: 0.1} 849 | - {x: -0.1, y: 0.1} 850 | - {x: -0.1, y: 0.3} 851 | - {x: 0.1, y: 0.3} 852 | - {x: 0.1, y: 0.1} 853 | - {x: 0.3, y: 0.1} 854 | - {x: 0.3, y: -0.3} 855 | - {x: -0.3, y: -0.3} 856 | mCustomShapeUVs: 0 857 | mShapeUVs: [] 858 | mCustomShapeEdgeUVs: 0 859 | mShapeEdgeUVs: [] 860 | PointInfos: [] 861 | --- !u!23 &1612085429 862 | MeshRenderer: 863 | m_ObjectHideFlags: 0 864 | m_CorrespondingSourceObject: {fileID: 0} 865 | m_PrefabInstance: {fileID: 0} 866 | m_PrefabAsset: {fileID: 0} 867 | m_GameObject: {fileID: 1612085426} 868 | m_Enabled: 1 869 | m_CastShadows: 1 870 | m_ReceiveShadows: 1 871 | m_DynamicOccludee: 1 872 | m_MotionVectors: 1 873 | m_LightProbeUsage: 1 874 | m_ReflectionProbeUsage: 1 875 | m_RayTracingMode: 2 876 | m_RenderingLayerMask: 1 877 | m_RendererPriority: 0 878 | m_Materials: 879 | - {fileID: 2100000, guid: 5dfec8c2a3e074441940138f56ba47e6, type: 2} 880 | m_StaticBatchInfo: 881 | firstSubMesh: 0 882 | subMeshCount: 0 883 | m_StaticBatchRoot: {fileID: 0} 884 | m_ProbeAnchor: {fileID: 0} 885 | m_LightProbeVolumeOverride: {fileID: 0} 886 | m_ScaleInLightmap: 1 887 | m_ReceiveGI: 1 888 | m_PreserveUVs: 0 889 | m_IgnoreNormalsForChartDetection: 0 890 | m_ImportantGI: 0 891 | m_StitchLightmapSeams: 0 892 | m_SelectedEditorRenderState: 3 893 | m_MinimumChartSize: 4 894 | m_AutoUVMaxDistance: 0.5 895 | m_AutoUVMaxAngle: 89 896 | m_LightmapParameters: {fileID: 0} 897 | m_SortingLayerID: 0 898 | m_SortingLayer: 0 899 | m_SortingOrder: 0 900 | --- !u!33 &1612085430 901 | MeshFilter: 902 | m_ObjectHideFlags: 0 903 | m_CorrespondingSourceObject: {fileID: 0} 904 | m_PrefabInstance: {fileID: 0} 905 | m_PrefabAsset: {fileID: 0} 906 | m_GameObject: {fileID: 1612085426} 907 | m_Mesh: {fileID: 2100842365} 908 | --- !u!4 &1612085431 909 | Transform: 910 | m_ObjectHideFlags: 0 911 | m_CorrespondingSourceObject: {fileID: 0} 912 | m_PrefabInstance: {fileID: 0} 913 | m_PrefabAsset: {fileID: 0} 914 | m_GameObject: {fileID: 1612085426} 915 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 916 | m_LocalPosition: {x: 0, y: 0, z: 0} 917 | m_LocalScale: {x: 1, y: 1, z: 1} 918 | m_Children: [] 919 | m_Father: {fileID: 0} 920 | m_RootOrder: 4 921 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 922 | --- !u!43 &1735601594 923 | Mesh: 924 | m_ObjectHideFlags: 0 925 | m_CorrespondingSourceObject: {fileID: 0} 926 | m_PrefabInstance: {fileID: 0} 927 | m_PrefabAsset: {fileID: 0} 928 | m_Name: GeneratedMesh 929 | serializedVersion: 10 930 | m_SubMeshes: 931 | - serializedVersion: 2 932 | firstByte: 0 933 | indexCount: 0 934 | topology: 0 935 | baseVertex: 0 936 | firstVertex: 0 937 | vertexCount: 0 938 | localAABB: 939 | m_Center: {x: 0, y: 0, z: 0} 940 | m_Extent: {x: 0, y: 0, z: 0} 941 | m_Shapes: 942 | vertices: [] 943 | shapes: [] 944 | channels: [] 945 | fullWeights: [] 946 | m_BindPose: [] 947 | m_BoneNameHashes: 948 | m_RootBoneNameHash: 0 949 | m_BonesAABB: [] 950 | m_VariableBoneCountWeights: 951 | m_Data: 952 | m_MeshCompression: 0 953 | m_IsReadable: 1 954 | m_KeepVertices: 1 955 | m_KeepIndices: 1 956 | m_IndexFormat: 0 957 | m_IndexBuffer: 958 | m_VertexData: 959 | serializedVersion: 3 960 | m_VertexCount: 0 961 | m_Channels: 962 | - stream: 0 963 | offset: 0 964 | format: 0 965 | dimension: 3 966 | - stream: 0 967 | offset: 0 968 | format: 0 969 | dimension: 0 970 | - stream: 0 971 | offset: 0 972 | format: 0 973 | dimension: 0 974 | - stream: 0 975 | offset: 0 976 | format: 0 977 | dimension: 0 978 | - stream: 0 979 | offset: 0 980 | format: 0 981 | dimension: 0 982 | - stream: 0 983 | offset: 0 984 | format: 0 985 | dimension: 0 986 | - stream: 0 987 | offset: 0 988 | format: 0 989 | dimension: 0 990 | - stream: 0 991 | offset: 0 992 | format: 0 993 | dimension: 0 994 | - stream: 0 995 | offset: 0 996 | format: 0 997 | dimension: 0 998 | - stream: 0 999 | offset: 0 1000 | format: 0 1001 | dimension: 0 1002 | - stream: 0 1003 | offset: 0 1004 | format: 0 1005 | dimension: 0 1006 | - stream: 0 1007 | offset: 0 1008 | format: 0 1009 | dimension: 0 1010 | - stream: 0 1011 | offset: 0 1012 | format: 0 1013 | dimension: 0 1014 | - stream: 0 1015 | offset: 0 1016 | format: 0 1017 | dimension: 0 1018 | m_DataSize: 0 1019 | _typelessdata: 1020 | m_CompressedMesh: 1021 | m_Vertices: 1022 | m_NumItems: 0 1023 | m_Range: 0 1024 | m_Start: 0 1025 | m_Data: 1026 | m_BitSize: 0 1027 | m_UV: 1028 | m_NumItems: 0 1029 | m_Range: 0 1030 | m_Start: 0 1031 | m_Data: 1032 | m_BitSize: 0 1033 | m_Normals: 1034 | m_NumItems: 0 1035 | m_Range: 0 1036 | m_Start: 0 1037 | m_Data: 1038 | m_BitSize: 0 1039 | m_Tangents: 1040 | m_NumItems: 0 1041 | m_Range: 0 1042 | m_Start: 0 1043 | m_Data: 1044 | m_BitSize: 0 1045 | m_Weights: 1046 | m_NumItems: 0 1047 | m_Data: 1048 | m_BitSize: 0 1049 | m_NormalSigns: 1050 | m_NumItems: 0 1051 | m_Data: 1052 | m_BitSize: 0 1053 | m_TangentSigns: 1054 | m_NumItems: 0 1055 | m_Data: 1056 | m_BitSize: 0 1057 | m_FloatColors: 1058 | m_NumItems: 0 1059 | m_Range: 0 1060 | m_Start: 0 1061 | m_Data: 1062 | m_BitSize: 0 1063 | m_BoneIndices: 1064 | m_NumItems: 0 1065 | m_Data: 1066 | m_BitSize: 0 1067 | m_Triangles: 1068 | m_NumItems: 0 1069 | m_Data: 1070 | m_BitSize: 0 1071 | m_UVInfo: 0 1072 | m_LocalAABB: 1073 | m_Center: {x: 0, y: 0, z: 0} 1074 | m_Extent: {x: 0, y: 0, z: 0} 1075 | m_MeshUsageFlags: 0 1076 | m_BakedConvexCollisionMesh: 1077 | m_BakedTriangleCollisionMesh: 1078 | m_MeshMetrics[0]: 1 1079 | m_MeshMetrics[1]: 1 1080 | m_MeshOptimizationFlags: 1 1081 | m_StreamData: 1082 | offset: 0 1083 | size: 0 1084 | path: 1085 | --- !u!43 &2100842365 1086 | Mesh: 1087 | m_ObjectHideFlags: 0 1088 | m_CorrespondingSourceObject: {fileID: 0} 1089 | m_PrefabInstance: {fileID: 0} 1090 | m_PrefabAsset: {fileID: 0} 1091 | m_Name: GeneratedMesh 1092 | serializedVersion: 10 1093 | m_SubMeshes: 1094 | - serializedVersion: 2 1095 | firstByte: 0 1096 | indexCount: 0 1097 | topology: 0 1098 | baseVertex: 0 1099 | firstVertex: 0 1100 | vertexCount: 0 1101 | localAABB: 1102 | m_Center: {x: 0, y: 0, z: 0} 1103 | m_Extent: {x: 0, y: 0, z: 0} 1104 | m_Shapes: 1105 | vertices: [] 1106 | shapes: [] 1107 | channels: [] 1108 | fullWeights: [] 1109 | m_BindPose: [] 1110 | m_BoneNameHashes: 1111 | m_RootBoneNameHash: 0 1112 | m_BonesAABB: [] 1113 | m_VariableBoneCountWeights: 1114 | m_Data: 1115 | m_MeshCompression: 0 1116 | m_IsReadable: 1 1117 | m_KeepVertices: 1 1118 | m_KeepIndices: 1 1119 | m_IndexFormat: 0 1120 | m_IndexBuffer: 1121 | m_VertexData: 1122 | serializedVersion: 3 1123 | m_VertexCount: 0 1124 | m_Channels: 1125 | - stream: 0 1126 | offset: 0 1127 | format: 0 1128 | dimension: 0 1129 | - stream: 0 1130 | offset: 0 1131 | format: 0 1132 | dimension: 0 1133 | - stream: 0 1134 | offset: 0 1135 | format: 0 1136 | dimension: 0 1137 | - stream: 0 1138 | offset: 0 1139 | format: 0 1140 | dimension: 0 1141 | - stream: 0 1142 | offset: 0 1143 | format: 0 1144 | dimension: 0 1145 | - stream: 0 1146 | offset: 0 1147 | format: 0 1148 | dimension: 0 1149 | - stream: 0 1150 | offset: 0 1151 | format: 0 1152 | dimension: 0 1153 | - stream: 0 1154 | offset: 0 1155 | format: 0 1156 | dimension: 0 1157 | - stream: 0 1158 | offset: 0 1159 | format: 0 1160 | dimension: 0 1161 | - stream: 0 1162 | offset: 0 1163 | format: 0 1164 | dimension: 0 1165 | - stream: 0 1166 | offset: 0 1167 | format: 0 1168 | dimension: 0 1169 | - stream: 0 1170 | offset: 0 1171 | format: 0 1172 | dimension: 0 1173 | - stream: 0 1174 | offset: 0 1175 | format: 0 1176 | dimension: 0 1177 | - stream: 0 1178 | offset: 0 1179 | format: 0 1180 | dimension: 0 1181 | m_DataSize: 0 1182 | _typelessdata: 1183 | m_CompressedMesh: 1184 | m_Vertices: 1185 | m_NumItems: 0 1186 | m_Range: 0 1187 | m_Start: 0 1188 | m_Data: 1189 | m_BitSize: 0 1190 | m_UV: 1191 | m_NumItems: 0 1192 | m_Range: 0 1193 | m_Start: 0 1194 | m_Data: 1195 | m_BitSize: 0 1196 | m_Normals: 1197 | m_NumItems: 0 1198 | m_Range: 0 1199 | m_Start: 0 1200 | m_Data: 1201 | m_BitSize: 0 1202 | m_Tangents: 1203 | m_NumItems: 0 1204 | m_Range: 0 1205 | m_Start: 0 1206 | m_Data: 1207 | m_BitSize: 0 1208 | m_Weights: 1209 | m_NumItems: 0 1210 | m_Data: 1211 | m_BitSize: 0 1212 | m_NormalSigns: 1213 | m_NumItems: 0 1214 | m_Data: 1215 | m_BitSize: 0 1216 | m_TangentSigns: 1217 | m_NumItems: 0 1218 | m_Data: 1219 | m_BitSize: 0 1220 | m_FloatColors: 1221 | m_NumItems: 0 1222 | m_Range: 0 1223 | m_Start: 0 1224 | m_Data: 1225 | m_BitSize: 0 1226 | m_BoneIndices: 1227 | m_NumItems: 0 1228 | m_Data: 1229 | m_BitSize: 0 1230 | m_Triangles: 1231 | m_NumItems: 0 1232 | m_Data: 1233 | m_BitSize: 0 1234 | m_UVInfo: 0 1235 | m_LocalAABB: 1236 | m_Center: {x: 0, y: 0, z: 0} 1237 | m_Extent: {x: 0, y: 0, z: 0} 1238 | m_MeshUsageFlags: 0 1239 | m_BakedConvexCollisionMesh: 1240 | m_BakedTriangleCollisionMesh: 1241 | m_MeshMetrics[0]: 1 1242 | m_MeshMetrics[1]: 1 1243 | m_MeshOptimizationFlags: -1 1244 | m_StreamData: 1245 | offset: 0 1246 | size: 0 1247 | path: 1248 | --------------------------------------------------------------------------------