рдлреНрд▓рд╛рдИ рдкрд░ рдореЙрдбрд▓ рдХреЛ рдмрджрд▓рдирд╛ рд╡рд┐рдХреГрддрд┐рдпреЛрдВ рдХреЗ рднреМрддрд┐рдХреА рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдФрд░ рдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕рд╛рдордЧреНрд░реА рд╡рд╛рд▓реЗ рдЦреЗрд▓реЛрдВ рдореЗрдВ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдо рдмрд╛рдд рд╣реИред рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдВрдкрд╛рджрди рдФрд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рдЕрдХреНрд╕рд░ рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрдЪрд╛рд░рд┐рдд рдХрд░рддреЗ рд╕рдордп рдкреЛрд╖рд┐рдд рдмрд╛рдЗрдЯ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдордЬреЗрджрд╛рд░ рд╣реИ!
рд▓реЗрдЦ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдПрдХрддрд╛ рдореЗрдВ рдореЗрд╖реЛрдВ рдХреЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдХреМрд╢рд▓ рдХреЛ рдкрдВрдк рдХрд░рдирд╛ рд╣реИред рд╣рдо рдПрдХ рдЬрд╛рд▓ рдХреЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдФрд░ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред

3 рдбреА рдореЙрдбрд▓ рдХреЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╕рдВрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реА рд╕рдЬреНрдЬрдирддрд╛рдкреВрд░реНрдг рдХрд┐рдЯ рдореЗрдВ рддреАрди рдмреБрдирд┐рдпрд╛рджреА рд╕рдВрдЪрд╛рд▓рди рд╢рд╛рдорд┐рд▓ рд╣реИрдВ: рддреНрд░рд┐рдХреЛрдгрд╛рд╕рди, рдмрд┐рдВрджреБрдУрдВ рдХреА рдЧрддрд┐, рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдирд╛ред рд╣рдо рдкрд┐рдЫрд▓реЗ рджреЛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЧрддрд┐ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ - рдЪрд▓рддреА рдХреЛрдиреЗ, рдШреВрд░реНрдгрди рдФрд░ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдХрд┐рдирд╛рд░реЛрдВ рдФрд░ рддреНрд░рд┐рдХреЛрдгред рдлрд┐рд░ рд╣рдо рдирдИ рдЬреНрдпрд╛рдорд┐рддрд┐ рдкреИрджрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрд░реАрдХреЗ рд╕реЗ рдирд┐рдкрдЯреЗрдВрдЧреЗ - рдПрдХреНрд╕рдЯреНрд░реВрдб рдСрдкрд░реЗрд╢рдиред
рдкрд┐рдЫрд▓реЗ рдкреНрд░рдХрд╛рд╢рди рдореЗрдВ, рд╣рдордиреЗ 3D рдореЙрдбрд▓ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реА рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдерд╛редрд╕рдВрд░рдЪрдирд╛ рдХреЛрдбpublic static class CustomMeshPool { private static List<CustomMesh> Pool; private static int pointer; public static CustomMesh GetMesh(int id) { return Pool[id]; } public static int Push(CustomMesh customMesh) { if (Pool == null) Pool = new List<CustomMesh>(); pointer = GetAvailableIndex(); if (pointer < Pool.Count) Pool[pointer] = customMesh; else Pool.Add(customMesh); return pointer; } public static bool Remove(int index) { if (Pool == null) return false; var b = Pool[index] == null; Pool[index] = null; return b; } public static int GetAvailableIndex() { if (Pool == null) return 0; var availableIndex = Pool.FindIndex(mesh => mesh == null); return availableIndex != -1 ? availableIndex : Pool.Count; } public static void Flush() { if (Pool != null) Pool.Clear(); } } public class CustomMesh { public int Id; public Triangle[] Triangles; public Vector3[] vertices; public Vector3[] normals; public Vector2[] uv0, uv2; public Color[] colors; public CustomMesh(Vector3[] vertices, int[] triangles, Vector3[] normals, Vector2[] uv0, Vector2[] uv2, Color[] colors) { this.vertices = vertices; this.normals = normals; if (normals != null) for (var i = 0; i < this.normals.Length; i++) { this.normals[i] = this.normals[i].normalized; } this.uv0 = uv0; this.uv2 = uv2; this.colors = colors; var ptr = CustomMeshPool.GetAvailableIndex(); CustomMeshPool.Push(this); Id = ptr; Triangles = new Triangle[triangles.Length / 3]; Triangles = Triangles .AsParallel() .Select((t, i) => new Triangle(ptr, i, triangles[i * 3], triangles[i * 3 + 1], triangles[i * 3 + 2])) .ToArray(); } } public struct Triangle { private int _index; public int Index { get { return _index; } set { _index = value; if (_edges != null) { _edges[0].TriangleIndex = value; _edges[1].TriangleIndex = value; _edges[2].TriangleIndex = value; } } } private int _meshId; public int MeshId { get { return _meshId; } internal set { _meshId = value; } } private Edge[] _edges; public Edge[] Edges { get { return _edges; } set { if (value.Length == 3) { _edges = value; for (var i = 0; i < 3; i++) { _edges[i].TriangleIndex = _index; } } else throw new IndexOutOfRangeException(); } } public Vertex V0 { get { return Edges[0].v0; } set { if (value.MeshId != MeshId) throw new Exception("Not the same mesh"); Edges[0].v0 = value; Edges[2].v1 = value; } } public Vertex V1 { get { return Edges[1].v0; } set { if (value.MeshId != MeshId) throw new Exception("Not the same mesh"); Edges[1].v0 = value; Edges[0].v1 = value; } } public Vertex V2 { get { return Edges[2].v0; } set { if (value.MeshId != MeshId) throw new Exception("Not the same mesh"); Edges[2].v0 = value; Edges[1].v1 = value; } } public Triangle(int meshId, int index, int v0, int v1, int v2) { _index = index; _meshId = meshId; var edges = new Edge[3]; edges[0] = new Edge(meshId, index, v0, v1); edges[1] = new Edge(meshId, index, v1, v2); edges[2] = new Edge(meshId, index, v2, v0); _edges = edges; } } public struct Edge { public Vertex v0; public Vertex v1; private int _meshId; public int MeshId { get { return _meshId; } internal set { _meshId = value; } } private int _triangleIndex; public int TriangleIndex { get { return _triangleIndex; } internal set { _triangleIndex = value; } } public Edge(int meshId, int triangleIndex, int v0Index, int v1Index) { _meshId = meshId; _triangleIndex = triangleIndex; v0 = new Vertex() { MeshId = meshId, Index = v0Index }; v1 = new Vertex() { MeshId = meshId, Index = v1Index }; } } public struct Vertex { public int Index; private int _meshId; public int MeshId { get { return _meshId; } internal set { _meshId = value; } } public Vector3 position { get { return CustomMeshPool.GetMesh(_meshId).vertices[Index]; } set { CustomMeshPool.GetMesh(_meshId).vertices[Index] = value; } } public Vector3 normal { get { return CustomMeshPool.GetMesh(_meshId).normals[Index]; } set { CustomMeshPool.GetMesh(_meshId).normals[Index] = value; } } public Vector2 uv0 { get { return CustomMeshPool.GetMesh(_meshId).uv0[Index]; } set { CustomMeshPool.GetMesh(_meshId).uv0[Index] = value; } } public Vector2 uv2 { get { return CustomMeshPool.GetMesh(_meshId).uv2[Index]; } set { CustomMeshPool.GetMesh(_meshId).uv2[Index] = value; } } public Color color { get { return CustomMeshPool.GetMesh(_meshId).colors[Index]; } set { CustomMeshPool.GetMesh(_meshId).colors[Index] = value; } } }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣рд╛рдВ PLINQ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рдирд▓ рдЬреНрдпрд╛рдорд┐рддрд┐ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдЕрдХреНрд╕рд░ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдмреЗрд╢рдХ, LINQ рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рдВрд╕ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рдЕрдзрд┐рдХ LINQ рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЬрдм "рдореИрдиреБрдЕрд▓" рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рддрд░рд╣ рдХреЗ рдбрд┐рдЬрд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХреЗ рд╕рд╛рде-рд╕рд╛рде PLINQ рдореЗрдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдмрдВрдзрди рдЙрдкрдХрд░рдгреЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рд╕реЗ рдпрд╣ рдХрдореА рдХрд╛рдлреА рд╣рдж рддрдХ рджреВрд░ рд╣реЛрддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдФрд░ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмреАрдЪ рд╕рдВрдХреНрд░рдордг рдХреЗрд╡рд▓ рдПрдХ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдбрд┐рдмрдЧрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рддрд╛ рд╣реИредрдореИрдВ рдШреБрдорд╛рддрд╛ рд╣реВрдВ, рдорд░реЛрдбрд╝рддрд╛ рд╣реВрдВ, рднреНрд░рдорд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ
рд╣рдо рдЖрдВрджреЛрд▓рди рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рд╣рд┐рд▓рддреЗ рд╣реБрдП рд╕рд┐рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдмрд╕ рд╕рдВрдпреЛрдЧ рдХреА рдЪреЛрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдордд рднреВрд▓рдирд╛: рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдЙрдирдХреА рд╕реНрдерд┐рддрд┐ рднреА рдмрджрд▓рдиреА рдЪрд╛рд╣рд┐рдПред
рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд╢реАрд░реНрд╖ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХ рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ рдЬреЛрдбрд╝рдХрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдмрджрд▓рд╛рд╡ рдореЙрдбрд▓ рдХреА рдЙрддреНрдкрддреНрддрд┐ (
рдзреБрд░реА ) рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдРрд╕реЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рджреМрд░рд╛рди рдмрд╣реБрднреБрдЬ рдХреА рд╕реНрдерд┐рддрд┐ рдмрджрд▓ рд╕рдХрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдирдХреЗ рдХреЛрдиреЗ рдХреЗ рдорд╛рдирджрдВрдб рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреНрд░рд╕реНрддреБрддрд┐ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред
рд╕реАрдПрдбреА рдЯреВрд▓реНрд╕ рдореЗрдВ рдкреБрдирд░реНрдЧрдгрдирд╛ рдорд╛рдирджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдорддреМрд░ рдкрд░ рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдЖрд╡рдВрдЯрди рдХреЛ рдХрд░рдиреЗ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдЖрдо рдкреНрд░рддреНрдпреЗрдХ рддреНрд░рд┐рдХреЛрдг рдХреЗ рд╡рд┐рдорд╛рди рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдкреНрд░рддреНрдпреЗрдХ рд╢реАрд░реНрд╖ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИ рддреНрд░рд┐рдХреЛрдг рдХреЗ рдорд╛рдирджрдВрдбреЛрдВ рдХреЗ рдФрд╕рдд рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛ рдЗрд╕ рд╢реАрд░реНрд╖ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИредрд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдХреЛрдб рдХреЛ рдЬрдЯрд┐рд▓ рдХрд░рдиреЗ рдФрд░ рдкрд░рд┐рд╡рд░реНрддрди рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдЕрдЪреНрдЫрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИред рдПрдХ рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ рдХреЛ рд╢реАрд░реНрд╖ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдЗрд╕рдХреЗ рдЖрдВрджреЛрд▓рди рдХреЗ рдПрдХ рд╕рд╣рдЬ рд╡рд┐рдЪрд╛рд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред

| 
|
рдПрдХ рд╢реАрд░реНрд╖ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреЗ рддрд░реАрдХреЗ public struct Vertex { ... public void Translate(Vector3 movement, bool withCoincident = false) { var newPosition = position + movement; if (withCoincident) { var vertices = CustomMeshPool.GetMesh(_meshId).vertices; var mask = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(position); for (int i = 0; i < vertices.Length; i++) if (mask[i]) vertices[i] = newPosition; } else { position = newPosition; } } } public class CustomMesh { тАж public bool[] GetVerticesInPosition(Vector3 position) { bool[] buffer = new bool[vertices.Length]; for (int i = 0; i < buffer.Length; i++) { buffer[i] = Mathf.Abs(position.x - vertices[i].x) < Mathf.Epsilon && Mathf.Abs(position.y - vertices[i].y) < Mathf.Epsilon && Mathf.Abs(position.z - vertices[i].z) < Mathf.Epsilon; } return buffer; } }
рдХрд┐рдирд╛рд░реЛрдВ рдФрд░ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреЗ рдЖрдВрджреЛрд▓рди рдХреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдПрдХ рд╡рд┐рд╕реНрдерд╛рдкрди рд╡реЗрдХреНрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рдХрд░ред
рдЕрднреА рднреА рдЬрд┐рдл рд╣реИрдВ рддреНрд░рд┐рдХреЛрдг рдФрд░ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреЗ рддрд░реАрдХреЗ public struct Edge { тАж public void Translate(Vector3 movement, bool withCoincident = false) { if (withCoincident) { var vertices = CustomMeshPool.GetMesh(MeshId).vertices; var newV0Position = v0.position + movement; var newV1Position = v1.position + movement; var maskV0 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v0.position); var maskV1 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v1.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; } } else { v0.Translate(movement); v1.Translate(movement); } } } public struct Triangle { тАж public void Translate(Vector3 movement, bool withCoincident = false) { if (withCoincident) { var vertices = CustomMeshPool.GetMesh(_meshId).vertices; var newV0Position = V0.position + movement; var newV1Position = V1.position + movement; var newV2Position = V2.position + movement; var maskV0 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V0.position); var maskV1 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V1.position); var maskV2 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V2.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; else if (maskV2[i]) vertices[i] = newV2Position; } } else { V0.Translate(movement); V1.Translate(movement); V2.Translate(movement); } } }
рд▓реЗрдХрд┐рди
рдЯреНрд░рд╛рдВрд╕рдлреЙрд░реНрдореЗрд╢рди рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдШреБрдорд╛рдирд╛ рдФрд░ рд╕реНрдХреЗрд▓ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдореЙрдбрд▓ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреА рдЙрддреНрдкрддреНрддрд┐ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рдЗрди рдСрдкрд░реЗрд╢рдиреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЖрдк рдХреНрдпрд╛ рдЪрд╛рд╣рддреЗ рдереЗ рдпрд╛ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рдереЗред рд░реЛрдЯреЗрд╢рди рдФрд░ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдХрд╛ рд╕рдВрджрд░реНрдн рдмрд┐рдВрджреБ рдЖрдорддреМрд░ рдкрд░ рд╡рд╕реНрддреБ рдХреЗ рдордзреНрдп рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдордиреБрд╖реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред
GIFs рдХреЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддреНрд░рд┐рдХреЛрдг рдФрд░ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рдШреБрдорд╛рдиреЗ рдФрд░ рд╕реНрдХреЗрд▓ рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐рдпрд╛рдВ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ public struct Edge { тАж public void Rotate(Quaternion rotation, bool withCoincident = false) { var pivot = (v0.position + v1.position) * 0.5f; var matrix = Matrix4x4.TRS(pivot, rotation, Vector3.one); var newV0Position = matrix.MultiplyPoint(v0.position - pivot); var newV1Position = matrix.MultiplyPoint(v1.position - pivot); if (withCoincident) { var vertices = CustomMeshPool.GetMesh(MeshId).vertices; var maskV0 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v0.position); var maskV1 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v1.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; } } else { v0.position = newV0Position; v1.position = newV1Position; } } public void Scale(Vector3 scale, bool withCoincident = false) { var pivot = (v0.position + v1.position) * 0.5f; var matrix = Matrix4x4.TRS(pivot, Quaternion.identity, scale); var newV0Position = matrix.MultiplyPoint(v0.position - pivot); var newV1Position = matrix.MultiplyPoint(v1.position - pivot); if (withCoincident) { var vertices = CustomMeshPool.GetMesh(MeshId).vertices; var maskV0 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v0.position); var maskV1 = CustomMeshPool.GetMesh(MeshId).GetVerticesInPosition(v1.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; } } else { v0.position = newV0Position; v1.position = newV1Position; } } } public struct Triangle { тАж public void Rotate(Quaternion rotation, bool withCoincident = false) { var pivot = (V0.position + V1.position + V2.position) / 3; var matrix = Matrix4x4.TRS(Vector3.zero, rotation, Vector3.one); var newV0Position = matrix.MultiplyPoint(V0.position - pivot) + pivot; var newV1Position = matrix.MultiplyPoint(V1.position - pivot) + pivot; var newV2Position = matrix.MultiplyPoint(V2.position - pivot) + pivot; if (withCoincident) { var vertices = CustomMeshPool.GetMesh(_meshId).vertices; var maskV0 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V0.position); var maskV1 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V1.position); var maskV2 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V2.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; else if (maskV2[i]) vertices[i] = newV2Position; } } else { Edges[0].v0.position = newV0Position; Edges[1].v0.position = newV1Position; Edges[2].v0.position = newV2Position; } Edges[0].v0.normal = matrix.MultiplyPoint(V0.normal); Edges[1].v0.normal = matrix.MultiplyPoint(V1.normal); Edges[2].v0.normal = matrix.MultiplyPoint(V2.normal); } public void Scale(Vector3 scale, bool withCoincident = false) { var pivot = (V0.position + V1.position + V2.position) / 3; var matrix = Matrix4x4.TRS(pivot, Quaternion.identity, scale); var newV0Position = matrix.MultiplyPoint(V0.position - pivot); var newV1Position = matrix.MultiplyPoint(V1.position - pivot); var newV2Position = matrix.MultiplyPoint(V2.position - pivot); if (withCoincident) { var vertices = CustomMeshPool.GetMesh(_meshId).vertices; var maskV0 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V0.position); var maskV1 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V1.position); var maskV2 = CustomMeshPool.GetMesh(_meshId).GetVerticesInPosition(V2.position); for (int i = 0; i < vertices.Length; i++) { if (maskV0[i]) vertices[i] = newV0Position; else if (maskV1[i]) vertices[i] = newV1Position; else if (maskV2[i]) vertices[i] = newV2Position; } } else { Edges[0].v0.position = newV0Position; Edges[1].v0.position = newV1Position; Edges[2].v0.position = newV2Position; } } }
рдЦреБрдж рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдл рд╕реБрдерд░рд╛ рдЫреЗрдж
3 рдбреА рдореЙрдбрд▓рд┐рдВрдЧ рдореЗрдВ, рдЕрдХреНрд╕рд░ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдСрдкрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП, рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ (рд╡рд┐рд╕реНрдерд╛рдкрди) рдФрд░ рдмрд╣реБрднреБрдЬ рдХреЗ рд╕реЗрдЯ рдХреЛ рдЬреНрдЮрд╛рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдирд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджреЛ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╡рд┐рдШрдЯрд┐рдд рд╣реЛ рд╕рдХрддреА рд╣реИ:
1. рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдореЛрд╢рди рд╡реЗрдХреНрдЯрд░ (
рдСрдлрд╕реЗрдЯ ) рджреНрд╡рд╛рд░рд╛ рдмрд╣реБрднреБрдЬ рдХреА
рдСрдлрд╕реЗрдЯ ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕реАрдорд╛ рдмрд╣реБрднреБрдЬ рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдП рдЧрдП рдХреЛрдиреЗ рдХреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рддрд╛рдХрд┐ рдЙрди рддрддреНрд╡реЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдкрд░реЗрд╢рд╛рди рди рдХрд░реЗрдВ рдЬреЛ рд╡рд┐рд╕реНрдерд╛рдкрд┐рдд рднрд╛рдЧ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИрдВред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЖрдкрдХреЛ рдЪрдпрдирд┐рдд рдЯреБрдХрдбрд╝реЗ рдХреЛ рдлрд╛рдбрд╝рдиреЗ рдФрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рдпрд╣ рдХрджрдо рдкрд╣рд▓реЗ рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдореЙрдбрд▓ рд╕рдВрднрд╡рддрдГ рдЙрди рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рдЧрд┐рд░ рдЬрд╛рдПрдЧрд╛ рдЬрд┐рдиреНрд╣реЗрдВ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ред

2. рд╡рд┐рд╕реНрдерд╛рдкрд┐рдд рд╣рд┐рд╕реНрд╕реЗ рдХреА рд╕реАрдорд╛ рдФрд░ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рджреМрд░рд╛рди рдмрдирдиреЗ рд╡рд╛рд▓реА рд╕реАрдорд╛ рдХреЗ рдмреАрдЪ рдирдИ рдЬреНрдпрд╛рдорд┐рддрд┐ рдЬреЛрдбрд╝рдирд╛ред рдореЙрдбрд▓ рдХреЗ рдореБрдЦреНрдп рдФрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рднрд╛рдЧреЛрдВ рдХреЗ рдмреАрдЪ рдХреА рдЦрд╛рдИ рдПрдХ рджреАрд╡рд╛рд░ рдмрдирд╛рдиреЗ рд╡рд╛рд▓реЗ рдмрд╣реБрднреБрдЬ рд╕реЗ рднрд░реА рд╣реБрдИ рд╣реИред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдкрд╣рд▓реЗ рджреАрд╡рд╛рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрд╛рд░реА рд╕реЗ рдкрд╣рд▓реЗ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реАрдорд╛ рдкрд░ рдХрд┐рдирд╛рд░реЛрдВ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рд╣реИ рдФрд░ рд╣рдо рддреБрд░рдВрдд рдЗрд╕ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдиреНрдпрдерд╛, рдЖрдкрдХреЛ рдпрд╛ рддреЛ рд╢реАрдпрд░ рд╡реЗрдХреНрдЯрд░ рдХреА рджрд┐рд╢рд╛ рдХреЛ рдкрд▓рдЯрдирд╛ рд╣реЛрдЧрд╛, рдпрд╛ рдореЗрд╖ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реЛрдЧрд╛ред
рдЬрд┐рд╕ рдореЙрдбрд▓ рдФрд░ рдЙрд╕рдХреЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд╕рд╛рде рд╣рдо рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рд╡реЗ рдЬреЛрдбрд╝реАрджрд╛рд░ рдЖрд╕рдиреНрди рдмрд╣реБрднреБрдЬ (рддреНрд░рд┐рдХреЛрдг) рдХреЗ рд╕реЗрдЯ рд╕реЗ рдмрдиреЗ рд╣реЛрддреЗ рд╣реИрдВред рд╣рдо рдРрд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрдЯ рдХреЛ рдПрдХ
рдХреНрд▓рд╕реНрдЯрд░ рдХрд╣рддреЗ рд╣реИрдВ ред
рдмреНрд▓реЗрдВрдбрд░ рдореЗрдВ рджреЛ рд╕рдорд░реНрдкрд┐рдд рдХреНрд▓рд╕реНрдЯрд░
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЙрди рд╕рднреА рдХрд┐рдирд╛рд░реЛрдВ рдХреЗ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдЪрдпрдирд┐рдд рд╕рдореВрд╣реЛрдВ рдХреЛ рдмрд╛рдВрдзрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рд╕реВрдЪреА рдореЗрдВ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝реЗрдВред рдпрджрд┐ рдПрдХ рдорд┐рд▓рд╛рди рдХрд┐рдирд╛рд░реЗ рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд┐рдирд╛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╕рд╣реА рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП, рдкреНрд░рддрд┐рдмрдВрдз рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ: рддреНрд░рд┐рдХреЛрдг рдХреЗ рдЪрдпрдирд┐рдд рд╕реЗрдЯ рдкрд░, рджреЛ рд╕рдВрдпреЛрдЧ рд╡рд╛рд▓реЗ рдХрд┐рдирд╛рд░реЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИрдВред рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЬрд╣рд╛рдВ
рдПрдХреНрд╕рдЯреНрд░реВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдореЙрдбрд▓ рдЕрдХреНрд╕рд░ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд▓рд┐рдП рдмрдбрд╝реЗ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рдирд▓ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рд╕рдореНтАНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐рдпрд╛рдВ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ internal static class LinkedListExtension { internal static IEnumerable<LinkedListNode<T>> Nodes<T>(this LinkedList<T> list) { for (var node = list.First; node != null; node = node.Next) { yield return node; } } } public struct Vertex { тАж public bool IsInPosition(Vector3 other) { return Mathf.Abs(position.x - other.x) < Mathf.Epsilon && Mathf.Abs(position.y - other.y) < Mathf.Epsilon && Mathf.Abs(position.z - other.z) < Mathf.Epsilon; } } public struct Edge { тАж public bool Coincides(Edge other, bool includeDirection = false) { return v0.IsInPosition(other.v0.position) && v1.IsInPosition(other.v1.position) || !includeDirection && v1.IsInPosition(other.v0.position) && v0.IsInPosition(other.v1.position); } } public class CustomMesh { тАж private LinkedList<Edge> ObtainHullEdges(int[] triIndices) { var edges = new LinkedList<Edge>(); for (var i = 0; i < triIndices.Length; i++) { var edge = edges.Nodes().FirstOrDefault(e => e.Value.Coincides(Triangles[triIndices[i]].Edges[0])); if (edge != null) edges.Remove(edge); else edges.AddFirst(Triangles[triIndices[i]].Edges[0]); edge = edges.Nodes().FirstOrDefault(e => e.Value.Coincides(Triangles[triIndices[i]].Edges[1])); if (edge != null) edges.Remove(edge); else edges.AddFirst(Triangles[triIndices[i]].Edges[1]); edge = edges.Nodes().FirstOrDefault(e => e.Value.Coincides(Triangles[triIndices[i]].Edges[2])); if (edge != null) edges.Remove(edge); else edges.AddFirst(Triangles[triIndices[i]].Edges[2]); } return edges; } }
рд╕рдореЛрдЪреНрдЪ рдХреЗ рд╕рднреА рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рджреАрд╡рд╛рд░реЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдордиреЗ рдХрдо рд╕реЗ рдХрдо рдкреНрд░рддрд┐рд░реЛрдз рдХрд╛ рд░рд╛рд╕реНрддрд╛ рддрдп рдХрд┐рдпрд╛ - рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд┐рдирд╛рд░реЛрдВ рдкрд░ рд╕реНрдерд┐рдд рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рд╕рдорд╛рдВрддрд░ рдЪрддреБрд░реНрднреБрдЬ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВред рдЪреВрдВрдХрд┐ рд╣рдо рд╕рднреА рдХрд╛ рдПрдХ рд╡рд┐рд╕реНрдерд╛рдкрди рд╣реИ, рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╕рдорд╛рдВрддрд░ рдЪрддреБрд░реНрднреБрдЬ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдареЛрд╕ рдФрд░ рдмрдВрдж рджреАрд╡рд╛рд░ рдмрдирд╛рдПрдВрдЧреЗред рдпрд╣ рджреАрд╡рд╛рд░ рддрддреНрд╡реЛрдВ рдХреЗ рдЙрдиреНрдореБрдЦреАрдХрд░рдг рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред
рджреАрд╡рд╛рд░, рдкреВрд░реЗ рдЬрд╛рд▓ рдХреА рддрд░рд╣, рддреНрд░рд┐рдХреЛрдг рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред
OpenGL рдХрдиреНрд╡реЗрдВрд╢рди рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдПрдХ рдЕрд▓рдЧ рддреНрд░рд┐рдХреЛрдг рд╕реНрдХреНрд░реАрди рдкрд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдЧрд░ рд╕реНрдХреНрд░реАрди рдкреНрд▓реЗрди рдкрд░ рдЙрд╕рдХреЗ рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд░рддреЗ рд╕рдордп, рдЙрдирдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдШреВрдордирд╛, рджрдХреНрд╖рд┐рдгрд╛рд╡рд░реНрдд рдШреВрдордирд╛ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ:

рддреЛ, рдПрдХ рддреНрд░рд┐рдХреЛрдг рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рд╛рдорд╛рдиреНрдп рд╡реЗрдХреНрдЯрд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдЬреЛ рд╕рд╛рдордиреЗ рдХреА рддрд░рдл рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рддреНрд░рд┐рднреБрдЬ рддреАрди рдХрд┐рдирд╛рд░реЛрдВ рд╕реЗ рдорд┐рд▓рдХрд░ рдПрдХ рдЙрддреНрддрд▓ рд╕рдореЛрдЪреНрдЪ рд╕реЗ рдШрд┐рд░рд╛ рд╣реЛрддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдХрд┐рдирд╛рд░реЗ рдореЗрдВ
v0 рдФрд░
v1 рдХреЗ рд░реВрдк рдореЗрдВ рд╣рдорд╛рд░реА рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд┐рдП рдЧрдП рджреЛ рдХреЛрдиреЗ рд╣реИрдВред рд╣рдо рдХрд┐рдирд╛рд░реЗ рдХреА рджрд┐рд╢рд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐
v0 рд╢реБрд░реБрдЖрдд рд╣реЛ,
v1 рдЕрдВрдд рд╣реЛред рдЕрдм, рдпрджрд┐ рддреНрд░рд┐рднреБрдЬ рдХреЗ рдХрд┐рдирд╛рд░реЛрдВ рдХреА рджрд┐рд╢рд╛ рдЗрд╕рдХреЗ рд╢реАрд░реНрд╖ рд░реЗрдЦрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реЗрдЦрдг рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ, рддреЛ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рдХрд┐рд╕реА рднреА рдмрд╛рд╣рд░реА рд╕рдореЛрдЪреНрдЪ рдореЗрдВ рдШрдбрд╝реА рдпрд╛ рд╡рд╛рдорд╛рд╡рд░реНрдд рдпрд╛ рддреЛ рдХрд┐рд╕реА рднреА рд╡рд┐рдкрд░реАрдд рджрд┐рд╢рд╛ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдХрд┐рд╕реА рднреА рдЖрдВрддрд░рд┐рдХ рд╕рдореЛрдЪреНрдЪ рдХреЛ рдЙрд▓реНрдЯрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдордиреЗ
CustomMesh рдФрд░
рддреНрд░рд┐рднреБрдЬ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рддрд╛рдХрд┐ рд╕рднреА рддреНрд░рд┐рднреБрдЬреЛрдВ рдХреЗ рд╡рд░реНрдЯреАрдХрд▓ рдХрд╛ рдШреБрдорд╛рд╡ рдШрдбрд╝реА рдХреА рджрд┐рд╢рд╛ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реЛред


рд╕рдореЛрдЪреНрдЪ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рдиреЗ рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рд╣реЛрдиреЗ рдкрд░, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкрд╕рд▓реА рдХрд╛ рдХреМрди рд╕рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╕рдореЛрдЪреНрдЪ рдХрд╛ рдЖрдВрддрд░рд┐рдХ рднрд╛рдЧ рд╣реИ, рдФрд░ рдЬреЛ рдмрд╛рд╣рд░реА рд╣реИред рдЗрд╕ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рджреАрд╡рд╛рд░ рдХреЗ рдЙрдиреНрдореБрдЦреАрдХрд░рдг рдХрд╛ рдЪрдпрди рдХрд░реЗрдВрдЧреЗред рдЖрдЬреНрдЮрд╛ рджреЗрдирд╛ (
v0, v1 ) рд╡рд╣ рдХрд┐рдирд╛рд░рд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд╛рдВрдЫрд┐рдд рд╕рдорд╛рдВрддрд░рд▓реЛрдЧреНрд░рд╛рдо рдЙрддреНрдкрдиреНрди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдСрдлрд╝рд╕реЗрдЯ рдкрджреЛрдВ
v0 рдФрд░
v1 рдХреЗ рд░реВрдк рдореЗрдВ рджреЛ рдЕрдВрдХ
v2 рдФрд░
v3 рд▓реЗрддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рджреЛ рддреНрд░рд┐рдХреЛрдг рдмрдирд╛рддреЗ рд╣реИрдВ:

рдФрд░ рдЗрд╕рд▓рд┐рдП рд╕рдореЛрдЪреНрдЪ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдХрд┐рдирд╛рд░реЗ рдХреЗ рд▓рд┐рдПред
рдХрд┐рдирд╛рд░реЛрдВ рдХреА рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджреАрд╡рд╛рд░реЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ public class CustomMesh { тАж private void ExtrudeEdgesSet(Edge[] edges, Vector3 offset) { if (offset == Vector3.zero || edges == null || edges.Length == 0) return; var initVerticesLength = vertices.Length; Array.Resize(ref vertices, initVerticesLength + edges.Length * 4); if (normals != null && normals.Length == initVerticesLength) { Array.Resize(ref normals, vertices.Length); } if (uv0 != null && uv0.Length == initVerticesLength) { Array.Resize(ref uv0, vertices.Length); } if (uv2 != null && uv2.Length == initVerticesLength) { Array.Resize(ref uv2, vertices.Length); } if (colors != null && colors.Length == initVerticesLength) { Array.Resize(ref colors, vertices.Length); } var initTrianglesLength = Triangles.Length; Array.Resize(ref Triangles, initTrianglesLength + edges.Length * 2); edges .AsParallel() .Select((edge, i) => { int j = initVerticesLength + i * 4; vertices[j] = edge.v0.position; vertices[j + 1] = edge.v1.position; vertices[j + 2] = edge.v0.position + offset; vertices[j + 3] = edge.v1.position + offset; if (normals != null && normals.Length == vertices.Length) { var normal = Vector3.Cross(vertices[j + 1] - vertices[j], offset); normals[j] = normals[j + 1] = normals[j + 2] = normals[j + 3] = normal; } if (uv0 != null && uv0.Length == vertices.Length) { uv0[j] = uv0[j + 2] = edge.v0.uv0; uv0[j + 1] = uv0[j + 3] = edge.v1.uv0; } if (uv2 != null && uv2.Length == vertices.Length) { uv2[j] = uv2[j + 2] = edge.v0.uv2; uv2[j + 1] = uv2[j + 3] = edge.v1.uv2; } if (colors != null && colors.Length == vertices.Length) { colors[j] = colors[j + 2] = edge.v0.color; colors[j + 1] = colors[j + 3] = edge.v1.color; } Triangles[initTrianglesLength + i * 2] = new Triangle( initTrianglesLength + i * 2, Id, j, j + 1, j + 2 ); Triangles[initTrianglesLength + i * 2 + 1] = new Triangle( initTrianglesLength + i * 2 + 1, Id, j + 3, j + 2, j + 1 ); return true; }).ToArray(); } }
рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рдЙрддреНрдкрдиреНрди рджреАрд╡рд╛рд░реЛрдВ рдХреЗ рд╕рд╛рдордиреЗ рдХреА рдУрд░ рд╕реНрд▓рд╛рдЗрдб рдФрд░ рдЧрдбреНрдвреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╣реЛрдЧреАред рдХреЗрд╡рд▓ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реАрдорд╛ рд╣реИ: рддреНрд░рд┐рдХреЛрдг рдХрд╛ рд╕реЗрдЯ, рдЬрд┐рд╕ рдкрд░
рдПрдХреНрд╕рдЯреНрд░реВрдб рдСрдкрд░реЗрд╢рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рд╕реНрд╡рдпрдВ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рд▓рдкреЗрдЯрд╛ рдирд╣реАрдВ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдмрд╣реБрднреБрдЬ рдХрд╛ рдПрдХ рд╕рдмрд╕реЗрдЯ рдЬреЛ рдСрдлрд╕реЗрдЯ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдЕрдорд╛рдиреНрдп рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдПрдХреНрд╕рдЯреНрд░реВрдб рдХреЗ рд╕рд╛рде рдмреНрд▓реЗрдВрдбрд░ рдореЗрдВ рднреА, рдЬреНрдпрд╛рдорд┐рддрд┐ рд╡рдХреНрд░ рд╕реЗ рдмрдЪрдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдмрд╣реБрднреБрдЬ рдХреЗ рдорд╛рдиреНрдп рд╕рдмрд╕реЗрдЯрджреАрд╡рд╛рд░ рддреИрдпрд╛рд░ рд╣реИ, рдпрд╣ рддреНрд░рд┐рдХреЛрдгреЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рдЗрд╕ рдЪрд░рдг рдХреЛ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмреЛрдЭрд┐рд▓ рд╣реЛ рдЧрдпрд╛ред
рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рд╢реАрд░реНрд╖ рдХреЗрд╡рд▓ рдЙрд╕рдХреЗ рддреНрд░рд┐рдХреЛрдг рдХреЗ рд╣реИрдВред рдпрджрд┐ рд╢рд░реНрдд рдкреВрд░реА рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рддреЛ рдХреБрдЫ рдкрдбрд╝реЛрд╕реА рдмрд╣реБрднреБрдЬ рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд▓рд┐рдП рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдкреНрд░рддреНрдпреЗрдХ рд╢реАрд░реНрд╖ рдХреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдХреНрд▓рд╕реНрдЯрд░ рдФрд░ рдмрд╛рдХреА рдореЙрдбрд▓ рджреЛрдиреЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдлрд┐рд░, рдХреНрд▓рд╕реНрдЯрд░ рдореЗрдВ рд╕рднреА рдмрд╣реБрднреБрдЬреЛрдВ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рд╢реАрд░реНрд╖ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рдмрджрд▓реЗрдВред рдЬрдм рд╕реНрдерд┐рддрд┐ рд╕рдВрддреБрд╖реНрдЯ рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рд╣рдо рдХреНрд▓рд╕реНрдЯрд░ рдХреЗ рд╕рднреА рдХреЛрдиреЗ рдХреЛ рдЧрддрд┐ рд╡реЗрдХреНрдЯрд░ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рдмрд╣реБрднреБрдЬ рдХреЗ рдПрдХ рдХреНрд▓рд╕реНрдЯрд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ public class CustomMesh { тАж private void TranslateTrianglesHard(int[] triIndices, Vector3 offset, int[] hullVerts) { var newVertexIndices = new Dictionary<int, int>(); var initVerticesCount = vertices.Length; Triangles.Where((t, i) => !triIndices.Contains(i)).Select(t => { if (hullVerts.Contains(t.V0.Index) && !newVertexIndices.ContainsKey(t.V0.Index)) newVertexIndices.Add(t.V0.Index, initVerticesCount + newVertexIndices.Count); if (hullVerts.Contains(t.V1.Index) && !newVertexIndices.ContainsKey(t.V1.Index)) newVertexIndices.Add(t.V1.Index, initVerticesCount + newVertexIndices.Count); if (hullVerts.Contains(t.V2.Index) && !newVertexIndices.ContainsKey(t.V2.Index)) newVertexIndices.Add(t.V2.Index, initVerticesCount + newVertexIndices.Count); return false; }).ToArray(); Array.Resize(ref vertices, initVerticesCount + newVertexIndices.Count); foreach (var pair in newVertexIndices) vertices[pair.Value] = vertices[pair.Key] + offset; if (normals != null && normals.Length == initVerticesCount) { Array.Resize(ref normals, vertices.Length); foreach (var pair in newVertexIndices) normals[pair.Value] = normals[pair.Key]; } if (uv0 != null && uv0.Length == initVerticesCount) { Array.Resize(ref uv0, vertices.Length); foreach (var pair in newVertexIndices) uv0[pair.Value] = uv0[pair.Key]; } if (uv2 != null && uv2.Length == initVerticesCount) { Array.Resize(ref uv2, vertices.Length); foreach (var pair in newVertexIndices) uv2[pair.Value] = uv2[pair.Key]; } if (colors != null && colors.Length == initVerticesCount) { Array.Resize(ref colors, vertices.Length); foreach (var pair in newVertexIndices) colors[pair.Value] = colors[pair.Key]; } var alreadyMoved = new HashSet<int>(); for (var i = 0; i < triIndices.Length; i++) { if (newVertexIndices.ContainsKey(Triangles[triIndices[i]].V0.Index)) { var index = newVertexIndices[Triangles[triIndices[i]].V0.Index]; Triangles[triIndices[i]].Edges[0].v0.Index = index; Triangles[triIndices[i]].Edges[2].v1.Index = index; } else if (!alreadyMoved.Contains(Triangles[triIndices[i]].V0.Index)) { vertices[Triangles[triIndices[i]].V0.Index] += offset; alreadyMoved.Add(Triangles[triIndices[i]].V0.Index); } if (newVertexIndices.ContainsKey(Triangles[triIndices[i]].V1.Index)) { var index = newVertexIndices[Triangles[triIndices[i]].V1.Index]; Triangles[triIndices[i]].Edges[0].v1.Index = index; Triangles[triIndices[i]].Edges[1].v0.Index = index; } else if (!alreadyMoved.Contains(Triangles[triIndices[i]].V1.Index)) { vertices[Triangles[triIndices[i]].V1.Index] += offset; alreadyMoved.Add(Triangles[triIndices[i]].V1.Index); } if (newVertexIndices.ContainsKey(Triangles[triIndices[i]].V2.Index)) { var index = newVertexIndices[Triangles[triIndices[i]].V2.Index]; Triangles[triIndices[i]].Edges[1].v1.Index = index; Triangles[triIndices[i]].Edges[2].v0.Index = index; } else if (!alreadyMoved.Contains(Triangles[triIndices[i]].V2.Index)) { vertices[Triangles[triIndices[i]].V2.Index] += offset; alreadyMoved.Add(Triangles[triIndices[i]].V2.Index); } } } }
рд╣реЛ рдЧрдпрд╛ред рдЕрдм, рд╕рднреА рдЪрд░рдгреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реБрдП, рд╣рдореЗрдВ рдПрдХ рдЫреЗрдж рдпрд╛ рдПрдХ рдкрд╣рд╛рдбрд╝реА рдорд┐рд▓рддреА рд╣реИред
рдПрдХреНрд╕рдЯреНрд░реВрдб рдСрдкрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЕрдВрддрд┐рдо рд╡рд┐рдзрд┐ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдирд╛ public class CustomMesh { тАж public void ExtrudeTriangles(int[] triIndices, Vector3 offset) { var edges = ObtainHullEdges(triIndices); ExtrudeEdgesSet(edges.ToArray(), offset); var hullVertices = edges.Select(edge => edge.v0.Index).ToArray(); TranslateTrianglesHard(triIndices, offset, hullVertices); } }
рдмрдирд╛рд╡рдЯ рд╕реНрдХреИрди рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдФрд░ рд╕рдореЛрдЪреНрдЪ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рд╡рд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрд╡рдХрд╛рд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

рдФрд░ рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИ
рдКрдкрд░ рдЪрд░реНрдЪрд╛ рдХрд┐рдП рдЧрдП рд╕рдВрдкрд╛рджрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдореЙрдбрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХреЛрдВ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ рджреЛ
CustomMesh рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
Combine () рд╡рд┐рдзрд┐ рд▓рд┐рдЦреА рд╣реИред рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░
UnityEngine.Mesh.CombineMeshes () рдХреЗ рдмреАрдЪ рдХрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдореЗрд╖реЛрдВ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рджреМрд░рд╛рди рдХреБрдЫ рдХреЛрдиреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмрд░рд╛рдмрд░ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЬреНрдпрд╛рдорд┐рддрд┐ рд╕реЗ рдмрдЪрддреЗ рд╣реИрдВред
рдЙрд╕реА рдореЙрдбреНрдпреВрд▓ рдореЗрдВ, рд╣рдордиреЗ
Delaunay рд╡рд┐рдорд╛рди рддреНрд░рд┐рдХреЛрдгреАрдп рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд▓рд╛рдЧреВ
рдХрд┐рдпрд╛ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдкрд╛рдиреА рдХреЗ рдмрдирд╛рд╡рдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдлреНрд▓реИрдЯ рдврдХреНрдХрди рдХреЗ рд╕рд╛рде
рдПрдХреНрд╕рдЯреНрд░реВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рдмрдбрд╝рд╛ рдЫреЗрдж рдмрдВрдж рдХрд░реЗрдВ рдФрд░ рдПрдХ рдЭреАрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:

рдЦреИрд░, рдЗрд╕реЗ рд╕реБрд▓рдЭрд╛ рд▓рд┐рдпрд╛! рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ
.fbx рдХреЛ
рдПрдХрддрд╛ рдореЗрдВ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдФрд░ рдореЙрдбрд▓ рд╕рддреНрдпрд╛рдкрди рдХреЗ рддрд░реАрдХреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
рдПрдХ рдирд╛рд╢реНрддреЗ рдХреЗ рд▓рд┐рдП (рд╕рд┐рд░реНрдл рд▓реБрд▓рдЬрд╝ рдХреЗ рд▓рд┐рдП)