示例#1
0
__forceinline void Pipedata::addVertex(const Viewport& vp, const vec4& src, const mat4& m)
{
	auto point_in_eyespace = mat4_mul(m, src);
	auto point_in_clipspace = vp.eye_to_clip(point_in_eyespace);
	auto clipflags = Guardband::clipPoint(point_in_clipspace);

	vlst_p.push_back(point_in_eyespace);
	vlst_cf.push_back(clipflags);
	new_vcnt++;
}
示例#2
0
void Pipedata::process_face(PFace& f, const Viewport& vp, const Viewdevice& vpd)
{
	vec4 p1 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[0]]));
	vec4 p2 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[1]]));
	vec4 p3 = vpd.clip_to_device(vp.eye_to_clip(vlst_p[f.ivp[2]]));

	const vec4 d31 = p3 - p1;
	const vec4 d21 = p2 - p1;
	const float area = d31.x*d21.y - d31.y*d21.x;

	bool backfacing = area < 0;
	
	if (backfacing) return; // cull

//	if (f.backfacing) {
//		std::swap(p1, p3);
//	}

	binner.insert(p1, p2, p3, backfacing, f);
}
示例#3
0
void Pipedata::addFace(const Viewport& vp, const Viewdevice& vpd, const Face& fsrc)
{
	const int vidx1 = fsrc.ivp[0] + vbase;
	const int vidx2 = fsrc.ivp[1] + vbase;
	const int vidx3 = fsrc.ivp[2] + vbase;

	const auto& pv1_p = vlst_p[vidx1];
	const auto& pv2_p = vlst_p[vidx2];
	const auto& pv3_p = vlst_p[vidx3];
	const auto& pv1_cf = vlst_cf[vidx1];
	const auto& pv2_cf = vlst_cf[vidx2];
	const auto& pv3_cf = vlst_cf[vidx3];

	// early out if all points are outside of any plane
	if (pv1_cf & pv2_cf & pv3_cf) return;

	const unsigned required_clipping = pv1_cf | pv2_cf | pv3_cf;
	if (required_clipping == 0) {
		// all inside
		process_face(fsrc.make_rebased(vbase, tbase, nbase), vp, vpd);
		return;
	}

	// 	needs clipping
	unsigned a_vidx[32], b_vidx[32];
	unsigned a_tidx[32], b_tidx[32];
	unsigned a_nidx[32], b_nidx[32];
	unsigned a_cnt = 3;
	for (unsigned i = 0; i < 3; i++) {
		a_vidx[i] = fsrc.ivp[i] + vbase;
		a_tidx[i] = fsrc.iuv[i] + tbase;
		a_nidx[i] = fsrc.ipn[i] + nbase;
	}


	for (int clip_plane = 0; clip_plane < 5; clip_plane++) { // XXX set to 6 to enable the far plane

		const int planebit = 1 << clip_plane;
		if (!(required_clipping & planebit)) continue; // skip plane that is ok

		bool we_are_inside;
		unsigned this_pi = 0;
		unsigned b_cnt = 0;

		do {
			const auto next_pi = (this_pi + 1) % a_cnt; // wrap

			const auto& this_v_p = vlst_p[a_vidx[this_pi]];
			const auto  this_v_c = vp.eye_to_clip(this_v_p);
			const auto& this_t = tlst[a_tidx[this_pi]];
			const auto& this_n = nlst[a_nidx[this_pi]];

			const auto& next_v_p = vlst_p[a_vidx[next_pi]];
			const auto  next_v_c = vp.eye_to_clip(next_v_p);
			const auto& next_t = tlst[a_tidx[next_pi]];
			const auto& next_n = nlst[a_nidx[next_pi]];

			if (this_pi == 0) {
				we_are_inside = Guardband::is_inside(planebit, this_v_c);
			}
			const bool next_is_inside = Guardband::is_inside(planebit, next_v_c);

			if (we_are_inside) {
				b_vidx[b_cnt] = a_vidx[this_pi];
				b_tidx[b_cnt] = a_tidx[this_pi];
				b_nidx[b_cnt] = a_nidx[this_pi];
				b_cnt++;
			}

			if (we_are_inside != next_is_inside) {
				we_are_inside = !we_are_inside;

				const float t = Guardband::clipLine(planebit, this_v_c, next_v_c);

				auto new_p = lerp(this_v_p, next_v_p, t);
				auto new_c = vp.eye_to_clip(new_p);
				vlst_p.push_back(new_p);
				vlst_cf.push_back(0);
				b_vidx[b_cnt] = vlst_p.size() - 1;

				tlst.push_back(lerp(this_t, next_t, t));  b_tidx[b_cnt] = tlst.size() - 1;
				nlst.push_back(lerp(this_n, next_n, t));  b_nidx[b_cnt] = nlst.size() - 1;
				b_cnt++;
			}

			this_pi = next_pi;
		} while (this_pi != 0);

		for (unsigned i = 0; i < b_cnt; i++) {
			a_vidx[i] = b_vidx[i];
			a_tidx[i] = b_tidx[i];
			a_nidx[i] = b_nidx[i];
		}
		a_cnt = b_cnt;
		
		if (a_cnt == 0) break;
	}
	if (a_cnt == 0) return;

	for (unsigned a = 1; a < a_cnt - 1; a++) {
		PFace f = make_tri(
			fsrc.mf,
			a_vidx[0], a_vidx[a], a_vidx[a + 1],
			a_tidx[0], a_tidx[a], a_tidx[a + 1],
			a_nidx[0], a_nidx[a], a_nidx[a + 1]);
		process_face(f, vp, vpd);
	}

}
示例#4
0
void Binner::insert_gltri(
	const Viewport& vp,
	const Viewdevice& vpd,
	const vec4 * const pv,
	const vec4 * const pn,
	const vec4 * const pc,
	const vec4 * const pt,
	int i0, int i1, int i2,
	const int material_id
)
{
	auto p1 = vpd.clip_to_device(vp.eye_to_clip(pv[i0]));
	auto p2 = vpd.clip_to_device(vp.eye_to_clip(pv[i1]));
	auto p3 = vpd.clip_to_device(vp.eye_to_clip(pv[i2]));

	const auto d31 = p3 - p1;
	const auto d21 = p2 - p1;
	const float area = d31.x*d21.y - d31.y*d21.x;
	auto backfacing = area < 0;
	if (backfacing) return; // cull
	/*
	if (backfacing) {
		std::swap(p1, p3);
		std::swap(i0, i2);
	}
	*/

	auto pmin = vmax(vmin(p1, vmin(p2, p3)), vec4::zero());
	auto pmax = vmin(vmax(p1, vmax(p2, p3)), device_max);

	auto x0 = int(pmin._x());
	auto y0 = int(pmin._y());
	auto x1 = int(pmax._x()); // trick: set this to pmin._x()
	auto y1 = int(pmax._y());

	const int ylim = min(y1 / tileheight, device_height_in_tiles - 1);
	const int xlim = min(x1 / tilewidth, device_width_in_tiles - 1);

	const int tx0 = x0 / tilewidth;
	for (int ty = y0 / tileheight; ty <= ylim; ty++) {
		int bin_row_offset = ty * device_width_in_tiles;
		for (int tx = tx0; tx <= xlim; tx++) {
			auto& bin = bins[bin_row_offset + tx];

			unsigned char facedata = material_id;
			if (backfacing) facedata |= 0x80;
			bin.glface.push_back(facedata);

			bin.gldata.push_back(p1);
			bin.gldata.push_back(pv[i0]);
			bin.gldata.push_back(pn[i0]);
			bin.gldata.push_back(pc[i0]);
			bin.gldata.push_back(pt[i0]);

			bin.gldata.push_back(p2);
			bin.gldata.push_back(pv[i1]);
			bin.gldata.push_back(pn[i1]);
			bin.gldata.push_back(pc[i1]);
			bin.gldata.push_back(pt[i1]);

			bin.gldata.push_back(p3);
			bin.gldata.push_back(pv[i2]);
			bin.gldata.push_back(pn[i2]);
			bin.gldata.push_back(pc[i2]);
			bin.gldata.push_back(pt[i2]);
		}
	}
}