Пример #1
0
IntersectionInfo Sphere::rayIntersect(Ray _ray) {
    Point3f e = _ray.e();
    Point3f c = center_;
    Vector3f d = _ray.d();
    float discriminant = dot(d,(e-c))*dot(d,(e-c))- 
        dot(d,d)*(dot((e-c),(e-c))-radius_*radius_);
    if (discriminant < 0.0) {
        return IntersectionInfo(0.0, 
                                Point3f(),
                                Vector3f(),
                                IntersectionInfo::miss());
    } else {
        float t1 = (dot(d*-1.0,(e-c))+sqrt(discriminant))/dot(d,d);
        float t2 = (dot(d*-1.0,(e-c))-sqrt(discriminant))/dot(d,d);
        float t;
        if (t1 < t2) {
            t = t1;
        } else {
            t = t2;
        }
        if (t < _ray.tMin() || t > _ray.tMax()) {
            return IntersectionInfo(0.0, 
                                    Point3f(),
                                    Vector3f(),
                                    IntersectionInfo::miss());
        }
        Point3f p = e + d*t;
        Vector3f n = 2.0*(p-c);
        n.normalize();       
        return IntersectionInfo(t, p, n, IntersectionInfo::hit());
    }
}
Пример #2
0
bool MeshShape::intersectTri(const Ray &r, float &t, Vector &p, Vector &n, float &u, float &v)
{
	// Transform the ray for the local transformation matrix
	Ray rt = _transform.inverse() * Ray(r);

	Vector A, B, C;
	float nearest_t = -1.0f, temp_t;
	int face_index = -1; // Index of intersected face
	for(unsigned int faceI=0; faceI<mesh->faces.size(); faceI+=3)
	{
		A = mesh->vertices[mesh->faces[faceI]];
		B = mesh->vertices[mesh->faces[faceI+1]];
		C = mesh->vertices[mesh->faces[faceI+2]];

		// Skip face if triangle plane and ray are parallel
		float temp = ((B-A).cross(C-A)).dot(rt.d());
		if(temp < eps && temp > -eps)
			continue;
		else
		{
			double a = A.x() - B.x();
			double b = A.y() - B.y();
			double c = A.z() - B.z();
			double d = A.x() - C.x();
			double e = A.y() - C.y();
			double f = A.z() - C.z();
			double g = rt.d().x();
			double h = rt.d().y();
			double i = rt.d().z();
			double j = A.x() - rt.e().x();
			double k = A.y() - rt.e().y();
			double l = A.z() - rt.e().z();

			double eiSubhf = e*i - h*f;
			double gfSubdi = g*f - d*i;
			double dhSubeg = d*h - e*g;

			double M = a*eiSubhf + b*gfSubdi + c*dhSubeg;

			double akSubjb = a*k - j*b;
			double jcSubal = j*c - a*l;
			double blSubkc = b*l - k*c;

			// Gamma and Beta represent distance along vectors (c-a) and (b-a) respectively,
			// if Gamma or Beta are beyond their respective vectors, then intersection is not within the surface of the triangle
			double Gamma = (i*akSubjb + h*jcSubal + g*blSubkc)/M;
			if(Gamma < 0 || Gamma > 1)
				continue;

			double Beta = (j*eiSubhf + k*gfSubdi + l*dhSubeg)/M;
			if(Beta < 0 || Beta > (1-Gamma))
				continue;


			temp_t = -((f*akSubjb + e*jcSubal + d*blSubkc)/M);


			if(temp_t > eps && (nearest_t <= eps || temp_t < nearest_t))
			{
				nearest_t = temp_t;

				// Retain intersected face index (remember face is specified by i*3,i*3+1,i*3+2)
				face_index = faceI;
			}
		}
	}

	// Return intersection details
	if(nearest_t > eps)
	{
		t = nearest_t;
		p = r.e() + r.d()*t;

		// Get the intersected triangle vertices
		A = mesh->vertices[mesh->faces[face_index]];
		B = mesh->vertices[mesh->faces[face_index+1]];
		C = mesh->vertices[mesh->faces[face_index+2]];

		// Compute flat face normal
		n = _transform.inverse().transpose().mult((B-A).cross(C-A).normalized()).normalized();

		Vector pLocal = rt.e() + rt.d()*t;
		Vector v0 = C - A;
		Vector v1 = B - A;
		Vector v2 = pLocal - A;
		float dot00 = v0.dot(v0);
		float dot01 = v0.dot(v1);
		float dot02 = v0.dot(v2);
		float dot11 = v1.dot(v1);
		float dot12 = v1.dot(v2);
		float invDenom = 1.0f / (dot00*dot11 - dot01*dot01);
		float local_u = (dot11*dot02 - dot01*dot12) * invDenom;
		float local_v = (dot00*dot12 - dot01*dot02) * invDenom;

		// Recall faces[face_index] is the index for the vertex, faces[face_index]*2 then maps to the correct u,v position in the uvList since uvList=(u0,v0,u1,v1,...)
		int uv_index = mesh->faces[face_index]*2;
		float u_0 = mesh->uvList[uv_index];
		float v_0 = mesh->uvList[uv_index+1];
		uv_index = mesh->faces[face_index+1]*2;
		float u_1 = mesh->uvList[uv_index];
		float v_1 = mesh->uvList[uv_index+1];
		uv_index = mesh->faces[face_index+2]*2;
		float u_2 = mesh->uvList[uv_index];
		float v_2 = mesh->uvList[uv_index+1];

		float tu1 = u_1 - u_0;
		float tv1 = v_1 - v_0;
		float tu0 = u_2 - u_0;
		float tv0 = v_2 - v_0;

		u = u_0 + tu0*local_u + tu1*local_v;
		v = v_0 + tv0*local_u + tv1*local_v;

		return true;
	}
	else
		return false;
}