예제 #1
0
	const MathVector<T, dimension> reflected(const MathVector<T, dimension>& other) const {
		MathVector<T, dimension> output;

		output = (*this) - other * T(2.0) * other.dot(*this);

		return output;
	}
예제 #2
0
	// Return the reflection of this vector around the given normal (must be unit length)
	const MathVector<T,3> reflect(const MathVector<T,3> & other) const {
		return (*this) - other * T(2.0) *other.dot(*this);
	}
예제 #3
0
bool Bezier::intersectsQuadrilateral(const MathVector<float, 3>& orig, const MathVector<float, 3>& dir,
									 const MathVector<float, 3>& v_00, const MathVector<float, 3>& v_10,
									 const MathVector<float, 3>& v_11, const MathVector<float, 3>& v_01,
									 float &t, float &u, float &v) const {
	const float EPSILON = 0.000001;

	// Reject rays that are parallel to Q, and rays that intersect the plane
	// of Q either on the left of the line V00V01 or below the line V00V10.
	MathVector<float, 3> E_01 = v_10 - v_00;
	MathVector<float, 3> E_03 = v_01 - v_00;
	MathVector<float, 3> P = dir.cross(E_03);
	float det = E_01.dot(P);

	if (std::abs(det) < EPSILON) return false;

	MathVector<float, 3> T = orig - v_00;
	float alpha = T.dot(P) / det;

	if (alpha < 0.0) return false;

	MathVector<float, 3> Q = T.cross(E_01);
	float beta = dir.dot(Q) / det;

	if (beta < 0.0) return false;

	if (alpha + beta > 1.0) {
		// Reject rays that that intersect the plane of Q either on
		// the right of the line V11V10 or above the line V11V00.
		MathVector<float, 3> E_23 = v_01 - v_11;
		MathVector<float, 3> E_21 = v_10 - v_11;
		MathVector<float, 3> P_prime = dir.cross(E_21);
		float det_prime = E_23.dot(P_prime);

		if (std::abs(det_prime) < EPSILON) return false;

		MathVector<float, 3> T_prime = orig - v_11;
		float alpha_prime = T_prime.dot(P_prime) / det_prime;

		if (alpha_prime < 0.0) return false;

		MathVector<float, 3> Q_prime = T_prime.cross(E_23);
		float beta_prime = dir.dot(Q_prime) / det_prime;

		if (beta_prime < 0.0) return false;
	}

	// Compute the ray parameter of the intersection point, and
	// reject the ray if it does not hit Q.
	t = E_03.dot(Q) / det;

	if (t < 0.0) return false;

	// Compute the barycentric coordinates of the fourth vertex.
	// These do not depend on the ray, and can be precomputed
	// and stored with the quadrilateral.
	float alpha_11, beta_11;
	MathVector<float, 3> E_02 = v_11 - v_00;
	MathVector<float, 3> n = E_01.cross(E_03);

	if ((std::abs(n[0]) >= std::abs(n[1])) && (std::abs(n[0]) >= std::abs(n[2]))) {
		alpha_11 = ((E_02[1] * E_03[2]) - (E_02[2] * E_03[1])) / n[0];
		beta_11 = ((E_01[1] * E_02[2]) - (E_01[2]  * E_02[1])) / n[0];
	} else if ((std::abs(n[1]) >= std::abs(n[0])) && (std::abs(n[1]) >= std::abs(n[2]))) {
		alpha_11 = ((E_02[2] * E_03[0]) - (E_02[0] * E_03[2])) / n[1];
		beta_11 = ((E_01[2] * E_02[0]) - (E_01[0]  * E_02[2])) / n[1];
	} else {
		alpha_11 = ((E_02[0] * E_03[1]) - (E_02[1] * E_03[0])) / n[2];
		beta_11 = ((E_01[0] * E_02[1]) - (E_01[1]  * E_02[0])) / n[2];
	}

	// Compute the bilinear coordinates of the intersection point.
	if (std::abs(alpha_11 - (1.0)) < EPSILON) {
		// Q is a trapezium.
		u = alpha;
		if (std::abs(beta_11 - (1.0)) < EPSILON) v = beta; // Q is a parallelogram.
		else v = beta / ((u * (beta_11 - (1.f))) + (1.f)); // Q is a trapezium.
	} else if (std::abs(beta_11 - (1.0)) < EPSILON) {
		// Q is a trapezium.
		v = beta;
		if ( ((v * (alpha_11 - (1.0))) + (1.0)) == 0 ) return false;
		u = alpha / ((v * (alpha_11 - (1.f))) + (1.f));
	} else {
		float A = (1.f) - beta_11;
		float B = (alpha * (beta_11 - (1.f)))
				- (beta * (alpha_11 - (1.f))) - (1.f);
		float C = alpha;
		float D = (B * B) - ((4.f) * A * C);
		if (D < 0) return false;
		float Q = (-0.5) * (B + ((B < (0.0) ? (-1.0) : (1.0))
				* std::sqrt(D)));
		u = Q / A;
		if ((u < (0.0)) || (u > (1.0))) u = C / Q;
		v = beta / ((u * (beta_11 - (1.f))) + (1.f));
	}

	return true;
}