Thursday, June 5, 2008

Object aligned slice based volume rendering


I just finished 2D texture slices based volume rendering today. Here are the snapshots of the application. Its damn fast. I will be adding some transfer function editing facility into it tomorrow.

A cool idea though will now work on transfer functions and then view aligned slicing of 3D texture.



Object aligned slicing

Implementation details:

I used glut and OpenGL for this b/c I think its much more fast to develop applications in OpenGL and glut. First I determine the current view direction vector which is simply obtained using the following code


GLfloat matView[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matView);
GLfloat viewDir[3]={ -matView[2], -matView[6], -matView[10]};


Next a 3d texture is loaded from the CT/MRI scans and then using this code, object space quad slices are generated. Here I am only giving the code for the PosZ axis. A slight modification is needed for the other axes.



void DrawSliceZPos()
{
float zPos = 0.5;
float zAmt = -1.0f/zSlices;

glBindTexture(GL_TEXTURE_3D,textureID);
glBegin(GL_QUADS);

//offset the slice so its in the middle
zPos += zAmt/2.0f;
for(int i=zSlices-1;i>=0;i--)
{
float tex = (((float)i)/zSlices);
glTexCoord3f(0,0,tex); glVertex3f(-0.5, -0.5, zPos);
glTexCoord3f(0,1,tex); glVertex3f(-0.5, 0.5, zPos);
glTexCoord3f(1,1,tex); glVertex3f( 0.5, 0.5, zPos);
glTexCoord3f(1,0,tex); glVertex3f( 0.5, -0.5, zPos);
zPos += zAmt;
}
glEnd();
}


The appropriate slices are drawn based on the maximum abs value of the current view direction as



switch(GetMaxDim(viewDir))
{
case 0:
if(viewDir[maxDim] > 0.0f)
DrawSlicePosX();
else
DrawSliceNegX();
break;
...
case n: ... and so on
}


Thats it and finally the result is blended to produce the rendering as shown above.

3 comments:

  1. Can you upload the code example of this. Thx in advance!!!!!! great job

    ReplyDelete
  2. Could you please show how do you do a final blending? Thanks...

    ReplyDelete
  3. Hi,
    It follows the conventional over blending eq. i.e.

    glEnable(GL_BLENDING);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    The overall rendering code is as follows (assuming volume texture is bound to texture target GL_TEXTURE_3D):

    void Render() {
    glClear(GL_COLOR_BUFFER_BIT|
    GL_DEPTH_BUFFER_BIT);

    //setup modelview matrix;
    GLfkoat MV[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, MV);
    GLfloat viewDir[3]={-MV[2],-MV[6], -MV[10]};

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    switch(GetMaxDim(viewDir)){
    case 0:
    if(viewDir[maxDim] > 0.f)
    DrawSlicesPosX();
    else
    DrawSlicesNegX();
    break;

    case 1:
    if(viewDir[maxDim] > 0.f)
    DrawSlicesPosY();
    else
    DrawSlicesNegY();
    break;

    case 2:
    if(viewDir[maxDim] > 0.f)
    DrawSlicesPosZ();
    else
    DrawSlicesNegZ();
    break;
    }
    glDisable(GL_BLEND);
    glutSwapBuffers();
    }

    ReplyDelete