Ejemplo n.º 1
0
void DrawPlane(const AABB& bounds, const Plane& plane)
{
	Vec3 points[6];
	struct Edge
	{
		int start;
		int end;
	};

	static Edge 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] = Vec3(minmax[ix]->x, minmax[iy]->y, minmax[iz]->z);
	}

	int numPoints = 0;

	// add corners
	for(int j = 0; j < 8; ++j)
	{
		float planeDist = dot(plane.m_normal, corners[j]) - plane.m_d;
		if(fabs(planeDist) < EPSILON)
			points[numPoints++] = corners[j];
	}

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

		float t = (plane.m_d - dot(plane.m_normal, a)) / dot(plane.m_normal, ab);
		if(t >= 0.f && t <= 1.f)
		{
			Vec3 pt = a + t * ab;
			Vec3 ptA = a - pt;
			Vec3 ptB = b - pt;
			float distSqA = magnitude_squared(ptA);
			float distSqB = magnitude_squared(ptB);
			if(distSqA > EPSILON_SQ && distSqB > EPSILON_SQ)
			{
				points[numPoints++] = pt;
				if(numPoints == 6)
					break;
			}	
		}
	}

	if(numPoints < 3)
		return;

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

	Vec3 sideVec = normalize(points[0] - center);
	Vec3 upVec = normalize(cross(plane.m_normal, 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;
				Vec3 temp = points[j];
				points[j] = points[k];
				points[k] = temp;
			}
		}
	}

	// Draw outline
	glColor3f(7.f, 0.3f, 0.3f);
	glLineWidth(2.f);

	glBegin(GL_LINES);
	for(int j = 0; j < numPoints; ++j)
	{
		int next = (j + 1) % numPoints;
		glVertex3fv(&points[j].x);
		glVertex3fv(&points[next].x);
	}
	glEnd();

	glLineWidth(1.f);

	// Draw triangles
	glColor4f(7.f, 0.3f, 0.3f, 0.3f);
	glBegin(GL_TRIANGLE_FAN);
	glVertex3fv(&center.x);
	for(int j = 0; j < numPoints; ++j)
		glVertex3fv(&points[j].x);
	glVertex3fv(&points[0].x);
	glEnd();

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

}
Ejemplo n.º 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();

}