Today I just fixed a few problems that I left behind when I changed the time from seconds to milliseconds. Now all the scenes work as they should.
At the end of this week I'll move to Scotland for a master, so I've not yet idea if I will be able to continue the work on the physics engine, but I definitely hope so.
mercoledì 24 agosto 2016
mercoledì 17 agosto 2016
Day 166: Sleep
I needed to stop working on the engine for a few days because my last game was approved on Steam and I had quite a few things to do. Today I had a bit of free time, and I added support for sleeping objects, which is very important to achieve high performance in the physical engine.
Basically each object have a motion value, which is a float number obtained from both rotation and velocity. The object is put to sleep if this value is low enough, and it is awoken again in three cases:
- The application of a force
- A change in velocity
- A collision
I tested it briefely, and it seems to work fine. It also need some fine tuning: the motion value is actually an average of the last frames as well, and it's crucial to find a good value of "how much" to keep of the last frames. And of course the threshold itself under which the object is put to sleep must be carefully chosen to be as big as possible, but not visible to the eye.
With this implementation I've actually concluded the implementation of the book. The engine is now roughly complete, but there are still things to do:
- Handle the friction and restitution coefficients (right now there is a universal value)
- Fix collision resolution (only sphere-sphere and sphere-plane seem to work without problems)
- Implement the octrees for the broad phase detection
- Lots of profiling and testin
Basically each object have a motion value, which is a float number obtained from both rotation and velocity. The object is put to sleep if this value is low enough, and it is awoken again in three cases:
- The application of a force
- A change in velocity
- A collision
I tested it briefely, and it seems to work fine. It also need some fine tuning: the motion value is actually an average of the last frames as well, and it's crucial to find a good value of "how much" to keep of the last frames. And of course the threshold itself under which the object is put to sleep must be carefully chosen to be as big as possible, but not visible to the eye.
With this implementation I've actually concluded the implementation of the book. The engine is now roughly complete, but there are still things to do:
- Handle the friction and restitution coefficients (right now there is a universal value)
- Fix collision resolution (only sphere-sphere and sphere-plane seem to work without problems)
- Implement the octrees for the broad phase detection
- Lots of profiling and testin
martedì 9 agosto 2016
Day 165: Friction fixed...maybe
Today I found after a painful amount of time the problem with friction. And of course, for the thousandth time in my life, it was a radians/degree problem.
Basically my whole engine is implemented with degrees, and this was not a problem for the most part, but while using the angular velocity to get the linear velocity in the contact point, it was mandatory to use radians.
Now as you can see from the gif both rotation and velocity are fine.
However there is a new problem: once the object velocity is resolved, it will continue to rotate (and slide) indefinitely. This is probably because the impulse to resolve the angular rotation is applied to the center of the body, instead of the contact point. This is fine for a point object, but not for a volumetric body.
The problem now is to understand if it is my fault, and something should've been done differently, or if this is a normal behaviour that should be resolved with rolling friction, which logically is exactly the kind of force that would solve it.
Basically my whole engine is implemented with degrees, and this was not a problem for the most part, but while using the angular velocity to get the linear velocity in the contact point, it was mandatory to use radians.
Now as you can see from the gif both rotation and velocity are fine.
However there is a new problem: once the object velocity is resolved, it will continue to rotate (and slide) indefinitely. This is probably because the impulse to resolve the angular rotation is applied to the center of the body, instead of the contact point. This is fine for a point object, but not for a volumetric body.
The problem now is to understand if it is my fault, and something should've been done differently, or if this is a normal behaviour that should be resolved with rolling friction, which logically is exactly the kind of force that would solve it.
lunedì 8 agosto 2016
Day 164: Friction
Today I implemented the code for friction. It was a little more complicated than what I had in mind but in the end I understood all the code. However I then spent hours to try and make it work, and I still didn't manage.
Basically, as you can see from the gif, friction works fine if I don't enable rotations. However if I do, the objects stars to slide on the ground instead of stopping. I actually think I have found the problem: basically the friction considers also the linear velocity generated by the torque at the contact point, and it adds it to the linear velocity to compensate. This basically adds too much velocity, and the objects starts to move in the opposite direction instead of staying still.
Tomorrow I'll try and fix it my way, even though I'm not sure that the code I'm following is wrong, and it is possible that I made some mistake...
Basically, as you can see from the gif, friction works fine if I don't enable rotations. However if I do, the objects stars to slide on the ground instead of stopping. I actually think I have found the problem: basically the friction considers also the linear velocity generated by the torque at the contact point, and it adds it to the linear velocity to compensate. This basically adds too much velocity, and the objects starts to move in the opposite direction instead of staying still.
Tomorrow I'll try and fix it my way, even though I'm not sure that the code I'm following is wrong, and it is possible that I made some mistake...
domenica 7 agosto 2016
Day 163: Resting contacts
Today I fixed a bad bug that I noticed yesterday evening. Basically the bodies were sinking instead of resting on one another. I found the bug, which was a penetration value with a wrong sign in the sphere_sphere collision resolution.
Then I introduced the calculation of the matrix for the rigidbodies in three different points:
- at the beginning of the physics step, in order to get the correct matrix if the objects were manually moved (instead of through forces)
- after the force application and bodies integration, to get the correct matrix for contact resolution
- after contact resolution (along with the complete transform matrix) for the rendering engine.
I don't know If it is possible to reduce this number for performance, but it works fine for now and it removed a lot of bugs I had until today.
Finally I noticed a bug in the change scene process: the input() method was called after the destruction of the scene, causing a nullptr exception.
Tomorrow I'll implement friction. I was quite scared at the idea of calculating the area of contact of two objects, because there is no way to easily do that, but thankfully my high school physics knowledge failed me: friction is not dependent on the surface area! This will make everything really really easy I think, tomorrow I'll implement that.
In the gif: the top two spheres fall with a high gravity acceleration. The left one is also moved manually, while the right one shows perfectly the resting contact. The other two spheres have infinite mass.
Then I introduced the calculation of the matrix for the rigidbodies in three different points:
- at the beginning of the physics step, in order to get the correct matrix if the objects were manually moved (instead of through forces)
- after the force application and bodies integration, to get the correct matrix for contact resolution
- after contact resolution (along with the complete transform matrix) for the rendering engine.
I don't know If it is possible to reduce this number for performance, but it works fine for now and it removed a lot of bugs I had until today.
Finally I noticed a bug in the change scene process: the input() method was called after the destruction of the scene, causing a nullptr exception.
Tomorrow I'll implement friction. I was quite scared at the idea of calculating the area of contact of two objects, because there is no way to easily do that, but thankfully my high school physics knowledge failed me: friction is not dependent on the surface area! This will make everything really really easy I think, tomorrow I'll implement that.
In the gif: the top two spheres fall with a high gravity acceleration. The left one is also moved manually, while the right one shows perfectly the resting contact. The other two spheres have infinite mass.
sabato 6 agosto 2016
Day 162: A buggy integration, and an unexpected surprise
Today I finally managed to integrate the physics, even though most of it is buggy and there are random crashes that will be a pain to track down.
In the gif you can see that sphere collisions are correctly resolved, as well as the half plane collisions (the invisible floor). However box-sphere collisions are slightly buggy, while box-box collisions are completely broken.
However the balance of this day is absolutely positive, because thanks to a bug in the physics engine I found a bug that was literally killing the performance of the rendering engine (which I actually thought were pretty good): each GameObject was duplicated in the copy constructor!
I tested immediately the old scenes, and the results are outstanding: the scene with 1000 dynamic lights from 17 fps skyrocketed to 40, and the directional lights scene went from ~40 to a perfect 60 fps.
In the gif you can see that sphere collisions are correctly resolved, as well as the half plane collisions (the invisible floor). However box-sphere collisions are slightly buggy, while box-box collisions are completely broken.
However the balance of this day is absolutely positive, because thanks to a bug in the physics engine I found a bug that was literally killing the performance of the rendering engine (which I actually thought were pretty good): each GameObject was duplicated in the copy constructor!
I tested immediately the old scenes, and the results are outstanding: the scene with 1000 dynamic lights from 17 fps skyrocketed to 40, and the directional lights scene went from ~40 to a perfect 60 fps.
venerdì 5 agosto 2016
Day 161: Physics world
Today I started to integrate everything with the Ryno Engine, and I created a PhysicsWorld class, which basically handles the process.
I've not yet been able to test it because I was stuck for hours on a problem: how to automatize the contact detection. Until now there were functions like "sphere_and_sphere" or "box_and_sphere". But the engine has a vector of generic primitives, and C++ does not have reflection. In order to avoid two nested switchs I tried different solutions, but I inevitably stomped against some wall.
In the end I gave up at finding an elegant solution, but I managed to write a "clever" switch: instead of nesting two switches, the first one calls a templated function passing the first argument with the correct type. The template function calls the correct function with a second switch.
As soon as I fixed that a new problem arose in the next function, the contact resolution one. I'll continue tomorrow.
I've not yet been able to test it because I was stuck for hours on a problem: how to automatize the contact detection. Until now there were functions like "sphere_and_sphere" or "box_and_sphere". But the engine has a vector of generic primitives, and C++ does not have reflection. In order to avoid two nested switchs I tried different solutions, but I inevitably stomped against some wall.
In the end I gave up at finding an elegant solution, but I managed to write a "clever" switch: instead of nesting two switches, the first one calls a templated function passing the first argument with the correct type. The template function calls the correct function with a second switch.
As soon as I fixed that a new problem arose in the next function, the contact resolution one. I'll continue tomorrow.
giovedì 4 agosto 2016
Day 160: Contact resolver
Yesterday I wrote the algorithms to resolve the velocity and interpenetration of a contact.
Today I wrote the ContactResolver, which is in charge of resolving all the contacts in the correct order. It has three main methods:
- prepare_contacts: calls the calculate_internals method on each contact, which basically sets up a few importand data
Today I wrote the ContactResolver, which is in charge of resolving all the contacts in the correct order. It has three main methods:
- prepare_contacts: calls the calculate_internals method on each contact, which basically sets up a few importand data
-adjust_positions: it iterates N times, and resolves the contact with the greatest penetration at each iteration. It also needs to update each other contact containing one of the two recently resolved rigidbodies.
-adjust_velocities: basically the same process of adjust_positions, but with velocities.
These last two functions are quite "iteratively" intensive, and it could be possible to experiment with alternatives. For instance by using linked lists it could be possible to avoid iterating so much.
I'll probably go back to this point once the engine will be running, for now I'll leave it like that, because it's easy and works nicely.
That being said, finally the engine is quite complete! I'm still missing friction, optimizations, resting objects and a good broad phase algorithm (like octrees), but it should be possible to use it now!
So tomorrow I'll try to integrate it inside the engine, with one main goal in mind: hide the implementation details, and make it easy to use.
After that I'll add friction and octrees, and proceed to polish the engine until I'm fine with it.
That being said, finally the engine is quite complete! I'm still missing friction, optimizations, resting objects and a good broad phase algorithm (like octrees), but it should be possible to use it now!
So tomorrow I'll try to integrate it inside the engine, with one main goal in mind: hide the implementation details, and make it easy to use.
After that I'll add friction and octrees, and proceed to polish the engine until I'm fine with it.
mercoledì 3 agosto 2016
Day 159: Resolve interpenetration
Today I implemented the piece of code that resolves the interpenetration.
In the particle engine it simply moved the objects back by an amount of the interpenetration proportional to their masses.
Here it also needs to account for the orientation.
The code calculates the inertia of the linear component and the inertia of the rotation component, and the penetration is resolved proportionally to their values.
Also, since big rotations could cause problems, if the amount of rotation is too big, part of it is still resolved as linear penetration.
In the particle engine it simply moved the objects back by an amount of the interpenetration proportional to their masses.
Here it also needs to account for the orientation.
The code calculates the inertia of the linear component and the inertia of the rotation component, and the penetration is resolved proportionally to their values.
Also, since big rotations could cause problems, if the amount of rotation is too big, part of it is still resolved as linear penetration.
martedì 2 agosto 2016
Day 158: Collision impulses
Today I studied and implemented the code to apply impulses during collisions.
This is done in order to simulate a bounce, not unlike the particle engine. The main difference is the rotation part.
The code is divided in a few main functions:
- A function to calculate the necessary velocity to resolve the contact
- A function to calculate the impulse strength: this was a little harder to understand due to a bad naming convention used in the book that made me misinterpret a variable meaning. In the end it does this: it calculates a unit_delta_velocity, which is the velocity imprinted by an impulse of 1. So the final impulse has a strength of desired_delta_velocity / unit_delta_velocity.
-A function to apply the movement: given the impulse, it is possible to extract the linear and angular velocities pretty easily, and apply them.
This doesn't account for interpenetrarion yet (which I'll hopefully do tomorrow).
This is done in order to simulate a bounce, not unlike the particle engine. The main difference is the rotation part.
The code is divided in a few main functions:
- A function to calculate the necessary velocity to resolve the contact
- A function to calculate the impulse strength: this was a little harder to understand due to a bad naming convention used in the book that made me misinterpret a variable meaning. In the end it does this: it calculates a unit_delta_velocity, which is the velocity imprinted by an impulse of 1. So the final impulse has a strength of desired_delta_velocity / unit_delta_velocity.
-A function to apply the movement: given the impulse, it is possible to extract the linear and angular velocities pretty easily, and apply them.
This doesn't account for interpenetrarion yet (which I'll hopefully do tomorrow).
lunedì 1 agosto 2016
Day 157: Contact basis
Today I just wrote a function that generates a matrix. This matrix represent the basis of the coordinate space of the contact. It will be very useful in the future.
Iscriviti a:
Post (Atom)



