https://github.com/ialhashim/topo-blend
Revision 39b13612ebd645a65eda854771b517371f2f858a authored by ennetws on 13 March 2015, 18:17:18 UTC, committed by ennetws on 13 March 2015, 18:17:18 UTC
1 parent c702819
Raw File
Tip revision: 39b13612ebd645a65eda854771b517371f2f858a authored by ennetws on 13 March 2015, 18:17:18 UTC
Create README.md
Tip revision: 39b1361
TriAccel.h
#pragma once

/**
* \brief Pre-computed triangle representation based on Ingo Wald's TriAccel layout.
*
* Fits into three 16-byte cache lines if single precision floats are used.
* The k parameter is also used for classification during kd-tree construction.
* \ingroup librender
*/
template<typename Real, typename Vector3>
struct TriAccel {
	unsigned int k;
	Real n_u;
	Real n_v;
	Real n_d;

	Real a_u;
	Real a_v;
	Real b_nu;
	Real b_nv;

	Real c_nu;
	Real c_nv;

	/// Construct from vertex data. Returns '1' if there was a failure
	inline int load(const Vector3 &A, const Vector3 &B, const Vector3 &C) 
	{
		static const int waldModulo[4] = { 1, 2, 0, 1 };

		Vector3 b = C-A, c = B-A, N = cross(c, b);

		k = 0;
		/* Determine the largest projection axis */
		for (int j=0; j<3; j++) {
			if (std::abs(N[j]) > std::abs(N[k]))
				k = j;
		}

		unsigned int u = waldModulo[k],	v = waldModulo[k+1];
		const Real n_k = N[k], denom = b[u]*c[v] - b[v]*c[u];

		if (denom == 0) {
			k = 3;
			qDebug() << "warning: load failed";
			return 1;
		}

		/* Pre-compute intersection calculation constants */
		n_u   =  N[u] / n_k;
		n_v   =  N[v] / n_k;
		n_d   =  dot(A, N) / n_k;
		b_nu  =  b[u] / denom;
		b_nv  = -b[v] / denom;
		a_u   =  A[u];
		a_v   =  A[v];
		c_nu  =  c[v] / denom;
		c_nv  = -c[u] / denom;
		return 0;
	}

	struct TriAccelRay{ Vector3 o,d; TriAccelRay(const Vector3& origin, const Vector3& direction) : o(origin), d(direction){} };

	/// Fast ray-triangle intersection test
	inline bool rayIntersect(const TriAccelRay &ray, Real mint, Real maxt, Real &u, Real &v, Real &t) const {
		Real o_u, o_v, o_k, d_u, d_v, d_k;
		switch (k) {
		case 0:
			o_u = ray.o[1];
			o_v = ray.o[2];
			o_k = ray.o[0];
			d_u = ray.d[1];
			d_v = ray.d[2];
			d_k = ray.d[0];
			break;
		case 1:
			o_u = ray.o[2];
			o_v = ray.o[0];
			o_k = ray.o[1];
			d_u = ray.d[2];
			d_v = ray.d[0];
			d_k = ray.d[1];
			break;
		case 2:
			o_u = ray.o[0];
			o_v = ray.o[1];
			o_k = ray.o[2];
			d_u = ray.d[0];
			d_v = ray.d[1];
			d_k = ray.d[2];
			break;
		default:
			return false;
		}

		/* Calculate the plane intersection (Typo in the thesis?) */
		t = (n_d - o_u*n_u - o_v*n_v - o_k) /
			(d_u * n_u + d_v * n_v + d_k);

		if (t < mint || t > maxt)
			return false;

		/* Calculate the projected plane intersection point */
		const Real hu = o_u + t * d_u - a_u;
		const Real hv = o_v + t * d_v - a_v;

		/* In barycentric coordinates */
		u = hv * b_nu + hu * b_nv;
		v = hu * c_nu + hv * c_nv;
		return u >= 0 && v >= 0 && u+v <= 1;
	}
};
back to top