jfinken's picture

Is it possible to import or reference a small subset of OpenTK.Compatibility.dll?

My sincere apologies if this is more of a general .NET question and/or too off-topic.

My app references OpenTK.dll and OpenTK.GLControl.dll. I'd like to investigate the use of the tesselator functionality found in OpenTK.Compatibility.dll, Glu.Tess*, etc. However including the Compat dll in my project wreaks havoc with my existing code due to GL calls not being fully-qualified. I get several hundred errors like:

'GL' is an ambiguous reference between 'OpenTK.Graphics.GL' and 'OpenTK.Graphics.OpenGL.GL'

because of things like:

GL.GenBuffers(1, out vbo.VertexBufferId);

instead of, say:

OpenTK.Graphics.OpenGL.GL.GL.GenBuffers(1, out vbo.VertexBufferId);

Is there a way to somehow include the Compatibility DLL but tell Visual Studio not use it to resolve identifiers? (Thus allowing me to cherry pick just the tesselator functionality via the 'using' directive). Or something similar? Yes, I could resolve the ambiguities but I thought I'd ask before the significant code change.

Many thanks in advance!


Comments

Comment viewing options

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

The source code is available, so I'd suggest to simply take the Glu source files and add them to your project. Problem solved!

elaverick's picture

I think (although I haven't tested it) that if you change the alias under which the compatibility library is imported it will only resolve when you refer to that alias. To do this expand the references section of the Solution Explorer and in the properties page change the Aliases property from global to something else. I think you'll have to do the same with the using directive as well. Have a look here for more details http://msdn.microsoft.com/en-us/library/c3ay4x3d.aspx

jfinken's picture

I was hoping to somewhat avoid that option, but in the interest of trying the tessellator, I gave it a go. One problem is that GluHelper.cs calls GL.GetExtensionDelegate thereby causing the same overall problem. So I copied the following methods and classes from OpenTK.Compatibility.Graphics.GL.GLHelper.cs to the GLHelper.cs now in my project:

GetExtensionDelegate
GetAddress
internal class GetProcAddressOSX : IGetProcAddress
internal class GetProcAddressX11 : IGetProcAddress
// I'm on a 32bit Windows 7 machine...
internal class GetProcAddressWindows : IGetProcAddress
internal interface IGetProcAddress
private static IGetProcAddress getProcAddress;

It compiles and when trying to run the tessellate code from my copied Glu.cs, I get the following exception during Glu::LoadAll():

EntryPointNotFoundException: Unable to find an entry point named 'wglGetProcAddress' in DLL 'glu32.dll'.

Is wglGetProcAddress only an entry point in opengl32.dll? Copying the above methods and classes not a good idea?

EDIT:
I can simply change the Library string from "glu32.dll" to "opengl32.dll" in my copied GluHelper.cs and ultimately the tessellate code gets invoked.

However I should have tried elaverick's suggestion first. Many thanks for the tip to investigate Aliases. I changed the Alias property of OpenTK.Compatibility to 'open_tk_glu', for example. Then referenced the aliased assembly like:

extern alias open_tk_glu;
...
using System;
using OpenTK;
...
 
unsafe static public bool Triangulate(Vector2[] Input, int[] VertsPerContour)
{  
    IntPtr tess = IntPtr.Zero;
 
    tess = open_tk_glu::OpenTK.Graphics.Glu.NewTess();
    ...
}

I now get a AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at the call to open_tk_glu::OpenTK.Graphics.Glu.DeleteTess(tess);

jfinken's picture

Here's my entire Tessellate class in case anyone has any ideas. Should look familiar! Thanks in advance.

extern alias open_tk_glu;
 
using System;
using System.Collections.Generic;
using System.Xml;
using System.Runtime.InteropServices;
using System.Diagnostics;
 
using OpenTK;
 
namespace Util
{
    //
    //This class use the OpenGL GLU tessellation
    //functions to triangulate a simple polygon.
    //
    //This code is based largely on Michael Foetsch
    //triangulation tutorial that can be found, as of
    //February 2, 2008, at http://www.geocities.com/foetsch/articles.htm.
    //
    //It interfaces with OpenGL through OpenTK.
    //
 
    static class Tesselate 
    {
        // Some of this code is lifted from the OpenTK tesselation sample:
        // Define the signatures for the callback functions, and declare the callbacks.
        delegate void BeginCallbackDelegate(int mode);
        delegate void EndCallbackDelegate();
        delegate void VertexCallbackDelegate(IntPtr v);
        delegate void EdgeFlagCallbackDelegate(int flag);
        delegate void ErrorCallbackDelegate(int code);
        unsafe delegate void CombineCallbackDelegate(
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)]double[] coordinates,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)]double*[] vertexData,
            [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)]float[] weight,
            double** dataOut);
 
 
        //After a successful call to Triangulate, this public list holds the indices
        //for the given input.
        static public List<int> Indices;
        static public bool InvalidPolygon;
 
        // Triangulate       
        unsafe static public bool Triangulate(Vector2[] Input, int[] VertsPerContour)
        {
            InvalidPolygon = false;
            Indices = new List<int>();
 
            IntPtr tess = IntPtr.Zero;
            // create tesselation object
            tess = open_tk_glu::OpenTK.Graphics.Glu.NewTess();
 
            // register tesselation callbacks
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessBegin, new BeginCallbackDelegate(BeginCallback));
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessEdgeFlag, new EdgeFlagCallbackDelegate(EdgeCallback));
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessVertex, new VertexCallbackDelegate (VertexCallback));
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessEnd, new EndCallbackDelegate(EndCallback));
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessCombine, new CombineCallbackDelegate(CombineCallback));
            open_tk_glu::OpenTK.Graphics.Glu.TessCallback(tess, open_tk_glu::OpenTK.Graphics.TessCallback.TessError, new ErrorCallbackDelegate(ErrorCallback));
 
            //copy input into a linear array of floats
            double[] Vertices = new double[3 * Input.Length];
            for(int v=0;v<Input.Length;v++)
            {
                Vertices[v*3+0] = Input[v].X;
                Vertices[v*3+1] = Input[v].Y;
                //Vertices[v*3+2] = Input[v].Z;
                Vertices[v*3+2] = 0.0;
            }
 
            // begin polygon
            open_tk_glu::OpenTK.Graphics.Glu.TessBeginPolygon(tess, IntPtr.Zero);
 
            // go through the contours
            int CurrentContour = 0;
            int VertsThisContour = 0;
 
            for(int v=0;v<Input.Length;v++)
            {
                if(v == 0)
                    open_tk_glu::OpenTK.Graphics.Glu.TessBeginContour(tess);
 
                // pass the corresponding vertex to the tesselator object
                double[] VertsToPass = new double[3];
                VertsToPass[0] = Vertices[v * 3 + 0];
                VertsToPass[1] = Vertices[v * 3 + 1];
                VertsToPass[2] = Vertices[v * 3 + 2];
                open_tk_glu::OpenTK.Graphics.Glu.TessVertex(tess,VertsToPass,v);
 
                if(InvalidPolygon)
                    break;
 
                VertsThisContour++;
 
                if(VertsThisContour >= VertsPerContour[CurrentContour])
                {
                    VertsThisContour = 0;
                    open_tk_glu::OpenTK.Graphics.Glu.TessEndContour(tess);
 
                    CurrentContour++;
 
                    if(CurrentContour < (long)VertsPerContour.Length)
                    {
                        open_tk_glu::OpenTK.Graphics.Glu.TessBeginContour(tess);
                    }
                }
            }
 
            if(InvalidPolygon)
            {
                // destroy the tesselation object
                open_tk_glu::OpenTK.Graphics.Glu.DeleteTess(tess);
                tess = IntPtr.Zero;
 
                return false; //error in polygon definition
            }
            else
            {
                //-------------------------------------------------------------
                // AccessViolationException: Attempted to read or write protected memory.  Occurs here...
                //-------------------------------------------------------------              
                open_tk_glu::OpenTK.Graphics.Glu.TessEndPolygon(tess);
 
                // destroy the tessellation object
                open_tk_glu::OpenTK.Graphics.Glu.DeleteTess(tess);
                tess = IntPtr.Zero;
 
                //The Indices object is now valid.
                return true;
            }
        }
 
 
        //GLU callback functions
        static void BeginCallback(int type)
        {
 
        }
 
        static void EdgeCallback(int flag)
        {
 
        }
 
        static void VertexCallback(IntPtr vertexIndex)
        {
            unsafe
            {
                Indices.Add(*((int*)vertexIndex));
            }
        }
 
        static void EndCallback()
        {           
        }
 
        unsafe static void CombineCallback(double[] coords, double*[] vertexData, float[] weight, double** outData)
        {
            //This means the polygon is self-intersecting.
            //See the OpenTK tesselation example for a working version of the
            //combine callback.
            InvalidPolygon = true;
        }
        static void ErrorCallback(int errno)
        {
            //some error ocurred, mark this triangulation as invalid
            InvalidPolygon = true;
        }
 
    }
}

Who's online

There are currently 0 users and 15 guests online.