示例#1
0
    void GenerateTurboForest(string biome, int type)
    {
        tfQuad.quads.Clear();

        Vector3 tpos         = new Vector3(0, 100000, 0); // raycast from (to check if tree on mesh)
        float   castDistance = Mathf.Abs(tpos.y * 2);

        Ray ray = new Ray();

        ray.direction = -Vector3.up;

        RaycastHit info;

        // forest area from collider
        Vector3 cmin = GetComponent <Collider>().bounds.min;
        Vector3 cmax = GetComponent <Collider>().bounds.max;

        int total = treesCount;

        int isize = 100;       // grid place trees step

        float step  = (cmax.x - cmin.x) / isize;
        float step2 = step * 2;

        // calc trees height on edges and randomize heights
        float[,] height = new float[isize, isize];
        float[,] blur   = new float[isize, isize];

        for (int i = 0; i < isize; i++)
        {
            for (int j = 0; j < isize; j++)
            {
                height[i, j] = .5f;

                tpos.x     = cmin.x + i * step;
                tpos.z     = cmin.z + j * step;
                ray.origin = tpos;
                if (this.GetComponent <Collider>().Raycast(ray, out info, castDistance))
                {
                    height[i, j] = 1;
                    if (Random.value < .3f)
                    {
                        height[i, j] = Random.value * .5f;
                    }
                }
            }
        }

        for (int t = 0; t < 4; t++)
        {
            for (int i = 0; i < isize; i++)
            {
                for (int j = 0; j < isize; j++)
                {
                    blur[i, j] = 0;
                    for (int ii = -1; ii < 2; ii++)
                    {
                        for (int jj = -1; jj < 2; jj++)
                        {
                            blur[i, j] += height[Clamp(i + ii, isize), Clamp(j + jj, isize)];
                        }
                    }
                    blur[i, j] /= 9;
                }
            }
            for (int i = 0; i < isize; i++)
            {
                for (int j = 0; j < isize; j++)
                {
                    height[i, j] = blur[i, j];
                }
            }
        }
        // heights calculated here

        while (total > 0)      // till all trees places
        {
            // fill one mesh
            for (int i = 0; i < isize; i++)
            {
                for (int j = 0; j < isize; j++)
                {
                    // tree position
                    tpos.x = cmin.x + i * step - step + Random.value * step2;
                    tpos.z = cmin.z + j * step - step + Random.value * step2;

                    ray.origin = tpos;


                    var c = _kdtree.NearestNeighbors(new double[] { tpos.x, tpos.z }, 1);
                    c.MoveNext();
                    var center = c.Current;
                    //if() // if tree on mesh
                    if (center.Biome != null && center.Biome.Name.ToLowerInvariant().Contains(biome.ToLowerInvariant()) &&
                        GetComponent <Collider>().Raycast(ray, out info, castDistance))
                    {
                        var q = new tfQuad(tpos.x, info.point.y, tpos.z);
                        q.scale = height[i, j] * (1.0f - eachTreeSizeRandomize + Random.value * eachTreeSizeRandomize * 2);
                        total--;

                        if (tfQuad.quads.Count == 10666)              // max quads per mesh (42 664 indices)
                        {
                            BuildMesh(type);
                            tfQuad.quads.Clear();                     // clear quads list for next mesh
                            System.GC.Collect();
                        }
                    }
                }
            }
        }

        if (tfQuad.quads.Count > 0)
        {
            BuildMesh(type);
            tfQuad.quads.Clear();             // clear quads list for next mesh
            System.GC.Collect();
        }
    }
示例#2
0
    void BuildMesh(int deftype)
    {
        if (tfQuad.quads.Count == 0)
        {
            return;
        }

        Vector3[] verts   = new Vector3[tfQuad.quads.Count * 4]; // all trees (in mesh) vertices
        Vector2[] uvs     = new Vector2[tfQuad.quads.Count * 4]; // trees uvs
        Vector2[] uvs2    = new Vector2[tfQuad.quads.Count * 4]; // uvs2 store tre type, one of 4 trees texture shift
        Vector3[] normals = new Vector3[tfQuad.quads.Count * 4]; // normals store each tree position in mesh (billboards no need normals ;)

        int[] indices = new int[tfQuad.quads.Count * 4];         // quads in mesh

        // need to calculate min and max bounds manualy, for correct AABB Unity calc
        Vector3 min = tfQuad.quads[0].pos;
        Vector3 max = min;

        Vector2 typeShift = new Vector2(0, 0);       // shift current on texture (tree type, one of 4)

        for (int i = 0; i < tfQuad.quads.Count; i++) // fill arrays
        {
            tfQuad q = tfQuad.quads[i];

            // AABB calc
            min.x = Mathf.Min(min.x, q.pos.x);
            min.y = Mathf.Min(min.y, q.pos.y);
            min.z = Mathf.Min(min.z, q.pos.z);

            max.x = Mathf.Max(max.x, q.pos.x);
            max.y = Mathf.Max(max.y, q.pos.y);
            max.z = Mathf.Max(max.z, q.pos.z);

            int ii = i * 4;

            // vertices of tree
            verts[ii]     = qv0 * q.scale;
            verts[ii + 1] = qv1 * q.scale;
            verts[ii + 2] = qv2 * q.scale;
            verts[ii + 3] = qv3 * q.scale;

            // randomize shading
            float tint = 1.0f - eachTreeShadingRandomize + (Random.value * eachTreeShadingRandomize * 2);
            verts[ii].z     = tint;
            verts[ii + 1].z = tint;
            verts[ii + 2].z = tint;
            verts[ii + 3].z = tint;

            // base tree uvs (first frame of this tree)
            uvs[ii]     = uv0;
            uvs[ii + 1] = uv1;
            uvs[ii + 2] = uv2;
            uvs[ii + 3] = uv3;

            indices[ii]     = ii;
            indices[ii + 1] = ii + 1;
            indices[ii + 2] = ii + 2;
            indices[ii + 3] = ii + 3;

            // push tree up from groung on it height
            q.pos.y += -qv0.y * q.scale;

            // write tree position to it normals (for shader)
            normals[ii]     = q.pos;
            normals[ii + 1] = q.pos;
            normals[ii + 2] = q.pos;
            normals[ii + 3] = q.pos;

            // calc and write tree type
            typeShift.x = 0;
            typeShift.y = 0;

            int type = 0;

            float r = Random.value;
            if (r > .25f)
            {
                type = 1;
            }
            if (r > .5f)
            {
                type = 2;
            }
            if (r > .75f)
            {
                type = 3;
            }

            //type = deftype;
            if (type == 1)
            {
                typeShift.x = .5f;
            }
            else if (type == 2)
            {
                typeShift.y = .5f;
            }
            else if (type == 3)
            {
                typeShift.x = .5f; typeShift.y = .5f;
            }

            uvs2[ii]     = typeShift;
            uvs2[ii + 1] = typeShift;
            uvs2[ii + 2] = typeShift;
            uvs2[ii + 3] = typeShift;
        }

        // creating mesh
        var trees = new GameObject();
        var mf    = trees.AddComponent <MeshFilter>();

        mf.sharedMesh = new Mesh();

        mf.sharedMesh.vertices = verts;

        mf.sharedMesh.normals = normals;
        mf.sharedMesh.uv      = uvs;
        mf.sharedMesh.uv2     = uvs2;
        mf.sharedMesh.SetIndices(indices, MeshTopology.Quads, 0);

        mf.sharedMesh.bounds = new Bounds(center: (min + max) / 2, size: max - min);         // alexzzzz fix

        MeshRenderer mr = trees.AddComponent <MeshRenderer>();

        mr.sharedMaterial = treeMaterial;
    }