コード例 #1
0
    public void GenerateCrystal()
    {
        //Debug.Log("Generating crystal");

        List <Vector3> vertices = new List <Vector3>();
        List <Vector3> normals  = new List <Vector3>();
        List <int>     tris     = new List <int>();

        for (int lobe = 0; lobe < numCrystals; lobe++)
        {
            // compute lobe parameters given randomness
            int   lobeNumCenters = Mathf.Max(1, (int)(numCenters - randomness * numCenters * NextRandomFloat));
            int   lobeNumSides   = Mathf.Max(MinNumSides, (int)(numCenters - randomness * numCenters * NextRandomFloat));
            float lobeScale      = 1f - 0.75f * randomness * NextRandomFloat; // limit maximum randomness on scale
            float lobeWidth      = lobeScale * crystalWidth * (1f - randomness + 2f * randomness * NextRandomFloat);
            float lobeLength     = lobeScale * crystalLength * (1f - randomness + 2f * randomness * NextRandomFloat);
            float maxRotation    = 2f * Mathf.PI / lobeNumSides;

            Vector3 lobeRoot = 0.25f * randomness * new Vector3(-1f + 2f * NextRandomFloat, 0, -1f + 2f * NextRandomFloat);

            //Debug.Log("Generating a crystal lobe " + lobe);

            Vector3    lobeDir  = Samplers.SampleRandomCosineHemisphere(NextRandomFloat, NextRandomFloat);
            Quaternion rotation = Quaternion.LookRotation(lobeDir);

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

            for (int j = 0; j < lobeNumCenters; j++)
            {
                float ratio = lobeNumCenters == 1 ? 0.5f: 1f * j / (lobeNumCenters - 1);

                Vector3 centerPos = lobeRoot + lobeLength * lobeDir * EvaluateDensityCurve(ratio);

                for (int side = 0; side < lobeNumSides; side++)
                {
                    float angle = maxRotation * side;

                    Vector3 sideDir = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle));
                    //todo rotate to crystalDir
                    Vector3 sidePos = centerPos + lobeWidth * sideDir * crystalSizeCurve.Evaluate(ratio);

                    //sidePos = rotation * sidePos;

                    sides.Add(sidePos);
                }
            }

            Vector3 crystalTop = lobeRoot + lobeLength * lobeDir;

            //Debug.Log("ROOT: " + lobeRoot);
            //Debug.Log("SIDES: " + sides.Count);
            //foreach (var v in sides)
            //    Debug.Log(v);
            //Debug.Log("TOP: " + crystalTop);

            int index, s1, s2, s3;
            // generate triangles for the sides
            for (int j = 0; j < lobeNumCenters - 1; j++)
            {
                for (int side = 0; side < lobeNumSides; side++)
                {
                    index = j * lobeNumSides + side;

                    s1 = index;
                    bool b = (side + 1) % lobeNumSides == 0;

                    // need to generate 2 triangles per side
                    for (int tri = 0; tri < 2; tri++)
                    {
                        if (tri == 0) // triangle 1
                        {
                            s2 = b ? index + lobeNumSides : index + lobeNumSides;
                            s3 = b ? index + 1 : index + lobeNumSides + 1;
                        }
                        else // triangle 2
                        {
                            s2 = b ? index + 1 : index + lobeNumSides + 1;
                            s3 = b ? index - lobeNumSides + 1 : index + 1;
                        }

                        //Debug.Log("Indices" + s1 + " " + s2 + " " + s3);

                        List <Vector3> verticesLocal = new List <Vector3>()
                        {
                            sides[s1], sides[s2], sides[s3]
                        };
                        MeshTriAdder.AddTriangle(new Vector3Int(0, 1, 2), verticesLocal, vertices, tris, false);
                    }
                }
            }

            bool    isBottom = true;
            Vector3 v1;
            // bottom and top triangles
            for (int c = 0; c < 2; c++)
            {
                if (isBottom)
                {
                    v1    = lobeRoot;
                    index = 0; // index is now used as an offset for the vertex indices
                }
                else
                {
                    v1    = crystalTop;
                    index = (lobeNumCenters - 1) * lobeNumSides;
                }

                for (int j = 0; j < lobeNumSides; j++)
                {
                    if (isBottom)
                    {
                        s2 = index + j;
                        s3 = (index + 1 + j) % lobeNumSides;
                    }
                    else
                    {
                        s2 = index + (1 + j) % lobeNumSides;
                        s3 = index + j;
                    }

                    List <Vector3> verticesLocal = new List <Vector3>()
                    {
                        v1, sides[s2], sides[s3]
                    };
                    MeshTriAdder.AddTriangle(new Vector3Int(0, 1, 2), verticesLocal, vertices, tris, false);
                }

                isBottom = false;
            }
        }

        Mesh mesh = new Mesh();

        mesh.Clear();
        mesh.subMeshCount = 2;

        mesh.SetVertices(vertices);

        mesh.SetTriangles(tris.ToArray(), 0);

        Vector2[] uvs = Unwrapping.GeneratePerTriangleUV(mesh);
        mesh.SetUVs(0, new List <Vector2>(uvs));

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        // assign back to meshFilter
        MeshFilter meshFilter = GetComponent <MeshFilter>();

        //mesh.Optimize();

        meshFilter.mesh = mesh;
    }
コード例 #2
0
        public override void InitializeMesh(Region region)
        {
            Debug.Log("Initializing region Mesh...");

            // compute mesh parameters
            Dictionary <Vector3, int> verticesDict = new Dictionary <Vector3, int>();
            List <Vector3>            normals      = new List <Vector3>();

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

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

            // copy vertice vectors
            Tile[,] tiles = region.GetTiles();

            Dictionary <string, bool> trisDict = new Dictionary <string, bool>();

            float yTotal    = 0;
            int   trisCount = 0;
            int   length    = tiles.GetLength(0);

            for (int i = 0; i < length; i++)
            {
                for (int j = 0; j < length; j++)
                {
                    if (tiles[i, j] != null)
                    {
                        // add 2 triangles per tile
                        // *  *
                        // *  *
                        // bottom left star is the current tile, will generate connections to 3 adjacent tiles

                        Vector2Int ind1, ind2;
                        for (int c = 0; c < 2; c++)
                        {
                            if (c == 0)
                            {
                                ind1 = SquareDirections.Top;
                                ind2 = SquareDirections.TopRight;
                            }
                            else
                            {
                                ind1 = SquareDirections.TopRight;
                                ind2 = SquareDirections.Right;
                            }

                            try
                            {
                                ind1 += new Vector2Int(i, j);
                                ind2 += new Vector2Int(i, j);

                                // compute string key for the triangle
                                int[] triInds = new int[] { (i * length + j), (ind1.x * length + ind1.y), (ind2.x * length + ind2.y) };
                                Array.Sort(triInds);
                                string triStringKey = "";
                                foreach (float f in triInds)
                                {
                                    triStringKey += $"{f}-";
                                }

                                // add triangle only if it wasnt added already
                                if (!trisDict.ContainsKey(triStringKey))
                                {
                                    trisDict.Add(triStringKey, true);

                                    yTotal += tiles[i, j].Pos.y + tiles[ind1.x, ind1.y].Pos.y + tiles[ind2.x, ind2.y].Pos.y;
                                    List <Vector3> verticesLocal = new List <Vector3>();
                                    verticesLocal.Add(tiles[i, j].Pos);
                                    verticesLocal.Add(tiles[ind1.x, ind1.y].Pos);
                                    verticesLocal.Add(tiles[ind2.x, ind2.y].Pos);

                                    List <Vector2> uvsLocal = new List <Vector2>();
                                    uvsLocal.Add(region.Pos2Uv(tiles[i, j].Pos));
                                    uvsLocal.Add(region.Pos2Uv(tiles[ind1.x, ind1.y].Pos));
                                    uvsLocal.Add(region.Pos2Uv(tiles[ind2.x, ind2.y].Pos));

                                    MeshTriAdder.AddTriangle(new Vector3Int(0, 1, 2), verticesLocal, verticesDict, tris, normals, uvsLocal, uvs);
                                    trisCount++;
                                }
                            }
                            catch (IndexOutOfRangeException e) { }
                            catch (NullReferenceException e)
                            {
                            }
                        }
                    }
                }
            }

            Debug.Log($"Tiles with size {length}");
            Debug.Log(
                $"Built a mesh with {verticesDict.Keys.Count} vertices and {trisCount} triangles; total height {yTotal}.");

            Mesh mesh = new Mesh();

            mesh.Clear();
            mesh.subMeshCount = 2;

            mesh.SetVertices(verticesDict.Keys.ToList <Vector3>());

            mesh.SetTriangles(tris.ToArray(), 0);

            //Vector2[] uvsUnwrap = Unwrapping.GeneratePerTriangleUV(mesh);
            mesh.SetUVs(0, uvs);

            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            // assign back to meshFilter
            MeshFilter   meshFilter   = GetComponent <MeshFilter>();
            MeshCollider meshCollider = GetComponent <MeshCollider>();

            mesh.Optimize();

            meshFilter.mesh         = mesh;
            meshCollider.sharedMesh = meshFilter.sharedMesh;
        }