VRML2GL parser

VRML2GL parser is a programmer's tool that converts Virtual Reality Markup Language (VRML) files to OpenGL source code.

With VRML2GL you can turn VRML files into static OpenGL C code. This allows the programmer to work with the OpenGL API without worrying over models. Someone learning OpenGL can also benefit from VRML2GL as it is always easier to learn something new when that something is less. Learning OpenGL is less when you use VRML2GL because it frees you from the question; I wonder if my model is working right?

What does VRML2GL not do?
VRML2GL only does VRML v1.0 files. The following VRML v1.0 nodes (tags) are not implemented: Also VRML files that have non-simple polygons are supported (undefined results).
 * AsciiText, FontStyle, Info, LOD, WWWAcnhor and WWWInline.

NOTE: that these restrictions are reasonable considering this tool was not meant to create final models. Although the models produced are accurate and reasonably fast, there are much optimization that could be done (see Optimizations). This tool was made to be paste only two lines of code into yours.

What does VRML2GL do?
VRML2GL does all other nodes for VRML v1.0. It is hoped that you will be able to simply run the parser and add two lines to your OpenGL code to get the model up and going. The parse even supports texture mapping. Note that texture mapping primitives is best as it doesn't require texture coordinates.

VRML2GL Configuration File
VRML2GL uses a configuration file to set some user switches. The file must be called VRML2GL.cfg. The file is simply a text file that you can edit. The config file also must be in the working directory. The VRML2gl profile uses the same rules as VRML. An explanation of the profile is as follows:  FUNC_PREFIX      SFString    # Names functions 'void X29( void );'. FILE_PREFIX      SFString    # Names files 'X29.c'.

SEPARATOR        SFBool      # TRUE -> 'Separator' is unchanged. # FALSE -> 'Separator' = 'SeparatorTransform'. Treat 'Separator' AS 'TransformSeparator'. This was added as I felt that many objects only really need (and maybe mean) to save position. With 'Separator' the parser must save whole meshes and many lists. This is huge over head that cause the parser to slow down and the source code produced to be slightly larger.

LIGHTS_OFF       SFBool      # TRUE -> lights get shut off after 'Separator'. # FALSE -> lights remain on once turned on. IGNORE_LIGHTS    SFBool      # TRUE -> all light nodes are ignored. # FALSE -> generate lights in the source code. GL_COLOR         SFBool      # TRUE -> use glColorMaterial; and glColor3f;. # FALSE -> use regular mglMaterialfv; calls. BUILD            SFEnum      # STATIC -> plot commands as received. # LOOP -> use loops and arrays to build objects. Loop or static building of meshes. Have an array of vertices and use a loop to plot the mesh (LOOP) or use many vertex3f; calls (STATIC). Actually you can set the parser to both (LOOP only for meshes                             with more than x vertices).

MIN_LOOP         SFLong      # This is the minimum size mesh to LOOP. PRECISION        SFLong      # Number of digits to the right of the decimal place.

AMBIENT          SFBool      # FALSE -> ignore ambient materials. DIFFUSE          SFBool      # FALSE -> ignore diffuse materials. SPECULAR         SFBool      # FALSE -> ignore specular materials. EMISSIVE         SFBool      # FALSE -> ignore emissive materials. TRANSPARENCY     SFBool      # FALSE -> ignore transparency materials. SHININESS        SFBool      # FALSE -> ignore shininess materials. Ignore one or more material types. This is useful as                             I have found that the SHININESS is usually too low. Also if you use glColorMaterial; and the DIFFUSE is different from AMBIENT then you will get two glColor3f; because the parser thinks its a new color. In order to get around this you can ignore either DIFFUSE or AMBIENT.  Example: given a popular VRML file such as X29.WRL vrml2gl x29.wrl Produces: vglObjX29.h      - these are the main source and header files that call vglObjX29.c        the rest of the source files. vglObjCanard.c   - Note that each function is stand alone. This allows vglObjCockpit.c    you to extract parts from scenes. vglObjMfuse.c vglObjNose.c vglObjRfuse.c vglObjVane.c vglObjVertstab.c vglObjWings.c To use the new mesh you include the header file 'vglObjX29.h' and call the function 'vglDrawX29;'. It is up to the user to set the makefile and make sure any platform specific includes or defines are set. NOTE: you must build the default 'glObjects.c' or supply your own in order to support drawing of primitives. The functions used are as follows: void glObjCube( float width, float height, float depth, int parts ); void glObjCylinder( float radius, float height, int parts ); void glObjCone( float radius, float height, int parts ); void glObjSphere( float radius, int parts );

Trouble Shooting:
1) Nothing shows up. This is most likely a focus problem. Look on my web page for a 'aux' framework that allows you to try many things out.

2) Source generated is too big and won't compile. See Optimizations.

3) Materials don't seem to work. Some materials won't work for LOOP building simply because the code is more trouble than it's worth. Use STATIC build.

4) The VRML file might have non-simply polygons.

5) Trace through to see if you have glFrontFace set right. If this is set to GL_CW then you should reset it to GL_CCW when all clockwise meshes are finished.

6) Turn up the shininess factor in the source VRML file. It seems that this is always too low for my taste.

7) Are the Lights on? Use my function in the 'glObj.h' file to set the light position.

glObjSetLight( 0,                  /* Light number.               */                  GL_FALSE,            /* Show lamp. Could be better. */                  GL_TRUE,             /* Is positional.              */                  0.0, 0.0, 0.0 );     /* Vector position. */

Optimizations:
1) Create a display list for the main 'vglDraw' function when your program starts up. The just call the display list in your paint routine. The reason I chose not to use display lists is because I think it assumes too much. I found it to best to brake parts into functions (stand-alone functions) and let you put the display lists in where you feel.

2) Remove empty functions. Functions like SceneInfo are usually empty. I guess I could have made sure that functions that are empty get parsed but I felt this was overkill (insert cop out here).

3) Play with the MIN_LOOP value. This STATIC to LOOP cut off can really reduce code size. Some files over use 'Separator' for small meshes. Note that the file 'bop.wrl' is responsible for that feature.

4) If the code generate is too big to be compiled, then you can take the source VRML file and do some find and replaces. Look for any 'Seperator' nodes. For each 'Seperator' node (or the big ones) you want to change them to read 'DEF x Seperator' where 'x' will be the object name (bop_1, bop_2, bop_3). What this will do is brake the mesh up into different files, as a new source file is only created for 'DEF' nodes. This problem is because the object has parts that were not named when create (or lost in some conversion).

5) Parse out some of the material that are redundant or not desired.

6) Try and remove some precision using the PRECISION value in the VRML2GL.cfg. Note that this could really ruin the model.

7) Remove some variable declarations that are not used and maybe redo the main variable declarations to suit your program.

8) If normal binding is PER_x_INDEXED then change the normal binding to PER_FACE to force the parser to generate normals via a function call. This makes the code way smaller but most likely not as nice looking as the original normals provided are for smooth shading.