Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Clipping plane by using stencil buffer for mesh objects with unclosed tubes

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4

    Question Clipping plane by using stencil buffer for mesh objects with unclosed tubes


    I have a project, which requires to intersect anatomical mesh objects along specified axis (e.g. from head to foot) into a series of 2D gray-level slices. I used OpenGL stencil buffer with defined clipping plane to generate 2D slices.
    For most of mesh objects, I can obtain good 2D intersected slices. But some mesh objects, like heart and trachea, with more tubes not-enclosed (airways, arteries, veins), this clipping algorithm did not work well. After stacking 2D slices to a volume, it looks to be extended along the end of tube to the bottom. Fig. 1 is the mesh object with texturing, Fig.2 shows each slice and Fig. 3 the stacked volume.

    Please help find possible reasons for this issue, and any helpful suggestions are welcome.
    Click image for larger version. 

Name:	test01.jpg 
Views:	24 
Size:	19.1 KB 
ID:	2455 Click image for larger version. 

Name:	test03.jpg 
Views:	23 
Size:	11.8 KB 
ID:	2456 Click image for larger version. 

Name:	test02.jpg 
Views:	35 
Size:	15.0 KB 
ID:	2457

    The following is my code snippets,

    Code cpp:

    Code cpp:
        GLdouble eq[] = {A, B, C, D};
        glClipPlane(GL_CLIP_PLANE0, eq);
     
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_CLIP_PLANE0);
        glEnable(GL_STENCIL_TEST);
     
        glClear(GL_STENCIL_BUFFER_BIT);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
     
        // first pass: back face increment
        glStencilFunc(GL_ALWAYS, 0, 0);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
        glCullFace(GL_FRONT);
        glEnable(GL_CULL_FACE);
     
        DrawCore(false, false, false, false); // draw mesh objects
     
        // second pass: front face increment
        glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
        glCullFace(GL_BACK);
        glEnable(GL_CULL_FACE);
     
        DrawCore(false, false, false, false); // draw mesh objects
     
        // drawing clip planes masked by stencil buffer content
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glEnable(GL_DEPTH_TEST);
        glDisable(GL_CLIP_PLANE0);
     
        glStencilFunc(GL_NOTEQUAL, 0, ~0);
     
        // rendering clip edges to frame buffer
        glPushMatrix();
        glLoadMatrixf(view_mat);    // Clip plane had been set up after view_mat space, thus we need to load
                            // view_mat matrix before rendering clip plane
        glBegin(GL_QUADS);
                CVector nrml = cross(CVector(verts[m_nEquationSelection][2] - verts[m_nEquationSelection][1]), CVector(verts[m_nEquationSelection][1] - verts[m_nEquationSelection][0]));
                nrml.normalize();
                glNormal3f(nrml(0), nrml(1), nrml(2)); //We want plane to be lit properly, thus we need to specify it's normal.
     
                glVertex3f(verts[m_nEquationSelection][0](0) * 100.0, verts[m_nEquationSelection][0](1) - eq[3], verts[m_nEquationSelection][0](2) * 100.0);
                glVertex3f(verts[m_nEquationSelection][1](0) * 100.0, verts[m_nEquationSelection][1](1) - eq[3], verts[m_nEquationSelection][1](2) * 100.0);
                glVertex3f(verts[m_nEquationSelection][2](0) * 100.0, verts[m_nEquationSelection][2](1) - eq[3], verts[m_nEquationSelection][2](2) * 100.0);
                glVertex3f(verts[m_nEquationSelection][3](0) * 100.0, verts[m_nEquationSelection][3](1) - eq[3], verts[m_nEquationSelection][3](2) * 100.0);
     
        glEnd();
     
        glPopMatrix();
     
        saveStencilBufferToExtraMemory(…, …);    // using "glReadPixels()" to read the stencil buffer and save to memory and then to a file
     
        glDisable(GL_DEPTH_TEST);
     
        glDisable(GL_STENCIL_TEST);
        glClear(GL_STENCIL_BUFFER_BIT);
    Last edited by Dark Photon; 08-17-2017 at 06:11 AM.

  2. #2
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    435
    i'd try to use a 3D texture to store the "slices", or an 2D array texture, but that would require to program your own pipeline (without legacy GL functions).

    for example, you disable depth testing / culling / stencil test etc, and attach a 3D texture to an framebuffe object, then use a simple vertex + fragment shader to render the meshes as usual, but in the fragment shader you use the fragments depth value to determine the final 3D texture texel in which to write the resulting color.

    when you want to visualize an arbitrary "slice", render a simple textured quad (use the generated 3D texture), depending on the orientation of your quad you can look into arbitrary positions on the mesh.
    Last edited by john_connor; 08-16-2017 at 04:10 PM.

  3. #3
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,480
    Quote Originally Posted by michael_ca View Post
    For most of mesh objects, I can obtain good 2D intersected slices. But some mesh objects, like heart and trachea, with more tubes not-enclosed (airways, arteries, veins), this clipping algorithm did not work well.
    Is the presence of uncapped tubes the only feature of the problematic meshes? Are they 2-manifold surfaces otherwise? Is face winding consistent (i.e. are front/back faces identified correctly)? Does it make any difference if you use a single pass (both front and back faces) with GL_INVERT?

    I can't think of any explanation for the vertical "smear" in the third attachment. It shouldn't be possible to modify the stencil value of any pixel which isn't covered by at least one surface.

    Quote Originally Posted by john_connor View Post
    i'd try to use a 3D texture to store the "slices"
    He isn't rendering voxel data. He's rendering meshes, using stencilling to detect regions which are made "open" by clipping.

  4. #4
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4

    Thank you for these helpful hints

    Thank very much you guys.
    GClements' hints are enlightening me. I am now checking my meshes and capping code.

    My mesh rendering looks good. I have intersected bones, lungs, kidneys, colon, and 2D capping looks very well. Only the capping for trachea, heart, stomach did not work well. Especially the result of intersecting for human heart mesh is so bad, because it has more uncapped tubes.

    In these objects, definition for the position of some meshes is mirrored(scale value is negative). Before capping, I changed the face winding direction (from GL_CCW to GL_CW). Only these meshes with uncapped tubes can not work.

    I also tried to use more passing processing. But till now, I did not get good results yet.

    Quote Originally Posted by GClements View Post
    Is the presence of uncapped tubes the only feature of the problematic meshes? Are they 2-manifold surfaces otherwise? Is face winding consistent (i.e. are front/back faces identified correctly)? Does it make any difference if you use a single pass (both front and back faces) with GL_INVERT?

    I can't think of any explanation for the vertical "smear" in the third attachment. It shouldn't be possible to modify the stencil value of any pixel which isn't covered by at least one surface.


    He isn't rendering voxel data. He's rendering meshes, using stencilling to detect regions which are made "open" by clipping.

  5. #5
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    4

    I finally fixed out this issue.

    Hello everybody,

    Finally I got very perfect volumes. GClements' suggestion is very helpful.

    I first tried my static model, and found the problem's core is hole issue. I used meshlab to close hole and run my code, it worked.

    Because my major interest is on dynamic data. I applied my needed vcglib (that meshlab uses) functions to my code, keeping the original vertices of mesh, no change was made.

    Of course, the result is amazing.

    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	NewResult.jpg 
Views:	11 
Size:	21.2 KB 
ID:	2536  

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •