예제 #1
0
파일: r_bsp.c 프로젝트: AAS/ezquake-source
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) {
	bedge_t *psideedges[2], *pnextedge, *ptedge;
	int i, side, lastside;
	float dist, frac, lastdist;
	mplane_t *splitplane, tplane;
	mvertex_t *pvert, *plastvert, *ptvert;
	mnode_t *pn;

	psideedges[0] = psideedges[1] = NULL;

	makeclippededge = false;

	// transform the BSP plane into model space
	// FIXME: cache these?
	splitplane = pnode->plane;
	tplane.dist = -PlaneDiff(r_entorigin, splitplane);
	tplane.normal[0] = PlaneDist (entity_rotation[0], splitplane);
	tplane.normal[1] = PlaneDist (entity_rotation[1], splitplane);
	tplane.normal[2] = PlaneDist (entity_rotation[2], splitplane);

	// clip edges to BSP plane
	for ( ; pedges ; pedges = pnextedge) {
		pnextedge = pedges->pnext;

		// set the status for the last point as the previous point
		// FIXME: cache this stuff somehow?
		plastvert = pedges->v[0];
		
		lastdist = DotProduct (plastvert->position, tplane.normal) - tplane.dist;
		lastside = (lastdist <= 0);

		pvert = pedges->v[1];
		
		dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
		side = (dist <= 0);

		if (side != lastside) {
			// clipped
			if (numbverts >= MAX_BMODEL_VERTS)
				return;

			// generate the clipped vertex
			frac = lastdist / (lastdist - dist);
			ptvert = &pbverts[numbverts++];
			ptvert->position[0] = plastvert->position[0] + frac * (pvert->position[0] -	plastvert->position[0]);
			ptvert->position[1] = plastvert->position[1] + frac * (pvert->position[1] - plastvert->position[1]);
			ptvert->position[2] = plastvert->position[2] + frac * (pvert->position[2] - plastvert->position[2]);

			// split into two edges, one on each side, and remember entering
			// and exiting points
			// FIXME: share the clip edge by having a winding direction flag?
			if (numbedges >= (MAX_BMODEL_EDGES - 1)) {
				Com_Printf ("Out of edges for bmodel\n");
				return;
			}

			ptedge = &pbedges[numbedges];
			ptedge->pnext = psideedges[lastside];
			psideedges[lastside] = ptedge;
			ptedge->v[0] = plastvert;
			ptedge->v[1] = ptvert;

			ptedge = &pbedges[numbedges + 1];
			ptedge->pnext = psideedges[side];
			psideedges[side] = ptedge;
			ptedge->v[0] = ptvert;
			ptedge->v[1] = pvert;

			numbedges += 2;

			if (side == 0) {
				// entering for front, exiting for back
				pfrontenter = ptvert;
				makeclippededge = true;
			} else {
				pfrontexit = ptvert;
				makeclippededge = true;
			}
		} else {
			// add the edge to the appropriate side
			pedges->pnext = psideedges[side];
			psideedges[side] = pedges;
		}
	}

	// if anything was clipped, reconstitute and add the edges along the clip
	// plane to both sides (but in opposite directions)
	if (makeclippededge) {
		if (numbedges >= (MAX_BMODEL_EDGES - 2)) {
			Com_Printf ("Out of edges for bmodel\n");
			return;
		}

		ptedge = &pbedges[numbedges];
		ptedge->pnext = psideedges[0];
		psideedges[0] = ptedge;
		ptedge->v[0] = pfrontexit;
		ptedge->v[1] = pfrontenter;

		ptedge = &pbedges[numbedges + 1];
		ptedge->pnext = psideedges[1];
		psideedges[1] = ptedge;
		ptedge->v[0] = pfrontenter;
		ptedge->v[1] = pfrontexit;

		numbedges += 2;
	}

	// draw or recurse further
	for (i = 0; i < 2; i++) {
		if (psideedges[i]) {
			// draw if we've reached a non-solid leaf, done if all that's left is a
			// solid leaf, and continue down the tree if it's not a leaf
			pn = pnode->children[i];

			// we're done with this branch if the node or leaf isn't in the PVS
			if (pn->visframe == r_visframecount) {
				if (pn->contents < 0) {
					if (pn->contents != CONTENTS_SOLID) {
						r_currentbkey = ((mleaf_t *)pn)->key;
						R_RenderBmodelFace (psideedges[i], psurf);
					}
				} else {
					R_RecursiveClipBPoly (psideedges[i], pnode->children[i], psurf);
				}
			}
		}
	}
}
예제 #2
0
static void ddDrawPlane(const Plane& plane, const AABB& bounds, const Color& color)
{
	vec3 points[6];
	struct edge_t
	{
		int start;
		int end;
	};

	static const edge_t edges[12] =
	{
		// bottom
		{0, 1},
		{1, 3},
		{3, 2},
		{2, 0},

		// top
		{4, 5},
		{5, 7},
		{7, 6},
		{6, 4},

		// top to bottom sides
		{0, 4},
		{1, 5},
		{2, 6},
		{3, 7},
	};

	// clip plane to bounds and render a quad
	vec3 corners[8];
	const vec3 *minmax[2] = { &bounds.m_min, &bounds.m_max };       
	for(int j = 0; j < 8; ++j)
	{
		int iz = j & 1;
		int ix = (j >> 1) & 1;
		int iy = (j >> 2) & 1;
		corners[j].Set(minmax[ix]->x, minmax[iy]->y, minmax[iz]->z);
	}

	int numPoints = 0;

	// add corners as points if they are close to the plane
	for(int j = 0; j < 8; ++j)
	{
		float planeDist = PlaneDist(plane, corners[j]);
		if(fabs(planeDist) < EPSILON)
			points[numPoints++] = corners[j];
	}

	// add edge intersections 
	for(int j = 0; j < 12; ++j)
	{
		vec3 a = corners[edges[j].start], 
			b = corners[edges[j].end], 
			ab = b - a;

		// intersect edge with plane
		float t = (-plane.m_d - Dot(plane.m_n, a)) / Dot(plane.m_n, ab);
		if(t >= 0.f && t <= 1.f)
		{
			vec3 pt = a + t * ab, 
				ptA = a - pt, 
				ptB = b - pt;

			float distSqA = LengthSq(ptA);
			float distSqB = LengthSq(ptB);
			if(distSqA > EPSILON_SQ && distSqB > EPSILON_SQ)
			{
				points[numPoints++] = pt;
				if(numPoints == 6)
					break;
			}       
		}
	}

	if(numPoints < 3)
		return;

	// Sort results
	const float inv_num = 1.f / numPoints;
	vec3 center = {0,0,0};
	for(int j = 0; j < numPoints; ++j)
		center += inv_num * points[j];

	vec3 sideVec = Normalize(points[0] - center);
	vec3 upVec = Normalize(Cross(plane.m_n, sideVec));

	for(int j = 1; j < numPoints; ++j)
	{    
		vec3 toPointJ = points[j] - center;

		float angleJ = AngleWrap(atan2(Dot(upVec, toPointJ), Dot(sideVec, toPointJ)));
		for(int k = j+1; k < numPoints; ++k)
		{
			vec3 toPointK = points[k] - center;
			float angleK = AngleWrap(atan2(Dot(upVec, toPointK), Dot(sideVec, toPointK)));
			if(angleK < angleJ) 
			{
				angleJ = angleK;
				std::swap(points[j], points[k]);
			}
		}
	}

	// Draw outline
	const ShaderInfo* shader = g_dbgdrawShader.get();
	GLint posLoc = shader->m_attrs[GEOM_Pos];
	GLint colorLoc = shader->m_attrs[GEOM_Color];
	glVertexAttrib3fv(colorLoc, &color.r);

	glLineWidth(2.f);
	glBegin(GL_LINES);
	for(int j = 0; j < numPoints; ++j)
	{
		int next = (j + 1) % numPoints;
		glVertexAttrib3fv(posLoc, &points[j].x);
		glVertexAttrib3fv(posLoc, &points[next].x);
	}
	glEnd();
	glLineWidth(1.f);

	// Draw triangles
	glVertexAttrib3fv(colorLoc, &color.r);
	glBegin(GL_TRIANGLE_FAN);
	glVertexAttrib3fv(posLoc, &center.x);
	for(int j = 0; j < numPoints; ++j)
		glVertexAttrib3fv(posLoc, &points[j].x);
	glVertexAttrib3fv(posLoc, &points[0].x);
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
	glVertexAttrib3fv(posLoc, &center.x);
	for(int j = numPoints-1; j >= 0; --j)
		glVertexAttrib3fv(posLoc, &points[j].x);
	glVertexAttrib3fv(posLoc, &points[numPoints-1].x);
	glEnd();

}