calculating viewing angle & back-to-front ordering

Hi, I’m trying to render a slice stack (later for use in volume rendering) in back-to-front order dependant of the viewing angle.

I have managed to get the basis down, but the code i have is quite buggy.

The main problem is that my tests for which order the slices should be rendered in does not always work properly, and sometimes returns front-to-back ordering, or doesn’t pick up that it should change the ordering at certain angles.

At first i thought this may be due to Gimbal lock, but upon using quaternions the problem has not been fixed. So i assume it is an error somewhere in my calculations.

can anyone possibly shead some light for me?

Thanks
–Tristan

Note: i built this code from the psuedo code from the Course notes of this site
http://www.cs.utah.edu/~jmk/sigg_crs_02/courses_0067.html

void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -10.0f);
CQuat test;
test.eulerToQuat(ogld::COpenGLDriver::getInstance()->camera_rotation.x, ogld::COpenGLDriver::getInstance()->camera_rotation.y, ogld::COpenGLDriver::getInstance()->camera_rotation.z);
glMultMatrixf(test.quatToMatrix().array);

GLdouble pModelViewMatrix[16];
GLdouble pModelViewRotationMatrix[16];
// obtain the current modeling/viewing matrix from the OpenGL state
glGetDoublev(GL_MODELVIEW_MATRIX, pModelViewMatrix);

// GetRotation( pModelViewMatrix, pModelViewRotationMatrix );
pModelViewRotationMatrix[0] = pModelViewMatrix[0];
pModelViewRotationMatrix[1] = pModelViewMatrix[1];
pModelViewRotationMatrix[2] = pModelViewMatrix[2];
pModelViewRotationMatrix[4] = pModelViewMatrix[4];
pModelViewRotationMatrix[5] = pModelViewMatrix[5];
pModelViewRotationMatrix[6] = pModelViewMatrix[6];
pModelViewRotationMatrix[8] = pModelViewMatrix[8];
pModelViewRotationMatrix[9] = pModelViewMatrix[9];
pModelViewRotationMatrix[10] = pModelViewMatrix[10];
pModelViewRotationMatrix[15] = 1;

// rotate the initial viewing direction
GLdouble pViewVector[3] = {0.0f, 0.0f, -1.0f};

// MatVecMultiply(pModelViewRotationMatrix, pViewVector);
GLdouble temp[3];
pViewVector[0] = pModelViewRotationMatrix[8]*pViewVector[2];
pViewVector[1] = pModelViewRotationMatrix[9]*pViewVector[2];
pViewVector[2] = pModelViewRotationMatrix[10]*pViewVector[2];

temp[0] = fabs(pViewVector[0]);
temp[1] = fabs(pViewVector[1]);
temp[2] = fabs(pViewVector[2]);

// find the maximal vector component
int index = -1;
if (temp[0] < temp[1]) {
if (temp[1] < temp[2])
index = 2;
else
index = 1;
} else {
if (temp[0] < temp[2])
index = 2;
else
index = 0;
}

int slices = 32;

glBegin(GL_QUADS);

if (index == 0)
{
glColor3f(1.0f, 0.0f, 0.0f);

  if (pViewVector[0] < 0.0f)	{

  	std::cout << "x:+

";
// draw slice stack positive x
for (float f = 1.0f ; f > -1.0f ; f -= 2.0f/slices) {
glVertex3f(f, -1.0f, -1.0f);
glVertex3f(f, -1.0f, 1.0f);
glVertex3f(f, 1.0f, 1.0f);
glVertex3f(f, 1.0f, -1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
}

  }	else	{

  	std::cout << "x:-

";
// draw slice stack negative x
for (float f = -1.0f ; f < 1.0f ; f += 2.0f/slices) {
glVertex3f(f, -1.0f, -1.0f);
glVertex3f(f, -1.0f, 1.0f);
glVertex3f(f, 1.0f, 1.0f);
glVertex3f(f, 1.0f, -1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
}
}

}
else if (index == 1)
{
glColor3f(1.0f, 0.0f, 0.0f);

  if (pViewVector[1] < 0.0f)	{

  	std::cout << "y:+

";
for (float f = 1.0f ; f > -1.0f ; f -= 2.0f/slices) {
glVertex3f(-1.0f, f, -1.0f);
glVertex3f(-1.0f, f, 1.0f);
glVertex3f( 1.0f, f, 1.0f);
glVertex3f( 1.0f, f, -1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
}

  }	else	{

  	std::cout << "y:-

";
for (float f = -1.0f ; f < 1.0f ; f += 2.0f/slices) {
glVertex3f(-1.0f, f, -1.0f);
glVertex3f(-1.0f, f, 1.0f);
glVertex3f( 1.0f, f, 1.0f);
glVertex3f( 1.0f, f, -1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
}
}
}
else if (index == 2)
{
glColor3f(1.0f, 0.0f, 0.0f);

  if (pViewVector[2] > 0.0f)	{

  	std::cout << "z:+

";
for (float f = 1.0f ; f > -1.0f ; f -= 2.0f/slices) {
glVertex3f(-1.0f, -1.0f, f);
glVertex3f( 1.0f, -1.0f, f);
glVertex3f( 1.0f, 1.0f, f);
glVertex3f(-1.0f, 1.0f, f);
glColor3f(1.0f, 1.0f, 1.0f);
}

  }	else	{

  	std::cout << "z:-

";
for (float f = -1.0f ; f < 1.0f ; f += 2.0f/slices) {
glVertex3f(-1.0f, -1.0f, f);
glVertex3f( 1.0f, -1.0f, f);
glVertex3f( 1.0f, 1.0f, f);
glVertex3f(-1.0f, 1.0f, f);
glColor3f(1.0f, 1.0f, 1.0f);
}
}
}

glEnd();
}

If it helps - here’s the code that I use to determine which stack to render and in what order (the enums should be self-explanatory) -

C2DRenderer::RenderOrder C2DRenderer::GetRenderingOrder()
{
	// determine rendering order based on current view
	float fMatrix[16];
	RenderOrder nOrder;

	// get current modelview matrix
	glGetFloatv(GL_MODELVIEW_MATRIX, fMatrix);

	//find the plane opposite the viewer
	if (fabs(fMatrix[2]) > fabs(fMatrix[6]))
	{
		if (fabs(fMatrix[2]) > fabs(fMatrix[10]))
		{
			//X is largest
			if (fMatrix[2] > 0.0f)
				nOrder = RO_X_FRONT_TO_BACK;
			else
				nOrder = RO_X_BACK_TO_FRONT;
		}
		else
		{
			//Z is largest
			if (fMatrix[10] > 0.0f)
				nOrder = RO_Z_FRONT_TO_BACK;
			else
				nOrder = RO_Z_BACK_TO_FRONT;
		}
	}
	else
	{
		if (fabs(fMatrix[6]) > fabs(fMatrix[10]))
		{
			//Y is largest
			if (fMatrix[6] > 0.0f)
				nOrder = RO_Y_FRONT_TO_BACK;
			else
				nOrder = RO_Y_BACK_TO_FRONT;
		}
		else
		{
			//Z is largest
			if (fMatrix[10] > 0.0f)
				nOrder = RO_Z_FRONT_TO_BACK;
			else
				nOrder = RO_Z_BACK_TO_FRONT;
		}
	}

	// return result
	return nOrder;
}

Any use?

thanks Rog
works beautifully :slight_smile:

–Tristan