Display lists and quadrics

Hi,

I haven't programmed in OpenGL in a while, but I do remember the basics of creating display lists and quadrics. I've tried to use them using .NET calls and they're not working. Are they built yet? If they are, could someone provide an example (e.g. a call to GLu.Cylinder or something)?

Kyle


Comments

Re: Display lists and quadrics
posted by the Fiddler

The code has been built, but it's untested.

What doesn't work? Is there an error message? Can you upload a small test case?

I'm just not sure how to call the function properly - what does the first argument (quad) do?

Re: Display lists and quadrics
posted by the Fiddler

The first parameter is a handle to a quadric object, which you generate with Glu.NewQuadric.

Edit: Check this tutorial on quadrics. It's for java, but the syntax is easy to translate.

Re: Display lists and quadrics
posted by Technolithic

I'm having the same issue with this.
Glu.QuadraticDrawStyle(int quad, QuadricDrawStyle.Fill)

The first parameter appears to accept an integer.
I'm running OpenTK 0.9.0 with C# on Visual Studio and it's setup to do auto-lookup so it provides me with a list of all method and property declarations as I type.

How does a handle to an object work, if it's an integer?
Can someone provide an example (or a link) using C# and OpenTK?

Just to see if it would work anyhow, I compiled and ran the code, but the Glu.GluQuadric object I used for the 1st parameter caused a runtime failure.

Re: Display lists and quadrics
posted by Inertia

Seems you are right, Glu.NewQuadric should return IntPtr rather than int. Glu is not very flexible when it comes to parameters (topology and texcoords), so it's way better to either generate geometry by a custom function or import it from a modelling application. However that answer isn't helping right away, so here's a quick port of pascal code to tesselate a sphere to C# (didn't test extensively, but the code does output a sphere so I guess the port is ok )

 public void DrawSphere( Vector3 Center, float Radius, uint Precision )
        {
            if ( Radius < 0f )
                Radius = -Radius;
            if ( Radius == 0f )
                throw new DivideByZeroException( "DrawSphere: Radius cannot be 0f." );
            if ( Precision == 0 )
                throw new DivideByZeroException( "DrawSphere: Precision of 8 or greater is required." );

            const float HalfPI = (float) ( Math.PI * 0.5 );
            float OneThroughPrecision = 1.0f / Precision;
            float TwoPIThroughPrecision = (float) ( Math.PI * 2.0 * OneThroughPrecision);

            float theta1, theta2, theta3;
            Vector3 Normal, Position;

            for ( uint j = 0 ; j < Precision / 2 ; j++ )
            {
                theta1 = ( j * TwoPIThroughPrecision ) - HalfPI;
                theta2 = ( ( j + 1 ) * TwoPIThroughPrecision ) - HalfPI;

                GL.Begin( BeginMode.TriangleStrip );
                for ( uint i = 0 ; i <= Precision ; i++ )
                {
                    theta3 = i * TwoPIThroughPrecision;

                    Normal.X = (float) ( Math.Cos( theta2 ) * Math.Cos( theta3 ) );
                    Normal.Y = (float) Math.Sin( theta2 );
                    Normal.Z = (float) ( Math.Cos( theta2 ) * Math.Sin( theta3 ) );
                    Position.X = Center.X + Radius * Normal.X;
                    Position.Y = Center.Y + Radius * Normal.Y;
                    Position.Z = Center.Z + Radius * Normal.Z;

                    GL.Normal3( Normal );
                    GL.TexCoord2( i * OneThroughPrecision, 2.0f * ( j + 1 ) * OneThroughPrecision );
                    GL.Vertex3( Position );

                    Normal.X = (float) ( Math.Cos( theta1 ) * Math.Cos( theta3 ) );
                    Normal.Y = (float) Math.Sin( theta1 );
                    Normal.Z = (float) ( Math.Cos( theta1 ) * Math.Sin( theta3 ) );
                    Position.X = Center.X + Radius * Normal.X;
                    Position.Y = Center.Y + Radius * Normal.Y;
                    Position.Z = Center.Z + Radius * Normal.Z;

                    GL.Normal3( Normal );
                    GL.TexCoord2( i * OneThroughPrecision, 2.0f * j * OneThroughPrecision );
                    GL.Vertex3( Position );
                }
                GL.End( );
            }
        }

Re: Display lists and quadrics
posted by Technolithic

Thanks, Inertia, the spheres function works nicely. I just need to figure out how to change their colors and model them without showing the occasional facing artifacts where it appears to inversely texturize the spheres, leaving a funny effect when rotating.

Re: Display lists and quadrics
posted by Technolithic

OK, to get rid of the facing artifacts, I enabled face culling using: GL.Enable(EnableCap.CullFace).
Now my project renders those spheres without goofing it up and they look great!

Thanks again, Inertia.

Re: Display lists and quadrics
posted by the Fiddler

Hm, the typemap correctly maps QuadricObj to IntPtr - the int parameter looks like a bug in the generator.

I'll see into that, however I do think that using code like the above is better (more flexible, possibly faster) than using Glu quadrics.

Re: Display lists and quadrics
posted by Technolithic

I think the OpenTK call lists are a bit faulty still, unless they can't be used for lighting. It seems that the first time I call the list for the default lighting on a sphere object, it works fine, but when my program changes the CallList value to use a different color matrix for particular spheres it goes crazy and does them all the same color. When I remove the call to GL.CallList and go back to setting each lighting matrix manually, it works fine; albeit probably less efficient than it could be.

Anyhow, I can get by with doing it this way for a while. Just letting you know there's probably an issue with GL.CallList() as well.

Re: Display lists and quadrics
posted by Technolithic

I'd like to add that I'm using GL.CallList() to display tons of spheres and it seems to work ok for that... for now. I'm only using 1 object, spheres, in the list. I'll have to create other objects as well. I'm sure I'll find out if there's a problem after I generate the code for the graphics to represent the other objects on screen.

Re: Display lists and quadrics
posted by Technolithic

In reply to Fiddler's last post, would incorporating the use of CallLists with Quadrics create code of equivalent efficiency if every call to render an object was contained in the call list or does using Quadrics create more complexities underneath that impose slower processing?

Re: Display lists and quadrics
posted by the Fiddler

It depends on the implementation of GLU, and on how efficient the drivers are in optimizing display lists. You'd have to profile a range of different implementations before drawing any safe conclusions.

Regarding GL.CallLists(), OpenTK simply passes the values to the underlying implementation. Unlike quadrics, this is well tested code. I suspect the problem with lighting does not lie there - if you can provide a test case, we'll be able to find the cause and fix it.

Re: Display lists and quadrics
posted by Technolithic

I'll have to come up with a simpler test-case than the project I'm working on... the CallList-generating code is rather intermingled into the source and the project is not OpenSource. I'll put this on my to-do list. It'll be good to do something to help out with the development of this cool framework.

Re: Display lists and quadrics
posted by Inertia

You're welcome, that function was part of a solar system simulation written to get a grip on Tao, but like you said I had to invert the texcoords for proper coordinates to texture the sphere. GL.TexCoord2( 1f - i * OneThroughPrecision, ...
When you try to model more than the simple planets (i.e. Saturn) it starts getting hackish to display it's rings.
You could also take a look at the PQ Torusknots application in the Personal Projects section of the forum, which gives you a more complex object to work with than a sphere.

Re: Display lists and quadrics
posted by Technolithic

Inertia, I noticed something with your spheres algorithm...

It makes beautiful spheres, but when I use a prime number for precision... or so it seems (since I haven't tested the all the numbers) like 13, 17, 19, 23, 53, 97... I think those are all primes... anyhow, after rotating the spheres around their own axis, they seem to have a small hole in them. Not that it matters much, but I thought it was interesting. Prime numbers don't divide by two very nicely, so I bet that's why the spheres don't like primes.

I've seen precisions of 64, 32, and 16 without any defects. Those are very nice spheres.

Oh, I'm using a radius of 1.0. The holes show up after zooming in a bit. It's just that I'm using so many of them and rotating them all at the same angle that they all expose this hole at the same time. I shouldn't rotate them, but I was trying to keep their holes from being seen. LOL, I guess I don't have to bother with rotating anymore.

Anyhow, nothing a bit of common-sense can't avoid. I seem to lose a bit of that from time to time. LOL

Re: Display lists and quadrics
posted by Inertia

Not sure if it's restricted to primes, the line for ( uint j = 0 ; j < Precision / 2 ; j++ ) should cause problems with anything that's not a multiple of 2. Another problem with this function is that it will call GL.Begin() multiple times, which is not ideal. If this solution is not satisfying, there's code for some geometric objects located at /Source/Examples/Shapes/, but I'm uncertain if that is deprecated or will be continued at some point.

Re: Display lists and quadrics
posted by Technolithic

Inertia, your solution is great. I just needed something that worked for now. I'm working via an Agile development environment using prototyping and working closely with my client, so the timely solution was perfect. We're using the separation-of-concerns paradigm that Djikstra wrote about in the 70s... I don't remember the exact date, but Wikipedia has a nice article on it. Anyhow, if Djikstra wrote about it, it must be good. I hear the industry has just recently started to use it.

So, really, anyway, the separation of concerns is all about abstraction, which we are using to simplify things and this goes along with optimizing things later, after we find out what's really bogging down performance to a rate of hindering the use of the program.

I made a nice cone object that utilizes a triangle fan. It's very basic, but seeing how I could make my own graphical objects was a nice experience.

Going off that, I like the triangle strips technique of how you created the sphere algorithm. I've had a few thoughts about how to make a more optimized sphere algorithm, after your suggestion about calling Gl.Begin() isn't so great for performance. What about creating two triangle fans, for the top and bottom, and then creating a spiraling triangle strip from the top fan down to the bottom? Maybe even creating the entire sphere out of a single spiraling triangle strip.

Re: Display lists and quadrics
posted by Inertia

Credits for the function go to Sascha Willems, I just ported it to C#. It sure would be best to draw the sphere with a single spiral strip instead of multiple strips, I came to the same conclusion when looking into tesselate the Torusknot more effectively. While better for the graphics API, the spiral has a serious drawback when it comes to people using the function: it's way more intuitive to have a few parameters to control ring/loop precision and radii rather than picturing what the final result of a spiral strip might look like. Another thing that gets way more complicated is supplying texture coordinates for the object. Not sure if the optimization is worth it, it might be better to change the naive approach to output BeginMode.Triangles rather than a strip, and wrap that into a display list or VBO.

Re: Display lists and quadrics
posted by Technolithic

Fiddler, it looks like the GL.CallLists are working properly, at least for my object drawings. I'm using GL.Color to alter the colors of the objects and "manually" changing the lighting of the objects using GL.Materialv(). If the program needs more optimization, I'll use more call lists for setting the material properties of the objects instead of hard coding it. It seems that since I hard coded it, the program renders properly, but it's difficult to determine the conclusion why it makes a difference with all the other experiments I've been performing to get OpenGL to do what I need it to.

At any rate, I feel like I'm almost a Novice with this stuff and I can really apply it to the next level of awesome graphics programming!