SceneGraph and Serialization

Apr 25, 2012 at 3:55 AM

Are there any plans to improve the SceneGraph classes to support materials and/or textures assigned against elements? Will the Serialization classes support loading associated materials and textures?  For my own use, I've made some enhancements in my copy of the source code in order to handle very basic read of materials from OBJ/MTL files, and for rendering polygons with that material info.  I'd be happy to share it, but there might be no value in doing so if the roadmap involves a more comprehensive solution in the not-too-distant future.

Coordinator
Apr 25, 2012 at 9:42 AM

Hi Sean,

There are indeed plans for this - it would be great if you could share what you've done and I can incorporate it. The idea is that materials and textures are Assets, which will be stored in the scene, and that objects can have references to assets.

Do you think you could provide an overview of your changes?

Apr 26, 2012 at 12:45 AM

As I just said in another reply, I'll send you what I've got later this evening.  A brief summary is below.  Most of the code I added was in the ObjFileFormat classes.  Where I say that I've "modified Render to support materials" all that means is that I've gone adding a few lines like below to the Render method:

            // Set the material.
            if (Material != null)
                Material.Bind(gl);

 

SharpGL libraries

SharpGL.SceneGraph.Assets.Material (modified to only bind non-null Texture, in case it has been set to null)
SharpGL.SceneGraph.Core.IHasMaterial (created interface per your other message)
SharpGL.SceneGraph.Face (implemented IHasMaterial to permit per-face material differences)
SharpGL.SceneGraph.Primitives.Polygon (implemented IHasMaterial, modified Render to support materials)
SharpGL.SceneGraph.Primities.Teapot (implemented IHasMaterial, modified Render to support materials)
SharpGL.SceneGraph.Quadrics.Quadric (implemented IHasMaterial, modified Render to support materials)
SharpGL.Serialization (added reference to SharpGL to permit invocation of Texture.Create)
SharpGL.Serialization.Wavefront.ObjFileFormat (added support for reading materials)

SharpGL samples

PolygonLoadingSample.FormPolygonLoadingSample
1. Provided menu options for switching rendering modes (line, filled, lighted/filled)
2. Enabled rendering of materials.
3. Provided menu option for clearing loaded polygons

Coordinator
Apr 26, 2012 at 2:32 PM

Hi Sean,

I've incorporated these changes into the current code with a few tweaks:

  1. Objects don't bind their own materials - the scene graph does (for example, quadric, polygon, teapot were all calling Material.Bind. Now the scene graph does it like this:
    //  If the element has a material, push it.
                if (sceneElement is IHasMaterial && ((IHasMaterial)sceneElement).Material != null)
                    ((IHasMaterial)sceneElement).Material.Push(gl);
    
     
  2. This means that the parent of an object is responsible for setting its material - so the way you've done the per-face materials is essentially unchanged (a polygon pushes the materials on a per-face basis).
  3. Rather than 'Bind', I've extended IBindable to have 'Push' and 'Pop'. Push means set the properties, but push the attribute stack first. Pop does the opposite. Otherwise if you bind a material to an object, all subsequent objects have that same material!
  4. Everything else you've done with the sample and loader has been checked in, but I'd love your input on the IHasMaterial interface usage. So far I actually haven't been able to test it as I'm away from my main machine until later - can you send me a decent *.obj file to test with?

I'd like to move onto the serialization next and maybe improve another sample to let you do some of the cool per-face stuff :)

Apr 26, 2012 at 3:07 PM

OK, I'm uploading some example free OBJ files I found somewhere via submit a patch, because I don't have a better way to get them to you at the moment.

Apr 29, 2012 at 2:51 PM
dwmkerr wrote:

Hi Sean,

I've incorporated these changes into the current code with a few tweaks:

  1. Objects don't bind their own materials - the scene graph does (for example, quadric, polygon, teapot were all calling Material.Bind. Now the scene graph does it like this:
    //  If the element has a material, push it.
                if (sceneElement is IHasMaterial && ((IHasMaterial)sceneElement).Material != null)
                    ((IHasMaterial)sceneElement).Material.Push(gl);
    
     

What you've done seems to generally fit the OpenGL stack approach better than my approach.  One downside to applying material from within the SceneGraph is that quadrics and the teapot only get materials when rendered through the scene graph, which I think makes usage of materials dependent upon using a SceneControl rather than the OpenGLControl.  Probably not a major deal, but something to consider.

Coordinator
Apr 29, 2012 at 9:18 PM

That is a very good point - I'm going to do some work on the SceneBuilder app in the tools solution and get that set up so that I can apply materials and textures to the various objects and see how it looks after that - it may be better to consider doing this another way for the exact reason you've mentioned.