Click here to Skip to main content
11,490,408 members (40,702 online)
Click here to Skip to main content

A small VRML viewer using OpenGL and MFC

, 30 Nov 1999 332K 14.1K 149
Rate this:
Please Sign up or sign in to vote.
  • Download files - 669 Kb
  • <!-- Article Starts -->

    FIG. 1. You can easily display a wrl-based terrain using OpenGL and MFC.
     

    This contribution is a small MFC sample to learn how to :

    • display a VRML file
    • use OpenGL display lists
    • superimpose wireframe on a flat or smoothly shaded mesh
    • smoothly subdivide a 3D triangular mesh (from Charles Loop)
    • implement mouse interaction (rotation and translation)
    • build a scene graph from a vrml 2.0 file (hand-made and not lex-based)

    DISPLAY LIST

    Using display lists is a nice way to accelerate your rendering application. A display list compiles a sequence of gl drawings using standard OpenGL calls, then can be recalled later using a simple list id number. The resulting list is thus resident in the main memory in a precompilated mode, the which greatly accelerates rendering loops. A good command sequence to build a display list may be :
    int list = ::glGenLists(1); <font color="#009900">// ask for a free id number</font> 
    ::glNewList(list,GL_COMPILE_AND_EXECUTE); 
      ::glBegin(GL_TRIANGLES); 
      <font color="#009900">// std gl calls here... fill vertices, normals, colors</font> 
      ::glEnd(); 
    ::glEndList();
    A good command sequence to use a display list may be :
    if(::glIsList(list) == GL_TRUE)
      ::glCallList(m_ListOpenGL);
    The sample builds a scene graph from a vrml 2.0 file (exported via 3D Studio Max only), then uses display lists. Each 3D mesh contains a list number, and use a glCallList command instead of standards glBegin(GL_TRIANGLES) commands when its list is built. A flag m_Modified permits to rebuild the list when the mesh is modified.
    //******************************************** 
    // The 3D mesh class definition 
    //******************************************** 
    class CMesh2d : public CObject3d 
    { 
    private : 
    
     // Std datas 
     CArray<CVertex3d> m_ArrayVertex; 
     CArray<CFace3d>   m_ArrayFace; 
    
     // OpenGL-specific 
     unsigned int m_ListOpenGL; 
     BOOL m_ListDone; 
     BOOL m_Modified; 
     .../... 
    
    public : 
     BOOL glDraw(); 
     .../... 
    } 
    
    //******************************************** 
    // Mesh drawing 
    //******************************************** 
    BOOL CMesh2d::glDraw() 
    { 
     // Build list at first 
     if(!m_ListDone || m_Modified) 
      glBuildList(); 
    
     // Is the list valid ? 
     if(::glIsList(m_ListOpenGL)==GL_TRUE) 
     { 
       ::glCallList(m_ListOpenGL); 
      return TRUE; 
     } 
     return FALSE; 
    }

    SUPERIMPOSING WIREFRAME

    Sometime you would like to view the wireframe superimposing the flat or smooth shaded mesh. A good way to do this is to use the glPolygonOffset command, which creates a z-buffer offset. The following code shows the RenderScene function of the document, if one resumes two rendering passes are necessary, the first render the mesh using lighted flat mode, the second cut off the light, set the line mode, set a z-buffer offset, then draw the mesh again.
    <font color="#009900">//*********************************************** 
    // RenderScene 
    //***********************************************</font> 
    void CMeshDoc::RenderScene() 
    { 
     // Main drawing 
     m_SceneGraph.glDraw(); 
    
     // Add wireframe (no light, and line mode) 
     if(m_AddWireframe) 
     { 
      // Set state 
      ::glDisable(GL_LIGHTING); 
      ::glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
      ::glEnable(GL_POLYGON_OFFSET_LINE); 
      ::glPolygonOffset(m_PolygonOffset,-1.0f); 
    
      // Draw again... 
      m_SceneGraph.glDraw(TYPE_MESh2D); 
    
      // Restore light and mode 
      ::glDisable(GL_POLYGON_OFFSET_LINE); 
      ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
      ::glEnable(GL_LIGHTING); 
     } 
    
     ::glFlush(); 
    }

    FIG. 2. You can superimpose a wireframe on a flat-rendered mesh, using a second rendering loop with the line option.

    SMOOTH SUBDIVISION

    From a given 3D mesh, how can we improve the geometric appearence on smooth models ? The Charles Loop smooth subdivision comes here to help us. Each triangle is divided in four triangles (see figure 3), and a filtering function permits the mesh to be smoothed. The command is easy-to-use in the document, and I let you discover the details in the mesh's code.
    <img SRC="wrl_viewer/wrl_viewer3.jpg" height=191 width=600>
    FIG.3. The one-to-four triangle subdivision scheme used by method.
    <font color="#006600">//*********************************************** 
    // Smooth subdivision 
    </font><font color="#009900">//***********************************************</font> 
    void CMeshDoc::OnMeshLoop() 
    { 
     BeginWaitCursor(); 
     int NbObject = m_SceneGraph.NbObject(); 
     for(int i=0;i<NbObject;i++) 
     { 
       CObject3d *pObject3d = m_SceneGraph[i]; 
       if(pObject3d->GetType() == TYPE_MESh2D) 
      { 
       CMesh2d *pMesh  = (CMesh2d *)pObject3d; 
       pMesh->SubdivisionLoop(); 
      } 
     } 
     UpdateAllViews(NULL); 
     EndWaitCursor(); 
    }

    FIG.4. Two successives iterations of one-to-four subdivision scheme.

    FIG.5. See the visual enhancement obtained by a smooth subdivsion scheme..
     

    MOUSE INTERACTION

    A few variables and commands inserted in the view permit mouse interaction.
    <font color="#009900">//*********************************************** 
    // Left button -> x/y translation 
    //*********************************************** 
    </font>void CMeshView::OnLButtonDown(UINT nFlags, CPoint point) 
    { 
     m_LeftButtonDown = TRUE; 
     m_LeftDownPos = point; 
     SetCapture(); 
     CView::OnLButtonDown(nFlags, point); 
    } 
    void CMeshView::OnLButtonUp(UINT nFlags, CPoint point) 
    { 
     m_RightButtonDown = FALSE; 
     m_LeftButtonDown = FALSE; 
     ReleaseCapture(); 
     CView::OnLButtonUp(nFlags, point); 
    } 
    
    <font color="#009900">//*********************************************** 
    // Right button : z translation 
    //*********************************************** 
    </font>void CMeshView::OnRButtonDown(UINT nFlags, CPoint point) 
    { 
     m_RightButtonDown = TRUE; 
     m_RightDownPos = point; 
     SetCapture(); 
     CView::OnRButtonDown(nFlags, point); 
    } 
    void CMeshView::OnRButtonUp(UINT nFlags, CPoint point) 
    { 
     m_RightButtonDown = FALSE; 
     m_LeftButtonDown = FALSE; 
     ReleaseCapture(); 
     CView::OnRButtonUp(nFlags, point); 
    } 
    
    <font color="#009900">//*********************************************** 
    // Mouse move 
    // Both : rotation 
    // Left : x / y translation 
    // Right : z translation 
    //*********************************************** 
    </font>void CMeshView::OnMouseMove(UINT nFlags, CPoint point) 
    { 
     // Both : rotation 
     if(m_LeftButtonDown && m_RightButtonDown) 
     { 
      if(m_xyRotation) 
      { 
       m_yRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation; 
       m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation; 
      } 
      else 
      { 
       m_zRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation; 
       m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation; 
      } 
      m_LeftDownPos = point; 
      m_RightDownPos = point; 
      InvalidateRect(NULL,FALSE); 
     } 
    
     else 
    
     // Left : x / y translation 
     if(m_LeftButtonDown) 
     { 
      m_xTranslation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedTranslation; 
      m_yTranslation += (float)(m_LeftDownPos.y - point.y) * m_SpeedTranslation; 
      m_LeftDownPos = point; 
      InvalidateRect(NULL,FALSE); 
     } 
    
     else 
    
     // Right : z translation 
     if(m_RightButtonDown) 
     { 
      m_zTranslation += (float)(m_RightDownPos.y - point.y) * m_SpeedTranslation; 
      m_RightDownPos = point; 
      InvalidateRect(NULL,FALSE); 
     } 
    
     CView::OnMouseMove(nFlags, point); 
    }

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    Share

    About the Author

    Pierre Alliez

    France France
    No Biography provided

    Comments and Discussions

     
    GeneralMy vote of 5 Pin
    Sergey Chepurin22-May-12 4:04
    memberSergey Chepurin22-May-12 4:04 
    GeneralThank you Pin
    Darryl Bryk7-Jan-11 10:05
    memberDarryl Bryk7-Jan-11 10:05 
    GeneralSolidWorks VRML files Pin
    DerrekCurtis2-Aug-10 10:03
    memberDerrekCurtis2-Aug-10 10:03 
    GeneralI can complie the code without error, but the graphic is NOT draw on the screen. Pin
    kamanwu19-Oct-09 9:48
    memberkamanwu19-Oct-09 9:48 
    Generalthank you Pin
    woshisiguigui9-Jul-09 5:22
    memberwoshisiguigui9-Jul-09 5:22 
    Smile | :) your code is very useful.
    Questionmouse interaction.. how to make each obkect "clickable" (or selectable)? Pin
    mimosa24-Jun-08 10:20
    membermimosa24-Jun-08 10:20 
    Generalunable to render other .wrl files Pin
    Rajani Kamath29-Apr-08 0:13
    memberRajani Kamath29-Apr-08 0:13 
    AnswerRe: unable to render other .wrl files Pin
    chaoguodong25-Jun-12 23:41
    memberchaoguodong25-Jun-12 23:41 
    GeneralWont compile in VisStudio 2005 Pin
    Member 460001413-Mar-08 15:31
    memberMember 460001413-Mar-08 15:31 
    AnswerRe: Wont compile in VisStudio 2005 Pin
    CDO18-Mar-08 23:35
    memberCDO18-Mar-08 23:35 
    Generalupdating surface Pin
    Olaf Petersen25-Oct-07 4:43
    memberOlaf Petersen25-Oct-07 4:43 
    Questionhow's that supposed to work? Pin
    Quarkette20-Aug-07 9:19
    memberQuarkette20-Aug-07 9:19 
    AnswerRe: how's that supposed to work? Pin
    DucThanh8-Oct-07 21:49
    memberDucThanh8-Oct-07 21:49 
    GeneralChange Alpha Value Pin
    Digvijay Gupta26-May-07 0:16
    memberDigvijay Gupta26-May-07 0:16 
    Generalthank you! Pin
    kru_pl9-Jan-07 2:13
    memberkru_pl9-Jan-07 2:13 
    Questioncan not draw Pin
    dapson.dps7-Sep-06 23:27
    memberdapson.dps7-Sep-06 23:27 
    GeneralSome suggest Pin
    Papyna11-Mar-06 21:09
    memberPapyna11-Mar-06 21:09 
    Generalnothing happens when i upload .wrl in openGL Pin
    vijethas20-Nov-05 14:09
    membervijethas20-Nov-05 14:09 
    GeneralThanks Pin
    coder@coder.gr6-Apr-05 10:42
    membercoder@coder.gr6-Apr-05 10:42 
    QuestionSpecifying a texture image onto the mesh surface? Pin
    TBiker24-Feb-05 12:33
    memberTBiker24-Feb-05 12:33 
    Generalwow Pin
    Yves5-Oct-04 18:38
    memberYves5-Oct-04 18:38 
    QuestionHow to save GDI+ bmp file as PDF File Format. Pin
    pubba13-Jul-04 21:03
    susspubba13-Jul-04 21:03 
    AnswerRe: How to save GDI+ bmp file as PDF File Format. Pin
    azonenberg4-Mar-08 5:09
    memberazonenberg4-Mar-08 5:09 
    Questionhow to display following files using opengl and mfc? Pin
    buaa200310-May-04 16:39
    memberbuaa200310-May-04 16:39 
    QuestionHow to run 2 different(or same) OpenGL objects in one DialogBox? Pin
    werter13-May-04 22:09
    memberwerter13-May-04 22:09 
    Generalproblem of runing the program Pin
    freeman1825-Mar-04 18:22
    memberfreeman1825-Mar-04 18:22 
    QuestionReverse sub-division? Pin
    GernotFrisch4-Nov-03 11:01
    sussGernotFrisch4-Nov-03 11:01 
    General4x4 Matrix Pin
    macmac388-Oct-03 11:13
    membermacmac388-Oct-03 11:13 
    GeneralRe: 4x4 Matrix Pin
    pxp13-Feb-05 1:28
    memberpxp13-Feb-05 1:28 
    GeneralMemory allocation error Pin
    Frontman2-Oct-03 6:44
    memberFrontman2-Oct-03 6:44 
    GeneralOpengl Color and select Pin
    mcalves@coc.ufrj.br7-Apr-03 7:07
    membermcalves@coc.ufrj.br7-Apr-03 7:07 
    GeneralRe: Opengl Color and select Pin
    differ121-May-03 19:25
    memberdiffer121-May-03 19:25 
    GeneralRe: Opengl Color and select Pin
    mcalves@coc.ufrj.br22-May-03 3:26
    membermcalves@coc.ufrj.br22-May-03 3:26 
    GeneralRe: Opengl Color and select Pin
    differ122-May-03 18:12
    memberdiffer122-May-03 18:12 
    GeneralBad to da bone Pin
    Jeffrey Dutschke3-Apr-03 20:53
    memberJeffrey Dutschke3-Apr-03 20:53 
    GeneralNothing show if i load other .wrl files Pin
    Man6-Nov-01 1:15
    memberMan6-Nov-01 1:15 
    GeneralRe: Nothing show if i load other .wrl files Pin
    mattie10-Dec-01 11:49
    membermattie10-Dec-01 11:49 
    GeneralRe: Nothing show if i load other .wrl files Pin
    Anonymous10-Oct-02 22:45
    sussAnonymous10-Oct-02 22:45 
    GeneralRe: Nothing show if i load other .wrl files Pin
    Anonymous3-Apr-02 0:44
    memberAnonymous3-Apr-02 0:44 
    GeneralRe: Nothing show if i load other .wrl files Pin
    powerdigital29-May-02 18:55
    memberpowerdigital29-May-02 18:55 
    GeneralRe: Nothing show if i load other .wrl files Pin
    Anonymous31-May-02 1:38
    memberAnonymous31-May-02 1:38 
    GeneralRe: Nothing show if i load other .wrl files Pin
    Anonymous24-Jul-02 5:26
    sussAnonymous24-Jul-02 5:26 
    GeneralRe: Nothing show if i load other .wrl files Pin
    John Ulvr15-Nov-06 16:09
    memberJohn Ulvr15-Nov-06 16:09 
    GeneralRe: Nothing show if i load other .wrl files Pin
    garaber9-Mar-05 7:39
    membergaraber9-Mar-05 7:39 
    GeneralRe: Nothing show if i load other .wrl files Pin
    Huy Le Xuan20-Feb-06 0:44
    memberHuy Le Xuan20-Feb-06 0:44 
    GeneralRe: Nothing show if i load other .wrl files Pin
    scupid1-Mar-06 19:49
    memberscupid1-Mar-06 19:49 
    GeneralRe: Nothing show if i load other .wrl files Pin
    zhodj14-Nov-11 22:47
    memberzhodj14-Nov-11 22:47 
    GeneralCrashes on vertex/line/face changes Pin
    Jason Douglas6-Jul-01 9:47
    memberJason Douglas6-Jul-01 9:47 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Terms of Use | Mobile
    Web03 | 2.8.150520.1 | Last Updated 1 Dec 1999
    Article Copyright 1999 by Pierre Alliez
    Everything else Copyright © CodeProject, 1999-2015
    Layout: fixed | fluid