Click here to Skip to main content
Click here to Skip to main content

A small VRML viewer using OpenGL and MFC

By , 30 Nov 1999
 
  • Download files - 669 Kb
  • 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->

    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

    About the Author

    Pierre Alliez
    France France
    Member
    No Biography provided

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    Generalupdating surfacememberOlaf Petersen25 Oct '07 - 3:43 
    Hi
     
    I'm searching for a ActiveX or other Libary to draw 3d surfaces with Color from high, like you have done. I want to draw 3d Images i get from an Camera and display them with min 12Hz. Is this possible by using this aktiveX, and how shoud i do this?
     
    best greating Olaf
    Questionhow's that supposed to work?memberQuarkette20 Aug '07 - 8:19 
         for(int i=0;i<NbVertex;i++)
         {
              // Get distance to set of faces
              distance = MAX_FLOAT;
              for(int j=0;j<NbFace;j++)
              {
                   double d = ::SquareDistanceVertexToFace(pArrayVertex->GetAt(i),
                                                                                 pArrayFace->GetAt(j),&v);
                   if(d < distance)
                        distance = d;
              }
              // Get max for each vertex
            if(distance > max)
              {
                   max = distance;
                   if(ppFace != NULL && ppVertex != NULL)
                   {
                        *ppFace = pArrayFace->GetAt(j);
    // how can j be accessible here?
                        *ppVertex = pArrayVertex->GetAt(i);
                   }
              }
         }
     
    error: d:\c++\projects\wrl_viewer\lib3d\utils3d.cpp(582) : error C2065: 'j' : undeclared identifier
     

    why am i not able to compile the project?
    (using vs2005)

     
    q.
    AnswerRe: how's that supposed to work?memberDucThanh8 Oct '07 - 20:49 
    Vs2005 compiler treat the variable "j" in those lines of code as the local one which can be used within the loop "for". To fix this problem, just declare it before the loop:
     
    // Get distance to set of faces
    distance = MAX_FLOAT;
    int j=0;
    for(j=0;jNguyen Duc Thanh
    GeneralChange Alpha ValuememberDigvijay Gupta25 May '07 - 23:16 
    I am implementing Transparency in Mesh Viewer. For that i have to change Alpha value. But when i change alpha value OF CCOLOR Class it hardly makes any difference. In that class Only m_Green,m_Red & m_Blue value been set.Even i m confused how thesse colors are transfered to OpenGl libraries or mesh.
     
    If anybody have any idea on this PLEASE help me.
     
    Thanks & Regards
    Digvijay Gupta
    Research Engineer

    Generalthank you!memberkru_pl9 Jan '07 - 1:13 
    neat, tidy, beautiful
     
    thank you for your effort in writing the article!
    very usefull
     
    cheers
     
    kru
    Questioncan not drawmemberdapson.dps7 Sep '06 - 22:27 
    i use IndexFaceSet format wrl file for test.
    when i debug it,i got the following erros:
    Face [4b8caf0] has the same vertices
    Face [4b8e770] has invalid reciproc. neighboring
    Face [4b90d70] has invalid reciproc. neighboring
    ok
    Calculate normal per vertex (522 faces, 261 vertices)...ok
    Build list.ok
    CMesh3d::Draw : unable to draw list 1
    The thread 'Win32 Thread' (0xadc) has exited with code 0 (0x0).
    The thread 'Win32 Thread' (0xb9c) has exited with code 0 (0x0).
    The thread 'Win32 Thread' (0xa34) has exited with code 0 (0x0).
     
    can you give any help? thanks! daipeishan@163.com
    GeneralSome suggestmemberPapyna11 Mar '06 - 20:09 
    First Of all, admire your program Smile | :)
     
    I suggets you changed the gl_Vertex to to glEnableClientState,it will takes less time on calling-driver to draw vertexs

    Generalnothing happens when i upload .wrl in openGLmembervijethas20 Nov '05 - 13:09 
    Hey,
    I have a VRML 2.0 file where i am giving the object a scale, and sound. when i run it in cosmo player it works perfectly, just the way i want it but when i run it in openGL, only the graphic is showing up. It doesn't play the sound and the scale doen'st work.Is there any way to make it work? am i missing any include file??
     
    In the code file, i have
    gstSeparator *rootSep;
    gstSeparator *vrmlSep = new gstSeparator();
    vrmlSep = gstReadVRMLFile("heart2.wrl");
     
    won't the other things that i have in VRML file work? This is partially what i have in my VRML file.
     
    DEF CLOCK TimeSensor {
    cycleInterval 1.0
    loop TRUE
    }
    DEF heartSIZE PositionInterpolator {
    key [ 0.0, 0.2, 0.65, 1.0 ]
    keyValue [ 1.0 1.0 1.0,
    1.5 1.5 1.5,
    1.1 1.1 1.1,
    1.0 1.0 1.0, ]
    }
    Sound{
    Sound DEF Mysound AudioClip{
    url [ "heartbeat3.wav"
    "http://www.a1freesoundeffects.com/popular1/heartbeat2.wav" ]
    }
    }
    ]
    }
    ROUTE CLOCK.fraction_changed TO heartSIZE.set_fraction
    ROUTE heartSIZE.value_changed TO heartTransform.set_scale
    ROUTE CLOCK.value_changed TO Mysound .set_scale
     
    Please help me.
    Thank you

    GeneralThanksmembercoder@coder.gr6 Apr '05 - 9:42 
    Awesome code thank you for sharing it with the rest of us
    QuestionSpecifying a texture image onto the mesh surface?memberTBiker24 Feb '05 - 11:33 
    Great work!
     
    Is there any demo that shows a texture image mapped to a surface and displayed with this project? For example, I want to map an arbitrary image onto the mountain surface dataset. How is that done?
    GeneralwowmemberYves5 Oct '04 - 17:38 
    Very, very, very interesting.
    QuestionHow to save GDI+ bmp file as PDF File Format.susspubba13 Jul '04 - 20:03 
    Hi everybody,
    I want to export GDI+ bmp files as PDF File format.
    I have created GDI+ bmp Objects like this.
    Bitmap bmp7(L"myImage.jpg");
     
    Now I want to save this bmp7 Object as PDF File format. u please help me if any one know this.Frown | :(
    Thanks.
    AnswerRe: How to save GDI+ bmp file as PDF File Format.memberazonenberg4 Mar '08 - 4:09 
    On way to do this is to get a PDF virtual printer, and print the bitmap to the printer. You could also try to find a PDF-generation library somewhere.
     
    Off the top of my head, the first is likely to be a bit easier for testing but the second is preferred for production apps.
    Questionhow to display following files using opengl and mfc?memberbuaa200310 May '04 - 15:39 
    IGES(*.igs),Neutral(*.neu),STEP(*.stp),STL(*.stl),Inventor(*.iv),
    WaveFront(*.obj),Render(*.slp),ACIS File(*.sat),Assembly(*.asm).
    Please give me some examples like the above "A small VRML viewer",thank you very much!
    QuestionHow to run 2 different(or same) OpenGL objects in one DialogBox?memberwerter13 May '04 - 21:09 

    How to run 2 different(or same) OpenGL objects in one DialogBox?
    IDC_STATIC1 is a first OpenGL objects Scene window.
    IDC_STATIC2 is a second OpenGL objects Scene window.
    IDC_STATIC1 and IDC_STATIC2 ,they are placed on IDD_DIALOG1.
     
    code:
    pclStatic = (CStatic *)GetDlgItem(IDC_OpenGL_Window);
    pclGlView = new CGlView(pclStatic);
    pclGlView->OnCreate();
    pclGlView->InitGL();
    pclGlView->DrawGLScene();
     
    pclStatic1 = (CStatic *)GetDlgItem(IDC_OpenGL_Window);
    pclGlView1 = new CGlView(pclStatic1);
    pclGlView1->OnCreate();
    pclGlView1->InitGL();
    pclGlView1->DrawGLScene();
     
    Will not involve both windows (IDC_STATIC2,IDC_STATIC1)
    Generalproblem of runing the programmemberfreeman1825 Mar '04 - 17:22 
    when i load a .wrl file which attached with the program, the program will hand, why this problem exit?
    QuestionReverse sub-division?sussGernotFrisch4 Nov '03 - 10:01 
    Er, nice, but my files have way to much triangles. Is there any way of un-subdividing them and make them still look good?
     
    Thank you,
    Gernot
    General4x4 Matrixmembermacmac388 Oct '03 - 10:13 
    Hi all,
     
    i found this article because i looked for a 4x4 matrix class. I ve started up
    with a small company this year to offer some 3d laserscan services.
     
    What i am looking for is some code to registrate the data from my scanner which comes in a x,y,z points coordinates ascii-file format. To registrate a number of scans i like to transform these x,y,z coordinates with a 4x4 (translation-rotation) matrix.
     
    If someone can help me with code, sources etc. please contact me.
     
    If someone like to program this for me i can also donate some money for that.

     
    Thanks, Mark
    GeneralRe: 4x4 Matrixmemberpxp13 Feb '05 - 0:28 
    Hi Mark,
     
    i was wondering if your search regarding point-coordinates transformation came up with some interesting stuff?
     
    Looking for the same myself. Something like a 'best-fit' or 'least-squares' algorithm would be needed there.
     
    Thank,
     
    Jan
    GeneralMemory allocation errormemberFrontman2 Oct '03 - 5:44 
    There is
    "Direct3D9: (ERROR) :Memory still allocated!"
    in output window when terminate the program.
    What's up? Who knows?
    GeneralOpengl Color and selectmembermcalves@coc.ufrj.br7 Apr '03 - 6:07 
    Confused | :confused: HI, making a program that read from a text file the nodes coordinates and element connection like finite element for instance. So i put colors to them. Another step is coloring the scalar and i use glColor for each node. OpenGl does not do a good interpolation of colors. For example if i have a node blue and the adjavent is red the interpolation is just from blue to red without pass for ywllow and others color and it's not good. I seem in this example of your that u make tha correct interpolation. How can i do it?
     
    The other doubt is: hou to select a node or element in a scene? All example that i've get in internet show how to select making a pre definie of all elements that scene contains.
    GeneralRe: Opengl Color and selectmemberdiffer121 May '03 - 18:25 
    hi,I am also concerned with your problems.Anyone who can solve them?
    And to mcalves:I hope to communicate with you.Big Grin | :-D
     
    hi,nice to meet you here!
    GeneralRe: Opengl Color and selectmembermcalves@coc.ufrj.br22 May '03 - 2:26 
    HI, now I know how to interpolate the colors. You have to use texture 1D to do it. Define a texture 1d with 8 colors for instance and. The values of scalars must be in the range 0-1. So you calculate the range of each color based in the range 0-1. That's because you have text coordinates between 0-1.
     
    Wink | ;)
    GeneralRe: Opengl Color and selectmemberdiffer122 May '03 - 17:12 
    I will try it in the way you gave,thanks a lot!
    By the way ,do you have the account of MSN,if yes,can you give it to me?
     
    hi,nice to meet you here!
    GeneralBad to da bonememberJeffrey Dutschke3 Apr '03 - 19:53 
    Poke tongue | ;-P Very interesting article. I really enjoyed it.
    Thank you!

     
    The only people who ever receive critisism are those who are actually doing something.
    GeneralNothing show if i load other .wrl filesmemberMan6 Nov '01 - 0:15 
    Hello,
    It is really an excellent source code that I have ever seen. ..But when I try to download some
    .wrl file from the website. The program show nothing(only a black screen inside). What is the
    problem? And How can I be solved? Help Please!!
     
    From student
    Man
    cmlee9@ie.cuhk.edu.hkCool | :cool:
     
    Man
    GeneralRe: Nothing show if i load other .wrl filesmembermattie10 Dec '01 - 10:49 
    same problem here
    file is 2.2meg
    GeneralRe: Nothing show if i load other .wrl filessussAnonymous10 Oct '02 - 21:45 
    maybe because of the fixed value of far plane while used in function
    gluPerspective(45,1,1,1000.0);

    GeneralRe: Nothing show if i load other .wrl filesmemberAnonymous2 Apr '02 - 23:44 
    This happens to me too.
    GeneralRe: Nothing show if i load other .wrl filesmemberpowerdigital29 May '02 - 17:55 
    me too..
    I think program is very very Exellent..
    Please Help me.Cool | :cool:
     
    Suwon Univ. Virtual Reality & Multimedia Laboratory. korea
    mik38317@orgio.net
    GeneralRe: Nothing show if i load other .wrl filesmemberAnonymous31 May '02 - 0:38 
    I got the same prob too. But only if i try to load 1.x .wrl. I got a self created fish model, WRML ver 0.97 an its shown. If i try to look at the fish created with WRML ver 1.0 i got a black screen.
    This seems to be no help, but u r not alone Smile | :)
     
    Greetings, Nils
    GeneralRe: Nothing show if i load other .wrl filessussAnonymous24 Jul '02 - 4:26 
    hey,guys.
    The program "only" support IndexFaceSet.
    In another word,this is not a complete program for general VRML files!!
    GeneralRe: Nothing show if i load other .wrl filesmemberJohn Ulvr15 Nov '06 - 15:09 
    (note: VRML files are text files) The file parser in this project relies on a line begining with the string 'DEF'. Cararra for one, does not do this... Back to the drawing board for me.
    GeneralRe: Nothing show if i load other .wrl filesmembergaraber9 Mar '05 - 6:39 
    there is a problem with parsing the coordIndex portion of the vrml data. the author has set his algorithm to work for only triangle faces. If you attempt to load any files with quad faces the application fails. There are also some other problems associated with interpreting vrml. Those of you who are hammering on the code one of the problems is in ParserVrml.cpp in CParserVrml::SizeMesh. There are other problems for a generic parser. All in all a nice article.
    GeneralRe: Nothing show if i load other .wrl filesmemberHuy Le Xuan19 Feb '06 - 23:44 
    Please see this line: # Produced by 3d Toolbox 1.0 (Pierre Alliez, CNET / DIH / HDM)
     
    May be, these VRML files ware created by this software. Anyone had it, please send to me. Thank you so much!
     
    huylexuan@yahoo.com
    GeneralRe: Nothing show if i load other .wrl filesmemberscupid1 Mar '06 - 18:49 
    Something must be hard coded.
    GeneralRe: Nothing show if i load other .wrl filesmemberzhodj14 Nov '11 - 21:47 
    Hi,I thank the source code cannot load other .wrl files if you donot change the source code.
    GeneralCrashes on vertex/line/face changesmemberJason Douglas6 Jul '01 - 8:47 
    Not sure why, but when I attempt to switch from face to vertex or line, the app crashes.
     
    Thanks,
    Jason

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

    Permalink | Advertise | Privacy | Mobile
    Web01 | 2.6.130516.1 | Last Updated 1 Dec 1999
    Article Copyright 1999 by Pierre Alliez
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid