PDA

View Full Version : c program using opengl for oscillating pendulum



andre_arjun
03-26-2014, 01:10 AM
need a program for an oscillating pendulum - a sphere suspended to the end of the thread that can oscillate about the fixed point at the other end of the thread. need the code. im creating the sphere by recursive subdivision of a tetrahedron. need help with attaching the string and making it oscillate. thank you.

Agent D
03-26-2014, 03:16 AM
"need the code." Homework task? How exactely is it Windows(R) specific?

How detailed does the simulation have to be? Is the thread supposed to be flexible or rigid?

For the rigid case, I remember having solved the underlying differential equation in school some time. The result can be found here (http://en.wikipedia.org/wiki/Pendulum)

Regarding the code: If you understand the problem and your programming language (neither is hard), it is fairly easy to write the simulation code yourself (from the post I assume you already have the drawing code).

andre_arjun
04-09-2014, 04:00 PM
Yes, its a homework task. I've just started working on the drawing code. I don't know much about OpenGL, just a beginner. If not the code for the entire program, I'd at least like an idea on how to go about with it. Like i said, i was able to create a sphere by recursive subdivision of a tetrahedron and the thread I created using GL_LINES from the centre of the sphere to a point outside. I need to get it to rotate about its axis now.

Agent D
04-13-2014, 04:31 AM
You could aproach the rotation picewise: Write down a translation matrix that moves the tip of the line to the origin (and the rest of the pendulum accordingly), a rotation matrix that rotates the pendulum around one of the major axes, a translation matrix that moves it back to it is supposed to be at. Multiply those matrices and you end up with a single matrix that depends on the angle of rotation.

Somewhere, you need a variable to store time passed since the beginning of the program. At the end of every frame, update that variable. At the beginning of the frame, this variable can be used to determine the angle from the formula on the Wikipedia page (or the solution of your differential equation). Once you have the angle, you can determine the value of the matrix and send it to the shader.

andre_arjun
04-19-2014, 05:40 AM
Well, I understand the multiplication of the 3 matrices to achieve the rotation but I dont understand how to construct a matrix for translation/rotation. Could you please help me with it? This is my code uptil now that just creates a stationary pendulum:
#include<stdio.h>
#include<msclr/glut.h>
#include<math.h>
int n=10;
GLfloat v[4][3]={{0.0,0.0,1.0},{0.0,0.942809,-0.33333},{-0.816497,-0.471405,-0.33333},{0.816497,-0.471405,-0.333333}};
GLfloat a[2][3]={{0.0,0.0,-0.333333},{0.0,10.0,-0.333333}};
void normalize(GLfloat *p)
{
double d=0.0;
int i;
for(i=0;i<3;i++)
d+=p[i]*p[i];
d=sqrt(d);
if(d>0.0)
for(i=0;i<3;i++)
p[i]/=d;
}
void triangle(GLfloat *a,GLfloat *b,GLfloat *c)
{
glBegin(GL_POLYGON);
glNormal3fv(a);
glVertex3fv(a);
glVertex3fv(b);
glVertex3fv(c);
glEnd();
}
void divide_triangle(GLfloat *a,GLfloat *b,GLfloat *c,int n)
{
GLfloat v1[3],v2[3],v3[3];
int j;
if(n>0)
{
for(j=0;j<3;j++)
v1[j]=a[j]+b[j];
normalize(v1);
for(j=0;j<3;j++)
v2[j]=a[j]+c[j];
normalize(v2);
for(j=0;j<3;j++)
v3[j]=c[j]+b[j];
normalize(v3);
divide_triangle(a,v2,v1,n-1);
divide_triangle(c,v3,v2,n-1);
divide_triangle(b,v1,v3,n-1);
divide_triangle(v1,v2,v3,n-1);
}
else
triangle(a,b,c);
}
void tetrahedron(int n)
{
divide_triangle(v[0],v[1],v[2],n);
divide_triangle(v[3],v[2],v[1],n);
divide_triangle(v[0],v[3],v[1],n);
divide_triangle(v[0],v[2],v[3],n);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glClearColor(1.0,1.0,1.0,1.0);
glColor3f(1.0,0.0,0.0);
glLoadIdentity();
tetrahedron(n);
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3fv(a[0]);
glVertex3fv(a[1]);
glEnd();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-2.0,2.0,-2.0*(GLfloat)h/(GLfloat)w,2.0*(GLfloat)h/(GLfloat)w,-10.0,10.0);
else
glOrtho(-2.0*(GLfloat)w/(GLfloat)h,2.0*(GLfloat)w/(GLfloat)h,-2.0,2.0,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow("Pendulum");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}

Agent D
04-20-2014, 10:13 AM
Well, I understand the multiplication of the 3 matrices to achieve the rotation but I dont understand how to construct a matrix for translation/rotation. Could you please help me with it?
Homogeneous coordinates (http://en.wikipedia.org/wiki/Homogeneous_coordinates)
You don't use 3x3 matrices and 3 component vectors, you use 4x4 matrices 4 component vectors. If the last component "happens to be" 1.0, it will result in the last row of the matrix being added to the vector.

I suggest reading a tutorial related to the subject. (http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/)

andre_arjun
04-23-2014, 09:44 AM
Alright, I figured the rotating out. Translate the figure to the origin, rotate and translate back. That works. But now I have a problem with limiting the angle of rotation. I declared a global variable theta to rotate by and used the glutIdleFunc to continuously increment theta. The problem is idlefunc is always running so my pendulum rotates in circles. How can I limit my rotation angle to, say, +90 and -90 degrees?
#include<stdio.h>
#include<GL/freeglut.h>
#include<math.h>
//normalize(GLfloat *p)
//triangle(GLfloat *a,GLfloat *b,GLfloat *c)
//divide_triangle(GLfloat *a,GLfloat *b,GLfloat *c,int n)
//void tetrahedron(int n)
GLfloat theta=0.0;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glClearColor(1.0,1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex3fv(a[0]);
glVertex3fv(a[1]);
glEnd();
glColor3f(1.0,0.0,0.0);
tetrahedron(n);
glColor3f(0.0,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,+3.0,-0.333333);
glRotatef(theta,0.0,0.0,1.0);
glTranslatef(0.0,-3.0,+0.333333);
glFlush();
}
//myReshape(int w,int h)
void oscillate()
{
theta+=10.0;
glutPostRedisplay();
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(1366,768);
glutCreateWindow("Pendulum");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutIdleFunc(oscillate);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}

andre_arjun
04-23-2014, 09:52 AM
I tried lot of alternatives.
A for loop in the idlefunc oscillate() to rotate till +90 and then back to -90:
void oscillate()
{
int i;
for(i=0;i<=90;i+=30)
theta+=30;
for(i=0;i<180;i+=30)
theta-=30;
glutPostRedisplay();
}

I tried to use a mouse callback function through which I incremented theta on a right click and decremented it on a left click. I used a global variable as a flag:
float global;
void oscillate()
{
if(global==0.0)
{
theta-=theta;
glutPostRedisplay();
}
else if(global==1.0)
{
theta+=theta;
glutPostRedisplay();
}
}

void mouse(int btn, int state, int x, int y)i
{
if(btn==GLUT_LEFT_BUTTON&&state==GLUT_DOWN)
global==0.0;
if(btn==GLUT_RIGHT_BUTTON&&state==GLUT_DOWN)
global==1.0;
}

Agent D
04-23-2014, 10:40 AM
I don't know what you thought of when writing those functions, but none of them have any relationship to movements of a pendulum. What was that strange for loop supposed to do that only adds constant values without anything being drawn at all? If you subtract theta from itself, the result is 0!!

If you go to that wikipedia article (http://en.wikipedia.org/wiki/Pendulum) I posted earlier, you would know that the movement of a pendulum is a cosine of some constant multiplied with the current time.

Knowledge of oscillation and a little bit of common sense should actually lead you to something like this:

theta = theta_0 * cos(w*t)

The article mentions how the angular frequency is caclulted. Simply use a global or static variable to accumulate time every frame and calculate theta from that.

andre_arjun
04-24-2014, 02:48 AM
Im sorry, thats theta+=10.0 and theta-=10.0. I just need to show that the pendulum (or the object that I've created) rotates to a particular angle, say 0 to +90 degrees and back to -90 degrees in a single plane. I just want to show that simple movement visually. I'm still a beginner, i just started studying opengl a month ago. This is a very very basic project. I didn't mean the exact movement of a pendulum scientifically, its just a simple project to show 2D movements, it doesnt need to be accurate physics-wise. As for all the alternatives I tried, they were just ideas I was trying to make work, obviously they were bad ones but I was just trying things out to get a solution.

Agent D
04-25-2014, 03:10 AM
Moving the angle back and forth in a loop in the idle function doesn't do anything. Think of the rendered frames as a sequence of time slices of your scene. What you have to do is to compute the difference in movement for each frame and update the translations and rotations just a bit at the beginning of every frame. The simplest solution would probably be to use the angle as a function of time from the article, calculating the angular freqency ahead and simply using accumulated time to calcualate the angle at the start of every frame.