/// <summary> /// Recalculates the distance to a hit item, or -1f if nothing /// was hit by the laser. /// </summary> /// <returns></returns> private void castUpdate() { if (resetHitThisUpdate) { updateForcedResultAge = 0; } else { ++updateForcedResultAge; } float newDist = -1f; // The location of origin is different in LateUpdate than it is // in Update, so it has to be reset in both: origin = this.part.transform.TransformPoint(relLaserOrigin); pointing = this.part.transform.rotation * Vector3d.down; HitName = "<none>"; if (hasPower && Activated && origin != null && pointing != null) { // the points on the map-space corresponding to these points is different: mapOrigin = ScaledSpace.LocalToScaledSpace(origin); mapPointing = pointing; if (bestLateUpdateHit.distance >= 0) { Debug.Log(" using local raycast result."); UpdateAge = updateForcedResultAge; RaycastHit hit = bestLateUpdateHit; newDist = hit.distance; // Walk up the UnityGameObject tree trying to find an object that is // something the user will be familiar with: GameObject hitObject = hit.transform.gameObject; if (hitObject != null) { HitName = hitObject.name; // default if the checks below don't work. // Despite the name and what the Unity documentation says, // GetComponentInParent actually looks all the way up the // ancestor list, not just in Parents, so these following // checks are walking up the ancestors to find the one that // has a KSP component assigned to it: if (hitObject.layer == 15) { // Support Kopernicus scatter colliders // - no more crashing into boulders // - shoot them with lasers! (and then drive around them) PQSMod_LandClassScatterQuad scatter = hitObject.GetComponentInParent <PQSMod_LandClassScatterQuad>(); if (scatter != null) { HitName = scatter.transform.parent.name; // the name of the Scatter, eg. "Scatter boulder". } else { // Fallback to the body. CelestialBody body = hitObject.GetComponentInParent <CelestialBody>(); if (body != null) { HitName = body.name; } } } else { Part part = hitObject.GetComponentInParent <Part>(); if (part != null) { HitName = part.name; } } UpdateAge = 0; } } // If the hit is not found, or it is found but is far enough // away that it might be on the other side of the planet, seen // through the ocean (which has no collider so raycasts pass // through it), then try the more expensive pqs ray cast solver. if (newDist < 0 || newDist > 100000) { Debug.Log(" numeric solver starting:."); double pqsDist; CelestialBody pqsBody; bool success = pqsTool.RayCast(origin, pointing, out pqsBody, out pqsDist); if (pqsTool.UpdateAge == 0) { Debug.Log(" UpdateAge == 0."); if (success) { Debug.Log(" success."); // If it's a closer hit than we have already, then use it: if (pqsDist < newDist || newDist < 0) { HitName = pqsBody.name; newDist = (float)pqsDist; } } } else { Debug.Log(" UpdateAge != 0."); if (pqsTool.PrevSuccess) { Debug.Log(" prevsuccess."); // If it's a closer hit than we have already, then use it: if (pqsTool.PrevDist < newDist || newDist < 0) { Debug.Log(" prevsuccess."); HitName = pqsTool.PrevBodyName; newDist = (float)pqsTool.PrevDist; } } } UpdateAge = pqsTool.UpdateAge; } } Distance = newDist; Debug.Log("Distance = " + Distance); resetHitThisUpdate = false; }
/// <summary> /// Recalculates the distance to a hit item, or -1f if nothing /// was hit by the laser. /// </summary> /// <returns></returns> private void castUpdate() { if (resetHitThisUpdate) { updateForcedResultAge = 0; } else { ++updateForcedResultAge; } float newDist = -1f; // The location of origin is different in LateUpdate than it is // in Update, so it has to be reset in both: UpdatePointing(); HitName = "<none>"; HitLayer = "<none>"; if (hasPower && Activated && origin != null && pointing != null) { // the points on the map-space corresponding to these points is different: mapOrigin = ScaledSpace.LocalToScaledSpace(origin); mapPointing = pointing; if (bestLateUpdateHit.distance >= 0) { DebugMsg(" using local raycast result."); UpdateAge = updateForcedResultAge; RaycastHit hit = bestLateUpdateHit; newDist = hit.distance; // Walk up the UnityGameObject tree trying to find an object that is // something the user will be familiar with: GameObject hitObject = (hit.transform == null ? null : hit.transform.gameObject); if (hitObject != null) { HitLayer = LayerMask.LayerToName(hitObject.layer); // for debug reasons HitName = hitObject.name; // default if the checks below don't work. // Despite the name and what the Unity documentation says, // GetComponentInParent actually looks all the way up the // ancestor list, not just in Parents, so these following // checks are walking up the ancestors to find the one that // has a KSP component assigned to it: if (hitObject.layer == 15) { // Support Kopernicus scatter colliders // - no more crashing into boulders // - shoot them with lasers! (and then drive around them) PQSMod_LandClassScatterQuad scatter = hitObject.GetComponentInParent <PQSMod_LandClassScatterQuad>(); if (scatter != null) { HitName = scatter.transform.parent.name; // the name of the Scatter, eg. "Scatter boulder". } else { // Fallback to the body. CelestialBody body = hitObject.GetComponentInParent <CelestialBody>(); if (body != null) { HitName = body.name; } } } else { Part part = hitObject.GetComponentInParent <Part>(); if (part != null) { HitName = part.name; } } UpdateAge = 0; } } // If the hit is not found, or it is found but is far enough // away that it might be on the other side of the planet, seen // through the ocean (which has no collider so raycasts pass // through it), then try the more expensive pqs ray cast solver. if (newDist < 0 || newDist > 100000) { DebugMsg(" numeric solver starting:."); double pqsDist; CelestialBody pqsBody; bool success = pqsTool.RayCast(origin, pointing, out pqsBody, out pqsDist); if (pqsTool.UpdateAge == 0) { DebugMsg(" UpdateAge == 0."); if (success) { DebugMsg(" success."); // If it's a closer hit than we have already, then use it: if (pqsDist < newDist || newDist < 0) { HitName = pqsBody.name; // Ignore any hit closer than 2km as probably bogus "vessel below PQS" hit: // (it's possible for the actual terrain polygons to approximate the PQS curve // in a way where the vessel sits "under" the PQS predicted altitude despite // being above the polygon - that generates a bogus "hit terrain" false positive // as the line goes from "under" the terrain to "above" it. The PQS systen should // not need to be queried for nearby terrain, so if there isn't a nearby real raycast // hit, then don't believe it when PQS claims there is one: if (pqsDist >= 2000) { newDist = (float)pqsDist; } } } } else { DebugMsg(" UpdateAge != 0."); if (pqsTool.PrevSuccess) { DebugMsg(" prevsuccess."); // If it's a closer hit than we have already, then use it: if (pqsTool.PrevDist < newDist || newDist < 0) { DebugMsg(" prevsuccess."); HitName = pqsTool.PrevBodyName; // Ignore any hit closer than 2km as probably bogus "vessel below PQS" hit: // (see comment above in the "if" about this.) if (pqsTool.PrevDist >= 2000) { newDist = (float)pqsTool.PrevDist; } } } } UpdateAge = pqsTool.UpdateAge; } } Distance = newDist; DebugMsg("Distance = " + Distance); resetHitThisUpdate = false; }