long check_point(Point3 p1, Point3 p2, float alpha, long mask) { Point3 plane_point; plane_point.x = LERP(alpha, p1.x, p2.x); plane_point.y = LERP(alpha, p1.y, p2.y); plane_point.z = LERP(alpha, p1.z, p2.z); return(face_plane(plane_point) & mask); }
Mesh::Mesh(const std::vector<Point3D>& verts, const std::vector< std::vector<int> >& faces) : m_verts(verts), m_faces(faces) { Point3D firstPoint = m_verts[0]; double minX = firstPoint[0]; double maxX = firstPoint[0]; double minY = firstPoint[1]; double maxY = firstPoint[1]; double minZ = firstPoint[2]; double maxZ = firstPoint[2]; for (unsigned int i = 0; i < m_verts.size(); i++) { Point3D p = m_verts[i]; minX = min(p[0], minX); maxX = max(p[0], maxX); minY = min(p[1], minY); maxY = min(p[1], maxY); minZ = min(p[2], minZ); maxZ = min(p[2], maxZ); } Point3D minPoint = Point3D(minX, minY, maxZ); double size = max(max(maxX - minX, maxY - minY), maxZ - minZ); aabb = new NonhierBox(minPoint, size); for (unsigned int i = 0; i < m_faces.size(); i++) { Face f = m_faces[i]; vector<Point3D> points; for (unsigned int j = 0; j < f.size(); j++) { Point3D p = m_verts[f[j]]; points.push_back(p); } facePlanes.push_back(face_plane(points)); } }
long t_c_intersection(Triangle3 t) { long v1_test,v2_test,v3_test; float d,denom; Point3 vect12,vect13,norm; Point3 hitpp,hitpn,hitnp,hitnn; /* First compare all three vertexes with all six face-planes */ /* If any vertex is inside the cube, return immediately! */ if ((v1_test = face_plane(t.v1)) == INSIDE) return(INSIDE); if ((v2_test = face_plane(t.v2)) == INSIDE) return(INSIDE); if ((v3_test = face_plane(t.v3)) == INSIDE) return(INSIDE); /* If all three vertexes were outside of one or more face-planes, */ /* return immediately with a trivial rejection! */ if ((v1_test & v2_test & v3_test) != 0) return(OUTSIDE); /* Now do the same trivial rejection test for the 12 edge planes */ v1_test |= bevel_2d(t.v1) << 8; v2_test |= bevel_2d(t.v2) << 8; v3_test |= bevel_2d(t.v3) << 8; if ((v1_test & v2_test & v3_test) != 0) return(OUTSIDE); /* Now do the same trivial rejection test for the 8 corner planes */ v1_test |= bevel_3d(t.v1) << 24; v2_test |= bevel_3d(t.v2) << 24; v3_test |= bevel_3d(t.v3) << 24; if ((v1_test & v2_test & v3_test) != 0) return(OUTSIDE); /* If vertex 1 and 2, as a pair, cannot be trivially rejected */ /* by the above tests, then see if the v1-->v2 triangle edge */ /* intersects the cube. Do the same for v1-->v3 and v2-->v3. */ /* Pass to the intersection algorithm the "OR" of the outcode */ /* bits, so that only those cube faces which are spanned by */ /* each triangle edge need be tested. */ if ((v1_test & v2_test) == 0) if (check_line(t.v1,t.v2,v1_test|v2_test) == INSIDE) return(INSIDE); if ((v1_test & v3_test) == 0) if (check_line(t.v1,t.v3,v1_test|v3_test) == INSIDE) return(INSIDE); if ((v2_test & v3_test) == 0) if (check_line(t.v2,t.v3,v2_test|v3_test) == INSIDE) return(INSIDE); /* By now, we know that the triangle is not off to any side, */ /* and that its sides do not penetrate the cube. We must now */ /* test for the cube intersecting the interior of the triangle. */ /* We do this by looking for intersections between the cube */ /* diagonals and the triangle...first finding the intersection */ /* of the four diagonals with the plane of the triangle, and */ /* then if that intersection is inside the cube, pursuing */ /* whether the intersection point is inside the triangle itself. */ /* To find plane of the triangle, first perform crossproduct on */ /* two triangle side vectors to compute the normal vector. */ SUB(t.v1,t.v2,vect12); SUB(t.v1,t.v3,vect13); CROSS(vect12,vect13,norm) /* The normal vector "norm" X,Y,Z components are the coefficients */ /* of the triangles AX + BY + CZ + D = 0 plane equation. If we */ /* solve the plane equation for X=Y=Z (a diagonal), we get */ /* -D/(A+B+C) as a metric of the distance from cube center to the */ /* diagonal/plane intersection. If this is between -0.5 and 0.5, */ /* the intersection is inside the cube. If so, we continue by */ /* doing a point/triangle intersection. */ /* Do this for all four diagonals. */ d = norm.x * t.v1.x + norm.y * t.v1.y + norm.z * t.v1.z; /* if one of the diagonals is parallel to the plane, the other will intersect the plane */ if(fabs(denom=(norm.x + norm.y + norm.z))>EPS) /* skip parallel diagonals to the plane; division by 0 can occur */ { hitpp.x = hitpp.y = hitpp.z = d / denom; if (fabs(hitpp.x) <= 0.5) if (point_triangle_intersection(hitpp,t) == INSIDE) return(INSIDE); } if(fabs(denom=(norm.x + norm.y - norm.z))>EPS) { hitpn.z = -(hitpn.x = hitpn.y = d / denom); if (fabs(hitpn.x) <= 0.5) if (point_triangle_intersection(hitpn,t) == INSIDE) return(INSIDE); } if(fabs(denom=(norm.x - norm.y + norm.z))>EPS) { hitnp.y = -(hitnp.x = hitnp.z = d / denom); if (fabs(hitnp.x) <= 0.5) if (point_triangle_intersection(hitnp,t) == INSIDE) return(INSIDE); } if(fabs(denom=(norm.x - norm.y - norm.z))>EPS) { hitnn.y = hitnn.z = -(hitnn.x = d / denom); if (fabs(hitnn.x) <= 0.5) if (point_triangle_intersection(hitnn,t) == INSIDE) return(INSIDE); } /* No edge touched the cube; no cube diagonal touched the triangle. */ /* We're done...there was no intersection. */ return(OUTSIDE); }
extern int trivial_vertex_tests(int nverts, const real verts[][3], int already_know_verts_are_outside_cube) { /*register*/ unsigned long cum_and; /* cumulative logical ANDs */ /*register*/ int i; /* * Compare the vertices with all six face-planes. * If it's known that no vertices are inside the unit cube * we can exit the loop early if we run out of bounding * planes that all vertices might be outside of. That simply means * that this test failed and we can go on to the next one. * If we must test for vertices within the cube, the loop is slightly * different in that we can trivially accept if we ever do find a * vertex within the cube, but we can't break the loop early if we run * out of planes to reject against because subsequent vertices might * still be within the cube. */ cum_and = ~0L; /* Set to all "1" bits */ if(already_know_verts_are_outside_cube) { for(i=0; i<nverts; i++) if(0L == (cum_and = face_plane(verts[i], cum_and))) break; /* No planes left to trivially reject */ } else { for(i=0; i<nverts; i++) { /* Note the ~0L mask below to always test all planes */ unsigned long face_bits = face_plane(verts[i], ~0L); if(0L == face_bits) /* vertex is inside the cube */ return 1; /* trivial accept */ cum_and &= face_bits; } } if(cum_and != 0L) /* All vertices outside some face plane. */ return 0; /* Trivial reject */ /* * Now do the just the trivial reject test against the 12 edge planes. */ cum_and = ~0L; /* Set to all "1" bits */ for(i=0; i<nverts; i++) if(0L == (cum_and = bevel_2d(verts[i], cum_and))) break; /* No planes left that might trivially reject */ if(cum_and != 0L) /* All vertices outside some edge plane. */ return 0; /* Trivial reject */ /* * Now do the trivial reject test against the 8 corner planes. */ cum_and = ~0L; /* Set to all "1" bits */ for(i=0; i<nverts; i++) if(0L == (cum_and = bevel_3d(verts[i], cum_and))) break; /* No planes left that might trivially reject */ if(cum_and != 0L) /* All vertices outside some corner plane. */ return 0; /* Trivial reject */ /* * By now we know that the polygon is not to the outside of any of the * test planes and can't be trivially accepted *or* rejected. */ return -1; }