'linmath.h': Rotation after translation problem - c

Using 'linmath.h', I'm trying to rotate an image after a translation. However, after the translation, the image doesn't move at all.
In the vextex shader, I have
gl_Position = transform * vec4(aPos, 1.0);
and in the program, I have
mat4x4 transform;
mat4x4_identity(transform);
mat4x4_rotate(transform, transform, 0.0f, 0.0f, 1.0f, (float) glfwGetTime());
mat4x4_translate(transform, 0.5f, -0.5f, 0.0f);
I want to point out that translating an image after a rotation (i.e., swapping the last two lines) works fine, so I don't know what could be wrong.

If you take a peek at the source for mat4x4_translate, you can see it resets the matrix to identity first.
You might be looking for the next function, mat4x4_translate_in_place.

Related

Moving the camera to the left and right based on mouse movement

I know this has been asked before, but I have yet to find an answer that works in my case.
Basically, I want the camera to move left and right based on the mouse cursor position. The more the mouse is to the left, the more the camera turns to the left. So it should be possible to turn around and move in the reverse direction. How do I do this?
This is my camera position:
GLfloat cameraPosition[] = { 0.0, 0.0, 3.5 };
GLfloat lx = 0.0; GLfloat ly = 0.0;
This is my projection matrix:
// set to projection mode
glMatrixMode(GL_PROJECTION);
// clear any previous transformations
glLoadIdentity();
// set the perspective
gluPerspective(45, (float)windowWidth / (float)windowHeight, 0.1, 20);
In the myDisplay function, this how I set the camera position:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// set the camera position
gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2],
lx, ly, cameraPosition[2] - 100,
0, 1, 0);
What should I do in the glutPassiveMotionFunc function?
Most probably you need to do something like this
glRotatef(-yAngle, 0.0f, 1.0, 0.0f);
glRotatef(-xAngle, 1.0f, 0.0f, 0.0f);
glTranslatef(cameraPosition[0], cameraPosition[1], cameraPosition[2])
instead of gluLookAt(). Try it out, maybe it will solve your problem.

how to use glTranslatef,glScalef,glRotatef in openGL

I just want something like this video : https://youtu.be/dGWtdYlryQQ
It shows how to use glTranslate, glRotate, gluOrtho2d in OpenGL ,but it's not guide me anything
In my case, I draw a diamond instead of triangle and here is my condition
condition :
when I press r or R on the keyboard the diamond will rotate clockwise
when I press t or T on the keyboard the diamond will move to the right side
when I press + on the keyboard the diamond will bigger
here is my code :
#include <stdlib.h>
#include <windows.h>
#include <GL/glut.h>
#include <iostream>
using namespace std;
float angle = 0;
float t,s=0.5,m=0;
void myinit(void){
glClearColor(1.0,1.0,1.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
}
void keyboard(unsigned char key, int x, int y){
if(key==27)
{
exit(0);
}else if(key == 82 || key == 114){
angle-=0.1;
glRotatef(angle,0,0,1);
glutPostRedisplay();
}else if(key == 84 || key == 116 )
{
t+=0.01;
glTranslatef(t,0,0);
glutPostRedisplay();
}else if(key == 43){
s+=0.01;
// m-=0.1;
// glTranslatef(m,m,0.0);
glScalef(s,s,0);
glutPostRedisplay();
}
(void)(x);
(void)(y);
}
void hut(void){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.5,0.4,0.0);
glVertex3f(0.42,0.5,0.0); // GREEN
glVertex3f(0.44,0.5,0.0);
glColor3f(1.5,1.0,0.0);
glVertex3f(0.46,0.5,0.0);
glColor3f(0.25,0.0,0.0);
glVertex3f(0.57,0.5,0.0);
glEnd();
glFlush();
glColor3f(1.5,1.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.44,0.55,0.0);
glVertex3f(0.42,0.5,0.0);
glVertex3f(0.46,0.5,0.0);
glColor3f(0.25,0.0,0.0);
glVertex3f(0.48,0.55,0.0);
glEnd();
glColor3f(1.5,1.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.48,0.55,0.0);
glVertex3f(0.46,0.5,0.0);
glVertex3f(0.50,0.5,0.0);
glColor3f(0.25,0.0,0.0);
glVertex3f(0.52,0.55,0.0);
glEnd();
glColor3f(1.5,1.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.52,0.55,0.0);
glVertex3f(0.50,0.5,0.0);
glVertex3f(0.54,0.5,0.0);
glColor3f(0.25,0.0,0.0);
glVertex3f(0.56,0.55,0.0);
glEnd();
glColor3f(1.5,1.0,0.0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.56,0.55,0.0);
glVertex3f(0.54,0.5,0.0);
glVertex3f(0.57,0.5,0.0);
glEnd();
glFlush();
}
int main(int argc,char** argv){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,480);
glutCreateWindow("Polygon with viewport");
myinit();
glutDisplayFunc(hut);
glutKeyboardFunc(keyboard);
glutMainLoop();
}
And here is my output : https://drive.google.com/file/d/14HHRiCbOHK9ZSZtDOqSl4GP4aSy7UQLh/view?usp=sharing
It it’s not similar to this https://youtu.be/dGWtdYlryQQ
The operations on the matrix stack are based on one another. The reference system of each operation is the current transformation.
See the documentation of glTranslate:
glTranslate produces a translation by x y z . The current matrix (see glMatrixMode) is multiplied by this translation matrix, with the product replacing the current matrix, [...]
and see the documentation of glRotate:
glRotate produces a rotation of angle degrees around the vector x y z . The current matrix (see glMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix.
This means that glRotate does a rotation around the origin of the current local system.
While glRotatetf followed by glTranslatef results in:
glTranslatef followed by glRotatef results in:
Since you object is displaced, you have to translate it in that way, that the rotation point is placed in the origin:
glTranslatef(-0.5f, -0.5f, 0.0f);
Then you can rotate it:
glRotatef(angle, 0.0f, 0.0f, 1.0f);
And move it back:
glTranslatef(0.5f, 0.5f, 0.0f);
Note, on the Fixed Function Pipeline stack you have to "push" this operations in the reverse order. Further you should use the GL_MODELVIEW matrix stack. (See glMatrixMode.)
Remove all the matrix operations from the function keyboard and add the following to the function hut:
void hut(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(t, 0.0f, 0.0f);
glTranslatef(0.5f, 0.5f, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glScalef(s, s, 0.0f);
glTranslatef(-0.5f, -0.5f, 0.0f);
.....
Further, your object gets destroyed by the aspect ratio of the view. This can be fixed by taking care of the aspect ratio when setting up the projection matrix:
float w = 640.0f;
float h = 480.0f;
glOrtho(0.0,w/h,0.0,1.0,-1.0,1.0);
glRotate rotates about the origin (0,0). Given your projection matrix (that you set with glOrtho) the origin is initially at the lower left corner of your screen, unless you use glTranslate. Your diamond is not centered at the origin, but positioned somewhat away from it. What you need to do is change the vertex values in your void hut(void) method to make the diamond centered at 0,0. Then use glTranslate to move the render origin (and thus also the diamond) to where you want it, then use glRotate.

OpenGL - Rotating moon around sun without it spinning?

I'm working on a graphics model of the Moon rotating around the Earth. Right now, the Moon spins on its y axis while rotating around the Earth. How can I prevent the Moon from spinning but still allow it to orbit? Here's the code..
Edit:
Added an animation video to demonstrate problem:
http://www.youtube.com/watch?v=ltGV4pXD5Cs
void DrawInhabitants(GLint nShadow)
{
static GLfloat yRot = 0.0f; // Rotation angle for animation
if(nShadow == 0)
{
yRot += 0.2f;
}
// Draw the randomly located spheres
glBindTexture(GL_TEXTURE_2D, textureObjects[MOON_TEXTURE]);
glPushMatrix();
glTranslatef(0.0f, 0.1f, -2.5f);
glPushMatrix();
glRotatef(-yRot * 2.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(1.0f, 0.0f, 0.0f);
gltDrawSphere(0.1f,21, 11);
glPopMatrix();
if(nShadow == 0)
{
// Torus alone will be specular
glMaterialfv(GL_FRONT, GL_SPECULAR, fBrightLight);
}
glRotatef(-yRot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, textureObjects[EARTH_TEXTURE]);
gltDrawSphere(0.3f, 21, 11);
glMaterialfv(GL_FRONT, GL_SPECULAR, fNoLight);
glPopMatrix();
}
The problem is that you're rotating the coordinate system in order to place the moon in its desired relative position. This rotation is global so it affects the orientation of the moon as well. You need to undo the rotation after translating, so you have "translation sandwich"
rotate a
translate
rotate -a

Why is my arrow drawing the wrong way?

I have this code to draw an arrow:
const GLfloat vertices[] = {
-0.25f, -0.25f,
0.0f, 0.0f,
0.25f, -0.25f,
0.0f, 0.5f,
};
glVertexPointer(2, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(0.0f, 0.5f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
It should draw similar to this:
This is the actual result (which is undesired):
I don't see what I have done wrong, the vertices seem correct to me, but it seems like OpenGL draws the polygon in a different order than I specified. Can anyone help me out? Thanks in advance. :)
Your triangle strip takes the lower three points first (i.e. the lower part of your green arrow) and then the right three points. Just change the order of points in your definition:
const GLfloat vertices[] = {
-0.25f, -0.25f,
0.0f, 0.0f,
0.0f, 0.5f,
0.25f, -0.25f,
};

How to fill polygon with different color than boundary?

I need to draw a polygon that has the boundary lines with one color and fill the interior with another color. Is there an easy way to do this ? I currently draw two polygons one for the interior color and 1 for the boundary. I think there must be a better to do this. Thanks for your help.
glColor3d (1, 1., .7);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_TRIANGLES);
glVertex3f(-0.8f, 0.0f, 0.0f);
glVertex3f(-0.6f, 0.0f, 0.0f);
glVertex3f(-0.7f, 0.2f, 0.0f);
glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3d (.5, .5, .7);
glBegin(GL_TRIANGLES);
glVertex3f(-0.8f, 0.0f, 0.0f);
glVertex3f(-0.6f, 0.0f, 0.0f);
glVertex3f(-0.7f, 0.2f, 0.0f);
glEnd();
Thank you everyone for answering my question. I am fairly new to openGL and was looking for a simple answer to a simple question. The answer appears to be not so simple and probably can take a semester worth of study.
A more modern approach would be to implement this via geometry shaders. This would work for OpenGL 3.2 and above as part of the core functionality, or for OpenGL 2.1 with extension GL_EXT_geometry_shader4.
This paper has all the relevant theory : Shader-Based wireframe drawing. It also provides a sample implementation of the simplest technique in GLSL.
Here is my own stab at it, basically a port of their implementation for OpenGL 3.3, limited to triangle primitives:
Vertex shader: (replace the inputs with whatever you use to pass in vertex data an m, v and p matrices)
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in mat4 mv;
out Data
{
vec4 position;
} vdata;
uniform mat4 projection;
void main()
{
vdata.position = projection * mv * position;
}
Geometry shader:
#version 330
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in Data
{
vec4 position;
} vdata[3];
out Data
{
noperspective out vec3 dist;
} gdata;
void main()
{
vec2 scale = vec2(500.0f, 500.0f); // scaling factor to make 'd' in frag shader big enough to show something
vec2 p0 = scale * vdata[0].position.xy/vdata[0].position.w;
vec2 p1 = scale * vdata[1].position.xy/vdata[1].position.w;
vec2 p2 = scale * vdata[2].position.xy/vdata[2].position.w;
vec2 v0 = p2-p1;
vec2 v1 = p2-p0;
vec2 v2 = p1-p0;
float area = abs(v1.x*v2.y - v1.y*v2.x);
gdata.dist = vec3(area/length(v0),0,0);
gl_Position = vdata[0].position;
EmitVertex();
gdata.dist = vec3(0,area/length(v1),0);
gl_Position = vdata[1].position;
EmitVertex();
gdata.dist = vec3(0,0,area/length(v2));
gl_Position = vdata[2].position;
EmitVertex();
EndPrimitive();
}
Vertex shader: (replace the colors with whatever you needed !)
#version 330
in Data
{
noperspective in vec3 dist;
} gdata;
out vec4 outputColor;
uniform sampler2D tex;
const vec4 wireframeColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
const vec4 fillColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
void main()
{
float d = min(gdata.dist.x, min(gdata.dist.y, gdata.dist.z));
float I = exp2(-2*d*d);
outputColor = mix(fillColor, wireframeColor, I);
}
You can switch the fill mode between polygons, lines and points, using glPolygonMode.
In order to draw polygon lines in a different color you can do the following:
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
draw_mesh( fill_color );
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glEnable(GL_POLYGON_OFFSET_LINE);
glPolygonOffset(-1.f,-1.f);
draw_mesh( line_color );
Line offset may be needed, because OpenGL doesn't guarantee the edges of polygons will be rasterized in the exact same pixels as the lines. So, without explicit offset you may and up with lines being hidden by polygons, due to failed depth test.
There are 2 ways to do this:
the one you do at the moment (2 polygons, one a little larger than the other or drawn after)
texture
to my knowledge there are no other possibilities and from a performance standpoint these 2 possibilities, especially the first one as long as you only color-fill, are extremely fast.
I think you should see this answer:
fill and outline
first draw your triangle using
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL) and use your desired color.
then draw the triangle again using
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE) using your outline color.

Resources