private void ProcessParameters(LightningBoltParameters p, RangeOfFloats delay, LightningBoltDependencies depends) { Vector3 start, end; MinimumDelay = Mathf.Min(delay.Minimum, MinimumDelay); p.delaySeconds = delay.Random(p.Random); // apply LOD if specified if (depends.LevelOfDetailDistance > Mathf.Epsilon) { float d; if (p.Points.Count > 1) { d = Vector3.Distance(depends.CameraPos, p.Points[0]); d = Mathf.Min(Vector3.Distance(depends.CameraPos, p.Points[p.Points.Count - 1])); } else { d = Vector3.Distance(depends.CameraPos, p.Start); d = Mathf.Min(Vector3.Distance(depends.CameraPos, p.End)); } int modifier = Mathf.Min(8, (int)(d / depends.LevelOfDetailDistance)); p.Generations = Mathf.Max(1, p.Generations - modifier); p.GenerationWhereForksStopSubtractor = Mathf.Clamp(p.GenerationWhereForksStopSubtractor - modifier, 0, 8); } p.generationWhereForksStop = p.Generations - p.GenerationWhereForksStopSubtractor; lifeTime = Mathf.Max(p.LifeTime + p.delaySeconds, lifeTime); maxLifeTime = Mathf.Max(lifeTime, maxLifeTime); p.forkednessCalculated = (int)Mathf.Ceil(p.Forkedness * (float)p.Generations); if (p.Generations > 0) { p.Generator = p.Generator ?? LightningGenerator.GeneratorInstance; p.Generator.GenerateLightningBolt(this, p, out start, out end); p.Start = start; p.End = end; } }
private static void UpdateTransform(LightningCustomTransformStateInfo state, LightningBoltPrefabScript script, RangeOfFloats scaleLimit) { if (state.Transform == null || state.StartTransform == null) { return; } else if (state.EndTransform == null) { // just put the lightning at the start and be done state.Transform.position = state.StartTransform.position - state.BoltStartPosition; return; } Quaternion rotation; if ((script.CameraMode == CameraMode.Auto && script.Camera.orthographic) || (script.CameraMode == CameraMode.OrthographicXY)) { // 2D rotation delta (xy) float startAngle = AngleBetweenVector2(state.BoltStartPosition, state.BoltEndPosition); float currentAngle = AngleBetweenVector2(state.StartTransform.position, state.EndTransform.position); rotation = Quaternion.AngleAxis((currentAngle - startAngle), Vector3.forward); } if (script.CameraMode == CameraMode.OrthographicXZ) { // 2D rotation delta (xz) float startAngle = AngleBetweenVector2(new Vector2(state.BoltStartPosition.x, state.BoltStartPosition.z), new Vector2(state.BoltEndPosition.x, state.BoltEndPosition.z)); float currentAngle = AngleBetweenVector2(new Vector2(state.StartTransform.position.x, state.StartTransform.position.z), new Vector2(state.EndTransform.position.x, state.EndTransform.position.z)); rotation = Quaternion.AngleAxis((currentAngle - startAngle), Vector3.up); } else { // 3D rotation delta Quaternion look1 = Quaternion.LookRotation((state.BoltEndPosition - state.BoltStartPosition).normalized); Quaternion look2 = Quaternion.LookRotation((state.EndTransform.position - state.StartTransform.position).normalized); rotation = look2 * Quaternion.Inverse(look1); } state.Transform.rotation = rotation; // scale based on how much the objects have moved relative to each other float startDistance = Vector3.Distance(state.BoltStartPosition, state.BoltEndPosition); float endDistance = Vector3.Distance(state.EndTransform.position, state.StartTransform.position); float scale = Mathf.Clamp((startDistance < Mathf.Epsilon ? 1.0f : endDistance / startDistance), scaleLimit.Minimum, scaleLimit.Maximum); state.Transform.localScale = new Vector3(scale, scale, scale); // anchor lightning to start position and account for rotation and scale Vector3 offset = rotation * (scale * state.BoltStartPosition); state.Transform.position = state.StartTransform.position - offset; }
private void Strike(Vector3?_start, Vector3?_end, bool intense, float intensity, Camera camera, Camera visibleInCamera) { // find a point around the camera that is not too close const float minDistance = 500.0f; float minValue = (intense ? -1000.0f : -5000.0f); float maxValue = (intense ? 1000 : 5000.0f); float closestValue = (intense ? 500.0f : 2500.0f); float x = (UnityEngine.Random.Range(0, 2) == 0 ? UnityEngine.Random.Range(minValue, -closestValue) : UnityEngine.Random.Range(closestValue, maxValue)); float y = script.LightningYStart; float z = (UnityEngine.Random.Range(0, 2) == 0 ? UnityEngine.Random.Range(minValue, -closestValue) : UnityEngine.Random.Range(closestValue, maxValue)); Vector3 start = script.Camera.transform.position; start.x += x; start.y = y; start.z += z; if (visibleInCamera != null) { // try and make sure the strike is visible in the camera Quaternion q = visibleInCamera.transform.rotation; visibleInCamera.transform.rotation = Quaternion.Euler(0.0f, q.eulerAngles.y, 0.0f); float screenX = UnityEngine.Random.Range(visibleInCamera.pixelWidth * 0.1f, visibleInCamera.pixelWidth * 0.9f); float ScreenZ = UnityEngine.Random.Range(visibleInCamera.nearClipPlane + closestValue + closestValue, maxValue); Vector3 point = visibleInCamera.ScreenToWorldPoint(new Vector3(screenX, 0.0f, ScreenZ)); start = point; start.y = y; visibleInCamera.transform.rotation = q; } Vector3 end = start; x = UnityEngine.Random.Range(-100, 100.0f); // 1 in 4 chance not to strike the ground y = (UnityEngine.Random.Range(0, 4) == 0 ? UnityEngine.Random.Range(-1, 600.0f) : -1.0f); z += UnityEngine.Random.Range(-100.0f, 100.0f); end.x += x; end.y = y; end.z += z; // make sure the bolt points away from the camera end.x += (closestValue * camera.transform.forward.x); end.z += (closestValue * camera.transform.forward.z); while ((start - end).magnitude < minDistance) { end.x += (closestValue * camera.transform.forward.x); end.z += (closestValue * camera.transform.forward.z); } start = (_start ?? start); end = (_end ?? end); // see if the bolt hit anything on it's way to the ground - if so, change the end point RaycastHit hit; if (Physics.Raycast(start, (start - end).normalized, out hit, float.MaxValue)) { end = hit.point; } int generations = script.LightningBoltScript.Generations; RangeOfFloats trunkWidth = script.LightningBoltScript.TrunkWidthRange; if (UnityEngine.Random.value < script.CloudLightningChance) { // cloud only lightning script.LightningBoltScript.TrunkWidthRange = new RangeOfFloats(); script.LightningBoltScript.Generations = 1; } script.LightningBoltScript.LightParameters.LightIntensity = intensity * 0.5f; script.LightningBoltScript.Trigger(start, end); script.LightningBoltScript.TrunkWidthRange = trunkWidth; script.LightningBoltScript.Generations = generations; }
private void ProcessAllLightningParameters() { int maxLightsForEachParameters = MaximumLightsPerBatch / dependencies.Parameters.Count; RangeOfFloats delay = new RangeOfFloats(); List <int> groupIndexes = new List <int>(dependencies.Parameters.Count + 1); int i = 0; #if ENABLE_PROFILING System.Diagnostics.Stopwatch w = System.Diagnostics.Stopwatch.StartNew(); #endif foreach (LightningBoltParameters parameters in dependencies.Parameters) { delay.Minimum = parameters.DelayRange.Minimum + parameters.Delay; delay.Maximum = parameters.DelayRange.Maximum + parameters.Delay; parameters.maxLights = maxLightsForEachParameters; groupIndexes.Add(segmentGroups.Count); ProcessParameters(parameters, delay, dependencies); } groupIndexes.Add(segmentGroups.Count); #if ENABLE_PROFILING w.Stop(); UnityEngine.Debug.LogFormat("GENERATE: {0}", w.Elapsed.TotalMilliseconds); w.Reset(); w.Start(); #endif LightningBoltDependencies dependenciesRef = dependencies; foreach (LightningBoltParameters parameters in dependenciesRef.Parameters) { Transform transform = RenderLightningBolt(parameters.quality, parameters.Generations, groupIndexes[i], groupIndexes[++i], parameters); #if !UNITY_WEBGL if (dependenciesRef.ThreadState != null) { dependenciesRef.ThreadState.AddActionForMainThread(() => { dependenciesRef.StartCoroutine(NotifyBolt(dependenciesRef, parameters, transform, parameters.Start, parameters.End)); }); } else #endif { dependenciesRef.StartCoroutine(NotifyBolt(dependenciesRef, parameters, transform, parameters.Start, parameters.End)); } } #if ENABLE_PROFILING w.Stop(); UnityEngine.Debug.LogFormat("RENDER: {0}", w.Elapsed.TotalMilliseconds); #endif #if !UNITY_WEBGL if (dependencies.ThreadState != null) { dependencies.ThreadState.AddActionForMainThread(EnableCurrentLineRendererFromThread); } else #endif { EnableCurrentLineRenderer(); dependencies.AddActiveBolt(this); } }