I wrote a program that will simulate a ball being thrown off a 50 meter building.
I added in collision detection by reversing the velocity in the y direction when the ball hits the ground (y < 0), keeping the horizontal velocity the same, and multiplying both velocities by some min value, so that the ball will ultimately come to a rest.
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
int main() {
FILE *fp;
FILE *fr;
float ax = 0, ay = 0, x = 0, y = 0, vx = 0, vy = 0;
float time = 0, deltaTime = .001;
float min = -.00000000001;
int numBounces = 0;
fr = fopen("input_data.txt", "rt");
fp = fopen( "output_data.txt", "w" );
if(fr == NULL){ printf("File not found");}
if(fp == NULL){ printf("File not found");}
fscanf(fr, "ax: %f ay: %f x: %f y: %f vx: %f vy: %f\n", &ax, &ay, &x, &y, &vx, &vy);
while (vx > min && vy > min) {
time = time + deltaTime;
vx = vx + ax*deltaTime;
vy = vy + ay*deltaTime;
x = x + vx*deltaTime + (.5*ax*deltaTime*deltaTime);
y = y + vy*deltaTime + (.5*ay*deltaTime*deltaTime);
fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time);
//Collision occurs; implement collision response
if(y < 0) {
vx = vx + ax*deltaTime*(.00001);
vy = -(vy + ay*deltaTime*(.00001));
numBounces++;
fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time);
}
}
fclose(fp);
fclose(fr);
system ("PAUSE");
return 0;
}
I am not getting the correct values needed to produce a correct graph of the data.
It could be because my conditions in the while loop need to be changed, or that I did not implement collision response correctly.
Here is also some sample data:
ax: 0 ay: -9.8 x: 0 y: 50 vx: 8.66 vy: 5
for not outputing anything you can try fflush(fp) at the end of each cycle. and as far as I can see in your code your object gets some more speed whenever it hits the ground you have to change vy = -(vy + ay*deltaTime*(.00001)) to vy = -(vy - ay*deltaTime*(.00001)) to correct it. you can also create a better implementation for collision if you calculate the exact time of collision whenever y < 0 and then move object down, change speeds, and move object up for the rest of cycle to have more realistic collision.
we know that deltaY = 1/2*ay*t^2 + vy*t so we can compute t using the folling formula :
assuming py is the current height of object(it's distance to ground)
=> -py = 0.5 * ay* t * t + vy * t
=> 0 = 0.5 * ay * t * t+ vy * t + py
=> t = (-vy +- sqrt(vy*vy - 2 * ay * py)) / (2 * ay)
and since t has to be positive and knowing that ay is negetive and py is positive, we can assume the currect answer is
=> tc = (sqrt(vy*vy - 2 * ay * py) - vy) / 2 / ay
now we have tc which is time of collision. so we have to reverse the last changes in position and speed, then just step time tc seconds and then reverse vy and step deltaTime - tc seconds to complete that frame. so inside the if condition would be like (I just may have some problems doing the math, so if by any chance you didn't get expected results jsut doublecheck all equations):
if (y < 0) {
float tc = (sqrt(vy*vy - 2 *ay * y)) / 2 / ay;
x = x - vx*deltaTime - (.5*ax*deltaTime*deltaTime);
y = y - vy*deltaTime - (.5*ay*deltaTime*deltaTime);
vx = vx - ax * deltaTime;
vy = vy - ay * deltaTime;
vx = vx + ax * tc;
vy = vy + ay * tc;
x = x + vx*tc + (.5*ax*tc*tc);
y = y + vy*tc + (.5*ay*tc*tc);
vy = -(vy - ay*deltaTime*(.00001));
// you can also change above line and simply write
// vy = vy * -0.99;
// that will also create friction as you want it to be there
vx = vx + ax * (deltaTime - tc);
vy = vy + ay * (deltaTime - tc);
x = x + vx* (deltaTime - tc) + (.5*ax* (deltaTime - tc)* (deltaTime - tc));
y = y + vy* (deltaTime - tc) + (.5*ay* (deltaTime - tc)* (deltaTime - tc));
numBounces++;
fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time);
}
Related
I want to find the point at distance d on the right side of a line defined by P1(x1,y1) and P2(x2,y2) (the distance is calculated from the middle of the line). I came up with the following code, which works well, but I think I have made unnecessary calculations, and it can be done faster.
#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
double x2, x1, y1, y2, px, py, p1x, p1y, p2x, p2y, d, ax, ay, b, dx, dy;
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
b = tan(atan2(y2 - y1, x2 - x1) + PI / 2); // slope of the perpendicular line
dx = (d / sqrt(1 + (b * b)));
dy = b * dx;
p1x = ax + dx;
p1y = ay + dy;
p2x = ax - dx;
p2y = ay - dy;
// cross product
if (((x2 - x1) * (p1y - y1) - (y2 - y1) * (p1x - x1)) > 0)
{
px = p1x;
py = p1y;
}
else
{
px = p2x;
py = p2y;
}
You don't need atan, b value, cross product to check orientation (moreover, b might be zero and cause division error).
Instead calculate normalized (unit length) direction vector and get right normal to it:
d = 2.0; // given distance
ax = (x1 + x2) / 2; // middle point
ay = (y1 + y2) / 2; // middle point
dx = x2 - x1;
dy = y2 - y1;
scale = d / sqrt(dx*dx + dy*dy); //distance/vector length
px = ax + dy * scale; // add normal vector to the right side of p1-p2 direction
py = ay - dx * scale; //note minus sign
For generating a 2D vector perpendicular to another, one result that falls out from a special case of the dot product is that you can swap the two components of the vector and negate one of them.
For example, let's say you have the vector d which points from p1 to p2:
dx = p2x - p1x;
dy = p2y - p1y;
And now you want to generate right which is perpendicular, it is simply:
rightx = dy;
righty = -dx;
Now, let's do a quick visual check for our definition of "on the right", in case we actually want to negate those two values...
o p2 = [2, 3]
/
o p1 = [0, 0]
Above, d is simple: [2, 3]. Intuitively, we would think of (as viewed from above) walking from p1 to p2 and looking to the right, which would mean a vector in the positive X direction and the negative Y direction. So yes, that looks fine.
Note: If your co-ordinate system is screen-based (i.e. positive Y direction is down), then the inverse is true (and you would negate both the terms in the calculation of the right vector). This is due to the handedness of the co-ordinate system being left instead of right.
Now, you can calculate the midpoint mid as either (p1 + p2) / 2 or p1 + d / 2.
midx = (p1x + p2x) / 2;
midy = (p1y + p2y) / 2;
And finally to generate p3 you start from mid and extend down the vector right by an amount height, you need to normalize that vector by dividing by its length and scale by height. Formally, the final point will be mid + right * height / length(right).
This is the only particularly expensive part of the calculation, because it needs a square root.
rdist = height / sqrt(rightx * rightx + righty * righty);
p3x = midx + rightx * rdist;
p3y = midy + righty * rdist;
Congratulations! You now have an isosceles triangle!
I have been writing this code for checking the euler angles and quaternions, but it is not run correcly (or maybe I do not understand the rotations):
#include <stdio.h>
#include <math.h>
#define DR2D (180 / M_PI)
#define DD2R (M_PI / 180)
int main(int argc, char** argv)
{
float x, y, z;
x = 0 * DD2R;
y = 0 * DD2R;
z = 180 * DD2R;
printf("x=%f y=%f z=%f\n", x, y, z);
float sx = sin(x / 2);
float sy = sin(y / 2);
float sz = sin(z / 2);
float cx = cos(x / 2);
float cy = cos(y / 2);
float cz = cos(z / 2);
float qx, qy, qz, qw;
printf("sx = %f sy = %f sz = %f cx = %f cy = %f cz = %f\n", sx, sy, sz, cx, cy, cy);
qx = cx*cy*sz + sx*sy*cz;
qy = sx*cy*cz + cx*sy*sz;
qz = cx*sy*cz - sx*cy*sz;
qw = cx*cy*cz - sx*sy*sz;
printf("Quaternion -> (%f, %f, %f, %f)\n", qx, qy , qz , qw);
//------------------------------------------------------------------
float sqw = qw*qw;
float sqx = qx*qx;
float sqy = qy*qy;
float sqz = qz*qz;
float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
float test = qx*qy + qz*qw;
if (test > 0.499*unit) { // singularity at north pole
x = 2 * atan2(qx,qw);
y = M_PI/2;
z = 0;
}
else if (test < -0.499*unit) { // singularity at south pole
x = -2 * atan2(qx,qw);
y = -M_PI/2;
z = 0;
}
else {
x = atan2(2*qy*qw-2*qx*qz , sqx - sqy - sqz + sqw);
y = asin(2*test/unit);
z = atan2(2*qx*qw-2*qy*qz , -sqx + sqy - sqz + sqw);
}
printf("recover euler x=%.2f y=%.2f z=%.2f\n",
x * DR2D, y * DR2D, z * DR2D);
}
Because the output is very weird:
For example: x 180º y 90º z 90º
x=3.141593 y=1.570796 z=1.570796
sx = 1.000000 sy = 0.707107 sz = 0.707107 cx = -0.000000 cy = 0.707107 cz = 0.707107
Quaternion -> (0.500000, 0.500000, -0.500000, -0.500000)
reconversion euler x=270.00 y=90.00 z=0.00
Or for example x 90º y 90º z 90º
x=1.570796 y=1.570796 z=1.570796
sx = 0.707107 sy = 0.707107 sz = 0.707107 cx = 0.707107 cy = 0.707107 cz = 0.707107
Quaternion -> (0.707107, 0.707107, 0.000000, 0.000000)
recover euler x=180.00 y=90.00 z=0.00
The algorithm you use has a domain that lies in the interval [0,pi/2) only, the first quadrant. Or, because you want the input to be in degrees, between 0 (zero) inclusive and 90 degrees exclusive.
I'm using SDL2.
The only way I can find to draw a shape is with the line, rect and pixel functions, as explained here.
Apart from using trig or the "equation of a circle", how could I draw a curve? How about general vector graphics?
Is SDL an appropriate starting point or should I look elsewhere?
This is an example of the Midpoint Circle Algorithm as referenced above. It doesn't require a math library and is very fast. (Renders in about 500 microseconds) This is what Windows uses/used to rasterize circles.
void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius)
{
const int32_t diameter = (radius * 2);
int32_t x = (radius - 1);
int32_t y = 0;
int32_t tx = 1;
int32_t ty = 1;
int32_t error = (tx - diameter);
while (x >= y)
{
// Each of the following renders an octant of the circle
SDL_RenderDrawPoint(renderer, centreX + x, centreY - y);
SDL_RenderDrawPoint(renderer, centreX + x, centreY + y);
SDL_RenderDrawPoint(renderer, centreX - x, centreY - y);
SDL_RenderDrawPoint(renderer, centreX - x, centreY + y);
SDL_RenderDrawPoint(renderer, centreX + y, centreY - x);
SDL_RenderDrawPoint(renderer, centreX + y, centreY + x);
SDL_RenderDrawPoint(renderer, centreX - y, centreY - x);
SDL_RenderDrawPoint(renderer, centreX - y, centreY + x);
if (error <= 0)
{
++y;
error += ty;
ty += 2;
}
if (error > 0)
{
--x;
tx += 2;
error += (tx - diameter);
}
}
}
If you want to write your own circle drawing function, then I'd suggest adapting the midpoint algorithm to SDL2 by drawing pixels.
Curves would be done similarly, but would use more of an ellipses drawing algorithm.
Actual vector graphics start to get much more complicated, and you'd probably have to find something that renders SVG files, which I'm not sure there are many options for SDL2.
However, if you would rather simply have functions that you can work with I'd suggest going straight to SDL2_gfx instead. It has many more functions already implemented for you to work with.
SDL allows for third party libs to draw on a texture. If cairo was desirable, it could be used in a function like this:
cairo_t*cb(cairo_t*cr)
{cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_rectangle(cr, 10, 20, 128, 128);
cairo_stroke(cr);
return cr;
}
then cb can be passed to this function:
cairo_t*cai(SDL_Window*w,SDL_Renderer*r,cairo_t*(*f)(cairo_t*))
{int width, height, pitch;void *pixels;
SDL_GetWindowSize(w, &width, &height);
SDL_Texture*t=SDL_CreateTexture(r,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMING,width,height);
SDL_LockTexture(t, NULL, &pixels, &pitch);
cairo_surface_t *cs=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32,width,height,pitch);
cairo_t*s=cairo_create(cs);
cairo_t*fr=f(s);SDL_UnlockTexture(t);SDL_RenderCopy(r,t,NULL,NULL);SDL_RenderPresent(r);
return fr;
}
If you want to do a circle or ellipse without 3rd party libraries, include math.h and use the function below I wrote. It will draw aliased ellipse or circles very well. Tested on SDL 2.0.2 and works. It draws one quadrant arc, and mirrors the other arcs, reducing calls to cosf and sinf.
//draw one quadrant arc, and mirror the other 4 quadrants
void sdl_ellipse(SDL_Renderer* r, int x0, int y0, int radiusX, int radiusY)
{
float pi = 3.14159265358979323846264338327950288419716939937510;
float pih = pi / 2.0; //half of pi
//drew 28 lines with 4x4 circle with precision of 150 0ms
//drew 132 lines with 25x14 circle with precision of 150 0ms
//drew 152 lines with 100x50 circle with precision of 150 3ms
const int prec = 27; // precision value; value of 1 will draw a diamond, 27 makes pretty smooth circles.
float theta = 0; // angle that will be increased each loop
//starting point
int x = (float)radiusX * cos(theta);//start point
int y = (float)radiusY * sin(theta);//start point
int x1 = x;
int y1 = y;
//repeat until theta >= 90;
float step = pih/(float)prec; // amount to add to theta each time (degrees)
for(theta=step; theta <= pih; theta+=step)//step through only a 90 arc (1 quadrant)
{
//get new point location
x1 = (float)radiusX * cosf(theta) + 0.5; //new point (+.5 is a quick rounding method)
y1 = (float)radiusY * sinf(theta) + 0.5; //new point (+.5 is a quick rounding method)
//draw line from previous point to new point, ONLY if point incremented
if( (x != x1) || (y != y1) )//only draw if coordinate changed
{
SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1 );//quadrant TR
SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1 );//quadrant TL
SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1 );//quadrant BL
SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1 );//quadrant BR
}
//save previous points
x = x1;//save new previous point
y = y1;//save new previous point
}
//arc did not finish because of rounding, so finish the arc
if(x!=0)
{
x=0;
SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1 );//quadrant TR
SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1 );//quadrant TL
SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1 );//quadrant BL
SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1 );//quadrant BR
}
}
My answer extends Scotty Stephens answer by making it a bunch more performant by reducing the API calls to a single one.
// rounding helper, simplified version of the function I use
int roundUpToMultipleOfEight( int v )
{
return (v + (8 - 1)) & -8;
}
void DrawCircle( SDL_Renderer * renderer, SDL_Point center, int radius )
{
// 35 / 49 is a slightly biased approximation of 1/sqrt(2)
const int arrSize = roundUpToMultipleOfEight( radius * 8 * 35 / 49 );
SDL_Point points[arrSize];
int drawCount = 0;
const int32_t diameter = (radius * 2);
int32_t x = (radius - 1);
int32_t y = 0;
int32_t tx = 1;
int32_t ty = 1;
int32_t error = (tx - diameter);
while( x >= y )
{
// Each of the following renders an octant of the circle
points[drawCount+0] = { center.x + x, center.y - y };
points[drawCount+1] = { center.x + x, center.y + y };
points[drawCount+2] = { center.x - x, center.y - y };
points[drawCount+3] = { center.x - x, center.y + y };
points[drawCount+4] = { center.x + y, center.y - x };
points[drawCount+5] = { center.x + y, center.y + x };
points[drawCount+6] = { center.x - y, center.y - x };
points[drawCount+7] = { center.x - y, center.y + x };
drawCount += 8;
if( error <= 0 )
{
++y;
error += ty;
ty += 2;
}
if( error > 0 )
{
--x;
tx += 2;
error += (tx - diameter);
}
}
SDL_RenderDrawPoints( renderer, points, drawCount );
}
A circle of radius 141 would have had 800 SDL_RenderDrawPoint calls in Scottys version, this new version does only execute one single SDL_RenderDrawPoints call, making it much more performant.
One could also strip the rendering portion out of this function, to allow the result to be cached and reused like shown below.
std::vector<SDL_Point> PixelizeCircle( SDL_Point center, int radius )
{
std::vector<SDL_Point> points;
// 35 / 49 is a slightly biased approximation of 1/sqrt(2)
const int arrSize = roundUpToMultipleOfEight( radius * 8 * 35 / 49 );
points.reserve( arrSize );
const int32_t diameter = (radius * 2);
int32_t x = (radius - 1);
int32_t y = 0;
int32_t tx = 1;
int32_t ty = 1;
int32_t error = (tx - diameter);
while( x >= y )
{
// Each of the following renders an octant of the circle
points.push_back( { center.x + x, center.y - y } );
points.push_back( { center.x + x, center.y + y } );
points.push_back( { center.x - x, center.y - y } );
points.push_back( { center.x - x, center.y + y } );
points.push_back( { center.x + y, center.y - x } );
points.push_back( { center.x + y, center.y + x } );
points.push_back( { center.x - y, center.y - x } );
points.push_back( { center.x - y, center.y + x } );
if( error <= 0 )
{
++y;
error += ty;
ty += 2;
}
if( error > 0 )
{
--x;
tx += 2;
error += (tx - diameter);
}
}
return points; // RVO FTW
}
int main()
{
std::vector<SDL_Point> circle = PixelizeCircle( SDL_Point{ 84, 72 }, 79 );
//...
while( true )
{
//...
SDL_RenderDrawPoints( renderer, circle.data(), circle.size() );
//...
}
}
How do I find the point on the straight line that is specific distance away from a given point. I am writing this code in C but I do not get the right answer..Could you anyone guide me on what I am doing wrong.
I get the x1,y1,x2,y2 values and the distance left fine. Using these I can find the slope m and the y-intercept also fine.
Now, I need to find the point on the straight line connecting these two points that is 10 units away from the point x1,y1. I seem to be going wrong here. here's the code that I wrote.
int x1 = node[n].currentCoordinates.xCoordinate;
int y1 = node[n].currentCoordinates.yCoordinate;
int x2 = node[n].destinationLocationCoordinates.xCoordinate;
int y2 = node[n].destinationLocationCoordinates.yCoordinate;
int distanceleft = (y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1);
distanceleft = sqrt(distanceleft);
printf("Distance left to cover is %d\n",distanceleft);
int m = (y2 - y1)/(x2 - x1); // slope.
int b = y1 - m * x1; //y-intercept
//find point on the line that is 10 units away from
//current coordinates on equation y = mx + b.
if(x2 > x1)
{
printf("x2 is greater than x1\n");
int tempx = 0;
int tempy = 0;
for(tempx = x1; tempx <= x2; tempx++)
{
tempy = y1 + (y2 - y1) * (tempx - x1)/(x2 - x1);
printf("tempx = %d, tempy = %d\n",tempx,tempy);
int distanceofthispoint = (tempy - y1) * (tempy - y1) + (tempx - x1) * (tempx - x1);
distanceofthispoint = sqrt((int)distanceofthispoint);
if(distanceofthispoint >= 10)
{
//found new points.
node[n].currentCoordinates.xCoordinate = tempx;
node[n].currentCoordinates.yCoordinate = tempy;
node[n].TimeAtCurrentCoordinate = clock;
printf("Found the point at the matching distance\n");
break;
}
}
}
else
{
printf("x2 is lesser than x1\n");
int tempx = 0;
int tempy = 0;
for(tempx = x1; tempx >= x2; tempx--)
{
tempy = y1 + (y2 - y1) * (tempx - x1)/(x2 - x1);
printf("tempx = %d, tempy = %d\n",tempx,tempy);
int distanceofthispoint = (tempy - y1) * (tempy - y1) + (tempx - x1) * (tempx - x1);
distanceofthispoint = sqrt((int)distanceofthispoint);
if(distanceofthispoint >= 10)
{
//found new points.
node[n].currentCoordinates.xCoordinate = tempx;
node[n].currentCoordinates.yCoordinate = tempy;
node[n].TimeAtCurrentCoordinate = clock;
printf("Found the point at the matching distance\n");
break;
}
}
}
printf("at time %f, (%d,%d) are the coordinates of node %d\n",clock,node[n].currentCoordinates.xCoordinate,node[n].currentCoordinates.yCoordinate,n);
Here is how it is in math, I don't have time to write something in C.
You have a point (x1,y1) and another one (x2,y2), when linked it gives you a segment.
Thus you have a directional vector v=(xv, yv) where xv=x2-x1 and yv=y2-y1.
Now, you need to divide this vector by its norm, you get a new vector: vector = v / sqrt(xv2 + yv2).
Now, you just have to add to your origin point the vector multiplied by the distance at which you want your point:
Position = (x origin, y origin) + distance × vector
I hope this helps!
Or simpler,
Find the angle from the slope
θ = arctan(y2-y1/x2-x1)
You might want to modify the quadrant of θ based on the numerator and denominator of the slope. Then you can find any point on the line at distance d from (x1, y1)
x_new = x1 + d×cos(θ)
y_new = y1 + d×sin(θ)
In this case, you have d=10
I am attempting to implement collision response in a simulation that I am creating.
Basically, the program simulates a ball being thrown off a 50 meter building with some initial velocity.
I don't believe that the program is outputting realistic values for time of collision as well as values for x, y and vx, vy.
Here is the program:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int main() {
FILE *fp;
FILE *fr;
//Declare and initialize all variables to be used
float ax = 0, ay = 0, x = 0, y = 0, vx = 0, vy = 0;
float time = 0, deltaTime = .001;
float vyImpact = 0, vxImpact = 0, xImpact = 0;
float old_y = 0, old_x = 0, old_vy = 0, old_vx = 0;
float deltaTime2 = 0, deltaTime3 = 0;
int numBounces = 0;
//Coefficient of Restitution; epsilon = ex = ey
float ex = .5;
float ey = .5;
fr = fopen("input_data.txt", "rt"); //Open file for reading
fp = fopen( "output_data.txt", "w" ); // Open file for writing
if(fr == NULL){ printf("File not found");} //if text file is not in directory...
if(fp == NULL){ printf("File not found");} //if text file is not in directory...
fscanf(fr, "ax: %f ay: %f x: %f y: %f vx: %f vy: %f\n", &ax, &ay, &x, &y, &vx, &vy);
while (numBounces < 9) {
//time = time + deltaTime
time = time + deltaTime;
//velocity[new] = velocity[old] + acc * deltaTime
vx = vx + ax*deltaTime;
vy = vy + ay*deltaTime;
//position[new] = position[old] + velocity*deltaTime + .5*acc*(deltaTime)^2
x = x + vx*deltaTime + (.5*ax*deltaTime*deltaTime);
y = y + vy*deltaTime + (.5*ay*deltaTime*deltaTime);
fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time);
//Collision occurs; implement collision response
if (y < 0) {
//"Undo" values for y, x, and velocity
old_y = y - vy*deltaTime - (.5*ay*deltaTime*deltaTime);
old_x = x - vx*deltaTime - (.5*ax*deltaTime*deltaTime);
old_vy = vy - ay*deltaTime;
old_vx = vx - ax*deltaTime;
//Calculate time of collision
deltaTime2 = (-old_y + sqrt((old_y*old_y) - 2*ay*old_y)) / (ay);
printf("Time of Collision = %f\n", time - deltaTime2);
//Calculate velocity and x position at collsion
vyImpact = old_vy + ay*deltaTime2;
vxImpact = old_vx + ax*deltaTime2;
xImpact = old_x + old_vx*deltaTime2 + .5*ax*(deltaTime2*deltaTime2);
//Calculate new time for when ball bounces
deltaTime3 = deltaTime - deltaTime2;
//Calculate new x and y position and velocity for when ball bounces
x = xImpact + (ex)*vxImpact*deltaTime3 + .5*ax*(deltaTime3*deltaTime3);
y = 0 + (-ey)*vyImpact*deltaTime3 + .5*ay*(deltaTime3*deltaTime3);
vy = (-ey)*vyImpact + ay*deltaTime3;
vx = (ex)*vxImpact + ax*deltaTime3;
numBounces++;
printf("Number of Bounce(s) = %d\n", numBounces);
fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time);
}
}
fclose(fp); //Close output file
fclose(fr); //Close input file
//system ("PAUSE");
return 0;
}
Basically, I am trying to produce accurate values so that I can see a plot of what this simulation is supposed to look like. I am assuming the logical errors have something to do with the physics. But being that my physics knowledge is limited, I am not able to see what exactly is wrong.
Here is sample input:
ax: 0 ay: -9.8 x: 0 y: 50 vx: 8.66 vy: 5
It seems to me that your problem may lie in how you're implementing the kinematics equations.
//velocity[new] = velocity[old] + acc * deltaTime
vx = vx + ax*deltaTime;
vy = vy + ay*deltaTime;
//position[new] = position[old] + velocity*deltaTime + .5*acc*(deltaTime)^2
x = x + vx*deltaTime + (.5*ax*deltaTime*deltaTime);
y = y + vy*deltaTime + (.5*ay*deltaTime*deltaTime);
Two things here: you're already taking the acceleration into account in your equations for vx and vy, and you're using summation rather than integrated equations. The .5*ax*deltaTime*deltaTime and .5*ay*deltaTime*deltaTime shouldn't be included. The equation x= 0.5*a*t^2 is used when calculating the distance traveled due to a constant acceleration for the total amount of time, based on the integral of the velocity equation. As you're doing summation and already include the acceleration in your velocity equations, there's no need to include the acceleration in the position equations.