Not calculating?

I am making a gravity simulation and it seams to not applying the force to the bodies, help?

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  #include <stdlib.h>
#include <glut.h>
#include <vector>
#include "Entity.h"
#include "Body.h"

using namespace std;

std::vector<Body> bodies;
Entity e;

void init() {
	glClearColor(0, 0, 0, 0);

	Body sun;
	sun.name = "sun";
	sun.mass = 1.98892 * pow(10, 30);
	sun.px = 0.0;
	sun.py = 0.0;
	sun.vx = 0.0;
	sun.vy = 0.0;

	Body mercury;
	mercury.name = "mercury";
	mercury.mass = 3.302 * pow(10, 13);
	mercury.px = 0.466 * e.AU;
	mercury.py = 0.0;
	mercury.vx = 0.0;
	mercury.vy = 47.87 * 1000;

	bodies.push_back(sun);
	bodies.push_back(mercury);
	e.setBodies(bodies);
}

void render() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	e.render();

	glutPostRedisplay();
	glutSwapBuffers();
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitWindowSize(640, 480);
	glutInitWindowPosition(10, 10);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutCreateWindow("Gravity");

	init();
	glutDisplayFunc(render);

	glutMainLoop();
	return 0;
}


Entity.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "Entity.h"
#include <glut.h>
#include <vector>
#include "Body.h"

Entity::Entity() {
	
}

struct BodyForce {
	Body id;
	double fx;
	double fy;
};

void Entity::render() {
	std::vector<BodyForce> force;
	for (Body body : bodies) {
		double totalFx = 0.0;
		double totalFy = 0.0;
		for (Body other : bodies) {
			if (body.name != other.name) {
				double* forces = body.attraction(other);
				totalFx += forces[0];
				totalFy += forces[1];
			}
		}
		force.push_back(BodyForce{body, totalFx, totalFy});
	}

	for (Body body : bodies) {
		double fx = 0;
		double fy = 0;
		for (BodyForce f : force) {
			if (body.name == f.id.name) {
				fx = f.fx;
				fy = f.fy;
			}
		}

		body.vx += fx / body.mass * timestep;
		body.vy += fy / body.mass * timestep;
		body.px += body.vx * timestep;
		body.py += body.vy * timestep;

		glBegin(GL_POINTS);
		glVertex2f(body.px * scale, body.py * scale);
		glEnd();
	}
}


Entity.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include <vector>
#include "Body.h"

class Entity {
public:
	Entity();
	void render();
	double AU = (149.6e6 * 1000);
	void setBodies(std::vector<Body> b) { bodies = b; }
private:
	double timestep = 24 * 1000;
	double scale = 250 / AU;
	std::vector<Body> bodies;
};


Body.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
#include <iostream>
#include <string>

class Body {
public:
	std::string name;
	double mass;
	double px;
	double py;
	double vx;
	double vy;
	int size;
	double* attraction(Body other);
private:
	double G = 6.67428e-11;
};


Body.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "Body.h"
#include <math.h>

double* Body::attraction(Body other) {
	// Izracunavanje udaljenosti od drugog tela
	double sx = px;
	double sy = py;
	double ox = other.px;
	double oy = other.py;
	double dx = ox - sx;
	double dy = oy - sy;
	double d = sqrt(pow(dx, 2) + pow(dy, 2));

	// Prikazi gresku ako je udaljenost jednaka nuli
	if (d == 0) std::cout << "[ ! ] Collision between objects is not possible; " << name << ", " << other.name << std::endl;

	// Izracunavanje sile F
	double F = G * mass * other.mass / pow(d, 2);

	// Izracunavanje pravca vektora sile F
	double theta = atan2(dy, dx);
	double arrayF[1];
	arrayF[0] = cos(theta) * F;
	arrayF[1] = sin(theta) * F;
	return arrayF;
}
I don't have the graphics libraries to run your simulation. How do you know that the gravitational force is not applied?

The only timestepping you do is in render() (via e.render()) where you do a single timestep. How many times do you call this function? One timestep is only 24000 s (about 7 hours) - Mercury's orbital period is about 88 days, so it will only move about 1 degree of arc in that time.

One way of testing the gravitational attraction is to temporarily set Mercury's initial velocity to zero. Then it should move (faster and faster) toward the sun.
The problem is this:
1
2
3
4
5
6
7
double* Body::attraction(Body other) {
...
	double arrayF[1]; // Note: this is a local variable. The pointer to it becomes invalid as soon as the function attraction(...) ends.
	arrayF[0] = cos(theta) * F;
	arrayF[1] = sin(theta) * F;
	return arrayF;
}
1
2
3
4
5
...
			if (body.name != other.name) {
				double* forces = body.attraction(other); // Note: forces is invalid
				totalFx += forces[0];
				totalFy += forces[1];


I would suggest that you make a struct Point { double x; double y; }; (or so) for transporting and organizing the coordinates.
Thanks coder777. I missed that!

I think
double arrayF[1];
only creates a one-element array anyway. You need two components.

A struct to hold your vector force components (and positions, and velocities) would be a good idea. Actually, so would a valarray: then you don't need to do x and y components separately.
I did that, but planets just jump to position (original px, py + vx, vy)
Have you checked (by printing out) what is actually in fx, fy and timestep before these lines, and what are the values of position and velocity afterward.
1
2
3
4
		body.vx += fx / body.mass * timestep;
		body.vy += fy / body.mass * timestep;
		body.px += body.vx * timestep;
		body.py += body.vy * timestep;


Also, it would make your code much simpler if you made fx and fy into data members of class Body - then you wouldn't need this confusing extra class BodyForce.
Topic archived. No new replies allowed.