Пример #1
0
void Sphere::intersect(HitRecord& hit, const RenderContext& rc, const Ray& ray)const{
	/*float a = dot(ray.d(), ray.d());
	Vector v = ray.p()-p;/*Vector(ray.p().x(), ray.p().y(), ray.p().z());*/
    /*float b = 2 * dot(ray.d(), v);
    float c = dot(v, v) - r2();
    float disc = b * b - 4 * a * c;
	if (disc < 0.f){
		hit.hit(std::numeric_limits<float>::infinity(), this, material);
		return;
	}
    float distSqrt = sqrtf(disc);
    float q;
    if (b < 0) q = (-b - distSqrt)/2.0f;
    else       q = (-b + distSqrt)/2.0f;
    float t0 = q / a;
    float t1 = c / q;
    if (t0 > t1){
        float temp = t0;
        t0 = t1;
        t1 = temp;
    }
    if (t1 < 0) hit.hit(std::numeric_limits<float>::infinity(), this, material);
	if (t0 < 0) hit.hit(t1, this, material);
    else		hit.hit(t0, this, material);*/

	Vector dist = ray.p() - p;
	float b = dot(dist, ray.d());
	float c = dot(dist, dist) - r2();
	float d = b*b - c;
	float t = d > 0 ? -b - sqrt(d) : std::numeric_limits<float>::infinity();

	hit.hit(t, this, this->material);
}
Пример #2
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());
    }
}
Пример #3
0
double Triangle::ix( const Ray& r )
{
    // Moeller, Trumbore: Fast, minimum storage ray/triangle intersection
    Vector e1 = p1( r.t0() ) - p0( r.t0() );
    Vector e2 = p2( r.t0() ) - p0( r.t0() );
    Vector  p = r.d().crossProduct( e2 );
    double D = e1.dotProduct( p );
    if( det < EPS )
        return -1;
    Vector  t = r.o() - p0( r.t0() );
    double U = t.dotProduct( p );
    if( U < EPS || U > D )  // less than check might need to use 0.0 instead of EPS
        return -1;
    Vector  q = t.crossProduct( e1 );
    double V = r.d().dotProduct( q );
    if ( V < EPS || U + V > D )
        return -1;
    double t = e1.dotProduct( q ) / D;
    return t;
}
Пример #4
0
void Plane::intersect(HitRecord& hit, const RenderContext& rc, const Ray& ray)const{
	//Vector p(ray.p().x(),ray.p().y(),ray.p().z());
	//Vector o(point.x(),point.y(),point.z());
	//float d = dot(o, norm);

	float num = dot(-norm, ray.p()-point);
	float denom = dot(norm, ray.d());
	float t=num/denom;
	if(denom==0 || num==0 || t<0) hit.hit(std::numeric_limits<float>::infinity(), this, material);
	else hit.hit(num/denom, this, material);
	
	//float num = -(dot(norm,p)+d);
	//float denom = dot(norm, ray.d());
	//if((denom==0 || num==0)) hit.hit(std::numeric_limits<float>::infinity(), this, material);
	//else hit.hit(num/denom, this, material);
}
Пример #5
0
double Sphere::ix( const Ray &r )
{
    Point c = p( r.t0() );
    Vector oc = ( r.o() - c );
    double B = 2.0 * r.d().dotProduct( oc );
    double C = pow( oc.m(), 2.0 ) - _R * _R;
    double temp = B * B - 4 * C;
    if( temp < EPS )
        return -1.0;
    temp = sqrt( temp );
    double D0 = ( -B + temp ) / ( 2 );
    double D1 = ( -B - temp ) / ( 2 );
    double D;
    if( D0 > EPS and D1 > EPS )
        D = min( D0, D1 );
    else if( D0 > EPS )
        D = D0;
    else if( D1 > EPS )
        D = D1;
    else
        return -1.0;
    return D;
}
Пример #6
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;
}