Java - simple include / exclude plane

This may have been answered before, and if so, please point me to the answer. Otherwise, here it goes.

You have x the number of objects in space that have bounded coordinates p0 and p1. p0 and p1 are each three-dimensional coordinate, and p0 always has lower values ​​- negative or positive, and p1 always has higher values.

You now have a plane that is perfectly orthogonal to the direction of camera C, which has a position (pC) and a heading (hC). This plane can then be defined as 90 degrees (pi / 2 radians) from the camera yaw (sometimes called "heading") and pitch and extending to the farthest defined boundaries in space.

Since I do not allow more than 180 degrees FOV, anything that lies completely outside the camera (outside the exclusion plane) should be excluded.

Is there an easy way to do this? On this point, I am not considering the need to check every object in space; Suppose for the purposes of our question that there is always a limited number of objects - controlled by partitioning space in some way - so that the objects we check are always "dubious".

Also keep in mind that since these are not points, but pairs of points representing 3d bounding cubes are not enough for the point to lie on either side of the plane.

I have a feeling that there is an easy way to do this, but without taking computer graphics, I was never familiar with mathematics.

+3


source to share


3 answers


So how to do it.

First, you need to store the eight points in each bounding box in a predictable way, for example, each bit into an integer representing its position relative to the center of the box. What you can do is use 0x4 to represent EAST (+ x) (zero in this bit means WEST) 0x2 to represent NORTH (zero in this bit means SOUTH) and 0x1 to represent TOP (zero in this bit means BOTTOM) ... Now you can access all points at the same position of the bounding box by specifying the position number. (All zero bits are zero. Java warns that these assignments are meaningless, but they do help with readability.)

Setting the bounding box: (do this for each bounding box)

    pointList = new Point3d[8];

    pointList[WEST|SOUTH|BOTTOM] = new Point3d(x0,y0,z0);
    pointList[WEST|SOUTH|TOP]    = new Point3d(x0,y0,z1);
    pointList[WEST|NORTH|BOTTOM] = new Point3d(x0,y1,z0);
    pointList[WEST|NORTH|TOP]    = new Point3d(x0,y1,z1);
    pointList[EAST|SOUTH|BOTTOM] = new Point3d(x1,y0,z0);
    pointList[EAST|SOUTH|TOP]    = new Point3d(x1,y0,z1);
    pointList[EAST|NORTH|BOTTOM] = new Point3d(x1,y1,z0);
    pointList[EAST|NORTH|TOP]    = new Point3d(x1,y1,z1);

      

Then calculate the normal from your viewing angle. (Yaw - left / right rotation, step - up / down rotation)

    float nx = -(float)Math.cos(yaw);
    float ny = (float)Math.sin(yaw);
    float nz = (float)Math.sin(pitch);

      

I think the negation is correct, but if everything is invisible on one side, just undo it :)

Calculate the characteristic point, which is just the index you are going to check in each bounding box, because it represents the point in each box that will be closest to the plane on the invisible side:

    int characteristicPoint = (nx<0?WEST:EAST)|
                              (ny<0?SOUTH:NORTH)|
                              (nz<0?BOTTOM:TOP);

      



Make sure each bounding box is set such that x, y, z is less than x, y, z prime (x0 = x aught, x1 = x prime)

Then create your characteristic point ("check"), your set of normals ("frustrum") and your camera position (x, y, z) and do this with each bounding box:

    float checkA = ((bounds.pointList[check].x-position.x)*frustrum.x) +
            ((bounds.pointList[check].y-position.y)*frustrum.y);

    float checkB = ((bounds.pointList[check].x-position.x)*frustrum.x) +
            ((bounds.pointList[check].z-position.z)*frustrum.z);
    if(checkB>=0&&checkA>=0) {
        visible = true;
        return;
    } else if(checkB<0&&checkA<0) {
        visible = false;
        return;
    } else {
       float checkC = ((bounds.pointList[check].y-position.y)*frustrum.y) +
            ((bounds.pointList[check].z-position.z)*frustrum.z);
       if(checkC>=0) {
          visible = true;
          return;
       } else {
          visible = false;
          return;
       }

    }

      

This is simple linear algebra (IMO) and the logic is this: if a point is on the positive side of two or more rows representing a plane, it is visible. If it is on the negative side of the tug or more lines representing the plane, it is invisible. You evaluate the first two, and if they are different (one negative, one positive), you test the third and take that value.

It is important to note the following property when considering lines as equations:

-x-y = p != x+y = p

      

The line is the same, but its implicit "reverse" is reversed.

Hope this helps someone else with this question. It was difficult, but pleasant to understand.

This can be made more efficient by keeping the first half of CheckA I suppose :)

+1


source


I think you want to find a lot of point pairs where both points are behind the camera plane (which I think you describe as a normal 2d plane containing a pC point and with a normal hC), but I may be confused.

If that's what you want, try this:

  • hC is your normal plane
  • set vp0 as a vector from pC to p0 (make p0 position - pC position)
  • set vp1 as a vector from pC to p1 (make p1 position - pC position)

p0 is seen if vp0. hC> = 0 (or> 0 if you want it to be strictly opposite the camera).



p1 is displayed if vp1. hC> = 0 (or> 0 if you want it to be strictly opposite the camera).

... there is a standard vector dot product here.

So, if both p0 and p1 are behind the camera, you can eliminate the shape.

+1


source


If any of the 6 corners of the "cube" (conventionally known as Axis Restricted Window or AABB) are on the viewing side of the plane, it is possible that something can be seen inside. You can start by checking the two starting points, but if they are both invisible, you will also need to check the other six corners, as shown below:

initial corners: p0=(p0.x, p0.y, p0.z)
                 p1=(p1.x, p1.y, p1.z)

other corners:      (p1.x, p0.y, p0.z)
                    (p0.x, p1.y, p0.z)
                    (p0.x, p0.y, p1.z)

                    (p1.x, p1.y, p0.z)
                    (p0.x, p1.y, p1.z)
                    (p1.x, p0.y, p1.z)

      

Note that a regular rasterization pipeline should not draw objects behind the camera because it clamps triangles that go beyond the clipping view . This suggests that you can test against other truncation planes as well, or perhaps viewing truncation in general, which is a bit tricky, but probably a good idea. It may seem tedious, but the truncation test will still be cheaper than trying to attract invisible objects.

+1


source







All Articles