I have a quick question and I’m sure I am just overlooking something, but I have been going around in circles and can’t find a resolution, and would greatly appreciate some assistance from those more experienced with OpenGL than myself.
I’m working on retrofitting a “simple” 2D display program that is written in OpenGL for VisualBasic (.Net 2, not that it matters).
I have no control over how the data commands come in, it is just my job to render them in the 2D window… However the order of some of the commands that come in make it very difficult to process given the normal push/pop transformation scheme.
So here is my conundrum:
The commands that come in can specify to define a “Rotate” transformation at any arbitrary absolute location in the view plane, start drawing content, and then subsequently jump to any other arbitrary location on the plane to draw more content. All content rendered between the “Start Rotate” and “End Rotate” commands need to keep the same base rotation point and angle, however the points that it jumps to are given in the primary view’s coordinate system.
There are occasionally relative translations, but almost all translations are performed by “Move” commands which are absolute references to the primary view’s coordinate system.
Complicating matters is that the prerendered symbology library that it calls to drop the generic symbols on the plane does not have a standard as to where it will leave the cursor after it is done drawing the symbol (again nothing that I have control over). If it was not for this I think I could just keep track of the location by-hand, however every time it draws a symbol it could leave the at any location on the symbol, top, bottom, middle, or anywhere else it happens to stop, and I have no way of tracking those transformations.
So the best way I have come up with (see code snippet below) is to try to transform the absolute translation “move” commands into relative translations based on the current rotation transformation. This way I can keep the rotation transformation pushed on the modelview matrix till the end rotate command pops it back off.
However something is wrong in my code and I just can’t seem to identify where. The move works fine when there is no rotation defined as the coordinate systems overlap each other making the task trivial. However if a rotation is defined it is off by a little bit, and seems to get more and more off as more moves occur until the rotation is removed.
I have been looking at this all weekend and just can’t identify the source of the error, so if anyone can assist it would be a great help!
'Module level variable to track the current rotation, modified only in the "Start Rotate" and "End Rotate" commands. Private mRotateAngle As Single = 0.0 Private Sub GLMoveAbs(ByVal _X As Single, ByVal _Y As Single) 'Early Exit for simple case If mRotateAngle = 0 Then GL.glTranslatef(_X, _Y, 0.0) Return End If 'Cannot pop/push or we will lose the rotation transformation Dim fromPoint As PointF = getCurrentGLPosition() 'Find the vector (direction and magnitude) with which to move to the designated point Dim delta_X As Double = _X - fromPoint.X Dim delta_Y As Double = _Y - fromPoint.Y Dim moveAngleRad As Double = Math.Atan2(delta_Y, delta_X) Dim rotateAngleRad As Double = mRotateAngle * Math.PI / 180 Dim translatedAngleRad As Double = moveAngleRad + rotateAngleRad Dim moveMagnitude As Double = Math.Sqrt((delta_X * delta_X) + (delta_Y * delta_Y)) 'Move along the translated vector GL.glTranslated(moveMagnitude * Math.Cos(translatedAngleRad), moveMagnitude * Math.Sin(translatedAngleRad), 0.0) End Sub Private Function getCurrentGLPosition() As PointF 'Only contains Translations and Rotations along the X/Y plane, which greatly simplifies the computations needed to get the X/Y coordinates from the MVM. Dim modelViewMatrix(15) As Single GL.glGetFloatv(GL.GL_MODELVIEW_MATRIX, modelViewMatrix) getCurrentGLPosition.X = (modelViewMatrix(0) * modelViewMatrix(12)) + (modelViewMatrix(4) * modelViewMatrix(13)) getCurrentGLPosition.Y = (modelViewMatrix(1) * modelViewMatrix(12)) + (modelViewMatrix(5) * modelViewMatrix(13)) End Function