// Intersect ray r with the triangle abc. If it hits returns true, // and puts the t parameter, barycentric coordinates, normal, object id, // and object material in the isect object bool TrimeshFace::intersectLocal( const ray& r, isect& i ) const { const Vec3d& a = parent->vertices[ids[0]]; const Vec3d& b = parent->vertices[ids[1]]; const Vec3d& c = parent->vertices[ids[2]]; // tangent vectors Vec3d t1 = b - a; Vec3d t2 = c - a; Vec3d n = crossProd(t1,t2); double D = -n*a; // if the surface is parallel to the ray there is no intersection if(r.getDirection()*n == 0) { return false; } double t = -(n*r.getPosition() + D)/(n*r.getDirection() ); if (t <= RAY_EPSILON) return false; // point of intersection with the same plane (doesn't mean intersection with triangle) p(t)=p+t*d Vec3d p = r.at(t); // triangle area double A = n.length()/2.0; // barycentric coords double wa = crossProd(c-b, p-b).length() / (2.0*A); double wb = crossProd(a-c, p-c).length() / (2.0*A); double wc = crossProd(b-a, p-a).length() / (2.0*A); if((wa >= 0.0) && (wb >= 0.0) && (wc >= 0.0) && (wa+wb+wc-1.0 <= 0.00001)) { i.setT(t); i.setBary(wa, wb, wc); if (parent->normals.size() == 0) { i.setN(n); } else { Vec3d inter_n = wa*parent->normals[ids[0]] + wb*parent->normals[ids[1]] + wc*parent->normals[ids[2]]; inter_n.normalize(); i.setN(inter_n); } i.setObject(this); if (parent->materials.size() == 0) { i.setMaterial(this->getMaterial() ); } else { Material inter_m = wa*(*parent->materials[ids[0]]); inter_m += wb*(*parent->materials[ids[1]]); inter_m += wc*(*parent->materials[ids[2]]); i.setMaterial(inter_m); } return true; } return false; }
bool Box::intersectLocal( const ray& r, isect& i ) const { Vec3d p = r.getPosition(); Vec3d d = r.getDirection(); int it; double x, y, t, bestT; int mod0, mod1, mod2, bestIndex; bestT = HUGE_DOUBLE; bestIndex = -1; for(it=0; it<6; it++){ mod0 = it%3; if(d[mod0] == 0){ continue; } t = ((it/3) - 0.5 - p[mod0]) / d[mod0]; if(t < RAY_EPSILON || t > bestT){ continue; } mod1 = (it+1)%3; mod2 = (it+2)%3; x = p[mod1]+t*d[mod1]; y = p[mod2]+t*d[mod2]; if( x<=0.5 && x>=-0.5 && y<=0.5 && y>=-0.5) { if(bestT > t){ bestT = t; bestIndex = it; } } } if(bestIndex < 0) return false; i.setT(bestT); i.setObject(this); Vec3d intersect_point = r.at(i.t); int i1 = (bestIndex + 1) % 3; int i2 = (bestIndex + 2) % 3; if(bestIndex < 3) { i.setN(Vec3d(-double(bestIndex == 0), -double(bestIndex == 1), -double(bestIndex == 2))); i.setUVCoordinates( Vec2d( 0.5 - intersect_point[ min(i1, i2) ], 0.5 + intersect_point[ max(i1, i2) ] ) ); } else { i.setN(Vec3d(double(bestIndex==3), double(bestIndex == 4), double(bestIndex == 5))); i.setUVCoordinates( Vec2d( 0.5 + intersect_point[ min(i1, i2) ], 0.5 + intersect_point[ max(i1, i2) ] ) ); } return true; }