Example #1
0
        public void GenerateMeshData(float resolutionMultiplier, int minResolution, AnimationCurve rootShape, float radiusMultiplier
                                     , float rootRadius, float rootHeight, float RootResolutionMultiplier, int flaresNumber, float displacmentStrength
                                     , float displacmentSize, float spinAmount)
        {
            Queue <int>        trianglesWithBadNormals = new Queue <int>();        // Triangles whose verts have been displaced, needing their normals to be recalculated
            Queue <Vector2Int> duplicatedVertexIndexes = new Queue <Vector2Int>(); // Used when recalculating normals to avoid shading seams

            while (splines.Count > 0)                                              // Each spline is an entire branch
            {
                SimplexNoiseGenerator noiseGenerator = new SimplexNoiseGenerator(new int[] { 0x16, 0x38, 0x32, 0x2c, 0x0d, 0x13, 0x07, 0x2a });
                Queue <TreePoint>     spline         = splines.Pop();
                int   lastResolution = -1;
                float uv_height      = 0f;
                while (spline.Count > 0) // drawing each node inside the branch
                {
                    TreePoint point = spline.Dequeue();
                    point.radius = Mathf.Max(point.radius, 0.001f);
                    int resolution = getResolution(point, minResolution, rootRadius, rootHeight, resolutionMultiplier);

                    Vector3[] newVerts;

                    if (lastResolution == -1 && point.parentRadius != 0 && point.type == NodeType.FromTrunk)
                    {
                        newVerts = AddCircleWrapped(point.position, point.direction, point.radius, resolution, point.parentRadius, point.parentDirection, displacmentStrength);
                    }
                    else
                    {
                        newVerts = AddCircle(point.position, point.direction, point.radius, resolution, uv_height * spinAmount * point.radius);
                    }
                    int n = verts.Count;
                    duplicatedVertexIndexes.Enqueue(new Vector2Int(n, n + resolution - 1));
                    BridgeLoops(newVerts, point, lastResolution, uv_height, n, getFillingGapRate(lastResolution, resolution), flaresNumber, rootRadius, rootHeight, radiusMultiplier,
                                rootShape, noiseGenerator, displacmentSize, displacmentStrength, trianglesWithBadNormals);
                    if (spline.Count > 0)
                    {
                        float rad = point.radius;
                        if (point.type == NodeType.Flare)
                        {
                            rad += rootRadius * rootShape.Evaluate(point.position.y / rootHeight) * radiusMultiplier;
                        }
                        uv_height += (point.position - spline.Peek().position).magnitude / rad;
                    }

                    lastResolution = resolution;
                }
            }
            RecalculateNormals(duplicatedVertexIndexes, trianglesWithBadNormals);
        }
Example #2
0
        int getResolution(TreePoint point, int minResolution, float rootRadius, float rootHeight, float resolutionMultiplier)
        {
            int resolution = (int)((point.radius) * resolutionMultiplier * 7);

            if (point.type == NodeType.Flare)
            {
                resolution += (int)(rootRadius * (Mathf.Pow(1 - Mathf.Max(0, point.position.y / rootHeight), 2)) * resolutionMultiplier * 3);
            }

            if (resolution < minResolution)
            {
                resolution = minResolution;
            }
            resolution++;
            return(resolution);
        }
Example #3
0
        void BridgeLoops(Vector3[] loop, TreePoint point, int lastResolution, float uvHeight, int n, int fillingGapRate, int flaresNumber,
                         float rootRadius, float rootHeight, float radiusMultiplier, AnimationCurve rootShape, SimplexNoiseGenerator noiseGenerator,
                         float displacementSize, float displacementStrength, Queue <int> trianglesWithBadNormals)
        {
            int resolution = loop.Length;
            int gaps       = lastResolution - resolution; //difference between the two loops

            for (int i = 0; i < resolution; i++)
            {
                Vector3 vert   = loop[i];
                Vector3 normal = (vert - point.position).normalized;

                Vector3 nrm      = (vert - point.position).normalized;
                float   uvOffset = 0f;
                if (lastResolution == -1)
                {
                    Vector3 orthoDir = Vector3.ProjectOnPlane(point.direction, point.parentDirection).normalized;
                    Vector3 center   = (loop[0] + loop[resolution / 2]) / 2 - orthoDir * point.parentRadius;
                    Vector3 pos      = Vector3.Project(vert - center, point.parentDirection) + center;
                    nrm = (vert - pos).normalized;
                    if (point.type == NodeType.FromTrunk)
                    {
                        uvOffset = point.parentRadius / Mathf.Max(3f, 1 - Mathf.Abs(Vector3.Dot(point.direction, point.parentDirection)));
                        uvOffset = Vector3.Distance(point.position, vert);
                    }
                }
                bool badNormals = false;
                if (point.type == NodeType.Trunk || point.type == NodeType.Flare) //Trunk displacement
                {
                    vert      += noiseGenerator.noiseGradient(vert * displacementSize / radiusMultiplier, flat: true) / 5 * point.radius * displacementStrength;
                    badNormals = true;
                }

                if (point.type == NodeType.Flare) // root flares displacement
                {
                    float angle        = i * 1f / (resolution - 1) * 2 * Mathf.PI;
                    float displacement = Mathf.Abs(Mathf.Sin(angle * flaresNumber / 2f)) * rootRadius * rootShape.Evaluate(point.position.y / rootHeight) * radiusMultiplier;
                    vert += normal * displacement;
                }

                verts.Enqueue(vert);
                normals.Enqueue(nrm);
                uvs.Enqueue(new Vector2(i * 1f / (resolution - 1), uvHeight / 3.2f + uvOffset));
                if (i > 0 && lastResolution > 0)
                {
                    if (badNormals)
                    {
                        trianglesWithBadNormals.Enqueue(triangles.Count);
                        trianglesWithBadNormals.Enqueue(triangles.Count + 3);
                    }
                    AddTriangle(n - lastResolution + i - 1, n + i - 1, n - lastResolution + i);
                    AddTriangle(n + i - 1, n + i, n - lastResolution + i);
                    if (i % fillingGapRate == 0 && gaps > 0) // filling a gap
                    {
                        if (badNormals)
                        {
                            trianglesWithBadNormals.Enqueue(triangles.Count);
                        }
                        AddTriangle(n - lastResolution + i, n + i, n - lastResolution + i + 1);
                        gaps--;
                        lastResolution--;
                    }
                }
                Color col = new Color(point.distanceFromOrigin / 10, 0, 0);
                colors.Enqueue(col);
            }
            if (gaps > 0) // Fill eventual remaining gap
            {
                AddTriangle(n - lastResolution + resolution - 1, n + resolution - 1, n - lastResolution + resolution);
            }
        }