Hide this comment

One of the things I liked about the directx demo Don Syme did on a channel 9 video was dynamically changing stuff in the Direct X rendered scene. What I would eventually like to end up with is a system to do the same thing with OpenGL. It would make working with OpenGl graphics a lot more interesting as you can see your changes immediately.

I have spent some time working on this issue and basically what you need is the TAO Framework which wraps OpenGl with a managed api. so including the following in a fsx file gives you access to the API

#r @"D:\Program Files\TaoFramework\bin\Tao.OpenGl.dll";;
#r @"D:\Program Files\TaoFramework\bin\Tao.FreeGlut.dll";;

open Tao.FreeGlut
open Tao.OpenGl

unfortunately trying to use any of the wrapper functions will throw exceptions because you will also need the native DLL which the wrapper needs to resolve the calls. The only way I have found to mitigate this problem is to copy the required DLL to the fsharp bin directory. However, if you don't mind working directly from a command line you can cd to a directory that has the required DLL and launch fsi from there. The last option is a nice solution but it cannot be used in Visual Studio, at least not to my knowledge.

Assuming you have gotten this far then you can use F# to work with OpenGL. Unfortunately the minute you execute "Glut.glutMainLoop()" your fsi will be stuck executing that mainloop function as it doesn't return. I have yet to find a clean way to exit the OpenGL window without causing the fsi console from crashing.

To side step that issue you can run the mainloop function in a separate thread. This allows you to continue working with your fsi instance. Unfortunately this is not the end of the road or even a rest stop to declare a minor victory. I say this because any changes made to the function definitions used to render a OpenGL scene will not lead to changes in the scene. I am not completely sure why this hap[pens but I have a feeling the functions are immutable upon definition so the copy OpenGL uses will not be changed by a simple definition change. Some one with more knowledge of how fsi handles function definitions can probably explain why.

To get around this hurdle I adopted message passing mechanism. Basically you create a mailbox that takes a new render function and that function will be retrieved by the OpenGL thread to do its rendering work. I got the inspiration for this idea from Expert F#, which that covers message passing in F#. The method illustrated on page 381-382 shows how to maintain an old display function and how to change that old function with a new one to be used the next time the mailbox is checked. The only thing left to do to see the changes are to force a redraw.

Now I am very much a newb to F# and async programming in F# but I figure there is a much more elegant way of allowing someone to work in F# with OpenGL while dynamically making changes that are reflected in the scene. For now I have a rest spot to call a minor victory until I find a better way of doing it. I think in the end the solution will resemble setting up a OpenGL "canvas" (I am using the term loosely) where you can post different display/render functions that are either updated versions of the previous version being used or completely different functions. But in the end you will have a nice system in which to write some OpenGL

By on 6/22/2008 9:50 AM ()Reply
Hide this comment

Found a quick way to change the working directory of fsi
System.Environment.CurrentDirectory <- @"path"

found this in a diectx tutorial included in the FSharp distrib. so you can now put the native dll in your project directory.

As for roberts response thanks for the heads up on the Event Loop All I have to do now is understand it and see how it would work best with OpenGl and the Tao Framework.

By on 6/23/2008 5:42 PM ()Reply
Hide this comment

Hi Birchoff,

I strongly suspect that the native dll needs to be on the system path for the avoid having to copy it to the fsi directory.

Each GUI framework uses its own even loop which is a sort of message queuing system. FSI supports this thought the IEventLoop interface. By default FSI launches an event loop for the WinForms library (System.Windows.Forms). The F# distrib comes with a sample that shows how to replace this event loop with an event loop for WFP (samples\fsharp\WPF\GettingStarted\load-wpf.fsx). To create one for TAO/ OpenGL I think you would need to call the “Glut.glutMainLoop()” method from the Run of IEventLoop, there may be other steps too, I’m not sure.

Cheers,
Rob

By on 6/23/2008 12:36 AM ()Reply
Hide this comment

So after implementing and installing a replacement IEventLoop, then what do you do to kick it off. I have tried running fsi.EventLoop.Run () but hat just causes fsi to die with an error message. I tried doing that with the wpf example and it also dies so I figure it shouldnt be called like that.

In a ay I wish there was more info about these kool features... I dont mind flailing around in the dark like the next guy but an occasional wall to shimmy across would be nice....

By on 6/24/2008 6:25 AM ()Reply
Hide this comment

Whats the Invoke method in the IEventLoop interface supposed to be used for?

By on 6/23/2008 8:30 PM ()Reply
Hide this comment

Whats the Invoke method in the IEventLoop interface supposed to be used for?

Dispatcher.Invoke calls the supplied delegate (or function) synchronously on the thread associated with the dispatcher (usually the creating thread). A lot of controls (both WPF and Forms) must be manipulated on the thread the GUI object (control) was created on. So, in the particular case here, the x.Invoke member ensures the parameter "f" gets run in the right context (thread) for the control.

In Windows.Forms, you should call form.InvokeRequired to see if the current thread needs to call Invoke or BeginInvoke. Otherwise, the control can be manipulated directly.

I've never written WPF code, but it appears that control.CheckAcceess serves the same function there.

-- Jay

By on 6/23/2008 11:15 PM ()Reply
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper

Logging in...