Elimination of large triangles isn't as simple as the vertices aren't on screen then the triangle can't be seen.
For an accurate frustum cull, the only valid elimination scenario for your data (there are more deeper versions) is that the all vertices are on one side of a frustum plane. The reason for this is that your triangle may straddle the frustum (ala cross the plane of your screen).
Testing the angle between the vertices and the camera position is also inaccurate, as your frustum isn't a point, its a projection of a box. Therefore you need to test your vertices against 6 planes that make up your frustum.
Finally, testing every vertex against the frustum will become expensive. This is where abstracting your data becomes more important. Usually abstraction comes in the form of using bounding boxes to group up sets of triangles (also known as a mesh) to quickly eliminate them from your potential visible set.
I've attached my frustum generation (create at start of every frame) code and the bounding box test:
// Create the frustum matrix from the view matrix and updated projection matrix.
matrix = m_wvp;
m_planes = new Vector4(matrix.M13,
matrix.M43); // near
m_planes = new Vector4(matrix.M14 - matrix.M13,
matrix.M24 - matrix.M23,
matrix.M34 - matrix.M33,
matrix.M44 - matrix.M43);
m_planes = new Vector4(matrix.M14 + matrix.M11,
matrix.M24 + matrix.M21,
matrix.M34 + matrix.M31,
matrix.M44 + matrix.M41); // left
m_planes = new Vector4(matrix.M14 - matrix.M11,
matrix.M24 - matrix.M21,
matrix.M34 - matrix.M31,
matrix.M44 - matrix.M41);//right
m_planes = new Vector4(matrix.M14 - matrix.M12,
matrix.M24 - matrix.M22,
matrix.M34 - matrix.M32,
matrix.M44 - matrix.M42); // top
m_planes = new Vector4(matrix.M14 + matrix.M12, matrix.M24 + matrix.M22, matrix.M34 + matrix.M32, matrix.M44 + matrix.M42); // bottom
for (int i = 0; i < s_frustumPlanes; i++)
public bool IsInViewableArea(List<Vector3> a_cornerLIst)
// this is a simpler occlusion test where we basically don't even need to test frustum as the the extents are outside the camera view distance. But you need to test extents + width because we only hold 2 corners and squares are 4
int iTotalIn = 0;
Vector4 pList = GetFrustumPlanes(); // this should only be called once.
// test all 8 corners against the 6 sides
// if all points are behind 1 specific plane, we are out
// if we are in with all points, then we are fully in
for (int p = 0; p < Camera3d.s_frustumPlanes; ++p)
int iInCount = 8;
int iPtIn = 1;
for (int i = 0; i < a_cornerLIst.Count; ++i)
//Vector3 a = pList[i].
// test this point against the planes
// if (pList[p].SideOfPlane(vList[i]) == BEHIND)
temp = (Vector4)(a_cornerLIst[i] );
temp.W = 1;
dotvector = Vector4.Dot(pList[p], temp);
if (dotvector < 0.0f)
iPtIn = 0;
// were all the points outside of plane p?
if (iInCount == 0)
// check if they were all on the right side of the plane
iTotalIn += iPtIn;
// so if iTotalIn is 6, then all are inside the view
// if (iTotalIn == 6)
// return true;
// we must be partly in then otherwise