Gamestudio Links
Zorro Links
Newest Posts
Trading Journey
by howardR. 04/28/24 09:55
basik85278
by basik85278. 04/28/24 08:56
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Help with plotting multiple ZigZag
by M_D. 04/26/24 20:03
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
M1 Oversampling
by jcl. 04/26/24 11:12
Why Zorro supports up to 72 cores?
by jcl. 04/26/24 11:09
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
1 registered members (blaurock), 750 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Newest Members
wandaluciaia, Mega_Rod, EternallyCurious, howardR, 11honza11
19049 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Let's research 01: Gravity simulation! #390064
12/22/11 01:51
12/22/11 01:51
Joined: Oct 2004
Posts: 4,134
Netherlands
Joozey Offline OP
Expert
Joozey  Offline OP
Expert

Joined: Oct 2004
Posts: 4,134
Netherlands
Hey all,

For the starting programmers among us, here is a fun project for you to do. This workshop is written for programmers that have some basic knowledge about lite-c, structures and pointers (you don't need too much knowledge wink ). I hope my explanations give you sufficient understanding in how to implement a concept or idea into working code. Feel free to give feedback and show your results! laugh. This is part 01, as I plan to write more if you find it useful.


Let's research 01: Gravity simulation!


Goal:
an application that shows n bodies moving around with various masses, positions and initial velocities according to the laws of physics.


Aproach:
We'll construct three source files:
  • gravity_simulation.c has the main, and a while loop to control the timelapse of the simulation
  • space_gravity.c does all the calculations, controlling the mass bodies in the universe
  • list.c is a linkedlist datastructure


We will use MDL_SPHERE entities as stars, and generate n entities with random mass and positions. We want to try and avoid using arrays as they have a fixed size and are not easily expandable if we want more stars than anticipated. Rather, we use a linkedlist to keep track of all our mass bodies. A linkedlist has a dynamic size; we don't need to worry about how many bodies we already made and are still able to walk through the list.

Here is the linkedlist code:
Click to reveal..
Code:
//list.c

//a list (node) structure, containing a subject (of type void*) and a pointer to the next list node
typedef struct List
{
	void* object;
	struct List* next;
} List;


//this method adds an object to the list, by creating a new list node and prepending it to the root list node
void list_add_object( List* root, void* object )
{
	List* list = sys_malloc( sizeof( List ) );
	list->object = object;
	list->next = root->next;
	root->next = list;
}

//removes a node containing the given object from the list
void list_remove_object( List* root, void* object )
{
	List* prev;
	while( root->next )
	{
		prev = root;
		root = root->next;
		
		if( root->object == object )
		{
			prev->next = root->next;
			sys_free( root );
		}
	}
}




Next up is gravity_simulation.c.
  • Create a main where you load an empty level (level_load(NULL)).
  • Put your camera above the level (about 3000 quants), and tilt it downwards so you look down on the nullvector.
  • Now create a for-loop with 200 iterations.
  • In there, use: ent_create( SPHERE_MDL, nullvector, NULL );
  • Give this entity a random position on x and y with a range of -500 to 500 (optionally also z for a cube of stars instead of a 2D plane).
  • Create am infinite while loop with a wait(1);. For now it'll stay empty.


Right, this should give us an empty level with 200 SPHERE_MDL models on random positions. So how are we going to give them a mass and calculate their heading according to gravity laws?


On to space_gravity.c!
We will make 3 functions in space_gravity.c. I precede function names in here with sg_, so we are reminded which source file the functions originate from.

3 functions:
  • sg_init initializes the list of mass objects
  • sg_add_mass_object adds a new mass object to the list
  • sg_update updates all mass objects in the list with a new position


There's also one structure that acts as the mass object:
Code:
typedef struct
{
	int mass;
	VECTOR* pos;
	VECTOR velocity;
	VECTOR acceleration; //helps in the calculation to determine change in speed	
} SgMassObject;



This structure contains an integer for the mass, a reference to a position to be updated, a velocity vector to determine speed, and an acceleration vector acting as the change in speed.


There's one last global variable to make in space_gravity.c: a list of mass objects. Under the structure we write: List sg_mass_list;. This List variable must be initialised before starting the simulation, and that's where we use sg_init() for.
In sg_init() we write:
Code:
sg_mass_list.object = 0;
sg_mass_list.next = 0;


That is all we do in sg_init(). Call sg_init() in your main function before the for-loop.


The next function is sg_add_mass_object( VECTOR* pos, int mass ). As the arguments suspect, we give a position for the algorithm to alter, and a mass to calculate with. Additionally we can add an initial velocity too in the arguments. Experiment with it later laugh.
In sg_add_mass_object:
  • Use SgMassObject mass_object = sys_malloc( sizeof( SgMassObject ) ); to allocate a new structure of SgMassObject.
  • Set mass and pos to the given arguments
  • Set velocity and acceleration on nullvector using vec_set
  • Now add our mass_object to the list by writing: list_add_object( &sg_mass_list, mass_object );

That's all we need to do in the sg_mass_add_object function.

We can now go back to our main function in gravity_simulator.c. In the for loop where we create the entities, call sg_add_mass_object like this: sg_add_mass_object( &(entity->x), mass ); where mass can be a random number (even negative!). We use the ampersand to create a reference to the x position of the entity, treating it correctly as a vector. We now have the entity's position stored in sg_mass_list, and can control it just using that vector without having the entity at all!

Back to space_gravity.c, we now need to create the hardest part. sg_update() will do the calculations of each mass object in the list and control the position according to the result. We plan the next steps:
  • Walk through the list and retrieve the mass object as mass_object (see below)
  • In the loop, walk through the list again from start and retrieve the mass object as mass2_object
  • if both objects are equal, skip code and continue to the next object in the (second) list
  • With the two objects, we use the gravitation formula F = ( G * M1 * M2 ) / ( r * r )
  • G = 6.674, M1 and M2 is the mass of each mass_object, r = distance between the two mass_objects (vec_dist), F = force
  • only do this if r > 4, where 4 can be adjusted to control peek speeds when objects come too close
  • Now we have F, we can calculate the acceleration using F = M * A, translated A = F / M where M = mass of the first object and A = an acceleration variable.
  • Determine the direction from the first mass object to the second, and normalize it using the acceleration variable (see below).
  • Add the resulting vector to the acceleration vector (of the struct) of the first mass entity
  • keep repeating these points until all mass objects in the list have their acceleration vector calculated


Click to reveal..

We can walk through the list like this:
Code:
List* mass_list = &sg_mass_list;
while( mass_list->next )
{
	mass_list = mass_list->next;
	
	SgMassObject* mass_object = mass_list->object;
	...
}



We can determine the direction of one position to the other like this:
Code:
VECTOR* tempvec = vector( 0, 0, 0 );
vec_set( tempvec, mass2_object->pos );
vec_sub( tempvec, mass_object->pos );

//we normalize the direction to get a unit direction vector (values -1 to 1), and multiply it by the acceleration
vec_normalize( tempvec, force / mass_object->mass ); //A = F / M




After the while loops of the algorithm, we make yet another while loop to walk through the entire list again. In this loop we add the acceleration vector of each mass object to its velocity vector using vec_add. Then we add the velocity vector to the mass object's position after multiplying by time_step:
Code:
mass_object->pos->x += mass_object->velocity.x * time_step;
//Same for y and z


Last thing to do in space_gravity.c: reset the acceleration vector of the mass object to nullvector using vec_set.


One more thing to do in our main while loop... and that's calling sg_update();!


It should work now if you did everything right laugh.
You learn best by trying yourself, type your own code and don't copy too much. Nevertheless, if you're completely stuck on something here are the working source files:
gravity_simulation.c, space_gravity.c, list.c
But consider it cheating using them wink.

Have fun!
Joozey




Click and join the 3dgs irc community!
Room: #3dgs
Re: Let's research 01: Gravity simulation! [Re: Joozey] #390067
12/22/11 04:21
12/22/11 04:21
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Nice workshop!

I see you're interested in this topic, so let me give you a IMO surprising information (if you don't know that already):
You've written a simulation where all N^2 pairwise interactions are calculated in, of course, O(N^2) time. However, there is a method that lets you calculate all interactions in linear time, i.e. with O(N) calculations, google for "Fast Multipole Method".


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: Let's research 01: Gravity simulation! [Re: Superku] #390069
12/22/11 06:52
12/22/11 06:52
Joined: Jul 2007
Posts: 619
Turkey, Izmir
Emre Offline
User
Emre  Offline
User

Joined: Jul 2007
Posts: 619
Turkey, Izmir
You guys really good programmers and generous. Nice workshop & useful for me. I am waiting for part 02-03 and more smile

Re: Let's research 01: Gravity simulation! [Re: Emre] #390070
12/22/11 06:58
12/22/11 06:58
Joined: Oct 2004
Posts: 4,134
Netherlands
Joozey Offline OP
Expert
Joozey  Offline OP
Expert

Joined: Oct 2004
Posts: 4,134
Netherlands
@superku: yes laugh this was the most overviewable code I could think of right away. There's also some optimisations possible in the formulas. Never heard of the fast multipole method though, I'll take a look to it. Thanks!


Click and join the 3dgs irc community!
Room: #3dgs

Moderated by  adoado, checkbutton, mk_1, Perro 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1