rotate shape become rotate and translating - c

I'm new on using openGL, and now I'm trying to rotate the square i made, but when I rotate it, the square doesn't only rotate, but also moving around while rotating. I think I made a mistake on the rotate and translate process, but cannot find the the solution
void drawSquare(double x,double y, int num)
{
double xLength = 0.6;
double yLength = 0.6;
for(int i=0;i<num;i++)
{
glLoadIdentity();
glPushMatrix();
glTranslatef(0, 0, 0.0f);
glRotatef(angleCW, 0.0f, 0.0f,1.0f);
glBegin( GL_QUADS );
if(i%2==0)
{
glColor3f(gCurrentRed,gCurrentGreen,gCurrentBlue);
}
else
{
glColor3f(0.0f,0.0f,0.0f);
}
glVertex3f(x,y,0);
glVertex3f(x+xLength,y,0);
glVertex3f(x+xLength,y+yLength,0);
glVertex3f(x,y+yLength,0);
xLength -=0.1;
yLength -=0.1;
x += 0.05;
y += 0.05;
glEnd();
glPopMatrix();
}
}

Your quads are going to rotate around the origin (0,0,0). If that's not in the middle of your quads then it is going to look like it is translating too. Maybe you can translate it so the quads a centered, rotate it, and then translate it back
Edit:
See #datenwolf's comment for an example where he:
creates the quad with 0,0,0 as the center
rotates the quad
translates the quad to its position

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.

Using gluLookAt() correctly?

I am trying to set the angle of View with gluLookAt()
Here I have my code where I tried to set the camera without results
Here the function displaycone():
void displayCone(void)
{
glMatrixMode(GL_MODELVIEW);
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// clear the identity matrix.
glLoadIdentity();
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
gluLookAt(3,3,3,0,0,-4.5,0,1,0);
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
With my main:
int main (int argc, char **argv)
{
glutInit(&argc, argv);
//double buffering used to avoid flickering problem in animation
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
// window size
glutInitWindowSize(400,350);
// create the window
glutCreateWindow("Cone Rotating Animation");
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glClearColor(0.0,0.0,0.0,0.0);
//Assign the function used in events
glutDisplayFunc(displayCone);
glutReshapeFunc(reshapeCone);
glutIdleFunc(idleCone);
//Let start glut loop
glutMainLoop();
return 0;
}
The function idlecone instead changes the values of xRotated, yRotated... and displays the cone. Any ideas?
I am pretty sure I didn't understand the right moment where to use gluLookAt()...
gluLookAt changes the current matrix, similar to glTranslatef or glRotatef.
The operation defines a transformation matrix and multiplies the current matrix by the new transformation matrix.
gluLookAt has to be called before glutSolidCone, e.g.:
void displayCone(void)
{
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(3,3,3,0,0,-4.5,0,1,0); // <----------------------- add
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}

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.

Texturing a sphere in OpenGL with glTexGen

I want to get an earth texture on sphere. My sphere is an icosphere built with many triangles (100+) and I found it confusing to set the UV coordinates for whole sphere. I tried to use glTexGen and effects are quite close but I got my texture repeated 8 times (see image) . I cannot find a way to make it just wrap the whole object once. Here is my code where the sphere and textures are created.
glEnable(GL_TEXTURE_2D);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++)
{
Triangle *draw_Trian = new_sphere->Trians+i;
glVertex3f(draw_Trian->pnts[0].coords[0], draw_Trian->pnts[0].coords[1], draw_Trian->pnts[0].coords[2]);
glVertex3f(draw_Trian->pnts[1].coords[0], draw_Trian->pnts[1].coords[1], draw_Trian->pnts[1].coords[2]);
glVertex3f(draw_Trian->pnts[2].coords[0], draw_Trian->pnts[2].coords[1], draw_Trian->pnts[2].coords[2]);
}
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
glEnd();
You need to define how your texture is supposed to map to your triangles. This depends on the texture you're using. There are a multitude of ways to map the surface of a sphere with a texture (since no one mapping is free of singularities). It looks like you have a cylindrical projection texture there. So we will emit cylindrical UV coordinates.
I've tried to give you some code here, but it's assuming that
Your mesh is a unit sphere (i.e., centered at 0 and has radius 1)
pnts.coords is an array of floats
You want to use the second coordinate (coord[1]) as the 'up' direction (or the height in a cylindrical mapping)
Your code would look something like this. I've defined a new function for emitting cylindrical UVs, so you can put that wherever you like.
/* Map [(-1, -1, -1), (1, 1, 1)] into [(0, 0), (1, 1)] cylindrically */
inline void uvCylinder(float* coord) {
float angle = 0.5f * atan2(coord[2], coord[0]) / 3.14159f + 0.5f;
float height = 0.5f * coord[1] + 0.5f;
glTexCoord2f(angle, height);
}
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++) {
Triangle *t = new_sphere->Trians+i;
uvCylinder(t->pnts[0].coords);
glVertex3f(t->pnts[0].coords[0], t->pnts[0].coords[1], t->pnts[0].coords[2]);
uvCylinder(t->pnts[1].coords);
glVertex3f(t->pnts[1].coords[0], t->pnts[1].coords[1], t->pnts[1].coords[2]);
uvCylinder(t->pnts[2].coords);
glVertex3f(t->pnts[2].coords[0], t->pnts[2].coords[1], t->pnts[2].coords[2]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
Note on Projections
The reason it's confusing to build UV coordinates for the whole sphere is that there isn't one 'correct' way to do it. Mathematically-speaking, there's no such thing as a perfect 2D mapping of a sphere; hence why we have so many different types of projections. When you have a 2D image that's a texture for a spherical object, you need to know what type of projection that image was built for, so that you can emit the correct UV coordinates for that texture.

Opengl hide parts of the screen

(code snippet. I know it's ugly but i wanted to make it work before making it better so please don't pay too much attention to the structure)
I modified slightly the glfw example present in the documentation to have a triangle that rotates when pressing the right arrow key and draws a circle described by the position of one of his vertices (the blue one in this case).
I clear the GL_COLOR_BUFFER_BIT only when initializing the window to avoid having to store all the coordinates that will be needed to draw the line (they would be hundreds of thousands in the final program), that means that on the screen every time i press the right arrow a "copy" of the triangle is draws rotated by 12 degrees and a line is drawn that connects the old blue angle position to the new one.
The problem now is that i would want to be able to press the escape key GLFW_KEY_ESCAPE and "delete" the triangles while keeping the lines drawn.
I tried using a z-buffer to hide the triangles behind a black rectangle but only the last line drawn is visualized (i think this is because opengl doesn't know the z of the previous lines since i don't store them).
Is there a way to do what i want without having to store all the point coordinates and then clearing the whole screen and redrawing only the lines? If this is the case, what would be the best way to store them?
Here is part of the code i have so far.
bool check = 0;
Vertex blue = {0.f, 0.6f, 0.5f};
Vertex green = {0.6f,-0.4f, 0.5f};
Vertex red = {-0.6f, -0.4f, 0.5f};
Vertex line = {0.f, 0.6f, 0.f};
Vertex line2 = {0.f, 0.6f, 0.f};
static void
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
check = !check;
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
line.x = line2.x;
line.y = line2.y;
rotation -= 12;
rad = DegToRad(-12);
double x = line.x*cos(rad) - line.y * sin(rad);
double y = line.y * cos(rad) + line.x * sin(rad);
line2.x = x;
line2.y = y;
}
int main(void) {
GLFWwindow *window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(1280, 720, "Example", NULL, NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glClear(GL_COLOR_BUFFER_BIT);
while (!glfwWindowShouldClose(window)) {
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(rotation, 0.f, 0.f, 1.f);
glBegin(GL_TRIANGLES);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(red.x, red.y, red.z);
glColor3f(0.f, 1.f, 0.f);
glVertex3f(green.x, green.y, green.z);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(blue.x, blue.y, blue.z);
glEnd();
glLoadIdentity();
glLineWidth(1.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex3f(line.x, line.y, line.z);
glVertex3f(line2.x, line2.y, line2.z);
glEnd();
if (check){
//hide the triangles but not the lines
}
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
I clear the GL_COLOR_BUFFER_BIT only when initializing the window
That's your problem right there. It's idiomatic in OpenGL to always start with a clear operation of the main framebuffer color bits. That is, because you don't know the state of your window main framebuffer when the operating system is asking for a redraw. For all you know it could have been all replaced with cat pictures in the background without your program knowing it. Seriously: If you have a cat video running and the OS felt the need to rearrange your window's main framebuffer memory this is what you might end up with.
Is there a way to do what i want without having to store all the point coordinates and then clearing the whole screen and redrawing only the lines?
For all intents and purposes: No. In theory one could come up with a contraption made out of a convoluted series of stencil buffer operations to implement that, but this would be barking up a very wrong tree.
Here's something for you to try out: Draw a bunch of triangles like you do, then resize your window down so there nothing remains, then resize it back to its original size… you see where the problem? There's a way to address this particular problem, but that's not what you should do here.
The correct thing is to redraw everything. If you feel that that's to slow you have to optimize your drawing process. On current generation hardware it's possible to churn out on the order of 100 million triangles per second.

Resources