public UniversalTarget() { displayName = "Universal"; m_SubTargets = TargetUtils.GetSubTargets(this); m_SubTargetNames = m_SubTargets.Select(x => x.displayName).ToList(); TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets); }
public BuiltInTarget() { displayName = "Built-In"; m_SubTargets = TargetUtils.GetSubTargets(this); m_SubTargetNames = m_SubTargets.Select(x => x.displayName).ToList(); TargetUtils.ProcessSubTargetList(ref m_ActiveSubTarget, ref m_SubTargets); }
public override float GenerateRandomXPoint() { float Y_point = UnityEngine.Random.Range(0.0f, cumulativeSatYPoints [cumulativeSatYPoints.Count - 1]); // computes the value x such that cumulative_sat(x) = Y_point. return(TargetUtils.LinearSpline(Y_point, cumulativeSatYPoints, cumulativeSatXPoints)); }
/// <summary> /// Computes the ratio between the area of the projected target inside frame, and the area inside viewport /// </summary> public float ComputeRatioInsideFrame(CLCameraMan camera, Rectangle frame) { if (this.screenArea < 0.00001) { // target is outside viewport or too small return(0.0f); } // clip screen representation by provided frame List <Vector2> partInFrame = new List <Vector2> (10); TargetUtils.Clip(frame, screenRepresentation, partInFrame); float framedArea = TargetUtils.ComputeScreenArea(partInFrame); return(framedArea / this.screenArea); }
public UniversalTarget() { displayName = "Universal"; m_SubTargets = TargetUtils.GetSubTargetsOfType <UniversalTarget>(); }
/// <summary> /// Computes the satisfaction in [0,1], given a value /// </summary> /// <returns>The satisfaction.</returns> /// <param name="value">Value.</param> public override float ComputeSatisfaction(float value) { return(TargetUtils.LinearSpline(value, satXPoints, satYPoints)); }
/// <summary> /// Computes and internally stores a screen representation of the target given the current camera. The screen /// representation is in turn used to reason about properties like size, framing, ... /// </summary> /// <param name="currentCamera">camera from which rendering is performed</param> /// <param name="performClipping">if true, we clip against the viewport. If not, screenArea can </param> public void Render(CLCameraMan camera, bool performClipping = true) { screenRepresentation.Clear(); visibleBBVertices.Clear(); /** * ok, so ... using the world-space AABB of the game object is not ideal because it appears it is the world AABB * of the world-transformed local AABB of the mesh, see http://answers.unity3d.com/questions/292874/renderer-bounds.html * Also, using the AABB of the colliderMesh does not help (it appears to be identical to the renderer AABB) * * Could transform the camera to local space and use the AABB of the mesh ... */ // world position of the camera Vector3 eye = camera.unityCamera.transform.position; Bounds AABB = boundingBox; // World-space min-max corners of the target's AABB Vector3 minCorner = AABB.min; Vector3 maxCorner = AABB.max; /** Calculate bit-string position to perform lookup in the table, real * spatial relationship is not relevant, the relevant information is the * vertex ordering */ int pos = ((eye.x < minCorner.x ? 1 : 0) << (int)TargetUtils.RelativePositioning.LEFT) + ((eye.x > maxCorner.x ? 1 : 0) << (int)TargetUtils.RelativePositioning.RIGHT) + ((eye.y < minCorner.y ? 1 : 0) << (int)TargetUtils.RelativePositioning.BOTTOM) + ((eye.y > maxCorner.y ? 1 : 0) << (int)TargetUtils.RelativePositioning.TOP) + ((eye.z < minCorner.z ? 1 : 0) << (int)TargetUtils.RelativePositioning.FRONT) + ((eye.z > maxCorner.z ? 1 : 0) << (int)TargetUtils.RelativePositioning.BACK); // If camera inside bounding box return 0 numVisibleBBVertices = TargetUtils.Number(pos); if (numVisibleBBVertices == 0) { this.screenArea = 0.0f; screenAABB = new Rectangle(0.0f, 0.0f, 0.0f, 0.0f); screenRatio = 0.0f; return; } // Otherwise project vertices on screen // Array for storing projected vertices List <Vector2> projectedBBVertices = new List <Vector2> (10); bool behindCamera = false; // project each visibile vertex for (int i = 0; i < numVisibleBBVertices; i++) { Vector3 visibleVertex = TargetUtils.ReturnAABBVertex(TargetUtils.Vertex(i, pos), AABB); Vector3 projectedVertex = camera.unityCamera.WorldToViewportPoint(visibleVertex); if (projectedVertex.z >= 0) { projectedBBVertices.Add(projectedVertex); visibleBBVertices.Add(visibleVertex); //Debug.Log ( newPoint.ToString("F5")); } else { behindCamera = true; } } // clip them by viewport if (performClipping) { TargetUtils.Clip(camera.clipRectangle, projectedBBVertices, screenRepresentation); } // if there are less than three vertices on screen, area is zero if (screenRepresentation.Count < 3) { this.screenArea = 0; screenAABB = new Rectangle(0.0f, 0.0f, 0.0f, 0.0f); screenRatio = 0.0f; } else { // compute area this.screenArea = Mathf.Min(TargetUtils.ComputeScreenArea(screenRepresentation), 1.0f); // compute min and max vertices Vector2 minPoint = screenRepresentation [0]; Vector2 maxPoint = screenRepresentation [1]; for (int i = 0; i < screenRepresentation.Count; i++) { if (minPoint.x > screenRepresentation [i].x) { minPoint.x = screenRepresentation [i].x; } if (minPoint.y > screenRepresentation [i].y) { minPoint.y = screenRepresentation [i].y; } if (maxPoint.x < screenRepresentation [i].x) { maxPoint.x = screenRepresentation [i].x; } if (maxPoint.y < screenRepresentation [i].y) { maxPoint.y = screenRepresentation [i].y; } } screenAABB = new Rectangle(minPoint.x, maxPoint.x, minPoint.y, maxPoint.y); if (!behindCamera) { screenRatio = this.screenArea / TargetUtils.ComputeScreenArea(projectedBBVertices); } else { screenRatio = 0.5f; // this is just a hack since otherwise bb projected points behind camera } // are simply thrown away and the target, while partially on screen, // could be considered entirely on screen if (screenRatio > 1.0f && performClipping) { screenRatio = 0.0f; } else if (screenRatio > 1.0f) { // this means we have no clipping and the projected AABB is greater than the viewport screenRatio = 1.0f; } } }
/// <summary> /// Precomputes a number of visibility points inside the target BB, to be used later for visibility checking. /// Visibility points are generated according to the chosen method (value of visibilityPointGeneration member) /// We generate 50 visibility points (this could be a parameter ...) /// </summary> /// <param name="standingOnGround">If set to <c>true</c> standing on ground.</param> private void PreComputeVisibilityPoints(bool standingOnGround, int numberofPoints = 50) { visibilityPoints = new List <Vector3> (numberofPoints); switch (visibilityPointGeneration) { case VisibilityPointGenerationMethod.ON_MESH: { // remove everything in scene except target (it should be enough to simply move the target to a special layer) foreach (GameObject go in colliders) { go.layer = LayerMask.NameToLayer("CameraControl"); } // find target center, and proper distance such that target is entirely on screen from every angle float d = radius / Mathf.Tan(50.0f); // supposing a h-fow of 100 // compute n points on unit sphere List <Vector3> samples = TargetUtils.ComputePointsOnSphere(numberofPoints, boundingBox.center, radius); // for visibility: cast 1 ray from each point to center, save point of intersection foreach (Vector3 point in samples) { RaycastHit hitPoint; bool hit = Physics.Linecast(point, boundingBox.center, out hitPoint, 1 << LayerMask.NameToLayer("CameraControl")); if (hit) { visibilityPoints.Add(hitPoint.point); } } break; } case VisibilityPointGenerationMethod.UNIFORM_IN_BB: { // We take the AABB, and choose a number of points inside it . For simplicity, we allow only an odd number of rays. // For more than 9 points, we move to random generation visibilityPoints.Add(boundingBox.center); if (numberofPoints > 1 && numberofPoints < 10) // add two points along the longest dimension of the AABB { float[] extents = new float[] { boundingBox.extents.x, boundingBox.extents.y, boundingBox.extents.z }; int[] indices = new int[] { 0, 1, 2 }; Array.Sort(extents, indices); int longest = indices [2]; int secondLongest = indices [1]; int shortest = indices [0]; Vector3 p1 = boundingBox.center; p1 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest]; Vector3 p2 = boundingBox.center; p2 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest]; if (numberofPoints > 3) { Vector3 p3 = boundingBox.center; p3 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest]; Vector3 p4 = boundingBox.center; p4 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest]; if (numberofPoints > 5) { p1 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest]; p1 [shortest] = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest]; p2 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest]; p2 [shortest] = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest]; p3 [shortest] = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest]; p4 [shortest] = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest]; Vector3 p5 = boundingBox.center; p5 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest]; p5 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest]; p5 [shortest] = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest]; Vector3 p6 = boundingBox.center; p6 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest]; p6 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest]; p6 [shortest] = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest]; if (numberofPoints == 9) { p3 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest]; p4 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest]; Vector3 p7 = boundingBox.center; p7 [longest] = 0.25f * boundingBox.min [longest] + 0.75f * boundingBox.max [longest]; p7 [secondLongest] = 0.75f * boundingBox.min [secondLongest] + 0.25f * boundingBox.max [secondLongest]; p7 [shortest] = 0.25f * boundingBox.min [shortest] + 0.75f * boundingBox.max [shortest]; Vector3 p8 = boundingBox.center; p8 [longest] = 0.75f * boundingBox.min [longest] + 0.25f * boundingBox.max [longest]; p8 [secondLongest] = 0.25f * boundingBox.min [secondLongest] + 0.75f * boundingBox.max [secondLongest]; p8 [shortest] = 0.75f * boundingBox.min [shortest] + 0.25f * boundingBox.max [shortest]; visibilityPoints.Add(p7); visibilityPoints.Add(p8); } visibilityPoints.Add(p5); visibilityPoints.Add(p6); } visibilityPoints.Add(p3); visibilityPoints.Add(p4); } visibilityPoints.Add(p1); visibilityPoints.Add(p2); } else { visibilityPointGeneration = VisibilityPointGenerationMethod.RANDOM; } break; } case (VisibilityPointGenerationMethod.RANDOM): { // random generation, corresponds to VisibilityPointGenerationMethod.RANDOM if (numberofPoints >= colliders.Count) { // assign 1 random point per collider, until they are over int colliderIndex = 0; while (numberofPoints > 0) { Vector3 newPoint = TargetUtils.RandomPointInsideBounds(colliders [colliderIndex].GetComponent <Collider> ().bounds); visibilityPoints.Add(newPoint); colliderIndex = (colliderIndex + 1) % colliders.Count; numberofPoints--; } } else // if we have more colliders than points, then let's consider the AABB of the target assign points inside it. Not ideal, but... { while (numberofPoints > 0) { Vector3 newPoint = TargetUtils.RandomPointInsideBounds(boundingBox); visibilityPoints.Add(newPoint); numberofPoints--; } } break; } default: { Debug.Log("Warning: NO visibility points computed for target " + name); break; } } }