📄 polyhedron.c
字号:
#include "Polyhedron.h"/************************************************************************* ** Class destructor ** *************************************************************************/Polyhedron::~Polyhedron(){int i;// delete the vertices and the plane equationsdelete vList;delete pList;// delete the facetsfor(i = 0; i < facetN; i++) delete iList[i];delete iList;}/************************************************************************* ** This method computes the intersection between a ray and the ** polyhedron. It returns the distance between the origin of the ray ** and the closest point of intersection (or 0.0 if not intersection ** occurs). ** The algorithm operates as follows: ** For each facet of the polyhedron ** + determine the intersection between the ray and the plane ** supporting the facet. ** + if the intersection exists, project the facet on a 2D plane. ** + Test if the intersection point is inside the resulting polygon. ** *************************************************************************/double Polyhedron::intersect(vec3& ray_org, vec3& ray_dir){int i, j, sNum = 0, // Number of intersections. axis, // Axis along which the facet will be projected. iNum; // Number of intersections between an imaginary half line // and the edges of a facet (used to determine inclusion).vec3 normal; // Normal to the current facet.vec2 p1, p2, // Two consecutive points on a facet. p, // A 2D projection of the point to test. n; // Normal to one of the edges of a facet.double s[facetN], // Space to store at most N intersections. vd, vn;for (i=0; i<facetN; i++) { // Test the case in which the ray is parallel to the facet (vd=0.0) vd = vec3(pList[i],PD) * ray_dir; if (vd == 0.0) continue; // Find a projection axis which maximizes the area of the facet (normal = vec3(pList[i], PD)).apply(&fabs); if (normal[VX] >= normal[VY]) if(normal[VX] >= normal[VZ]) axis = VX; else axis = VZ; else if(normal[VY] >= normal[VZ]) axis = VY; else axis = VZ; // Compute the point of intersection between the ray and the facet plane. // Project it along the desired axis. vn = pList[i] * vec4(ray_org); s[sNum] = -vn / vd; p = vec2(ray_org + s[sNum] * ray_dir, axis); // Test if the intersection point is inside the facet. // We do this by checking for each edge of the facet if there is an // intersection between this edge and a half-line, starting at p and // going towards positive X. We count the number of intersections: if it // is odd, the point is inside the facet, if not, it is outside. iNum = 0; p1 = vec2(vList[iList[i][iList[i][0]]], axis); for (j=1; j<= iList[i][0]; j++) { p2 = vec2(vList[iList[i][j]], axis); // Is p in the band generated by sweeping the [p1p2] segment in the // positive X direction ? if ((p1[VY] - p[VY]) * (p2[VY] - p[VY]) <= 0.0) { // Does the half-line trivially intersect the edge ? if (p[VX] < min(p1[VX], p2[VX])) iNum++; // Does the half-line trivially miss the edge ? else if (p[VX] < max(p1[VX], p2[VX])) { // tough case: compute the normal to the edge pointing towards // positive X use the dot product between this normal and the // p1p vector to see if the edge and the half line intersect. // (This is similar to the Cyrus-Beck line-clipping test) n[VX] = p1[VY] - p2[VY]; n[VY] = p2[VX] - p1[VX]; if (n[VX] < 0.0) n = -n; if (n * (p - p1) <= 0.0) iNum++; } } p1 = p2; } if (iNum % 2) sNum++; }return closest_intersection(s, sNum);}/************************************************************************* ** This method computes the normal vector to the polyhedron at the point ** of intersection. ** It does so by finding out which plane the intersection point belongs ** to. Once this plane is determined, it simply returns the normal to ** this plane, which is already normalized. ** *************************************************************************/vec3 Polyhedron::normalAt(vec3& p){int i, index = 0; // index of the facet being hit by the raydouble h, hmin = 1e16; // initialize hmin to some very large numberfor (i=0; i<facetN; i++) { h = fabs(pList[i] * vec4(p)); if (h < hmin) { index = i; hmin = h; } }return vec3(pList[index], PD);}/************************************************************************* ** Input from stream. ** *************************************************************************/istream& operator >> (istream& s, Polyhedron& a){int i,j,M;mat4 T; // local coordinates to world coordinates transformationvec3 n; // normal to the facet// call the implementation of the super-classs >> *((Primitive*) &a);// create the matrix to transform local coordinates to world coordinatesT = translation3D(a.pos) * (a.orient.transpose());// read the vertices. Transform them on the fly to world coordinatess >> a.vertexN;a.vList = new vec3[a.vertexN];for (i = 0; i < a.vertexN; i++) { s >> a.vList[i]; a.vList[i] = T * a.vList[i]; }// read the facets.s >> a.facetN;a.iList = new int*[a.facetN];for (i = 0; i< a.facetN; i++) { s >> M; a.iList[i] = new int[M+1]; a.iList[i][0] = M; for (j=1; j<=M; j++) s >> a.iList[i][j]; }// compute the normal and plane equation of the facet using Newell methoda.pList = new vec4[a.facetN];for (i = 0; i < a.facetN; i++) { n = vec3(0.0); for (j = 1; j <= a.iList[i][0]; j++) if (j != a.iList[i][0]) n += a.vList[a.iList[i][j]] ^ a.vList[a.iList[i][j+1]]; else n += a.vList[a.iList[i][j]] ^ a.vList[a.iList[i][1]]; n.normalize(); a.pList[i] = vec4(n, - a.vList[a.iList[i][1]] * n); }return s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -