Go Back
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
GLint width=480, height=240;
GLint mainWindow;
const double TOL = 1E-6;
// Important Constants
const double PI = 3.14159265358979323846;
const double CD = 0.5;
const double RHO = 1.29;
const double g = 9.81, G = 6.6726E-11;
// Timestep, window settings
const double DT = 0.001;
double xmax=1000, ymax=500;
double xmin = xmax/-10.0, ymin = ymax/-10.0;
double dx = (xmax-xmin)/width, dy = (ymax-ymin)/height;
// Projectile and Target settings
double xtarget=xmax*0.9, rtarget = xmax*0.025;
double rball = 0.1;
double aball = PI*rball*rball;
double mball = 1E2;
// Initial position/velocity values
double xp0=0.0, yp0=0.0, v0=100.0, theta0=45;
double xpos=xp0, ypos=yp0, vlast[2]={v0*cos(theta0),v0*sin(theta0)}, vnew[2];
// OpenGL Window functions
void display();
void reshape(int w, int h);
void dispGraph();
// Helper functions for OpenGL Window functions
void init();
void dispString(int x, int y, int z, char *string, void *font);
void dispAxes();
// Math-ish stuff for the calculations
void normalize(double *v);
double abs(double a);
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(width, height);
mainWindow = glutCreateWindow("Projectile Fun, Part I");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void reshape(int w, int h)
{
// My Favorite Evil Technique (tm) -
// if they want to resize the window, too bad.
glutSetWindow(mainWindow);
glutReshapeWindow(width, height);
glFlush();
glutPostRedisplay();
}
void display()
{
double force[2], d[2], dmag2, fmag, vmag, vang, i;
glClear(GL_COLOR_BUFFER_BIT);
// DRAW AXES
dispAxes();
//DRAW TARGET
glColor3f(0.5, 0.5, 1.0);
glBegin(GL_QUADS);
glVertex3f(xtarget-rtarget, -3*dy, 0);
glVertex3f(xtarget-rtarget, 3*dy, 0);
glVertex3f(xtarget+rtarget, 3*dy, 0);
glVertex3f(xtarget+rtarget, -3*dy, 0);
glEnd();
// The Yellow Path - gravity plus air resistance
glColor3f(1.0, 1.0, 0.5);
glBegin(GL_LINE_STRIP);
xpos=xp0, ypos=yp0, vnew[0]=v0*cos(theta0), vnew[1]=v0*sin(theta0);
do {
vlast[0]=vnew[0], vlast[1]=vnew[1];
// Update position based on velocity
if (ypos+vlast[1]*DT < 0)
{
xpos += (vlast[0] * abs(ypos/vlast[1]));
ypos = 0;
}
else
xpos += vlast[0]*DT, ypos += vlast[1]*DT;
glVertex3f(xpos, ypos, 0);
// GRAVITY - EARTH
vnew[1] -= g*DT;
// DRAG FORCE
vmag = hypot(vlast[0], vlast[1]);
vang = atan2(vlast[1], vlast[0]);
fmag = CD*RHO*aball*(vmag*vmag)/2.0;
vnew[0] -= (fmag/mball)*DT*cos(vang);
vnew[1] -= (fmag/mball)*DT*sin(vang);
} while (ypos > 0);
glEnd();
// The Green Path - just gravity
glColor3f(0.5, 1.0, 0.5);
glBegin(GL_LINE_STRIP);
xpos=xp0, ypos=yp0, vnew[0]=v0*cos(theta0), vnew[1]=v0*sin(theta0);
do {
vlast[0]=vnew[0], vlast[1]=vnew[1];
// Update position based on velocity
if (ypos+vlast[1]*DT < 0)
{
xpos += (vlast[0] * abs(ypos/vlast[1]));
ypos = 0;
}
else
xpos += vlast[0]*DT, ypos += vlast[1]*DT;
glVertex3f(xpos, ypos, 0);
// GRAVITY - EARTH
vnew[1] -= g*DT;
} while (ypos > 0);
glEnd();
}
void init()
{
// Window settings
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(xmin, xmax, ymin, ymax, -1.0, 1.0);
}
void dispString(int x, int y, int z, char *string, void *font)
{
// Display a string. I'm not sure why I kept this in here,
// but if I ever decide to stick a string in, I can.
int len, i;
glRasterPos3f(x, y, 0);
len = (int) strlen(string);
for (i = 0; i < len; i++)
glutBitmapCharacter(font, string[i]);
}
void dispAxes()
{
// Draw the axes and tick marks along them.
double i;
glColor3f(0.35, 0.35, 0.35);
glBegin(GL_LINES);
glVertex3f(xmin, 0.0, 0.0);
glVertex3f(xmax, 0.0, 0.0);
glVertex3f(0.0, ymin, 0.0);
glVertex3f(0.0, ymax, 0.0);
for (i = 0; i <= xmax+TOL; i += (xmax / 4))
{
glVertex3f(i, 0.0, 0.0);
glVertex3f(i, 4.0*dy, 0.0);
}
for (i = 0; i <= ymax+TOL; i += (ymax / 4))
{
glVertex3f(0.0, i, 0.0);
glVertex3f(4.0*dx, i, 0.0);
}
glEnd();
}
void normalize(double *v)
{
// Find a unit vector with the same direction as v.
double dist = hypot(v[0], v[1]);
v[0] /= dist;
v[1] /= dist;
}
double abs(double a)
{
// the stdlib.h abs() only seems to like ints. ~shrug~
if (a >= 0) return a;
return (-1*a);
}