I'm new to OpenGL; very experienced with C#. And I'm out of ideas.
I have 56640 points (x,y,z) in a CSV file created from an image of a corroded metal plate. x,y are actual coordinates, z is the plate surface height, FWIW. I'm using an OpenTK GLControl to show the data in a WinForms application. VS 2010 Express, .NET Framework 4 Client Profile on Windows 7 64-bit. My machine is a Lenovo T520, 4 GB RAM with an Intel HD 3000 integrated adapter. According to the "realtech OpenGL Extension Viewer", the chip supports OpenGL 3.1 fully.
I read the whole set into a Vector3 array, calculating a grayscale color based upon the z value. I create a VBO large enough to hold axis endpoints, data points and a Vector3 color for each, organized by all points first, and then all colors (i.e. consecutive, not interleaved). Then I copy the data from the managed arrays into my VBO:
int isize = Marshal.SizeOf(axes); IntPtr axesBytes = new IntPtr(isize * axes.Length); IntPtr verticesBytes = new IntPtr(isize * disk1bVertices.Length); IntPtr colorsBytes = new IntPtr(isize * colors.Length); IntPtr totalBytes = new IntPtr(axesBytes.ToInt32() + verticesBytes.ToInt32() + colorsBytes.ToInt32()); GL.BufferData(BufferTarget.ArrayBuffer, totalBytes, IntPtr.Zero, BufferUsageHint.StaticDraw); GCHandle haxes = GCHandle.Alloc(axes, GCHandleType.Pinned); GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, axesBytes, haxes.AddrOfPinnedObject()); haxes.Free(); GCHandle hvertices = GCHandle.Alloc(disk1bVertices, GCHandleType.Pinned); GL.BufferSubData(BufferTarget.ArrayBuffer, axesBytes, verticesBytes, hvertices.AddrOfPinnedObject()); hvertices.Free(); IntPtr colorOffset = new IntPtr(axesBytes.ToInt32() + verticesBytes.ToInt32()); GCHandle hcolors = GCHandle.Alloc(colors, GCHandleType.Pinned); GL.BufferSubData(BufferTarget.ArrayBuffer, colorOffset, colorsBytes, hcolors.AddrOfPinnedObject()); hcolors.Free(); // since we're using VBO and OpenGL 3+, the vertex pointer (last parameter) // is actually the offset into the currently bound ArrayBuffer GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero); // so do the same for colors GL.ColorPointer(3, ColorPointerType.Float, 0, colorOffset.ToInt32());
I set up an identity projection matrix, an orthographic projection to show the whole volume, and use the whole window:
GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); GL.Ortho(_xmin, _xmax, _ymin, _ymax, _zmax, _zmin); GL.Viewport(0, 0, w, h);
My render just draws the axes and the data:
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.EnableClientState(ArrayCap.VertexArray); // number of axis vertices int nAxisVert = naxes * 2; // draw world axis using identity model transformation, so it stays fixed GL.Color3(Color.AntiqueWhite); GL.DrawArrays(BeginMode.Lines, 0, nAxisVert); GL.EnableClientState(ArrayCap.ColorArray); // _npoints contains the number of points GL.DrawArrays(BeginMode.Points, nAxisVert, _npoints); GL.DisableClientState(ArrayCap.ColorArray); GL.DisableClientState(ArrayCap.VertexArray); glControl31.SwapBuffers();
It seems to work, but doesn't, with the oddest failure. Imagine that you have the correct image, but you cut a narrow strip from the left edge and paste it over on the right. I can draw lines using the same x coordinates, and the lines appear in the correct place. I even modified the grayscale calculation, dropping the blue channel to create a yellow-tinted color, only for the lesser x values, and that strip on the right (ostensibly higher x values) turns yellow. The CSV file is organized such that the x values change faster than the y (i.e. by rows), so it isn't like the first n points are messed up.
I added a clipped inline image. The yellow strip on the right should be on the left. The magenta line is drawn using the same coordinates as the points in the yellow strip; notice the line is in the right place. The blue is my clear color.
It is worse: I can change my CSV file such that y values change faster, and the wrapping moves from the right to the bottom!
I got no ideas what to try. I can send the code for anyone who wants to help.
Addendum: I co-worker suggested that I try immediate mode, and it worked. So something is far wrong with my VBO implementation.
Thanks a lot.