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; } }
public void GenerateLightningBolt(LightningBolt bolt, LightningBoltParameters p) { Vector3 start = p.ApplyVariance(p.Start, p.StartVariance); Vector3 end = p.ApplyVariance(p.End, p.EndVariance); OnGenerateLightningBolt(bolt, start, end, p); }
public void CreateFork(LightningBolt bolt, LightningBoltParameters p, int generation, int totalGenerations, Vector3 start, Vector3 midPoint) { if (ShouldCreateFork(p, generation, totalGenerations)) { Vector3 branchVector = (midPoint - start) * p.ForkMultiplier(); Vector3 splitEnd = midPoint + branchVector; GenerateLightningBoltStandard(bolt, midPoint, splitEnd, generation, totalGenerations, 0.0f, p); } }
/// <summary> /// Create multiple lightning bolts, attempting to batch them into as few draw calls as possible /// </summary> /// <param name="parameters">Lightning bolt creation parameters</param> public void CreateLightningBolts(ICollection <LightningBoltParameters> parameters) { if (parameters != null && parameters.Count != 0) { UpdateTexture(); LightningBolt bolt = GetOrCreateLightningBolt(); LightningBoltDependencies dependencies = CreateLightningBoltDependencies(parameters); bolt.SetupLightningBolt(dependencies); } }
public void GenerateLightningBolt(LightningBoltParameters p, LightningBolt bolt) { CurrentBolt = bolt; Vector3 start = p.ApplyVariance(p.Start, p.StartVariance); Vector3 end = p.ApplyVariance(p.End, p.EndVariance); OnGenerateLightningBolt(start, end, p); CurrentBolt = null; }
/// <summary> /// Create a lightning bolt /// </summary> /// <param name="p">Lightning bolt creation parameters</param> public virtual void CreateLightningBolt(LightningBoltParameters p) { if (p != null) { UpdateTexture(); oneParameterArray[0] = p; LightningBolt bolt = GetOrCreateLightningBolt(); LightningBoltDependencies dependencies = CreateLightningBoltDependencies(oneParameterArray); bolt.SetupLightningBolt(dependencies); } }
public void RandomVector(LightningBolt bolt, ref Vector3 start, ref Vector3 end, float offsetAmount, System.Random random, out Vector3 result) { if (bolt.CameraMode == CameraMode.Perspective) { Vector3 direction = (end - start).normalized; Vector3 side = Vector3.Cross(start, end); if (side == Vector3.zero) { // slow path, rarely hit unless cross product is zero GetPerpendicularVector(ref direction, out side); } else { side.Normalize(); } // generate random distance and angle float distance = (((float)random.NextDouble() + 0.1f) * offsetAmount); #if DEBUG float rotationAngle = ((float)random.NextDouble() * 360.0f); result = Quaternion.AngleAxis(rotationAngle, direction) * side * distance; #else // optimized path for RELEASE mode, skips two normalize and two multiplies in Quaternion.AngleAxis float rotationAngle = ((float)random.NextDouble() * Mathf.PI); direction *= (float)System.Math.Sin(rotationAngle); Quaternion rotation; rotation.x = direction.x; rotation.y = direction.y; rotation.z = direction.z; rotation.w = (float)System.Math.Cos(rotationAngle); result = rotation * side * distance; #endif } else if (bolt.CameraMode == CameraMode.OrthographicXY) { // XY plane end.z = start.z; Vector3 directionNormalized = (end - start).normalized; Vector3 side = new Vector3(-directionNormalized.y, directionNormalized.x, 0.0f); float distance = ((float)random.NextDouble() * offsetAmount * 2.0f) - offsetAmount; result = side * distance; } else { // XZ plane end.y = start.y; Vector3 directionNormalized = (end - start).normalized; Vector3 side = new Vector3(-directionNormalized.z, 0.0f, directionNormalized.x); float distance = ((float)random.NextDouble() * offsetAmount * 2.0f) - offsetAmount; result = side * distance; } }
internal void AddActiveBolt(LightningBolt bolt) { #if DEBUG if (bolt == null || activeBolts.Contains(bolt)) { Debug.LogError("Attempted to add null or duplicate active lightning bolt"); return; } #endif // only called from the main thread activeBolts.Add(bolt); }
private void UpdateActiveBolts() { for (int i = activeBolts.Count - 1; i >= 0; i--) { LightningBolt bolt = activeBolts[i]; if (!bolt.Update()) { // bolt is done, remove it and put back in cache activeBolts.RemoveAt(i); bolt.Cleanup(); lightningBoltCache.Add(bolt); } } }
private LightningBolt GetOrCreateLightningBolt() { if (lightningBoltCache.Count == 0) { #if ENABLE_PROFILING Debug.Log("Lightning cache miss"); #endif return(new LightningBolt()); } LightningBolt b = lightningBoltCache[lightningBoltCache.Count - 1]; lightningBoltCache.RemoveAt(lightningBoltCache.Count - 1); return(b); }
/// <summary> /// Create multiple lightning bolts, attempting to batch them into as few draw calls as possible /// </summary> /// <param name="parameters">Lightning bolt creation parameters</param> public void CreateLightningBolts(ICollection <LightningBoltParameters> parameters) { #if UNITY_EDITOR if (Camera == null) { UnityEngine.Debug.LogError("Camera not assigned to lightning script. Either set the camera or tag your camera as main camera."); } #endif if (parameters != null && parameters.Count != 0 && Camera != null) { UpdateTexture(); LightningBolt bolt = GetOrCreateLightningBolt(); LightningBoltDependencies dependencies = CreateLightningBoltDependencies(parameters); bolt.SetupLightningBolt(dependencies); } }
/// <summary> /// Create a lightning bolt /// </summary> /// <param name="p">Lightning bolt creation parameters</param> public virtual void CreateLightningBolt(LightningBoltParameters p) { #if UNITY_EDITOR if (Camera == null) { UnityEngine.Debug.LogError("Camera not assigned to lightning script. Either set the camera or tag your camera as main camera."); } #endif if (p != null && Camera != null) { UpdateTexture(); oneParameterArray[0] = p; LightningBolt bolt = GetOrCreateLightningBolt(); LightningBoltDependencies dependencies = CreateLightningBoltDependencies(oneParameterArray); bolt.SetupLightningBolt(dependencies); } }
private void OnSceneLoaded(UnityEngine.SceneManagement.Scene arg0, UnityEngine.SceneManagement.LoadSceneMode arg1) { LightningBolt.ClearCache(); }
private LineRendererMesh CreateLineRenderer(LightningBolt lightningBolt, List<LineRendererMesh> lineRenderers) { LineRendererMesh lineRenderer; if (rendererCache.Count == 0) { // create a line renderer in a new game object underneath the parent GameObject obj = new GameObject(); obj.name = "LightningBoltMeshRenderer"; obj.hideFlags = HideFlags.HideAndDontSave; lineRenderer = obj.AddComponent<LineRendererMesh>(); } else { lineRenderer = rendererCache[rendererCache.Count - 1]; rendererCache.RemoveAt(rendererCache.Count - 1); } // clear parent - this ensures that the rotation and scale can be reset before assigning a new parent lineRenderer.gameObject.transform.parent = null; lineRenderer.gameObject.transform.rotation = Quaternion.identity; lineRenderer.gameObject.transform.localScale = Vector3.one; lineRenderer.gameObject.transform.parent = lightningBolt.Parent.transform; lineRenderer.gameObject.layer = lightningBolt.Parent.layer; // maintain the layer of the parent if (lightningBolt.UseWorldSpace) { lineRenderer.gameObject.transform.position = Vector3.zero; } else { lineRenderer.gameObject.transform.localPosition = Vector3.zero; } lineRenderer.Material = (lightningBolt.HasGlow ? Material : MaterialNoGlow); lineRenderer.MeshRenderer.sortingLayerName = lightningBolt.SortLayerName; lineRenderer.MeshRenderer.sortingOrder = lightningBolt.SortOrderInLayer; currentLineRenderer = lineRenderer; lineRenderers.Add(lineRenderer); return lineRenderer; }
public void Begin(LightningBolt lightningBolt) { List<LineRendererMesh> lineRenderers; if (!renderers.TryGetValue(lightningBolt, out lineRenderers)) { lineRenderers = new List<LineRendererMesh>(); renderers[lightningBolt] = lineRenderers; CreateLineRenderer(lightningBolt, lineRenderers); } }
public void End(LightningBolt lightningBolt) { if (currentLineRenderer != null) { Script.StartCoroutine(EnableRenderer(currentLineRenderer, lightningBolt)); currentLineRenderer = null; } }
public void Cleanup(LightningBolt lightningBolt) { List<LineRendererMesh> lineRenderers; if (renderers.TryGetValue(lightningBolt, out lineRenderers)) { renderers.Remove(lightningBolt); foreach (LineRendererMesh lineRenderer in lineRenderers) { rendererCache.Add(lineRenderer); lineRenderer.Reset(); } } }
protected override void OnGenerateLightningBolt(LightningBolt bolt, Vector3 start, Vector3 end, LightningBoltParameters p) { GenerateLightningBoltPath(bolt, start, end, p); }
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; } } }
private IEnumerator EnableRenderer(LineRendererMesh renderer, LightningBolt lightningBolt) { yield return new WaitForSeconds(lightningBolt.MinimumDelay); if (renderer != null && lightningBolt.IsActive) { renderer.Begin(); } }
public void GenerateLightningBolt(LightningBolt bolt, LightningBoltParameters p) { Vector3 start, end; GenerateLightningBolt(bolt, p, out start, out end); }
protected virtual void OnGenerateLightningBolt(LightningBolt bolt, Vector3 start, Vector3 end, LightningBoltParameters p) { GenerateLightningBoltStandard(bolt, start, end, p.Generations, p.Generations, 0.0f, p); }
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); } }