1
\$\begingroup\$

I've got two points which I need to create a bounding box with, and then check to see if points are within this bounding box. The end result is a marquee selection tool.

So, here is the code I started with:

    var v1 = Camera.main.ScreenToViewportPoint( screenPosition1 );
    var v2 = Camera.main.ScreenToViewportPoint( screenPosition2 );
    var min = Vector3.Min( v1, v2 );
    var max = Vector3.Max( v1, v2 );
    //min.z = camera.nearClipPlane;
    //max.z = camera.farClipPlane;

    var bounds = new Bounds();
    bounds.SetMinMax( min, max );
    return bounds;

So then when I run it, it seems to create the correct bounds: Center (0.4,0.4,22.3), Extends (0.2,0.2,0.0)

And the point seems like it should be within: (0.4,0.3,22.4)

Now, my initial thoughts were that the z-index was off. However, i've tried setting that a bunch of different ways, including setting the z index of the center to 22, and the extent to 25. Nothing works.

I'm checking to see if it's contained, with:

bool unitInsideSelection = viewportBounds.Contains(camera.WorldToViewportPoint( gameObject.transform.position ) );

Where viewportBounds is the return object of the function above.

Any Thoughts?

\$\endgroup\$
6
  • \$\begingroup\$ But if the Z extent is 0.0 then no point can be within except when its Z coordinate is exactly 22.3, so (0.4,0.3,22.4) is outside as expected. \$\endgroup\$ Commented Jan 19, 2017 at 3:18
  • \$\begingroup\$ That's true, so I just went in and expanded the bounds on the z coordinate. I now have a bounds of: Center: (0.4,0.5,22.3), Extents: (0.2,0.3,5.0) with a point of (0.4,0.5,22.4). That should have worked right? \$\endgroup\$
    – user96577
    Commented Jan 19, 2017 at 3:55
  • \$\begingroup\$ I figured it out, I was passing in a different point than I was looking at. My bad... sorry for wasting your time! :( \$\endgroup\$
    – user96577
    Commented Jan 19, 2017 at 3:58
  • 5
    \$\begingroup\$ @user96577 if you found your own solution , i recommend you to answer your own question with the solution to tell future reader , or delete your question so future visitor can ask the same \$\endgroup\$ Commented Jan 19, 2017 at 12:16
  • \$\begingroup\$ Determining if a set of points are inside or outside a square \$\endgroup\$
    – Theraot
    Commented Feb 21, 2017 at 12:27

2 Answers 2

3
\$\begingroup\$

This is an X/Y problem. You want to select something on the screen, right? So do things in screen space.

Get your point in the world in question p_w. Project it onto the screen giving p_s in pixels. Then check a pixel rectangle on the screen to see if it contains p_s. Easy right?

Here's some pseudocode.

// Tells if a point on the screen is within a rectangle given by min and max bounds.
bool contains(Point2 pointOnScreen, Point2 screenMin, Point2 screenMax) {
    return pointOnScreen.x <= screenMax.x &&
           pointOnScreen.y <= screenMax.y && 
           pointOnScreen.x >= screenMin.x &&
           pointOnScreen.y >= screenMin.y;
}

// Determines if a point in the world is within the bounds on the screen.
bool contains(Point3 pointInWorld, Camera camera, 
              Point2 screenMin, Point2 screenMax) {
   // Project a point in the world to the screen. This gives a 3D
   // vector in pixels, with an added z depth.
   Point3 pointOnScreen = camera.projectToScreen(pointInWorld);
   return contains(pointOnScreen.xy, screenMin, screenMax) && pointOnScreen.z > 0;
}
\$\endgroup\$
1
\$\begingroup\$

From my understanding of your problem, building a selection marque function, you would follow this approach

  1. Project test points p0, p1, ... to viewport space (or some surface) that is facing the camera.

  2. Get viewport space (or surface) coordinates of two mouse points. These form the bounding box for selection marquee.

  3. Use point-inside-rectangle test to determine if projected points are inside bounding box.

The easiest way to test if a 2D point is inside a rectangle is to test if all the 2D cross products are the same sign.

If b0, b1, b2, and b3 are the coordinates of your box, and your are testing if p is inside then you check that all the following are true.

cross( p - b0, b1 - b0 ) > 0

cross( p - b1, b2 - b1 ) > 0

cross( p - b2, b3 - b2 ) > 0

cross( p - b3, b4 - b3 ) > 0

I hope I understood what you are trying to do. Please correct me if I am wrong.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .