public void ShowShield(RadioactiveSource src) { foreach (ShadowShieldEffect shld in src.ShadowShields) { SetupShadowShieldRenderer(shld, src); shadowShields.Add(shld); } }
public RadiationLink(RadioactiveSource src, RadioactiveSink snk) { fluxStart = RadioactivitySettings.defaultRaycastFluxStart; source = src; sink = snk; if (Radioactivity.Instance.RayOverlayShown) ShowOverlay(); //ComputeConnection(src, snk); }
public void HideShield(RadioactiveSource src) { List<ShadowShieldEffect> toClear = new List<ShadowShieldEffect>(); foreach (ShadowShieldEffect shld in shadowShields) { foreach (ShadowShieldEffect shldSrc in src.ShadowShields) { if (shld == shldSrc) { toClear.Add(shld); DestroyShadowShieldRenderer(shld.renderer); } } } for (int i = 0; i < toClear.Count ; i++) { shadowShields.Remove(toClear[i]); } }
protected void SetupShadowShieldRenderer(ShadowShieldEffect shld, RadioactiveSource parent) { GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cylinder); shld.renderer = go; Destroy(go.GetComponent<Collider>()); go.transform.parent = parent.part.partTransform; go.transform.localPosition = shld.localPosition; go.transform.localScale = shld.dimensions; go.transform.up = parent.EmitterTransform.position - go.transform.position; MeshRenderer m = go.GetComponent<MeshRenderer>(); m.material = new Material(Shader.Find(RadioactivitySettings.overlayRayMaterial)); m.material.color = Color.blue; m.material.renderQueue = 3000; if (RadioactivitySettings.debugOverlay) Utils.Log("Overlay: Showing shadow shield on " + parent.SourceID ); }
protected void TryAddSource(RadioactiveSource src) { bool exists = false; for (int i=0; i< allRadSources.Count; i++) { if (allRadSources[i] == src) exists = true; } if (!exists) this.RegisterSource(src); }
// Removes all links to a given radiation source protected void RemoveRadiationLink(RadioactiveSource src) { List <RadiationLink> toRm = new List<RadiationLink>(); for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].source == src) { toRm.Add(allLinks[i]); } } if (toRm.Count> 0) { for (int i = 0; i < toRm.Count; i++) { toRm[i].HideOverlay(); toRm[i].CleanupSink(); allLinks.Remove(toRm[i]); } } }
// Build new links for a new source in the network protected void BuildNewRadiationLink(RadioactiveSource src) { for (int i=0; i< allRadSinks.Count; i++) { RadiationLink l = new RadiationLink(src, allRadSinks[i]); allLinks.Add(l); } }
// Remove a radiation source from the source list public void UnregisterSource(RadioactiveSource src) { if (allRadSources.Count > 0) { pointRadiationNetworkChanged = true; RemoveRadiationLink(src); allRadSources.Remove(src); if (rayOverlayShown && src.ShadowShields.Count > 0) RadioactivityOverlay.Instance.HideShield(src); if (RadioactivitySettings.debugNetwork && src != null) Utils.Log("Network: Removing radiation source " + src.SourceID + " on part " + src.part.name + " from simulator"); } }
// Show the ray overlay for a given source or sink public void ShowOverlay(RadioactiveSource src) { for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].source == src && !allLinks[i].overlayShown) { allLinks[i].ShowOverlay(); } } }
// Add a radiation source to the source list public void RegisterSource(RadioactiveSource src) { allRadSources.Add(src); BuildNewRadiationLink(src); pointRadiationNetworkChanged = true; if (rayOverlayShown && src.ShadowShields.Count > 0) RadioactivityOverlay.Instance.ShowShield(src); if (RadioactivitySettings.debugNetwork) Utils.Log("Network: Adding radiation source "+ src.SourceID +" on part " + src.part.name + " to simulator"); }
//Hide the ray overlay for a given source or sink public void HideOverlay(RadioactiveSource src) { for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].source == src) { allLinks[i].HideOverlay(); } } }
// Compute the ray path between the source and sink public void ComputeGeometry(RadioactiveSource src, RadioactiveSink target) { if (RadioactivitySettings.debugNetwork) Utils.Log("Network: Creating connection from " + src.part.name + " to " + target.part.name); // Store the relative position of both endpoints relPos = Utils.getRelativePosition(src.EmitterTransform, target.SinkTransform.position);//src.EmitterTransform.position - target.SinkTransform.position; // Gets parts between source and sink attenuationPath = GetLineOfSight(src, target); // Attenuate the ray between these fluxStart = src.AttenuateShadowShields(target.SinkTransform.position- src.EmitterTransform.position); fluxEndScale = AttenuateFlux(attenuationPath, fluxStart); needsGeometricRecalculation = false; }
// Computes LOS between a source and a sink // Returns the list of parts between the two objects protected List<AttenuationZone> GetLineOfSight(RadioactiveSource src, RadioactiveSink target) { RaycastHit[] hits1; RaycastHit[] hits2; float sep = Vector3.Distance(src.EmitterTransform.position, target.SinkTransform.position); // Only cast against Default and Terrain LayerMask mask; LayerMask maskA = 1 << LayerMask.NameToLayer("Default"); LayerMask maskB = 1 << LayerMask.NameToLayer("TerrainColliders"); LayerMask maskC = 1 << LayerMask.NameToLayer("Local Scenery"); mask = maskA | maskB | maskC; // raycast from the source to target and vice versa hits1 = Physics.RaycastAll(src.EmitterTransform.position, target.SinkTransform.position - src.EmitterTransform.position, sep, mask); hits2 = Physics.RaycastAll(target.SinkTransform.position, src.EmitterTransform.position - target.SinkTransform.position, sep, mask); List<RaycastHit> hitsBackward = hits2.ToList(); List<RaycastHit> hitsForward = hits1.ToList(); /// sort by distance, ascending if (hitsForward.Count > 0) { hitsForward = hitsForward.OrderBy(o => o.distance).ToList(); } if (hitsBackward.Count > 0) { hitsBackward = hitsBackward.OrderByDescending(o => o.distance).ToList(); } return CreatePathway(hitsForward, hitsBackward, src, target, sep); }
// Go through raycast results (both ways) in order to create the attenuation path protected List<AttenuationZone> CreatePathway(List<RaycastHit> outgoing, List<RaycastHit> incoming, RadioactiveSource src, RadioactiveSink target, float totalPathLength) { List<AttenuationZone> attens = new List<AttenuationZone>(); if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Looking along a distance of " +totalPathLength.ToString() + " with "+ outgoing.Count + " hits"); float curZoneStartDistance = RadioactivitySettings.defaultSourceFluxDistance; float curZoneEndDistance = 0.01f; Vector3 curZoneStartPoint = src.EmitterTransform.position + (target.SinkTransform.position - src.EmitterTransform.position).normalized*curZoneStartDistance; Vector3 curZoneEndPoint = target.SinkTransform.position; int hitNum = 0; // for each object we hit outgoing, see if we found it incoming for (int i=0; i < outgoing.Count; i++) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Looking for incoming rayhits with " + outgoing[i].collider.name); RaycastHit found = incoming.Find(item => item.collider == outgoing[i].collider); // If there is a matching collider if (found.collider != null) { curZoneEndDistance = outgoing[i].distance; curZoneEndPoint = outgoing[i].point; if (curZoneEndDistance - curZoneStartDistance > 0f) { attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); curZoneStartPoint = curZoneEndPoint; curZoneStartDistance = curZoneEndDistance; } int layer = found.collider.gameObject.layer; if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Hit on layer " + LayerMask.LayerToName(layer)); if (layer == LayerMask.NameToLayer("Default")) { Part associatedPart = outgoing[i].collider.GetComponentInParent<Part>(); if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " and part is " + associatedPart.ToString()); if (associatedPart != target.part) { curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, associatedPart, curZoneStartPoint, curZoneEndPoint)); } } if (found.collider.gameObject.layer == LayerMask.NameToLayer("TerrainColliders")) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on terraincolliders layer"); curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } if (found.collider.gameObject.layer == LayerMask.NameToLayer("Local Scenery")) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on LocalScenery layer"); curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } hitNum++; } else { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: No incoming hits with " + outgoing[i].collider.name + ", discarding..."); } } curZoneEndPoint = target.SinkTransform.position; if (hitNum > 0) curZoneStartDistance = curZoneEndDistance; curZoneEndDistance = totalPathLength; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); // TODO: Need to add another AttenuationZone if we start inside a part. probably take the last hit in the incoming array to do this (not the best assumption) // TODO: Need to add another AttenuationZone to account for the target part. probably take the last hit in the outgoing array to do this (good assumption) // Add the empty space as a single zone //if (totalPathLength > 0f) // attens.Add(new AttenuationZone(totalPathLength, src.EmitterTransform.position, target.SinkTransform.position)); return attens; }