GetAdaptiveSamples() public static method

public static GetAdaptiveSamples ( TreeGroup group, TreeNode node, float adaptiveQuality ) : List
group TreeGroup
node TreeNode
adaptiveQuality float
return List
Exemplo n.º 1
0
        private void UpdateNodeMesh(TreeNode node, List <TreeMaterial> materials, List <TreeVertex> verts, List <TreeTriangle> tris, List <TreeAOSphere> aoSpheres, int buildFlags, float adaptiveQuality, float aoDensity)
        {
            node.triStart  = tris.Count;
            node.triEnd    = tris.Count;
            node.vertStart = verts.Count;
            node.vertEnd   = verts.Count;
            if (!node.visible || !this.visible)
            {
                return;
            }
            Profiler.BeginSample("TreeGroupBranch.UpdateNodeMesh");
            int             count             = verts.Count;
            float           approximateLength = node.spline.GetApproximateLength();
            List <RingLoop> list                   = new List <RingLoop>();
            float           adaptiveQuality2       = Mathf.Clamp01(adaptiveQuality * this.lodQualityMultiplier);
            List <float>    adaptiveSamples        = TreeData.GetAdaptiveSamples(this, node, adaptiveQuality2);
            int             adaptiveRadialSegments = TreeData.GetAdaptiveRadialSegments(this.radius, adaptiveQuality2);
            TreeGroupBranch treeGroupBranch        = null;

            if (this.parentGroup != null && this.parentGroup.GetType() == typeof(TreeGroupBranch))
            {
                treeGroupBranch = (TreeGroupBranch)this.parentGroup;
            }
            if (this.geometryMode == TreeGroupBranch.GeometryMode.BranchFrond || this.geometryMode == TreeGroupBranch.GeometryMode.Branch)
            {
                int   materialIndex = TreeGroup.GetMaterialIndex(this.materialBranch, materials, true);
                float num           = 0f;
                float num2          = 0f;
                float num3          = approximateLength / (this.GetRadiusAtTime(node, 0f, false) * 3.14159274f * 2f);
                bool  flag          = true;
                if (node.parent != null && treeGroupBranch != null)
                {
                    num2 = node.offset * node.parent.spline.GetApproximateLength();
                }
                float num4 = 1f - node.capRange;
                for (int i = 0; i < adaptiveSamples.Count; i++)
                {
                    float      num5           = adaptiveSamples[i];
                    Vector3    positionAtTime = node.spline.GetPositionAtTime(num5);
                    Quaternion rotationAtTime = node.spline.GetRotationAtTime(num5);
                    float      radiusAtTime   = this.GetRadiusAtTime(node, num5, false);
                    Matrix4x4  m = node.matrix * Matrix4x4.TRS(positionAtTime, rotationAtTime, new Vector3(1f, 1f, 1f));
                    Vector3    flareWeldAtTime = this.GetFlareWeldAtTime(node, num5);
                    float      num6            = Mathf.Max(flareWeldAtTime.x, Mathf.Max(flareWeldAtTime.y, flareWeldAtTime.z) * 0.25f);
                    if (num5 <= num4)
                    {
                        adaptiveRadialSegments = TreeData.GetAdaptiveRadialSegments(radiusAtTime + num6, adaptiveQuality2);
                    }
                    if (flag)
                    {
                        if (i > 0)
                        {
                            float num7 = adaptiveSamples[i - 1];
                            float num8 = num5 - num7;
                            float num9 = (radiusAtTime + this.GetRadiusAtTime(node, num7, false)) * 0.5f;
                            num += num8 * approximateLength / (num9 * 3.14159274f * 2f);
                        }
                    }
                    else
                    {
                        num = num2 + num5 * num3;
                    }
                    Vector2  vector   = base.ComputeWindFactor(node, num5);
                    RingLoop ringLoop = new RingLoop();
                    ringLoop.Reset(radiusAtTime, m, num, adaptiveRadialSegments);
                    ringLoop.SetSurfaceAngle(node.GetSurfaceAngleAtTime(num5));
                    ringLoop.SetAnimationProperties(vector.x, vector.y, 0f, node.animSeed);
                    ringLoop.SetSpread(flareWeldAtTime.y, flareWeldAtTime.z);
                    ringLoop.SetNoise(this.noise * Mathf.Clamp01(this.noiseCurve.Evaluate(num5)), this.noiseScaleU * 10f, this.noiseScaleV * 10f);
                    ringLoop.SetFlares(flareWeldAtTime.x, this.flareNoise * 10f);
                    int count2 = verts.Count;
                    ringLoop.BuildVertices(verts);
                    int count3 = verts.Count;
                    if ((buildFlags & 2) != 0)
                    {
                        float num10 = this.weldHeight;
                        float num11 = Mathf.Pow(Mathf.Clamp01((1f - num5 - (1f - this.weldHeight)) / this.weldHeight), 1.5f);
                        float d     = 1f - num11;
                        if (num5 < num10 && node.parent != null && node.parent.spline != null)
                        {
                            Ray ray = default(Ray);
                            for (int j = count2; j < count3; j++)
                            {
                                ray.origin    = verts[j].pos;
                                ray.direction = m.MultiplyVector(-Vector3.up);
                                Vector3 pos   = verts[j].pos;
                                Vector3 nor   = verts[j].nor;
                                float   num12 = -10000f;
                                float   num13 = 100000f;
                                for (int k = node.parent.triStart; k < node.parent.triEnd; k++)
                                {
                                    object obj = MathUtils.IntersectRayTriangle(ray, verts[tris[k].v[0]].pos, verts[tris[k].v[1]].pos, verts[tris[k].v[2]].pos, true);
                                    if (obj != null)
                                    {
                                        RaycastHit raycastHit = (RaycastHit)obj;
                                        if (Mathf.Abs(raycastHit.distance) < num13 && raycastHit.distance > num12)
                                        {
                                            num13        = Mathf.Abs(raycastHit.distance);
                                            verts[j].nor = verts[tris[k].v[0]].nor * raycastHit.barycentricCoordinate.x + verts[tris[k].v[1]].nor * raycastHit.barycentricCoordinate.y + verts[tris[k].v[2]].nor * raycastHit.barycentricCoordinate.z;
                                            verts[j].nor = verts[j].nor * num11 + nor * d;
                                            verts[j].pos = raycastHit.point * num11 + pos * d;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    list.Add(ringLoop);
                    if (num5 == 1f && ringLoop.radius > 0.005f)
                    {
                        RingLoop ringLoop2 = ringLoop.Clone();
                        ringLoop2.radius      = 0f;
                        ringLoop2.baseOffset += radiusAtTime / 6.28318548f;
                        ringLoop2.BuildVertices(verts);
                        list.Add(ringLoop2);
                    }
                }
                if (list.Count > 0 && list[list.Count - 1].radius > 0.025f && node.breakOffset < 1f)
                {
                    float    mappingScale = 1f / (this.radius * 3.14159274f * 2f);
                    float    sphereFactor = 0f;
                    float    num14        = 1f;
                    int      mappingMode  = 0;
                    Material m2           = this.materialBranch;
                    if (this.materialBreak != null)
                    {
                        m2 = this.materialBreak;
                    }
                    int materialIndex2 = TreeGroup.GetMaterialIndex(m2, materials, false);
                    list[list.Count - 1].Cap(sphereFactor, num14, mappingMode, mappingScale, verts, tris, materialIndex2);
                }
                node.triStart = tris.Count;
                for (int l = 0; l < list.Count - 1; l++)
                {
                    list[l].Connect(list[l + 1], tris, materialIndex, false, false);
                }
                node.triEnd = tris.Count;
                list.Clear();
            }
            float num15 = Mathf.Min(this.frondRange.x, this.frondRange.y);
            float num16 = Mathf.Max(this.frondRange.x, this.frondRange.y);
            float num17 = num15;
            float num18 = num16;

            num15 = Mathf.Clamp(num15, 0f, node.breakOffset);
            num16 = Mathf.Clamp(num16, 0f, node.breakOffset);
            if ((this.geometryMode == TreeGroupBranch.GeometryMode.BranchFrond || this.geometryMode == TreeGroupBranch.GeometryMode.Frond) && this.frondCount > 0 && num15 != num16)
            {
                bool flag2 = true;
                bool flag3 = true;
                for (int n = 0; n < adaptiveSamples.Count; n++)
                {
                    float num19 = adaptiveSamples[n];
                    if (num19 < num15)
                    {
                        adaptiveSamples.RemoveAt(n);
                        n--;
                    }
                    else
                    {
                        if (num19 == num15)
                        {
                            flag2 = false;
                        }
                        else
                        {
                            if (num19 == num16)
                            {
                                flag3 = false;
                            }
                            else
                            {
                                if (num19 > num16)
                                {
                                    adaptiveSamples.RemoveAt(n);
                                    n--;
                                }
                            }
                        }
                    }
                }
                if (flag2)
                {
                    adaptiveSamples.Insert(0, num15);
                }
                if (flag3)
                {
                    adaptiveSamples.Add(num16);
                }
                int   materialIndex3 = TreeGroup.GetMaterialIndex(this.materialFrond, materials, false);
                float num20          = 1f - node.capRange;
                for (int num21 = 0; num21 < this.frondCount; num21++)
                {
                    float   num22   = this.frondCrease * 90f * 0.0174532924f;
                    float   num23   = (this.frondRotation * 360f + (float)num21 * 180f / (float)this.frondCount - 90f) * 0.0174532924f;
                    float   f       = -num23 - num22;
                    float   f2      = num23 - num22;
                    Vector3 a       = new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f));
                    Vector3 vector2 = new Vector3(a.z, 0f, -a.x);
                    Vector3 a2      = new Vector3(Mathf.Sin(f2), 0f, -Mathf.Cos(f2));
                    Vector3 vector3 = new Vector3(-a2.z, 0f, a2.x);
                    for (int num24 = 0; num24 < adaptiveSamples.Count; num24++)
                    {
                        float num25     = adaptiveSamples[num24];
                        float y         = (num25 - num17) / (num18 - num17);
                        float timeParam = num25;
                        if (num25 > num20)
                        {
                            timeParam = num20;
                            float f3    = Mathf.Acos(Mathf.Clamp01((num25 - num20) / node.capRange));
                            float num26 = Mathf.Sin(f3);
                            float y2    = Mathf.Cos(f3) * this.capSmoothing;
                            a       = new Vector3(Mathf.Sin(f) * num26, y2, Mathf.Cos(f) * num26);
                            vector2 = new Vector3(a.z, a.y, -a.x);
                            a2      = new Vector3(Mathf.Sin(f2) * num26, y2, -Mathf.Cos(f2) * num26);
                            vector3 = new Vector3(-a2.z, a2.y, a2.x);
                        }
                        Vector3    a3 = new Vector3(0f, 0f, -1f);
                        Vector3    positionAtTime2 = node.spline.GetPositionAtTime(timeParam);
                        Quaternion rotationAtTime2 = node.spline.GetRotationAtTime(num25);
                        float      d2       = Mathf.Clamp01(this.frondCurve.Evaluate(num25)) * this.frondWidth * node.GetScale();
                        Matrix4x4  matrix4x = node.matrix * Matrix4x4.TRS(positionAtTime2, rotationAtTime2, new Vector3(1f, 1f, 1f));
                        if (TreeGroup.GenerateDoubleSidedGeometry)
                        {
                            for (float num27 = -1f; num27 < 2f; num27 += 2f)
                            {
                                TreeVertex treeVertex = new TreeVertex();
                                treeVertex.pos       = matrix4x.MultiplyPoint(a * d2);
                                treeVertex.nor       = matrix4x.MultiplyVector(vector2 * num27).normalized;
                                treeVertex.tangent   = TreeGroup.CreateTangent(node, rotationAtTime2, treeVertex.nor);
                                treeVertex.tangent.w = -num27;
                                treeVertex.uv0       = new Vector2(1f, y);
                                TreeVertex treeVertex2 = new TreeVertex();
                                treeVertex2.pos       = matrix4x.MultiplyPoint(Vector3.zero);
                                treeVertex2.nor       = matrix4x.MultiplyVector(a3 * num27).normalized;
                                treeVertex2.tangent   = TreeGroup.CreateTangent(node, rotationAtTime2, treeVertex2.nor);
                                treeVertex2.tangent.w = -num27;
                                treeVertex2.uv0       = new Vector2(0.5f, y);
                                TreeVertex treeVertex3 = new TreeVertex();
                                treeVertex3.pos       = matrix4x.MultiplyPoint(Vector3.zero);
                                treeVertex3.nor       = matrix4x.MultiplyVector(a3 * num27).normalized;
                                treeVertex3.tangent   = TreeGroup.CreateTangent(node, rotationAtTime2, treeVertex3.nor);
                                treeVertex3.tangent.w = -num27;
                                treeVertex3.uv0       = new Vector2(0.5f, y);
                                TreeVertex treeVertex4 = new TreeVertex();
                                treeVertex4.pos       = matrix4x.MultiplyPoint(a2 * d2);
                                treeVertex4.nor       = matrix4x.MultiplyVector(vector3 * num27).normalized;
                                treeVertex4.tangent   = TreeGroup.CreateTangent(node, rotationAtTime2, treeVertex4.nor);
                                treeVertex4.tangent.w = -num27;
                                treeVertex4.uv0       = new Vector2(0f, y);
                                Vector2 vector4 = base.ComputeWindFactor(node, num25);
                                treeVertex.SetAnimationProperties(vector4.x, vector4.y, this.animationEdge, node.animSeed);
                                treeVertex2.SetAnimationProperties(vector4.x, vector4.y, 0f, node.animSeed);
                                treeVertex3.SetAnimationProperties(vector4.x, vector4.y, 0f, node.animSeed);
                                treeVertex4.SetAnimationProperties(vector4.x, vector4.y, this.animationEdge, node.animSeed);
                                verts.Add(treeVertex);
                                verts.Add(treeVertex2);
                                verts.Add(treeVertex3);
                                verts.Add(treeVertex4);
                            }
                            if (num24 > 0)
                            {
                                int          count4        = verts.Count;
                                TreeTriangle treeTriangle  = new TreeTriangle(materialIndex3, count4 - 4, count4 - 3, count4 - 11);
                                TreeTriangle treeTriangle2 = new TreeTriangle(materialIndex3, count4 - 4, count4 - 11, count4 - 12);
                                treeTriangle.flip();
                                treeTriangle2.flip();
                                TreeTriangle item  = new TreeTriangle(materialIndex3, count4 - 8, count4 - 7, count4 - 15);
                                TreeTriangle item2 = new TreeTriangle(materialIndex3, count4 - 8, count4 - 15, count4 - 16);
                                tris.Add(treeTriangle);
                                tris.Add(treeTriangle2);
                                tris.Add(item);
                                tris.Add(item2);
                                TreeTriangle item3         = new TreeTriangle(materialIndex3, count4 - 2, count4 - 9, count4 - 1);
                                TreeTriangle item4         = new TreeTriangle(materialIndex3, count4 - 2, count4 - 10, count4 - 9);
                                TreeTriangle treeTriangle3 = new TreeTriangle(materialIndex3, count4 - 6, count4 - 13, count4 - 5);
                                TreeTriangle treeTriangle4 = new TreeTriangle(materialIndex3, count4 - 6, count4 - 14, count4 - 13);
                                treeTriangle3.flip();
                                treeTriangle4.flip();
                                tris.Add(item3);
                                tris.Add(item4);
                                tris.Add(treeTriangle3);
                                tris.Add(treeTriangle4);
                            }
                        }
                        else
                        {
                            TreeVertex treeVertex5 = new TreeVertex();
                            treeVertex5.pos = matrix4x.MultiplyPoint(a * d2);
                            treeVertex5.nor = matrix4x.MultiplyVector(vector2).normalized;
                            treeVertex5.uv0 = new Vector2(0f, y);
                            TreeVertex treeVertex6 = new TreeVertex();
                            treeVertex6.pos = matrix4x.MultiplyPoint(Vector3.zero);
                            treeVertex6.nor = matrix4x.MultiplyVector(Vector3.back).normalized;
                            treeVertex6.uv0 = new Vector2(0.5f, y);
                            TreeVertex treeVertex7 = new TreeVertex();
                            treeVertex7.pos = matrix4x.MultiplyPoint(a2 * d2);
                            treeVertex7.nor = matrix4x.MultiplyVector(vector3).normalized;
                            treeVertex7.uv0 = new Vector2(1f, y);
                            Vector2 vector5 = base.ComputeWindFactor(node, num25);
                            treeVertex5.SetAnimationProperties(vector5.x, vector5.y, this.animationEdge, node.animSeed);
                            treeVertex6.SetAnimationProperties(vector5.x, vector5.y, 0f, node.animSeed);
                            treeVertex7.SetAnimationProperties(vector5.x, vector5.y, this.animationEdge, node.animSeed);
                            verts.Add(treeVertex5);
                            verts.Add(treeVertex6);
                            verts.Add(treeVertex7);
                            if (num24 > 0)
                            {
                                int          count5 = verts.Count;
                                TreeTriangle item5  = new TreeTriangle(materialIndex3, count5 - 2, count5 - 3, count5 - 6);
                                TreeTriangle item6  = new TreeTriangle(materialIndex3, count5 - 2, count5 - 6, count5 - 5);
                                tris.Add(item5);
                                tris.Add(item6);
                                TreeTriangle item7 = new TreeTriangle(materialIndex3, count5 - 2, count5 - 4, count5 - 1);
                                TreeTriangle item8 = new TreeTriangle(materialIndex3, count5 - 2, count5 - 5, count5 - 4);
                                tris.Add(item7);
                                tris.Add(item8);
                            }
                        }
                    }
                }
            }
            if ((buildFlags & 1) != 0)
            {
                for (int num28 = count; num28 < verts.Count; num28++)
                {
                    verts[num28].SetAmbientOcclusion(TreeGroup.ComputeAmbientOcclusion(verts[num28].pos, verts[num28].nor, aoSpheres, aoDensity));
                }
            }
            node.vertEnd = verts.Count;
            Profiler.EndSample();
        }
Exemplo n.º 2
0
 private void UpdateNodeMesh(TreeNode node, List <TreeMaterial> materials, List <TreeVertex> verts, List <TreeTriangle> tris, List <TreeAOSphere> aoSpheres, int buildFlags, float adaptiveQuality, float aoDensity)
 {
     node.triStart  = tris.Count;
     node.triEnd    = tris.Count;
     node.vertStart = verts.Count;
     node.vertEnd   = verts.Count;
     if (node.visible && base.visible)
     {
         int             count             = verts.Count;
         float           approximateLength = node.spline.GetApproximateLength();
         List <RingLoop> list  = new List <RingLoop>();
         float           num3  = Mathf.Clamp01(adaptiveQuality * this.lodQualityMultiplier);
         List <float>    list2 = TreeData.GetAdaptiveSamples(this, node, num3);
         int             adaptiveRadialSegments = TreeData.GetAdaptiveRadialSegments(this.radius, num3);
         TreeGroupBranch parentGroup            = null;
         if ((base.parentGroup != null) && (base.parentGroup.GetType() == typeof(TreeGroupBranch)))
         {
             parentGroup = (TreeGroupBranch)base.parentGroup;
         }
         if ((this.geometryMode == GeometryMode.BranchFrond) || (this.geometryMode == GeometryMode.Branch))
         {
             int   materialIndex = TreeGroup.GetMaterialIndex(this.materialBranch, materials, true);
             float bOffset       = 0f;
             float num7          = 0f;
             float num8          = approximateLength / ((this.GetRadiusAtTime(node, 0f, false) * 3.141593f) * 2f);
             bool  flag          = true;
             if ((node.parent != null) && (parentGroup != null))
             {
                 num7 = node.offset * node.parent.spline.GetApproximateLength();
             }
             float num9 = 1f - node.capRange;
             for (int i = 0; i < list2.Count; i++)
             {
                 float      timeParam      = list2[i];
                 Vector3    positionAtTime = node.spline.GetPositionAtTime(timeParam);
                 Quaternion rotationAtTime = node.spline.GetRotationAtTime(timeParam);
                 float      r = this.GetRadiusAtTime(node, timeParam, false);
                 Matrix4x4  m = node.matrix * Matrix4x4.TRS(positionAtTime, rotationAtTime, new Vector3(1f, 1f, 1f));
                 Vector3    flareWeldAtTime = this.GetFlareWeldAtTime(node, timeParam);
                 float      num13           = Mathf.Max(flareWeldAtTime.x, Mathf.Max(flareWeldAtTime.y, flareWeldAtTime.z) * 0.25f);
                 if (timeParam <= num9)
                 {
                     adaptiveRadialSegments = TreeData.GetAdaptiveRadialSegments(r + num13, num3);
                 }
                 if (flag)
                 {
                     if (i > 0)
                     {
                         float t     = list2[i - 1];
                         float num15 = timeParam - t;
                         float num16 = (r + this.GetRadiusAtTime(node, t, false)) * 0.5f;
                         bOffset += (num15 * approximateLength) / ((num16 * 3.141593f) * 2f);
                     }
                 }
                 else
                 {
                     bOffset = num7 + (timeParam * num8);
                 }
                 Vector2  vector3 = base.ComputeWindFactor(node, timeParam);
                 RingLoop item    = new RingLoop();
                 item.Reset(r, m, bOffset, adaptiveRadialSegments);
                 item.SetSurfaceAngle(node.GetSurfaceAngleAtTime(timeParam));
                 item.SetAnimationProperties(vector3.x, vector3.y, 0f, node.animSeed);
                 item.SetSpread(flareWeldAtTime.y, flareWeldAtTime.z);
                 item.SetNoise(this.noise * Mathf.Clamp01(this.noiseCurve.Evaluate(timeParam)), this.noiseScaleU * 10f, this.noiseScaleV * 10f);
                 item.SetFlares(flareWeldAtTime.x, this.flareNoise * 10f);
                 int num17 = verts.Count;
                 item.BuildVertices(verts);
                 int num18 = verts.Count;
                 if ((buildFlags & 2) != 0)
                 {
                     float weldHeight = this.weldHeight;
                     float num20      = Mathf.Pow(Mathf.Clamp01(((1f - timeParam) - (1f - this.weldHeight)) / this.weldHeight), 1.5f);
                     float num21      = 1f - num20;
                     if ((timeParam < weldHeight) && ((node.parent != null) && (node.parent.spline != null)))
                     {
                         Ray ray = new Ray();
                         for (int k = num17; k < num18; k++)
                         {
                             ray.origin    = verts[k].pos;
                             ray.direction = m.MultiplyVector(-Vector3.up);
                             Vector3 pos   = verts[k].pos;
                             Vector3 nor   = verts[k].nor;
                             float   num23 = -10000f;
                             float   num24 = 100000f;
                             for (int n = node.parent.triStart; n < node.parent.triEnd; n++)
                             {
                                 object obj2 = MathUtils.IntersectRayTriangle(ray, verts[tris[n].v[0]].pos, verts[tris[n].v[1]].pos, verts[tris[n].v[2]].pos, true);
                                 if (obj2 != null)
                                 {
                                     RaycastHit hit = (RaycastHit)obj2;
                                     if ((Mathf.Abs(hit.distance) < num24) && (hit.distance > num23))
                                     {
                                         num24        = Mathf.Abs(hit.distance);
                                         verts[k].nor = (Vector3)(((verts[tris[n].v[0]].nor * hit.barycentricCoordinate.x) + (verts[tris[n].v[1]].nor * hit.barycentricCoordinate.y)) + (verts[tris[n].v[2]].nor * hit.barycentricCoordinate.z));
                                         verts[k].nor = (Vector3)((verts[k].nor * num20) + (nor * num21));
                                         verts[k].pos = (Vector3)((hit.point * num20) + (pos * num21));
                                     }
                                 }
                             }
                         }
                     }
                 }
                 list.Add(item);
                 if ((timeParam == 1f) && (item.radius > 0.005f))
                 {
                     RingLoop loop2 = item.Clone();
                     loop2.radius      = 0f;
                     loop2.baseOffset += r / 6.283185f;
                     loop2.BuildVertices(verts);
                     list.Add(loop2);
                 }
             }
             if (((list.Count > 0) && (list[list.Count - 1].radius > 0.025f)) && (node.breakOffset < 1f))
             {
                 float    mappingScale   = 1f / ((this.radius * 3.141593f) * 2f);
                 float    sphereFactor   = 0f;
                 float    noise          = 1f;
                 int      mappingMode    = 0;
                 Material materialBranch = this.materialBranch;
                 if (this.materialBreak != null)
                 {
                     materialBranch = this.materialBreak;
                 }
                 int num30 = TreeGroup.GetMaterialIndex(materialBranch, materials, false);
                 list[list.Count - 1].Cap(sphereFactor, noise, mappingMode, mappingScale, verts, tris, num30);
             }
             node.triStart = tris.Count;
             for (int j = 0; j < (list.Count - 1); j++)
             {
                 list[j].Connect(list[j + 1], tris, materialIndex, false, false);
             }
             node.triEnd = tris.Count;
             list.Clear();
         }
         float num32 = Mathf.Min(this.frondRange.x, this.frondRange.y);
         float num33 = Mathf.Max(this.frondRange.x, this.frondRange.y);
         float num34 = num32;
         float num35 = num33;
         num32 = Mathf.Clamp(num32, 0f, node.breakOffset);
         num33 = Mathf.Clamp(num33, 0f, node.breakOffset);
         if (((this.geometryMode == GeometryMode.BranchFrond) || (this.geometryMode == GeometryMode.Frond)) && ((this.frondCount > 0) && (num32 != num33)))
         {
             bool flag2 = true;
             bool flag3 = true;
             for (int num36 = 0; num36 < list2.Count; num36++)
             {
                 float num37 = list2[num36];
                 if (num37 < num32)
                 {
                     list2.RemoveAt(num36);
                     num36--;
                 }
                 else if (num37 == num32)
                 {
                     flag2 = false;
                 }
                 else if (num37 == num33)
                 {
                     flag3 = false;
                 }
                 else if (num37 > num33)
                 {
                     list2.RemoveAt(num36);
                     num36--;
                 }
             }
             if (flag2)
             {
                 list2.Insert(0, num32);
             }
             if (flag3)
             {
                 list2.Add(num33);
             }
             int   material = TreeGroup.GetMaterialIndex(this.materialFrond, materials, false);
             float num39    = 1f - node.capRange;
             for (int num40 = 0; num40 < this.frondCount; num40++)
             {
                 float   num41    = (this.frondCrease * 90f) * 0.01745329f;
                 float   num42    = (((this.frondRotation * 360f) + ((num40 * 180f) / ((float)this.frondCount))) - 90f) * 0.01745329f;
                 float   f        = -num42 - num41;
                 float   num44    = num42 - num41;
                 Vector3 vector9  = new Vector3(Mathf.Sin(f), 0f, Mathf.Cos(f));
                 Vector3 v        = new Vector3(vector9.z, 0f, -vector9.x);
                 Vector3 vector11 = new Vector3(Mathf.Sin(num44), 0f, -Mathf.Cos(num44));
                 Vector3 vector12 = new Vector3(-vector11.z, 0f, vector11.x);
                 for (int num45 = 0; num45 < list2.Count; num45++)
                 {
                     float num46 = list2[num45];
                     float y     = (num46 - num34) / (num35 - num34);
                     float num48 = num46;
                     if (num46 > num39)
                     {
                         num48 = num39;
                         float num49 = Mathf.Acos(Mathf.Clamp01((num46 - num39) / node.capRange));
                         float num50 = Mathf.Sin(num49);
                         float num51 = Mathf.Cos(num49) * this.capSmoothing;
                         vector9  = new Vector3(Mathf.Sin(f) * num50, num51, Mathf.Cos(f) * num50);
                         v        = new Vector3(vector9.z, vector9.y, -vector9.x);
                         vector11 = new Vector3(Mathf.Sin(num44) * num50, num51, -Mathf.Cos(num44) * num50);
                         vector12 = new Vector3(-vector11.z, vector11.y, vector11.x);
                     }
                     Vector3    vector13 = new Vector3(0f, 0f, -1f);
                     Vector3    vector14 = node.spline.GetPositionAtTime(num48);
                     Quaternion q        = node.spline.GetRotationAtTime(num46);
                     float      num52    = (Mathf.Clamp01(this.frondCurve.Evaluate(num46)) * this.frondWidth) * node.GetScale();
                     Matrix4x4  matrixx2 = node.matrix * Matrix4x4.TRS(vector14, q, new Vector3(1f, 1f, 1f));
                     if (TreeGroup.GenerateDoubleSidedGeometry)
                     {
                         for (float num53 = -1f; num53 < 2f; num53 += 2f)
                         {
                             TreeVertex vertex = new TreeVertex {
                                 pos = matrixx2.MultiplyPoint((Vector3)(vector9 * num52)),
                                 nor = matrixx2.MultiplyVector((Vector3)(v * num53)).normalized
                             };
                             vertex.tangent   = TreeGroup.CreateTangent(node, q, vertex.nor);
                             vertex.tangent.w = -num53;
                             vertex.uv0       = new Vector2(1f, y);
                             TreeVertex vertex2 = new TreeVertex {
                                 pos = matrixx2.MultiplyPoint(Vector3.zero),
                                 nor = matrixx2.MultiplyVector((Vector3)(vector13 * num53)).normalized
                             };
                             vertex2.tangent   = TreeGroup.CreateTangent(node, q, vertex2.nor);
                             vertex2.tangent.w = -num53;
                             vertex2.uv0       = new Vector2(0.5f, y);
                             TreeVertex vertex3 = new TreeVertex {
                                 pos = matrixx2.MultiplyPoint(Vector3.zero),
                                 nor = matrixx2.MultiplyVector((Vector3)(vector13 * num53)).normalized
                             };
                             vertex3.tangent   = TreeGroup.CreateTangent(node, q, vertex3.nor);
                             vertex3.tangent.w = -num53;
                             vertex3.uv0       = new Vector2(0.5f, y);
                             TreeVertex vertex4 = new TreeVertex {
                                 pos = matrixx2.MultiplyPoint((Vector3)(vector11 * num52)),
                                 nor = matrixx2.MultiplyVector((Vector3)(vector12 * num53)).normalized
                             };
                             vertex4.tangent   = TreeGroup.CreateTangent(node, q, vertex4.nor);
                             vertex4.tangent.w = -num53;
                             vertex4.uv0       = new Vector2(0f, y);
                             Vector2 vector19 = base.ComputeWindFactor(node, num46);
                             vertex.SetAnimationProperties(vector19.x, vector19.y, base.animationEdge, node.animSeed);
                             vertex2.SetAnimationProperties(vector19.x, vector19.y, 0f, node.animSeed);
                             vertex3.SetAnimationProperties(vector19.x, vector19.y, 0f, node.animSeed);
                             vertex4.SetAnimationProperties(vector19.x, vector19.y, base.animationEdge, node.animSeed);
                             verts.Add(vertex);
                             verts.Add(vertex2);
                             verts.Add(vertex3);
                             verts.Add(vertex4);
                         }
                         if (num45 > 0)
                         {
                             int          num54     = verts.Count;
                             TreeTriangle triangle  = new TreeTriangle(material, num54 - 4, num54 - 3, num54 - 11);
                             TreeTriangle triangle2 = new TreeTriangle(material, num54 - 4, num54 - 11, num54 - 12);
                             triangle.flip();
                             triangle2.flip();
                             TreeTriangle triangle3 = new TreeTriangle(material, num54 - 8, num54 - 7, num54 - 15);
                             TreeTriangle triangle4 = new TreeTriangle(material, num54 - 8, num54 - 15, num54 - 0x10);
                             tris.Add(triangle);
                             tris.Add(triangle2);
                             tris.Add(triangle3);
                             tris.Add(triangle4);
                             TreeTriangle triangle5 = new TreeTriangle(material, num54 - 2, num54 - 9, num54 - 1);
                             TreeTriangle triangle6 = new TreeTriangle(material, num54 - 2, num54 - 10, num54 - 9);
                             TreeTriangle triangle7 = new TreeTriangle(material, num54 - 6, num54 - 13, num54 - 5);
                             TreeTriangle triangle8 = new TreeTriangle(material, num54 - 6, num54 - 14, num54 - 13);
                             triangle7.flip();
                             triangle8.flip();
                             tris.Add(triangle5);
                             tris.Add(triangle6);
                             tris.Add(triangle7);
                             tris.Add(triangle8);
                         }
                     }
                     else
                     {
                         TreeVertex vertex5 = new TreeVertex {
                             pos = matrixx2.MultiplyPoint((Vector3)(vector9 * num52)),
                             nor = matrixx2.MultiplyVector(v).normalized,
                             uv0 = new Vector2(0f, y)
                         };
                         TreeVertex vertex6 = new TreeVertex {
                             pos = matrixx2.MultiplyPoint(Vector3.zero),
                             nor = matrixx2.MultiplyVector(Vector3.back).normalized,
                             uv0 = new Vector2(0.5f, y)
                         };
                         TreeVertex vertex7 = new TreeVertex {
                             pos = matrixx2.MultiplyPoint((Vector3)(vector11 * num52)),
                             nor = matrixx2.MultiplyVector(vector12).normalized,
                             uv0 = new Vector2(1f, y)
                         };
                         Vector2 vector23 = base.ComputeWindFactor(node, num46);
                         vertex5.SetAnimationProperties(vector23.x, vector23.y, base.animationEdge, node.animSeed);
                         vertex6.SetAnimationProperties(vector23.x, vector23.y, 0f, node.animSeed);
                         vertex7.SetAnimationProperties(vector23.x, vector23.y, base.animationEdge, node.animSeed);
                         verts.Add(vertex5);
                         verts.Add(vertex6);
                         verts.Add(vertex7);
                         if (num45 > 0)
                         {
                             int          num55      = verts.Count;
                             TreeTriangle triangle9  = new TreeTriangle(material, num55 - 2, num55 - 3, num55 - 6);
                             TreeTriangle triangle10 = new TreeTriangle(material, num55 - 2, num55 - 6, num55 - 5);
                             tris.Add(triangle9);
                             tris.Add(triangle10);
                             TreeTriangle triangle11 = new TreeTriangle(material, num55 - 2, num55 - 4, num55 - 1);
                             TreeTriangle triangle12 = new TreeTriangle(material, num55 - 2, num55 - 5, num55 - 4);
                             tris.Add(triangle11);
                             tris.Add(triangle12);
                         }
                     }
                 }
             }
         }
         if ((buildFlags & 1) != 0)
         {
             for (int num56 = count; num56 < verts.Count; num56++)
             {
                 verts[num56].SetAmbientOcclusion(TreeGroup.ComputeAmbientOcclusion(verts[num56].pos, verts[num56].nor, aoSpheres, aoDensity));
             }
         }
         node.vertEnd = verts.Count;
     }
 }
        private void UpdateNodeMesh(TreeNode node, List <TreeMaterial> materials, List <TreeVertex> verts, List <TreeTriangle> tris, List <TreeAOSphere> aoSpheres, int buildFlags, float adaptiveQuality, float aoDensity)
        {
            // Clear tri range
            node.triStart  = tris.Count;
            node.triEnd    = tris.Count;
            node.vertStart = verts.Count;
            node.vertEnd   = verts.Count;

            // Check for visibility
            if (!node.visible || !visible)
            {
                return;
            }

            Profiler.BeginSample("TreeGroupBranch.UpdateNodeMesh");

            int vertOffset = verts.Count;

            float totalHeight = node.spline.GetApproximateLength();// *node.GetScale(); //height * node.GetScale();

            // list to hold the ring loops
            List <RingLoop> ringloops = new List <RingLoop>();

            // Modify LOD to fit local settings
            float lodQuality = Mathf.Clamp01(adaptiveQuality * lodQualityMultiplier);

            // LOD settings
            List <float> heightSamples = TreeData.GetAdaptiveSamples(this, node, lodQuality);
            int          radialSamples = TreeData.GetAdaptiveRadialSegments(radius, lodQuality);

            //
            // Parent branch group if any..
            TreeGroupBranch parentBranchGroup = null;

            if ((parentGroup != null) && (parentGroup.GetType() == typeof(TreeGroupBranch)))
            {
                parentBranchGroup = (TreeGroupBranch)parentGroup;
            }

            if ((geometryMode == GeometryMode.BranchFrond) || (geometryMode == GeometryMode.Branch))
            {
                int materialIndex = GetMaterialIndex(materialBranch, materials, true);

                float uvOffset     = 0.0f;
                float uvBaseOffset = 0.0f;
                float uvStep       = totalHeight / (GetRadiusAtTime(node, 0.0f, false) * Mathf.PI * 2.0f);
                bool  uvAdapt      = true;

                if (node.parent != null && parentBranchGroup != null)
                {
                    uvBaseOffset = node.offset * node.parent.spline.GetApproximateLength();
                }

                float capStart = 1.0f - node.capRange;
                for (int i = 0; i < heightSamples.Count; i++)
                {
                    float t = heightSamples[i];

                    Vector3    pos = node.spline.GetPositionAtTime(t);
                    Quaternion rot = node.spline.GetRotationAtTime(t);
                    float      rad = GetRadiusAtTime(node, t, false);

                    Matrix4x4 m = node.matrix * Matrix4x4.TRS(pos, rot, new Vector3(1, 1, 1));

                    // total offset for wind animation
                    //float totalOffset = (totalOffsetBase + t);

                    // flare / weld spreading
                    Vector3 flareWeldSpread = GetFlareWeldAtTime(node, t);

                    // Do adaptive LOD for ringloops
                    float radModify = Mathf.Max(flareWeldSpread.x, Mathf.Max(flareWeldSpread.y, flareWeldSpread.z) * 0.25f);

                    // keep the same number of vertices per ring for the cap.. to give a nicer result
                    if (t <= capStart)
                    {
                        radialSamples = TreeData.GetAdaptiveRadialSegments(rad + radModify, lodQuality);
                    }

                    // uv offset..
                    if (uvAdapt)
                    {
                        if (i > 0)
                        {
                            float preT    = heightSamples[i - 1];
                            float uvDelta = t - preT;
                            float uvRad   = (rad + GetRadiusAtTime(node, preT, false)) * 0.5f;
                            uvOffset += (uvDelta * totalHeight) / (uvRad * Mathf.PI * 2.0f);
                        }
                    }
                    else
                    {
                        uvOffset = uvBaseOffset + (t * uvStep);
                    }

                    // wind
                    Vector2 windFactors = ComputeWindFactor(node, t);

                    RingLoop r = new RingLoop();
                    r.Reset(rad, m, uvOffset, radialSamples);
                    r.SetSurfaceAngle(node.GetSurfaceAngleAtTime(t));
                    r.SetAnimationProperties(windFactors.x, windFactors.y, 0.0f, node.animSeed);
                    r.SetSpread(flareWeldSpread.y, flareWeldSpread.z);
                    r.SetNoise(noise * Mathf.Clamp01(noiseCurve.Evaluate(t)), noiseScaleU * 10.0f, noiseScaleV * 10.0f);
                    r.SetFlares(flareWeldSpread.x, flareNoise * 10.0f);

                    int vertStart = verts.Count;
                    r.BuildVertices(verts);
                    int vertEnd = verts.Count;


                    if ((buildFlags & (int)BuildFlag.BuildWeldParts) != 0)
                    {
                        float projectionRange    = weldHeight;
                        float projectionBlend    = Mathf.Pow(Mathf.Clamp01(((1.0f - t) - (1.0f - weldHeight)) / weldHeight), 1.5f);
                        float invProjectionBlend = 1.0f - projectionBlend;

                        if (t < projectionRange)
                        {
                            if ((node.parent != null) && (node.parent.spline != null))
                            {
                                Ray ray = new Ray();
                                for (int v = vertStart; v < vertEnd; v++)
                                {
                                    ray.origin    = verts[v].pos;
                                    ray.direction = m.MultiplyVector(-Vector3.up);

                                    Vector3 origPos = verts[v].pos;
                                    Vector3 origNor = verts[v].nor;

                                    float minDist = -10000.0f;
                                    float maxDist = 100000.0f;
                                    // project vertices onto parent
                                    for (int tri = node.parent.triStart; tri < node.parent.triEnd; tri++)
                                    {
                                        object hit = MathUtils.IntersectRayTriangle(ray, verts[tris[tri].v[0]].pos,
                                                                                    verts[tris[tri].v[1]].pos,
                                                                                    verts[tris[tri].v[2]].pos, true);
                                        if (hit != null)
                                        {
                                            RaycastHit rayHit = ((RaycastHit)hit);
                                            if ((Mathf.Abs(rayHit.distance) < maxDist) && (rayHit.distance > minDist))
                                            {
                                                maxDist      = Mathf.Abs(rayHit.distance);
                                                verts[v].nor = (verts[tris[tri].v[0]].nor * rayHit.barycentricCoordinate.x) +
                                                               (verts[tris[tri].v[1]].nor * rayHit.barycentricCoordinate.y) +
                                                               (verts[tris[tri].v[2]].nor * rayHit.barycentricCoordinate.z);

                                                verts[v].nor = (verts[v].nor * projectionBlend) + (origNor * invProjectionBlend);

                                                verts[v].pos = (rayHit.point * projectionBlend) + (origPos * invProjectionBlend);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }


                    ringloops.Add(r);

                    // make sure we cap the puppy..
                    if ((t == 1.0f) && (r.radius > 0.005f))
                    {
                        RingLoop r2 = r.Clone();
                        r2.radius      = 0.0f;
                        r2.baseOffset += rad / (Mathf.PI * 2.0f);
                        r2.BuildVertices(verts);
                        ringloops.Add(r2);
                    }
                }

                // Cap
                // if needed..
                if (ringloops.Count > 0)
                {
                    if (ringloops[ringloops.Count - 1].radius > 0.025f)
                    {
                        if (node.breakOffset < 1.0f)
                        {
                            float    mappingScale     = 1.0f / (radius * Mathf.PI * 2.0f);
                            float    tempCapSpherical = 0.0f;
                            float    tempCapNoise     = 1.0f;
                            int      tempCapMapping   = 0;
                            Material tempCapMaterial  = materialBranch;

                            if (materialBreak != null)
                            {
                                tempCapMaterial = materialBreak;
                            }

                            int capMaterialIndex = GetMaterialIndex(tempCapMaterial, materials, false);

                            ringloops[ringloops.Count - 1].Cap(tempCapSpherical, tempCapNoise, tempCapMapping, mappingScale,
                                                               verts,
                                                               tris,
                                                               capMaterialIndex);
                        }
                    }
                }

                // Build triangles
                // Debug.Log("MAT INDEX: "+materialIndex);
                node.triStart = tris.Count;
                for (int i = 0; i < (ringloops.Count - 1); i++)
                {
                    ringloops[i].Connect(ringloops[i + 1], tris, materialIndex, false, false);
                }
                node.triEnd = tris.Count;

                ringloops.Clear();
            }

            // Build fronds
            float frondMin = Mathf.Min(frondRange.x, frondRange.y);
            float frondMax = Mathf.Max(frondRange.x, frondRange.y);

            // Mapping range.. may be different from min/max if broken..
            float frondMappingMin = frondMin;
            float frondMappingMax = frondMax;

            // Include breaking
            frondMin = Mathf.Clamp(frondMin, 0.0f, node.breakOffset);
            frondMax = Mathf.Clamp(frondMax, 0.0f, node.breakOffset);

            if ((geometryMode == GeometryMode.BranchFrond) || (geometryMode == GeometryMode.Frond))
            {
                if ((frondCount > 0) && (frondMin != frondMax))
                {
                    bool needStartPoint = true;
                    bool needEndPoint   = true;

                    for (int i = 0; i < heightSamples.Count; i++)
                    {
                        float t = heightSamples[i];

                        if (t < frondMin)
                        {
                            heightSamples.RemoveAt(i);
                            i--;
                        }
                        else if (t == frondMin)
                        {
                            needStartPoint = false;
                        }
                        else if (t == frondMax)
                        {
                            needEndPoint = false;
                        }
                        else if (t > frondMax)
                        {
                            heightSamples.RemoveAt(i);
                            i--;
                        }
                    }

                    if (needStartPoint)
                    {
                        heightSamples.Insert(0, frondMin);
                    }
                    if (needEndPoint)
                    {
                        heightSamples.Add(frondMax);
                    }

                    int frondMaterialIndex = GetMaterialIndex(materialFrond, materials, false);

                    float capStart = 1.0f - node.capRange;
                    //float capRadius = GetRadiusAtTime(capStart);
                    for (int j = 0; j < frondCount; j++)
                    {
                        float   crease     = (frondCrease * 90.0f) * Mathf.Deg2Rad;
                        float   angle      = ((frondRotation * 360.0f) + (((float)j * 180.0f) / frondCount) - 90.0f) * Mathf.Deg2Rad;
                        float   angleA     = -angle - crease;
                        float   angleB     = angle - crease;
                        Vector3 directionA = new Vector3(Mathf.Sin(angleA), 0.0f, Mathf.Cos(angleA));
                        Vector3 normalA    = new Vector3(directionA.z, 0.0f, -directionA.x);
                        Vector3 directionB = new Vector3(Mathf.Sin(angleB), 0.0f, -Mathf.Cos(angleB));
                        Vector3 normalB    = new Vector3(-directionB.z, 0.0f, directionB.x);

                        //float totalOffsetBase = GetTotalOffset();

                        for (int i = 0; i < heightSamples.Count; i++)
                        {
                            float t = heightSamples[i];
                            float v = (t - frondMappingMin) / (frondMappingMax - frondMappingMin);

                            // handle soft capping..
                            float t2 = t;
                            if (t > capStart)
                            {
                                t2 = capStart;

                                float capAngle    = Mathf.Acos(Mathf.Clamp01((t - capStart) / node.capRange));
                                float sinCapAngle = Mathf.Sin(capAngle);
                                float cosCapAngle = Mathf.Cos(capAngle) * capSmoothing;

                                directionA = new Vector3(Mathf.Sin(angleA) * sinCapAngle, cosCapAngle, Mathf.Cos(angleA) * sinCapAngle);
                                normalA    = new Vector3(directionA.z, directionA.y, -directionA.x);
                                directionB = new Vector3(Mathf.Sin(angleB) * sinCapAngle, cosCapAngle, -Mathf.Cos(angleB) * sinCapAngle);
                                normalB    = new Vector3(-directionB.z, directionB.y, directionB.x);
                            }

                            Vector3 normalMid = new Vector3(0, 0, -1);

                            Vector3    pos = node.spline.GetPositionAtTime(t2);
                            Quaternion rot = node.spline.GetRotationAtTime(t);
                            float      rad = (Mathf.Clamp01(frondCurve.Evaluate(t)) * frondWidth * node.GetScale());

                            Matrix4x4 m = node.matrix * Matrix4x4.TRS(pos, rot, new Vector3(1, 1, 1));

                            if (GenerateDoubleSidedGeometry)
                            {
                                // Generate double sided geometry to compensate for lack of VFACE shader semantic
                                // Twice the poly count
                                // Split vertices along back seam, to avoid bent normals.. 8 verts instead of 3

                                for (float side = -1; side < 2; side += 2)
                                {
                                    TreeVertex v0 = new TreeVertex();
                                    v0.pos       = m.MultiplyPoint(directionA * rad);
                                    v0.nor       = m.MultiplyVector(normalA * side).normalized;
                                    v0.tangent   = CreateTangent(node, rot, v0.nor);
                                    v0.tangent.w = -side;
                                    v0.uv0       = new Vector2(1.0f, v);

                                    TreeVertex v1 = new TreeVertex();
                                    v1.pos       = m.MultiplyPoint(Vector3.zero);
                                    v1.nor       = m.MultiplyVector(normalMid * side).normalized;
                                    v1.tangent   = CreateTangent(node, rot, v1.nor);
                                    v1.tangent.w = -side;
                                    v1.uv0       = new Vector2(0.5f, v);

                                    TreeVertex v2 = new TreeVertex();
                                    v2.pos       = m.MultiplyPoint(Vector3.zero);
                                    v2.nor       = m.MultiplyVector(normalMid * side).normalized;
                                    v2.tangent   = CreateTangent(node, rot, v2.nor);
                                    v2.tangent.w = -side;
                                    v2.uv0       = new Vector2(0.5f, v);

                                    TreeVertex v3 = new TreeVertex();
                                    v3.pos       = m.MultiplyPoint(directionB * rad);
                                    v3.nor       = m.MultiplyVector(normalB * side).normalized;
                                    v3.tangent   = CreateTangent(node, rot, v3.nor);
                                    v3.tangent.w = -side;
                                    v3.uv0       = new Vector2(0.0f, v);

                                    // Animation properties..
                                    Vector2 windFactors = ComputeWindFactor(node, t);

                                    v0.SetAnimationProperties(windFactors.x, windFactors.y, animationEdge, node.animSeed);
                                    v1.SetAnimationProperties(windFactors.x, windFactors.y, 0.0f, node.animSeed); // no edge flutter for center vertex
                                    v2.SetAnimationProperties(windFactors.x, windFactors.y, 0.0f, node.animSeed); // no edge flutter for center vertex
                                    v3.SetAnimationProperties(windFactors.x, windFactors.y, animationEdge, node.animSeed);

                                    verts.Add(v0); verts.Add(v1); verts.Add(v2); verts.Add(v3);
                                }

                                if (i > 0)
                                {
                                    int voffset = verts.Count;

                                    //
                                    // theoretical left side :)
                                    //
                                    // back
                                    TreeTriangle tri0 = new TreeTriangle(frondMaterialIndex, voffset - 4, voffset - 3, voffset - 11);
                                    TreeTriangle tri1 = new TreeTriangle(frondMaterialIndex, voffset - 4, voffset - 11, voffset - 12);
                                    tri0.flip(); tri1.flip();

                                    // front
                                    TreeTriangle tri2 = new TreeTriangle(frondMaterialIndex, voffset - 8, voffset - 7, voffset - 15);
                                    TreeTriangle tri3 = new TreeTriangle(frondMaterialIndex, voffset - 8, voffset - 15, voffset - 16);

                                    tris.Add(tri0); tris.Add(tri1);
                                    tris.Add(tri2); tris.Add(tri3);

                                    //
                                    // theoretical right side :)
                                    //
                                    // front
                                    TreeTriangle tri4 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 9, voffset - 1);
                                    TreeTriangle tri5 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 10, voffset - 9);

                                    // back
                                    TreeTriangle tri6 = new TreeTriangle(frondMaterialIndex, voffset - 6, voffset - 13, voffset - 5);
                                    TreeTriangle tri7 = new TreeTriangle(frondMaterialIndex, voffset - 6, voffset - 14, voffset - 13);
                                    tri6.flip(); tri7.flip();

                                    tris.Add(tri4); tris.Add(tri5);
                                    tris.Add(tri6); tris.Add(tri7);
                                }
                            }
                            else
                            {
                                // Single sided geometry .. we'll keep this for later

                                TreeVertex v0 = new TreeVertex();
                                v0.pos = m.MultiplyPoint(directionA * rad);
                                v0.nor = m.MultiplyVector(normalA).normalized;
                                v0.uv0 = new Vector2(0.0f, v);

                                TreeVertex v1 = new TreeVertex();
                                v1.pos = m.MultiplyPoint(Vector3.zero);
                                v1.nor = m.MultiplyVector(Vector3.back).normalized;
                                v1.uv0 = new Vector2(0.5f, v);

                                TreeVertex v2 = new TreeVertex();
                                v2.pos = m.MultiplyPoint(directionB * rad);
                                v2.nor = m.MultiplyVector(normalB).normalized;
                                v2.uv0 = new Vector2(1.0f, v);

                                // Animation properties..
                                Vector2 windFactors = ComputeWindFactor(node, t);

                                v0.SetAnimationProperties(windFactors.x, windFactors.y, animationEdge, node.animSeed);
                                v1.SetAnimationProperties(windFactors.x, windFactors.y, 0.0f, node.animSeed); // no edge flutter for center vertex
                                v2.SetAnimationProperties(windFactors.x, windFactors.y, animationEdge, node.animSeed);

                                verts.Add(v0); verts.Add(v1); verts.Add(v2);

                                if (i > 0)
                                {
                                    int voffset = verts.Count;

                                    TreeTriangle tri0 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 3, voffset - 6);
                                    TreeTriangle tri1 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 6, voffset - 5);
                                    tris.Add(tri0); tris.Add(tri1);

                                    TreeTriangle tri2 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 4, voffset - 1);
                                    TreeTriangle tri3 = new TreeTriangle(frondMaterialIndex, voffset - 2, voffset - 5, voffset - 4);
                                    tris.Add(tri2); tris.Add(tri3);
                                }
                            }
                        }
                    }
                }
            }

            // compute ambient occlusion..
            if ((buildFlags & (int)BuildFlag.BuildAmbientOcclusion) != 0)
            {
                for (int i = vertOffset; i < verts.Count; i++)
                {
                    verts[i].SetAmbientOcclusion(ComputeAmbientOcclusion(verts[i].pos, verts[i].nor, aoSpheres, aoDensity));
                }
            }

            node.vertEnd = verts.Count;

            Profiler.EndSample(); // TreeGroupBranch.UpdateNodeMesh
        }