// evaluates constraints in the given order in the list using lazy evaluation (so they should be ordered by // increasing evaluation cost) public override float EvaluateSatisfaction(CLCameraMan camera, float threshold) { if (!evaluated) { inScreenRatio = 1.0f; float currentSat = 0.0f; float maxSat = 1.0f; bool lazyTriggered = false; int weightIndex = 0; foreach (CLVisualProperty f in this.properties) { currentSat += f.EvaluateSatisfaction(camera) * weights[weightIndex]; inScreenRatio = inScreenRatio * f.inScreenRatio; maxSat -= weights [weightIndex++]; if ((maxSat + currentSat) < threshold) { lazyTriggered = true; break; } } if (lazyTriggered) { currentSat = -1.0f; } evaluated = true; satisfaction = currentSat; } return(satisfaction); }
/// <summary> /// Computes the screen size of the property target /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { if (targets.Count == 1) // one target, we report size with respect to the viewport { if (sizeType == SizeMode.AREA) { return(Mathf.Min(targets [0].screenArea, satFunction.domain.y)); } if (sizeType == SizeMode.WIDTH) { return(Mathf.Min(targets [0].screenAABB.CalculateWidth(), satFunction.domain.y)); } // else: height property return(Mathf.Min(targets [0].screenAABB.CalculateHeight(), satFunction.domain.y)); } else // there are two targets, we report size of first with respect to second { if (sizeType == SizeMode.AREA) { return(Mathf.Min(targets [0].screenArea / targets [1].screenArea, satFunction.domain.y)); } if (sizeType == SizeMode.WIDTH) { return(Mathf.Min(targets [0].screenAABB.CalculateWidth() / targets [1].screenAABB.CalculateWidth(), satFunction.domain.y)); } // else: height property return(Mathf.Min(targets [0].screenAABB.CalculateHeight() / targets [1].screenAABB.CalculateHeight(), satFunction.domain.y)); } }
/// <summary> /// Computes the value of the property (depending on the actual mode) /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { Vector3 viewTarget; // world target to camera Vector3 targetToCamera = (camera.unityCamera.transform.position - targets [0].boundingBox.center).normalized; // we must now convert it to float angle; if (orientation == OrientationMode.HORIZONTAL) { // retrieve local up vector for the target Vector3 up = targets [0].gameObject.transform.up.normalized; // up is the normal of the horizontal plane of the target // we project targetToCamera to the horizontal plane using // v1_projected = v1 - Dot(v1, n) * n; viewTarget = (targetToCamera - Vector3.Dot(targetToCamera, up) * up).normalized; angle = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.FORWARD); } else if (orientation == OrientationMode.VERTICAL) { viewTarget = targetToCamera; angle = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.UP); } else // orientation == OrientationMode.VERTICAL_WORLD) { viewTarget = targetToCamera; angle = targets [0].ComputeAngleWith(viewTarget, TargetUtils.Axis.WORLD_UP); } return(Mathf.Min(angle, satFunction.domain.y)); }
/// <summary> /// Evaluates the viewpoint using the provided camera man /// </summary> /// <returns>The viewpoint satisfaction in [0,1].</returns> /// <param name="camera">camera man object</param> public virtual float EvaluateViewpoint(CLCameraMan cameraman, bool setObjectiveFunction = false) { if (setObjectiveFunction) { cameraman.SetSpecification(properties); cameraman.UpdateTargets(); } cameraman.unityCamera.transform.position = this.position; cameraman.unityCamera.transform.rotation = this.rotation; foreach (CLVisualProperty p in cameraman.properties) { p.evaluated = false; } foreach (CLTarget t in cameraman.targets) { t.rendered = false; } float result = properties[0].EvaluateSatisfaction(cameraman); satisfaction = new List <float> (); inScreenRatio = new List <float> (); for (int i = 0; i < cameraman.properties.Count; i++) { satisfaction.Add(cameraman.properties [i].satisfaction); inScreenRatio.Add(cameraman.properties [i].inScreenRatio); } return(result); }
/// <summary> /// Computes how much screen representation is inside given rectangular frame /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { // compute projection of target center Vector3 projectedCenter = camera.unityCamera.WorldToViewportPoint(targets[0].boundingBox.center); // compute distance from desidered point float distance = (position - new Vector2(projectedCenter[0], projectedCenter[1])).magnitude; return(Mathf.Min(distance, satFunction.domain.y)); }
/// <summary> /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where /// satisfaction is higher /// </summary> /// <returns>The random satisfying position.</returns> /// <param name="camera">Camera.</param> public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera) { Vector3 result = new Vector3(); bool found = false; Vector2 minMaxDistance = new Vector2(0.1f, 1000f); // just a placeholder; this method should not be used anymore int maxtries = 0; while (!found && maxtries < 30) { maxtries++; float x = satFunction.GenerateRandomXPoint(); // random angle //Debug.Log (x); //x = 0.0f; // generate random distance float distance = minMaxDistance.x + Random.value * (minMaxDistance.y - minMaxDistance.x); // generate random height float height = camera.ComputeRandomViewpoint(3)[1]; if (orientation == OrientationMode.HORIZONTAL) { result.x = Mathf.Sin(Mathf.Deg2Rad * x) * distance; result.z = Mathf.Cos(Mathf.Deg2Rad * x) * distance; result = targets [0].gameObject.transform.TransformPoint(result); result.y = height; } else // VERTICAL // generate a random theta in cilindrical coordinates { float theta = Random.value * 2 * Mathf.PI; float phi = Mathf.Deg2Rad * x; // convert from spherical to cartesian result.x = Mathf.Sin(phi) * Mathf.Cos(theta) * distance; result.y = Mathf.Sin(phi) * Mathf.Sin(theta) * distance; result.z = Mathf.Cos(phi) * distance; result = targets [0].gameObject.transform.TransformPoint(result); } // if we are in problem bounds, ok - otherwise we throw away the point and generate a new one if (camera.InSearchSpace(new float[] { result.x, result.y, result.z })) { found = true; } } if (!found) { float[] randomCandidate = camera.ComputeRandomViewpoint(3); result = new Vector3(randomCandidate[0], randomCandidate[1], randomCandidate[2]); } return(result); }
public float EvaluateSatisfaction(CLCameraMan cameraMan, bool renderTargets, float threshold = -0.001f) { foreach (CLVisualProperty p in cameraMan.properties) { p.evaluated = false; } foreach (CLTarget t in targets) { t.rendered = false; } return(EvaluateSatisfaction(cameraMan, 0.001f)); }
public override float EvaluateSatisfaction(CLCameraMan camera, float threshold) { if (!evaluated) { inScreenRatio = RenderTargets(camera); value = this.ComputeValue(camera); satisfaction = satFunction.ComputeSatisfaction(value) * inScreenRatio; evaluated = true; } return(satisfaction); }
/// <summary> /// Computes how much the target is occluded by other objects by shooting rays and checking intersections with colliders /// </summary> public float ComputeOcclusion(CLCameraMan camera, bool frontBack = false, int _nRays = 0) { if (this.gameObject.layer == LayerMask.NameToLayer("Overlay")) { return(0.0f); } float result = 0.0f; RaycastHit hitFront; RaycastHit hitBack; List <Vector3> points = new List <Vector3> (); int n = _nRays > 0? nRays: actualVisibilityPoints.Count; // now move all colliders to layer 2 (ignore ray cast) foreach (GameObject go in colliders) { go.layer = 2; } for (int i = 0; i < n; i++) { Vector3 p = actualVisibilityPoints[i]; bool isOccludedFront = Physics.Linecast(camera.unityCamera.transform.position, p, out hitFront, layerMask); if (isOccludedFront) { result += 1.0f / n; } else if (frontBack) { bool isOccludedBack = Physics.Linecast(p, camera.unityCamera.transform.position, out hitBack, layerMask); if (isOccludedBack) { result += 1.0f / n; } } } int j = 0; foreach (GameObject go in colliders) { go.layer = collidersLayers[j]; j++; } return(Mathf.Min(result, 1.0f)); }
// this is ok but it might not be necessary to render all targets once e.g. we know that one is off screen /// <summary> /// Renders the targets of the property /// </summary> /// <returns>The targets.</returns> /// <param name="camera">Camera from which to render</param> public float RenderTargets(CLCameraMan camera) { float inScreenRatio = 1.0f; foreach (CLTarget t in targets) { if (!t.rendered) { t.Render(camera); t.rendered = true; } inScreenRatio = t.screenRatio * inScreenRatio; } return(inScreenRatio); }
/// <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); }
/// <summary> /// Generates a random distance from the target with more probability where satisfaction is higher /// </summary> /// <returns>The random satisfying distance.</returns> /// <param name="camera">Camera.</param> public float GenerateRandomSatisfyingDistance(CLCameraMan camera) { float FOV, result; Vector2 yFOVrange = camera.cameraDomain.yFOVBounds; float yFOV = (yFOVrange [1] + yFOVrange [0]) / 2; // required vertical FOV // AR is width/height float AR = camera.unityCamera.aspect; // we compute horizontal FOV float xFOV = AR * yFOV; if (sizeType == SizeMode.WIDTH) { FOV = xFOV; } else if (sizeType == SizeMode.HEIGHT) { FOV = yFOV; } else { // AREA property. We convert areas to radiuses, and use the min of the two FOVs FOV = Mathf.Min(xFOV, yFOV); } float bs_radius = targets [0].radius; float tmp = 0.3f / Mathf.Tan(Mathf.Deg2Rad * FOV / 2); // should be 0.5, but bs is bigger than AABB float randomSize = satFunction.GenerateRandomXPoint(); // convert x, which is a size, to a distance from camera if (randomSize < 0.0001f) { randomSize = 0.0001f; // to avoid computing an infinite distance. } if (sizeType == SizeMode.AREA) { // AREA property. We convert areas to radiuses, and use the average of the two FOVs randomSize = Mathf.Sqrt(randomSize / Mathf.PI); } result = (bs_radius / randomSize) * tmp; // now x is a distance (instead of width, height or area) return(result); }
/// <summary> /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where /// satisfaction is higher /// </summary> /// <returns>The random satisfying position.</returns> /// <param name="camera">Camera.</param> public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera) { Vector3 result = new Vector3(); bool found = false; int maxtries = 0; while (!found && maxtries < 30) { maxtries++; float distance = GenerateRandomSatisfyingDistance(camera ); // check we are outside bs. we don't want to assign candidates inside bs. if (distance > targets [0].radius) { // generate random direction float inclination = (Mathf.PI) * Random.value; float azimuth = Mathf.PI * 2 * Random.value; result.x = distance * Mathf.Sin(azimuth) * Mathf.Sin(inclination); result.y = distance * Mathf.Cos(inclination); result.z = distance * Mathf.Cos(azimuth) * Mathf.Sin(inclination); result = result + targets [0].boundingBox.center; if (camera.InSearchSpace(new float[] { result.x, result.y, result.z })) { found = true; } } } if (!found) { float[] randomCandidate = camera.ComputeRandomViewpoint(3); result = new Vector3(randomCandidate[0], randomCandidate[1], randomCandidate[2]); } return(result); }
/// <summary> /// Computes the value of the property /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { if (positionType == RelativePositionMode.LEFT) { return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, targets [1].screenAABB.xMin, 0.0f, 1.0f))); } if (positionType == RelativePositionMode.BELOW) { return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, 1.0f, 0.0f, targets [1].screenAABB.yMin))); } if (positionType == RelativePositionMode.RIGHT) { return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(targets [1].screenAABB.xMax, 1.0f, 0.0f, 1.0f))); } // else: ABOVE property return(targets [0].ComputeRatioInsideFrame(camera, new Rectangle(0.0f, 1.0f, targets [1].screenAABB.yMax, 1.0f))); }
//// <summary> /// Returns objective function value for the candidate, or -2 if candidate not in search space /// </summary> public float EvaluateSatisfaction(CLCameraMan evaluator, bool lazy) { // if we are not in search space there is no point evaluating the objective function if (!InSearchSpace(evaluator)) { timesOutOfSearchSpace++; return(-2.0f); // give penalty to out-of-bounds candidates } inSearchSpace = true; if (lazy) { evaluation = evaluator.EvaluateSatisfaction(position, bestEvaluation); } else { evaluation = evaluator.EvaluateSatisfaction(position, -0.001f); } return(evaluation); }
//// <summary> /// Returns the best found CLViewpoint given the allowed time in milliseconds, /// the required satisfaction threshold in [0,1], a CLCameraMan for evaluating a /// candidate satisfaction. If init is true, we start search from scratch, i.e. by /// first initializing candidates; otherwise, we use the current candidates /// </summary> public CLViewpoint SearchOptimal(float _timeLimit, float _satisfactionThreshold, CLCameraMan _evaluator, List <CLCandidate> initialCandidates, bool checkGeometry = false, bool init = true) { //if init, initialize n candidates ( with r_part candidates randomly initialized ) beginTime = Time.realtimeSinceStartup; elapsedTime = 0.0f; timeLimit = _timeLimit / 1000.0f; if (init) { rnd = new System.Random(); iterations = 0; iterOfBest = 0; this.evaluator = _evaluator; this.maxSatisfaction = _satisfactionThreshold; globalBestViewpoints = new List <CLViewpoint> (); minSearchRange = evaluator.GetMinCameraParameters(candidateDimension); maxSearchRange = evaluator.GetMaxCameraParameters(candidateDimension); searchRanges = evaluator.GetParametersRange(candidateDimension); averageRange = 0.0f; for (int i = 0; i < candidateDimension; i++) { averageRange += searchRanges[i]; } averageRange = averageRange / candidateDimension; InitializeCandidates(initialCandidates); InitSolverParameters(_timeLimit); elapsedTime = Time.realtimeSinceStartup - beginTime; } if (elapsedTime > timeLimit) { exitCondition = 0; } else { exitCondition = 2; } while (DoAnotherIteration()) { iterations++; // we start from 1 // execute loop body (dependent on method). exitCondition = ExecuteSearchIteration(); } //elaborate results and return best solution (access to other solutions should be provided) // this is for handling the case where no optima have been found at all (e.g. not enough time) if (globalBestViewpoints.Count == 0) { CLViewpoint noSolution = new CLViewpoint(); noSolution.satisfaction = new List <float>(); noSolution.properties = new List <CLVisualProperty> (evaluator.properties); foreach (CLVisualProperty p in noSolution.properties) { noSolution.satisfaction.Add(-1.0f); } noSolution.psoRepresentation = new float[] { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 60.0f }; globalBestViewpoints.Add(noSolution); } // this returns only one solution !!!! return(globalBestViewpoints[globalBestViewpoints.Count - 1]); }
/// <summary> /// Computes the value of the property. In this case, a signed distance from the plane (positive if we are on the same side of the normal) /// </summary> /// <returns>The computed angle</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(referencePlane.GetDistanceToPoint(camera.unityCamera.transform.position)); }
/// <summary> /// Given a desired on screen size (area, width, or height), computes camera distance, assuming the target is /// approximated by its bounding sphere, centered on the screen. /// </summary> /// <returns>the camera distance</returns> /// <param name="targetSize">Target size.</param> /// <param name="sizeMode">Size mode.</param> /// <param name="camera">Camera.</param> /// <param name="yFOV">yFOV, in degrees</param> public float ComputeDistanceFromSize(float targetSize, CLSizeProperty.SizeMode sizeMode, CLCameraMan camera, float yFOV) { // AR is width/height float AR = camera.unityCamera.aspect; // we compute horizontal FOV float yFOVRad = Mathf.Deg2Rad * yFOV; float projectedRadius = 1.0f; // now we need to compute distance from size if (sizeMode == CLSizeProperty.SizeMode.AREA) { // assuming viewport height is 1, area viewport is 1*AR. Our target area is therefore relative to targetSize*AR // projected radius should then be projectedRadius = Mathf.Sqrt(targetSize * AR / Mathf.PI); } else if (sizeMode == CLSizeProperty.SizeMode.HEIGHT) { // assuming viewport height is 1, our target height is correct (relative to 1). We need half height projectedRadius = 0.5f * targetSize; } else // it is a width property // assuming viewport height is 1, our target width is relative to targetSize*AR { projectedRadius = 0.5f * targetSize * AR; } // this means, in world space, the distance from the center of the sphere to the top of the screen should be float halfscreen = radius * 0.5f / projectedRadius; // now solve with the usual trigonometry relation float distance = halfscreen / Mathf.Tan(yFOVRad / 2); return(distance); }
/// <summary> /// Check if candidate is in problem search space /// </summary> /// <returns><c>true</c>, if search space was ined, <c>false</c> otherwise.</returns> /// <param name="evaluator">CLCameraMan evaluator</param> /// <param name="checkGeometry">If set to <c>true</c> check geometry.</param> public bool InSearchSpace(CLCameraMan evaluator) { return(evaluator.InSearchSpace(position)); }
/// <summary> /// Computes the property satisfaction. /// </summary> /// <returns>The satisfaction.</returns> /// <param name="cameraMan">Camera man.</param> /// <param name="threshold">Threshold for lazy evaluation. Defaults to non-lazy evaluation</param> public abstract float EvaluateSatisfaction(CLCameraMan cameraMan, float threshold = -0.001f);
// this method generates a random viewpoint with more probability where // target properties will be satisfied. It assumes we have at least a size // property for the target, plus optional angle and occlusion properties public Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera, bool considerVisibility = false) { Vector3 result = new Vector3(); bool found = false; int ntries = 0; float yFOV = (camera.cameraDomain.yFOVBounds [0] + camera.cameraDomain.yFOVBounds [1]) / 2; // we allow for 30 tries before giving up while (ntries < 30 && !found) { float distance = 0.0f; float phi = 0.0f; float theta = 0.0f; foreach (CLGroundProperty p in groundProperties) { if (p is CLSizeProperty) { CLSizeProperty sp = (CLSizeProperty)p; // this returns a random area, or width, or height, depending on the type of size // property, with more probability where the satisfaction is higher float randomSize = p.satFunction.GenerateRandomXPoint(); if (randomSize < 0.0001f) { randomSize = 0.0001f; // to avoid computing an infinite distance. } // compute distance from target size distance = ComputeDistanceFromSize(randomSize, sp.sizeType, camera, yFOV); } if (p is CLOrientationProperty) { CLOrientationProperty op = (CLOrientationProperty)p; if (op.orientation == CLOrientationProperty.OrientationMode.HORIZONTAL) { phi = Mathf.Deg2Rad * op.satFunction.GenerateRandomXPoint(); // horizontal random angle } else { theta = Mathf.Deg2Rad * op.satFunction.GenerateRandomXPoint(); // vertical random angle } } } // if we are not inside bs sphere if (distance > radius) { result = ComputeWorldPosFromSphericalCoordinates(distance, phi, theta); if (camera.InSearchSpace(new float[] { result.x, result.y, result.z })) { found = true; } } ntries++; } if (!found) { float[] randomCandidate = camera.cameraDomain.ComputeRandomViewpoint(3); result = new Vector3(randomCandidate [0], randomCandidate [1], randomCandidate [2]); //Debug.Log ("random candidate"); } else { //Debug.Log ("smart candidate in " + ntries + " tries"); } return(result); }
/// <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> /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where satisfaction is higher /// </summary> /// <returns>The random satisfying position.</returns> /// <param name="camera">Camera.</param> public abstract Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera);
/// <summary> /// Computes how much screen representation is inside given rectangular frame /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(Mathf.Min(targets [0].ComputeRatioInsideFrame(camera, frame), satFunction.domain.y)); }
/// <summary> /// Generates a random viewpoint position that satisfies the property to some degree, with more probability where /// satisfaction is higher /// </summary> /// <returns>The random satisfying position.</returns> /// <param name="camera">Camera.</param> public override Vector3 GenerateRandomSatisfyingPosition(CLCameraMan camera) { return(new Vector3(0.0f, 0.0f, 0.0f)); }
/// <summary> /// Computes the degree of occlusion /// </summary> /// <returns>The value.</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(Mathf.Min(targets [0].ComputeOcclusion(camera, frontBack), satFunction.domain.y)); }
/// <summary> /// Computes the value of the property. In this case, the YFOV of the provided camera /// </summary> /// <returns>The computed angle</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(Mathf.Min(camera.unityCamera.fieldOfView, satFunction.domain.y)); }
/// <summary> /// Computes the value of the property. In this case, the angle between the provided reference camera rotation, and the rotation of the camera /// </summary> /// <returns>The computed angle</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { bool result = Physics.Linecast(point, camera.unityCamera.transform.position, layerMask); return(result ? 0.0f : 1.0f); }
/// <summary> /// Computes the value of the property. In this case, the distance between the camera and the reference position /// </summary> /// <returns>The computed angle</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(Vector3.Distance(referencePosition, camera.unityCamera.transform.position)); }
/// <summary> /// Computes the value of the property. In this case, the angle between the provided reference camera rotation, and the rotation of the camera /// </summary> /// <returns>The computed angle</returns> /// <param name="camera">Camera.</param> public override float ComputeValue(CLCameraMan camera) { return(Quaternion.Angle(referenceCameraOrientation, camera.unityCamera.transform.rotation)); }