Пример #1
0
 void Torus::ObjectSpace_AppendAllIntersections(
     const Vector& vantage, 
     const Vector& direction, 
     IntersectionList& intersectionList) const
 {
     double u[4];
     const int numSolutions = SolveIntersections(vantage, direction, u);
     for (int i=0; i < numSolutions; ++i)
     {
         Intersection intersection;
         const Vector disp = u[i] * direction;
         intersection.point = vantage + disp;
         intersection.distanceSquared = disp.MagnitudeSquared();
         intersection.surfaceNormal = SurfaceNormal(intersection.point);
         intersection.solid = this;
         intersectionList.push_back(intersection);
     }
 }
Пример #2
0
    void Spheroid::ObjectSpace_AppendAllIntersections(
        const Vector& vantage, 
        const Vector& direction, 
        IntersectionList& intersectionList) const
    {
        double u[2];
        const int numSolutions = Algebra::SolveQuadraticEquation(
            b2*c2*direction.x*direction.x + a2*c2*direction.y*direction.y + a2*b2*direction.z*direction.z,
            2.0*(b2*c2*vantage.x*direction.x + a2*c2*vantage.y*direction.y + a2*b2*vantage.z*direction.z),
            b2*c2*vantage.x*vantage.x + a2*c2*vantage.y*vantage.y + a2*b2*vantage.z*vantage.z - a2*b2*c2,
            u
        );

        for (int i=0; i < numSolutions; ++i)
        {
            if (u[i] > EPSILON)
            {
                Intersection intersection;
                Vector displacement = u[i] * direction;
                intersection.distanceSquared = displacement.MagnitudeSquared();
                intersection.point = vantage + displacement;

                // The surface normal vector was calculated by expressing the spheroid as a 
                // function z(x,y) = sqrt(1 - (x/a)^2 - (y/b)^2),
                // taking partial derivatives dz/dx = (c*c*x)/(a*a*z), dz/dy = (c*c*y)/(b*b*z), 
                // and using these to calculate the vectors <1, 0, dz/dx> and <0, 1, dy,dz>.
                // The normalized cross product of these two vectors yields the surface normal vector.
                const double x = intersection.point.x;
                const double y = intersection.point.y;
                const double z = intersection.point.z;

                // But we need to handle special cases when z is very close to 0.
                if (fabs(z) <= EPSILON)
                {
                    if (fabs(x) <= EPSILON)
                    {
                        // The equation devolves to (y^2)/(b^2) = 1, or y = +/- b.
                        intersection.surfaceNormal = Vector(0.0, ((y > 0.0) ? 1.0 : -1.0), 0.0);
                    }
                    else
                    {
                        // The equation devolves to an ellipse on the xy plane : 
                        // (x^2)/(a^2) + (y^2)/(b^2) = 1.
                        intersection.surfaceNormal = Vector(-1.0, -(a2*y)/(b2*x), 0.0).UnitVector();
                    }
                }
                else
                {
                    intersection.surfaceNormal = Vector((c2*x)/(a2*z), (c2*y)/(b2*z), 1.0).UnitVector();
                }

                // Handle special cases with polarity: the polarity of the components of
                // the surface normal vector must match that of the <x,y,z> intersection point,
                // because the surface normal vector always points (roughly) away from the vantage, just
                // like any point on the surface of the spheroid does.

                if (x * intersection.surfaceNormal.x < 0.0)     // negative product means opposite polarities
                {
                    intersection.surfaceNormal.x *= -1.0;
                }

                if (y * intersection.surfaceNormal.y < 0.0)     // negative product means opposite polarities
                {
                    intersection.surfaceNormal.y *= -1.0;
                }

                if (z * intersection.surfaceNormal.z < 0.0)     // negative product means opposite polarities
                {
                    intersection.surfaceNormal.z *= -1.0;
                }

                intersection.solid = this;

                intersectionList.push_back(intersection);
            }
        }
    }
Пример #3
0
    void TriangleMesh::AppendAllIntersections(
        const Vector& vantage, 
        const Vector& direction, 
        IntersectionList& intersectionList) const
    {
        // Iterate through all the triangles in this solid object, 
        // looking for every intersection.
        TriangleList::const_iterator iter = triangleList.begin();
        TriangleList::const_iterator end  = triangleList.end();
        for (; iter != end; ++iter)
        {
            const Triangle& tri = *iter;
            const Vector& aPoint = pointList[tri.a];
            const Vector& bPoint = pointList[tri.b];
            const Vector& cPoint = pointList[tri.c];

            // The variables u, v, w are deliberately left 
            // uninitialized for efficiency; they are only 
            // assigned values if we find an intersection.
            double u, v, w;     

            // Sometimes we have to try more than one ordering of the points (A,B,C) 
            // in order to get a valid solution to the intersection equations.
            // Take advantage of C++ short-circuit boolean or "||" operator:
            // as soon as one of the function calls returns true, we don't call any more.
            if (AttemptPlaneIntersection(vantage, direction, aPoint, bPoint, cPoint, u, v, w) ||
                AttemptPlaneIntersection(vantage, direction, bPoint, cPoint, aPoint, u, v, w) ||
                AttemptPlaneIntersection(vantage, direction, cPoint, aPoint, bPoint, u, v, w))
            {
                // We found an intersection of the direction with the plane that passes through the points (A,B,C).
                // Figure out whether the intersection point is inside the triangle (A,B,C) or outside it.
                // We are interested only in intersections that are inside the triangle.
                // The trick here is that the values v,w are fractions that will be 0..1 along the
                // line segments AB and BC (or whichever ordered triple of points we found the solution for).
                // If we just checked that both v and w are in the range 0..1, we would be finding
                // intersections with a parallelogram ABCD, where D is the fourth point that completes the
                // parallelogram whose other vertices are ABC.
                // But checking instead that v + w <= 1.0 constrains the set of points
                // to the interior or border of the triangle ABC.
                if ((v >= 0.0) && (w >= 0.0) && (v + w <= 1.0) && (u >= EPSILON))
                {
                    // We have found an intersection with one of the triangular facets!
                    // Also determine whether the intersection point is in "front" of the vantage (positively along the direction)
                    // by checking for (u >= EPSILON).  Note that we allow for a little roundoff error by checking
                    // against EPSILON instead of 0.0, because this method is called using vantage = a point on this surface,
                    // in order to calculate surface lighting, and we don't want to act like the surface is shading itself!
                    if (u >= EPSILON)
                    {
                        // We have found a new intersection to be added to the list.
                        const Vector displacement = u * direction;

                        Intersection intersection;
                        intersection.distanceSquared = displacement.MagnitudeSquared();
                        intersection.point = vantage + displacement;
                        intersection.surfaceNormal = NormalVector(tri);
                        intersection.solid = this;
                        intersection.context = &tri;   // remember which triangle we hit, for SurfaceOptics().

                        intersectionList.push_back(intersection);
                    }
                }
            }
        }
    }
Пример #4
0
    void Cuboid::ObjectSpace_AppendAllIntersections(
        const Vector& vantage, 
        const Vector& direction, 
        IntersectionList& intersectionList) const
    {
        double u;
        Intersection intersection;
        Vector displacement;

        // Check for intersections with left/right faces: x = +a or x = -a.
        if (fabs(direction.x) > EPSILON)
        {
            // right face (x = +a)
            u = (a - vantage.x) / direction.x;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(+1.0, 0.0, 0.0);
                    intersection.solid = this;
                    intersection.tag = "right face";
                    intersectionList.push_back(intersection);
                }
            }

            // left face (x = -a)
            u = (-a - vantage.x) / direction.x;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(-1.0, 0.0, 0.0);
                    intersection.solid = this;
                    intersection.tag = "left face";
                    intersectionList.push_back(intersection);
                }
            }
        }

        // Check for intersections with front/back faces: y = -b or y = +b.
        if (fabs(direction.y) > EPSILON)
        {
            // front face (y = +b)
            u = (b - vantage.y) / direction.y;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(0.0, +1.0, 0.0);
                    intersection.solid = this;
                    intersection.tag = "front face";
                    intersectionList.push_back(intersection);
                }
            }

            // back face (y = -b)
            u = (-b - vantage.y) / direction.y;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(0.0, -1.0, 0.0);
                    intersection.solid = this;
                    intersection.tag = "back face";
                    intersectionList.push_back(intersection);
                }
            }
        }

        // Check for intersections with top/bottom faces: z = -c or z = +c.
        if (fabs(direction.z) > EPSILON)
        {
            // top face (z = +c)
            u = (c - vantage.z) / direction.z;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(0.0, 0.0, +1.0);
                    intersection.solid = this;
                    intersection.tag = "top face";
                    intersectionList.push_back(intersection);
                }
            }

            // bottom face (z = -c)
            u = (-c - vantage.z) / direction.z;
            if (u > EPSILON)
            {
                displacement = u * direction;
                intersection.point = vantage + displacement;
                if (ObjectSpace_Contains(intersection.point))
                {
                    intersection.distanceSquared = displacement.MagnitudeSquared();
                    intersection.surfaceNormal = Vector(0.0, 0.0, -1.0);
                    intersection.solid = this;
                    intersection.tag = "bottom face";
                    intersectionList.push_back(intersection);
                }
            }
        }
    }
Пример #5
0
IntersectionList Sphere::AllIntersections(const Ray& inray) const
{
	Ray ray = LorentzTransform(inray, RefFrame);

#define D ray.Direction
#define O ray.Origin
#define S InitialPosition
#define V RefFrame.Velocity

	double r1, r2;

	{
		double tmp181 = (D.x*O.x);
		double tmp180 = (-tmp181);
		double tmp179 = (D.y*O.y);
		double tmp149 = (D.z*O.z);
		double tmp176 = (D.x*S.x);
		double tmp174 = (D.y*S.y);
		double tmp148 = (D.z*S.z);
		double tmp139 = (O.t*V.x);
		double tmp171 = (D.x*tmp139);
		double tmp146 = (O.x*V.x);
		double tmp137 = (S.t*V.x);
		double tmp168 = (D.x*tmp137);
		double tmp91 = (S.x*V.x);
		double tmp12 = V.x*V.x;
		double tmp143 = (O.t*tmp12);
		double tmp85 = (S.t*tmp12);
		double tmp57 = (O.t*V.y);
		double tmp163 = (D.y*tmp57);
		double tmp133 = (O.y*V.y);
		double tmp55 = (S.t*V.y);
		double tmp160 = (D.y*tmp55);
		double tmp69 = (S.y*V.y);
		double tmp7 = V.y*V.y;
		double tmp130 = (O.t*tmp7);
		double tmp63 = (S.t*tmp7);
		double tmp122 = (O.t*V.z);
		double tmp121 = (D.z*tmp122);
		double tmp50 = (O.z*V.z);
		double tmp46 = (S.t*V.z);
		double tmp118 = (D.z*tmp46);
		double tmp39 = (S.z*V.z);
		double tmp2 = V.z*V.z;
		double tmp115 = (O.t*tmp2);
		double tmp32 = (S.t*tmp2);
		double tmp147 = (tmp149 - tmp148);
		double tmp145 = (tmp147 - tmp146);
		double tmp144 = (tmp145 + tmp91);
		double tmp142 = (tmp144 - tmp143);
		double tmp141 = (tmp142 + tmp85);
		double tmp140 = (O.x - S.x);
		double tmp138 = (tmp140 + tmp139);
		double tmp136 = (tmp138 - tmp137);
		double tmp135 = (D.x*tmp136);
		double tmp134 = (tmp141 + tmp135);
		double tmp132 = (tmp134 - tmp133);
		double tmp131 = (tmp132 + tmp69);
		double tmp129 = (tmp131 - tmp130);
		double tmp128 = (tmp129 + tmp63);
		double tmp127 = (O.y - S.y);
		double tmp126 = (tmp127 + tmp57);
		double tmp125 = (tmp126 - tmp55);
		double tmp124 = (D.y*tmp125);
		double tmp123 = (tmp128 + tmp124);
		double tmp120 = (tmp123 + tmp121);
		double tmp119 = (tmp120 - tmp50);
		double tmp117 = (tmp119 - tmp118);
		double tmp116 = (tmp117 + tmp39);
		double tmp114 = (tmp116 - tmp115);
		double tmp113 = (tmp114 + tmp32);
		double tmp112 = tmp113*tmp113;
		double tmp111 = (4 * tmp112);
		double tmp110 = O.x*O.x;
		double tmp109 = O.y*O.y;
		double tmp108 = (tmp110 + tmp109);
		double tmp107 = O.z*O.z;
		double tmp106 = (tmp108 + tmp107);
		double tmp105 = Radius * Radius;
		double tmp104 = (tmp106 - tmp105);
		double tmp103 = S.x*S.x;
		double tmp102 = (tmp104 + tmp103);
		double tmp101 = S.y*S.y;
		double tmp100 = (tmp102 + tmp101);
		double tmp99 = (O.z*S.z);
		double tmp98 = (2 * tmp99);
		double tmp97 = (tmp100 - tmp98);
		double tmp96 = S.z*S.z;
		double tmp95 = (tmp97 + tmp96);
		double tmp94 = (O.t*tmp91);
		double tmp93 = (2 * tmp94);
		double tmp92 = (tmp95 - tmp93);
		double tmp90 = (S.t*tmp91);
		double tmp89 = (2 * tmp90);
		double tmp88 = (tmp92 + tmp89);
		double tmp35 = O.t*O.t;
		double tmp87 = (tmp35*tmp12);
		double tmp86 = (tmp88 + tmp87);
		double tmp84 = (O.t*tmp85);
		double tmp83 = (2 * tmp84);
		double tmp82 = (tmp86 - tmp83);
		double tmp28 = S.t*S.t;
		double tmp81 = (tmp28*tmp12);
		double tmp80 = (tmp82 + tmp81);
		double tmp79 = (-O.t);
		double tmp78 = (tmp79 + S.t);
		double tmp77 = (tmp78*V.x);
		double tmp76 = (S.x + tmp77);
		double tmp75 = (O.x*tmp76);
		double tmp74 = (2 * tmp75);
		double tmp73 = (tmp80 - tmp74);
		double tmp72 = (O.t*tmp69);
		double tmp71 = (2 * tmp72);
		double tmp70 = (tmp73 - tmp71);
		double tmp68 = (S.t*tmp69);
		double tmp67 = (2 * tmp68);
		double tmp66 = (tmp70 + tmp67);
		double tmp65 = (tmp35*tmp7);
		double tmp64 = (tmp66 + tmp65);
		double tmp62 = (O.t*tmp63);
		double tmp61 = (2 * tmp62);
		double tmp60 = (tmp64 - tmp61);
		double tmp59 = (tmp28*tmp7);
		double tmp58 = (tmp60 + tmp59);
		double tmp56 = (S.y - tmp57);
		double tmp54 = (tmp56 + tmp55);
		double tmp53 = (O.y*tmp54);
		double tmp52 = (2 * tmp53);
		double tmp51 = (tmp58 - tmp52);
		double tmp49 = (O.t*tmp50);
		double tmp48 = (2 * tmp49);
		double tmp47 = (tmp51 + tmp48);
		double tmp45 = (O.z*tmp46);
		double tmp44 = (2 * tmp45);
		double tmp43 = (tmp47 - tmp44);
		double tmp42 = (O.t*tmp39);
		double tmp41 = (2 * tmp42);
		double tmp40 = (tmp43 - tmp41);
		double tmp38 = (S.t*tmp39);
		double tmp37 = (2 * tmp38);
		double tmp36 = (tmp40 + tmp37);
		double tmp34 = (tmp35*tmp2);
		double tmp33 = (tmp36 + tmp34);
		double tmp31 = (O.t*tmp32);
		double tmp30 = (2 * tmp31);
		double tmp29 = (tmp33 - tmp30);
		double tmp27 = (tmp28*tmp2);
		double tmp26 = (tmp29 + tmp27);
		double tmp20 = D.x*D.x;
		double tmp19 = D.y*D.y;
		double tmp18 = (tmp20 + tmp19);
		double tmp17 = D.z*D.z;
		double tmp16 = (tmp18 + tmp17);
		double tmp15 = (D.x*V.x);
		double tmp14 = (2 * tmp15);
		double tmp13 = (tmp16 - tmp14);
		double tmp11 = (tmp13 + tmp12);
		double tmp10 = (D.y*V.y);
		double tmp9 = (2 * tmp10);
		double tmp8 = (tmp11 - tmp9);
		double tmp6 = (tmp8 + tmp7);
		double tmp5 = (D.z*V.z);
		double tmp4 = (2 * tmp5);
		double tmp3 = (tmp6 - tmp4);
		double tmp1 = (tmp3 + tmp2);
		double tmp25 = (tmp1*tmp26);
		double tmp24 = (4 * tmp25);
		double tmp23 = (tmp111 - tmp24);

		if (tmp23 < 0.0)
			//Determinant is less than 0 (No solutions)
			return IntersectionList();

		double tmp22 = sqrt(tmp23);
		double tmp178 = (tmp180 - tmp179);
		double tmp177 = (tmp178 - tmp149);
		double tmp175 = (tmp177 + tmp176);
		double tmp173 = (tmp175 + tmp174);
		double tmp172 = (tmp173 + tmp148);
		double tmp170 = (tmp172 - tmp171);
		double tmp169 = (tmp170 + tmp146);
		double tmp167 = (tmp169 + tmp168);
		double tmp166 = (tmp167 - tmp91);
		double tmp165 = (tmp166 + tmp143);
		double tmp164 = (tmp165 - tmp85);
		double tmp162 = (tmp164 - tmp163);
		double tmp161 = (tmp162 + tmp133);
		double tmp159 = (tmp161 + tmp160);
		double tmp158 = (tmp159 - tmp69);
		double tmp157 = (tmp158 + tmp130);
		double tmp156 = (tmp157 - tmp63);
		double tmp155 = (tmp156 - tmp121);
		double tmp154 = (tmp155 + tmp50);
		double tmp153 = (tmp154 + tmp118);
		double tmp152 = (tmp153 - tmp39);
		double tmp151 = (tmp152 + tmp115);
		double tmp150 = (tmp151 - tmp32);
		double tmp21 = (tmp22 / 2.);
		r2 = ((tmp150 + tmp21) / tmp1);
		r1 = ((tmp150 - tmp21) / tmp1);

	}

#undef D
#undef O
#undef S
#undef V

	IntersectionList lst;
	Intersection isect;
	isect.SurfaceVel = Vector3d::zero();
	isect.RefFrame = RefFrame;
	isect.Object = ObjectRef(this);
	isect.Colour = ColourSource;
	isect.IncomingDir = ray.Direction;
	{
		isect.Position = ray.Origin + ray.GetFourVelocity() * r1;
		Vector3d PosAtTime = subvec<3>(InitialPosition) + RefFrame.Velocity * (InitialPosition.t - isect.Position.t);
		isect.Normal = normalize(subvec<3>(isect.Position) - PosAtTime);
		lst.push_back(isect);
	}
	{
		isect.Position = ray.Origin + ray.GetFourVelocity() * r2;
		Vector3d PosAtTime = subvec<3>(InitialPosition) + RefFrame.Velocity * (InitialPosition.t - isect.Position.t);
		isect.Normal = normalize(subvec<3>(isect.Position) - PosAtTime);
		lst.push_back(isect);
	}
	return lst;
}