Hey there! So currently I’m developing my own rendering engine. At the moment I have face rendering, z-ordering, and mediocre face occlusion culling working. However, that last item on the list is like I said, mediocre. Currently, to detect whether a face is visible at all or not I do these in order:
Calculate surface normal using two points on the surface (Cross product of top left corner and top right corner)
Take dot product of camera’s look vector and previously calculated surface normal
If the result is less than -PI/2 then render
However, the result I get is this:
What’s the problem exactly? Well, as you can see the bottom face is not rendering like it’s supposed to. So, any help will be appreciated. If you are interested in how I do z-ordering all I do is render each face based off it’s distance to the camera. (May not be the best method)
You need 3 points to define a plane, if you’re using 2 points as vectors, these are essentially vectors from 0,0,0 to each point, and the cross product of those is not what you want (unless the origin just coincidentally is in the plane of the face). If you have any 3 points on a face which are not all collinear, you can take the cross product of two different vectors between any of the points. Just keep in mind that ordering matters in so far as getting the normal of the correct side of the face (right hand rule).
There shouldn’t be a pi/2 in this calculation anywhere. The face is aimed at the camera if the dot product is less than 0 (directly at the camera if normal:dot(camera.lookVector)==-1 and both vectors are unit vectors). You’d only compare with pi/2 if you were dealing with radians, i.e. if you already took the arccosine of the dot product. For this particular check, you don’t need to normalize the normal vector, since the cutoff is always zero, but if you do any other calculations with the normal, it might be useful to store it normalized.
So, if I have four points for a given face I would just take the cross product of two random points in that plane instead of taking the cross product between two corners?
The 3D cross product is a product of two vectors that gives a 3rd vector orthogonal to both. While points on the face can be interpreted as vectors, they represent the vectors from (0,0,0) to their coordinates (x,y,z). These are not the vectors you want the cross product of, you need the cross product of two vectors that lie in the plane of the face (and are not parallel). The simplest way to do this is to use two vectors from one of the vertices to the two adjacent vertices (two edges of the face that share a vertex). The only time you can use the points themselves is if you know that the origin (0,0,0) lies in the plane of the face, which is clearly not the general case. This is why one does not usually talk about taking the cross product of two points, only of vectors.
For example, suppose you have a single square face at an arbitrary point in 3D space, and you call the four corner vertices A, B, C, and D in clockwise order. Each is a Vector3. Cross products of these Vector3 values, such as A:Cross(B), are not face normals (apart from the special case I mentioned above). What you want is a cross product such as (A-B):Cross(C-B), or (B-C):Cross(D-C), etc. In other words, two vectors in the plane of the face that are not parallel. They need not be orthogonal, though in the case of a square face many choices are. You could even use the diagonals, like (C-A):Cross(B-D), or an edge and a diagonal like (D-A):Cross(C-A). You just can’t use parallel sides, so for the square, (D-A):Cross(C-B) is no go, that has a zero vector cross product.
In all cases, your cross product expression is going to involve 3 points on the face (which can be vertices), and both vectors will be differences of two of the points in the plane of the face.