LDraw.org Discussion Forums

Full Version: Simple renderer in .net with SharpGL (openGL)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I like to have for my several apps a slim renderer.
It should be done in pur net language
I have already set up a little bit, but run into problems that I am too stupid for to solve.
Is there anybody out there that can help on this?
Although I don't use .net specifically in my programs, maybe I can help on the general stuff. Any LDraw renderer uses the same principles anyway.

What problems are you having?
At present it is just that I have a flipped picture in my renderer. I'll send a screenshot by PM to you this evening along with the source code in .net vb.
I hope you help a little bit.
Are you compensating for DirectX being left handed while LDraw (and OpenGL) use right handed coordinates.
That might be the problem.
Please note that all lines with ' are comments
and sorry for my german comments:

This is to set the renderscene:
Public Sub InitSettings()
        ' Das hier sollte Sie erst einmal auch nicht kümmern.
        ' Hier wird mit Hilfe einer Matrix festgelegt, wie
        ' die einzelnen Objekte zu rendern sind.

        Dim Lookat As New Vector3
        Dim CameraPosition As New Vector3
        Dim UpDown As New Vector3
        Dim Factor As Integer = 3

        With Lookat
            .X = gLookAt.X
            .Y = gLookAt.Y
            .Z = gLookAt.Z
        End With

        With CameraPosition
            .X = 123.182831 / Factor '-70
            .Y = -100.578362 / Factor '-50
            .Z = -125.182831 / Factor '-100
        End With

        With UpDown
            .X = 0 '-0.35
            .Y = -1 '-0.866
            .Z = 0 '0.35
        End With

        'declare the World as identity matrix
        matWorld = Matrix.Identity

        'D3DDevice.SetTransform(TransformType.World1, matWorld)
        D3DDevice.SetTransform(TransformType.View, matWorld)

        ' Diese Matrix kann man als Kamera betrachten, mit
        ' der sich das Sichtfeld modifizieren lässt.
        ' Der erste MakeVector ist der Standort der Camera 100, -100, 100
        ' Der zweite MakeVector ist der Lookat Punkt 0, 0, 0
        ' Der dritte MakeVector bestimmt oben und unten 0, -1 , 0
        matView = Matrix.LookAtLH(CameraPosition, Lookat, UpDown)

        D3DDevice.SetTransform(TransformType.View, matView)

        ' Mit der Projektion-Matrix legen wir Sichtweite und
        ' Sichtwinkel fest.
        'Die beiden letzten Werte legen fest was man sieht, bei 1 ,1000 ist alles ok
        'bei 0.001 , 1000 sieht man hindurch
        'matProj = Matrix.PerspectiveFovLH((Pi / 4), 4 / 3, 10, 1000)
        matProj = Matrix.PerspectiveFovLH((Pi / 4), frmLDParts.Panel1.Width / frmLDParts.Panel1.Height, 10, 1000)
        D3DDevice.SetTransform(TransformType.Projection, matProj)

        ' Jetzt teilen wir dem Device noch mit, welches
        ' Art Vertex wir haben
        D3DDevice.VertexFormat = CType(D3DFVF_COLORVERTEX, VertexFormats)

        'With vbLightAmbient
        '  .a = 255
        '  .b = 125
        '  .g = 125
        '  .r = 125
        'End With
        'vbLight.Ambient = vbLightAmbient

        Dim vbTestBench As New VertexBuffer(D3DDevice, 400, Usage.Points, CType(D3DFVF_COLORVERTEX, VertexFormats), Pool.Default)
        'MsgBox("Vertexbuffer.SizeInBytes: " & test.SizeInBytes)
        Dim descr As VertexBufferDescription = vbTestBench.Description
        'MsgBox("VertexbufferDecsription.VertexFormat: " & descr.VertexFormat)
        'Dim descr As VertexBufferDescription
        'descr.Format = Format.VertexData
        'descr.VertexFormat = D3DFVF_COLORVERTEX
        'descr.Usage = Usage.Points
        'descr.Type = ResourceType.VertexBuffer

        ' Und noch ein paar Einstellungen

        'D3DDevice.SetRenderState(RenderStates.ZEnable, True)
        D3DDevice.RenderState.ZBufferWriteEnable = True
        'D3DDevice.SetRenderState(RenderStates.Lighting, False)
        D3DDevice.RenderState.Lighting = False
        'D3DDevice.SetRenderState(RenderStates.FillMode, FillMode.Solid)
        D3DDevice.RenderState.FillMode = FillMode.Solid
        'D3DDevice.SetRenderState(RenderStates.CullMode, Cull.CounterClockwise)
        D3DDevice.RenderState.CullMode = Cull.None
        D3DDevice.RenderState.AntiAliasedLineEnable = True
        D3DDevice.RenderState.LocalViewer = True

        'D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_CCW
    End Sub

The main loop:
Public Sub Mainloop()
        ' Der MainLoop läuft solange wie wir die
        ' bRunning-Variable auf 'true' lassen

        Do While bRunning

            ' Das vorher Gezeichnete löschen, indem wir es mit
            ' grauer Farbe übermalen
            D3DDevice.Clear((Direct3D.ClearFlags.Target Or Direct3D.ClearFlags.ZBuffer), Color.WhiteSmoke, 1.0F, 0)
            'D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &HC0C0C0, 1.0#, 0
            '&HFF& = Blau
            '&HAA& =

            ' Dem Device sagen, dass das "rendern gleich
            ' beginnt"

            ' Und nun lassen wir das Ganze noch rotieren
            Rotation = Rotation + 0.01

            matWorld = Matrix.Identity
            matRotation = Matrix.RotationY(CSng(Rotation * 1 * Pi / 180))
            matWorld = Matrix.Multiply(matWorld, matRotation)

            'D3DDevice.SetTransform(TransformType.World, matWorld)

            ' Hier "rendern" wir unsere Szene
            'Debug.Print("Start Rendern")
            If UBound(gLines) > 0 Then
                D3DDevice.DrawUserPrimitives(PrimitiveType.LineList, CInt(CLng(UBound(gLines) / 2)), gLines)
            End If

            'Dim a As New Line(D3DDevice)
            'a.DrawTransform(gLines, matWorld, gLines(1).Color)

            If UBound(gTriangles) > 0 Then
                D3DDevice.DrawUserPrimitives(PrimitiveType.TriangleList, CInt(CLng(UBound(gTriangles) / 3)), gTriangles)
            End If
            If UBound(gQuads) > 0 Then
                D3DDevice.DrawUserPrimitives(PrimitiveType.TriangleList, CInt(CLng(UBound(gQuads) / 3)), gQuads)
            End If
            'D3DDevice.SetTexture(0, Textur)
            'D3DDevice.VertexFormat = CustomVertex.PositionTextured.Format

            'Debug.Print("End Rendern")

            ' Rendern beendet

            ' Und das Ganze "präsentieren"

            ' Jeder, der schon mal einen Loop ohne Beendigungs-
            ' Bedingung gebastelt hat, weiß, dass man ein
            ' Doevents braucht, um noch Eingaben in seinen
            ' PC machen zu können
            'bRunning = False
    End Sub

Maybe you can see in the code above why my picture with this renderer is mirrored.
You seem to correct for the neg y-axis in the viewmatrix, but I don't think you correct for the left/right stuff. I believe you need to scale all ldraw matrices with the inverse of 1, 1, -1 for that.
Yes, that sounds reasonable. I'll try that soon and let you know.
I dug up some very old LD4DModeler code, which used DirectX

In it I do correction during the type 1 line loading.

//x y z
  matrix.m[3, 0]:=getvalue(line);
  matrix.m[3, 1]:=getvalue(line);
  matrix.m[3, 2]:=getvalue(line);
  matrix.m[3, 3]:=1;

  //a b c
  matrix.m[0, 0]:=getvalue(line);
  matrix.m[1, 0]:=getvalue(line);
  matrix.m[2, 0]:=getvalue(line);

  //d e f
  matrix.m[0, 1]:=getvalue(line);
  matrix.m[1, 1]:=getvalue(line);
  matrix.m[2, 1]:=getvalue(line);

  //g h i
  matrix.m[0, 2]:=getvalue(line);
  matrix.m[1, 2]:=getvalue(line);
  matrix.m[2, 2]:=getvalue(line);

  matrix.m[0, 3]:=0;
  matrix.m[1, 3]:=0;
  matrix.m[2, 3]:=0;        

  //rechthandig matrix -> linkshandige matrix
  //(T^-1)ST      waar s bron is en T rh2lhflip is

  D3DXMatrixInverse(mat, @dummy, rh2lhflip);
  D3DXMatrixMultiply(mat, mat, matrix);
  D3DXMatrixMultiply(matrix, mat, rh2lhflip);

rh2lhflip is inited elsewhere as D3DXMatrixScaling(rh2lhflip, 1, -1, 1);

Do note this is very (11 years!) old code, and I wasn't exactly an expert myself at that time Smile

edit: above code is less then correct and unnecessary overcomplicated. It's better to convert to lefthand/neg y axis at the model level.
Thanks for sharing that code.
At present I am looking for the right matrix to use:
1 0 0 0
0 1 0 0
0 0 -1 0
0 0 0 1

Do you think this is the correct matrix to use?
If yes, I set up a manual matrix and multiply just before the output with this.
I think so, but i'm not sure. I am a bit confused by my own ancient code (given it uses 1,-1,1 which seems to be the neg y correction and not left/right conversion). In short I think my above code is wrong and/or just plain inefficient Smile

So i did a bit of searching and found you can actually just use right handed stuff in directx just by replacing the LH with RH in all the api calls.
Ok, i'll try.
Life can be so easy Smile Thanks, that problem is solved. If I run into the next I'll ask again.
Ok, here is my next challenge:

I have currently a fixed value for field of view and distance.
The lookat point is calculated as the middle of the bounding box.

But how can I calculate the field of view and the distance (camera location point) to get the same behaviour like all other viewers out there???
In LDCad I use the zoom value as the with of the frustum at the lookat point. Everything else is then calculated based on that.
I think I know what I was doing in my old code, it doesn't matter which axis you clip as long it exactly one, so I choice Y to simultaneous correct for the neg y axis.
I am sure you are right Smile
But I have no clue how to do all this. You know my code. Where should I add what???
Sorry for being so stupid, but all the vectors drive me crazy. Also in schooltime vectors has not be my friends.
I'm afraid setting up a decent camera system isn't done in a couple of lines, I use a handfull of different classes (window, frustum, boundingbox, etc) for it in my renderer.

First you (neg) translate your scene to the lookat point and apply optional rotation.
Then you calculate the distance from the lookat point to the eye (zoom and fov angle combined with trigonometry)
That value you use to (neg) translate the scene, so it ends up in front of the camera.
Last you determine far and near

In this situation the camera eye is always at 0,0,0 and you basically put the model inside it's view (frustum).
Ok, thanks so far for your help.

I understand (hopefully) most of what you have said.
But I think it needs to be calculated the other way round.
Field of view is a given (fixed) value (maybe changeable elsewhere) and based of the bounding box I need to find the distance to this bounding box by a calculation. The camera will be only zoomed on a dedicated line. By doing this I have always the same point from which i look at the model.
O you are looking for the auto fit values, sorry I thought you wanted a simple movable camera.

Simplest way to do auto fit is to calculate the bounding sphere of the model and based on it's radius and the lookat point calculate the eye position.

An exact auto fit is something very different though, I'm still not happy with mine (which is the 3rd version or so).
Yes, with my approach I think it is easy to rotate the part and zoom in and out to look for some details. This should be at the end only mouse driven like ldview does, as everybody is familar with that tool.

Now I only need someone who tells me how to do that calculation with the given tools of .net Smile
I can't directly answer your question, since I don't know Direct3D. However, I can give an overview of what LDView does.

IIRC, LDView first calculates the bounding box for the whole model. Next, using the center of that box, it calculates the bounding sphere for the whole model. It then moves the camera to the center of the sphere, then backs it up by an amount calculated based on the FOV and the sphere radius. I believe that the distance to move back is:

radius / sin(fov/2)

Note that I believe fov in the above is either the horizontal FOV (if the window is taller than it is wide) or the vertical FOV (if the window is wider than it is tall). OpenGL expects you to always give it the vertical FOV, so LDView calculates that based on the horizontal FOV when the window is taller than it is wide. I suspect that Direct3D also wants the vertical FOV. If you always use the same FOV value, no matter what the window shape, I believe you'll get a cropped image if you use that in the above calculation when the window is taller than it is wide.

If have have the horizontal FOV, the vertical FOV can be calculated like so:

VFOV = 2*atan(tan(hfov/2)/(width/height))

Note also that LDView's default zoom level (calculated as per above) is set up so that no matter how you rotate the model, it will always be fully visible (which is why it uses the bounding sphere).

LDView's "zoom to fit" functionality uses an algorithm I got from Lars C. Hassing that solves numerous equations for numerous unknowns to move the view pyramid around until at least two points on the model are exactly at the edge of the view. (Those two points are either at the top and bottom of the view, or at the left and right.) The pyramid is moved in such a way that the view direction remains constant, but the camera position moves in all three dimensions, so the look-at point also moves.
Thanks for leaving your ideas here Smile

The way of calculating the camera position is the same I thought that should be a good way, so I will go with that.

For the FOV I use the following function:

So it seems that you are right with your guess Smile

Now I _only_ have to put that into some code.

I'll keep you informed.

Now I realized that DirectX is just not the choice that I should take, as this requires wine under linux.

I need to use a .net version of an openGL engine.

If someone has experience with that I would be glad to get help Smile
All you need are the header files, I'm sure a quick search will point you to them if they aren't available by default. The default ones might be old, but for basic LDraw rendering OpenGL 2.0 is good enough unless you want to do some very fancy stuff.
I have taken the openTK library to get it simple Smile

First steps are made.
Why isn't there a good tutorial on these things on the net ? Sad

After several hours of searching I am close before shutting down my idea.

Current status:
I have a control where I can draw a triangle in ortho mode.
All attempts that I made so far for a 3D part (at least a simple box) failed.

If someone has already experience with OpenTK (please not direct openGL) please let me know in simple words:

How do I set the camera in a world.
How do I set a light in a world.
How do I set the lookat point in a world.

Any help is very much wished.
Currently i am far away from the point I already reached with DirectX, but I need to switch to openTK for different os's.
For example:

Private Sub GlControl1_Load(sender As Object, e As System.EventArgs) Handles GlControl1.Load
        glLoaded = True
        GL.ClearColor(Color.SkyBlue) ' .NET Colors can be used directly!
End Sub
Private Sub SetupViewport()
        Dim w As Integer = GlControl1.Width
        Dim h As Integer = GlControl1.Height
        GL.Ortho(0, w, 0, h, -1, 1) ' // Bottom-left corner pixel has coordinate (0, 0)
        GL.Viewport(0, 0, w, h) ' // Use all of the glControl painting area
End Sub
Public Sub GlControl1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint
        If Not glLoaded Then Exit Sub

        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)


        GL.Vertex2(10, 20)
        GL.Vertex2(100, 20)
        GL.Vertex2(100, 50)

End Sub

This is the code that currently works.
Why don't you want to use the OpenGL api directly? There are tons of tutorials/examples for that, as it doesn't really matter which language you are using.

Also you your above code seems to use intermediate mode, which is something you want to avoid for the core part mesh data.
Why I do not use the api directly? In visual basic you can not just add the header files from another language. You have to define each function etc separately. So this is already done by the openTK team.

What do you mean by
Roland Melkert Wrote:Also you your above code seems to use intermediate mode, which is something you want to avoid for the core part mesh data.

I am an absolutly newbee if we coming to 3D coding, so please explain for stupid guys Smile
Header files are just the thing that makes functions from external dll's visible/usable inside your language, so they them self need to be visual basic in your case. But when you use them they supply access to functions like 'glBegin', glDrawElemenets' etc etc . Those functions are identical no matter which language you use. So whenever an tutorial or example uses those functions you can use the same approach in any given language as long the basic OpenGL api functions are available (though language specific header files).

OpenTK seems to do just that but uses the vb function names (gl.begin instead of glBegin), but the principle remains the same, so you don't have to look for OpenTK specific tutorials, any OpenGL tutorial will do, just adjust the function names.

The intermediate mode lets you output individual points etc to make up triangles and quads etc, which is very slow / old fashioned. Modern OpenGL want's you to use buffers. When beginning with OpenGL you just as well jump right into using buffers and don't waste time understanding the old system.

As for the camera,lookat etc those are 'hidden' in the projection and modelview matrices, you can use api (glut) functions to initialize those.
Thanks for your information.

I had to leave openTK and now I am working with SharpGL (http://sharpgl.codeplex.com/) and I have my first 3D window.

Now I am trying to see something LDraw like in the window Smile

Currently I stay with the BEGIN and END structure as I understand that easily. As soon as I got that to work (my computer is fast) I'll ask for the buffers and how to use them.
It is very frustrating Sad(

I have a sample code that works, I can see a triangle and a box.

If I substitude the code for that two objects with the code for a part, I see - nothing.

At present I have no clue what I am doing wrong. Sad
Ok, i have my first - very little - success. I see now the lines. But why do i not see the triangles?
If you're sure they are inside the camera's view, it's probably because of the winding.

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);

will enable two sided rendering for all polly's
Thanks for the tip, i'll try that.
But it was something different - stupid me. I did not draw the quads (divided into triangles) also. And at a 3005 there are many quads.

I added that, but I can not see any difference as all faces are black.

I have already set the color gl.Color(0, 100, 0) but also this results in black.

Maybe I have to make some light on?

I added also:
gl.Light(SharpGL.Enumerations.LightName.Light0, SharpGL.Enumerations.LightParameter.Ambient, 1)
gl.Light(SharpGL.Enumerations.LightName.Light1, SharpGL.Enumerations.LightParameter.Diffuse, 1)
but no change in the picture Sad

By the way, the best tutorial so far (in german language) is http://www.3dsource.de/faq/index.htm
I would suggest keeping lighting disabled until you can see proper geometry. Lighting should be disabled by default, and if it is, then things should show up in the color they're drawn in. However, I believe that glColor() only works as expected if you use glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE) and glEnable(GL_COLOR_MATERIAL).
Thanks to all for your help.

Currently I do not exactly what the reason is, but if you use glcolor I have to append a "F" at the number and then the wanted color is drawn.
I have never been aware of that possibility, but that was the only difference to other codes that seems to work.

gl.Color(100, 0, 0) -> shows only black surfaces
gl.Color(100.0F, 0.0F, 0.0F) -> shows the desired surface color

Now I know why! If I enter just a number then it is assumed to be an integer instead a single value.
I know from LDraw that we use RGB values in the range 0 to 255 and so I entered that numbers. But that seems to be wrong!

Maybe someone with more knowlage about this issue can write one or two lines here for others and me to explain why this is this way.
Also make sure you don't forget


just before you start drawing stuff (every frame).

Also if you found a tutorial source, I'm sure they offer a basic render loop example which would take care of setting defaults for camera, materials and lighting etc.
OpenGL uses 0..1 values for most stuff, The api functions have variations indicating the type of the parameters e.g. glColor3f or glColor3d . If the vb wrappers are hiding this, a mistake is made very quickly indeed.

I use this class function to get the float values for OpenGL from LDraw lines.

void init(const unsigned int rgb, const unsigned char alpha=255) {
  r=(float)((rgb & 0xFF0000) >> 16)/255.0;
  g=(float)((rgb & 0xFF00) >> 8)/255.0;
  b=(float)(rgb & 0xFF)/255;
check if you have an old version of sharpgl containing this bug

by the way, why did you prefer sharpgl over opentk?
Thanks for mention this issue with SharpGL. Maybe this explains the behaviour I see at present. I am using 2.0 and according to the link you provided version 2.1 should be fine without this error.

I switched to SharpGL for two reasons:
1) At many places on the net I have read that openTK is dead.
2) The naming of the functions in SharpGL looks for me more like the standard C functions, so discussing the features seems to be easier.
I have now the colors ready, but I am in trouble with the global behaviour of the openGL understanding.
As far as I have understand the whole thing, I have three different matrices:
Textures (not yet used)

At first I set the projection matrix to the values I need.
At second step I set the modelview matrix.
Now I put the model into the modelview.

The following code currently gives blank window:
gl = Me.OpenGLControl2.OpenGL

        gl.Viewport(0, 0, OpenGLControl2.Width, OpenGLControl2.Height)

        gl.LookAt(CDbl(gradiusOfBoundingbox / Math.Sin(fov / 2)), CDbl(gradiusOfBoundingbox / Math.Sin(5 / 2)), CDbl(gradiusOfBoundingbox / Math.Sin(5 / 2)), CDbl(0), CDbl(0), CDbl(0), CDbl(0), CDbl(-1), CDbl(0))
        gl.Perspective(CDbl(fov), CDbl(OpenGLControl2.Width / OpenGLControl2.Height), CDbl(2), CDbl(2 * gradiusOfBoundingbox + 2))

        gl.Rotate(45.0F, 0.0F, 1.0F, 0.0F) 'Rotation for LDView like viewing angle
        gl.Rotate(22.5, 1, 0, 1)                'Rotation for LDView like viewing angle
        gl.Translate(gradiusOfBoundingbox, 0, gradiusOfBoundingbox)

I am right with my thoughts how this should work and I have only a stupid thinking error, or is the behaviour different than I wrote above??

Any help is very welcome.
I'm not familiar with SharpGL, so I'm not sure what you are doing in the projection part. Only thing I can tell you is you don't need lookat there (don't know what the gl.LookAt function does).

You only need to apply your lookat it in the viewmatrix, using a negative translate.
SharpGL should (hopefully) totally identically with standard OpenGL functions.
The glulookat function is part of the OpenGL Grafics System Utility Library
It should make life easier Smile

But you did not answer my global question. Did I understand opengl right if I have a world matrix and a model matrix that i can individually transform and both together make the result?
I did not realize it's the gluLookAt function. Anyway that's a modelview function, but the following perspective (gluPerspective i assume) will override it. This is because your preceding matrixmode indicated all matrix related functions must use the projection matrix.

The projection and viewmatrix must be set separately, and will always stay separate. In practice you initialize the projection matrix just once, and do all the per frame (camera control) stuff in the viewmatrix.

If you use the lookat function (after the matrixmode switch to modelview), you don't need to translate as the lookat function constructs the viewmatrix includiing lookat correction, hence the name.

I hope this is what you ment.
Ok, I changed to use the lookat at the modelview matrix.

I can now see something, but I need to have still an error in my view.

It's very frustrating Sad

Now I see not the full model, it is cutted. I believe it depends on the near, far, right, left, top, buttom parameters, but I stupid guy can not solve my problem so far. Sad
Near should be a fairly small number (1? ... 0.1?). Far should be greater than the distance to the farthest point in the model from the camera. If you have calulated a bounding sphere, you can probably just add the sphere's diameter to the distance between the camera and the lookat point. (You can use radius, but only if the lookat point is the center of the sphere.)
Yes, that is what I also thinking about. But there needs to be another thinking error. I have to check with a lot of coffee this morning Smile

Here is my current code (I see - nothing), that I now explain:
loadidentity - set the current matrix (Projection) to start modus
viewport - is the 2d window that should be used (left bottom corner at 0,0 and upper right corner from control width and height)
perspective (field of view in radian, ratio, znear, zfar) - for zfar I use two times the radius of the bounding box.
frustum (left, right, bottom, top, znear, zfar) - for left, right, bottom, top I use the radius of the bounding box, zfar like above.
Then I switch to the modelview and start with a fresh matrix.
The only transformation now is with the lookat matrix
lookat (eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz)
        gl.Viewport(0, 0, OpenGLControl2.Width, OpenGLControl2.Height)
        gl.Perspective(CDbl(fov), CDbl(OpenGLControl2.Width / OpenGLControl2.Height), CDbl(0.1), CDbl(2 * gradiusOfBoundingbox))
        gl.Frustum(CDbl(gradiusOfBoundingbox + 100), CDbl((gradiusOfBoundingbox + 100) * -1), CDbl((gradiusOfBoundingbox + 100) * -1), CDbl(gradiusOfBoundingbox + 100), CDbl(0.1), CDbl(2 * gradiusOfBoundingbox))


        gl.LookAt(CDbl(0), CDbl(0), CDbl(0), CDbl(0), CDbl(0), CDbl((gradiusOfBoundingbox / Math.Sin(fov / 2)) * 2), CDbl(0), CDbl(-1), CDbl(0))



Where is my error??
OpenTK has the advantage that it is - different than SharpGL - not tied to Windows Forms.
This means that supporting Mono on e.g. Ubuntu will be easier,
where - AFAIK - the Windows Forms implementation is still poor (tell me if I'm wrong).
A good combination for you could be GTK# (for the GUI), plus GLWidget (for a GUI container holding OpenTK),
and inside that OpenTK for the OpenGL stuff.
This will give you a heavily portable, OS independent C# application.
OR can anybody recommend a better combination maybe? Including reasons? I'd be very curious to know.

Have fun!
Pages: 1 2