Avogadro: New Ring & Polygon Engines
I recently added a couple of new engines to Avogadro and the screen shot below shows them both. The ring engine finds all the rings of the molecule and draws a transparent plane through the ring. The polygon engine finds atomic centres with three or more atoms bonded and draws a polygon around that atom. This is only done for atoms that are not the common organic types.

I think these are useful engines that have been prompted by user requests. May be not as exciting as the ribbon engine or the surface support we are working on but useful to display certain structures. The ring engine has not been without its problems though as you can probably spot in the image below showing the ring engine rendering a carbon nanotube.

The lighting just flips at certain points - the same happens as you rotate molecules that are using the ring or polygon engine. I guess the lighting is flicking on at certain angles. I would be interested if anyone with more OpenGL knowledge than I might know how I can improve the rendering. Some rings are near white and some of the back rings don't seem to be drawn - that could actually be drawing order though which is always tough to get right.
Comments and tips are always welcome. The big challenge right now is getting surface support added in. This is something I think we really need and I would use in my daily work as I am sure many others would. I have been reading up on marching cubes and stuff but would welcome tips in that area too!
Comments
Display comments as Linear | Threaded
ephemient on :
Benoit Jacob on :
I think we have two separate issues there. One with the z-buffer preventing certain polygons from being drawn at all, and one with wrong normal vectors causing the lighting to "flip at certain points" because a normal vector is the opposite of what it should be.
Since you have transparent objects that can be seen from either side, you probably have to draw them twice with two different (opposite) normal vectors.
I wanted to say more but I'm in a hurry to leave -- also I admit it's a nontrivial issue!
Good luck,
Benoit
ephemient on :
(a) The depth buffer might be occluding some of the transparent polygons. The correct order of operations is:
1. Draw opaque objects with depth buffer enabled, because it's easier that way.
2. Draw transparent objects with depth testing enabled, but without writing to the depth buffer. This allows the opaque objects to correctly occlude the transparent objects, but makes the transparent objects blend instead of occluding each other.
3. Because the depth buffer is not being used, you need to do painter's algorithm yourself, drawing the furthest transparent objects first. Yes, this is a huge pain! But OpenGL's alpha blending comes out with incorrect results if you don't do this. Consider a red polygon and a blue polygon, both with alpha 0.5, overlaying each other: if red is drawn first, the final color is [0.5,0,1]; if blue is drawn first, the final color is [1,0.0.5].
(b) If a polygon is facing away from a light, the normal is facing the wrong way relative to what you want, and this can give you messed up shading.
Looking at the screenshot in more detail, I'm pretty sure you're suffering from (a), I'm not so sure about (b).
Marcus D. Hanwell on :
Now the normal flipping seems a tougher problem to solve. It is apparent in the bottom right of the nanotube. The algorithm has to work across all molecules - not just this one. I can fix that example by working out the centre of the nanotube but this breaks many other flat molecules in this sense. I am not sure on the best fix.
I think with transparent rings I will have to do depth sorting to get it right. When opaque I could switch that off.
ephemient on :
Normals can be trivially fixed by using
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
(it incurs a performance penalty, but it's easy).
I was guessing that the depth-buffer was responsible for the lack of polygons in the back of the tube, by the upper-left and lower-right of the screenshot. That is easy to handle.
glDepthMask(GL_TRUE);
// draw opaque
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
// draw transparent
Sorting is a gigantic pain. However, with these simple grays, you could get away without anybody noticing it.
Marcus D. Hanwell on :
I didn't think the two pass rendering in that way would work. I will give it a try. Thanks for the tips - I will see what I can do. I always appreciate input - feel free to checkout the code and tell me where I screwed up too
Marcus D. Hanwell on :
glDepthMask(GL_TRUE);
// draw opaque
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
// draw transparent
That won't work in this case as far as I see and we are effectively doing that already. All of the rings are transparent and the only way to get proper blending would be to depth sort I think. We already draw all opaque engines before transparent ones and that works for most things.
Ray Giguere on :
http://tang.skidmore.edu/4/exhibitions/doc/2070/
http://tang.skidmore.edu/4/exhibitions/show/1771/doc/2280/