PDA

View Full Version : 2D Absolute Move without push/pop



LostInTheCode
08-23-2010, 08:07 PM
Greetings all,
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!

Thanks! ~Lost




'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

LostInTheCode
08-24-2010, 10:18 AM
No one wants to take a stab at it? Or just that everyone despises VB so much that they donít want to look at the code? ;)

Dark Photon
08-24-2010, 04:37 PM
No one wants to take a stab at it? Or just that everyone despises VB so much that they donít want to look at the code? ;)
It's not just that. You didn't clearly articulate the problem (maybe I just missed it?).

You make it clear that your trudging through existing code that does some transformations, but it's not really clear why you're trying to change the way it works, or why you have the constraints you do.

So if anybody else is like me, the result of reading the first message was a head shake and shoulder shrug, followed by "Next Post".

...and then there's the BASIC thing... ;) Didn't we ditch that thing a few decades back along with COBOL? (I'm blocking out having helped my wife write some VB macros in Excel 6 years ago).

mhagain
08-24-2010, 05:23 PM
Try using the -f versions of functions instead of the -d versions (and of course Singles instead of Doubles) - most (all?) current GPUs use single precision FP internally so there's nothing/nada/nowt/sfa to be had from using doubles (pathological worst case is that they may even send you through software emulation).

I don't really know VB, but is your modelview matrix also one short?

If they don't fix it, you likely have an error in your transformation algorithm somewhere. To be honest I'm totally failing to see why you're not using glRotatef instead of what seems like something horribly complex and fragile.