OpenGL Rotate something that has been popped off matrix - opengl

I have a question about applying transformations to textures/vertices (I'm an OpenGL learner). I've got a situation where I'm using SharpGL's DrawText function. You can specify the X and Y coordinate but I want to rotate the text so that it's oriented vertically. The function doesn't take an angle though. The way that SharpGL writes text is that it gets an array of bitmaps that it writes to the screen.
No matter what I try, my text always comes out horizontal.
The gl.DrawText function does the following (I dug into the source code).
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.PushMatrix();
gl.LoadIdentity();
int[] viewport = new int[4];
gl.GetInteger(OpenGL.GL_VIEWPORT, viewport);
gl.Ortho(0, width, 0, height, -1, 1);
// Create the appropriate modelview matrix.
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.PushMatrix();
gl.LoadIdentity();
gl.Color(r, g, b);
gl.RasterPos(x, y);
gl.PushAttrib(OpenGL.GL_LIST_BIT | OpenGL.GL_CURRENT_BIT |
OpenGL.GL_ENABLE_BIT | OpenGL.GL_TRANSFORM_BIT);
gl.Color(r, g, b);
gl.Disable(OpenGL.GL_LIGHTING);
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.Disable(OpenGL.GL_DEPTH_TEST);
gl.RasterPos(x, y);
// Set the list base.
gl.ListBase(fontBitmapEntry.ListBase);
// Create an array of lists for the glyphs.
var lists = text.Select(c => (byte) c).ToArray();
// Call the lists for the string.
gl.CallLists(lists.Length, lists);
gl.Flush();
Is there a way that I can make transformation calls apply to any drawing that has already been made and had the associated matrices popped off?

If SharpGL is using glBitmap() behind the scenes you'll have to render the text to a texture (glReadPixels()/PBO/FBO) then render a (rotated) quad with that texture.

Related

OpenGL. Window-To-Viewport Transformation

I'm new to OpenGL. Hence I require some assistance in the matter described below. I'm not sure how to produce viewport coordinates with respect to screen coordinates as well as producing it in c++ since I used to deal with Java.
In this question I need to implement the function worldToViewportTransform.
The function implements a 2D orthographic projection matrix, which is used for the (world)window-to-viewport transformation. In OpenGL this matrix is defined by gluOrtho2D.
Input are the coordinates of the world-window (winLeft, winRight, winBottom, winTop), the top-left corner of the viewport (window) on the screen (windowX, windowY), and the size of the viewport (window) on the screen (windowWidth, windowHeight).
Output are the values A, B, C and D which constitute the world-to-viewport transformation.
The answer needs to use the function format below - copy it and fill out the missing code. The function uses pointer variables for the values A, B, C and D since Coderunner does not seem to accept C++ notation - the code segment below converts the pointer variables to double values and back, so you don't need to understand how pointers work.
void worldToViewportTransform (double winLeft, double winRight, double winBottom, double winTop,
int windowX, int windowY, int windowWidth, int windowHeight,
double* APtr, double* BPtr, double* CPtr, double* DPtr)
{
double A=*APtr, B=*BPtr, C=*CPtr, D=*DPtr;
<INSERT YOUR CODE HERE>
*APtr=A; *BPtr=B; *CPtr=C; *DPtr=D;
}
Particular Test case should produces the output:(u,v)=(-200,367)
//Code for Testing
double A, B, C, D;
double winLeft=1.5, winRight=4.5, winBottom=0.0, winTop=3.0;
int windowX=100, windowY=100, windowWidth=600, windowHeight=400;
worldToViewportTransform(winLeft, winRight, winBottom, winTop,
windowX, windowY, windowWidth, windowHeight,
&A, &B, &C, &D);
// Test cases
double x, y; // world coordinates
int u, v; // window coordinates
x=0.0f; y=1.0f;
u=(int) floor(A*x+C+0.5f);
v=(int) floor(B*y+D+0.5f);
printf("(u,v)=(%d,%d)",u,v);
The function implements a 2D orthographic projection matrix, which is used for the (world)window-to-viewport transformation. In OpenGL this matrix is defined by gluOrtho2D.
No! gluOrtho2D/glOrtho is not doing that. These functions setup a orthographic projection matrix, which purpose is to transform from view-space into clip-space.
Then an implicit clip-space to NDC-space transform happens behind the scenes.
Finally the NDC-space coordinates are transformed to window coordinates in the viewport range.
Input are the coordinates of the world-window (winLeft, winRight, winBottom, winTop), the top-left corner of the viewport (window) on the screen (windowX, windowY), and the size of the viewport (window) on the screen (windowWidth, windowHeight).
Your nomenclature seems a little bit off.
The usual convention is that the viewport defines the target rectangle within the window, specified in window-relative coordinates. In OpenGL the window coordinate (0,0) being the lower-left corner of the window.
Window coordinates are usually relative to its parent window; hence for top-level window relative to the screen coordinates. In usual screen coordinate systems (0,0) is the upper-left.
Output are the values A, B, C and D which constitute the world-to-viewport transformation.
It's unclear what you actually want, but my best educated guess is, that you want to recreate the OpenGL transformation chain. Of course if you're using shaders, everything could be done in there. But in practice you'll probably just want to follow the chain
r_clip = P · M · r_in
r_NDC = r_clip/r_clip.w
r_viewport = (r_NDC.xy + 1)*viewport.width_height/2 + viewport.xy
where P is your projection matrix, for example the matrix produced by glOrtho.

Object orientation within an opengl scene

I'm having difficulty getting the right orientation from my objects within a scene. The objects are defined in standard Cartesian coordinates in the same units as I define the scene.
I then define my scenes matrix with the following code:
void SVIS_SetLookAt (double eyePos[3], double center[3], double up[3])
{
// Determine the new n
double vN[3] = {eyePos[0] - center[0], eyePos[1] - center[1], eyePos[2] - center[2]};
// Don't I need to normalize the above?
// Determine the new up by crossing witht he Up Vector.
double vU[3];
MATH_crossproduct(up, vN, vU);
MATH_NormalizeVector(vN);
MATH_NormalizeVector(vU);
// Determine V by crossing n and u...
double vV[3];
MATH_crossproduct(vN, vU, vV);
MATH_NormalizeVector(vV);
// Create the model view matrix.
double modelView[16] = {
vU[0], vV[0], vN[0], 0,
vU[1], vV[1], vN[1], 0,
vU[2], vV[2], vN[2], 0,
// -MATH_Dotd(eyePos, vU), -MATH_Dotd(eyePos, vV), -MATH_Dotd(eyePos, vN), 1
0, 0, 0, 1
};
// Load the modelview matrix. The model view matrix shoudl already be active.
glLoadMatrixd(modelView);
}
I am attempting to display n-1 objects such that each object is facing the object in front of it, excluding the first object which is not displayed. So for each object, I define the up, right, and forward vectors as such:
lal_to_ecef(curcen, pHits->u); // up vector is our position normalized
MATH_subtractVec3D((SVN_VEC3D*) prevcenter, (SVN_VEC3D*) curcen, (SVN_VEC3D*) pHits->f);
MATH_NormalizeVector(pHits->u);
MATH_NormalizeVector(pHits->f);
MATH_crossproduct(pHits->u, pHits->f, pHits->r);
MATH_NormalizeVector(pHits->r);
MATH_crossproduct(pHits->f, pHits->r, pHits->u);
MATH_NormalizeVector(pHits->u);
I then go on to display each object with the following code:
double p[3] = {pHits->cen[0] - position[0],
pHits->cen[1] - position[1],
pHits->cen[2] - position[2]};
glPushMatrix();
SVIS_LookAt(pHits->u, pHits->f, pHits->r, p);
glCallList(G_svisHitsListId);
glPopMatrix();
void SVIS_LookAt (double u[3], double f[3], double l[3], double pos[3])
{
double model[16] = {
l[0], u[0], f[0], 0,
l[1], u[1], f[1], 0,
l[2], u[2], f[2], 0,
pos[0], pos[1], pos[2], 1
};
glMultMatrixd(model);
}
I would expect this to work for any object such that the output would be whatever was defined in the Cartesian coordinate system would be present at the given point oriented such that it was pointed at the proceeding object with 0,1,0 and 0,-1,0 from the defined object would be aligned vertically on the screen. What I am seeing instead (by using simple rectangle as the object to be displayed) is that the objects are consistently rotated about the forward axis.
Can anyone point out what I am doing wrong here?
[Edit]
I've displayed an axis grid without translating by taking the three vectors multiplying a scalar and adding/subtracting it to the centre point. Doing this, the axis align up as I would expect. Overlaying the object described above shows the object to not be aligned the same way. Is there a relationship between the object space forward, right, and up vectors and the desired world-space vectors that I am missing? Am I simply completely off the mark with regards to my rotation translation matrix?
You are conflicted here; part of that matrix is transposed and part of
it is correct... you have the 4th column correct but your top-left 3x3
matrix is transposed. Each column of the 3x3 matrix (row in that array
of 16 double) is supposed to be one of your axes. It should be:
l[0],l[1],l[2],0, u[0],u[1],u[2],0, f[0],f[1],f[2],0,
pos[0],pos[1],pos[2],1. – Andon M. Coleman
This was dead on. Thanks Andon.
Building an entirely new modelview matrix from scratch using a 'lookat' implementation for each object is, frankly, crazy (or will at least drive you crazy). What you're doing is tantamount to trying to build a scene by having set of objects which are always in a fixed location, and constantly repositioning a camera to catch them from different angles.
A lookat style function should be called once to set up the camera (the view portion of the modelview matrix) position, and subsequently you should be using the matrix stack to position objects within the scene (the model portion of the modelview matrix). That's why it's called the modelview matrix, and not just the view matrix.
In code terms, it would look something like this
// Set up camera position
SVIS_LookAt(....);
for (int i = 0; i < n; ++i) {
glPushMatrix();
// move the object to it's location relative to the world coordinate system
glTranslate(...);
// rotate the object to have the correct orientation
glRotate(...);
// render the geometry
glCallList(...);
glPopMatrix();
}
Of course this assumes that everything has it's position defined in world coordinates. If you have a hierarchy of objects, then you would need to descend into an objects children between the glCallList and glPopMatrix in order to have their locations applied relative to their parent object.

OpenGL Vertex Array, Matrix Pointer?

I wrote a piece of code a year back for rendering editable 2D Shapes using C# + OpenTK. Each shape has its own vertices and editing the Shape directly changes the vertex values.
I have a CollectVertices() in the display_callback_func which iterates all the Shapes and combine the vertex information in big arrays and draw them at once using the snippet below:
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.ColorArray);
// draw fills (triangles)
GL.ColorPointer<byte>(3, ColorPointerType.UnsignedByte, 0, fillColor);
GL.VertexPointer<double>(2, VertexPointerType.Double, 0, fillArray);
GL.DrawArrays(BeginMode.Triangles, 0, fillArray.Length / 2);
// draw lines
GL.ColorPointer<byte>(3, ColorPointerType.UnsignedByte, 0, lineColor);
GL.VertexPointer<double>(2, VertexPointerType.Double, 0, lineArray);
GL.DrawArrays(BeginMode.Lines, 0, lineArray.Length / 2);
GL.DisableClientState(ArrayCap.ColorArray);
GL.DisableClientState(ArrayCap.VertexArray);
One year later today, I want to introduce a new struct Transform to the Shape object. It will contain a Vector2 Center and Matrix Orientation. Editing the Shape now will change values in Transform instead (although scaling will still be done on vertex data, as it should logically be so).
What is a neat way, with minimal changes to the above snippet, to include the transformation matrix?

Not updating coordinate positions?

I have managed to rotate a rectangle in OpenGL (C++) just fine. I am making a program that tests two rectangles for collision using the "separated axis theorem". To use the theorem, I need the x and y coordinates of each corner of the rectangle, but my problem is that, although I call glRotatef(...), the coordinates of the corners of the rectangle are not changed to the values that they are rotated too, but the rectangle rotates as it should. How can I update the coordinates of my rectangle after glRotatef is called?
Code:
// float r1.x[4] and r1.y[4] hold the x and y position of each of the 4 corners, starting with the upper left (r1.x[0], r1.y[0])
glLoadIdentity();
glTranslatef((r1.x[0] + r1.x[2]) / 2, (r1.y[1] + r1.y[3]) / 2, 0); // Translates matrix to center of rectangle
glRotatef(r1.angle, 0, 0, 1);
glTranslatef(-((r1.x[0] + r1.x[2]) / 2), -((r1.y[1] + r1.y[3]) / 2), 0); // Translates back
r1.angle++;
glBegin(GL_QUADS);
glVertex2f(r1.x[0], r1.y[0]);
glVertex2f(r1.x[1], r1.y[1]);
glVertex2f(r1.x[2], r1.y[2]);
glVertex2f(r1.x[3], r1.y[3]);
glEnd();
Transformation calls in OpenGL (like glTranslatef and glRotatef) update an internal transformation matrix that get multiplied by the points you provide before getting drawn on the screen. OpenGL does not at all touch your data.
In general, that is what you want. You have a model that is constant in time, but it gets transformed around.
If however, you do need to update your data, you need to create your own transformation matrix, manually multiply it and then draw with a clean transformation matrix (with glLoadIdentity)
You could get a little help from OpenGL though, as you can get the transformation matrix from OpenGL, but I don't recommend this. The math is not that hard and you'd appreciate learning how to do it.

OpenGL flip or mirror the drawing object

How can i flip, ot mirror up/left of the image OBJECT, not the screen in the onDraw method?
I tried scale(1, -1, 1) that not worked
my code:
opengl.selectVertex(vertexname)
.translate(x-1, y, -9);
if (opengl.getPathModifier(vertexname).getAngle()>-180 &&
opengl.getPathModifier(vertexname).getAngle()<0 ) {
opengl.selectVertex(vertexname).scale(-scale,scale,1);
} else {
opengl.selectVertex(vertexname).scale(scale,scale,1);
}
opengl.rotate(opengl.getPathModifier(vertexname).getAngle()+90, 0, 0, 1);
Not 100% sure what you're asking here, but I think what you want to do is transform the projection matrix. If you want to flip so that things on the left appear on the right then you need to Scale the projection matrix by (-1, 1, 1). If you want things at the top to appear at the bottom you need to scale by (1,-1, 1) and if you want both you can scale (-1, -1, 1).
Edit based on extra information: If all you want to do is display the object exactly the same, but with texture flipped, you need to change the texture coordinates of the vertices in the objects - flip the texture coordinates by replacing the old u texture coordinate with 1-u.
If you are using glFrustum(l,r,b,t,n,f) then change it yo glFrustum(l,r,t,b,n,f), in case you want a vertical flip. This apply also to glOrtho function.