예제 #1
0
    void Start()
    {
        _filter        = GetComponent <MeshFilter>();
        _draft         = GenerateMesh();
        _draftOriginal = new MeshDraft(_draft.ToMesh());
        _filter.mesh   = _draft.ToMesh();

        InvokeRepeating("ToggleNoise", noiseSpeed, noiseSpeed);
    }
예제 #2
0
 public static void AssignDraftToMeshFilter(MeshDraft draft, MeshFilter meshFilter, ref Mesh mesh)
 {
     if (mesh == null)
     {
         mesh = draft.ToMesh();
     }
     else
     {
         draft.ToMesh(ref mesh);
     }
     meshFilter.sharedMesh = mesh;
 }
 protected static void AssignDraftToMeshFilter(MeshDraft draft, MeshFilter meshFilter, ref Mesh mesh)
 {
     if (mesh == null)
     {
         mesh = draft.ToMesh();
     }
     else
     {
         draft.ToMesh(ref mesh);
     }
     mesh.RecalculateBounds();
     meshFilter.sharedMesh = mesh;
 }
예제 #4
0
    void MoveVerts(Vector3 position)
    {
        draft = new MeshDraft(draft.ToMesh());

        //draft.Move(new Vector3(0, 0, val));



        int vertexCount = draft.vertices.Count;

        //Vector3[] verts = new Vector3[vertexCount];

        List <Vector3> verts = new List <Vector3>();

        for (int i = 0; i < vertexCount; i++)
        {
            Vector3 vertex = draftOrig.vertices[i];
            vertex += position;
            verts.Add(vertex);
        }

        draft.vertices          = verts;
        myMeshFilter.sharedMesh = draft.ToMesh();

        //myMeshFilter.sharedMesh.SetVertices(verts);
        //myMeshFilter.sharedMesh.UploadMeshData(false);
    }
예제 #5
0
        private void Awake()
        {
            template = MeshE.TetrahedronDraft(0.3f);

            swarmCount = Mathf.Min(65000/template.vertices.Count, swarmCount);
            simulationUpdate = Mathf.RoundToInt(swarmCount*simulationPercent);
            var vertexCount = swarmCount*template.vertices.Count;

            draft = new MeshDraft
            {
                name = "Boids",
                vertices = new List<Vector3>(vertexCount),
                triangles = new List<int>(vertexCount),
                normals = new List<Vector3>(vertexCount),
                uv = new List<Vector2>(vertexCount),
                colors = new List<Color>(vertexCount)
            };
            for (var i = 0; i < swarmCount; i++)
            {
                boids.Add(new Boid());
                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            GetComponent<MeshFilter>().mesh = mesh;

            Generate();

            StartCoroutine(Simulate());
        }
예제 #6
0
        public BoidController(MeshFilter meshFilter)
        {
            template = MeshDraft.Tetrahedron(0.3f);

            // Avoid vertex count overflow
            swarmCount = Mathf.Min(65000 / template.vertices.Count, swarmCount);
            // Optimization trick: in each frame we simulate only small percent of all boids
            simulationUpdate = Mathf.RoundToInt(swarmCount * simulationPercent);
            int vertexCount = swarmCount * template.vertices.Count;

            draft = new MeshDraft
            {
                name      = "Boids",
                vertices  = new List <Vector3>(vertexCount),
                triangles = new List <int>(vertexCount),
                normals   = new List <Vector3>(vertexCount),
                uv        = new List <Vector2>(vertexCount),
                colors    = new List <Color>(vertexCount)
            };
            for (var i = 0; i < swarmCount; i++)
            {
                boids.Add(new Boid());
                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            meshFilter.mesh = mesh;
        }
예제 #7
0
        private void Awake()
        {
            template = MeshE.TetrahedronDraft(0.3f);

            swarmCount       = Mathf.Min(65000 / template.vertices.Count, swarmCount);
            simulationUpdate = Mathf.RoundToInt(swarmCount * simulationPercent);
            var vertexCount = swarmCount * template.vertices.Count;

            draft = new MeshDraft
            {
                name      = "Boids",
                vertices  = new List <Vector3>(vertexCount),
                triangles = new List <int>(vertexCount),
                normals   = new List <Vector3>(vertexCount),
                uv        = new List <Vector2>(vertexCount),
                colors    = new List <Color>(vertexCount)
            };
            for (var i = 0; i < swarmCount; i++)
            {
                boids.Add(new Boid());
                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            GetComponent <MeshFilter>().mesh = mesh;

            Generate();

            StartCoroutine(Simulate());
        }
예제 #8
0
    MeshDraft AddNoiseToDraft()
    {
        MeshDraft draft       = new MeshDraft(_draftOriginal.ToMesh());
        var       noiseOffset = new Vector2(Random.Range(0f, 100f), Random.Range(0f, 100f));

        for (int i = 0; i < draft.triangles.Count; i++)
        {
            // Calculate noise value
            int     v1     = draft.triangles[i];
            Vector3 vertex = draft.vertices[v1];
            float   x      = vertex.x + (Random.Range(-noiseScale, noiseScale));
            float   y      = vertex.y + (Random.Range(-noiseScale, noiseScale));
            float   z      = vertex.z + (Random.Range(-noiseScale, noiseScale));
            draft.vertices[i] = new Vector3(x, y, z);
        }
        return(draft);
    }
예제 #9
0
 void ToggleNoise()
 {
     if (viewingOriginal)
     {
         _draft       = AddNoiseToDraft();
         _filter.mesh = _draft.ToMesh();
     }
     else
     {
         _filter.mesh = _draftOriginal.ToMesh();
     }
     viewingOriginal = !viewingOriginal;
 }
예제 #10
0
        /// <summary>
        /// Generate new colors and positions for boids
        /// </summary>
        public Mesh Generate(Color colorA, Color colorB)
        {
            template = MeshDraft.Tetrahedron(0.3f);

            // Avoid vertex count overflow
            swarmCount = Mathf.Min(65000 / template.vertices.Count, swarmCount);
            // Optimization trick: in each frame we simulate only small percent of all boids
            maxSimulationSteps = Mathf.RoundToInt(swarmCount * simulationPercent);
            // int vertexCount = swarmCount*template.vertices.Count;

            // Paint template in random color
            template.colors.Clear();
            // Assuming that we are dealing with tetrahedron, first vertex should be boid's "nose"
            template.colors.Add(colorA);
            for (int i = 1; i < template.vertices.Count; i++)
            {
                template.colors.Add(Tile.Lighten(colorB, i * 0.1f));
            }

            draft = new MeshDraft
            {
                name      = "Boids",
                vertices  = new List <Vector3>(),
                triangles = new List <int>(),
                normals   = new List <Vector3>(),
                uv        = new List <Vector2>(),
                colors    = new List <Color>()
            };

            for (var i = 0; i < swarmCount; i++)
            {
                // Assign random starting values for each boid
                var boid = new Boid
                {
                    position = Random.onUnitSphere * worldSphere,
                    rotation = Random.rotation,
                    velocity = Random.onUnitSphere * maxSpeed
                };
                boid.position.y = Mathf.Abs(boid.position.y);
                boid.velocity.y = Mathf.Abs(boid.velocity.y);
                boids.Add(boid);

                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();

            return(mesh);
        }
    public void Generate()
    {
        meshFilter = GetComponent <MeshFilter>();

        MeshDraft draft = TerrainDraft(TerrainSize, CellSize, NoiseOffset, NoiseScale, Gradient);

        draft.Move(Vector3.left * TerrainSize.x / 2 + Vector3.back * TerrainSize.z / 2);
        meshFilter.mesh = draft.ToMesh();

        MeshCollider meshCollider = GetComponent <MeshCollider>();

        if (meshCollider)
        {
            meshCollider.sharedMesh = meshFilter.mesh;
        }
    }
예제 #12
0
    /// <summary>
    /// Convert the draft to a mesh and assign it to the tile's MeshFilter component.
    /// </summary>
    private void DraftToMesh()
    {
        // Move the center of the vertices to the center of the tile
        draft.Move(Vector3.left * TerrainController.TerrainSize.x / 2 + Vector3.back * TerrainController.TerrainSize.z / 2);

        meshFilter.mesh = draft.ToMesh();

        meshCollider.sharedMesh = meshFilter.mesh;

        meshRenderer.enabled = true;

        // Start generating points for asset placement
        // now that we know where each biome is (BiomeEdges, YEdgesPerXStep and XEdgesPerYStep)
        if (assetPlacement)
        {
            assetPlacement.GenerateSpawnPoints();
        }
    }
예제 #13
0
        private void Generate()
        {
            gradient = RandomE.gradientHSV;

            var noiseOffset = new Vector2(Random.Range(0f, 100f), Random.Range(0f, 100f));

            draft.colors.Clear();
            for (int i = 0; i < draft.vertices.Count; i++)
            {
                var vertex = draft.vertices[i];
                var x      = scale * vertex.x / xSegments + noiseOffset.x;
                var y      = scale * vertex.z / zSegments + noiseOffset.y;
                var noise  = Mathf.PerlinNoise(x, y);
                draft.vertices[i] = new Vector3(vertex.x, noise, vertex.z);
                draft.colors.Add(gradient.Evaluate(noise));
            }

            GetComponent <MeshFilter>().mesh = draft.ToMesh();
        }
예제 #14
0
        public static void SetModel(UnityEngine.GameObject obj, VOX.Model model, Texture2D customTexture = null, bool enableGrid = false)
        {
            var mr = obj.GetComponent <MeshRenderer>();

            if (mr == null)
            {
                mr = obj.AddComponent <MeshRenderer>();
            }

            var mf = obj.GetComponent <MeshFilter>();

            if (mf == null)
            {
                mf = obj.AddComponent <MeshFilter>();
            }

            var       texture = customTexture != null ? customTexture : VOX.Texture.FromModel(model, 1, true);
            MeshDraft mesh    = VOX.Mesh.FromModel(model);

            mr.sharedMaterial = new UnityEngine.Material(Shader.Find("Standard"));
            mr.sharedMaterial.SetTexture("_MainTex", texture);

            if (enableGrid)
            {
                var hlines = Resources.Load("hlines_tr") as UnityEngine.Texture;
                mr.sharedMaterial.SetTexture("_DetailAlbedoMap", hlines);
                mr.sharedMaterial.SetTextureScale("_DetailAlbedoMap", new Vector2(16f, 16f));
                mr.sharedMaterial.EnableKeyword("_DETAIL_MULX2");
                mr.sharedMaterial.SetColor("_Color", new Color(0.5f, 0.5f, 0.5f)); // To lower brightness of additional hlines texture
            }
            else
            {
                mr.sharedMaterial.DisableKeyword("_DETAIL_MULX2");
                mr.sharedMaterial.SetTexture("_DetailAlbedoMap", null);
                mr.sharedMaterial.SetColor("_Color", Color.white);
            }
            mr.sharedMaterial.EnableKeyword("_SPECULARHIGHLIGHTS_OFF");
            mr.sharedMaterial.SetFloat("_SpecularHighlights", 0f);
            mf.sharedMesh = mesh.ToMesh();
            mf.sharedMesh.RecalculateNormals();
        }
        /// <summary>
        /// Generate new colors and positions for boids
        /// </summary>
        public Mesh Generate(Config config)
        {
            this.config = config;

            // Avoid vertex count overflow
            config.swarmCount = Mathf.Min(65000 / config.template.vertexCount, config.swarmCount);
            // Optimization trick: in each frame we simulate only small percent of all boids
            maxSimulationSteps = Mathf.RoundToInt(config.swarmCount * config.simulationPercent);
            int vertexCount = config.swarmCount * config.template.vertexCount;

            draft = new MeshDraft
            {
                name      = "Boids",
                vertices  = new List <Vector3>(vertexCount),
                triangles = new List <int>(vertexCount),
                normals   = new List <Vector3>(vertexCount),
                uv        = new List <Vector2>(vertexCount),
                colors    = new List <Color>(vertexCount)
            };

            for (var i = 0; i < config.swarmCount; i++)
            {
                // Assign random starting values for each boid
                var boid = new Boid
                {
                    position = Random.insideUnitSphere * config.spawnSphere,
                    rotation = Random.rotation,
                    velocity = Random.onUnitSphere * config.maxSpeed
                };
                boids.Add(boid);

                draft.Add(config.template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            // Set bounds manually for correct culling
            mesh.bounds = new Bounds(Vector3.zero, Vector3.one * config.worldSphere * 2);
            return(mesh);
        }
예제 #16
0
        /// <summary>
        /// Generate new colors and positions for boids
        /// </summary>
        public Mesh Generate()
        {
            template = MeshDraft.Tetrahedron(0.3f);

            // Avoid vertex count overflow
            swarmCount = Mathf.Min(65000/template.vertices.Count, swarmCount);
            // Optimization trick: in each frame we simulate only small percent of all boids
            maxSimulationSteps = Mathf.RoundToInt(swarmCount*simulationPercent);
            int vertexCount = swarmCount*template.vertices.Count;

            // Paint template in random color
            template.colors.Clear();
            var color = RandomE.colorHSV;
            // Assuming that we are dealing with tetrahedron, first vertex should be boid's "nose"
            template.colors.Add(color.Inverted());
            for (int i = 1; i < template.vertices.Count; i++)
            {
                template.colors.Add(color);
            }

            draft = new MeshDraft
            {
                name = "Boids",
                vertices = new List<Vector3>(vertexCount),
                triangles = new List<int>(vertexCount),
                normals = new List<Vector3>(vertexCount),
                uv = new List<Vector2>(vertexCount),
                colors = new List<Color>(vertexCount)
            };

            for (var i = 0; i < swarmCount; i++)
            {
                // Assign random starting values for each boid
                var boid = new Boid
                {
                    position = Random.insideUnitSphere*spawnSphere,
                    rotation = Random.rotation,
                    velocity = Random.onUnitSphere*maxSpeed
                };
                boids.Add(boid);

                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            return mesh;
        }
예제 #17
0
    public void GetMesh(SocketIOEvent e)
    {
        GameObject[] receivedMeshes = GameObject.FindGameObjectsWithTag("ReceivedMesh");

        List <JSONObject> meshDatas = e.data.GetField("meshes").list;

        for (int n = 0; n < meshDatas.Count; n++)
        //foreach (JSONObject meshData in e.data.GetField("meshes").list)
        {
            JSONObject meshData = meshDatas[n];
            byte[]     data     = Convert.FromBase64String(meshData.str);

            var customMesh = ZeroFormatterSerializer.Deserialize <CustomMesh>(data);

            //print("verts: " + customMesh.vertices.Count);

            List <Vector3> vertices = new List <Vector3>();
            if (vertices != null)
            {
                for (int i = 0; i < customMesh.vertices.Count; i++)
                {
                    vertices.Add(new Vector3(customMesh.vertices[i][0], customMesh.vertices[i][1], customMesh.vertices[i][2]));
                }
            }


            List <int> triangles = new List <int>();
            if (customMesh.faces != null)
            {
                for (int i = 0; i < customMesh.faces.Count; i++)
                {
                    if (customMesh.faces[i][0] == 0)
                    {
                        triangles.Add(customMesh.faces[i][1]);
                        triangles.Add(customMesh.faces[i][2]);
                        triangles.Add(customMesh.faces[i][3]);
                    }
                    else if (customMesh.faces[i][0] == 1)
                    {
                        triangles.Add(customMesh.faces[i][1]);
                        triangles.Add(customMesh.faces[i][2]);
                        triangles.Add(customMesh.faces[i][3]);

                        triangles.Add(customMesh.faces[i][1]);
                        triangles.Add(customMesh.faces[i][3]);
                        triangles.Add(customMesh.faces[i][4]);
                    }
                }
            }

            List <Vector2> uvs = new List <Vector2>();
            if (customMesh.uvs != null)
            {
                for (int i = 0; i < customMesh.uvs.Count; i++)
                {
                    uvs.Add(new Vector2(customMesh.uvs[i][0], customMesh.uvs[i][1]));
                }
            }

            List <Vector3> normals = new List <Vector3>();
            if (customMesh.normals != null)
            {
                for (int i = 0; i < customMesh.normals.Count; i++)
                {
                    normals.Add(new Vector3(customMesh.normals[i][0], customMesh.normals[i][1], customMesh.normals[i][2]));
                }
            }

            MeshDraft meshDraft = new MeshDraft();
            meshDraft.vertices  = vertices;
            meshDraft.triangles = triangles;
            meshDraft.uv        = uvs;
            meshDraft.normals   = normals;

            if (n + 1 >= receivedMeshes.Length)
            {
                GameObject receivedMeshInstance = (GameObject)Instantiate(receivedMeshPrefab);
                receivedMeshInstance.GetComponent <MeshFilter>().mesh = meshDraft.ToMesh();
            }
            else
            {
                receivedMeshes[n].GetComponent <MeshFilter>().mesh = meshDraft.ToMesh();
            }
        }

        if (receivedMeshes.Length > meshDatas.Count)
        {
            for (int i = meshDatas.Count; i < receivedMeshes.Length; i++)
            {
                Destroy(receivedMeshes[i]);
            }

            Resources.UnloadUnusedAssets();
        }
    }
예제 #18
0
    // private IEnumerator BeepBoop()
    // {
    //  // wait 1 seconds and continue
    //  yield return new WaitForSeconds(1);

    //  socket.Emit("beep");

    //  // wait 3 seconds and continue
    //  yield return new WaitForSeconds(3);

    //  socket.Emit("beep");

    //  // wait 2 seconds and continue
    //  yield return new WaitForSeconds(2);

    //  socket.Emit("beep");

    //  // wait ONE FRAME and continue
    //  yield return null;

    //  socket.Emit("beep");
    //  socket.Emit("beep");
    // }

    // public void TestOpen(SocketIOEvent e)
    // {
    //  Debug.Log("[SocketIO] Open received: " + e.name + " " + e.data);
    // }

    // public void TestBoop(SocketIOEvent e)
    // {
    //  Debug.Log("[SocketIO] Boop received: " + e.name + " " + e.data);

    //  if (e.data == null) { return; }

    //  Debug.Log(
    //      "#####################################################" +
    //      "THIS: " + e.data.GetField("this").str +
    //      "#####################################################"
    //  );
    // }

    // public void TestError(SocketIOEvent e)
    // {
    //  Debug.Log("[SocketIO] Error received: " + e.name + " " + e.data);
    // }

    // public void TestClose(SocketIOEvent e)
    // {
    //  Debug.Log("[SocketIO] Close received: " + e.name + " " + e.data);
    // }

    public void GetMesh(SocketIOEvent e)
    {
        print("data received");

        //print(e.data.GetField("mesh"));
        byte[] data = Convert.FromBase64String(e.data.GetField("mesh").str);

        //print(data.Length);

        var customMesh = ZeroFormatterSerializer.Deserialize <CustomMesh>(data);

        // print(customMesh.GetType());
        print("verts: " + customMesh.vertices.Count);

        List <Vector3> vertices = new List <Vector3> ();

        if (vertices != null)
        {
            for (int i = 0; i < customMesh.vertices.Count; i++)
            {
                //CustomVector3d cv = customMesh.vertices [i];
                vertices.Add(new Vector3(customMesh.vertices[i][0], customMesh.vertices[i][1], customMesh.vertices[i][2]));
            }
        }


        List <int> triangles = new List <int> ();

        if (customMesh.faces != null)
        {
            for (int i = 0; i < customMesh.faces.Count; i++)
            {
                if (customMesh.faces[i][0] == 0)
                {
                    triangles.Add(customMesh.faces[i][1]);
                    triangles.Add(customMesh.faces[i][2]);
                    triangles.Add(customMesh.faces[i][3]);
                }
                else if (customMesh.faces[i][0] == 1)
                {
                    triangles.Add(customMesh.faces[i][1]);
                    triangles.Add(customMesh.faces[i][2]);
                    triangles.Add(customMesh.faces[i][3]);

                    triangles.Add(customMesh.faces[i][1]);
                    triangles.Add(customMesh.faces[i][3]);
                    triangles.Add(customMesh.faces[i][4]);
                }
            }
        }

        List <Vector2> uvs = new List <Vector2>();

        if (customMesh.uvs != null)
        {
            for (int i = 0; i < customMesh.uvs.Count; i++)
            {
                uvs.Add(new Vector2(customMesh.uvs[i][0], customMesh.uvs[i][1]));
            }
        }

        List <Vector3> normals = new List <Vector3>();

        if (customMesh.normals != null)
        {
            for (int i = 0; i < customMesh.normals.Count; i++)
            {
                normals.Add(new Vector3(customMesh.normals[i][0], customMesh.normals[i][1], customMesh.normals[i][2]));
            }
        }


        MeshDraft meshDraft = new MeshDraft();

        meshDraft.vertices  = vertices;
        meshDraft.triangles = triangles;
        meshDraft.uv        = uvs;
        meshDraft.normals   = normals;

        GetComponent <MeshFilter>().mesh = meshDraft.ToMesh();

        //CustomMesh customMesh = new CustomMesh();

        // print(customMesh.ToString());
        //var d = ZeroFormatterSerializer.Serialize(customMesh);
        //var dd = ZeroFormatterSerializer.Deserialize<CustomMesh>(d);
    }
예제 #19
0
        void Start()
        {
            if (baseMesh == null)
            {
                baseMesh = GetComponent <MeshFilter>().sharedMesh;
            }

#if UNITY_EDITOR
            var cam = Camera.current;
            if (cam == null || Application.isPlaying)
            {
                cam = Camera.main;
            }
#else
            var cam = Camera.main;
#endif

            var draft = new MeshDraft();

            var rand = new System.Random(0);

            // expend the number of triangles
            var triangles = baseMesh.Triangles();

            var dist      = Vector3.Distance(cam.transform.position, transform.position);
            var lod       = (1f - ((Mathf.Clamp(dist, minDist, maxDist)) - minDist) / (maxDist - minDist));
            var numSplits = lod * maxSplits;
            var height    = lod * maxHeight;

#if DEBUG
            Debug.Log(dist + " : " + numSplits);
#endif

            for (int i = 0; i < numSplits; i++)
            {
                var tmpTriangles = new List <(Vector3 a, Vector3 b, Vector3 c)>();

                foreach (var tri in triangles)
                {
                    var(middle, oposite, first, second) = tri.MiddleLargestSide();
                    tmpTriangles.Add((oposite, first, middle));
                    tmpTriangles.Add((oposite, middle, second));
                }

                triangles = tmpTriangles.ToArray();
            }

            foreach (var tri in triangles)
            {
                var middle  = tri.Middle(((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()));
                var normal  = tri.Normal();
                var sideDir = (tri.Item1 - middle).normalized;
                var leanDir = MeshExension.Normal(sideDir, normal);

                var rot = Quaternion.RotateTowards(Quaternion.LookRotation(sideDir, normal), Quaternion.LookRotation(sideDir, normal), (float)rand.NextDouble());

                sideDir = rot * sideDir;
                leanDir = rot * leanDir;

                var a = middle + sideDir * (maxWidth + ((float)rand.NextDouble() - 0.5f) * randWidth);
                var b = middle - sideDir * (maxWidth + ((float)rand.NextDouble() - 0.5f) * randWidth);
                var c = middle + (normal + leanDir * (leanDist + ((float)rand.NextDouble() - 0.5f) * randLeanDist)).normalized * (maxHeight + ((float)rand.NextDouble() - 0.5f) * randHeight);

                //normal = MeshExension.Normal(a, b, c);
                //if (Vector3.Dot(normal, cam.transform.forward) < 0)
                //    normal = -normal;
                //normal = -Camera.main.transform.forward;
                //normal = (Camera.main.transform.position - middle).normalized;

                draft.AddTriangle(a, b, c, -leanDir, -leanDir, normal);
            }

            Grass = draft.ToMesh();
        }
예제 #20
0
        public BoidController(MeshFilter meshFilter)
        {
            template = MeshDraft.Tetrahedron(0.3f);

            // Avoid vertex count overflow
            swarmCount = Mathf.Min(65000/template.vertices.Count, swarmCount);
            // Optimization trick: in each frame we simulate only small percent of all boids
            simulationUpdate = Mathf.RoundToInt(swarmCount*simulationPercent);
            int vertexCount = swarmCount*template.vertices.Count;

            draft = new MeshDraft
            {
                name = "Boids",
                vertices = new List<Vector3>(vertexCount),
                triangles = new List<int>(vertexCount),
                normals = new List<Vector3>(vertexCount),
                uv = new List<Vector2>(vertexCount),
                colors = new List<Color>(vertexCount)
            };
            for (var i = 0; i < swarmCount; i++)
            {
                boids.Add(new Boid());
                draft.Add(template);
            }

            mesh = draft.ToMesh();
            mesh.MarkDynamic();
            meshFilter.mesh = mesh;
        }