djk's picture

Glu NURBS Curve and Surface example

I had the need to start working with Glu.Nurbs curves and surfaces this week.

To get a handle on the structures and procedures involved, I created a simple OpenTK example for using Glu.NurbsCurves and Glu.NurbsSurfaces. It's built using the example framework and the SVN revision 1324 of OpenTK. The Curve and surface data is from a RedBook example, if this is a problem, I can change the data.

Please consider this as my first contribution to OpenTK.


[Edit] I started to add trimming curves to the surface and the parameter GLU_MAP1_TRIM_2 is missing from the MapTarget enum.

[Edit2] It looks like the GLU_MAP1_TRIM_2 is actually a NurbsTrim.Map1Trim2, the Glu.NurbsCurve does not have a signature that is compatible with a NurbsTrim. I have not figured out how to add the missing overload.

I have updated the drawing code to allow trimming and commented out the trimming operation, its in the rev1 zip file.

W06_GluNurbs_rev6.zip7.46 KB


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Inertia's picture

Thanks! I've ported the Quadrics example from the redbook aswell, it's not on svn because of the very same copyright question. The email sent to clarify this couldn't be delivered.

Since the redbook is mirrored online by several universities and other GL pages, I kinda believe it's ok to add it's ported C# code to OpenTK. There might be legal consequences if you try to put OpenTK on a CD/DVD and sell that (they might want a piece of that pie), but for non-commercial/educational use I see no reason why this could become a problem.

djk's picture

The example is evolving and I will replace the few bits that are left from the RedBook with orignal work over the next few days.

I am still stuck on the trimming curve issue, I added the Map1Trim2 enum to the MapTarget enum. When I apply the trimming curve it blows up deep in the bowels of OpenTK. Could you and/or fiddler take a look at rev2 and let me know if the trimmed surface error I am getting is fundamentally the same issue as that faced by the vertex array. I am starting to think that the trimmed surface process is using both client and graphics memory.

[Edit] Below is the temporary addition I made to MapTarget enum

    public enum MapTarget
        GeometryDeformationSgix = ((int)0X8194),
        Map1Color4 = ((int)0X0D90),
        Map1Index = ((int)0X0D91),
        Map2Index = ((int)0X0Db1),
        Map1Vertex4 = ((int)0X0D98),
        TextureDeformationSgix = ((int)0X8195),
        Map1Vertex3 = ((int)0X0D97),
        Map1Normal = ((int)0X0D92),
        Map2Vertex4 = ((int)0X0Db8),
        Map2Color4 = ((int)0X0Db0),
        Map2Vertex3 = ((int)0X0Db7),
        Map2Normal = ((int)0X0Db2),
        Map1TextureCoord4 = ((int)0X0D96),
        Map1TextureCoord2 = ((int)0X0D94),
        Map1TextureCoord3 = ((int)0X0D95),
        Map2TextureCoord2 = ((int)0X0Db4),
        Map2TextureCoord3 = ((int)0X0Db5),
        Map2TextureCoord1 = ((int)0X0Db3),
        Map1TextureCoord1 = ((int)0X0D93),
        Map2TextureCoord4 = ((int)0X0Db6),
        Map1Trim2 = 100210
djk's picture

I have added some controls for exploring the tesselation parameters of the Glu Nurbs surface and curves in rev3.

Inertia's picture

The problem is related to the delegate:

internal unsafe delegate void NurbsCurve(IntPtr nurb, Int32 knotCount, [Out] float* knots, Int32 stride, [Out] float* control, Int32 order, MapTarget type);

both [Out] keywords are marshaling data in the wrong direction. PlwCurve() should work without modifications.

djk's picture

In rev3 I fixed part of the problem, I had to many control points to the specified knot vector. The problem now seems to be in the EndSurface method that is called right after the trim curve is closed.

Rev4 uses PwlCurve, and PwlCurve or the NurbsCurve gives me the same error:

if (_trimSurface)
     //Glu.NurbsCurve(_theNurb, 8, _trimKnots, 2, _trimControlPoints, 4, MapTarget.Map1Trim2); // trim curve is a foil shape.
     Glu.PwlCurve(_theNurb,4, _trimControlPoints, 2, NurbsTrim.Map1Trim2); // trim curve is a diamond shape

Error message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Stack Trace: at OpenTK.Graphics.Glu.Imports.EndSurface(IntPtr nurb)
at OpenTK.Graphics.Glu.EndSurface(IntPtr nurb) in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\OpenGLControls\OpenTK\OpenTk-0.9.1\Source\OpenTK\Graphics\Glu\Glu.cs:line 269
at Examples.WinForms.W06_GluNurbs.NurbsSurface.Draw() in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\OpenGLControls\OpenTK\OpenTk-0.9.1\Source\Examples\WinForms\W06_GluNurbs.cs:line 321

Inertia's picture

Mhmm I'm unable to reproduce the error, so it's very likely - as you said earlier - that this is similar to the "Vertex Array" problem. My guess is the pointer to the controlpoints isn't used before Glu.EndSurface() is called, so pinning the ControlPoints (maybe adding a GL.Finish before releasing the pin too) should give the desired result.
I'm not familiar with the math for Nurbs - no idea if the points are specified correctly - but the example draws the very same surface no matter if including the trim or not. I recall reading somewhere that the control points have to be clamped to uv space [0f..1f] but not entirely sure if that is an issue hereby.

djk's picture

I tried to pin the data with no success. I am quite comfortable working with nurbs data. The trim curve is defined in the uv range of [0f..1f].


djk's picture

Well, I finally figured out the problem; I don't seem to be able to tell the difference between clockwise and counter-clockwise.

NurbsCurve still needs to have a set of overloads that takes a NurbsTrim.Map1Trim2.

To make rev5 work, the MapTarget enum has to be temporarily modified as above to add Map1Trim2.


the Fiddler's picture

I'll test this on Mono, then add it to the examples. Thanks!

Inertia's picture

Good job :) Btw. is there any reason why you did not wrap the Nurbs into display lists? That would pretty much work around the issue with pinning except at display list compile time, which is imo desireable. Since you don't allow the control points to be changed through the form it would probably be best practice to do this, assuming display lists can wrap whatever the Glu functions do call in GL.