Exemplo n.º 1
0
        public void GenerateLightningBoltStandard(LightningBolt bolt, Vector3 start, Vector3 end, int generation, int totalGenerations, float offsetAmount, LightningBoltParameters p)
        {
            if (generation < 1)
            {
                return;
            }

            LightningBoltSegmentGroup group = bolt.AddGroup();

            group.Segments.Add(new LightningBoltSegment {
                Start = start, End = end
            });

            // every generation, get the percentage we have gone down and square it, this makes lines thinner
            float widthMultiplier = (float)generation / (float)totalGenerations;

            widthMultiplier *= widthMultiplier;

            Vector3 randomVector;

            group.LineWidth          = p.TrunkWidth * widthMultiplier;
            group.Generation         = generation;
            group.Color              = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(255.0f * widthMultiplier));
            group.EndWidthMultiplier = p.EndWidthMultiplier * p.ForkEndWidthMultiplier;
            if (offsetAmount <= 0.0f)
            {
                offsetAmount = (end - start).magnitude * p.ChaosFactor;
            }

            while (generation-- > 0)
            {
                int previousStartIndex = group.StartIndex;
                group.StartIndex = group.Segments.Count;
                for (int i = previousStartIndex; i < group.StartIndex; i++)
                {
                    start = group.Segments[i].Start;
                    end   = group.Segments[i].End;

                    // determine a new direction for the split
                    Vector3 midPoint = (start + end) * 0.5f;

                    // adjust the mid point to be the new location
                    RandomVector(bolt, ref start, ref end, offsetAmount, p.Random, out randomVector);
                    midPoint += randomVector;

                    // add two new segments
                    group.Segments.Add(new LightningBoltSegment {
                        Start = start, End = midPoint
                    });
                    group.Segments.Add(new LightningBoltSegment {
                        Start = midPoint, End = end
                    });

                    CreateFork(bolt, p, generation, totalGenerations, start, midPoint);
                }

                // halve the distance the lightning can deviate for each generation down
                offsetAmount *= 0.5f;
            }
        }
Exemplo n.º 2
0
        private void CreateLightsForGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, LightningBoltQualitySetting quality, int maxLights)
        {
            if (lightCount == MaximumLightCount || maxLights <= 0)
            {
                return;
            }

            float fadeOutTime       = (lifeTime - group.PeakEnd) * lp.FadeOutMultiplier;
            float peakGap           = (group.PeakEnd - group.PeakStart) * lp.FadeFullyLitMultiplier;
            float peakStart         = group.PeakStart * lp.FadeInMultiplier;
            float peakEnd           = peakStart + peakGap;
            float maxLifeWithLights = peakEnd + fadeOutTime;

            maxLifeTime = Mathf.Max(maxLifeTime, group.Delay + maxLifeWithLights);

            segmentGroupsWithLight.Add(group);

            int   segmentCount = group.SegmentCount;
            float lightPercent, lightShadowPercent;

            if (quality == LightningBoltQualitySetting.LimitToQualitySetting)
            {
                int level = QualitySettings.GetQualityLevel();
                LightningQualityMaximum maximum;
                if (LightningBoltParameters.QualityMaximums.TryGetValue(level, out maximum))
                {
                    lightPercent       = Mathf.Min(lp.LightPercent, maximum.MaximumLightPercent);
                    lightShadowPercent = Mathf.Min(lp.LightShadowPercent, maximum.MaximumShadowPercent);
                }
                else
                {
                    Debug.LogError("Unable to read lightning quality for level " + level.ToString());
                    lightPercent       = lp.LightPercent;
                    lightShadowPercent = lp.LightShadowPercent;
                }
            }
            else
            {
                lightPercent       = lp.LightPercent;
                lightShadowPercent = lp.LightShadowPercent;
            }

            maxLights = Mathf.Max(1, Mathf.Min(maxLights, (int)(segmentCount * lightPercent)));
            int nthLight         = Mathf.Max(1, (int)((segmentCount / maxLights)));
            int nthShadows       = maxLights - (int)((float)maxLights * lightShadowPercent);
            int nthShadowCounter = nthShadows;

            // add lights evenly spaced
            for (int i = group.StartIndex + (int)(nthLight * 0.5f); i < group.Segments.Count; i += nthLight)
            {
                if (AddLightToGroup(group, lp, i, nthLight, nthShadows, ref maxLights, ref nthShadowCounter))
                {
                    return;
                }
            }

            // Debug.Log("Lightning light count: " + lightCount.ToString());
        }
Exemplo n.º 3
0
        public LightningBoltSegmentGroup CreateGroup()
        {
            LightningBoltSegmentGroup g;

            if (groupCache.Count == 0)
            {
                g = new LightningBoltSegmentGroup();
            }
            else
            {
                int index = groupCache.Count - 1;
                g = groupCache[index];
                groupCache.RemoveAt(index);
            }
            CurrentBolt.segmentGroups.Add(g);
            return(g);
        }
Exemplo n.º 4
0
        public LightningBoltSegmentGroup AddGroup()
        {
            LightningBoltSegmentGroup group;

            lock (groupCache)
            {
                if (groupCache.Count == 0)
                {
                    group = new LightningBoltSegmentGroup();
                }
                else
                {
                    int index = groupCache.Count - 1;
                    group = groupCache[index];
                    group.Reset();
                    groupCache.RemoveAt(index);
                }
            }
            segmentGroups.Add(group);
            return(group);
        }
Exemplo n.º 5
0
        private bool AddLightToGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, int segmentIndex,
                                     int nthLight, int nthShadows, ref int maxLights, ref int nthShadowCounter)
        {
            Light light = GetOrCreateLight(lp);

            group.Lights.Add(light);
            Vector3 pos = (group.Segments[segmentIndex].Start + group.Segments[segmentIndex].End) * 0.5f;

            if (dependencies.CameraIsOrthographic)
            {
                if (dependencies.CameraMode == CameraMode.OrthographicXZ)
                {
                    pos.y = dependencies.CameraPos.y + lp.OrthographicOffset;
                }
                else
                {
                    pos.z = dependencies.CameraPos.z + lp.OrthographicOffset;
                }
            }
            if (dependencies.UseWorldSpace)
            {
                light.gameObject.transform.position = pos;
            }
            else
            {
                light.gameObject.transform.localPosition = pos;
            }
            if (lp.LightShadowPercent == 0.0f || ++nthShadowCounter < nthShadows)
            {
                light.shadows = LightShadows.None;
            }
            else
            {
                light.shadows    = LightShadows.Soft;
                nthShadowCounter = 0;
            }

            // return true if no more lights possible, false otherwise
            return(++lightCount == MaximumLightCount || --maxLights == 0);
        }
Exemplo n.º 6
0
        public void GenerateLightningBoltPath(LightningBolt bolt, Vector3 start, Vector3 end, LightningBoltParameters p)
        {
            if (p.Points.Count < 2)
            {
                Debug.LogError("Lightning path should have at least two points");
                return;
            }

            int     generation = p.Generations;
            int     totalGenerations = generation;
            float   offsetAmount, d;
            int     smoothingFactor = p.SmoothingFactor - 1;
            Vector3 distance, randomVector;
            LightningBoltSegmentGroup group = bolt.AddGroup();

            group.LineWidth          = p.TrunkWidth;
            group.Generation         = generation--;
            group.EndWidthMultiplier = p.EndWidthMultiplier;
            group.Color = Color.white;

            p.Start = p.Points[0] + start;
            p.End   = p.Points[p.Points.Count - 1] + end;
            end     = p.Start;

            for (int i = 1; i < p.Points.Count; i++)
            {
                start    = end;
                end      = p.Points[i];
                distance = (end - start);
                d        = PathGenerator.SquareRoot(distance.sqrMagnitude);
                if (p.ChaosFactor > 0.0f)
                {
                    if (bolt.CameraMode == CameraMode.Perspective)
                    {
                        end += (d * p.ChaosFactor * RandomDirection3D(p.Random));
                    }
                    else if (bolt.CameraMode == CameraMode.OrthographicXY)
                    {
                        end += (d * p.ChaosFactor * RandomDirection2D(p.Random));
                    }
                    else
                    {
                        end += (d * p.ChaosFactor * RandomDirection2DXZ(p.Random));
                    }
                    distance = (end - start);
                }
                group.Segments.Add(new LightningBoltSegment {
                    Start = start, End = end
                });

                offsetAmount = d * p.ChaosFactor;
                RandomVector(bolt, ref start, ref end, offsetAmount, p.Random, out randomVector);

                if (ShouldCreateFork(p, generation, totalGenerations))
                {
                    Vector3 branchVector = distance * p.ForkMultiplier() * smoothingFactor * 0.5f;
                    Vector3 forkEnd      = end + branchVector + randomVector;
                    GenerateLightningBoltStandard(bolt, start, forkEnd, generation, totalGenerations, 0.0f, p);
                }

                if (--smoothingFactor == 0)
                {
                    smoothingFactor = p.SmoothingFactor - 1;
                }
            }
        }
Exemplo n.º 7
0
        private Transform RenderLightningBolt(LightningBoltQualitySetting quality, int generations, int startGroupIndex, int endGroupIndex, LightningBoltParameters parameters)
        {
            if (segmentGroups.Count == 0 || startGroupIndex >= segmentGroups.Count || endGroupIndex > segmentGroups.Count)
            {
                return(null);
            }

            Transform transform         = null;
            LightningLightParameters lp = parameters.LightParameters;

            if (lp != null)
            {
                if ((hasLight |= lp.HasLight))
                {
                    lp.LightPercent       = Mathf.Clamp(lp.LightPercent, Mathf.Epsilon, 1.0f);
                    lp.LightShadowPercent = Mathf.Clamp(lp.LightShadowPercent, 0.0f, 1.0f);
                }
                else
                {
                    lp = null;
                }
            }

            LightningBoltSegmentGroup mainTrunkGroup = segmentGroups[startGroupIndex];
            Vector3 start = mainTrunkGroup.Segments[mainTrunkGroup.StartIndex].Start;
            Vector3 end   = mainTrunkGroup.Segments[mainTrunkGroup.StartIndex + mainTrunkGroup.SegmentCount - 1].End;

            parameters.FadePercent = Mathf.Clamp(parameters.FadePercent, 0.0f, 0.5f);

            // create a new line renderer mesh right now if we have a custom transform
            if (parameters.CustomTransform != null)
            {
                LineRendererMesh currentLineRenderer = (activeLineRenderers.Count == 0 || !activeLineRenderers[activeLineRenderers.Count - 1].Empty ? null : activeLineRenderers[activeLineRenderers.Count - 1]);

                if (currentLineRenderer == null)
                {
#if !UNITY_WEBGL
                    if (dependencies.ThreadState != null)
                    {
                        // we need to block until this action is run, Unity objects can only be modified and created on the main thread
                        dependencies.ThreadState.AddActionForMainThread(() =>
                        {
                            EnableCurrentLineRenderer();
                            currentLineRenderer = GetOrCreateLineRenderer();
                        }, true);
                    }
                    else
#endif

                    {
                        EnableCurrentLineRenderer();
                        currentLineRenderer = GetOrCreateLineRenderer();
                    }
                }
                if (currentLineRenderer == null)
                {
                    return(null);
                }

                currentLineRenderer.CustomTransform = parameters.CustomTransform;
                transform = currentLineRenderer.Transform;
            }

            for (int i = startGroupIndex; i < endGroupIndex; i++)
            {
                LightningBoltSegmentGroup group = segmentGroups[i];
                group.Delay     = parameters.delaySeconds;
                group.LifeTime  = parameters.LifeTime;
                group.PeakStart = group.LifeTime * parameters.FadePercent;
                group.PeakEnd   = group.LifeTime - group.PeakStart;
                float peakGap = group.PeakEnd - group.PeakStart;
                float fadeOut = group.LifeTime - group.PeakEnd;
                group.PeakStart      *= parameters.FadeInMultiplier;
                group.PeakEnd         = group.PeakStart + (peakGap * parameters.FadeFullyLitMultiplier);
                group.LifeTime        = group.PeakEnd + (fadeOut * parameters.FadeOutMultiplier);
                group.LightParameters = lp;
                RenderGroup(group, parameters);
            }

#if !UNITY_WEBGL
            if (dependencies.ThreadState != null)
            {
                dependencies.ThreadState.AddActionForMainThread(() =>
                {
                    RenderParticleSystems(start, end, parameters.TrunkWidth, parameters.LifeTime, parameters.delaySeconds);

                    // create lights only on the main trunk
                    if (lp != null)
                    {
                        CreateLightsForGroup(segmentGroups[startGroupIndex], lp, quality, parameters.maxLights);
                    }
                });
            }
            else
#endif

            {
                RenderParticleSystems(start, end, parameters.TrunkWidth, parameters.LifeTime, parameters.delaySeconds);

                // create lights only on the main trunk
                if (lp != null)
                {
                    CreateLightsForGroup(segmentGroups[startGroupIndex], lp, quality, parameters.maxLights);
                }
            }

            return(transform);
        }
Exemplo n.º 8
0
        private void RenderGroup(LightningBoltSegmentGroup group, LightningBoltParameters p)
        {
            if (group.SegmentCount == 0)
            {
                return;
            }

#if UNITY_WEBGL
            float timeOffset = 0.0f;
#else
            float timeOffset = (dependencies.ThreadState == null ? 0.0f : (float)(DateTime.UtcNow - startTimeOffset).TotalSeconds);
#endif

            float   timeStart    = timeSinceLevelLoad + group.Delay + timeOffset;
            Vector4 fadeLifeTime = new Vector4(timeStart, timeStart + group.PeakStart, timeStart + group.PeakEnd, timeStart + group.LifeTime);
            float   radius       = group.LineWidth * 0.5f * LightningBoltParameters.Scale;
            int     lineCount    = (group.Segments.Count - group.StartIndex);
            float   radiusStep   = (radius - (radius * group.EndWidthMultiplier)) / (float)lineCount;

            // growth multiplier
            float timeStep;
            if (p.GrowthMultiplier > 0.0f)
            {
                timeStep   = (group.LifeTime / (float)lineCount) * p.GrowthMultiplier;
                timeOffset = 0.0f;
            }
            else
            {
                timeStep   = 0.0f;
                timeOffset = 0.0f;
            }

            LineRendererMesh currentLineRenderer = (activeLineRenderers.Count == 0 ? GetOrCreateLineRenderer() : activeLineRenderers[activeLineRenderers.Count - 1]);

            // if we have filled up the mesh, we need to start a new line renderer
            if (!currentLineRenderer.PrepareForLines(lineCount))
            {
                if (currentLineRenderer.CustomTransform != null)
                {
                    // can't create multiple meshes if using a custom transform callback
                    return;
                }

#if !UNITY_WEBGL
                if (dependencies.ThreadState != null)
                {
                    // we need to block until this action is run, Unity objects can only be modified and created on the main thread
                    dependencies.ThreadState.AddActionForMainThread(() =>
                    {
                        EnableCurrentLineRenderer();
                        currentLineRenderer = GetOrCreateLineRenderer();
                    }, true);
                }
                else
#endif

                {
                    EnableCurrentLineRenderer();
                    currentLineRenderer = GetOrCreateLineRenderer();
                }
            }

            currentLineRenderer.BeginLine(group.Segments[group.StartIndex].Start, group.Segments[group.StartIndex].End, radius, group.Color, p.Intensity, fadeLifeTime, p.GlowWidthMultiplier, p.GlowIntensity);
            for (int i = group.StartIndex + 1; i < group.Segments.Count; i++)
            {
                radius -= radiusStep;
                if (p.GrowthMultiplier < 1.0f)
                {
                    timeOffset  += timeStep;
                    fadeLifeTime = new Vector4(timeStart + timeOffset, timeStart + group.PeakStart + timeOffset, timeStart + group.PeakEnd, timeStart + group.LifeTime);
                }
                currentLineRenderer.AppendLine(group.Segments[i].Start, group.Segments[i].End, radius, group.Color, p.Intensity, fadeLifeTime, p.GlowWidthMultiplier, p.GlowIntensity);
            }
        }
Exemplo n.º 9
0
        public void AddGroup(LightningBolt lightningBolt, LightningBoltSegmentGroup group, float growthMultiplier)
        {
            if (group.SegmentCount == 0)
            {
                return;
            }

            List<LineRendererMesh> lineRenderers = renderers[lightningBolt];
            LineRendererMesh lineRenderer = lineRenderers[lineRenderers.Count - 1];
            float timeStart = Time.timeSinceLevelLoad + group.Delay;
            Vector4 fadeLifeTime = new Vector4(timeStart, timeStart + group.PeakStart, timeStart + group.PeakEnd, timeStart + group.LifeTime);
            float radius = group.LineWidth * 0.5f * LightningBoltParameters.Scale;
            int lineCount = (group.Segments.Count - group.StartIndex);
            float radiusStep = (radius - (radius * group.EndWidthMultiplier)) / (float)lineCount;

            // growth multiplier
            float timeStep, timeOffset;
            if (growthMultiplier > 0.0f)
            {
                timeStep = (group.LifeTime / (float)lineCount) * growthMultiplier;
                timeOffset = 0.0f;
            }
            else
            {
                timeStep = 0.0f;
                timeOffset = 0.0f;
            }

            if (!lineRenderer.PrepareForLines(lineCount))
            {
                Script.StartCoroutine(EnableRenderer(lineRenderer, lightningBolt));
                lineRenderer = CreateLineRenderer(lightningBolt, lineRenderers);
            }

            lineRenderer.BeginLine(group.Segments[group.StartIndex].Start, group.Segments[group.StartIndex].End, radius, group.Color, fadeLifeTime, GlowWidthMultiplier, GlowIntensityMultiplier);
            for (int i = group.StartIndex + 1; i < group.Segments.Count; i++)
            {
                radius -= radiusStep;
                if (growthMultiplier < 1.0f)
                {
                    timeOffset += timeStep;
                    fadeLifeTime = new Color(timeStart + timeOffset, timeStart + group.PeakStart + timeOffset, timeStart + group.PeakEnd, timeStart + group.LifeTime);
                }
                lineRenderer.AppendLine(group.Segments[i].Start, group.Segments[i].End, radius, group.Color, fadeLifeTime, GlowWidthMultiplier, GlowIntensityMultiplier);
            }
        }
Exemplo n.º 10
0
        private bool AddLightToGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, int segmentIndex,
            int nthLight, int nthShadows, ref int maxLights, ref int nthShadowCounter)
        {
            Light light = CreateLight(lp);
            group.Lights.Add(light);
            Vector3 pos = (group.Segments[segmentIndex].Start + group.Segments[segmentIndex].End) * 0.5f;
            if (Camera != null && Camera.orthographic)
            {
                pos.z = Camera.transform.position.z;
            }
            light.gameObject.transform.position = pos;
            if (lp.LightShadowPercent == 0.0f || ++nthShadowCounter < nthShadows)
            {
                light.shadows = LightShadows.None;
            }
            else
            {
                light.shadows = LightShadows.Soft;
                nthShadowCounter = 0;
            }

            // return true if no more lights possible, false otherwise
            return (++lightCount == MaximumLightCount || --maxLights == 0);
        }
Exemplo n.º 11
0
        private void CreateLightsForGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, LightningBoltQualitySetting quality,
            int maxLights, int groupIndex)
        {
            if (lightCount == MaximumLightCount || maxLights <= 0)
            {
                return;
            }

            segmentGroupsWithLight.Add(group);

            int segmentCount = group.SegmentCount;
            float lightPercent, lightShadowPercent;
            if (quality == LightningBoltQualitySetting.LimitToQualitySetting)
            {
                int level = QualitySettings.GetQualityLevel();
                LightningQualityMaximum maximum;
                if (LightningBoltParameters.QualityMaximums.TryGetValue(level, out maximum))
                {
                    lightPercent = Mathf.Min(lp.LightPercent, maximum.MaximumLightPercent);
                    lightShadowPercent = Mathf.Min(lp.LightShadowPercent, maximum.MaximumShadowPercent);
                }
                else
                {
                    Debug.LogError("Unable to read lightning quality for level " + level.ToString());
                    lightPercent = lp.LightPercent;
                    lightShadowPercent = lp.LightShadowPercent;
                }
            }
            else
            {
                lightPercent = lp.LightPercent;
                lightShadowPercent = lp.LightShadowPercent;
            }

            maxLights = Mathf.Max(1, Mathf.Min(maxLights, (int)(segmentCount * lightPercent)));
            int nthLight = Mathf.Max(1, (int)((segmentCount / maxLights)));
            int nthShadows = maxLights - (int)((float)maxLights * lightShadowPercent);

            int nthShadowCounter = nthShadows;

            // add lights evenly spaced
            for (int i = group.StartIndex + (int)(nthLight * 0.5f); i < group.Segments.Count; i += nthLight)
            {
                if (AddLightToGroup(group, lp, i, nthLight, nthShadows, ref maxLights, ref nthShadowCounter))
                {
                    return;
                }
            }

            // Debug.Log("Lightning light count: " + lightCount.ToString());
        }
Exemplo n.º 12
0
 public LightningBoltSegmentGroup CreateGroup()
 {
     LightningBoltSegmentGroup g;
     if (groupCache.Count == 0)
     {
         g = new LightningBoltSegmentGroup();
     }
     else
     {
         int index = groupCache.Count - 1;
         g = groupCache[index];
         groupCache.RemoveAt(index);
     }
     CurrentBolt.segmentGroups.Add(g);
     return g;
 }
Exemplo n.º 13
0
 public static void ReturnGroupToCache(LightningBoltSegmentGroup group)
 {
     groupCache.Add(group);
 }