Unexpected flying boxes while trying to render - opengl

So for a quick sample in pictures:
This is normal:
this is after rotating 180 deg on either the X or Y axis:
I don't see why this is happening at all. I'm using OpenTK to render a simple Bullet physics scene. The code is straight forward and it almost seems like there's something wrong in the way the matrix is handled. It's straight-forward render code:
GL.PushMatrix();
GL.MultMatrix(Body.MotionState.WorldTransform.ToArray());
GL.Scale(HalfX * 2, HalfY * 2, HalfZ * 2);
GL.Color4(Color4.Blue);
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 0, 10);
GL.End();
GL.Color4(Color4.Yellow);
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 10, 0);
GL.End();
GL.Color4(Color4.Green);
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(0, 0, 0);
GL.Vertex3(10, 0, 0);
GL.End();
if (Body.ActivationState == ActivationState.ActiveTag)
{
GL.Color4(Color4.Blue);
}
else if (Mass == 0)
{
GL.Color4(Color4.Red);
}
else
{
GL.Color4(Color4.Green);
}
model.Draw();
GL.PopMatrix();
I've tried breaking it down to it's components: the translation vector is fine, scaling is fine, rotating on the Z axis appears fine... it's when you add rotations on the X or Y axis that it starts flying. I have console output going: the box is at exactly 6.9999 on the Z axis in both images.
Where am I going wrong? What am I missing? How do I fix this?!

Okay so... PushAttrib(AttribMask.AllAttribBits); PushMatrix(); in my /TEXTFONT LOADING CODE/ fixed it. Somehow, some weird attribute set in the code that loads fonts to later render made GL.Rotate rotate around (0, 0, 1) instead of (0, 0, 0)... OpenGL sure is temperamental...
So the lesson here is... never assume unrelated code is truly unrelated when dealing with OpenGL.

Related

How to use rotation matrices to move in direction of a camera opengl

I'm tinkering around with opengl and c++ and so far everything has gone pretty smoothly, using glm/glfw/glew however I've run into a bit of a problem when dealing with using the cameras rotation to rotate a movement vector in the direction of the camera for a fly-by camera effect. i.e.
The program receives W + A as inputs so W subtracts 1 to the z component of a direction vector and A adds 1 to the x component.
This produces a direction vector of {1, 0, -1}
example code might be
if (Keyboard::isKeyDown(Key::W)) {
dir += {0, 0, -1};
}
if (Keyboard::isKeyDown(Key::S)) {
dir += {0, 0, 1};
}
if (Keyboard::isKeyDown(Key::A)) {
dir += {1, 0, 0};
}
if (Keyboard::isKeyDown(Key::D)) {
dir += {-1. 0, 0};
}
Then the output is normalised to produce a constant movement speed no matter which direction, now this works fine if the camera is pointed perfectly in the "forward" direction, i can make this code work by calculating forward and right vectors and using this instead of the unit movement lengths, however i find this code not very ellegant and would like to use some sort of function to rotate the movement vector in the direction of the camera in 3d space so you can look up and fly up, I'm using the rotation vector of the camera to calculate the rotation matrix and using this, how this seems to calculate everything weirdly inverted and moving in the wrong direction but relative to the camera?
So calculated every frame is:
m_rotationMatrix = glm::identity<glm::mat4>();
Maths::rotateMatrix(m_rotationMatrix, m_rotation);
using the rotateMatrix method defined here:
void rotateMatrix(glm::mat4& matrix, const glm::vec3& degrees){
matrix = glm::rotate(matrix, glm::radians(degrees.x), { 1, 0, 0 });
matrix = glm::rotate(matrix, glm::radians(degrees.y), { 0, 1, 0 });
matrix = glm::rotate(matrix, glm::radians(degrees.z), { 0, 0, 1 });
}
then in the movement code it's used like so:
m_camera->translate(m_camera->transformDirection(dir) * deltaTime * movementSpeed);
using the transformDirection method defined in the camera as:
glm::vec3 Camera::transformDirection(glm::vec3 vec){
glm::vec4 inputAsVec4 = glm::vec4(vec.x, vec.y, vec.z, 1.0);
glm::vec4 result = m_rotationMatrix * inputAsVec4;
return { result.x, result.y, result.z };
}
I'm pretty new to OpenGL and relatively new to c++ also, so is there anything I'm missing/doing wrong to cause this behavior?

2D Coordinate Confusion

Alright, so I have never created a game before, and I am trying to make a 2d tile based game.
So I am really confused about something that should be pretty simple, coordinates.
I have tile coordinates, like
{0,0,0,0,0,1}
{0,0,1,0,0,1}
{0,0,0,0,0,1}
{0,0,1,1,1,1}
{0,0,0,0,0,1}
lets say this is my world and i am trying to render it, well i cant render it, each tile needs a width,
this is where i get confused, so you can do, im not new to coding
twidth = 100, theight = 100;
for(y = each row) {
for(x = each tile in each row) {
draw rect (
X1 = x*twidth,
Y1 = y*theight,
X2 = x*twidth+twidth,
X2 = y*theight+theight
)
}
}
I might be wrong about this, but: now literally everything else needs to multiplied by the twidth/height, it will be even harder if you want different sized tiles, at least its confusing to me, how do other games handle things like this? im not sure if i explained very well what my problem is, any help would be appreciated
im using opengl[legacy] and i think the solution might be a function to setup screenspace differently, so rendering
glVertex2d(0,1) is actually 100px, this would make collisions, and such, much easier
im using opengl[legacy] and i think the solution might be a function to setup screenspace differently, so rendering glVertex2d(0,1) is actually 100px, this would make collisions, and such, much easier
You can achieve that in legacy OpenGL by setting up the projection matrix properly:
glMatrixMode(GL_PROJECTION);
glOrtho(0, 16, 0, 9, -1, 1);
This will set it up so that glVertex2d(0, 0) maps to the bottom left corner and glVertex2d(16, 9) will map to the top right corner, giving you 16x9 tiles in the viewport. To fix the size of the tile in pixels we calculate the fractional number of tiles instead:
glOrtho(0, (double)viewportWidth / twidth, 0, (double)viewportHeight / theight, -1, 1);
After that you can 'scroll' the world by translating it through the GL_MODELVIEW matrix.

Allegro 5 - creating a custom bitmap with alpha channel

Afternoon everyone,
I was wondering if there's any way I could create a custom bitmap with alpha channel
bitmap = al_create_bitmap(30, 30);
al_set_target_bitmap(bitmap);
al_clear_to_color(al_map_rgb(255,255,255));
....
al_draw_tinted_bitmap(bitmap, al_map_rgba(0, 0, 0, 0.5), X, Y, 0);
I'm sure that I'm either not creating or drawing the bitmap correctly, so I could really use some advice.
Thanks in advance,
Alex
The only thing wrong with your code snippet is:
al_map_rgba(0, 0, 0, 0.5)
should be:
al_map_rgba_f(0, 0, 0, 0.5)
The former range is an integer from 0 to 255.
Also, keep in mind that Allegro's default blender is pre-multiplied alpha. So if you wanted to tint red at 50%, you'd use:
float a = 0.5;
... al_map_rgba_f(1.0 * a, 0.0 * a, 0.0 * a, a) ...
If you're not thinking about it, you're probably assuming it's interpolating. i.e., the more intuitive blender for most people seems to be:
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA)
but that is not the default for the reasons mentioned in the above link.
after I set the
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
it allowed me to draw my "bouncer" bitmap and change its alpha channel using the below function:
al_draw_tinted_bitmap(bouncer, al_map_rgba_f(1, 1, 1, alpha) 40, 0, 0);
This previously did not work , so I guess adding the al_set_blender solved the "mistery".
Thanks for all your help.

OpenGL glViewport() (resetting coordinates)

I have a problem with glViewport. In my liitle programm i have two viewports. I can draw a form (with the motionfunc) in one of those viewports and in the other a line is automatically drawn.
So far so good..
When i try to draw something with mousefunc the viewport is in a total different place. And it is very difficult to find the new correct coordinates for that viewport.
Is there a possibility to reset the coordinates..
I cant use glLoadIdentity in mouse or motion because then nothing is displayed.
I hope you understand what i mean. It is a bit difficult to explain.
OK here a codesnippet....
void mouse (int button, int state, int mx, int my)
{
if (modus == 0 && button==GLUT_LEFT_BUTTON && state != GLUT_DOWN)
{
...
}
else if (modus == 1 && button==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
**glViewport(10,10 , sw_w1, sw_h1);**
//the drawing is much higher than in the first viewport in motion.
//But it should be the same viewport like the first in motion.
glBegin()...glEnd()
glFlush();
}
}
void motion(int mousex,int mousey)
{
GLdouble h=12;
GLdouble winkel=360/h;
Line liste[num];
liste[++last].x =(mousex)-((sw_w1+2*GAP)/2);
liste[last].y =(mousey)-((sw_h1+2*GAP)/2);
if (modus==0 && gruppe == 0) {
if (last>=1)
{
glViewport(10, 10, sw_w1, sw_h1); //works fine
glColor3d(R, G, B);
for(h+1;h>0;h--){
glRotated(winkel, 0, 0, 1);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
}
glLineWidth(linewidth+0.5);
glColor3f(1, 0, 0);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
glViewport(1020,10 , sw_w2, sw_h2); //works fine
glColor3f(1, 0, 0);
glBegin(GL_LINE_STRIP);
for(int i=last-1;i<=last;i++){
glVertex2i(liste[i].x,liste[i].y);
}
glEnd();
}
glFlush();
}
}
The second and third viewport works fine. The first one is the same as the second but the picture is displayed much higher.Why is that so?
And how could i change it so that i get the same viewport like the second one.
I hope you now understand what i mean.
You should check your modelview/projection matrices and see if they are what you expect them to be in each function.
Also, as Christian's commented, it is not necessary, nor recommended, to draw in the motion func. Update your application state per the input and call glutPostRedisplay to signal that you want to redraw your window. That way, your application will have a cleaner design and it will be easier to make it behave consistently.
(added my comment as answer since that was the problem, and added Christian's comment, since that is the proper solution. Don't draw in motionfunc!.)

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.